[Scummvm-git-logs] scummvm master -> c2bbb608cdf86261f24aa21eba205e8b3281a9c3

sev- noreply at scummvm.org
Sun Dec 24 12:20:57 UTC 2023


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

Summary:
11d7381c3f COMMON: Allow inlining of BaseString::makeUnique
0edfc8f6dd COMMON: Add append function to BaseString which takes a pointer range
7205774eef COMMON: Add replace char function to String
9260a58d6d COMMON: Make IgnoreCaseAndMac_EqualsTo name consistent with String
be7130f296 COMMON: Rework path storage
23fda47ac8 COMMON: Improve punydecode performance
6f46727c77 COMMON: Check if string is puny encoded before trying to decode it
eeba7ca153 COMMON: Add more path functions
6f4a86db7e COMMON: Add a native directory separator
1722511c32 COMMON: Allow to store and fetch paths in configuration
8b2e5ef649 COMMON: Make getPath() return a Path
28b63470f0 COMMON: Migrate DumpFile to Path
56552fa282 COMMON: Various path related fixes in archives
088db8ca65 BASE: Various some path related cleanups
74a6158347 GUI: Add a PathWidget
fd0267cfd1 GUI: Make TextViewerDialog use a Path instead of a String
d9a8131ba2 COMMON: Make getDefaultLogFileName return a Path instead of a String
01ebece807 COMMON: Make getDefaultConfigFileName return a Path instead of a String
d87571766e BACKENDS: NETWORKING: Use Path for cURL requests
460be938f3 CLOUD: Make cloud use Path for local folders and files
87e9a406fa BACKENDS: NETWORKING: Use Path instead of String for local files
d8db629cd5 BACKENDS: NETWORKING: Make rootpath a Path and use Path everywhere
e689166a2c BACKENDS: Make screenshots use the Path class
b97da06876 COMMON: Make taskbar use Path
dc7fadef28 COMMON: Make iconspath a Path object
bfc61439fb COMMON: Make themepath a Path object
802c91554f COMMON: Make extrapath a Path object
db5041ecb0 COMMON: Make savepath a Path object
0a636d0d40 COMMON: Make pluginspath a Path object
ce961cabbc COMMON: Make soundfont a Path object
2f34975164 COMMON: Make shaders API use the Path class
317432030d BACKENDS: SDL: Make controller_map_db a Path object
0e1d950dec BACKENDS: SDL: Make vkeybdpath a Path object
c34e475a0e VKEYBD: Migrate virtual keyboard to Path class
db41390587 BACKENDS: Make browser_lastpath a Path object
3c5fe56de6 BACKENDS: OPENGL: Small cleanups on paths
93a8f7f4d6 COMMON: Move Archive API to Path
e0fd69bda0 COMMON: Make INIFile use Path
fc3f03d21d COMMON: Make EVENT_DROP_FILE use a Path
226de788c8 GRAPHICS: Make API use the Path class
4ecccceca6 AUDIO: Move API to Path
85952c72bf VIDEO: Move API to Path
645a35c05b ENGINES: Migrate to Path class
d931c58b5b BASE: Start considering game paths as Path class
339cff9358 BACKENDS: Make audio CD use Path class
b3fbce7782 BACKENDS: Migrate plugins to Path API
40dcce567b BACKENDS: DC: Start considering game paths as Path class
7853b05482 BACKENDS: WII: Start considering game paths as Path class
e1aeab81f5 ACCESS: Migrate engine to Path
4b00b7e83d ADL: Migrate engine to Path
3457d49fd5 AGI: Migrate engine to Path
d614b5d31c AGOS: Migrate engine to Path
728b2cbac7 AGS: Migrate engine to Path
979b7f3669 ASYLUM: Migrate engine to Path
905ea1386e AVALANCHE: Migrate engine to Path
6cfc214d5b BBVS: Migrate engine to Path
db6fcfcc24 BLADERUNNER: Migrate engine to Path
e90ae68c58 BURIED: Migrate engine to Path
430d0dedd2 CHAMBER: Migrate engine to Path
e9e09319e4 CHEWY: Migrate engine to Path
f3c7cd6393 CINE: Migrate engine to Path
bbc4d51fc4 COMPOSER: Migrate engine to Path
724ccbd1c6 CRAB: Migrate engine to Path
94f6c8852b CRYOMNI3D: Migrate engine to Path
cf3eac29c3 DIRECTOR: Migrate engine to Path
80827c49f0 DRACI: Migrate engine to Path
d4242bf32a DRAGONS: Migrate engine to Path
2d06591564 DRASCULA: Migrate engine to Path
678c63ad1e DREAMWEB: Migrate engine to Path
6ef53571fb EFH: Migrate engine to Path
a8e11a0611 FREESCAPE: Migrate engine to Path
ff87ff4e24 GLK: Migrate engine to Path
49da9211ec GNAP: Migrate engine to Path
8c49d1442e GOB: Migrate engine to Path
43cf69c238 GRIFFON: Migrate engine to Path
7627ae3b97 GRIM: Migrate engine to Path
cef464ac93 GROOVIE: Migrate engine to Path
09803f7a26 HADESCH: Migrate engine to Path
d7c749864b HDB: Migrate engine to Path
063e516fc8 HOPKINS: Migrate engine to Path
69665f6803 HPL1: Migrate engine to Path
a1a5407c64 HUGO: Migrate engine to Path
27396734e9 HYPNO: Migrate engine to Path
d5736f602e ICB: Migrate engine to Path
0ab0721905 ILLUSIONS: Migrate engine to Path
fa613cc8e9 IMMORTAL: Migrate engine to Path
ca89a72b68 KINGDOM: Migrate engine to Path
abfc953046 KYRA: Migrate engine to Path
244ee1b79e LAB: Migrate engine to Path
1a31b42ca4 LASTEXPRESS: Migrate engine to Path
0df39efb81 LILLIPUT: Migrate engine to Path
8e05d9c349 M4: Migrate engine to Path
cd9c525b6d MACVENTURE: Migrate engine to Path
f50a364ee8 MADS: Migrate engine to Path
0512d96b47 MM: Migrate engine to Path
731798c481 MOHAWK: Migrate engine to Path
1b1f9fc209 MORTEVIELLE: Migrate engine to Path
c78ace6701 MTROPOLIS: Migrate engine to Path
c8d211090e MUTATIONOFJB: Migrate engine to Path
aa5ad1f500 MYST3: Migrate engine to Path
1c2d757dbd NANCY: Migrate engine to Path
31d3a266bd NEVERHOOD: Migrate engine to Path
7961472a09 NGI: Migrate engine to Path
bb879ae56e PARALLACTION: Migrate engine to Path
ffe2ad5446 PEGASUS: Migrate engine to Path
cfdd63abf8 PETKA: Migrate engine to Path
e62dcdfed4 PINK: Migrate engine to Path
e8a4a8af80 PLUMBERS: Migrate engine to Path
d7526ad280 PRINCE: Migrate engine to Path
50e4085263 PRIVATE: Migrate engine to Path
f58b045ec8 SAGA: Migrate engine to Path
0c3ddc2a87 SAGA2: Migrate engine to Path
45286ad131 SCI: Migrate engine to Path
17f09bb48c SCUMM: Migrate engine to Path
ff6f58a8b6 SHERLOCK: Migrate engine to Path
98dc1933a5 SKY: Migrate engine to Path
6ad766f8d8 SLUDGE: Migrate engine to Path
03331e6964 STARK: Migrate engine to Path
4400b8eea3 STARTREK: Migrate engine to Path
c696963343 SUPERNOVA: Migrate engine to Path
b9150691d9 SWORD1: Migrate engine to Path
78dc2d9eb9 SWORD2: Migrate engine to Path
3f9512c7cb SWORD25: Migrate engine to Path
ed0b59973a TEENAGENT: Migrate engine to Path
17e1bd01ef TESTBED: Migrate engine to Path
468cdd81bd TETRAEDGE: Migrate engine to Path
cd802da8ae TINSEL: Migrate engine to Path
da5f81d151 TITANIC: Migrate engine to Path
7d05b38654 TOLTECS: Migrate engine to Path
77a61aafc6 TONY: Migrate engine to Path
c45606f133 TOON: Migrate engine to Path
a17ccbea72 TOUCHE: Migrate engine to Path
e06e8761f1 TRECISION: Migrate engine to Path
c803257af9 TSAGE: Migrate engine to Path
a57eaeb342 TUCKER: Migrate engine to Path
6d86d20e1c TWINE: Migrate engine to Path
ca246ba56a ULTIMA: Migrate engine to Path
1968695f6e VCRUISE: Migrate engine to Path
17ceed4eb3 VOYEUR: Migrate engine to Path
dd374a778e WATCHMAKER: Migrate engine to Path
ca31647aeb WAGE: Migrate engine to Path
bdb515b913 WINTERMUTE: Migrate engine to Path
043e5ad420 ZVISION: Migrate engine to Path
ed9ded9e83 GUI: Migrate GUI to Path class
04d68d87c0 BASE: Migrate to Path class
9bdf1233b1 BACKENDS: Migrate to Path API
431af3e37d COMMON: Delete getPath compatibility shim
c2bbb608cd COMMON: Make String to Path conversion explicit


Commit: 11d7381c3f215431fc1dbb93bb169dd2d370dbdf
    https://github.com/scummvm/scummvm/commit/11d7381c3f215431fc1dbb93bb169dd2d370dbdf
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Allow inlining of BaseString::makeUnique

Changed paths:
    common/str-base.cpp
    common/str-base.h


diff --git a/common/str-base.cpp b/common/str-base.cpp
index b489fd3600a..7ceebb852fc 100644
--- a/common/str-base.cpp
+++ b/common/str-base.cpp
@@ -123,10 +123,6 @@ TEMPLATE BASESTRING::~BaseString() {
 	decRefCount(_extern._refCount);
 }
 
-TEMPLATE void BASESTRING::makeUnique() {
-	ensureCapacity(_size, true);
-}
-
 TEMPLATE void BASESTRING::ensureCapacity(uint32 new_size, bool keep_old) {
 	bool isShared;
 	uint32 curCapacity, newCapacity;
diff --git a/common/str-base.h b/common/str-base.h
index b8e447236e1..cf279c4cc57 100644
--- a/common/str-base.h
+++ b/common/str-base.h
@@ -245,7 +245,10 @@ public:
 protected:
 	~BaseString();
 
-	void makeUnique();
+	void makeUnique() {
+		ensureCapacity(_size, true);
+	}
+
 	void ensureCapacity(uint32 new_size, bool keep_old);
 	void incRefCount() const;
 	void decRefCount(int *oldRefCount);


Commit: 0edfc8f6dd3652c66aea659eda315776d4b27924
    https://github.com/scummvm/scummvm/commit/0edfc8f6dd3652c66aea659eda315776d4b27924
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Add append function to BaseString which takes a pointer range

This allows to add efficiently a substring to another

Changed paths:
    common/str-base.cpp
    common/str-base.h


diff --git a/common/str-base.cpp b/common/str-base.cpp
index 7ceebb852fc..b4af5319a79 100644
--- a/common/str-base.cpp
+++ b/common/str-base.cpp
@@ -788,6 +788,25 @@ TEMPLATE void BASESTRING::trim() {
 }
 #endif
 
+TEMPLATE void BASESTRING::append(const value_type *beginP, const value_type *endP) {
+	assert(endP >= beginP);
+	size_t len = endP - beginP;
+	if (len == 0)
+		return;
+
+	// Don't test endP as it must be in the same buffer
+	if (pointerInOwnBuffer(beginP)) {
+		assignAppend(BaseString(beginP, endP));
+		return;
+	}
+
+	ensureCapacity(_size + len, true);
+
+	memcpy(_str + _size, beginP, len * sizeof(value_type));
+	_size += len;
+	_str[_size] = 0;
+}
+
 TEMPLATE void BASESTRING::assignAppend(value_type c) {
 	if (c == 0) {
 #ifndef SCUMMVM_UTIL
diff --git a/common/str-base.h b/common/str-base.h
index cf279c4cc57..9dda1edf8bf 100644
--- a/common/str-base.h
+++ b/common/str-base.h
@@ -201,6 +201,9 @@ public:
 	size_t find(const value_type *s, uint32 pos = 0) const;
 	uint32 find(const BaseString &str, uint32 pos = 0) const;
 
+	/** Appends a string containing the characters between beginP (including) and endP (excluding). */
+	void append(const value_type *begin, const value_type *end);
+
 	/**
 	 * Wraps the text in the string to the given line maximum. Lines will be
 	 * broken at any whitespace character. New lines are assumed to be


Commit: 7205774eefb4d580bc11c6822825ba664ffa7409
    https://github.com/scummvm/scummvm/commit/7205774eefb4d580bc11c6822825ba664ffa7409
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Add replace char function to String

It allows to efficiently replace all character occurences in a string.
It uses strchr to allow optimized libc implementations of string
scanning.

Changed paths:
    common/str.cpp
    common/str.h


diff --git a/common/str.cpp b/common/str.cpp
index 193e5b3ed16..aa124d270eb 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -249,6 +249,29 @@ void String::replace(uint32 posOri, uint32 countOri, const char *str,
 
 }
 
+void String::replace(char from, char to) {
+	// Don't allow removing trailing \x00
+	if (from == '\x00') {
+		return;
+	}
+
+	char *next = strchr(_str, from);
+	if (!next) {
+		// Nothing to do
+		return;
+	}
+
+	size_t off = next - _str;
+	makeUnique();
+
+	next = _str + off;
+	while(next) {
+		*next = to;
+		next++;
+		next = strchr(next, from);
+	}
+}
+
 // static
 String String::format(const char *fmt, ...) {
 	String output;
diff --git a/common/str.h b/common/str.h
index e23dc1abe48..18480c04a7b 100644
--- a/common/str.h
+++ b/common/str.h
@@ -181,6 +181,13 @@ public:
 					uint32 posDest, uint32 countDest);
 	/**@}*/
 
+	/**
+	 * Replace all from characters in object by to character
+	 * @param from the character to look for
+	 * @param to The replacement character
+	 */
+	void replace(char from, char to);
+
 	/**
 	 * Print formatted data into a String object. Similar to sprintf,
 	 * except that it stores the result in (variably sized) String


Commit: 9260a58d6d39eb0becc3522e611a5e2610f1bc8d
    https://github.com/scummvm/scummvm/commit/9260a58d6d39eb0becc3522e611a5e2610f1bc8d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make IgnoreCaseAndMac_EqualsTo name consistent with String

Use IgnoreCaseAndMac_EqualTo.

Changed paths:
    common/fs.h
    common/path.cpp
    common/path.h
    engines/cryomni3d/font_manager.cpp
    engines/director/director.h


diff --git a/common/fs.h b/common/fs.h
index 7e2f13ea0de..058670bd3a2 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -349,7 +349,7 @@ class FSDirectory : public Archive {
 
 	// Caches are case insensitive, clashes are dealt with when creating
 	// Key is stored in lowercase.
-	typedef HashMap<Path, FSNode, Path::IgnoreCaseAndMac_Hash, Path::IgnoreCaseAndMac_EqualsTo> NodeCache;
+	typedef HashMap<Path, FSNode, Path::IgnoreCaseAndMac_Hash, Path::IgnoreCaseAndMac_EqualTo> NodeCache;
 	mutable NodeCache	_fileCache, _subDirCache;
 	mutable bool _cached;
 
diff --git a/common/path.cpp b/common/path.cpp
index 5df923fb679..8a2df691677 100644
--- a/common/path.cpp
+++ b/common/path.cpp
@@ -423,7 +423,7 @@ bool Path::matchPattern(const Path& pattern) const {
 	return true;
 }
 
-bool Path::IgnoreCaseAndMac_EqualsTo::operator()(const Path& x, const Path& y) const {
+bool Path::IgnoreCaseAndMac_EqualTo::operator()(const Path& x, const Path& y) const {
 	return x.getIdentifierString().equalsIgnoreCase(y.getIdentifierString());
 }
 
diff --git a/common/path.h b/common/path.h
index a9d89f9d039..4ce192dbba0 100644
--- a/common/path.h
+++ b/common/path.h
@@ -61,7 +61,7 @@ public:
 	 * to match both "xn--Sound Manager 3.1  SoundLib-lba84k/Sound"
 	 * and "Sound Manager 3.1 : SoundLib/Sound"
 	 */
-	struct IgnoreCaseAndMac_EqualsTo {
+	struct IgnoreCaseAndMac_EqualTo {
 		bool operator()(const Path& x, const Path& y) const;
 	};
 
diff --git a/engines/cryomni3d/font_manager.cpp b/engines/cryomni3d/font_manager.cpp
index cad06f5aafa..f3b01a7fa66 100644
--- a/engines/cryomni3d/font_manager.cpp
+++ b/engines/cryomni3d/font_manager.cpp
@@ -67,7 +67,7 @@ void FontManager::loadFonts(const Common::Array<Common::Path> &fontFiles,
 	_fonts.reserve(fontFiles.size());
 
 	Common::HashMap<Common::Path, Graphics::Font *,
-		Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualsTo> fontsCache;
+		Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualTo> fontsCache;
 
 	for (Common::Array<Common::Path>::const_iterator it = fontFiles.begin(); it != fontFiles.end();
 	        it++) {
diff --git a/engines/director/director.h b/engines/director/director.h
index 666ed71adf8..014d75e0d6e 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -258,9 +258,9 @@ public:
 	Common::List<Common::String> _extraSearchPath;
 
 	// Owner of all Archive objects.
-	Common::HashMap<Common::Path, Archive *, Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualsTo> _allSeenResFiles;
+	Common::HashMap<Common::Path, Archive *, Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualTo> _allSeenResFiles;
 	// Handles to resource files that were opened by OpenResFile.
-	Common::HashMap<Common::Path, Archive *, Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualsTo> _openResFiles;
+	Common::HashMap<Common::Path, Archive *, Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualTo> _openResFiles;
 	// List of all currently open resource files
 	Common::List<Common::Path> _allOpenResFiles;
 


Commit: be7130f296aba60d9d1d0bd8717c6cda42307068
    https://github.com/scummvm/scummvm/commit/be7130f296aba60d9d1d0bd8717c6cda42307068
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Rework path storage

Changed paths:
    common/path.cpp
    common/path.h
    test/common/path.h


diff --git a/common/path.cpp b/common/path.cpp
index 8a2df691677..da492a7b251 100644
--- a/common/path.cpp
+++ b/common/path.cpp
@@ -25,256 +25,571 @@
 #include "common/list.h"
 #include "common/punycode.h"
 
-const char ESCAPER = '/';
-const char ESCAPE_SLASH = '+';
-const char ESCAPE_SEPARATOR = '/';
-const char *DIR_SEPARATOR = "//";
-const char *SLASH_ESCAPED = "/+";
-
 namespace Common {
 
-Path::Path(const Path &path) {
-	_str = path._str;
-}
+#ifndef RELEASE_BUILD
+bool Path::_shownSeparatorCollisionWarning = false;
+#endif
 
-Path::Path(const char *str, char separator) {
-	set(str, separator);
-}
+inline void Path::escape(String &dst, char srcSeparator, const char *begin, const char *end) {
+	if (!end) {
+		end = begin + strlen(begin);
+	}
 
-Path::Path(const String &str, char separator) {
-	set(str.c_str(), separator);
-}
+	const char *nextEsc = strchr(begin, ESCAPE);
+	const char *nextEscSep, *nextSrcSep;
+	if (srcSeparator == SEPARATOR) {
+		// The source directory separator is ours, no need to escape it
+		nextEscSep = nullptr;
+	} else {
+		nextEscSep = strchr(begin, SEPARATOR);
+	}
+	if (!srcSeparator || srcSeparator == SEPARATOR) {
+		// There is no source directory separator, every SEPARATOR will get escaped
+		// Source directory separator is already a SEPARATOR, nothing to do
+		nextSrcSep = nullptr;
+	} else {
+		nextSrcSep = strchr(begin, srcSeparator);
+	}
 
-String Path::toString(char separator) const {
-	String res;
-	for (uint i = 0; i < _str.size(); i++) {
-		if (_str[i] == ESCAPER) {
-			i++;
-			if (_str[i] == ESCAPE_SLASH)
-				res += '/';
-			else if (_str[i] == ESCAPE_SEPARATOR)
-				res += separator;
-			else
-				error("Path::toString(): Malformed Common::Path. '%c' unexpected after '/'", _str[i]);
+	while (true) {
+		const char *next = nullptr;
+		if (nextEsc && nextEsc < end && (!next || nextEsc < next)) {
+			next = nextEsc;
+		}
+		if (nextEscSep && nextEscSep < end && (!next || nextEscSep < next)) {
+			next = nextEscSep;
+		}
+		if (nextSrcSep && nextSrcSep < end && (!next || nextSrcSep < next)) {
+			next = nextSrcSep;
+		}
+		if (!next) {
+			break;
+		}
+
+		// Append all content up to what we found first, excluded
+		dst.append(begin, next);
+
+		// We will look after the current found character
+		begin = next + 1;
+
+		// Do the escaping
+		if (next == nextEsc) {
+			// We found an ESCAPE
+			dst += ESCAPE;
+			dst += ESCAPED_ESCAPE;
+			nextEsc = strchr(begin, ESCAPE);
+		} else if (next == nextEscSep) {
+			// We found a SEPARATOR
+			dst += ESCAPE;
+			dst += ESCAPED_SEPARATOR;
+			nextEscSep = strchr(begin, SEPARATOR);
 		} else {
-			res += _str[i];
+			// We found a srcSeparator
+			dst += SEPARATOR;
+			nextSrcSep = strchr(begin, srcSeparator);
 		}
 	}
-	return res;
+
+	// Append anything after the last escape up to end
+	dst.append(begin, end);
 }
 
-size_t Path::findLastSeparator(size_t last) const {
-	if (_str.size() < 2)
-		return String::npos;
+inline String Path::unescape(char dstSeparator, const char *begin, const char *end) {
+	String dst;
 
-	size_t res = String::npos;
-	if (last == String::npos || last > _str.size())
-		last = _str.size();
+	if (!end) {
+		end = begin + strlen(begin);
+	}
 
-	for (uint i = 0; i < last - 1; i++) {
-		if (_str[i] == ESCAPER && _str[i + 1] == ESCAPE_SEPARATOR) {
-			res = i;
+#ifndef RELEASE_BUILD
+	if (!_shownSeparatorCollisionWarning &&
+	        dstSeparator &&
+	        dstSeparator != ESCAPE && dstSeparator != SEPARATOR) {
+		// ESCAPE and SEPARATOR cases are handled when unescaping
+		const char *dstSep = strchr(begin, dstSeparator);
+		if (dstSep && dstSep < end) {
+			warning("Collision in path \"%s\" with separator %c", begin, dstSeparator);
+			_shownSeparatorCollisionWarning = true;
 		}
 	}
+#endif
+
+	const char *nextEsc = strchr(begin, ESCAPE);
+	const char *nextSep;
+	if (dstSeparator == SEPARATOR) {
+		// dstSeparator is SEPARATOR so there is no substitution to do
+		nextSep = nullptr;
+	} else {
+		nextSep = strchr(begin, SEPARATOR);
+	}
 
-	return res;
-}
+	while (true) {
+		const char *next = nullptr;
+		if (nextEsc && nextEsc < end && (!next || nextEsc < next)) {
+			next = nextEsc;
+		}
+		if (nextSep && nextSep < end && (!next || nextSep < next)) {
+			next = nextSep;
+		}
+		if (!next) {
+			break;
+		}
 
-Path Path::getParent() const {
-	if (_str.size() < 2)
-		return Path();
-	// ignore potential trailing separator
-	size_t separatorPos = findLastSeparator(_str.size() - 1);
-	if (separatorPos == String::npos)
-		return Path();
-	Path ret;
-	ret._str = _str.substr(0, separatorPos + 2);
-	return ret;
+		// Append all content up to character excluded
+		dst.append(begin, next);
+
+		if (next == nextSep) {
+			// We found a SEPARATOR, replace with dstSeparator
+			// Make sure dstSeparator is not 0
+			assert(dstSeparator);
+			dst += dstSeparator;
+			begin = next + 1;
+			nextSep = strchr(begin, SEPARATOR);
+
+			continue;
+		}
+
+		// We found an ESCAPE
+		char follower = *(next + 1);
+		switch (follower) {
+		case ESCAPED_ESCAPE:
+			dst += ESCAPE;
+#ifndef RELEASE_BUILD
+			if (!_shownSeparatorCollisionWarning && dstSeparator == ESCAPE) {
+				warning("Collision while unescaping in path part \"%s\" with separator %c", begin, dstSeparator);
+				_shownSeparatorCollisionWarning = true;
+			}
+#endif
+			break;
+		case ESCAPED_SEPARATOR:
+			dst += SEPARATOR;
+#ifndef RELEASE_BUILD
+			if (!_shownSeparatorCollisionWarning && dstSeparator == SEPARATOR) {
+				warning("Collision while unescaping in path part \"%s\" with separator %c", begin, dstSeparator);
+				_shownSeparatorCollisionWarning = true;
+			}
+#endif
+			break;
+		default:
+			error("Invalid escape character '%c' in path part \"%s\"", follower, begin);
+		}
+		begin = next + 2;
+		// Look for the next one
+		nextEsc = strchr(begin, ESCAPE);
+	}
+
+	// Append anything after the last ESCAPE up to end
+	dst.append(begin, end);
+
+	return dst;
 }
 
-Path Path::getLastComponent() const {
-	if (_str.size() < 2)
-		return *this;
-	// ignore potential trailing separator
-	size_t separatorPos = findLastSeparator(_str.size() - 1);
-	if (separatorPos == String::npos)
-		return *this;
-	Path ret;
-	ret._str = _str.substr(separatorPos + 2);
-	return ret;
+bool Path::canUnescape(bool willBeAtBegin, bool wasAtBegin,
+                       const char *begin, const char *end) {
+	if (begin == end || (end == nullptr && *begin == '\x00')) {
+		// It's empty
+		return true;
+	}
+
+	if (*begin == ESCAPE) {
+		if (willBeAtBegin) {
+			// begin will be the start and contains an ESCAPE marker
+			// This means it escapes either a SEPARATOR or an ESCAPE
+			return false;
+		}
+
+		// We won't end up at begin of future path so we must check further what ESCAPE we have
+	} else {
+		if (wasAtBegin && end == nullptr) {
+			// begin is the start of an escaped path and doesn't begin with an ESCAPE
+			// and we go till the end of string
+			// This means we must have ESCAPED_SEPARATOR somewhere
+			return false;
+		}
+	}
+
+	const char *esc = strchr(begin, ESCAPE);
+	while (esc && (!end || esc < end)) {
+		if (*(esc + 1) == ESCAPED_SEPARATOR) {
+			return false;
+		}
+		esc = strchr(esc + 2, ESCAPE);
+	}
+	return true;
 }
 
-static String escapePath(const String& in) {
-	String ret;
-	for (uint i = 0; i < in.size(); i++) {
-		if (in[i] == '/')
-			ret += SLASH_ESCAPED;
-		else
-			ret += in[i];
+String Path::encode(const char *str, char separator) {
+	if (*str != ESCAPE && !strchr(str, SEPARATOR)) {
+		// If we start with ESCAPE we will need to escape
+		// No SEPARATOR, no clash
+		Common::String ret(str);
+		if (separator) {
+			// If separator is 0 there is only one path component
+			ret.replace(separator, SEPARATOR);
+		}
+		return ret;
 	}
+
+	// Prepend ESCAPE as we are escaping
+	Common::String ret(ESCAPE);
+
+	// Do the escape and replace separators by SEPARATOR
+	escape(ret, separator, str);
+
 	return ret;
 }
 
-Path Path::appendComponent(const String &x) const {
-	if (x.empty())
-		return *this;
-	String str = _str;
-	size_t lastSep = findLastSeparator();
-	if (!str.empty() && (lastSep == String::npos || lastSep != str.size() - 2))
-		str += DIR_SEPARATOR;
+Path Path::extract(const char *begin, const char *end) const {
+	if (_str.empty() || begin == end) {
+		// We are empty, we can't extract anything
+		return Path();
+	}
 
-	str += escapePath(x);
+	if (!end) {
+		end = _str.c_str() + _str.size();
+	}
 
+	if (!isEscaped()) {
+		Path ret;
+		if (*begin == ESCAPE) {
+			// We were not escaped but we will need to because we are creating a path starting with ESCAPE
+			ret._str += ESCAPE;
+			escape(ret._str, SEPARATOR, begin, end);
+		} else {
+			// Not escaped and no escape character at begin: just do the extraction
+			ret._str = String(begin, end);
+		}
+		return ret;
+	}
+
+	// We are escaped
+
+	// Make sure begin points on real start
+	if (begin == _str.c_str()) {
+		begin++;
+	}
+
+	if (canUnescape(true, false, begin, end)) {
+		// No escaped separator was found and no ESCAPE was at begin, unescape
+		Path ret;
+		ret._str = unescape(SEPARATOR, begin, end);
+
+		return ret;
+	}
+
+	// We can't unescape add escape marker and the escaped range
 	Path ret;
-	ret._str = str;
+	ret._str += ESCAPE;
+	ret._str.append(begin, end);
 	return ret;
 }
 
-bool Path::operator==(const Path &x) const {
-	return _str == x._str;
-}
+String Path::toString(char separator) const {
+	// toString should never be called with \x00 separator
+	assert(separator != kNoSeparator);
 
-bool Path::operator!=(const Path &x) const {
-	return _str != x._str;
-}
+	if (_str.empty() ||
+	        (separator == SEPARATOR && !isEscaped())) {
+		return _str;
+	}
 
-bool Path::empty() const {
-	return _str.empty();
-}
+	if (!isEscaped()) {
+		// Path was not escaped, replace all SEPARATOR by the real separator
+#ifndef RELEASE_BUILD
+		if (!_shownSeparatorCollisionWarning && strchr(_str.c_str(), separator)) {
+			warning("Collision while unescaping path \"%s\" with separator %c", _str.c_str(), separator);
+			_shownSeparatorCollisionWarning = true;
+		}
+#endif
 
-Path &Path::operator=(const Path &path) {
-	_str = path._str;
-	return *this;
-}
+		Common::String ret(_str);
+		ret.replace(SEPARATOR, separator);
+		return ret;
+	}
 
-Path &Path::operator=(const char *str) {
-	set(str);
-	return *this;
-}
+	// Remove leading escape indicator and do our stuff
+	const char *str = _str.c_str();
+	str++;
 
-Path &Path::operator=(const String &str) {
-	set(str.c_str());
-	return *this;
+	// Unescape and replace SEPARATORs by separator
+	return unescape(separator, str, _str.c_str() + _str.size());
 }
 
-void Path::set(const char *str, char separator) {
-	_str.clear();
-	appendInPlace(str, separator);
-}
+size_t Path::findLastSeparator(size_t last) const {
+	if (last == String::npos || last > _str.size()) {
+		// Easy case
+		const char *sep = strrchr(_str.c_str(), SEPARATOR);
+		if (!sep) {
+			return String::npos;
+		} else {
+			return sep - _str.c_str();
+		}
+	}
 
-Path &Path::appendInPlace(const Path &x) {
-	_str += x._str;
-	return *this;
-}
+	// Let's jump from separator to separator
+	const char *begin = _str.c_str();
+	const char *end = begin + last;
 
-Path &Path::appendInPlace(const String &str, char separator) {
-	appendInPlace(str.c_str(), separator);
-	return *this;
-}
+	const char *str = begin;
+	const char *sep = strchr(str, SEPARATOR);
+	while (sep && sep < end) {
+		str = sep + 1;
+		sep = strchr(str, SEPARATOR);
+	}
 
-Path &Path::appendInPlace(const char *str, char separator) {
-	for (; *str; str++) {
-		if (*str == separator)
-			_str += DIR_SEPARATOR;
-		else if (*str == '/') // Order matters as / may be the separator and often is.
-			_str += SLASH_ESCAPED;
-		else
-			_str += *str;
+	if (str == begin) {
+		// Nothing was found in the range specified
+		return String::npos;
+	} else {
+		// str was pointing just after the matching separator
+		return (str - 1) - begin;
 	}
-	return *this;
 }
 
-Path Path::append(const Path &x) const {
-	Path temp(*this);
-	temp.appendInPlace(x);
-	return temp;
-}
+Path Path::getParent() const {
+	if (_str.empty()) {
+		return Path();
+	}
 
-Path Path::append(const String &str, char separator) const {
-	return append(str.c_str(), separator);
+	// ignore potential trailing separator
+	size_t separatorPos = findLastSeparator(_str.size() - 1);
+	if (separatorPos == String::npos) {
+		return Path();
+	}
+
+	const char *begin = _str.c_str();
+	const char *end = begin + separatorPos + 1;
+	return extract(begin, end);
 }
 
-Path Path::append(const char *str, char separator) const {
-	Path temp(*this);
-	temp.appendInPlace(str, separator);
-	return temp;
+Path Path::getLastComponent() const {
+	if (_str.empty()) {
+		return Path();
+	}
+
+	// ignore potential trailing separator
+	size_t separatorPos = findLastSeparator(_str.size() - 1);
+	if (separatorPos == String::npos) {
+		return *this;
+	}
+
+	const char *begin = _str.c_str() + separatorPos + 1;
+	const char *end = _str.c_str() + _str.size();
+	return extract(begin, end);
 }
 
-Path &Path::joinInPlace(const Path &x) {
-	if (x.empty())
+Path &Path::appendInPlace(const Path &x) {
+	if (x._str.empty()) {
 		return *this;
+	}
 
-	size_t lastSep = findLastSeparator();
-	if (!_str.empty() && (lastSep == String::npos || lastSep != _str.size() - 2) && !x._str.hasPrefix(DIR_SEPARATOR))
-		_str += DIR_SEPARATOR;
+	if (_str.empty()) {
+		_str = x._str;
+		return *this;
+	}
+	// From here both paths have data
 
-	_str += x._str;
+	if (isEscaped() == x.isEscaped()) {
+		if (isEscaped()) {
+			// Both are escaped: no chance we could unescape
+			// Append the other without its escape mark
+			_str.append(x._str.begin() + 1, x._str.end());
+		} else {
+			// No escape: append as we will don't need to escape
+			_str += x._str;
+		}
+		return *this;
+	}
+
+	// If we are here, one of us is escaped and the other one is not
+	if (isEscaped()) {
+		// This one is escaped not the other one
+		// There is no chance we could unescape this one
+		escape(_str, SEPARATOR, x._str.c_str(), x._str.c_str() + x._str.size());
+		return *this;
+	}
 
+	// This one is not escaped the other one is
+	// There is a small chance the other one is escaped because it started with ESCAPED
+	// In this case (and only this one) we could unescape
+	const char *other = x._str.c_str() + 1; // Remove leading ESCAPE
+
+	if (canUnescape(false, true, other)) {
+		// This one stays unescaped and the other one becomes unescaped
+		_str += unescape(SEPARATOR, other, x._str.c_str() + x._str.size());
+	} else {
+		// This one gets escaped and the other one stays escaped
+		String str(ESCAPE);
+		escape(str, SEPARATOR, _str.c_str(), _str.c_str() + _str.size());
+		str.append(other, x._str.c_str() + x._str.size());
+		// Replace ourselves
+		_str = str;
+	}
 	return *this;
 }
 
-Path &Path::joinInPlace(const String &str, char separator) {
-	return joinInPlace(str.c_str(), separator);
-}
+Path &Path::appendInPlace(const char *str, char separator) {
+	if (!*str) {
+		return *this;
+	}
+	if (_str.empty()) {
+		set(str, separator);
+		return *this;
+	}
+	// From here both paths have data
 
-Path &Path::joinInPlace(const char *str, char separator) {
-	if (*str == '\0')
+	if (isEscaped()) {
+		// This one is escaped
+		// There is no chance we could unescape it
+		escape(_str, separator, str);
+		return *this;
+	}
+
+	// We are not escaped, let's hope str won't need escaping
+	if (!needsEncoding(str, separator)) {
+		// No need to encode means it's perfect
+		_str += str;
 		return *this;
+	}
 
-	size_t lastSep = findLastSeparator();
-	if (!_str.empty() && (lastSep == String::npos || lastSep != _str.size() - 2) && *str != separator)
-		_str += DIR_SEPARATOR;
+	if (!strchr(str, SEPARATOR)) {
+		// No SEPARATOR, no clash
+		// Even if str starts with ESCAPE, no need to escape as we append
+		Common::String tmp(str);
+		if (separator) {
+			// If separator is 0 there is only one path component
+			tmp.replace(separator, SEPARATOR);
+		}
+		_str += tmp;
+		return *this;
+	}
 
-	appendInPlace(str, separator);
+	// Too bad, we need to escape
+	String tmp(ESCAPE);
+	escape(tmp, SEPARATOR, _str.c_str(), _str.c_str() + _str.size());
+	escape(tmp, separator, str);
+	// Replace ourselves
+	_str = tmp;
 
 	return *this;
 }
 
-Path Path::join(const Path &x) const {
-	Path temp(*this);
-	temp.joinInPlace(x);
-	return temp;
+Path Path::appendComponent(const char *str) const {
+	if (!*str) {
+		return *this;
+	}
+
+	if (_str.empty()) {
+		return Path(str, kNoSeparator);
+	}
+
+	bool addSeparator = (*(_str.end() - 1) != SEPARATOR);
+
+	if (isEscaped()) {
+		// We are escaped, escape str as well
+		Path ret(*this);
+		if (addSeparator) {
+			ret._str += SEPARATOR;
+		}
+		// It's a component, there is no directory separator in source
+		escape(ret._str, kNoSeparator, str);
+		return ret;
+	} else if (strchr(str, SEPARATOR)) {
+		// We are not escaped but str will need escape: escape both parts
+		Path ret;
+		ret._str += ESCAPE;
+		escape(ret._str, SEPARATOR, _str.c_str(), _str.c_str() + _str.size());
+		if (addSeparator) {
+			ret._str += SEPARATOR;
+		}
+		// It's a component, there is no directory separator in source
+		escape(ret._str, kNoSeparator, str);
+		return ret;
+	} else {
+		// No need to escape anything
+		Path ret(*this);
+		if (addSeparator) {
+			ret._str += SEPARATOR;
+		}
+		ret._str += str;
+		return ret;
+	}
 }
 
-Path Path::join(const String &str, char separator) const {
-	return join(str.c_str(), separator);
+Path &Path::joinInPlace(const Path &x) {
+	if (x.empty()) {
+		return *this;
+	}
+	if (_str.empty()) {
+		_str = x._str;
+		return *this;
+	}
+
+	const char *str = x._str.c_str();
+	// Append SEPARATOR if:
+	// - we don't finish with SEPARATOR already
+	// - other Path is escaped and doesn't begin by SEPARATOR
+	// - or other Path isn't escaped and doesn't begin by SEPARATOR
+	if (*(_str.end() - 1) != SEPARATOR &&
+	        ((x.isEscaped() && str[1] != SEPARATOR) ||
+	         *str != SEPARATOR)) {
+		_str += SEPARATOR;
+	}
+
+	return appendInPlace(x);
 }
 
-Path Path::join(const char *str, char separator) const {
-	Path temp(*this);
-	temp.joinInPlace(str, separator);
-	return temp;
+Path &Path::joinInPlace(const char *str, char separator) {
+	if (*str == '\0') {
+		return *this;
+	}
+	if (_str.empty()) {
+		set(str, separator);
+		return *this;
+	}
+
+	if (*(_str.end() - 1) != SEPARATOR && *str != separator) {
+		_str += SEPARATOR;
+	}
+
+	return appendInPlace(str, separator);
 }
 
 Path Path::normalize() const {
-	if (empty()) {
+	if (_str.empty()) {
 		return Path();
 	}
 
-	Common::String::const_iterator cur = _str.begin();
-	const Common::String::const_iterator end = _str.end();
+	const char *cur = _str.c_str();
 
-	Common::Path result;
+	bool hasLeadingSeparator = false;
 
-	// If there is a leading slash, preserve that:
-	if (cur != end &&
-	    *cur == ESCAPER &&
-	    *(cur + 1) == ESCAPE_SEPARATOR) {
-		result._str += DIR_SEPARATOR;
-		cur += 2;
-		// Skip over multiple leading slashes, so "//" equals "/"
-		while (cur != end && *cur == ESCAPER && *(cur + 1) == ESCAPE_SEPARATOR)
-			cur += 2;
+	if (isEscaped()) {
+		// We are an escaped path
+		cur++;
+	}
+
+	// If there is a leading separator, preserve that:
+	if (*cur == SEPARATOR) {
+		hasLeadingSeparator = true;
+		cur++;
+		// Skip over multiple leading separators, so "//" equals "/"
+		while (*cur == SEPARATOR) {
+			cur++;
+		}
 	}
 
 	// Scan for path components till the end of the String
-	List<String> comps;
-	while (cur != end) {
-		Common::String::const_iterator start = cur;
+	StringArray comps;
+	while (*cur) {
+		const char *start = cur;
 
 		// Scan till the next path separator resp. the end of the string
-		while (!(*cur == ESCAPER && *(cur + 1) == ESCAPE_SEPARATOR) && cur != end)
-			cur++;
+		cur = strchr(cur, SEPARATOR);
+		if (!cur) {
+			cur = _str.c_str() + _str.size();
+		}
 
 		const String component(start, cur);
 
@@ -289,16 +604,70 @@ Path Path::normalize() const {
 		}
 
 		// Skip over separator chars
-		while (cur != end && *cur == ESCAPER && *(cur + 1) == ESCAPE_SEPARATOR)
-			cur += 2;
+		while (*cur == SEPARATOR) {
+			cur++;
+		}
+	}
+
+	Common::Path result;
+
+	if (comps.empty()) {
+		// No components, add the leading separator if there was any
+		if (hasLeadingSeparator) {
+			result._str += SEPARATOR;
+		}
+		return result;
+	}
+
+	// Before making the new path, we need to determine if it will be escaped
+	bool needEscape = false;
+	bool needUnescape = false;
+	if (isEscaped()) {
+		// We are an escaped path
+		// Maybe we can get unescaped because problematic component got shifted
+		if (hasLeadingSeparator || *comps.front().c_str() != ESCAPE) {
+			// Well, we don't start with ESCAPE so there is still a chance we get unescaped
+			needUnescape = true;
+
+			StringArray::const_iterator it;
+			for (it = comps.begin(); it != comps.end(); it++) {
+				if (!canUnescape(false, false, it->c_str())) {
+					// Nope we can't get unescaped
+					needUnescape = false;
+					break;
+				}
+			}
+		}
+
+		// We will have an escaped result
+		if (!needUnescape) {
+			result._str += ESCAPE;
+		}
+	} else {
+		// We are not an escaped path
+		// The only reason we would need to escape is that we begin with an ESCAPE character
+		if (!hasLeadingSeparator && *comps.front().c_str() == ESCAPE) {
+			// Uh oh: we need to escape everything
+			needEscape = true;
+			result._str += ESCAPE;
+		}
 	}
 
 	// Finally, assemble all components back into a path
-	while (!comps.empty()) {
-		result._str += comps.front();
-		comps.pop_front();
-		if (!comps.empty())
-			result._str += DIR_SEPARATOR;
+	bool addSep = hasLeadingSeparator;
+	for (StringArray::const_iterator it = comps.begin(); it != comps.end(); it++) {
+		if (addSep) {
+			result._str += SEPARATOR;
+		}
+		addSep = true;
+
+		if (needEscape) {
+			escape(result._str, kNoSeparator, it->c_str(), it->c_str() + it->size());
+		} else if (needUnescape) {
+			result._str += unescape(kNoSeparator, it->c_str(), it->c_str() + it->size());
+		} else {
+			result._str += *it;
+		}
 	}
 
 	return result;
@@ -306,129 +675,268 @@ Path Path::normalize() const {
 
 StringArray Path::splitComponents() const {
 	StringArray res;
-	String cur;
-	for (uint i = 0; i < _str.size(); i++) {
-		if (_str[i] == ESCAPER) {
-			i++;
-			if (_str[i] == ESCAPE_SLASH)
-				cur += '/';
-			else if (_str[i] == ESCAPE_SEPARATOR) {
-				res.push_back(cur);
-				cur = "";
-			} else {
-				error("Path::splitComponents(): Malformed Common::Path. '%c' unexpected after '/'", _str[i]);
-			}
-		} else
-			cur += _str[i];
+
+	if (_str.empty()) {
+		// We always return at least 1 component
+		res.push_back("");
+		return res;
 	}
 
-	res.push_back(cur);
+	const char *str = _str.c_str();
+	const char *end = str + _str.size();
+
+	bool escaped = isEscaped();
+	if (escaped) {
+		str++;
+	}
+
+	const char *sep = strchr(str, SEPARATOR);
+	while (sep) {
+		if (!escaped) {
+			res.push_back(String(str, sep));
+		} else {
+			res.push_back(unescape(kNoSeparator, str, sep));
+		}
+		str = sep + 1;
+		sep = strchr(str, SEPARATOR);
+	}
+
+	if (!escaped) {
+		res.push_back(String(str, end));
+	} else {
+		res.push_back(unescape(kNoSeparator, str, end));
+	}
 
 	return res;
 }
 
-Path Path::punycodeDecode() const {
-	StringArray c = splitComponents();
-	String res;
-
-	for (uint i = 0; i < c.size(); i++) {
-		res += escapePath(punycode_decodefilename(c[i]));
-		if (i + 1 < c.size())
-			res += DIR_SEPARATOR;
+Path Path::joinComponents(StringArray::const_iterator begin, StringArray::const_iterator end) {
+	if (begin == end) {
+		return Path();
 	}
 
-	Path ret;
-	ret._str = res;
+	Path ret(*begin, kNoSeparator);
+
+	for (StringArray::const_iterator it = begin + 1; it != end; it++) {
+		ret._str += SEPARATOR;
+		ret.appendInPlace(*it, kNoSeparator);
+	}
 	return ret;
 }
 
-Path Path::joinComponents(const StringArray& c) {
-	String res;
+template<typename T>
+T Path::reduceComponents(T(*reducer)(T value, const String &element, bool last), T value) const {
+	if (_str.empty()) {
+		return value;
+	}
+
+	const char *str = _str.c_str();
+	const char *end = str + _str.size();
 
-	for (uint i = 0; i < c.size(); i++) {
-		res += escapePath(c[i]);
-		if (i + 1 < c.size())
-			res += DIR_SEPARATOR;
+	bool escaped = isEscaped();
+	if (escaped) {
+		str++;
 	}
 
-	Path ret;
-	ret._str = res;
-	return ret;
-}
+	const char *sep = strchr(str, SEPARATOR);
+	while (sep) {
+		String item;
+		if (escaped) {
+			item = unescape(kNoSeparator, str, sep);
+		} else {
+			item = String(str, sep);
+		}
 
-// See getIdentifierString() for more details.
-// This does the same but for a single path component and is used by
-// getIdentifierString().
-static String getIdentifierComponent(const String& in) {
-	String part = punycode_decodefilename(in);
-	String res = "";
-	for (uint j = 0; j < part.size(); j++)
-		if (part[j] == '/')
-			res += ':';
-		else
-			res += part[j];
-	return res;
-}
+		value = reducer(value, item, false);
 
-// For a path creates a string with following property:
-// if 2 files have the same case-insensitive
-// identifier string then and only then we treat them as
-// effectively the same file. For this there are 2
-// transformations we need to do:
-// * decode punycode
-// * Replace / with : in path components so a path from
-// HFS(+) image will end up with : independently of how
-// it was dumped or copied from
-String Path::getIdentifierString() const {
-	StringArray c = splitComponents();
-	String res;
+		str = sep + 1;
+		sep = strchr(str, SEPARATOR);
+	}
 
-	for (uint i = 0; i < c.size(); i++) {
-		res += getIdentifierComponent(c[i]);
-		if (i + 1 < c.size())
-			res += DIR_SEPARATOR;
+	String item;
+	if (escaped) {
+		item = unescape(kNoSeparator, str, end);
+	} else {
+		item = String(str, end);
 	}
 
-	return res;
+	value = reducer(value, item, true);
+
+	return value;
 }
 
-Path Path::punycodeEncode() const {
-	StringArray c = splitComponents();
-	String res;
+bool Path::compareComponents(bool (*comparator)(const String &x, const String &y),
+                             const Path &other) const {
+	if (_str.empty() != other._str.empty()) {
+		// One is empty and the other is not
+		return false;
+	}
+	if (_str.empty()) {
+		// Both are empty
+		return true;
+	}
 
-	for (uint i = 0; i < c.size(); i++) {
-		res += escapePath(punycode_encodefilename(c[i]));
-		if (i + 1 < c.size())
-			res += DIR_SEPARATOR;
+	const char *str = _str.c_str();
+	const char *end = str + _str.size();
+	bool escaped = isEscaped();
+	if (escaped) {
+		str++;
 	}
 
-	Path ret;
-	ret._str = res;
-	return ret;
-}
+	const char *strOther = other._str.c_str();
+	const char *endOther = strOther + other._str.size();
+	bool escapedOther = other.isEscaped();
+	if (escapedOther) {
+		strOther++;
+	}
 
-bool Path::matchPattern(const Path& pattern) const {
-	StringArray c = splitComponents();
-	StringArray cpat = pattern.splitComponents();
+	const char *sep = strchr(str, SEPARATOR);
+	const char *sepOther = strchr(strOther, SEPARATOR);
+	while (sep && sepOther) {
+		String item;
+		if (escaped) {
+			item = unescape(kNoSeparator, str, sep);
+		} else {
+			item = String(str, sep);
+		}
 
-	// Prevent wildcards from matching the directory separator.
-	if (c.size() != cpat.size())
-		return false;
+		String itemOther;
+		if (escapedOther) {
+			itemOther = unescape(kNoSeparator, strOther, sepOther);
+		} else {
+			itemOther = String(strOther, sepOther);
+		}
 
-	for (uint i = 0; i < c.size(); i++) {
-		if (!getIdentifierComponent(c[i]).matchString(getIdentifierComponent(cpat[i]), true))
+		if (!comparator(item, itemOther)) {
 			return false;
+		}
+
+		str = sep + 1;
+		strOther = sepOther + 1;
+		sep = strchr(str, SEPARATOR);
+		sepOther = strchr(strOther, SEPARATOR);
 	}
 
-	return true;
+	if (sep != sepOther) {
+		// When one is nullptr and the other is not
+		// This means we don't have an equal number of path components
+		return false;
+	}
+
+	String item;
+	if (escaped) {
+		item = unescape(kNoSeparator, str, end);
+	} else {
+		item = String(str);
+	}
+
+	String itemOther;
+	if (escapedOther) {
+		itemOther = unescape(kNoSeparator, strOther, endOther);
+	} else {
+		itemOther = String(strOther);
+	}
+
+	return comparator(item, itemOther);
 }
 
-bool Path::IgnoreCaseAndMac_EqualTo::operator()(const Path& x, const Path& y) const {
-	return x.getIdentifierString().equalsIgnoreCase(y.getIdentifierString());
+Path Path::punycodeDecode() const {
+	Path tmp;
+	return reduceComponents<Path &>(
+		+[](Path &path, const String &in, bool last) -> Path & {
+			// We encode the result as UTF-8
+			String out = punycode_decodefilename(in).encode();
+			path.appendInPlace(out, kNoSeparator);
+			if (!last) {
+				path._str += SEPARATOR;
+			}
+			return path;
+		}, tmp);
+}
+
+Path Path::punycodeEncode() const {
+	Path tmp;
+	return reduceComponents<Path &>(
+		+[](Path &path, const String &in, bool last) -> Path & {
+			// We decode the result as UTF-8
+			Common::String out = punycode_encodefilename(in.decode());
+			path.appendInPlace(out, kNoSeparator);
+			if (!last) {
+				path._str += SEPARATOR;
+			}
+			return path;
+		}, tmp);
 }
 
-uint Path::IgnoreCaseAndMac_Hash::operator()(const Path& x) const {
-	return hashit_lower(x.getIdentifierString().c_str());
+// For a path component creates a string with following property:
+// if 2 files have the same case-insensitive
+// identifier string then and only then we treat them as
+// effectively the same file. For this there are 2
+// transformations we need to do:
+// * decode punycode
+// * Replace / with : in path components so a path from
+// HFS(+) image will end up with : independently of how
+// it was dumped or copied from
+static String getIdentifierComponent(const String &in) {
+	String part = punycode_decodefilename(in).encode();
+	part.replace('/', ':');
+	return part;
+}
+
+// This hash algorithm is inspired by a Python proposal to hash for tuples
+// https://bugs.python.org/issue942952#msg20602
+// As we don't have the length, it's not added in but
+// it doesn't change collisions that much on their stress test
+struct hasher {
+	uint result;
+	uint mult;
+};
+
+uint Path::hashIgnoreCase() const {
+	hasher v = { 0x345678, 1000003 };
+	reduceComponents<hasher &>(
+		+[](hasher &value, const String &in, bool last) -> hasher & {
+			uint hash = hashit_lower(in);
+
+			value.result = (value.result + hash) * value.mult;
+			value.mult = (value.mult * 69069);
+			return value;
+		}, v);
+	return v.result;
+}
+
+uint Path::hashIgnoreCaseAndMac() const {
+	hasher v = { 0x345678, 1000003 };
+	reduceComponents<hasher &>(
+		+[](hasher &value, const String &in, bool last) -> hasher & {
+			uint hash = hashit_lower(getIdentifierComponent(in));
+
+			value.result = (value.result + hash) * value.mult;
+			value.mult = (value.mult * 69069);
+			return value;
+		}, v);
+	return v.result;
+}
+
+bool Path::matchPattern(const Path &pattern) const {
+	return compareComponents(
+		+[](const String &x, const String &y) {
+			return getIdentifierComponent(x).matchString(getIdentifierComponent(y), true);
+		}, pattern);
+}
+
+bool Path::equalsIgnoreCase(const Path &other) const {
+	return compareComponents(
+		+[](const String &x, const String &y) {
+			return x.equalsIgnoreCase(y);
+		}, other);
+}
+
+bool Path::equalsIgnoreCaseAndMac(const Path &other) const {
+	return compareComponents(
+		+[](const String &x, const String &y) {
+			return getIdentifierComponent(x).equalsIgnoreCase(getIdentifierComponent(y));
+		}, other);
 }
 
 } // End of namespace Common
diff --git a/common/path.h b/common/path.h
index 4ce192dbba0..469412880e6 100644
--- a/common/path.h
+++ b/common/path.h
@@ -26,6 +26,10 @@
 #include "common/str.h"
 #include "common/str-array.h"
 
+#ifdef CXXTEST_RUNNING
+class PathTestSuite;
+#endif
+
 namespace Common {
 
 /**
@@ -40,18 +44,144 @@ namespace Common {
 /**
  * Simple path class. Allows simple conversion to/from path strings with
  * arbitrary directory separators, providing a common representation.
- * 
+ *
  * Internally, this is just a simple wrapper around a String, using
- * "//" (unit separator) as a directory separator and "/+" as "/".
+ * "/" as a directory separator.
+ * It escapes it using "|" if / is used inside a path component.
  */
 class Path {
+#ifdef CXXTEST_RUNNING
+	friend class ::PathTestSuite;
+#endif
+
 private:
+#ifndef RELEASE_BUILD
+	static bool _shownSeparatorCollisionWarning;
+#endif
+
+	// The directory separator
+	static const char SEPARATOR = '/';
+	// The escape prefix character
+	static const char ESCAPE = '|';
+	// How the prefix character is escaped (doubling)
+	static const char ESCAPED_ESCAPE = '|';
+	// How the separator is escaped
+	static const char ESCAPED_SEPARATOR  = '\\';
+
 	String _str;
 
-	String getIdentifierString() const;
+	/**
+	 * Escapes a path:
+	 * - all ESCAPE are encoded to ESCAPE ESCAPED_ESCAPE
+	 * - all SEPARATOR are encoded to ESCAPE ESCAPED_SEPARATOR if srcSeparator is not SEPARATOR
+	 * - replaces all srcSeparator to SEPARATOR
+	 *
+	 * @param dst The String object to append result to.
+	 * @param srcSeparator The directory separator used in source string.
+	 * @param begin Begin of range
+	 * @param end End of the range excluded.
+	 */
+	static void escape(String &dst, char srcSeparator, const char *src, const char *end = nullptr);
+
+	/**
+	 * Invert of escape
+	 * - all ESCAPE ESCAPED_ESCAPE sequences are restored to ESCAPE
+	 * - all ESCAPE ESCAPED_SEPARATOR sequences are restored to SEPARATOR
+	 * - all SEPARATOR are replaced by dstSeparator
+	 * Collisions in resulting path are checked and warned once.
+	 *
+	 * @param dstSeparator The directory separator to use in resulting string.
+	 * @param begin Start of the range.
+	 * @param end End of the range excluded.
+	 */
+	static String unescape(char dstSeparator, const char *src, const char *end = nullptr);
+
+	/**
+	 * Checks if the provided range can be unescaped
+	 *
+	 * @param atBegin Whether this range will end up at the begin of path or not.
+	 * @param begin Start of the range.
+	 * @param end End of the range excluded.
+	 *
+	 */
+	static bool canUnescape(bool willBeAtBegin, bool wasAtBegin,
+	                        const char *begin, const char *end = nullptr);
+
+	/**
+	 * Determines if the provided string will need to be encode and can't be copied as is
+	 *
+	 * @param str The string to check
+	 * @param separator The directory separator used in str
+	 */
+	static inline bool needsEncoding(const char *str, char separator) {
+		return *str && // String is not empty and
+		       (separator != SEPARATOR || // separator is not the one we use
+		        *str == ESCAPE); // or string begins with ESCAPE
+	}
+
+	/**
+	 * Encodes a path:
+	 * - escapes when needed
+	 * - all separators are changed to SEPARATOR
+	 * - a ESCAPE is prepended to string if escaping took place
+	 * - if separator is \x00 str is assumed to be only one component
+	 * - using ESCAPE as separator is not supported
+	 *
+	 * @param str The string to encode
+	 * @param separator The directory separator used in str
+	 */
+	static String encode(const char *str, char separator);
+
+	/**
+	 * Creates a path using [begin, end) path data from ourselves.
+	 * begin and end are assumed to lie inside _str
+	 *
+	 * @param begin Start of the range.
+	 * @param end End of the range excluded.
+	 *
+	 */
+	Path extract(const char *begin, const char *end = nullptr) const;
+
+	/** Finds the last separator before @p last. */
 	size_t findLastSeparator(size_t last = String::npos) const;
 
+	/**
+	 * Apply a reduction function on every path components
+	 * and returns the reducer result
+	 *
+	 * @param reducer The function which reduces the path components
+	 * @param value The initial value passed to reducer
+	 */
+	template<typename T>
+	T reduceComponents(T (*reducer)(T value, const String &element, bool last), T value) const;
+
+	/**
+	 * Compares a path component by component by calling a comparator function
+	 * The function bails out as soon as the comparision fails.
+	 *
+	 * @param comparator The function which compares the path components
+	 * @param other The other path to compare with
+	 */
+	bool compareComponents(bool (*comparator)(const String &x, const String &y), const Path &other) const;
+
+	static Path &punycode_decodefilename_helper(Path &path, const String &in, bool last);
+	static Path &punycode_encodefilename_helper(Path &path, const String &in, bool last);
+
+	/**
+	 * Determines if the path is escaped
+	 */
+	inline bool isEscaped() const {
+		// c_str() returns a null terminated string, if _str is empty we get \0
+		return *_str.c_str() == ESCAPE;
+	}
+
 public:
+	/**
+	 * A separator to use when building path conataining only base names
+	 * This must not be used with toString(), use baseName() instead.
+	 */
+	static const char kNoSeparator = '\x00';
+
 	/**
 	 * Hash and comparator for Path with following changes:
 	 * * case-insensitive
@@ -62,42 +192,61 @@ public:
 	 * and "Sound Manager 3.1 : SoundLib/Sound"
 	 */
 	struct IgnoreCaseAndMac_EqualTo {
-		bool operator()(const Path& x, const Path& y) const;
+		bool operator()(const Path &x, const Path &y) const { return x.equalsIgnoreCaseAndMac(y); }
 	};
 
 	struct IgnoreCaseAndMac_Hash {
-		uint operator()(const Path& x) const;
+		uint operator()(const Path &x) const { return x.hashIgnoreCaseAndMac(); }
+	};
+
+	/**
+	 * Hash and comparator for Path with case-insensitivity
+	 * This may not be used when punycoded and Mac files could be found
+	 * but this should be safe in other places and costs less
+	 */
+	struct IgnoreCase_EqualTo {
+		bool operator()(const Path &x, const Path &y) const { return x.equalsIgnoreCase(y); }
+	};
+
+	struct IgnoreCase_Hash {
+		uint operator()(const Path &x) const { return x.hashIgnoreCase(); }
 	};
 
 	/** Construct a new empty path. */
 	Path() {}
 
 	/** Construct a copy of the given path. */
-	Path(const Path &path);
+	Path(const Path &path) : _str(path._str) { }
 
 	/**
 	 * Construct a new path from the given NULL-terminated C string.
-	 * 
+	 *
 	 * @param str       A NULL-terminated C string representing a path,
 	 *                  e.g. "foo/bar/baz"
 	 * @param separator The directory separator used in the path string.
+	 *                  Use kNoSeparator if there is no separator.
 	 *                  Defaults to '/'.
 	 */
-	Path(const char *str, char separator = '/');
+	Path(const char *str, char separator = '/') :
+		_str(needsEncoding(str, separator) ? encode(str, separator) : str) { }
 
 	/**
 	 * Construct a new path from the given String.
-	 * 
+	 *
 	 * @param str       A String representing a path, e.g. "foo/bar/baz"
 	 * @param separator The directory separator used in the path string.
+	 *                  Use kNoSeparator if there is no separator.
 	 *                  Defaults to '/'.
 	 */
-	Path(const String &str, char separator = '/');
+	Path(const String &str, char separator = '/') :
+		_str(needsEncoding(str.c_str(), separator) ? encode(str.c_str(), separator) : str) { }
 
 	/**
 	 * Converts a path to a string using the given directory separator.
-	 * 
+	 * Collisions in resulting path are checked and warned once.
+	 *
 	 * @param separator The character used to separate directory names.
+	 *                  kNoSeparator must not be used here.
 	 *                  Defaults to '/'.
 	 */
 	String toString(char separator = '/') const;
@@ -119,24 +268,66 @@ public:
 	Path getLastComponent() const;
 
 	/** Check whether this path is identical to path @p x. */
-	bool operator==(const Path &x) const;
+	bool operator==(const Path &x) const {
+		return _str == x._str;
+	}
 
 	/** Check whether this path is different than path @p x. */
-	bool operator!=(const Path &x) const;
+	bool operator!=(const Path &x) const {
+		return _str != x._str;
+	}
+
+	/**
+	 * Check whether this path is identical to path @p x.
+	 * Ignores case
+	 */
+	bool equalsIgnoreCase(const Path &x) const;
+	/**
+	 * Check whether this path is identical to path @p x.
+	 * Ignores case, punycode and Mac path separator.
+	 */
+	bool equalsIgnoreCaseAndMac(const Path &x) const;
+
+	/**
+	 * Calculate a case insensitive hash of path
+	 */
+	uint hashIgnoreCase() const;
+	/**
+	 * Calculate a hash of path which is case insensitive.
+	 * Ignores case, punycode and Mac path separator.
+	 */
+	uint hashIgnoreCaseAndMac() const;
 
 	/** Return if this path is empty */
-	bool empty() const;
+	bool empty() const {
+		return _str.empty();
+	}
 
 	/** Assign a given path to this path. */
-	Path &operator=(const Path &str);
+	Path &operator=(const Path &path) {
+		_str = path._str;
+		return *this;
+	}
 
 	/** @overload */
-	Path &operator=(const char *str);
+	Path &operator=(const char *str) {
+		set(str);
+		return *this;
+	}
 
 	/** @overload */
-	Path &operator=(const String &str);
-
-	void set(const char *str, char separator = '/');
+	Path &operator=(const String &str) {
+		set(str.c_str());
+		return *this;
+	}
+
+	void set(const char *str, char separator = '/') {
+		if (needsEncoding(str, separator)) {
+			_str = encode(str, separator);
+		} else {
+			_str = str;
+		}
+	}
 
 	/**
 	 * Appends the given path to this path (in-place).
@@ -145,7 +336,10 @@ public:
 	Path &appendInPlace(const Path &x);
 
 	/** @overload */
-	Path &appendInPlace(const String &str, char separator = '/');
+	Path &appendInPlace(const String &str, char separator = '/') {
+		appendInPlace(str.c_str(), separator);
+		return *this;
+	}
 
 	/** @overload */
 	Path &appendInPlace(const char *str, char separator = '/');
@@ -154,19 +348,34 @@ public:
 	 * Returns this path with the given path appended (out-of-place).
 	 * Does not automatically add a directory separator.
 	 */
-	Path append(const Path &x) const;
+	Path append(const Path &x) const {
+		Path temp(*this);
+		temp.appendInPlace(x);
+		return temp;
+	}
 
 	/** @overload */
-	Path append(const String &str, char separator = '/') const;
+	Path append(const String &str, char separator = '/') const {
+		return append(str.c_str(), separator);
+	}
 
 	/** @overload */
-	Path append(const char *str, char separator = '/') const;
+	Path append(const char *str, char separator = '/') const {
+		Path temp(*this);
+		temp.appendInPlace(str, separator);
+		return temp;
+	}
 
 	/**
 	 * Appends exactly one component, without any separators
 	 * and prepends a separator if necessarry
 	 */
-	Path appendComponent(const String &x) const;
+	Path appendComponent(const char *str) const;
+
+	/** @overload */
+	Path appendComponent(const String &x) const {
+		return appendComponent(x.c_str());
+	}
 
 	/**
 	 * Joins the given path to this path (in-place).
@@ -175,7 +384,9 @@ public:
 	Path &joinInPlace(const Path &x);
 
 	/** @overload */
-	Path &joinInPlace(const String &str, char separator = '/');
+	Path &joinInPlace(const String &str, char separator = '/') {
+		return joinInPlace(str.c_str(), separator);
+	}
 
 	/** @overload */
 	Path &joinInPlace(const char *str, char separator = '/');
@@ -184,28 +395,38 @@ public:
 	 * Returns this path joined with the given path (out-of-place).
 	 * Automatically adds a directory separator.
 	 */
-	Path join(const Path &x) const;
+	Path join(const Path &x) const {
+		Path temp(*this);
+		temp.joinInPlace(x);
+		return temp;
+	}
 
 	/** @overload */
-	Path join(const String &str, char separator = '/') const;
+	Path join(const String &str, char separator = '/') const {
+		return join(str.c_str(), separator);
+	}
 
 	/** @overload */
-	Path join(const char *str, char separator = '/') const;
+	Path join(const char *str, char separator = '/') const {
+		Path temp(*this);
+		temp.joinInPlace(str, separator);
+		return temp;
+	}
 
 	/**
 	 * Convert path from Punycode
 	 */
 	Path punycodeDecode() const;
 
-        /**
-	 * Convert path to Punycode
+	/**
+	* Convert path to Punycode
 	 */
 	Path punycodeEncode() const;
 
-        /**
-	 * Check pattern match similar matchString
+	/**
+	* Check pattern match similar matchString
 	 */
-	bool matchPattern(const Path& pattern) const;
+	bool matchPattern(const Path &pattern) const;
 
 	/**
 	 * Normalize path to a canonical form. In particular:
@@ -227,11 +448,13 @@ public:
 	 */
 	StringArray splitComponents() const;
 
-
 	/**
 	 * Opposite of splitComponents
 	 */
-	static Path joinComponents(const StringArray& c);
+	static Path joinComponents(StringArray::const_iterator begin, StringArray::const_iterator end);
+	static Path joinComponents(const StringArray &c) {
+		return joinComponents(c.begin(), c.end());
+	}
 };
 
 /** @} */
diff --git a/test/common/path.h b/test/common/path.h
index 043f19dcea1..7d1bb58194e 100644
--- a/test/common/path.h
+++ b/test/common/path.h
@@ -1,40 +1,138 @@
 #include <cxxtest/TestSuite.h>
 
+#include "test/common/str-helper.h"
+
 #include "common/path.h"
+#include "common/hashmap.h"
 
 static const char *TEST_PATH = "parent/dir/file.txt";
+static const char *TEST_ESCAPED1_PATH = "|parent/dir/file.txt";
+static const char *TEST_ESCAPED2_PATH = "par/ent\\dir\\file.txt";
+static const char *TEST_BS_PATH = "parent\\dir\\file.txt";
 
 class PathTestSuite : public CxxTest::TestSuite
 {
 	public:
 	void test_Path() {
 		Common::Path p;
-		TS_ASSERT_EQUALS(p.toString(), Common::String());
+		TS_ASSERT_EQUALS(p.toString(), "");
+		TS_ASSERT_EQUALS(p.empty(), true);
 
 		Common::Path p2(TEST_PATH);
-		TS_ASSERT_EQUALS(p2.toString(), Common::String(TEST_PATH));
+		TS_ASSERT_EQUALS(p2.toString(), TEST_PATH);
+		TS_ASSERT_EQUALS(p2.toString('|'), "parent|dir|file.txt");
+		TS_ASSERT_EQUALS(p2.toString('\\'), "parent\\dir\\file.txt");
+
+		Common::Path p3(TEST_ESCAPED1_PATH);
+		TS_ASSERT_EQUALS(p3.toString(), TEST_ESCAPED1_PATH);
+		TS_ASSERT_EQUALS(p3.toString('\\'), "|parent\\dir\\file.txt");
+
+		Common::Path p4(TEST_ESCAPED2_PATH, '\\');
+		TS_ASSERT_EQUALS(p4.toString('\\'), TEST_ESCAPED2_PATH);
+
+		Common::Path p5(TEST_BS_PATH, '\\');
+		TS_ASSERT_EQUALS(p5.toString('\\'), TEST_BS_PATH);
+
+#ifndef RELEASE_BUILD
+		Common::Path::_shownSeparatorCollisionWarning = false;
+		TS_ASSERT_EQUALS(p3.toString('|'), "|parent|dir|file.txt");
+		TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
+
+		Common::Path::_shownSeparatorCollisionWarning = false;
+		TS_ASSERT_EQUALS(p3.toString('i'), "|parentidirifile.txt");
+		TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
+
+		Common::Path::_shownSeparatorCollisionWarning = false;
+		TS_ASSERT_EQUALS(p4.toString('/'), "par/ent/dir/file.txt");
+		TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
+
+		Common::Path::_shownSeparatorCollisionWarning = false;
+		TS_ASSERT_EQUALS(p5.toString('i'), "parentidirifile.txt");
+		TS_ASSERT_EQUALS(Common::Path::_shownSeparatorCollisionWarning, true);
+#endif
 	}
 
-	void test_getLastComponent() {
+	void test_clear() {
 		Common::Path p(TEST_PATH);
-		TS_ASSERT_EQUALS(p.getLastComponent().toString(), "file.txt");
+		TS_ASSERT_EQUALS(p.empty(), false);
+
+		p.clear();
+		TS_ASSERT_EQUALS(p.empty(), true);
+
+		TS_ASSERT(p.equals(Common::Path()));
+		TS_ASSERT(p != Common::Path(TEST_PATH));
+	}
+
+	void test_getLastComponent() {
+		Common::Path p;
+		TS_ASSERT_EQUALS(p.getLastComponent().toString(), "");
+		TS_ASSERT_EQUALS(p.getLastComponent(), Common::Path());
+
+		Common::Path p2(TEST_PATH);
+		TS_ASSERT_EQUALS(p2.getLastComponent().toString(), "file.txt");
+		TS_ASSERT_EQUALS(p2.getLastComponent(), Common::Path("file.txt"));
+
+		Common::Path p3("parent/dir/|file.txt");
+		TS_ASSERT_EQUALS(p3.getLastComponent().toString(), "|file.txt");
+		TS_ASSERT_EQUALS(p3.getLastComponent(), Common::Path("|file.txt"));
 	}
 
 	void test_getParent() {
-		Common::Path p(TEST_PATH);
-		TS_ASSERT_EQUALS(p.getParent().toString(), "parent/dir/");
+		Common::Path p;
+		TS_ASSERT_EQUALS(p.getParent().toString(), "");
+
+		Common::Path p2(TEST_PATH);
+		TS_ASSERT_EQUALS(p2.getParent().toString(), "parent/dir/");
+		// TODO: should this work?
+		TS_ASSERT_EQUALS(p2.getParent().getLastComponent().toString(), "dir/");
+
+		Common::Path p3(TEST_ESCAPED1_PATH);
+		TS_ASSERT_EQUALS(p3.getParent().toString(), "|parent/dir/");
 		// TODO: should this work?
-		TS_ASSERT_EQUALS(p.getParent().getLastComponent().toString(), "dir/");
+		TS_ASSERT_EQUALS(p3.getParent().getLastComponent().toString(), "dir/");
+
+		Common::Path p4(TEST_ESCAPED2_PATH, '\\');
+		TS_ASSERT_EQUALS(p4.getParent().toString('\\'), "par/ent\\dir\\");
+		// TODO: should this work?
+		TS_ASSERT_EQUALS(p4.getParent().getLastComponent().toString('\\'), "dir\\");
 	}
 
 	void test_join() {
 		Common::Path p("dir");
 		Common::Path p2 = p.join("file.txt");
 		TS_ASSERT_EQUALS(p2.toString(), "dir/file.txt");
+		p2 = p.join("");
+		TS_ASSERT_EQUALS(p2.toString(), "dir");
+		p2 = p.join(Common::Path());
+		TS_ASSERT_EQUALS(p2.toString(), "dir");
+
+		Common::Path p3;
+		Common::Path p4 = p3.join("file.txt");
+		TS_ASSERT_EQUALS(p4.toString(), "file.txt");
+		p4 = p3.join(Common::String("file.txt"));
+		TS_ASSERT_EQUALS(p4.toString(), "file.txt");
+		p4 = p3.join(Common::Path("file.txt"));
+		TS_ASSERT_EQUALS(p4.toString(), "file.txt");
 
-		Common::Path p3(TEST_PATH);
-		Common::Path p4 = p3.getParent().join("other.txt");
-		TS_ASSERT_EQUALS(p4.toString(), "parent/dir/other.txt");
+		Common::Path p5(TEST_PATH);
+		Common::Path p6 = p5.getParent().join("other.txt");
+		TS_ASSERT_EQUALS(p6.toString(), "parent/dir/other.txt");
+		p6 = p5.getParent().join("|child\\other.txt", '\\');
+		TS_ASSERT_EQUALS(p6.toString(), "parent/dir/|child/other.txt");
+		p6 = p5.getParent().join("/child\\other.txt", '\\');
+		TS_ASSERT_EQUALS(p6.toString('|'), "parent|dir|/child|other.txt");
+		p6 = p5.getParent().join(Common::Path("|other.txt"));
+		TS_ASSERT_EQUALS(p6.toString(), "parent/dir/|other.txt");
+		p6 = p5.getParent().join(Common::Path("oth/er.txt", '\\'));
+		TS_ASSERT_EQUALS(p6.toString('\\'), "parent\\dir\\oth/er.txt");
+
+		Common::Path p7(TEST_ESCAPED1_PATH);
+		Common::Path p8 = p7.getParent().join("other.txt");
+		TS_ASSERT_EQUALS(p8.toString(), "|parent/dir/other.txt");
+		p8 = p7.getParent().join(Common::Path("other.txt"));
+		TS_ASSERT_EQUALS(p8.toString(), "|parent/dir/other.txt");
+		p8 = p7.getParent().join(Common::Path("|other.txt"));
+		TS_ASSERT_EQUALS(p8.toString(), "|parent/dir/|other.txt");
 	}
 
 	// Ensure we can joinInPlace correctly with leading or trailing separators
@@ -54,6 +152,52 @@ class PathTestSuite : public CxxTest::TestSuite
 		Common::Path p4("123/def");
 		p4.joinInPlace(Common::Path("/file4.txt"));
 		TS_ASSERT_EQUALS(p4.toString(), "123/def/file4.txt");
+
+		Common::Path p5("abc/def");
+		p5.joinInPlace(Common::String("file.txt"));
+		TS_ASSERT_EQUALS(p5.toString(), "abc/def/file.txt");
+	}
+
+	void test_append() {
+		Common::Path p("abc/def");
+		p.appendInPlace("");
+		TS_ASSERT_EQUALS(p.toString(), "abc/def");
+
+		Common::Path p2;
+		p2.appendInPlace("file.txt");
+		TS_ASSERT_EQUALS(p2.toString(), "file.txt");
+
+		Common::Path p3("abc/def");
+		p3.appendInPlace(Common::Path());
+		TS_ASSERT_EQUALS(p3.toString(), "abc/def");
+
+		Common::Path p4;
+		p4.appendInPlace(Common::Path("file.txt"));
+		TS_ASSERT_EQUALS(p4.toString(), "file.txt");
+
+		TS_ASSERT_EQUALS(p4.append("a|b", '|').toString(), "file.txta/b");
+		TS_ASSERT_EQUALS(p4.append(Common::String("a|b"), '|').toString('/'), "file.txta/b");
+		TS_ASSERT_EQUALS(p4.append(p3).toString(), "file.txtabc/def");
+	}
+
+	void test_appendComponent() {
+		Common::Path p("abc/def");
+		Common::Path p2 = p.appendComponent("");
+		TS_ASSERT_EQUALS(p2.toString(), "abc/def");
+
+		Common::Path p3;
+		Common::Path p4 = p3.appendComponent("file.txt");
+		TS_ASSERT_EQUALS(p4.toString(), "file.txt");
+
+		p2 = p.appendComponent("file.txt");
+		TS_ASSERT_EQUALS(p2.toString(), "abc/def/file.txt");
+
+		p2 = p.appendComponent("fi/le.txt");
+		TS_ASSERT_EQUALS(p2.toString('\\'), "abc\\def\\fi/le.txt");
+
+		Common::Path p5("abc\\de/f", '\\');
+		Common::Path p6 = p5.appendComponent(Common::String("fi/le.txt"));
+		TS_ASSERT_EQUALS(p6.toString('\\'), "abc\\de/f\\fi/le.txt");
 	}
 
 	void test_separator() {
@@ -67,8 +211,61 @@ class PathTestSuite : public CxxTest::TestSuite
 		TS_ASSERT_EQUALS(p2.getParent().getParent().toString('#'), "par#");
 	}
 
+	void test_splitComponents() {
+		Common::Path p(TEST_PATH);
+		Common::StringArray array = p.splitComponents();
+
+		TS_ASSERT_EQUALS(array.size(), 3u);
+
+		Common::StringArray::iterator iter = array.begin();
+
+		TS_ASSERT_EQUALS(*iter, "parent");
+		++iter;
+		TS_ASSERT_EQUALS(*iter, "dir");
+		++iter;
+		TS_ASSERT_EQUALS(*iter, "file.txt");
+
+		Common::Path p2;
+		Common::StringArray array2 = p2.splitComponents();
+		TS_ASSERT_EQUALS(array2.size(), 1u);
+		Common::StringArray::iterator iter2 = array2.begin();
+		TS_ASSERT_EQUALS(*iter2, "");
+
+		Common::Path p3(TEST_ESCAPED1_PATH);
+		Common::StringArray array3 = p3.splitComponents();
+
+		TS_ASSERT_EQUALS(array3.size(), 3u);
+
+		Common::StringArray::iterator iter3 = array3.begin();
+
+		TS_ASSERT_EQUALS(*iter3, "|parent");
+		++iter3;
+		TS_ASSERT_EQUALS(*iter3, "dir");
+		++iter3;
+		TS_ASSERT_EQUALS(*iter3, "file.txt");
+
+	}
+
+	void test_joinComponents() {
+		Common::StringArray array;
+		Common::Path p = Common::Path::joinComponents(array);
+		TS_ASSERT_EQUALS(p.toString(), "");
+
+		array.push_back("");
+		p = Common::Path::joinComponents(array);
+		TS_ASSERT_EQUALS(p.toString(), "");
+
+		Common::StringArray array2;
+		array2.push_back("par/ent");
+		array2.push_back("dir");
+		array2.push_back("file.txt");
+		p = Common::Path::joinComponents(array2);
+		TS_ASSERT_EQUALS(p.toString('\\'), TEST_ESCAPED2_PATH);
+	}
+
 	void test_normalize() {
 		TS_ASSERT_EQUALS(Common::Path("/", '/').normalize().toString(), "/");
+		TS_ASSERT_EQUALS(Common::Path("///", '/').normalize().toString(), "/");
 		TS_ASSERT_EQUALS(Common::Path("/foo/bar", '/').normalize().toString(), "/foo/bar");
 		TS_ASSERT_EQUALS(Common::Path("/foo//bar/", '/').normalize().toString(), "/foo/bar");
 		TS_ASSERT_EQUALS(Common::Path("/foo/./bar", '/').normalize().toString(), "/foo/bar");
@@ -94,5 +291,129 @@ class PathTestSuite : public CxxTest::TestSuite
 		TS_ASSERT_EQUALS(Common::Path("foo/../../bar//", '/').normalize().toString(), "../bar");
 		TS_ASSERT_EQUALS(Common::Path("../foo/../bar", '/').normalize().toString(), "../bar");
 		TS_ASSERT_EQUALS(Common::Path("../../foo/bar/", '/').normalize().toString(), "../../foo/bar");
+
+		TS_ASSERT_EQUALS(Common::Path("foo/../|bar", '/').normalize().toString(), "|bar");
+		TS_ASSERT_EQUALS(Common::Path("foo/^..^bar", '^').normalize().toString('^'), "bar");
+		TS_ASSERT_EQUALS(Common::Path("foo^..^bar/", '^').normalize().toString('^'), "bar/");
+	}
+
+	void test_punycode() {
+		Common::Path p;
+		Common::Path p2 = p.punycodeDecode();
+		TS_ASSERT_EQUALS(p.toString(), "");
+
+		Common::Path p3("parent/dir/xn--Sound Manager 3.1  SoundLib-lba84k/Sound");
+		Common::Path p4 = p3.punycodeDecode();
+
+		TS_ASSERT_EQUALS(p4.toString(':'), "parent:dir:Sound Manager 3.1 / SoundLib:Sound");
+		Common::Path p5 = p4.punycodeEncode();
+		TS_ASSERT_EQUALS(p5.toString('/'), "parent/dir/xn--Sound Manager 3.1  SoundLib-lba84k/Sound");
+
+		typedef Common::HashMap<Common::Path, bool,
+				Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualTo> TestPathMap;
+		TestPathMap map;
+
+		map.setVal(p3, false);
+		TS_ASSERT_EQUALS(map.size(), 1u);
+		map.setVal(p4, false);
+		TS_ASSERT_EQUALS(map.size(), 1u);
+		map.setVal(p5, false);
+		TS_ASSERT_EQUALS(map.size(), 1u);
+
+		map.setVal(p, false);
+		TS_ASSERT_EQUALS(map.size(), 2u);
+	}
+
+	void test_caseinsensitive() {
+		Common::Path p;
+		Common::Path p2("parent:dir:Sound Manager 3.1 / SoundLib:Sound", ':');
+		Common::Path p3("parent:dir:sound manager 3.1 / soundlib:sound", ':');
+		Common::Path p4("parent/dir/xn--Sound Manager 3.1  SoundLib-lba84k/Sound");
+
+		typedef Common::HashMap<Common::Path, bool,
+				Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> TestPathMap;
+		TestPathMap map;
+
+		map.setVal(p2, false);
+		TS_ASSERT_EQUALS(map.size(), 1u);
+		map.setVal(p3, false);
+		TS_ASSERT_EQUALS(map.size(), 1u);
+		map.setVal(p4, false);
+		TS_ASSERT_EQUALS(map.size(), 2u);
+
+		map.setVal(p, false);
+		TS_ASSERT_EQUALS(map.size(), 3u);
+	}
+
+	void test_casesensitive() {
+		Common::Path p2("parent:dir:Sound Manager 3.1 / SoundLib:Sound", ':');
+		Common::Path p3("parent:dir:sound manager 3.1 / soundlib:sound", ':');
+		Common::Path p4("parent/dir/xn--Sound Manager 3.1  SoundLib-lba84k/Sound");
+
+		TS_ASSERT_DIFFERS(p2.hash(), p3.hash());
+		TS_ASSERT_DIFFERS(p2.hash(), p4.hash());
+		TS_ASSERT_DIFFERS(p3.hash(), p4.hash());
+	}
+
+	void test_matchString() {
+		TS_ASSERT(Common::Path("").matchPattern(""));
+		TS_ASSERT(Common::Path("a").matchPattern("*"));
+		TS_ASSERT(Common::Path("monkey.s01").matchPattern("*"));
+
+		TS_ASSERT(!Common::Path("").matchPattern("?"));
+		TS_ASSERT(Common::Path("a").matchPattern("?"));
+		TS_ASSERT(!Common::Path("monkey.s01").matchPattern("?"));
+
+		TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s??"));
+		TS_ASSERT(Common::Path("monkey.s99").matchPattern("monkey.s??"));
+		TS_ASSERT(!Common::Path("monkey.s101").matchPattern("monkey.s??"));
+
+		TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s?1"));
+		TS_ASSERT(!Common::Path("monkey.s99").matchPattern("monkey.s?1"));
+		TS_ASSERT(!Common::Path("monkey.s101").matchPattern("monkey.s?1"));
+
+		TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s*"));
+		TS_ASSERT(Common::Path("monkey.s99").matchPattern("monkey.s*"));
+		TS_ASSERT(Common::Path("monkey.s101").matchPattern("monkey.s*"));
+
+		TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s*1"));
+		TS_ASSERT(!Common::Path("monkey.s99").matchPattern("monkey.s*1"));
+		TS_ASSERT(Common::Path("monkey.s101").matchPattern("monkey.s*1"));
+
+		TS_ASSERT(Common::Path("monkey.s01").matchPattern("monkey.s##"));
+		TS_ASSERT(!Common::Path("monkey.s01").matchPattern("monkey.###"));
+
+		TS_ASSERT(Common::Path("monkey.s0#").matchPattern("monkey.s0\\#"));
+		TS_ASSERT(!Common::Path("monkey.s0#").matchPattern("monkey.s0#"));
+		TS_ASSERT(!Common::Path("monkey.s01").matchPattern("monkey.s0\\#"));
+
+		TS_ASSERT(Common::Path("test/monkey.s01").matchPattern("*/*"));
+		TS_ASSERT(!Common::Path("test/monkey.s01").matchPattern("|test/*"));
+		TS_ASSERT(Common::Path("|test/monkey.s01").matchPattern("*/*"));
+		TS_ASSERT(!Common::Path("test/monkey.s01").matchPattern("*"));
+		TS_ASSERT(!Common::Path("test/monkey.s01").matchPattern(Common::Path("test\\fi/le.txt", '\\')));
+	}
+
+	// These tests are here to exercise cases currently not used
+	// This allow to reach 100% code coverage (except unescape error)
+	void test_findLastSeparator() {
+		Common::Path p(TEST_PATH);
+		TS_ASSERT_EQUALS(p.findLastSeparator(), 10u);
+
+		Common::Path p2("file.txt");
+		TS_ASSERT_EQUALS(p2.findLastSeparator(), Common::String::npos);
+	}
+
+	void test_extract() {
+		Common::Path p(TEST_PATH);
+		Common::Path p2 = p.extract(p._str.c_str(), p._str.c_str());
+		TS_ASSERT_EQUALS(p2, Common::Path());
+
+		Common::Path p3("file.txt");
+		TS_ASSERT_EQUALS(p3.extract(p3._str.c_str()), p3);
+	}
+
+	void test_canUnescape() {
+		TS_ASSERT(Common::Path::canUnescape(true, true, ""));
 	}
 };


Commit: 23fda47ac87407ad592d18191b15450a4833f448
    https://github.com/scummvm/scummvm/commit/23fda47ac87407ad592d18191b15450a4833f448
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Improve punydecode performance

Avoid copies as much as we can by working in place.

Changed paths:
    common/punycode.cpp
    common/punycode.h


diff --git a/common/punycode.cpp b/common/punycode.cpp
index 43054152e1a..e3ea1c538be 100644
--- a/common/punycode.cpp
+++ b/common/punycode.cpp
@@ -223,12 +223,14 @@ bool punycode_needEncode(const String &src) {
 	return false;
 }
 
-U32String punycode_decode(const String &src1) {
-	if (!src1.hasPrefix("xn--"))
+U32String punycode_decode(const String &src1, bool *error) {
+	if (error) *error = true;
+	if (!src1.hasPrefix("xn--")) {
 		return src1;
+	}
 
-	String src(&src1.c_str()[4]); // Skip the prefix for simplification
-	uint srclen = src.size();
+	const char *src = src1.c_str() + 4; // Skip the prefix for simplification
+	uint srclen = src1.size() - 4;
 
 	// Ensure that the input contains only ASCII characters.
 	for (uint si = 0; si < srclen; si++) {
@@ -237,81 +239,76 @@ U32String punycode_decode(const String &src1) {
 		}
 	}
 
-	size_t di = src.findLastOf('-');
-
+	// Look for start insertions
+	const char *startinsert = strrchr(src, '-');
 	// If we have no '-', the entire string is non-ASCII character insertions.
-	if (di == String::npos)
-		di = 0;
-
-	Common::String tail;
-
-	// Sometimes strings could contain garbage at the end, like '.zip' added
-	// We try to detect these tails and keep it as is
-
-	// First, try to chop off any extensions
-	size_t dotPos = src.findLastOf('.');
-
-	while (dotPos != String::npos && dotPos > di) {
-		tail = String(src.c_str() + dotPos) + tail;
-		src = String(src.c_str(), dotPos);
-		srclen = src.size();
-
-		dotPos = src.findLastOf('.');
-
-		debug(9, "punycode_decode: src is: '%s', tail is: '%s'", src.c_str(), tail.c_str());
+	if (!startinsert) {
+		startinsert = src;
+	} else {
+		startinsert++;
 	}
 
-	// And now scan for the illegal characters as a whole
-	while (di != 0) {
-		bool noncode = false;
+	const char *tail = src + srclen;
 
-		// Scan string to the end for illegal characters
-		for (uint i = di + 1; i < srclen; i++) {
-			if (!((src[i] >= '0' && src[i] <= '9') || (src[i] >= 'a' && src[i] <= 'z'))) {
-				noncode = true;
+	while(true) {
+		// Check that the insertions string is valid
+		const char *p;
+		for(p = startinsert; p < tail; p++) {
+			if (!((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'z'))) {
+				// Invalid code
 				break;
 			}
 		}
+		if (p == tail) {
+			// Everything was good
+			break;
+		}
 
-		if (noncode && di < srclen) {
-			tail = String(src.c_str() + di) + tail;
-			src = String(src.c_str(), di);
-			srclen = src.size();
-
-			debug(9, "punycode_decode: src is: '%s', tail is: '%s'", src.c_str(), tail.c_str());
+		if (*p == '.') {
+			// Until then we got valid insertions, chop off what looks like an extension
+			// We are now good
+			tail = p;
+			srclen = tail - src;
+			break;
+		}
 
-			di = src.findLastOf('-');
+		// We got something invalid: assume it was garbage from start
+		// Look for another insertions start
+		if (startinsert == src) {
+			warning("punycode_decode: malformed string for string (%s)", src1.c_str());
+			return src1;
+		}
 
-			if (di == String::npos) {
-				warning("punycode_decode: malformed string for string (%s)", src1.c_str());
-				return src1;
+		// Move back to the dash
+		startinsert--;
+		tail = startinsert;
+		for(; startinsert > src; startinsert--) {
+			if (*(startinsert - 1) == '-') {
+				break;
 			}
-		} else {
-			break;
 		}
+		// Try another round
 	}
 
-	U32String dst;
-
-	for (size_t i = 0; i < di; i++) {
-		dst += src[i];
-	}
+	// Create dst with ASCII characters
+	U32String dst(src, startinsert == src ? src : startinsert - 1);
 
-	size_t b = di;
+	const char *b = startinsert;
+	size_t di = dst.size();
 	size_t i = 0;
 	size_t n = INITIAL_N;
 	size_t bias = INITIAL_BIAS;
 
-	for (int si = b + (b > 0 ? 1 : 0); si < (int)srclen; di++) {
+	for (const char *si = b; si < tail; di++) {
 		size_t org_i = i;
 
 		for (size_t w = 1, k = BASE; true; k += BASE) {
-			if (si >= (int)src.size()) {
+			if (si >= tail) {
 				warning("punycode_decode: incorrect digit for string (%s)", src1.c_str());
 				return src1;
 			}
 
-			size_t digit = decode_digit(src[si++]);
+			size_t digit = decode_digit(*si++);
 
 			if (digit == SMAX) {
 				warning("punycode_decode: incorrect digit2 for string (%s)", src1.c_str());
@@ -352,25 +349,22 @@ U32String punycode_decode(const String &src1) {
 
 		if (i / (di + 1) > SMAX - n) {
 			// OVERFLOW
-				warning("punycode_decode: overflow3 for string (%s)", src1.c_str());
+			warning("punycode_decode: overflow3 for string (%s)", src1.c_str());
 			return src1;
 		}
 
 		n += i / (di + 1);
 		i %= (di + 1);
 
-		U32String dst1(dst.c_str(), i);
-		dst1 += (u32char_type_t)n;
-		dst1 += U32String(&dst.c_str()[i]);
-		dst = dst1;
+		dst.insertChar(n, i);
 		i++;
 	}
 
 	// If we chopped off tail, readd it here
-	dst += tail;
+	dst += Common::U32String(tail);
 
 	debug(9, "punycode_decode: returning %s", Common::U32String(dst).encode().c_str());
-
+	if (error) *error = false;
 	return dst;
 }
 
@@ -393,25 +387,25 @@ String punycode_encodefilename(const U32String &src) {
 	return punycode_encode(dst);
 }
 
-U32String punycode_decodefilename(const String &src1) {
-	U32String dst;
-	U32String src = punycode_decode(src1);
+U32String punycode_decodefilename(const String &src) {
+	bool error;
+	U32String dst = punycode_decode(src, &error);
 
-	// Check if the string did not change which could be
-	// also on decoding failure
-	if (src == src1)
-		return src;
+	if (error)
+		return dst;
 
-	for (uint i = 0; i < src.size(); i++) {
-		if (src[i] == 0x81 && i + 1 < src.size()) {
-			i++;
-			if (src[i] == 0x79)
-				dst += 0x81;
-			else
-				dst += src[i] - 0x80;
+	uint32 i = dst.find(0x81, 0);
+	while (i < dst.size() - 1) {
+		U32String::value_type c = dst[i + 1];
+		if (c == 0x79) {
+			// 0x81 0x79 means 0x81: delete 0x79
+			dst.deleteChar(i + 1);
 		} else {
-			dst += src[i];
+			// 0x81 0xXX means 0xXX - 0x80: delete 0x81 and change 0xXX
+			dst.deleteChar(i);
+			dst.setChar(c - 0x80, i);
 		}
+		i = dst.find(0x81, i + 1);
 	}
 
 	return dst;
diff --git a/common/punycode.h b/common/punycode.h
index cad4f32408b..8d9c11157be 100644
--- a/common/punycode.h
+++ b/common/punycode.h
@@ -56,14 +56,14 @@ String punycode_encode(const U32String &src);
 /**
  * Convert Punycode to UTF-32. Returns the decoded string
  */
-U32String punycode_decode(const String &src);
+U32String punycode_decode(const String &src, bool *error = nullptr);
 
-String punycode_encodefilename(const U32String &src1);
+String punycode_encodefilename(const U32String &src);
 
 /**
  * Convert Punycode filename to Binary using special 0x81 escape character. Returns the decoded string
  */
-U32String punycode_decodefilename(const String &src1);
+U32String punycode_decodefilename(const String &src);
 
 bool punycode_hasprefix(const String &src);
 


Commit: 6f46727c771fb8599722c7097b84857851b0c92c
    https://github.com/scummvm/scummvm/commit/6f46727c771fb8599722c7097b84857851b0c92c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Check if string is puny encoded before trying to decode it

This avoids the following useless conversion String->U32String->String
while the content will not change.

Changed paths:
    common/path.cpp
    common/punycode.cpp
    common/punycode.h


diff --git a/common/path.cpp b/common/path.cpp
index da492a7b251..d8480662dd9 100644
--- a/common/path.cpp
+++ b/common/path.cpp
@@ -845,7 +845,9 @@ Path Path::punycodeDecode() const {
 	return reduceComponents<Path &>(
 		+[](Path &path, const String &in, bool last) -> Path & {
 			// We encode the result as UTF-8
-			String out = punycode_decodefilename(in).encode();
+			String out = punycode_hasprefix(in) ?
+				     punycode_decodefilename(in).encode() :
+				     in;
 			path.appendInPlace(out, kNoSeparator);
 			if (!last) {
 				path._str += SEPARATOR;
@@ -878,7 +880,9 @@ Path Path::punycodeEncode() const {
 // HFS(+) image will end up with : independently of how
 // it was dumped or copied from
 static String getIdentifierComponent(const String &in) {
-	String part = punycode_decodefilename(in).encode();
+	String part = punycode_hasprefix(in) ?
+	              punycode_decodefilename(in).encode() :
+	              in;
 	part.replace('/', ':');
 	return part;
 }
diff --git a/common/punycode.cpp b/common/punycode.cpp
index e3ea1c538be..8ff95eb36eb 100644
--- a/common/punycode.cpp
+++ b/common/punycode.cpp
@@ -202,10 +202,6 @@ String punycode_encode(const U32String &src) {
 	return dst;
 }
 
-bool punycode_hasprefix(const String &src) {
-	return src.hasPrefix("xn--");
-}
-
 bool punycode_needEncode(const String &src) {
 	if (!src.size())
 		return false;
diff --git a/common/punycode.h b/common/punycode.h
index 8d9c11157be..6c3c27643d9 100644
--- a/common/punycode.h
+++ b/common/punycode.h
@@ -65,7 +65,9 @@ String punycode_encodefilename(const U32String &src);
  */
 U32String punycode_decodefilename(const String &src);
 
-bool punycode_hasprefix(const String &src);
+inline bool punycode_hasprefix(const String &src) {
+	return src.hasPrefix("xn--");
+}
 
 bool punycode_needEncode(const String &src);
 


Commit: eeba7ca153aab01172ecec815699ff8e1ebc0d5e
    https://github.com/scummvm/scummvm/commit/eeba7ca153aab01172ecec815699ff8e1ebc0d5e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Add more path functions

Changed paths:
    common/path.cpp
    common/path.h
    test/common/path.h


diff --git a/common/path.cpp b/common/path.cpp
index d8480662dd9..541980b74f8 100644
--- a/common/path.cpp
+++ b/common/path.cpp
@@ -379,6 +379,29 @@ Path Path::getLastComponent() const {
 	return extract(begin, end);
 }
 
+String Path::baseName() const {
+	if (_str.empty()) {
+		return String();
+	}
+
+	size_t last = _str.size();
+	if (isSeparatorTerminated()) {
+		last--;
+	}
+
+	const char *begin = _str.c_str();
+	const char *end = _str.c_str();
+
+	size_t separatorPos = findLastSeparator(last);
+
+	if (separatorPos != String::npos) {
+		begin += separatorPos + 1;
+	}
+	end += last;
+
+	return unescape(kNoSeparator, begin, end);
+}
+
 Path &Path::appendInPlace(const Path &x) {
 	if (x._str.empty()) {
 		return *this;
@@ -556,6 +579,107 @@ Path &Path::joinInPlace(const char *str, char separator) {
 	return appendInPlace(str, separator);
 }
 
+Path &Path::removeTrailingSeparators() {
+	while (_str.size() > 1 && _str.lastChar() == SEPARATOR) {
+		_str.deleteLastChar();
+	}
+	return *this;
+}
+
+const char *Path::getSuffix(const Common::Path &other) const {
+	if (other.empty()) {
+		// Other is empty, return full string
+		const char *suffix = _str.c_str();
+		if (isEscaped()) {
+			suffix++;
+		}
+		return suffix;
+	}
+
+	if (isEscaped() == other.isEscaped()) {
+		// Easy one both have same escapism
+		if (_str.hasPrefix(other._str)) {
+			const char *suffix = _str.c_str() + other._str.size();
+			if (!other.isSeparatorTerminated()) {
+				// Make sure we didn't end up in the middle of some path component
+				if (*suffix != SEPARATOR && *suffix != '\x00') {
+					return nullptr;
+				}
+				suffix++;
+			}
+			return suffix;
+		} else {
+			return nullptr;
+		}
+	}
+
+	// One is escaped and not the other
+	if (other.isEscaped()) {
+		// If the other is escaped it can't be a substring of this one
+		// as it must contain something which needed escape and we obviously didn't need it
+		return nullptr;
+	}
+
+	// We may be escaped because something needs escape after the end of the prefix
+	// We need to iterate over both paths and checking escape in ours
+	const char *str = _str.c_str() + 1;
+	const char *strOther = other._str.c_str();
+	while (*strOther) {
+		char c = *str;
+		if (c == ESCAPE) {
+			str++;
+			switch (*str) {
+			case ESCAPED_ESCAPE:
+				c = ESCAPE;
+				break;
+			case ESCAPED_SEPARATOR:
+				/* We are not supposed to have an escaped separator as
+				 * the other one would need one too.
+				 * We would then have the same escapism.
+				 */
+				c = SEPARATOR;
+				break;
+			default:
+				error("Invalid escape character '%c' in path \"%s\"", *str, _str.c_str());
+			}
+		}
+		if (*strOther != c) {
+			break;
+		}
+		++strOther;
+		++str;
+	}
+	// It's a prefix, if and only if all letters in other are 'used up' before
+	// we end.
+	if (*strOther != '\0') {
+		return nullptr;
+	}
+
+	if (!other.isSeparatorTerminated()) {
+		// Make sure we didn't end up in the middle of some path component
+		if (*str != SEPARATOR) {
+			return nullptr;
+		}
+		str++;
+	}
+
+	return str;
+}
+
+Path Path::relativeTo(const Common::Path &other) const {
+	const char *suffix = getSuffix(other);
+	if (!suffix) {
+		return *this;
+	}
+
+	// Remove all spurious separators
+	while (*suffix == SEPARATOR) {
+		suffix++;
+	}
+
+	return extract(suffix);
+}
+
 Path Path::normalize() const {
 	if (_str.empty()) {
 		return Path();
@@ -896,6 +1020,19 @@ struct hasher {
 	uint mult;
 };
 
+uint Path::hash() const {
+	hasher v = { 0x345678, 1000003 };
+	reduceComponents<hasher &>(
+		+[](hasher &value, const String &in, bool last) -> hasher & {
+			uint hash = hashit(in.c_str());
+
+			value.result = (value.result + hash) * value.mult;
+			value.mult = (value.mult * 69069);
+			return value;
+		}, v);
+	return v.result;
+}
+
 uint Path::hashIgnoreCase() const {
 	hasher v = { 0x345678, 1000003 };
 	reduceComponents<hasher &>(
@@ -943,4 +1080,32 @@ bool Path::equalsIgnoreCaseAndMac(const Path &other) const {
 		}, other);
 }
 
+bool Path::operator<(const Path &x) const {
+	// Here order matters: if we other is empty it is less or equal than us
+	// We can only be greater or equal
+	if (x.empty()) {
+		return false;
+	}
+	// Other is not empty, we are: we are less
+	if (empty()) {
+		return true;
+	}
+
+	// Same escapism, easy to compare
+	if (isEscaped() == x.isEscaped()) {
+		return _str < x._str;
+	}
+
+	// Different escapism: fall back on escaped
+	const Common::String &ref = isEscaped() ? _str : x._str;
+	Common::String val(ESCAPE);
+	if (isEscaped()) {
+		escape(val, SEPARATOR, x._str.c_str());
+		return ref < val;
+	} else {
+		escape(val, SEPARATOR, _str.c_str());
+		return val < ref;
+	}
+}
+
 } // End of namespace Common
diff --git a/common/path.h b/common/path.h
index 469412880e6..afbceb4f9f3 100644
--- a/common/path.h
+++ b/common/path.h
@@ -175,6 +175,12 @@ private:
 		return *_str.c_str() == ESCAPE;
 	}
 
+	/**
+	 * Returns the suffix in this path after @p other path
+	 * Returns nullptr if @p other isn't a prefix
+	 */
+	const char *getSuffix(const Common::Path &other) const;
+
 public:
 	/**
 	 * A separator to use when building path conataining only base names
@@ -212,6 +218,14 @@ public:
 		uint operator()(const Path &x) const { return x.hashIgnoreCase(); }
 	};
 
+	struct EqualTo {
+		bool operator()(const Path &x, const Path &y) const { return x.equals(y); }
+	};
+
+	struct Hash {
+		uint operator()(const Path &x) const { return x.hash(); }
+	};
+
 	/** Construct a new empty path. */
 	Path() {}
 
@@ -251,6 +265,11 @@ public:
 	 */
 	String toString(char separator = '/') const;
 
+	/**
+	 * Clears the path object
+	 */
+	void clear() { _str.clear(); }
+
 	/**
 	 * Returns the Path for the parent directory of this path.
 	 *
@@ -267,6 +286,13 @@ public:
 	 */
 	Path getLastComponent() const;
 
+	/**
+	 * Returns the last non-empty component of this path.
+	 * Compared to getLastComponent(), baseName() doesn't
+	 * return the trailing / if any.
+	 */
+	String baseName() const;
+
 	/** Check whether this path is identical to path @p x. */
 	bool operator==(const Path &x) const {
 		return _str == x._str;
@@ -277,6 +303,12 @@ public:
 		return _str != x._str;
 	}
 
+	/**
+	 * Check whether this path is identical to path @p x.
+	 */
+	bool equals(const Path &x) const {
+		return _str.equals(x._str);
+	}
 	/**
 	 * Check whether this path is identical to path @p x.
 	 * Ignores case
@@ -288,6 +320,10 @@ public:
 	 */
 	bool equalsIgnoreCaseAndMac(const Path &x) const;
 
+	/**
+	 * Calculate a case sensitive hash of path
+	 */
+	uint hash() const;
 	/**
 	 * Calculate a case insensitive hash of path
 	 */
@@ -298,6 +334,8 @@ public:
 	 */
 	uint hashIgnoreCaseAndMac() const;
 
+	bool operator<(const Path &x) const;
+
 	/** Return if this path is empty */
 	bool empty() const {
 		return _str.empty();
@@ -413,6 +451,27 @@ public:
 		return temp;
 	}
 
+	/**
+	 * Removes the trainling separators if any in this path (in-place).
+	 */
+	Path &removeTrailingSeparators();
+
+	/**
+	 * Returns whether this path ends with a separator
+	 */
+	bool isSeparatorTerminated() const { return _str.lastChar() == SEPARATOR; }
+
+	/**
+	 * Returns whether this path begins with @p other path
+	 */
+	bool isRelativeTo(const Common::Path &other) const { return getSuffix(other) != nullptr; }
+
+	/**
+	 * Returns a new path relative to the @p other one.
+	 * Returns a copy this if it wasn't relative to.
+	 */
+	Path relativeTo(const Common::Path &other) const;
+
 	/**
 	 * Convert path from Punycode
 	 */
@@ -423,6 +482,28 @@ public:
 	 */
 	Path punycodeEncode() const;
 
+	/**
+	 * Convert all characters in the path to lowercase.
+	 *
+	 * Be aware that this only affects the case of ASCII characters. All
+	 * other characters will not be touched at all.
+	 */
+	void toLowercase() {
+		// Escapism is not changed by changing case
+		_str.toLowercase();
+	}
+
+	/**
+	 * Convert all characters in the path to uppercase.
+	 *
+	 * Be aware that this only affects the case of ASCII characters. All
+	 * other characters will not be touched at all.
+	 */
+	void toUppercase() {
+		// Escapism is not changed by changing case
+		_str.toUppercase();
+	}
+
 	/**
 	* Check pattern match similar matchString
 	 */
diff --git a/test/common/path.h b/test/common/path.h
index 7d1bb58194e..950d2300a7f 100644
--- a/test/common/path.h
+++ b/test/common/path.h
@@ -77,6 +77,20 @@ class PathTestSuite : public CxxTest::TestSuite
 		TS_ASSERT_EQUALS(p3.getLastComponent(), Common::Path("|file.txt"));
 	}
 
+	void test_baseName() {
+		Common::Path p;
+		TS_ASSERT_EQUALS(p.baseName(), "");
+
+		Common::Path p2(TEST_PATH);
+		TS_ASSERT_EQUALS(p2.baseName(), "file.txt");
+
+		Common::Path p3("parent\\dir\\fi/le.txt", '\\');
+		TS_ASSERT_EQUALS(p3.baseName(), "fi/le.txt");
+
+		Common::Path p4("parent/dir/file.txt/");
+		TS_ASSERT_EQUALS(p4.baseName(), "file.txt");
+	}
+
 	void test_getParent() {
 		Common::Path p;
 		TS_ASSERT_EQUALS(p.getParent().toString(), "");
@@ -263,6 +277,77 @@ class PathTestSuite : public CxxTest::TestSuite
 		TS_ASSERT_EQUALS(p.toString('\\'), TEST_ESCAPED2_PATH);
 	}
 
+	void test_removeTrailingSeparators() {
+		Common::Path p;
+		p.removeTrailingSeparators();
+		TS_ASSERT_EQUALS(p.toString(), "");
+
+		Common::Path p2(TEST_PATH);
+		p2.removeTrailingSeparators();
+		TS_ASSERT_EQUALS(p2.toString(), TEST_PATH);
+
+		Common::Path p3("parent/dir/file.txt///");
+		p3.removeTrailingSeparators();
+		TS_ASSERT_EQUALS(p3.toString(), "parent/dir/file.txt");
+
+		Common::Path p4("//");
+		p4.removeTrailingSeparators();
+		TS_ASSERT_EQUALS(p4.toString(), "/");
+	}
+
+	void test_isRelativeTo() {
+		Common::Path p, p1(TEST_PATH), p2(TEST_ESCAPED1_PATH);
+
+		// Everything is relative to empty
+		TS_ASSERT_EQUALS(p1.isRelativeTo(p), true);
+		TS_ASSERT_EQUALS(p2.isRelativeTo(p), true);
+		// A path is not relative to empty one
+		TS_ASSERT_EQUALS(p.isRelativeTo(p1), false);
+
+		TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("parent/dir")), true);
+		TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("parent/dir/")), true);
+		TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("parent/dir/fi")), false);
+
+		TS_ASSERT_EQUALS(p1.isRelativeTo(Common::Path("|parent/dir")), false);
+
+		Common::Path p3("parent\\dir\\fi/le.txt", '\\');
+		TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir")), true);
+		TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir/")), true);
+		TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir/fi")), false);
+		TS_ASSERT_EQUALS(p3.isRelativeTo(Common::Path("parent/dir/fa")), false);
+
+		Common::Path p4("par|ent\\dir\\fi/le.txt", '\\');
+		TS_ASSERT_EQUALS(p4.isRelativeTo(Common::Path("par|ent/dir")), true);
+	}
+
+	void test_relativeTo() {
+		Common::Path p, p1(TEST_PATH), p2(TEST_ESCAPED1_PATH);
+
+		// Everything is relative to empty
+		TS_ASSERT_EQUALS(p1.relativeTo(p).toString(), TEST_PATH);
+		TS_ASSERT_EQUALS(p2.relativeTo(p).toString(), TEST_ESCAPED1_PATH);
+		// A path is not relative to empty one
+		TS_ASSERT_EQUALS(p.relativeTo(p1), p);
+
+		TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("parent/dir")).toString(), "file.txt");
+		TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("parent/dir/")).toString(), "file.txt");
+		TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("parent/dir/fi")), p1);
+
+		TS_ASSERT_EQUALS(p1.relativeTo(Common::Path("|parent/dir")), p1);
+
+		Common::Path p3("parent\\dir\\fi/le.txt", '\\');
+		TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir")).toString('\\'), "fi/le.txt");
+		TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir/")).toString('\\'), "fi/le.txt");
+		TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir/fi")), p3);
+		TS_ASSERT_EQUALS(p3.relativeTo(Common::Path("parent/dir/fa")), p3);
+
+		Common::Path p4("par|ent\\dir\\fi/le.txt", '\\');
+		TS_ASSERT_EQUALS(p4.relativeTo(Common::Path("par|ent/dir")).toString('\\'), "fi/le.txt");
+
+		Common::Path p5("par|ent\\dir\\\\\\fi/le.txt", '\\');
+		TS_ASSERT_EQUALS(p5.relativeTo(Common::Path("par|ent/dir")).toString('\\'), "fi/le.txt");
+	}
+
 	void test_normalize() {
 		TS_ASSERT_EQUALS(Common::Path("/", '/').normalize().toString(), "/");
 		TS_ASSERT_EQUALS(Common::Path("///", '/').normalize().toString(), "/");
@@ -324,6 +409,26 @@ class PathTestSuite : public CxxTest::TestSuite
 		TS_ASSERT_EQUALS(map.size(), 2u);
 	}
 
+	void test_lowerupper() {
+		Common::Path p2(TEST_PATH);
+		p2.toUppercase();
+		TS_ASSERT_EQUALS(p2.toString('/'), "PARENT/DIR/FILE.TXT");
+
+		p2 = TEST_PATH;
+		p2.toLowercase();
+		TS_ASSERT_EQUALS(p2.toString('/'), TEST_PATH);
+
+		Common::Path p3(TEST_ESCAPED1_PATH);
+		p3.toUppercase();
+		TS_ASSERT_EQUALS(p3.toString('/'), "|PARENT/DIR/FILE.TXT");
+
+		Common::String s3(TEST_ESCAPED1_PATH);
+		s3.toUppercase();
+		p3 = s3;
+		p3.toLowercase();
+		TS_ASSERT_EQUALS(p3.toString('/'), TEST_ESCAPED1_PATH);
+	}
+
 	void test_caseinsensitive() {
 		Common::Path p;
 		Common::Path p2("parent:dir:Sound Manager 3.1 / SoundLib:Sound", ':');


Commit: 6f4a86db7e691135505268ddb0626b8f6f9593e0
    https://github.com/scummvm/scummvm/commit/6f4a86db7e691135505268ddb0626b8f6f9593e0
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Add a native directory separator

This will be used when converting the Path back to string to be used by
native filesystem APIs

Changed paths:
    common/path.h


diff --git a/common/path.h b/common/path.h
index afbceb4f9f3..151086a0a6c 100644
--- a/common/path.h
+++ b/common/path.h
@@ -188,6 +188,16 @@ public:
 	 */
 	static const char kNoSeparator = '\x00';
 
+	/**
+	 * The platform native separator.
+	 * This is used when accessing files on disk
+	 */
+#if defined(WIN32)
+	static const char kNativeSeparator = '\\';
+#else
+	static const char kNativeSeparator = '/';
+#endif
+
 	/**
 	 * Hash and comparator for Path with following changes:
 	 * * case-insensitive


Commit: 1722511c3295f021c7dbac8da97bdf0b3063a452
    https://github.com/scummvm/scummvm/commit/1722511c3295f021c7dbac8da97bdf0b3063a452
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Allow to store and fetch paths in configuration

Changed paths:
    common/config-manager.cpp
    common/config-manager.h
    common/path.cpp
    common/path.h


diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 55d4d159003..236f1f17b7b 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -567,6 +567,10 @@ bool ConfigManager::getBool(const String &key, const String &domName) const {
 	      key.c_str(), domName.c_str(), value.c_str());
 }
 
+Path ConfigManager::getPath(const String &key, const String &domName) const {
+	return Path::fromConfig(get(key, domName));
+}
+
 
 #pragma mark -
 
@@ -653,6 +657,10 @@ void ConfigManager::setBool(const String &key, bool value, const String &domName
 	set(key, String(value ? "true" : "false"), domName);
 }
 
+void ConfigManager::setPath(const String &key, const Path &value, const String &domName) {
+	set(key, value.toConfig(), domName);
+}
+
 
 #pragma mark -
 
@@ -673,6 +681,10 @@ void ConfigManager::registerDefault(const String &key, bool value) {
 	registerDefault(key, value ? "true" : "false");
 }
 
+void ConfigManager::registerDefault(const String &key, const Path &value) {
+	registerDefault(key, value.toConfig());
+}
+
 
 #pragma mark -
 
diff --git a/common/config-manager.h b/common/config-manager.h
index 25e73703bae..6b85fab29e3 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -24,6 +24,7 @@
 
 #include "common/array.h"
 #include "common/hashmap.h"
+#include "common/path.h"
 #include "common/singleton.h"
 #include "common/str.h"
 #include "common/hash-str.h"
@@ -186,13 +187,16 @@ public:
 
 	int                      getInt(const String &key, const String &domName = String()) const; /*!< Get integer value. */
 	bool                     getBool(const String &key, const String &domName = String()) const; /*!< Get Boolean value. */
+	Path                     getPath(const String &key, const String &domName = String()) const; /*!< Get path value. */
 	void                     setInt(const String &key, int value, const String &domName = String()); /*!< Set integer value. */
 	void                     setBool(const String &key, bool value, const String &domName = String()); /*!< Set Boolean value. */
+	void                     setPath(const String &key, const Path &value, const String &domName = String()); /*!< Set path value. */
 
 	void                     registerDefault(const String &key, const String &value); /*!< Register a value as the default. */
 	void                     registerDefault(const String &key, const char *value); /*!< @overload */
 	void                     registerDefault(const String &key, int value); /*!< @overload */
 	void                     registerDefault(const String &key, bool value); /*!< @overload */
+	void                     registerDefault(const String &key, const Path &value); /*!< @overload */
 
 	void                     flushToDisk(); /*!< Flush configuration to disk. */
 
diff --git a/common/path.cpp b/common/path.cpp
index 541980b74f8..9bc5129b92f 100644
--- a/common/path.cpp
+++ b/common/path.cpp
@@ -1108,4 +1108,26 @@ bool Path::operator<(const Path &x) const {
 	}
 }
 
+Path Path::fromConfig(const String &value) {
+	if (value.empty()) {
+		return Path();
+	}
+
+	// Paths saved under WIN32 used \ separator
+	// We now punyencode and store using /
+#if defined(WIN32)
+	if (strchr(value.c_str(), Path::kNativeSeparator)) {
+		String value_ = value;
+		// We may have mixed \ and / in our paths before
+		// As / is forbidden in paths under WIN32, this will never be a collision
+		value_.replace(Path::kNativeSeparator, '/');
+		// As we have \, we are sure we didn't punyencode this path
+		return Path(value, '/');
+	}
+#endif
+
+	// If the path is not punyencoded this will be a no-op
+	return Path(value, '/').punycodeDecode();
+}
+
 } // End of namespace Common
diff --git a/common/path.h b/common/path.h
index 151086a0a6c..b5b095731ac 100644
--- a/common/path.h
+++ b/common/path.h
@@ -546,6 +546,19 @@ public:
 	static Path joinComponents(const StringArray &c) {
 		return joinComponents(c.begin(), c.end());
 	}
+
+	/**
+	 * Use by ConfigManager to store a path in a protected fashion
+	 * All components are punyencoded and / is used as a delimiter for all platforms
+	 */
+	String toConfig() const {
+		return punycodeEncode().toString('/');
+	}
+
+	/**
+	 * Used by ConfigManager to parse a configuration value in a bacwards compatible way
+	 */
+	static Path fromConfig(const String &value);
 };
 
 /** @} */


Commit: 8b2e5ef649e04c2aca4cb0694588fa6d7c3f56be
    https://github.com/scummvm/scummvm/commit/8b2e5ef649e04c2aca4cb0694588fa6d7c3f56be
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make getPath() return a Path

Also add a compatibility shim which acts like a String.
In addition, simplify path related code to avoid stringification when
it's not needed.
Use the native path separator to display paths inside filesystem.

Changed paths:
    common/fs.cpp
    common/fs.h


diff --git a/common/fs.cpp b/common/fs.cpp
index 76aad9ef8f4..843db5c6110 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -118,7 +118,7 @@ FSNode::FSNode(const Path &p) {
 	if (p.empty() || p == Path("."))
 		tmp = factory->makeCurrentDirectoryFileNode();
 	else
-		tmp = factory->makeFileNodePath(p.toString());
+		tmp = factory->makeFileNodePath(p.toString(Common::Path::kNativeSeparator));
 	_realNode = SharedPtr<AbstractFSNode>(tmp);
 }
 
@@ -183,7 +183,7 @@ String FSNode::getFileName() const {
 }
 
 Common::Path FSNode::getPathInArchive() const {
-	return getName();
+	return Common::Path(getName(), Common::Path::kNoSeparator);
 }
 
 String FSNode::getRealName() const {
@@ -203,9 +203,9 @@ FSNode FSNode::getParent() const {
 	}
 }
 
-String FSNode::getPath() const {
+PathProxy FSNode::getPath() const {
 	assert(_realNode);
-	return _realNode->getPath();
+	return PathProxy(_realNode->getPath(), Common::Path::kNativeSeparator);
 }
 
 bool FSNode::isDirectory() const {
@@ -341,7 +341,7 @@ FSNode *FSDirectory::lookupCache(NodeCache &cache, const Path &name) const {
 }
 
 bool FSDirectory::hasFile(const Path &path) const {
-	if (path.toString().empty() || !_node.isDirectory())
+	if (path.empty() || !_node.isDirectory())
 		return false;
 
 	FSNode *node = lookupCache(_fileCache, path);
@@ -349,7 +349,7 @@ bool FSDirectory::hasFile(const Path &path) const {
 }
 
 bool FSDirectory::isPathDirectory(const Path &path) const {
-	if (path.toString().empty() || !_node.isDirectory())
+	if (path.empty() || !_node.isDirectory())
 		return false;
 
 	FSNode *node = lookupCache(_fileCache, path);
@@ -357,16 +357,16 @@ bool FSDirectory::isPathDirectory(const Path &path) const {
 }
 
 const ArchiveMemberPtr FSDirectory::getMember(const Path &path) const {
-	if (path.toString().empty() || !_node.isDirectory())
+	if (path.empty() || !_node.isDirectory())
 		return ArchiveMemberPtr();
 
 	FSNode *node = lookupCache(_fileCache, path);
 
 	if (!node || !node->exists()) {
-		warning("FSDirectory::getMember: '%s' does not exist", Common::toPrintable(path.toString()).c_str());
+		warning("FSDirectory::getMember: '%s' does not exist", Common::toPrintable(path.toString(Common::Path::kNativeSeparator)).c_str());
 		return ArchiveMemberPtr();
 	} else if (node->isDirectory()) {
-		warning("FSDirectory::getMember: '%s' is a directory", Common::toPrintable(path.toString()).c_str());
+		warning("FSDirectory::getMember: '%s' is a directory", Common::toPrintable(path.toString(Common::Path::kNativeSeparator)).c_str());
 		return ArchiveMemberPtr();
 	}
 
@@ -374,35 +374,35 @@ const ArchiveMemberPtr FSDirectory::getMember(const Path &path) const {
 }
 
 SeekableReadStream *FSDirectory::createReadStreamForMember(const Path &path) const {
-	if (path.toString().empty() || !_node.isDirectory())
+	if (path.empty() || !_node.isDirectory())
 		return nullptr;
 
 	FSNode *node = lookupCache(_fileCache, path);
 	if (!node)
 		return nullptr;
 
-	debug(5, "FSDirectory::createReadStreamForMember('%s') -> '%s'", path.toString().c_str(), node->getPath().c_str());
+	debug(5, "FSDirectory::createReadStreamForMember('%s') -> '%s'", path.toString(Common::Path::kNativeSeparator).c_str(), node->getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	SeekableReadStream *stream = node->createReadStream();
 	if (!stream)
-		warning("FSDirectory::createReadStreamForMember: Can't create stream for file '%s'", Common::toPrintable(path.toString()).c_str());
+		warning("FSDirectory::createReadStreamForMember: Can't create stream for file '%s'", Common::toPrintable(path.toString(Common::Path::kNativeSeparator)).c_str());
 
 	return stream;
 }
 
 SeekableReadStream *FSDirectory::createReadStreamForMemberAltStream(const Path &path, AltStreamType altStreamType) const {
-	if (path.toString().empty() || !_node.isDirectory())
+	if (path.empty() || !_node.isDirectory())
 		return nullptr;
 
 	FSNode *node = lookupCache(_fileCache, path);
 	if (!node)
 		return nullptr;
 
-	debug(5, "FSDirectory::createReadStreamForMemberAltStream('%s', %i) -> '%s'", path.toString().c_str(), static_cast<int>(altStreamType), node->getPath().c_str());
+	debug(5, "FSDirectory::createReadStreamForMemberAltStream('%s', %i) -> '%s'", path.toString(Common::Path::kNativeSeparator).c_str(), static_cast<int>(altStreamType), node->getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	SeekableReadStream *stream = node->createReadStreamForAltStream(altStreamType);
 	if (!stream)
-		warning("FSDirectory::createReadStreamForMemberAltStream: Can't create stream for file '%s' alt stream type %i", Common::toPrintable(path.toString()).c_str(), static_cast<int>(altStreamType));
+		warning("FSDirectory::createReadStreamForMemberAltStream: Can't create stream for file '%s' alt stream type %i", Common::toPrintable(path.toString(Common::Path::kNativeSeparator)).c_str(), static_cast<int>(altStreamType));
 
 	return stream;
 }
@@ -413,7 +413,7 @@ FSDirectory *FSDirectory::getSubDirectory(const Path &name, int depth, bool flat
 
 FSDirectory *FSDirectory::getSubDirectory(const Path &prefix, const Path &name, int depth,
 		bool flat, bool ignoreClashes) {
-	if (name.toString().empty() || !_node.isDirectory())
+	if (name.empty() || !_node.isDirectory())
 		return nullptr;
 
 	FSNode *node = lookupCache(_subDirCache, name);
@@ -440,12 +440,12 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const Path& pr
 				// Always warn in this case as it's when there are 2 directories at the same place with different case
 				// That means a problem in user installation as lookups are always done case insensitive
 				warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'",
-				        Common::toPrintable(name.toString('/')).c_str());
+				        Common::toPrintable(name.toString(Common::Path::kNativeSeparator)).c_str());
 			} else {
 				if (_subDirCache.contains(name)) {
 					if (!_ignoreClashes) {
 						warning("FSDirectory::cacheDirectory: name clash when building subDirCache with subdirectory '%s'",
-						        Common::toPrintable(name.toString('/')).c_str());
+						        Common::toPrintable(name.toString(Common::Path::kNativeSeparator)).c_str());
 					}
 				}
 				cacheDirectoryRecursive(*it, depth - 1, _flat ? prefix : name);
@@ -455,7 +455,7 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const Path& pr
 			if (_fileCache.contains(name)) {
 				if (!_ignoreClashes) {
 					warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'",
-					        Common::toPrintable(name.toString('/')).c_str());
+					        Common::toPrintable(name.toString(Common::Path::kNativeSeparator)).c_str());
 				}
 			} else
 				_fileCache[name] = *it;
diff --git a/common/fs.h b/common/fs.h
index 058670bd3a2..ec282731e09 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -49,6 +49,31 @@ class SeekableReadStream;
 class WriteStream;
 class SeekableWriteStream;
 
+/**
+ * A minimal and temporary class which can act like a Path and like a String
+ * This is used to ease transition of getPath() from String to Path
+ * FIXME: Remove this class when it's not needed anymore
+ */
+class PathProxy : public Path {
+private:
+	String str() const { return toString(Path::kNativeSeparator); }
+public:
+	using Path::Path;
+
+	operator String() const { return str(); };
+	operator U32String() const { return decode(); }
+
+	const char *c_str() const { return str().c_str(); }
+	U32String decode(CodePage page = kUtf8) const { return str().decode(page); }
+	bool matchString(const char *pat, bool ignoreCase = false, const char *wildcardExclusions = NULL) const {
+		return str().matchString(pat, ignoreCase, wildcardExclusions);
+	}
+
+	String substr(size_t pos = 0, size_t len = String::npos) const {
+		return str().substr(pos, len);
+	}
+};
+
 /**
  * List of multiple file system nodes. For example, the contents of a given directory.
  * This is a subclass instead of just a typedef so that forward declarations
@@ -181,7 +206,7 @@ public:
 	 *
 	 * @return The file name.
 	 */
-	Common::Path getPathInArchive() const override;
+	Path getPathInArchive() const override;
 
 	/**
 	 * Return a string representation of the name of the file, without any
@@ -194,18 +219,14 @@ public:
 	virtual String getRealName() const;
 
 	/**
-	 * Return a string representation of the file that is suitable for
-	 * archiving (i.e. writing to the config file). This will usually be a
-	 * 'path' (hence the name of the method), but can be anything that meets
-	 * the above criteria. What a 'path' is differs greatly from system to
+	 * Return a path representation of the file that is suitable for
+	 * archiving (i.e. writing to the config file).
+	 * What a 'path' is differs greatly from system to
 	 * system.
 	 *
-	 * @note Do not assume that this string contains (back)slashes or any
-	 *       other kind of 'path separators'.
-	 *
 	 * @return The 'path' represented by this file system node.
 	 */
-	String getPath() const;
+	PathProxy getPath() const;
 
 	/**
 	 * Get the parent node of this node. If this node has no parent node,


Commit: 28b63470f0e609384b6a3947eb9e258933a5bacf
    https://github.com/scummvm/scummvm/commit/28b63470f0e609384b6a3947eb9e258933a5bacf
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Migrate DumpFile to Path

Also display warnings using proper directory separator when opening
FSNode.

Changed paths:
    common/file.cpp
    common/file.h


diff --git a/common/file.cpp b/common/file.cpp
index ca8ab78c662..0d58ce969b3 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -65,12 +65,12 @@ bool File::open(const FSNode &node) {
 		warning("File::open: node does not exist");
 		return false;
 	} else if (node.isDirectory()) {
-		warning("File::open: '%s' is a directory", node.getPath().c_str());
+		warning("File::open: '%s' is a directory", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	SeekableReadStream *stream = node.createReadStream();
-	return open(stream, node.getPath());
+	return open(stream, node.getPath().toString(Common::Path::kNativeSeparator));
 }
 
 bool File::open(SeekableReadStream *stream, const String &name) {
@@ -150,24 +150,39 @@ DumpFile::~DumpFile() {
 	close();
 }
 
-bool DumpFile::open(const String &filename, bool createPath) {
+bool DumpFile::open(const Path &filename, bool createPath) {
 	assert(!filename.empty());
 	assert(!_handle);
 
 	if (createPath) {
-		for (uint32 i = 0; i < filename.size(); ++i) {
-			if (filename[i] == '/' || filename[i] == '\\') {
-				Common::String subpath = filename;
-				subpath.erase(i);
-				if (subpath.empty() || subpath == ".") continue;
-				AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(subpath);
+		Common::Path dirname(filename.getParent());
+
+		// If the parent directory already exists keep it simple
+		AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(dirname.toString(Common::Path::kNativeSeparator));
+		if (!node->exists()) {
+			delete node;
+
+			dirname = dirname.normalize();
+			StringArray components = dirname.splitComponents();
+
+			Common::Path subpath;
+			for (StringArray::iterator it = components.end() - 1; it != components.begin(); --it) {
+				subpath.joinInPlace(*it, Common::Path::kNoSeparator);
+				if (subpath.empty()) {
+					continue;
+				}
+				node = g_system->getFilesystemFactory()->makeFileNodePath(subpath.toString(Common::Path::kNativeSeparator));
 				if (node->exists()) {
 					delete node;
 					continue;
 				}
-				if (!node->createDirectory()) warning("DumpFile: unable to create directories from path prefix (%s)", subpath.c_str());
+				if (!node->createDirectory()) {
+					warning("DumpFile: unable to create directories from path prefix (%s)", subpath.toString(Common::Path::kNativeSeparator).c_str());
+				}
 				delete node;
 			}
+		} else {
+			delete node;
 		}
 	}
 
diff --git a/common/file.h b/common/file.h
index a90913d41e9..9f5d3fac83f 100644
--- a/common/file.h
+++ b/common/file.h
@@ -151,7 +151,7 @@ public:
 	DumpFile();
 	virtual ~DumpFile();
 
-	virtual bool open(const String &filename, bool createPath = false);
+	virtual bool open(const Path &filename, bool createPath = false);
 	virtual bool open(const FSNode &node);
 
 	virtual void close();


Commit: 56552fa282d89f46026cd6ffdce7a2f7de2e2fc9
    https://github.com/scummvm/scummvm/commit/56552fa282d89f46026cd6ffdce7a2f7de2e2fc9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Various path related fixes in archives

Changed paths:
    common/archive.cpp
    common/archive.h


diff --git a/common/archive.cpp b/common/archive.cpp
index 153d6fc4d3f..2df42fdd312 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -122,7 +122,7 @@ SeekableReadStream *Archive::createReadStreamForMemberAltStream(const Path &path
 	return nullptr;
 }
 
-Common::Error Archive::dumpArchive(String destPath) {
+Common::Error Archive::dumpArchive(const Path &destPath) {
 	Common::ArchiveMemberList files;
 
 	listMembers(files);
@@ -135,7 +135,7 @@ Common::Error Archive::dumpArchive(String destPath) {
 		debug(1, "File: %s", filePath.toString().c_str());
 
 		// skip if f represents a directory
-		if (filePath.toString().lastChar() == '/') continue;
+		if (filePath.isSeparatorTerminated()) continue;
 
 		Common::SeekableReadStream *stream = f->createReadStream();
 
@@ -149,9 +149,9 @@ Common::Error Archive::dumpArchive(String destPath) {
 		stream->read(data, len);
 
 		Common::DumpFile out;
-		Common::Path outPath = Common::Path(destPath).join(filePath);
-		if (!out.open(outPath.toString(), true)) {
-			return Common::Error(Common::kCreatingFileFailed, "Cannot open/create dump file " + outPath.toString());
+		Common::Path outPath = destPath.join(filePath);
+		if (!out.open(outPath, true)) {
+			return Common::Error(Common::kCreatingFileFailed, "Cannot open/create dump file " + outPath.toString(Common::Path::kNativeSeparator));
 		} else {
 			uint32 writtenBytes = out.write(data, len);
 			if (writtenBytes < len) {
@@ -298,7 +298,7 @@ void SearchSet::add(const String &name, Archive *archive, int priority, bool aut
 
 }
 
-void SearchSet::addDirectory(const String &name, const String &directory, int priority, int depth, bool flat) {
+void SearchSet::addDirectory(const String &name, const Path &directory, int priority, int depth, bool flat) {
 	FSNode dir(directory);
 	addDirectory(name, dir, priority, depth, flat);
 }
@@ -310,6 +310,13 @@ void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority
 	add(name, new FSDirectory(dir, depth, flat, _ignoreClashes), priority);
 }
 
+void SearchSet::addDirectory(const Path &directory, int priority, int depth, bool flat) {
+	addDirectory(directory.toString(), directory, priority, depth, flat);
+}
+void SearchSet::addDirectory(const FSNode &directory, int priority, int depth, bool flat) {
+	addDirectory(directory.getPath().toString(), directory, priority, depth, flat);
+}
+
 void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority, int depth, bool flat) {
 	FSList subDirs;
 	if (!directory.getChildren(subDirs))
@@ -344,11 +351,13 @@ void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPa
 				multipleMatches[name] = true;
 			} else {
 				if (matchIter->_value) {
-					warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), matchIter->_key.c_str());
+					warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(),
+							directory.getPath().toString(Common::Path::kNativeSeparator).c_str(), matchIter->_key.c_str());
 					matchIter->_value = false;
 				}
 
-				warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), name.c_str());
+				warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(),
+						directory.getPath().toString(Common::Path::kNativeSeparator).c_str(), name.c_str());
 			}
 
 			if (nextPattern.empty())
diff --git a/common/archive.h b/common/archive.h
index 7cc0f4901f0..fb066b8ff14 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -22,14 +22,14 @@
 #ifndef COMMON_ARCHIVE_H
 #define COMMON_ARCHIVE_H
 
-#include "common/str.h"
+#include "common/error.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
 #include "common/list.h"
 #include "common/path.h"
 #include "common/ptr.h"
-#include "common/hashmap.h"
-#include "common/hash-str.h"
 #include "common/singleton.h"
-#include "common/error.h"
+#include "common/str.h"
 
 namespace Common {
 
@@ -205,7 +205,7 @@ public:
 	/**
 	 * Dump all files from the archive to the given directory
 	 */
-	Common::Error dumpArchive(String destPath);
+	Common::Error dumpArchive(const Path &destPath);
 
 	/**
 	 * Returns the separator used by internal paths in the archive
@@ -343,13 +343,19 @@ public:
 	/**
 	 * Create and add an FSDirectory by name.
 	 */
-	void addDirectory(const String &name, const String &directory, int priority = 0, int depth = 1, bool flat = false);
+	void addDirectory(const String &name, const Path &directory, int priority = 0, int depth = 1, bool flat = false);
 
 	/**
 	 * Create and add an FSDirectory by FSNode.
 	 */
 	void addDirectory(const String &name, const FSNode &directory, int priority = 0, int depth = 1, bool flat = false);
 
+	/**
+	 * Overloads which use directory path as name
+	 */
+	void addDirectory(const Path &directory, int priority = 0, int depth = 1, bool flat = false);
+	void addDirectory(const FSNode &directory, int priority = 0, int depth = 1, bool flat = false);
+
 	/**
 	 * Create and add a subdirectory by name (caseless).
 	 *


Commit: 088db8ca65b0b749d44d9b3978440adb707ad355
    https://github.com/scummvm/scummvm/commit/088db8ca65b0b749d44d9b3978440adb707ad355
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BASE: Various some path related cleanups

Changed paths:
    base/commandLine.cpp
    base/main.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 1e82b438539..a36f3755b5c 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1454,7 +1454,7 @@ static DetectedGames getGameList(const Common::FSNode &dir) {
 
 	// Collect all files from directory
 	if (!dir.getChildren(files, Common::FSNode::kListAll)) {
-		printf("Path %s does not exist or is not a directory.\n", dir.getPath().c_str());
+		printf("Path %s does not exist or is not a directory.\n", dir.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		return DetectedGames();
 	}
 
@@ -1496,7 +1496,7 @@ static Common::String detectGames(const Common::String &path, const Common::Stri
 	DetectedGames candidates = recListGames(dir, engineId, gameId, recursive);
 
 	if (candidates.empty()) {
-		printf("WARNING: ScummVM could not find any game in %s\n", dir.getPath().c_str());
+		printf("WARNING: ScummVM could not find any game in %s\n", dir.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		if (noPath) {
 			printf("WARNING: Consider using --path=<path> to specify a directory\n");
 		}
@@ -1591,13 +1591,9 @@ static void calcMD5(Common::FSNode &path, int32 length) {
 static void calcMD5Mac(Common::Path &filePath, int32 length) {
 	// We need to split the path into the file name and a SearchSet
 	Common::SearchSet dir;
-	char nativeSeparator = '/';
-#ifdef WIN32
-	nativeSeparator = '\\';
-#endif
-	Common::FSNode dirNode(filePath.getParent().toString(nativeSeparator));
-	dir.addDirectory(dirNode.getPath(), dirNode);
-	Common::String fileName = filePath.getLastComponent().toString();
+	Common::FSNode dirNode(filePath.getParent());
+	dir.addDirectory(dirNode);
+	Common::Path fileName = filePath.getLastComponent();
 
 	Common::MacResManager macResMan;
 	// FIXME: There currently isn't any way to tell the Mac resource
@@ -1605,11 +1601,11 @@ static void calcMD5Mac(Common::Path &filePath, int32 length) {
 	// and constructs a file name out of that. While usually a desirable
 	// thing, it's not ideal here.
 	if (!macResMan.open(fileName, dir)) {
-		printf("Mac resource file '%s' not found or could not be open\n", filePath.toString(nativeSeparator).c_str());
+		printf("Mac resource file '%s' not found or could not be open\n", filePath.toString(Common::Path::kNativeSeparator).c_str());
 	} else {
 		Common::ScopedPtr<Common::SeekableReadStream> dataFork(Common::MacResManager::openFileOrDataFork(fileName, dir));
 		if (!macResMan.hasResFork() && !dataFork) {
-			printf("'%s' has neither data not resource fork\n", macResMan.getBaseFileName().toString().c_str());
+			printf("'%s' has neither data not resource fork\n", macResMan.getBaseFileName().toString(Common::Path::kNativeSeparator).c_str());
 		} else {
 			bool tail = false;
 			if (length < 0) {// Tail md5 is requested
@@ -1622,7 +1618,7 @@ static void calcMD5Mac(Common::Path &filePath, int32 length) {
 				Common::String md5 = macResMan.computeResForkMD5AsString(length, tail);
 				if (length != 0 && length < (int32)macResMan.getResForkDataSize())
 					md5 += Common::String::format(" (%s %d bytes)", tail ? "last" : "first", length);
-				printf("%s (resource): %s, %llu bytes\n", macResMan.getBaseFileName().toString().c_str(), md5.c_str(), (unsigned long long)macResMan.getResForkDataSize());
+				printf("%s (resource): %s, %llu bytes\n", macResMan.getBaseFileName().toString(Common::Path::kNativeSeparator).c_str(), md5.c_str(), (unsigned long long)macResMan.getResForkDataSize());
 			}
 			if (dataFork) {
 				if (tail && dataFork->size() > length)
@@ -1630,7 +1626,7 @@ static void calcMD5Mac(Common::Path &filePath, int32 length) {
 				Common::String md5 = Common::computeStreamMD5AsString(*dataFork, length);
 				if (length != 0 && length < dataFork->size())
 					md5 += Common::String::format(" (%s %d bytes)", tail ? "last" : "first", length);
-				printf("%s (data): %s, %llu bytes\n", macResMan.getBaseFileName().toString().c_str(), md5.c_str(), (unsigned long long)dataFork->size());
+				printf("%s (data): %s, %llu bytes\n", macResMan.getBaseFileName().toString(Common::Path::kNativeSeparator).c_str(), md5.c_str(), (unsigned long long)dataFork->size());
 			}
 		}
 		macResMan.close();
diff --git a/base/main.cpp b/base/main.cpp
index a3b93193e5e..df1ed029c1b 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -235,7 +235,7 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 			metaEngineDetection.getEngineName(),
 			err.getDesc().c_str(),
 			target.c_str(),
-			dir.getPath().c_str()
+			dir.getPath().toString(Common::Path::kNativeSeparator).c_str()
 			);
 
 		// If a temporary target failed to launch, remove it from the configuration manager
@@ -278,7 +278,7 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 	// Add extrapath (if any) to the directory search list
 	if (ConfMan.hasKey("extrapath")) {
 		dir = Common::FSNode(ConfMan.get("extrapath"));
-		SearchMan.addDirectory(dir.getPath(), dir);
+		SearchMan.addDirectory(dir);
 	}
 
 	// If a second extrapath is specified on the app domain level, add that as well.
@@ -289,7 +289,7 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 		Common::String extraPath = ConfMan.get("extrapath", Common::ConfigManager::kApplicationDomain);
 		if (!SearchMan.hasArchive(extraPath)) {
 			dir = Common::FSNode(extraPath);
-			SearchMan.addDirectory(dir.getPath(), dir);
+			SearchMan.addDirectory(dir);
 		}
 	}
 


Commit: 74a615834719e2dc20ae7606ed7268a197df5e06
    https://github.com/scummvm/scummvm/commit/74a615834719e2dc20ae7606ed7268a197df5e06
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GUI: Add a PathWidget

It stores a Path and displays an optional placeholder if the path is
empty.
It is based on StaticTextWidget and doesn't allow edits.

Changed paths:
    gui/widget.h


diff --git a/gui/widget.h b/gui/widget.h
index 4498e2c452e..55edf2ffca2 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -456,6 +456,53 @@ protected:
 	Graphics::ManagedSurface _gfx;
 };
 
+class PathWidget : public StaticTextWidget {
+public:
+	PathWidget(GuiObject *boss, int x, int y, int w, int h, bool scale,
+			const Common::Path &path, Graphics::TextAlign align,
+			const Common::U32String &placeholder = Common::U32String(),
+			const Common::U32String &tooltip = Common::U32String(),
+			ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold,
+			bool useEllipsis = true) :
+		StaticTextWidget(boss, x, y, w, h, scale,
+				path.empty() ? placeholder : Common::U32String(path.toString(Common::Path::kNativeSeparator)),
+				align, tooltip, font, Common::UNK_LANG, useEllipsis),
+		_placeholder(placeholder) { }
+	PathWidget(GuiObject *boss, int x, int y, int w, int h,
+			const Common::Path &path, Graphics::TextAlign align,
+			const Common::U32String &placeholder = Common::U32String(),
+			const Common::U32String &tooltip = Common::U32String(),
+			ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold,
+			bool useEllipsis = true) :
+		StaticTextWidget(boss, x, y, w, h,
+				path.empty() ? placeholder : Common::U32String(path.toString(Common::Path::kNativeSeparator)),
+				align, tooltip, font, Common::UNK_LANG, useEllipsis),
+		_placeholder(placeholder) {}
+	PathWidget(GuiObject *boss, const Common::String &name,
+			const Common::Path &path,
+			const Common::U32String &placeholder = Common::U32String(),
+			const Common::U32String &tooltip = Common::U32String(),
+			ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold,
+			bool useEllipsis = true) :
+		StaticTextWidget(boss, name,
+				path.empty() ? placeholder : Common::U32String(path.toString(Common::Path::kNativeSeparator)),
+				tooltip, font, Common::UNK_LANG, useEllipsis),
+		_placeholder(placeholder) {}
+	void setLabel(const Common::Path &path) {
+		_path = path;
+		if (path.empty()) {
+			StaticTextWidget::setLabel(_placeholder);
+		} else {
+			StaticTextWidget::setLabel(path.toString(Common::Path::kNativeSeparator));
+		}
+	}
+	const Common::Path &getLabel() const { return _path; }
+	void setEmptyPlaceHolder(const Common::U32String &placeholder) { _placeholder = placeholder; }
+protected:
+	Common::Path _path;
+	Common::U32String _placeholder;
+};
+
 /* ContainerWidget */
 class ContainerWidget : public Widget {
 public:


Commit: fd0267cfd1ca199a13e1bca5d2d1a5b35210fa93
    https://github.com/scummvm/scummvm/commit/fd0267cfd1ca199a13e1bca5d2d1a5b35210fa93
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GUI: Make TextViewerDialog use a Path instead of a String

Changed paths:
    gui/textviewer.cpp
    gui/textviewer.h


diff --git a/gui/textviewer.cpp b/gui/textviewer.cpp
index 0dac5045e8a..a63d1e9d610 100644
--- a/gui/textviewer.cpp
+++ b/gui/textviewer.cpp
@@ -39,7 +39,7 @@ namespace GUI {
 #define kPadX 0.05
 #define kPadY 0.05
 
-TextViewerDialog::TextViewerDialog(Common::String fname)
+TextViewerDialog::TextViewerDialog(const Common::Path &fname)
 	: Dialog(0, 0, 1, 1), _fname(fname) {
 	_font = &g_gui.getFont(ThemeEngine::kFontStyleConsole);
 	_charWidth = _font->getMaxCharWidth();
@@ -64,11 +64,11 @@ TextViewerDialog::~TextViewerDialog() {
 	destroy();
 }
 
-bool TextViewerDialog::loadFile(Common::String &fname) {
+bool TextViewerDialog::loadFile(const Common::Path &fname) {
 	Common::FSNode file(fname);
 
 	if (!file.exists()) {
-		warning("TextViewerDialog::loadFile(): Cannot open file %s", fname.c_str());
+		warning("TextViewerDialog::loadFile(): Cannot open file %s", fname.toString(Common::Path::kNativeSeparator).c_str());
 
 		return false;
 	}
@@ -76,7 +76,7 @@ bool TextViewerDialog::loadFile(Common::String &fname) {
 	Common::SeekableReadStream *stream = file.createReadStream();
 
 	if (!stream) {
-		warning("TextViewerDialog::loadFile(): Cannot load file %s", fname.c_str());
+		warning("TextViewerDialog::loadFile(): Cannot load file %s", fname.toString(Common::Path::kNativeSeparator).c_str());
 
 		return false;
 	}
diff --git a/gui/textviewer.h b/gui/textviewer.h
index 250c1a82e1b..a50400a0faa 100644
--- a/gui/textviewer.h
+++ b/gui/textviewer.h
@@ -51,14 +51,14 @@ private:
 	ScrollBarWidget *_scrollBar;
 	ButtonWidget *_closeButton;
 
-	Common::String _fname;
+	Common::Path _fname;
 	const Graphics::Font *_font = nullptr;
 
-	bool loadFile(Common::String &fname);
+	bool loadFile(const Common::Path &fname);
 	void reflowLayout();
 
 public:
-	TextViewerDialog(Common::String fname);
+	TextViewerDialog(const Common::Path &fname);
 	~TextViewerDialog();
 
 	void destroy();


Commit: d9a8131ba28ba5a752eeb2c2339ac48e427dad1a
    https://github.com/scummvm/scummvm/commit/d9a8131ba28ba5a752eeb2c2339ac48e427dad1a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make getDefaultLogFileName return a Path instead of a String

Changed paths:
    backends/platform/3ds/osystem.cpp
    backends/platform/3ds/osystem.h
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/ios7/ios7_osys_main.h
    backends/platform/samsungtv/samsungtv.cpp
    backends/platform/samsungtv/samsungtv.h
    backends/platform/sdl/kolibrios/kolibrios.cpp
    backends/platform/sdl/kolibrios/kolibrios.h
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx.h
    backends/platform/sdl/miyoo/miyoo.cpp
    backends/platform/sdl/miyoo/miyoo.h
    backends/platform/sdl/opendingux/opendingux.cpp
    backends/platform/sdl/opendingux/opendingux.h
    backends/platform/sdl/posix/posix.cpp
    backends/platform/sdl/posix/posix.h
    backends/platform/sdl/ps3/ps3.cpp
    backends/platform/sdl/ps3/ps3.h
    backends/platform/sdl/psp2/psp2.cpp
    backends/platform/sdl/psp2/psp2.h
    backends/platform/sdl/riscos/riscos.cpp
    backends/platform/sdl/riscos/riscos.h
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h
    backends/platform/sdl/switch/switch.cpp
    backends/platform/sdl/switch/switch.h
    backends/platform/sdl/win32/win32.cpp
    backends/platform/sdl/win32/win32.h
    common/system.h
    gui/options.cpp


diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index 4de8549e89c..6ef15db0f4c 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -171,7 +171,7 @@ Common::String OSystem_3DS::getDefaultConfigFileName() {
 	return "sdmc:/3ds/scummvm/scummvm.ini";
 }
 
-Common::String OSystem_3DS::getDefaultLogFileName() {
+Common::Path OSystem_3DS::getDefaultLogFileName() {
 	return "sdmc:/3ds/scummvm/scummvm.log";
 }
 
@@ -240,9 +240,9 @@ Common::WriteStream *OSystem_3DS::createLogFile() {
 	// of a failure, we know that no log file is open.
 	_logFilePath.clear();
 
-	Common::String logFile;
+	Common::Path logFile;
 	if (ConfMan.hasKey("logfile"))
-		logFile = ConfMan.get("logfile");
+		logFile = ConfMan.getPath("logfile");
 	else
 		logFile = getDefaultLogFileName();
 	if (logFile.empty())
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index fac4d88e729..3b58a141243 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -197,7 +197,7 @@ private:
 	void flushGameScreen();
 	void flushCursor();
 
-	virtual Common::String getDefaultLogFileName();
+	virtual Common::Path getDefaultLogFileName();
 	virtual Common::WriteStream *createLogFile();
 
 protected:
@@ -288,7 +288,7 @@ private:
 	u16 _magWidth, _magHeight;
 	u16 _magCenterX, _magCenterY;
 
-	Common::String _logFilePath;
+	Common::Path _logFilePath;
 
 public:
 	// Pause
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 983149c0ce8..e5e14e17c36 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -193,7 +193,7 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
 	_trackball_scale(2),
 	_joystick_scale(10),
 	_defaultConfigFileName(""),
-	_defaultLogFileName(""),
+	_defaultLogFileName(),
 	_systemPropertiesSummaryStr(""),
 	_systemSDKdetectedStr(""),
 	_logger(nullptr) {
@@ -586,7 +586,7 @@ Common::String OSystem_Android::getDefaultConfigFileName() {
 	return _defaultConfigFileName;
 }
 
-Common::String OSystem_Android::getDefaultLogFileName() {
+Common::Path OSystem_Android::getDefaultLogFileName() {
 	if (_defaultLogFileName.empty()) {
 		_defaultLogFileName = JNI::getScummVMLogPath();
 	}
@@ -594,12 +594,14 @@ Common::String OSystem_Android::getDefaultLogFileName() {
 }
 
 Common::WriteStream *OSystem_Android::createLogFileForAppending() {
-	if (getDefaultLogFileName().empty()) {
+	Common::String logPath(getDefaultLogFileName().toString(Common::Path::kNativeSeparator));
+
+	if (logPath.empty()) {
 		__android_log_write(ANDROID_LOG_ERROR, android_log_tag, "Log file path is not known upon create attempt!");
 		return nullptr;
 	}
 
-	FILE *scvmLogFilePtr = fopen(getDefaultLogFileName().c_str(), "a");
+	FILE *scvmLogFilePtr = fopen(logPath.c_str(), "a");
 	if (scvmLogFilePtr != nullptr) {
 		// We check for log file size; if it's too big, we rewrite it.
 		// This happens only upon app launch, in initBackend() when createLogFileForAppending() is called
@@ -608,9 +610,9 @@ Common::WriteStream *OSystem_Android::createLogFileForAppending() {
 		if (sz > MAX_ANDROID_SCUMMVM_LOG_FILESIZE_IN_BYTES) {
 			fclose(scvmLogFilePtr);
 			__android_log_write(ANDROID_LOG_WARN, android_log_tag, "Default log file is bigger than 100KB. It will be overwritten!");
-			if (!getDefaultLogFileName().empty()) {
+			if (!logPath.empty()) {
 				// Create the log file from scratch overwriting the previous one
-				scvmLogFilePtr = fopen(getDefaultLogFileName().c_str(), "w");
+				scvmLogFilePtr = fopen(logPath.c_str(), "w");
 				if (scvmLogFilePtr == nullptr) {
 					__android_log_write(ANDROID_LOG_ERROR, android_log_tag, "Could not open default log file for rewrite!");
 					return nullptr;
@@ -622,7 +624,7 @@ Common::WriteStream *OSystem_Android::createLogFileForAppending() {
 		}
 	} else {
 		__android_log_write(ANDROID_LOG_ERROR, android_log_tag, "Could not open default log file for writing/appending.");
-		__android_log_write(ANDROID_LOG_ERROR, android_log_tag, getDefaultLogFileName().c_str());
+		__android_log_write(ANDROID_LOG_ERROR, android_log_tag, logPath.c_str());
 	}
 	return new PosixIoStream(scvmLogFilePtr);
 }
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 7be989a4a77..ffec1486e91 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -166,7 +166,7 @@ private:
 	TouchControls _touchControls;
 
 	Common::String _defaultConfigFileName;
-	Common::String _defaultLogFileName;
+	Common::Path _defaultLogFileName;
 	Common::String _systemPropertiesSummaryStr;
 	Common::String _systemSDKdetectedStr;
 
@@ -223,7 +223,7 @@ public:
 	Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
 
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 
 	void registerDefaultSettings(const Common::String &target) const override;
 	GUI::OptionsContainerWidget *buildBackendOptionsWidget(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const override;
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index b9e19702368..09454729980 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -158,7 +158,7 @@ public:
 	bool isConnectionLimited() override;
 	void virtualController(bool connect);
 
-	virtual Common::String getDefaultLogFileName() override { return Common::String("/scummvm.log"); }
+	virtual Common::Path getDefaultLogFileName() override { return Common::Path("/scummvm.log"); }
 
 	virtual GUI::OptionsContainerWidget* buildBackendOptionsWidget(GUI::GuiObject *boss, const Common::String &name, const Common::String &target) const override;
 	virtual void applyBackendSettings() override;
diff --git a/backends/platform/samsungtv/samsungtv.cpp b/backends/platform/samsungtv/samsungtv.cpp
index c63e372c6fe..eca25927917 100644
--- a/backends/platform/samsungtv/samsungtv.cpp
+++ b/backends/platform/samsungtv/samsungtv.cpp
@@ -57,9 +57,9 @@ Common::String OSystem_SDL_SamsungTV::getDefaultConfigFileName() {
 	return "/mtd_rwarea/.scummvmrc";
 }
 
-Common::String OSystem_SDL_SamsungTV::getDefaultLogFileName() {
+Common::Path OSystem_SDL_SamsungTV::getDefaultLogFileName() {
 	if (!Posix::assureDirectoryExists("/mtd_ram", nullptr)) {
-		return Common::String();
+		return Common::Path();
 	}
 
 	return "/mtd_ram/scummvm.log";
diff --git a/backends/platform/samsungtv/samsungtv.h b/backends/platform/samsungtv/samsungtv.h
index 466c08b4e8f..f48b1788aee 100644
--- a/backends/platform/samsungtv/samsungtv.h
+++ b/backends/platform/samsungtv/samsungtv.h
@@ -35,7 +35,7 @@ public:
 
 protected:
 	virtual Common::String getDefaultConfigFileName();
-	virtual Common::String getDefaultLogFileName();
+	virtual Common::Path getDefaultLogFileName();
 };
 
 #endif
diff --git a/backends/platform/sdl/kolibrios/kolibrios.cpp b/backends/platform/sdl/kolibrios/kolibrios.cpp
index adafa025ef3..d0cddf1b075 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.cpp
+++ b/backends/platform/sdl/kolibrios/kolibrios.cpp
@@ -108,8 +108,8 @@ Common::String OSystem_KolibriOS::getScreenshotsPath() {
 	return _writablePath.join(SCREENSHOTS_DIR_NAME).toString();
 }
 
-Common::String OSystem_KolibriOS::getDefaultLogFileName() {
-	return _writablePath.join("scummvm.log").toString();
+Common::Path OSystem_KolibriOS::getDefaultLogFileName() {
+	return _writablePath.join("scummvm.log");
 }
 
 AudioCDManager *OSystem_KolibriOS::createAudioCDManager() {
diff --git a/backends/platform/sdl/kolibrios/kolibrios.h b/backends/platform/sdl/kolibrios/kolibrios.h
index 4a3d4056444..5cffe2b30b1 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.h
+++ b/backends/platform/sdl/kolibrios/kolibrios.h
@@ -39,7 +39,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 
 	AudioCDManager *createAudioCDManager() override;
 
diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index d309d41a681..7ba950fa14e 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -157,7 +157,9 @@ bool OSystem_MacOSX::displayLogFile() {
 	if (_logFilePath.empty())
 		return false;
 
-	CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)_logFilePath.c_str(), _logFilePath.size(), false);
+	Common::String logFilePath(_logFilePath.toString(Common::Path::kNativeSeparator));
+
+	CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)logFilePath.c_str(), logFilePath.size(), false);
 	OSStatus err = LSOpenCFURLRef(url, NULL);
 	CFRelease(url);
 
@@ -236,19 +238,19 @@ Common::String OSystem_MacOSX::getDefaultConfigFileName() {
 	return configFile;
 }
 
-Common::String OSystem_MacOSX::getDefaultLogFileName() {
+Common::Path OSystem_MacOSX::getDefaultLogFileName() {
 	const char *prefix = getenv("HOME");
 	if (prefix == nullptr) {
-		return Common::String();
+		return Common::Path();
 	}
 
 	if (!Posix::assureDirectoryExists("Library/Logs", prefix)) {
-		return Common::String();
+		return Common::Path();
 	}
 
 	Common::String appName = getMacBundleName();
 	appName.toLowercase();
-	return Common::String(prefix) + "/Library/Logs/" + appName + ".log";
+	return Common::Path(prefix).join(Common::String("Library/Logs/") + appName + ".log");
 }
 
 Common::String OSystem_MacOSX::getDefaultIconsPath() {
diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h
index e244b36d0b5..72bd20ae48a 100644
--- a/backends/platform/sdl/macosx/macosx.h
+++ b/backends/platform/sdl/macosx/macosx.h
@@ -56,7 +56,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 
 	// Override createAudioCDManager() to get our Mac-specific
 	// version.
diff --git a/backends/platform/sdl/miyoo/miyoo.cpp b/backends/platform/sdl/miyoo/miyoo.cpp
index bb56ceea5fa..fd4a8a52644 100644
--- a/backends/platform/sdl/miyoo/miyoo.cpp
+++ b/backends/platform/sdl/miyoo/miyoo.cpp
@@ -203,7 +203,7 @@ Common::String OSystem_SDL_Miyoo::getDefaultConfigFileName() {
 
 }
 
-Common::String OSystem_SDL_Miyoo::getDefaultLogFileName() {
+Common::Path OSystem_SDL_Miyoo::getDefaultLogFileName() {
 	return LOG_FILE;
 }
 
diff --git a/backends/platform/sdl/miyoo/miyoo.h b/backends/platform/sdl/miyoo/miyoo.h
index bdf0cb70bda..faa3fec9c35 100644
--- a/backends/platform/sdl/miyoo/miyoo.h
+++ b/backends/platform/sdl/miyoo/miyoo.h
@@ -36,7 +36,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 };
 
 #endif
diff --git a/backends/platform/sdl/opendingux/opendingux.cpp b/backends/platform/sdl/opendingux/opendingux.cpp
index bdde0986db8..6b0e386d68f 100644
--- a/backends/platform/sdl/opendingux/opendingux.cpp
+++ b/backends/platform/sdl/opendingux/opendingux.cpp
@@ -178,7 +178,7 @@ Common::String OSystem_SDL_Opendingux::getDefaultConfigFileName() {
 
 }
 
-Common::String OSystem_SDL_Opendingux::getDefaultLogFileName() {
+Common::Path OSystem_SDL_Opendingux::getDefaultLogFileName() {
 	return LOG_FILE;
 }
 
diff --git a/backends/platform/sdl/opendingux/opendingux.h b/backends/platform/sdl/opendingux/opendingux.h
index 29c5eaaa186..ef962c425a8 100644
--- a/backends/platform/sdl/opendingux/opendingux.h
+++ b/backends/platform/sdl/opendingux/opendingux.h
@@ -36,7 +36,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 };
 
 #endif
diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index 7ade2bfd9dc..90c8c359299 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -335,7 +335,7 @@ void OSystem_POSIX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority
 	OSystem_SDL::addSysArchivesToSearchSet(s, priority);
 }
 
-Common::String OSystem_POSIX::getDefaultLogFileName() {
+Common::Path OSystem_POSIX::getDefaultLogFileName() {
 	Common::String logFile;
 
 	// On POSIX systems we follow the XDG Base Directory Specification for
@@ -357,7 +357,11 @@ Common::String OSystem_POSIX::getDefaultLogFileName() {
 		return Common::String();
 	}
 
-	return Common::String::format("%s/%s/scummvm.log", prefix, logFile.c_str());
+	Common::Path logPath(prefix);
+	logPath.joinInPlace(logFile);
+	logPath.joinInPlace("scummvm.log");
+
+	return logPath;
 }
 
 bool OSystem_POSIX::displayLogFile() {
@@ -376,7 +380,7 @@ bool OSystem_POSIX::displayLogFile() {
 	} else if (pid == 0) {
 
 		// Try xdg-open first
-		execlp("xdg-open", "xdg-open", _logFilePath.c_str(), (char *)0);
+		execlp("xdg-open", "xdg-open", _logFilePath.toString(Common::Path::kNativeSeparator).c_str(), (char *)0);
 
 		// If we're here, that clearly failed.
 
@@ -385,7 +389,7 @@ bool OSystem_POSIX::displayLogFile() {
 
 		// Try xterm+less next
 
-		execlp("xterm", "xterm", "-e", "less", _logFilePath.c_str(), (char *)0);
+		execlp("xterm", "xterm", "-e", "less", _logFilePath.toString(Common::Path::kNativeSeparator).c_str(), (char *)0);
 
 		// TODO: If less does not exist we could fall back to 'more'.
 		// However, we'll have to use 'xterm -hold' for that to prevent the
diff --git a/backends/platform/sdl/posix/posix.h b/backends/platform/sdl/posix/posix.h
index 248419f6988..3a75da172c5 100644
--- a/backends/platform/sdl/posix/posix.h
+++ b/backends/platform/sdl/posix/posix.h
@@ -42,7 +42,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 
 	Common::String getXdgUserDir(const char *name);
 
diff --git a/backends/platform/sdl/ps3/ps3.cpp b/backends/platform/sdl/ps3/ps3.cpp
index 0f7653e3511..b903a6f4f74 100644
--- a/backends/platform/sdl/ps3/ps3.cpp
+++ b/backends/platform/sdl/ps3/ps3.cpp
@@ -108,7 +108,7 @@ Common::String OSystem_PS3::getDefaultConfigFileName() {
 	return PREFIX "/scummvm.ini";
 }
 
-Common::String OSystem_PS3::getDefaultLogFileName() {
+Common::Path OSystem_PS3::getDefaultLogFileName() {
 	return PREFIX "/scummvm.log";
 }
 
diff --git a/backends/platform/sdl/ps3/ps3.h b/backends/platform/sdl/ps3/ps3.h
index 2f938b4f930..d4f247cd138 100644
--- a/backends/platform/sdl/ps3/ps3.h
+++ b/backends/platform/sdl/ps3/ps3.h
@@ -33,7 +33,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 };
 
 #endif
diff --git a/backends/platform/sdl/psp2/psp2.cpp b/backends/platform/sdl/psp2/psp2.cpp
index 9e2b52ba237..91569bd08db 100644
--- a/backends/platform/sdl/psp2/psp2.cpp
+++ b/backends/platform/sdl/psp2/psp2.cpp
@@ -186,7 +186,7 @@ Common::String OSystem_PSP2::getDefaultConfigFileName() {
 	return "ux0:data/scummvm/scummvm.ini";
 }
 
-Common::String OSystem_PSP2::getDefaultLogFileName() {
+Common::Path OSystem_PSP2::getDefaultLogFileName() {
 	return "ux0:data/scummvm/scummvm.log";
 }
 
diff --git a/backends/platform/sdl/psp2/psp2.h b/backends/platform/sdl/psp2/psp2.h
index 811967eca0d..29f8f354a9c 100644
--- a/backends/platform/sdl/psp2/psp2.h
+++ b/backends/platform/sdl/psp2/psp2.h
@@ -39,7 +39,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 };
 
 #endif
diff --git a/backends/platform/sdl/riscos/riscos.cpp b/backends/platform/sdl/riscos/riscos.cpp
index 427ce48b0ed..9b6a8de9589 100644
--- a/backends/platform/sdl/riscos/riscos.cpp
+++ b/backends/platform/sdl/riscos/riscos.cpp
@@ -155,14 +155,16 @@ Common::String OSystem_RISCOS::getDefaultConfigFileName() {
 	return "/<Choices$Write>/ScummVM/scummvmrc";
 }
 
-Common::String OSystem_RISCOS::getDefaultLogFileName() {
+Common::Path OSystem_RISCOS::getDefaultLogFileName() {
 	Common::String logFile = "/<Choices$Write>/ScummVM/Logs";
 
 	if (!Riscos::assureDirectoryExists(logFile)) {
-		return Common::String();
+		return Common::Path();
 	}
 
-	return logFile + "/scummvm";
+	Common::Path logPath(logFile);
+	logPath.joinInPlace("scummvm");
+	return logPath;
 }
 
 #endif
diff --git a/backends/platform/sdl/riscos/riscos.h b/backends/platform/sdl/riscos/riscos.h
index 9dade0867c1..2ac9e9e1580 100644
--- a/backends/platform/sdl/riscos/riscos.h
+++ b/backends/platform/sdl/riscos/riscos.h
@@ -38,7 +38,7 @@ public:
 
 protected:
 	virtual Common::String getDefaultConfigFileName();
-	virtual Common::String getDefaultLogFileName();
+	virtual Common::Path getDefaultLogFileName();
 };
 
 #endif
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 8cd8bba06d2..e920b6b55e0 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -615,9 +615,9 @@ Common::WriteStream *OSystem_SDL::createLogFile() {
 	// of a failure, we know that no log file is open.
 	_logFilePath.clear();
 
-	Common::String logFile;
+	Common::Path logFile;
 	if (ConfMan.hasKey("logfile"))
-		logFile = ConfMan.get("logfile");
+		logFile = ConfMan.getPath("logfile");
 	else
 		logFile = getDefaultLogFileName();
 	if (logFile.empty())
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 1315ae9b7fe..52c9da91f40 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -123,7 +123,7 @@ protected:
 	 * only use of this value is to use it to open the log file in an
 	 * editor; for that, we need it only as a string anyway.
 	 */
-	Common::String _logFilePath;
+	Common::Path _logFilePath;
 
 	/**
 	 * The event source we use for obtaining SDL events.
diff --git a/backends/platform/sdl/switch/switch.cpp b/backends/platform/sdl/switch/switch.cpp
index 7901f847c68..834748b4f74 100644
--- a/backends/platform/sdl/switch/switch.cpp
+++ b/backends/platform/sdl/switch/switch.cpp
@@ -149,7 +149,7 @@ void OSystem_Switch::logMessage(LogMessageType::Type type, const char *message)
 	printf("%s\n", message);
 }
 
-Common::String OSystem_Switch::getDefaultLogFileName() {
+Common::Path OSystem_Switch::getDefaultLogFileName() {
 	return "scummvm.log";
 }
 
diff --git a/backends/platform/sdl/switch/switch.h b/backends/platform/sdl/switch/switch.h
index 378b95e92f3..73f539593e3 100644
--- a/backends/platform/sdl/switch/switch.h
+++ b/backends/platform/sdl/switch/switch.h
@@ -36,7 +36,7 @@ public:
 	virtual Common::String getSystemLanguage() const;
 
 protected:
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 };
 
 #endif
diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp
index 91118cf5824..e48d2f6976c 100644
--- a/backends/platform/sdl/win32/win32.cpp
+++ b/backends/platform/sdl/win32/win32.cpp
@@ -161,7 +161,7 @@ bool OSystem_Win32::displayLogFile() {
 
 	// Try opening the log file with the default text editor
 	// log files should be registered as "txtfile" by default and thus open in the default text editor
-	TCHAR *tLogFilePath = Win32::stringToTchar(_logFilePath);
+	TCHAR *tLogFilePath = Win32::stringToTchar(_logFilePath.toString(Common::Path::kNativeSeparator));
 	SHELLEXECUTEINFO sei;
 
 	memset(&sei, 0, sizeof(sei));
@@ -377,7 +377,7 @@ Common::String OSystem_Win32::getDefaultConfigFileName() {
 	return Win32::tcharToString(configFile);
 }
 
-Common::String OSystem_Win32::getDefaultLogFileName() {
+Common::Path OSystem_Win32::getDefaultLogFileName() {
 	TCHAR logFile[MAX_PATH];
 
 	if (_isPortable) {
@@ -385,7 +385,7 @@ Common::String OSystem_Win32::getDefaultLogFileName() {
 	} else {
 		// Use the Application Data directory of the user profile
 		if (!Win32::getApplicationDataDirectory(logFile)) {
-			return Common::String();
+			return Common::Path();
 		}
 		_tcscat(logFile, TEXT("\\Logs"));
 		CreateDirectory(logFile, nullptr);
@@ -393,7 +393,7 @@ Common::String OSystem_Win32::getDefaultLogFileName() {
 
 	_tcscat(logFile, TEXT("\\scummvm.log"));
 
-	return Win32::tcharToString(logFile);
+	return Common::Path(Win32::tcharToString(logFile), Common::Path::kNativeSeparator);
 }
 
 bool OSystem_Win32::detectPortableConfigFile() {
diff --git a/backends/platform/sdl/win32/win32.h b/backends/platform/sdl/win32/win32.h
index ff418d59965..66a7578ffe5 100644
--- a/backends/platform/sdl/win32/win32.h
+++ b/backends/platform/sdl/win32/win32.h
@@ -55,7 +55,7 @@ public:
 
 protected:
 	Common::String getDefaultConfigFileName() override;
-	Common::String getDefaultLogFileName() override;
+	Common::Path getDefaultLogFileName() override;
 
 	// Override createAudioCDManager() to get our Windows-specific
 	// version.
diff --git a/common/system.h b/common/system.h
index 291e34ab1b9..5f5dd667192 100644
--- a/common/system.h
+++ b/common/system.h
@@ -29,6 +29,7 @@
 #include "common/ustr.h"
 #include "common/str-array.h" // For OSystem::updateStartSettings()
 #include "common/hash-str.h" // For OSystem::updateStartSettings()
+#include "common/path.h"
 #include "graphics/pixelformat.h"
 #include "graphics/mode.h"
 #include "graphics/opengl/context.h"
@@ -1810,7 +1811,7 @@ public:
 	 *
 	 * Note that not all ports can use this.
 	 */
-	virtual Common::String getDefaultLogFileName() { return Common::String(); }
+	virtual Common::Path getDefaultLogFileName() { return Common::Path(); }
 
 	/**
 	 * Register the default values for the settings the backend uses into the
diff --git a/gui/options.cpp b/gui/options.cpp
index 0e7cd22818c..37254d87583 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2493,16 +2493,17 @@ void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String
 	if (ConfMan.isKeyTemporary("config"))
 		configPathWidget->setFontColor(ThemeEngine::FontColor::kFontColorOverride);
 
-	Common::U32String logPath = g_system->getDefaultLogFileName();
+	Common::Path logPath = g_system->getDefaultLogFileName();
 	bool colorOverride = false;
 
 	if (ConfMan.hasKey("logfile")) {
-		logPath = ConfMan.get("logfile");
+		logPath = ConfMan.getPath("logfile");
 
 		if (ConfMan.isKeyTemporary("logfile"))
 			colorOverride = true;
 	}
-	_logPath = new StaticTextWidget(boss, prefix + "LogPath", _("ScummVM log path: ") + logPath, logPath);
+	Common::U32String logPathS = logPath.toString(Common::Path::kNativeSeparator);
+	_logPath = new StaticTextWidget(boss, prefix + "LogPath", _("ScummVM log path: ") + logPathS, logPathS);
 
 	if (colorOverride)
 		_logPath->setFontColor(ThemeEngine::FontColor::kFontColorOverride);
@@ -3286,10 +3287,10 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 
 		break;
 	case kViewLogCmd: {
-		Common::String logPath;
+		Common::Path logPath;
 
 		if (ConfMan.hasKey("logfile"))
-			logPath = ConfMan.get("logfile");
+			logPath = ConfMan.getPath("logfile");
 		else
 			logPath = g_system->getDefaultLogFileName();
 


Commit: 01ebece8079a3d9ce171d37eb750f6eee359724d
    https://github.com/scummvm/scummvm/commit/01ebece8079a3d9ce171d37eb750f6eee359724d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make getDefaultConfigFileName return a Path instead of a String

Changed paths:
    backends/platform/3ds/osystem.cpp
    backends/platform/3ds/osystem.h
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/atari/osystem_atari.cpp
    backends/platform/atari/osystem_atari.h
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/ios7_osys_main.h
    backends/platform/libretro/include/libretro-os.h
    backends/platform/libretro/src/libretro-os-utils.cpp
    backends/platform/psp/osys_psp.cpp
    backends/platform/psp/osys_psp.h
    backends/platform/samsungtv/samsungtv.cpp
    backends/platform/samsungtv/samsungtv.h
    backends/platform/sdl/kolibrios/kolibrios.cpp
    backends/platform/sdl/kolibrios/kolibrios.h
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx.h
    backends/platform/sdl/miyoo/miyoo.cpp
    backends/platform/sdl/miyoo/miyoo.h
    backends/platform/sdl/opendingux/opendingux.cpp
    backends/platform/sdl/opendingux/opendingux.h
    backends/platform/sdl/posix/posix.cpp
    backends/platform/sdl/posix/posix.h
    backends/platform/sdl/ps3/ps3.cpp
    backends/platform/sdl/ps3/ps3.h
    backends/platform/sdl/psp2/psp2.cpp
    backends/platform/sdl/psp2/psp2.h
    backends/platform/sdl/riscos/riscos.cpp
    backends/platform/sdl/riscos/riscos.h
    backends/platform/sdl/win32/win32.cpp
    backends/platform/sdl/win32/win32.h
    common/config-manager.cpp
    common/config-manager.h
    common/system.cpp
    common/system.h
    gui/options.cpp


diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index 6ef15db0f4c..724527eb389 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -167,7 +167,7 @@ void OSystem_3DS::updateConfig() {
 	}
 }
 
-Common::String OSystem_3DS::getDefaultConfigFileName() {
+Common::Path OSystem_3DS::getDefaultConfigFileName() {
 	return "sdmc:/3ds/scummvm/scummvm.ini";
 }
 
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 3b58a141243..137bc302846 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -126,7 +126,7 @@ public:
 	virtual void fatalError();
 	virtual void quit();
 
-	virtual Common::String getDefaultConfigFileName();
+	virtual Common::Path getDefaultConfigFileName();
 	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
 
 	// Graphics
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index e5e14e17c36..f1731d86e3f 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -192,7 +192,7 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
 	_thirdPointerId(-1),
 	_trackball_scale(2),
 	_joystick_scale(10),
-	_defaultConfigFileName(""),
+	_defaultConfigFileName(),
 	_defaultLogFileName(),
 	_systemPropertiesSummaryStr(""),
 	_systemSDKdetectedStr(""),
@@ -578,7 +578,7 @@ void OSystem_Android::initBackend() {
 	BaseBackend::initBackend();
 }
 
-Common::String OSystem_Android::getDefaultConfigFileName() {
+Common::Path OSystem_Android::getDefaultConfigFileName() {
 	// if possible, skip JNI call which is more costly (performance wise)
 	if (_defaultConfigFileName.empty()) {
 		_defaultConfigFileName = JNI::getScummVMConfigPath();
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index ffec1486e91..2e61f09c487 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -165,7 +165,7 @@ private:
 
 	TouchControls _touchControls;
 
-	Common::String _defaultConfigFileName;
+	Common::Path _defaultConfigFileName;
 	Common::Path _defaultLogFileName;
 	Common::String _systemPropertiesSummaryStr;
 	Common::String _systemSDKdetectedStr;
@@ -222,7 +222,7 @@ public:
 	Common::KeymapArray getGlobalKeymaps() override;
 	Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
 
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 
 	void registerDefaultSettings(const Common::String &target) const override;
diff --git a/backends/platform/atari/osystem_atari.cpp b/backends/platform/atari/osystem_atari.cpp
index 67f2005b221..da6820089da 100644
--- a/backends/platform/atari/osystem_atari.cpp
+++ b/backends/platform/atari/osystem_atari.cpp
@@ -419,18 +419,15 @@ void OSystem_Atari::addSysArchivesToSearchSet(Common::SearchSet &s, int priority
 #endif
 }
 
-Common::String OSystem_Atari::getDefaultConfigFileName() {
-	const Common::String baseConfigName = OSystem::getDefaultConfigFileName();
-
-	Common::String configFile;
+Common::Path OSystem_Atari::getDefaultConfigFileName() {
+	const Common::Path baseConfigName = OSystem::getDefaultConfigFileName();
 
 	const char *envVar = getenv("HOME");
 	if (envVar && *envVar) {
-		configFile = envVar;
-		configFile += '/';
-		configFile += baseConfigName;
+		Common::Path configFile(envVar);
+		confgFile.joinInPlace(baseConfigName);
 
-		if (configFile.size() < MAXPATHLEN)
+		if (configFile.toString(Common::Path::kNativeSeparator).size() < MAXPATHLEN)
 			return configFile;
 	}
 
diff --git a/backends/platform/atari/osystem_atari.h b/backends/platform/atari/osystem_atari.h
index b4c3f4c6ced..2afc60b97b2 100644
--- a/backends/platform/atari/osystem_atari.h
+++ b/backends/platform/atari/osystem_atari.h
@@ -44,7 +44,7 @@ public:
 	void logMessage(LogMessageType::Type type, const char *message) override;
 
 	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 
 	void update();
 
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index 33911a90fc3..18f472ccd66 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -418,9 +418,8 @@ OSystem_iOS7 *OSystem_iOS7::sharedInstance() {
 	return instance;
 }
 
-Common::String OSystem_iOS7::getDefaultConfigFileName() {
-	Common::String path = "/Preferences";
-	return path;
+Common::Path OSystem_iOS7::getDefaultConfigFileName() {
+	return Common::Path("/Preferences");
 }
 
 void OSystem_iOS7::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index 09454729980..70c31b3fa0e 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -142,7 +142,7 @@ public:
 	void startSoundsystem();
 	void stopSoundsystem();
 
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 
 	void logMessage(LogMessageType::Type type, const char *message) override;
 	void fatalError() override;
diff --git a/backends/platform/libretro/include/libretro-os.h b/backends/platform/libretro/include/libretro-os.h
index d8d926c1425..95090f81078 100644
--- a/backends/platform/libretro/include/libretro-os.h
+++ b/backends/platform/libretro/include/libretro-os.h
@@ -161,7 +161,7 @@ public:
 	/* Utils */
 	void getTimeAndDate(TimeDate &t, bool skipRecord) const override;
 	Audio::Mixer *getMixer(void) override;
-	Common::String getDefaultConfigFileName(void) override;
+	Common::Path getDefaultConfigFileName(void) override;
 	void logMessage(LogMessageType::Type type, const char *message) override;
 	int testGame(const char *filedata, bool autodetect);
 	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0) override {}
diff --git a/backends/platform/libretro/src/libretro-os-utils.cpp b/backends/platform/libretro/src/libretro-os-utils.cpp
index 254f2411308..e7d89d265c0 100644
--- a/backends/platform/libretro/src/libretro-os-utils.cpp
+++ b/backends/platform/libretro/src/libretro-os-utils.cpp
@@ -55,11 +55,11 @@ void OSystem_libretro::getTimeAndDate(TimeDate &t, bool skipRecord) const {
 	t.tm_mday = dayno + 1;
 }
 
-Common::String OSystem_libretro::getDefaultConfigFileName() {
+Common::Path OSystem_libretro::getDefaultConfigFileName() {
 	if (s_systemDir.empty())
-		return Common::String("scummvm.ini");
+		return Common::Path("scummvm.ini");
 	else
-		return s_systemDir + "/scummvm.ini";
+		return Common::Path(s_systemDir).appendComponent("scummvm.ini");
 }
 
 void OSystem_libretro::logMessage(LogMessageType::Type type, const char *message) {
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index de541fc4a9f..387594631a0 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -437,6 +437,6 @@ void OSystem_PSP::getTimeAndDate(TimeDate &td, bool skipRecord) const {
 	td.tm_wday = t.tm_wday;
 }
 
-Common::String OSystem_PSP::getDefaultConfigFileName() {
+Common::Path OSystem_PSP::getDefaultConfigFileName() {
 	return "ms0:/scummvm.ini";
 }
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index 3287420c4bc..57fc4cf51b4 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -141,7 +141,7 @@ public:
 
 	void logMessage(LogMessageType::Type type, const char *message);
 
-	virtual Common::String getDefaultConfigFileName();
+	virtual Common::Path getDefaultConfigFileName();
 };
 
 #endif /* OSYS_PSP_H */
diff --git a/backends/platform/samsungtv/samsungtv.cpp b/backends/platform/samsungtv/samsungtv.cpp
index eca25927917..9eb081c06e0 100644
--- a/backends/platform/samsungtv/samsungtv.cpp
+++ b/backends/platform/samsungtv/samsungtv.cpp
@@ -53,7 +53,7 @@ void OSystem_SDL_SamsungTV::fatalError() {
 	for (;;) {}
 }
 
-Common::String OSystem_SDL_SamsungTV::getDefaultConfigFileName() {
+Common::Path OSystem_SDL_SamsungTV::getDefaultConfigFileName() {
 	return "/mtd_rwarea/.scummvmrc";
 }
 
diff --git a/backends/platform/samsungtv/samsungtv.h b/backends/platform/samsungtv/samsungtv.h
index f48b1788aee..58d37d327b8 100644
--- a/backends/platform/samsungtv/samsungtv.h
+++ b/backends/platform/samsungtv/samsungtv.h
@@ -34,7 +34,7 @@ public:
 	virtual bool hasFeature(Feature f);
 
 protected:
-	virtual Common::String getDefaultConfigFileName();
+	virtual Common::Path getDefaultConfigFileName();
 	virtual Common::Path getDefaultLogFileName();
 };
 
diff --git a/backends/platform/sdl/kolibrios/kolibrios.cpp b/backends/platform/sdl/kolibrios/kolibrios.cpp
index d0cddf1b075..bc777f11d61 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.cpp
+++ b/backends/platform/sdl/kolibrios/kolibrios.cpp
@@ -85,8 +85,8 @@ void OSystem_KolibriOS::initBackend() {
 	OSystem_SDL::initBackend();
 }
 
-Common::String OSystem_KolibriOS::getDefaultConfigFileName() {
-	return _writablePath.join("scummvm.ini").toString();
+Common::Path OSystem_KolibriOS::getDefaultConfigFileName() {
+	return _writablePath.join("scummvm.ini");
 }
 
 Common::String OSystem_KolibriOS::getDefaultIconsPath() {
diff --git a/backends/platform/sdl/kolibrios/kolibrios.h b/backends/platform/sdl/kolibrios/kolibrios.h
index 5cffe2b30b1..44e39b1cbae 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.h
+++ b/backends/platform/sdl/kolibrios/kolibrios.h
@@ -38,7 +38,7 @@ public:
 	const Common::Path& getExePath() const { return _exePath; }
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 
 	AudioCDManager *createAudioCDManager() override;
diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index 7ba950fa14e..f462e842fc0 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -220,17 +220,16 @@ Common::String OSystem_MacOSX::getSystemLanguage() const {
 #endif // USE_DETECTLANG
 }
 
-Common::String OSystem_MacOSX::getDefaultConfigFileName() {
+Common::Path OSystem_MacOSX::getDefaultConfigFileName() {
 	const Common::String baseConfigName = "Library/Preferences/" + getMacBundleName() + " Preferences";
 
-	Common::String configFile;
+	Common::Path configFile;
 
 	Common::String prefix = getenv("HOME");
 
 	if (!prefix.empty() && (prefix.size() + 1 + baseConfigName.size()) < MAXPATHLEN) {
 		configFile = prefix;
-		configFile += '/';
-		configFile += baseConfigName;
+		configFile.joinInPlace(baseConfigName);
 	} else {
 		configFile = baseConfigName;
 	}
diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h
index 72bd20ae48a..eb2eaa72cf4 100644
--- a/backends/platform/sdl/macosx/macosx.h
+++ b/backends/platform/sdl/macosx/macosx.h
@@ -55,7 +55,7 @@ public:
 	Common::String getScreenshotsPath() override;
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 
 	// Override createAudioCDManager() to get our Mac-specific
diff --git a/backends/platform/sdl/miyoo/miyoo.cpp b/backends/platform/sdl/miyoo/miyoo.cpp
index fd4a8a52644..036041c38dc 100644
--- a/backends/platform/sdl/miyoo/miyoo.cpp
+++ b/backends/platform/sdl/miyoo/miyoo.cpp
@@ -198,7 +198,7 @@ void OSystem_SDL_Miyoo::initBackend() {
 	OSystem_SDL::initBackend();
 }
 
-Common::String OSystem_SDL_Miyoo::getDefaultConfigFileName() {
+Common::Path OSystem_SDL_Miyoo::getDefaultConfigFileName() {
 	return CONFIG_FILE;
 
 }
diff --git a/backends/platform/sdl/miyoo/miyoo.h b/backends/platform/sdl/miyoo/miyoo.h
index faa3fec9c35..3441d9ba9b6 100644
--- a/backends/platform/sdl/miyoo/miyoo.h
+++ b/backends/platform/sdl/miyoo/miyoo.h
@@ -35,7 +35,7 @@ public:
 	Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 };
 
diff --git a/backends/platform/sdl/opendingux/opendingux.cpp b/backends/platform/sdl/opendingux/opendingux.cpp
index 6b0e386d68f..4819d542f5b 100644
--- a/backends/platform/sdl/opendingux/opendingux.cpp
+++ b/backends/platform/sdl/opendingux/opendingux.cpp
@@ -173,7 +173,7 @@ void OSystem_SDL_Opendingux::initBackend() {
 	OSystem_SDL::initBackend();
 }
 
-Common::String OSystem_SDL_Opendingux::getDefaultConfigFileName() {
+Common::Path OSystem_SDL_Opendingux::getDefaultConfigFileName() {
 	return CONFIG_FILE;
 
 }
diff --git a/backends/platform/sdl/opendingux/opendingux.h b/backends/platform/sdl/opendingux/opendingux.h
index ef962c425a8..fb399acf8bf 100644
--- a/backends/platform/sdl/opendingux/opendingux.h
+++ b/backends/platform/sdl/opendingux/opendingux.h
@@ -35,7 +35,7 @@ public:
 	Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 };
 
diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index 90c8c359299..81f55f51446 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -111,7 +111,7 @@ bool OSystem_POSIX::hasFeature(Feature f) {
 	return OSystem_SDL::hasFeature(f);
 }
 
-Common::String OSystem_POSIX::getDefaultConfigFileName() {
+Common::Path OSystem_POSIX::getDefaultConfigFileName() {
 	const Common::String baseConfigName = "scummvm.ini";
 
 	Common::String configFile;
diff --git a/backends/platform/sdl/posix/posix.h b/backends/platform/sdl/posix/posix.h
index 3a75da172c5..0568fa2772d 100644
--- a/backends/platform/sdl/posix/posix.h
+++ b/backends/platform/sdl/posix/posix.h
@@ -41,7 +41,7 @@ public:
 	Common::String getScreenshotsPath() override;
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 
 	Common::String getXdgUserDir(const char *name);
diff --git a/backends/platform/sdl/ps3/ps3.cpp b/backends/platform/sdl/ps3/ps3.cpp
index b903a6f4f74..94ca6d79b93 100644
--- a/backends/platform/sdl/ps3/ps3.cpp
+++ b/backends/platform/sdl/ps3/ps3.cpp
@@ -104,7 +104,7 @@ void OSystem_PS3::initBackend() {
 	OSystem_SDL::initBackend();
 }
 
-Common::String OSystem_PS3::getDefaultConfigFileName() {
+Common::Path OSystem_PS3::getDefaultConfigFileName() {
 	return PREFIX "/scummvm.ini";
 }
 
diff --git a/backends/platform/sdl/ps3/ps3.h b/backends/platform/sdl/ps3/ps3.h
index d4f247cd138..ff1f585653e 100644
--- a/backends/platform/sdl/ps3/ps3.h
+++ b/backends/platform/sdl/ps3/ps3.h
@@ -32,7 +32,7 @@ public:
 	Common::HardwareInputSet *getHardwareInputSet() override;
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 };
 
diff --git a/backends/platform/sdl/psp2/psp2.cpp b/backends/platform/sdl/psp2/psp2.cpp
index 91569bd08db..fae1e73bee3 100644
--- a/backends/platform/sdl/psp2/psp2.cpp
+++ b/backends/platform/sdl/psp2/psp2.cpp
@@ -182,7 +182,7 @@ void OSystem_PSP2::logMessage(LogMessageType::Type type, const char *message) {
 #endif
 }
 
-Common::String OSystem_PSP2::getDefaultConfigFileName() {
+Common::Path OSystem_PSP2::getDefaultConfigFileName() {
 	return "ux0:data/scummvm/scummvm.ini";
 }
 
diff --git a/backends/platform/sdl/psp2/psp2.h b/backends/platform/sdl/psp2/psp2.h
index 29f8f354a9c..09a76a29013 100644
--- a/backends/platform/sdl/psp2/psp2.h
+++ b/backends/platform/sdl/psp2/psp2.h
@@ -38,7 +38,7 @@ public:
 	Common::HardwareInputSet *getHardwareInputSet() override;
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 };
 
diff --git a/backends/platform/sdl/riscos/riscos.cpp b/backends/platform/sdl/riscos/riscos.cpp
index 9b6a8de9589..528a3c06c53 100644
--- a/backends/platform/sdl/riscos/riscos.cpp
+++ b/backends/platform/sdl/riscos/riscos.cpp
@@ -151,7 +151,7 @@ void OSystem_RISCOS::messageBox(LogMessageType::Type type, const char *message)
 	_kernel_swi(Wimp_ReportError, &regs, &regs);
 }
 
-Common::String OSystem_RISCOS::getDefaultConfigFileName() {
+Common::Path OSystem_RISCOS::getDefaultConfigFileName() {
 	return "/<Choices$Write>/ScummVM/scummvmrc";
 }
 
diff --git a/backends/platform/sdl/riscos/riscos.h b/backends/platform/sdl/riscos/riscos.h
index 2ac9e9e1580..96b6c669253 100644
--- a/backends/platform/sdl/riscos/riscos.h
+++ b/backends/platform/sdl/riscos/riscos.h
@@ -37,7 +37,7 @@ public:
 	virtual void messageBox(LogMessageType::Type type, const char *message);
 
 protected:
-	virtual Common::String getDefaultConfigFileName();
+	virtual Common::Path getDefaultConfigFileName();
 	virtual Common::Path getDefaultLogFileName();
 };
 
diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp
index e48d2f6976c..6781f3085ac 100644
--- a/backends/platform/sdl/win32/win32.cpp
+++ b/backends/platform/sdl/win32/win32.cpp
@@ -327,7 +327,7 @@ Common::String OSystem_Win32::getScreenshotsPath() {
 	return Win32::tcharToString(picturesPath);
 }
 
-Common::String OSystem_Win32::getDefaultConfigFileName() {
+Common::Path OSystem_Win32::getDefaultConfigFileName() {
 	TCHAR configFile[MAX_PATH];
 
 	// if this is the first time the default config file name is requested
@@ -374,7 +374,7 @@ Common::String OSystem_Win32::getDefaultConfigFileName() {
 		}
 	}
 
-	return Win32::tcharToString(configFile);
+	return Common::Path(Win32::tcharToString(configFile), Common::Path::kNativeSeparator);
 }
 
 Common::Path OSystem_Win32::getDefaultLogFileName() {
diff --git a/backends/platform/sdl/win32/win32.h b/backends/platform/sdl/win32/win32.h
index 66a7578ffe5..29934213747 100644
--- a/backends/platform/sdl/win32/win32.h
+++ b/backends/platform/sdl/win32/win32.h
@@ -54,7 +54,7 @@ public:
 	Common::String getScreenshotsPath() override;
 
 protected:
-	Common::String getDefaultConfigFileName() override;
+	Common::Path getDefaultConfigFileName() override;
 	Common::Path getDefaultLogFileName() override;
 
 	// Override createAudioCDManager() to get our Windows-specific
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 236f1f17b7b..44da7cc1837 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -78,7 +78,7 @@ void ConfigManager::copyFrom(ConfigManager &source) {
 }
 
 
-bool ConfigManager::loadDefaultConfigFile(const String &fallbackFilename) {
+bool ConfigManager::loadDefaultConfigFile(const Path &fallbackFilename) {
 	// Open the default config file
 	assert(g_system);
 	SeekableReadStream *stream = g_system->createConfigReadStream();
@@ -103,22 +103,22 @@ bool ConfigManager::loadDefaultConfigFile(const String &fallbackFilename) {
 	return loadResult;
 }
 
-bool ConfigManager::loadConfigFile(const String &filename, const String &fallbackFilename) {
+bool ConfigManager::loadConfigFile(const Path &filename, const Path &fallbackFilename) {
 	_filename = filename;
 
 	FSNode node(filename);
 	File cfg_file;
 	if (!cfg_file.open(node)) {
 		if (!loadFallbackConfigFile(fallbackFilename))
-			debug("Creating configuration file: %s", filename.c_str());
+			debug("Creating configuration file: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	} else {
-		debug("Using configuration file: %s", _filename.c_str());
+		debug("Using configuration file: %s", _filename.toString(Common::Path::kNativeSeparator).c_str());
 		return loadFromStream(cfg_file);
 	}
 	return true;
 }
 
-bool ConfigManager::loadFallbackConfigFile(const String &filename) {
+bool ConfigManager::loadFallbackConfigFile(const Path &filename) {
 	if (filename.empty())
 		return false;
 
@@ -126,7 +126,7 @@ bool ConfigManager::loadFallbackConfigFile(const String &filename) {
 	if (!fallbackFile.open(FSNode(filename)))
 		return false;
 
-	debug("Using initial configuration file: %s", filename.c_str());
+	debug("Using initial configuration file: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	loadFromStream(fallbackFile);
 	return true;
 }
@@ -298,7 +298,7 @@ void ConfigManager::flushToDisk() {
 		assert(dump);
 
 		if (!dump->open(_filename)) {
-			warning("Unable to write configuration file: %s", _filename.c_str());
+			warning("Unable to write configuration file: %s", _filename.toString(Common::Path::kNativeSeparator).c_str());
 			delete dump;
 			return;
 		}
diff --git a/common/config-manager.h b/common/config-manager.h
index 6b85fab29e3..5ab99ff27f6 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -126,8 +126,8 @@ public:
 	static char const *const kCloudDomain;
 #endif
 
-	bool                     loadDefaultConfigFile(const String &fallbackFilename); /*!< Load the default configuration file. */
-	bool                     loadConfigFile(const String &filename, const String &fallbackFilename); /*!< Load a specific configuration file. */
+	bool                     loadDefaultConfigFile(const Path &fallbackFilename); /*!< Load the default configuration file. */
+	bool                     loadConfigFile(const Path &filename, const Path &fallbackFilename); /*!< Load a specific configuration file. */
 
 	/**
 	 * Retrieve the config domain with the given name.
@@ -222,7 +222,7 @@ public:
 	DomainMap::iterator      beginGameDomains() { return _gameDomains.begin(); } /*!< Return the beginning position of game domains. */
 	DomainMap::iterator      endGameDomains() { return _gameDomains.end(); } /*!< Return the ending position of game domains. */
 
-	const String             &getCustomConfigFileName() { return _filename; } /*!< Return the custom config file being used, or an empty string when using the default config file */
+	const Path              &getCustomConfigFileName() { return _filename; } /*!< Return the custom config file being used, or an empty string when using the default config file */
 
 	static void              defragment(); /*!< Move the configuration in memory to reduce fragmentation. */
 	void                     copyFrom(ConfigManager &source); /*!< Copy from a ConfigManager instance. */
@@ -231,7 +231,7 @@ private:
 	friend class Singleton<SingletonBaseType>;
 	ConfigManager();
 
-	bool            loadFallbackConfigFile(const String &filename);
+	bool			loadFallbackConfigFile(const Path &filename);
 	bool			loadFromStream(SeekableReadStream &stream);
 	void			addDomain(const String &domainName, const Domain &domain);
 	void			writeDomain(WriteStream &stream, const String &name, const Domain &domain);
@@ -256,7 +256,7 @@ private:
 	String			_activeDomainName;
 	Domain *		_activeDomain;
 
-	String			_filename;
+	Path			_filename;
 };
 
 /** @} */
diff --git a/common/system.cpp b/common/system.cpp
index d202be13340..6d0b013e8c4 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -242,7 +242,7 @@ Common::WriteStream *OSystem::createConfigWriteStream() {
 #endif
 }
 
-Common::String OSystem::getDefaultConfigFileName() {
+Common::Path OSystem::getDefaultConfigFileName() {
 	return "scummvm.ini";
 }
 
diff --git a/common/system.h b/common/system.h
index 5f5dd667192..6b515342cff 100644
--- a/common/system.h
+++ b/common/system.h
@@ -1803,7 +1803,7 @@ public:
 	 *
 	 * Note that not all ports can use this.
 	 */
-	virtual Common::String getDefaultConfigFileName();
+	virtual Common::Path getDefaultConfigFileName();
 
 	/**
 	 * Get the default file name (or even path) where the scummvm.log
diff --git a/gui/options.cpp b/gui/options.cpp
index 37254d87583..9311b7d5f74 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2480,15 +2480,15 @@ void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String
 		new ButtonWidget(boss, prefix + "PluginsButton", _("Plugins Path:"), Common::U32String(), kChoosePluginsDirCmd);
 	else
 		new ButtonWidget(boss, prefix + "PluginsButton", _c("Plugins Path:", "lowres"), Common::U32String(), kChoosePluginsDirCmd);
-	_pluginsPath = new StaticTextWidget(boss, prefix + "PluginsPath", _c("None", "path"));
+	_pluginsPath = new PathWidget(boss, prefix + "PluginsPath", Common::Path(), _c("None", "path"));
 
 	_pluginsPathClearButton = addClearButton(boss, "GlobalOptions_Paths.PluginsPathClearButton", kPluginsPathClearCmd);
 #endif // DYNAMIC_MODULES
 #endif // !defined(__DC__)
 
-	Common::U32String confPath = ConfMan.getCustomConfigFileName();
+	Common::U32String confPath = ConfMan.getCustomConfigFileName().toString(Common::Path::kNativeSeparator);
 	if (confPath.empty())
-		confPath = g_system->getDefaultConfigFileName();
+		confPath = g_system->getDefaultConfigFileName().toString(Common::Path::kNativeSeparator);
 	StaticTextWidget *configPathWidget = new StaticTextWidget(boss, prefix + "ConfigPath", _("ScummVM config path: ") + confPath, confPath);
 	if (ConfMan.isKeyTemporary("config"))
 		configPathWidget->setFontColor(ThemeEngine::FontColor::kFontColorOverride);


Commit: d87571766ee4f056d92f6347128c3caf98c57aec
    https://github.com/scummvm/scummvm/commit/d87571766ee4f056d92f6347128c3caf98c57aec
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: NETWORKING: Use Path for cURL requests

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


diff --git a/backends/networking/curl/curlrequest.cpp b/backends/networking/curl/curlrequest.cpp
index b9f42ab0e07..7c847aee827 100644
--- a/backends/networking/curl/curlrequest.cpp
+++ b/backends/networking/curl/curlrequest.cpp
@@ -112,7 +112,7 @@ void CurlRequest::addFormField(const Common::String &name, const Common::String
 	_formFields[name] = value;
 }
 
-void CurlRequest::addFormFile(const Common::String &name, const Common::String &filename) {
+void CurlRequest::addFormFile(const Common::String &name, const Common::Path &filename) {
 	if (_bytesBuffer)
 		warning("CurlRequest: added POST form files would be ignored, because there is buffer present");
 
diff --git a/backends/networking/curl/curlrequest.h b/backends/networking/curl/curlrequest.h
index aed00332616..577871d9400 100644
--- a/backends/networking/curl/curlrequest.h
+++ b/backends/networking/curl/curlrequest.h
@@ -23,6 +23,7 @@
 #define BACKENDS_NETWORKING_CURL_CURLREQUEST_H
 
 #include "backends/networking/curl/request.h"
+#include "common/path.h"
 #include "common/str.h"
 #include "common/array.h"
 #include "common/hashmap.h"
@@ -44,7 +45,7 @@ protected:
 	curl_slist *_headersList;
 	Common::String _postFields;
 	Common::HashMap<Common::String, Common::String> _formFields;
-	Common::HashMap<Common::String, Common::String> _formFiles;
+	Common::HashMap<Common::String, Common::Path> _formFiles;
 	byte *_bytesBuffer;
 	uint32 _bytesBufferSize;
 	bool _uploading; //using PUT method
@@ -75,7 +76,7 @@ public:
 	virtual void addFormField(const Common::String &name, const Common::String &value);
 
 	/** Adds a form/multipart file (field name, file name). */
-	virtual void addFormFile(const Common::String &name, const Common::String &filename);
+	virtual void addFormFile(const Common::String &name, const Common::Path &filename);
 
 	/** Sets bytes buffer. */
 	virtual void setBuffer(byte *buffer, uint32 size);
diff --git a/backends/networking/curl/networkreadstream.cpp b/backends/networking/curl/networkreadstream.cpp
index 0f7ed8e33ba..1315d4addb6 100644
--- a/backends/networking/curl/networkreadstream.cpp
+++ b/backends/networking/curl/networkreadstream.cpp
@@ -158,7 +158,7 @@ void NetworkReadStream::setupBufferContents(const byte *buffer, uint32 bufferSiz
 	ConnMan.registerEasyHandle(_easy);
 }
 
-void NetworkReadStream::setupFormMultipart(const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::String> &formFiles) {
+void NetworkReadStream::setupFormMultipart(const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::Path> &formFiles) {
 	// set POST multipart upload form fields/files
 	struct curl_httppost *formpost = nullptr;
 	struct curl_httppost *lastptr = nullptr;
@@ -176,12 +176,12 @@ void NetworkReadStream::setupFormMultipart(const Common::HashMap<Common::String,
 			warning("NetworkReadStream: field curl_formadd('%s') failed", i->_key.c_str());
 	}
 
-	for (Common::HashMap<Common::String, Common::String>::iterator i = formFiles.begin(); i != formFiles.end(); ++i) {
+	for (Common::HashMap<Common::String, Common::Path>::iterator i = formFiles.begin(); i != formFiles.end(); ++i) {
 		CURLFORMcode code = curl_formadd(
 			&formpost,
 			&lastptr,
 			CURLFORM_COPYNAME, i->_key.c_str(),
-			CURLFORM_FILE, i->_value.c_str(),
+			CURLFORM_FILE, i->_value.toString(Common::Path::kNativeSeparator).c_str(),
 			CURLFORM_END
 		);
 
@@ -199,7 +199,7 @@ NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, c
 	setupBufferContents((const byte *)postFields.c_str(), postFields.size(), uploading, usingPatch, false);
 }
 
-NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::String> &formFiles, bool keepAlive, long keepAliveIdle, long keepAliveInterval):
+NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::Path> &formFiles, bool keepAlive, long keepAliveIdle, long keepAliveInterval):
 		_backingStream(DisposeAfterUse::YES), _keepAlive(keepAlive), _keepAliveIdle(keepAliveIdle), _keepAliveInterval(keepAliveInterval), _errorBuffer(nullptr), _errorCode(CURLE_OK) {
 	initCurl(url, headersList);
 	setupFormMultipart(formFields, formFiles);
@@ -220,7 +220,7 @@ bool NetworkReadStream::reuse(const char *url, curl_slist *headersList, const Co
 	return true;
 }
 
-bool NetworkReadStream::reuse(const char *url, curl_slist *headersList, const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::String> &formFiles) {
+bool NetworkReadStream::reuse(const char *url, curl_slist *headersList, const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::Path> &formFiles) {
 	if (!reuseCurl(url, headersList))
 		return false;
 
diff --git a/backends/networking/curl/networkreadstream.h b/backends/networking/curl/networkreadstream.h
index 2625a13fcbf..3e1d9fb39e5 100644
--- a/backends/networking/curl/networkreadstream.h
+++ b/backends/networking/curl/networkreadstream.h
@@ -23,6 +23,7 @@
 #define BACKENDS_NETWORKING_CURL_NETWORKREADSTREAM_H
 
 #include "common/memstream.h"
+#include "common/path.h"
 #include "common/stream.h"
 #include "common/str.h"
 #include "common/hashmap.h"
@@ -52,7 +53,7 @@ class NetworkReadStream : public Common::ReadStream {
 	void initCurl(const char *url, curl_slist *headersList);
 	bool reuseCurl(const char *url, curl_slist *headersList);
 	void setupBufferContents(const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post);
-	void setupFormMultipart(const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::String> &formFiles);
+	void setupFormMultipart(const Common::HashMap<Common::String, Common::String> &formFields, const Common::HashMap<Common::String, Common::Path> &formFiles);
 
 	/**
 	 * Fills the passed buffer with _sendingContentsBuffer contents.
@@ -81,7 +82,7 @@ public:
 	NetworkReadStream(
 	    const char *url, curl_slist *headersList,
 	    const Common::HashMap<Common::String, Common::String> &formFields,
-	    const Common::HashMap<Common::String, Common::String> &formFiles,
+	    const Common::HashMap<Common::String, Common::Path> &formFiles,
 		bool keepAlive = false, long keepAliveIdle = 120, long keepAliveInterval = 60);
 	/** Send <buffer>, using POST by default. */
 	NetworkReadStream(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading = false, bool usingPatch = false, bool post = true, bool keepAlive = false, long keepAliveIdle = 120, long keepAliveInterval = 60);
@@ -93,7 +94,7 @@ public:
 	bool reuse(
 		const char *url, curl_slist *headersList,
 		const Common::HashMap<Common::String, Common::String> &formFields,
-		const Common::HashMap<Common::String, Common::String> &formFiles);
+		const Common::HashMap<Common::String, Common::Path> &formFiles);
 	/** Send <buffer>, using POST by default. */
 	bool reuse(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading = false, bool usingPatch = false, bool post = true);
 


Commit: 460be938f3d510ca41879d60393c89f2beedd719
    https://github.com/scummvm/scummvm/commit/460be938f3d510ca41879d60393c89f2beedd719
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
CLOUD: Make cloud use Path for local folders and files

Changed paths:
    backends/cloud/box/boxstorage.cpp
    backends/cloud/box/boxstorage.h
    backends/cloud/box/boxuploadrequest.cpp
    backends/cloud/box/boxuploadrequest.h
    backends/cloud/cloudmanager.cpp
    backends/cloud/cloudmanager.h
    backends/cloud/folderdownloadrequest.cpp
    backends/cloud/folderdownloadrequest.h
    backends/cloud/id/iddownloadrequest.cpp
    backends/cloud/id/iddownloadrequest.h
    backends/cloud/id/idstorage.cpp
    backends/cloud/id/idstorage.h
    backends/cloud/storage.cpp
    backends/cloud/storage.h
    gui/downloaddialog.cpp
    gui/downloaddialog.h
    gui/launcher.cpp


diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp
index e06833ab3cb..4865a803cdf 100644
--- a/backends/cloud/box/boxstorage.cpp
+++ b/backends/cloud/box/boxstorage.cpp
@@ -174,7 +174,7 @@ Networking::Request *BoxStorage::createDirectoryWithParentId(const Common::Strin
 	return addRequest(request);
 }
 
-Networking::Request *BoxStorage::upload(const Common::String &remotePath, const Common::String &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
+Networking::Request *BoxStorage::upload(const Common::String &remotePath, const Common::Path &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
 	if (!errorCallback)
 		errorCallback = getErrorPrintingCallback();
 	return addRequest(new BoxUploadRequest(this, remotePath, localPath, callback, errorCallback));
diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h
index 3fc755e3faf..27f2af06694 100644
--- a/backends/cloud/box/boxstorage.h
+++ b/backends/cloud/box/boxstorage.h
@@ -86,7 +86,7 @@ public:
 	Networking::Request *createDirectoryWithParentId(const Common::String &parentId, const Common::String &directoryName, BoolCallback callback, Networking::ErrorCallback errorCallback) override;
 
 	/** Returns UploadStatus struct with info about uploaded file. */
-	Networking::Request *upload(const Common::String &remotePath, const Common::String &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) override;
+	Networking::Request *upload(const Common::String &remotePath, const Common::Path &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) override;
 	Networking::Request *upload(const Common::String &path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) override;
 
 	/** Returns whether Storage supports upload(ReadStream). */
diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp
index fe528a9adcc..256db30cce7 100644
--- a/backends/cloud/box/boxuploadrequest.cpp
+++ b/backends/cloud/box/boxuploadrequest.cpp
@@ -34,7 +34,7 @@ namespace Box {
 
 #define BOX_API_FILES "https://upload.box.com/api/2.0/files"
 
-BoxUploadRequest::BoxUploadRequest(BoxStorage *storage, const Common::String &path, const Common::String &localPath, Storage::UploadCallback callback, Networking::ErrorCallback ecb):
+BoxUploadRequest::BoxUploadRequest(BoxStorage *storage, const Common::String &path, const Common::Path &localPath, Storage::UploadCallback callback, Networking::ErrorCallback ecb):
 	Networking::Request(nullptr, ecb), _storage(storage), _savePath(path), _localPath(localPath), _uploadCallback(callback),
 	_workingRequest(nullptr), _ignoreCallback(false) {
 	start();
diff --git a/backends/cloud/box/boxuploadrequest.h b/backends/cloud/box/boxuploadrequest.h
index 681bba464fa..64666513c79 100644
--- a/backends/cloud/box/boxuploadrequest.h
+++ b/backends/cloud/box/boxuploadrequest.h
@@ -33,7 +33,8 @@ class BoxStorage;
 
 class BoxUploadRequest: public Networking::Request {
 	BoxStorage *_storage;
-	Common::String _savePath, _localPath;
+	Common::String _savePath;
+	Common::Path _localPath;
 	Storage::UploadCallback _uploadCallback;
 	Request *_workingRequest;
 	bool _ignoreCallback;
@@ -49,7 +50,7 @@ class BoxUploadRequest: public Networking::Request {
 	void finishUpload(const StorageFile &status);
 
 public:
-	BoxUploadRequest(BoxStorage *storage, const Common::String &path, const Common::String &localPath, Storage::UploadCallback callback, Networking::ErrorCallback ecb);
+	BoxUploadRequest(BoxStorage *storage, const Common::String &path, const Common::Path &localPath, Storage::UploadCallback callback, Networking::ErrorCallback ecb);
 	~BoxUploadRequest() override;
 
 	void handle() override;
diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp
index cc0be93b95d..e0eaba3a4f0 100644
--- a/backends/cloud/cloudmanager.cpp
+++ b/backends/cloud/cloudmanager.cpp
@@ -393,7 +393,7 @@ Networking::Request *CloudManager::listDirectory(const Common::String &path, Sto
 	return nullptr;
 }
 
-Networking::Request *CloudManager::downloadFolder(const Common::String &remotePath, const Common::String &localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) {
+Networking::Request *CloudManager::downloadFolder(const Common::String &remotePath, const Common::Path &localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) {
 	Storage *storage = getCurrentStorage();
 	if (storage) {
 		return storage->downloadFolder(remotePath, localPath, callback, errorCallback, recursive);
@@ -514,7 +514,7 @@ void CloudManager::showCloudDisabledIcon() {
 
 ///// DownloadFolderRequest-related /////
 
-bool CloudManager::startDownload(const Common::String &remotePath, const Common::String &localPath) const {
+bool CloudManager::startDownload(const Common::String &remotePath, const Common::Path &localPath) const {
 	Storage *storage = getCurrentStorage();
 	if (storage)
 		return storage->startDownload(remotePath, localPath);
@@ -575,11 +575,11 @@ Common::String CloudManager::getDownloadRemoteDirectory() const {
 	return "";
 }
 
-Common::String CloudManager::getDownloadLocalDirectory() const {
+Common::Path CloudManager::getDownloadLocalDirectory() const {
 	Storage *storage = getCurrentStorage();
 	if (storage)
 		return storage->getDownloadLocalDirectory();
-	return "";
+	return Common::Path();
 }
 
 bool CloudManager::pollEvent(Common::Event &event) {
diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h
index 072235cca45..85574b5c283 100644
--- a/backends/cloud/cloudmanager.h
+++ b/backends/cloud/cloudmanager.h
@@ -240,7 +240,7 @@ public:
 	Networking::Request *listDirectory(const Common::String &path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
 
 	/** Returns Common::Array<StorageFile> with list of files, which were not downloaded. */
-	Networking::Request *downloadFolder(const Common::String &remotePath, const Common::String &localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
+	Networking::Request *downloadFolder(const Common::String &remotePath, const Common::Path &localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
 
 	/** Return the StorageInfo struct. */
 	Networking::Request *info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback);
@@ -291,7 +291,7 @@ public:
 	///// DownloadFolderRequest-related /////
 
 	/** Starts a folder download. */
-	bool startDownload(const Common::String &remotePath, const Common::String &localPath) const;
+	bool startDownload(const Common::String &remotePath, const Common::Path &localPath) const;
 
 	/** Cancels running download. */
 	void cancelDownload() const;
@@ -318,7 +318,7 @@ public:
 	Common::String getDownloadRemoteDirectory() const;
 
 	/** Returns local directory path. */
-	Common::String getDownloadLocalDirectory() const;
+	Common::Path getDownloadLocalDirectory() const;
 };
 
 /** Shortcut for accessing the connection manager. */
diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp
index 7b4d9cbc4ad..af790f76541 100644
--- a/backends/cloud/folderdownloadrequest.cpp
+++ b/backends/cloud/folderdownloadrequest.cpp
@@ -29,7 +29,7 @@
 
 namespace Cloud {
 
-FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, const Common::String &remoteDirectoryPath, const Common::String &localDirectoryPath, bool recursive):
+FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, const Common::String &remoteDirectoryPath, const Common::Path &localDirectoryPath, bool recursive):
 	Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _fileArrayCallback(callback),
 	_remoteDirectoryPath(remoteDirectoryPath), _localDirectoryPath(localDirectoryPath), _recursive(recursive),
 	_workingRequest(nullptr), _ignoreCallback(false), _totalFiles(0) {
@@ -124,23 +124,23 @@ void FolderDownloadRequest::downloadNextFile() {
 	sendCommand(GUI::kDownloadProgressCmd, (int)(getProgress() * 100));
 
 	Common::String remotePath = _currentFile.path();
-	Common::String localPath = remotePath;
-	if (_remoteDirectoryPath == "" || remotePath.hasPrefix(_remoteDirectoryPath)) {
-		localPath.erase(0, _remoteDirectoryPath.size());
-		if (_remoteDirectoryPath != "" && (_remoteDirectoryPath.lastChar() != '/' && _remoteDirectoryPath.lastChar() != '\\'))
-			localPath.erase(0, 1);
-	} else {
-		warning("FolderDownloadRequest: Can't process the following paths:");
-		warning("remote directory: %s", _remoteDirectoryPath.c_str());
-		warning("remote file under that directory: %s", remotePath.c_str());
+	Common::String localPathStr = remotePath;
+	if (!_remoteDirectoryPath.empty()) {
+		if (remotePath.hasPrefix(_remoteDirectoryPath)) {
+			localPathStr.erase(0, _remoteDirectoryPath.size());
+			if (_remoteDirectoryPath.lastChar() != '/' && _remoteDirectoryPath.lastChar() != '\\')
+				localPathStr.erase(0, 1);
+		} else {
+			warning("FolderDownloadRequest: Can't process the following paths:");
+			warning("remote directory: %s", _remoteDirectoryPath.c_str());
+			warning("remote file under that directory: %s", remotePath.c_str());
+		}
 	}
-	if (_localDirectoryPath != "") {
-		if (_localDirectoryPath.lastChar() == '/' || _localDirectoryPath.lastChar() == '\\')
-			localPath = _localDirectoryPath + localPath;
-		else
-			localPath = _localDirectoryPath + "/" + localPath;
+	Common::Path localPath(localPathStr);
+	if (!_localDirectoryPath.empty()) {
+		localPath = _localDirectoryPath.append(localPath);
 	}
-	debug(9, "FolderDownloadRequest: %s -> %s", remotePath.c_str(), localPath.c_str());
+	debug(9, "FolderDownloadRequest: %s -> %s", remotePath.c_str(), localPath.toString(Common::Path::kNativeSeparator).c_str());
 	_workingRequest = _storage->downloadById(
 		_currentFile.id(), localPath,
 		new Common::Callback<FolderDownloadRequest, const Storage::BoolResponse &>(this, &FolderDownloadRequest::fileDownloadedCallback),
diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h
index 9acbe5e7234..d134f79bc97 100644
--- a/backends/cloud/folderdownloadrequest.h
+++ b/backends/cloud/folderdownloadrequest.h
@@ -31,7 +31,8 @@ namespace Cloud {
 class FolderDownloadRequest: public Networking::Request, public GUI::CommandSender {
 	Storage *_storage;
 	Storage::FileArrayCallback _fileArrayCallback;
-	Common::String _remoteDirectoryPath, _localDirectoryPath;
+	Common::String _remoteDirectoryPath;
+	Common::Path _localDirectoryPath;
 	bool _recursive;
 	Common::Array<StorageFile> _pendingFiles, _failedFiles;
 	StorageFile _currentFile;
@@ -48,7 +49,7 @@ class FolderDownloadRequest: public Networking::Request, public GUI::CommandSend
 	void downloadNextFile();
 	void finishDownload(Common::Array<StorageFile> &files);
 public:
-	FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, const Common::String &remoteDirectoryPath, const Common::String &localDirectoryPath, bool recursive);
+	FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, const Common::String &remoteDirectoryPath, const Common::Path &localDirectoryPath, bool recursive);
 	~FolderDownloadRequest() override;
 
 	void handle() override;
@@ -70,7 +71,7 @@ public:
 	Common::String getRemotePath() const { return _remoteDirectoryPath; }
 
 	/** Returns local directory path. */
-	Common::String getLocalPath() const { return _localDirectoryPath; }
+	Common::Path getLocalPath() const { return _localDirectoryPath; }
 };
 
 } // End of namespace Cloud
diff --git a/backends/cloud/id/iddownloadrequest.cpp b/backends/cloud/id/iddownloadrequest.cpp
index 924a58942a6..c4271553f7e 100644
--- a/backends/cloud/id/iddownloadrequest.cpp
+++ b/backends/cloud/id/iddownloadrequest.cpp
@@ -26,7 +26,7 @@
 namespace Cloud {
 namespace Id {
 
-IdDownloadRequest::IdDownloadRequest(IdStorage *storage, const Common::String &remotePath, const Common::String &localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb):
+IdDownloadRequest::IdDownloadRequest(IdStorage *storage, const Common::String &remotePath, const Common::Path &localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb):
 	Networking::Request(nullptr, ecb), _requestedFile(remotePath), _requestedLocalFile(localPath), _storage(storage), _boolCallback(cb),
 	_workingRequest(nullptr), _ignoreCallback(false) {
 	start();
diff --git a/backends/cloud/id/iddownloadrequest.h b/backends/cloud/id/iddownloadrequest.h
index ac2ad2e0e62..f88fedbfe38 100644
--- a/backends/cloud/id/iddownloadrequest.h
+++ b/backends/cloud/id/iddownloadrequest.h
@@ -32,7 +32,8 @@ namespace Id {
 class IdStorage;
 
 class IdDownloadRequest: public Networking::Request {
-	Common::String _requestedFile, _requestedLocalFile;
+	Common::String _requestedFile;
+	Common::Path _requestedLocalFile;
 	IdStorage *_storage;
 	Storage::BoolCallback _boolCallback;
 	Request *_workingRequest;
@@ -45,7 +46,7 @@ class IdDownloadRequest: public Networking::Request {
 	void downloadErrorCallback(const Networking::ErrorResponse &error);
 	void finishDownload(bool success);
 public:
-	IdDownloadRequest(IdStorage *storage, const Common::String &remotePath, const Common::String &localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb);
+	IdDownloadRequest(IdStorage *storage, const Common::String &remotePath, const Common::Path &localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb);
 	~IdDownloadRequest() override;
 
 	void handle() override;
diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp
index d92b4786a3d..b24a87d7c98 100644
--- a/backends/cloud/id/idstorage.cpp
+++ b/backends/cloud/id/idstorage.cpp
@@ -106,7 +106,7 @@ Networking::Request *IdStorage::streamFile(const Common::String &path, Networkin
 	return addRequest(new IdStreamFileRequest(this, path, outerCallback, errorCallback));
 }
 
-Networking::Request *IdStorage::download(const Common::String &remotePath, const Common::String &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) {
+Networking::Request *IdStorage::download(const Common::String &remotePath, const Common::Path &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) {
 	return addRequest(new IdDownloadRequest(this, remotePath, localPath, callback, errorCallback));
 }
 
diff --git a/backends/cloud/id/idstorage.h b/backends/cloud/id/idstorage.h
index 187e5cd7e3f..90b1bc35af0 100644
--- a/backends/cloud/id/idstorage.h
+++ b/backends/cloud/id/idstorage.h
@@ -73,7 +73,7 @@ public:
 	virtual Networking::Request *streamFileById(const Common::String &id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) override = 0;
 
 	/** Calls the callback when finished. */
-	Networking::Request *download(const Common::String &remotePath, const Common::String &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) override;
+	Networking::Request *download(const Common::String &remotePath, const Common::Path &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) override;
 
 	virtual Common::String getRootDirectoryId() = 0;
 };
diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp
index 23e693644ea..50c0c86db37 100644
--- a/backends/cloud/storage.cpp
+++ b/backends/cloud/storage.cpp
@@ -84,7 +84,7 @@ void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer
 		syncSaves(nullptr, nullptr);
 }
 
-Networking::Request *Storage::upload(const Common::String &remotePath, const Common::String &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
+Networking::Request *Storage::upload(const Common::String &remotePath, const Common::Path &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
 	if (!errorCallback) errorCallback = getErrorPrintingCallback();
 
 	Common::File *f = new Common::File();
@@ -110,12 +110,12 @@ Networking::Request *Storage::streamFile(const Common::String &path, Networking:
 	return streamFileById(path, callback, errorCallback);
 }
 
-Networking::Request *Storage::download(const Common::String &remotePath, const Common::String &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) {
+Networking::Request *Storage::download(const Common::String &remotePath, const Common::Path &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) {
 	//most Storages use paths instead of ids, so this should work
 	return downloadById(remotePath, localPath, callback, errorCallback);
 }
 
-Networking::Request *Storage::downloadById(const Common::String &remoteId, const Common::String &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) {
+Networking::Request *Storage::downloadById(const Common::String &remoteId, const Common::Path &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) {
 	if (!errorCallback) errorCallback = getErrorPrintingCallback();
 
 	Common::DumpFile *f = new Common::DumpFile();
@@ -131,7 +131,7 @@ Networking::Request *Storage::downloadById(const Common::String &remoteId, const
 	return addRequest(new DownloadRequest(this, callback, errorCallback, remoteId, f));
 }
 
-Networking::Request *Storage::downloadFolder(const Common::String &remotePath, const Common::String &localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) {
+Networking::Request *Storage::downloadFolder(const Common::String &remotePath, const Common::Path &localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) {
 	if (!_isEnabled) {
 		warning("Storage::downloadFolder: cannot be run while Storage is disabled");
 		if (errorCallback)
@@ -250,7 +250,7 @@ void Storage::savesSyncDefaultErrorCallback(const Networking::ErrorResponse &err
 
 ///// DownloadFolderRequest-related /////
 
-bool Storage::startDownload(const Common::String &remotePath, const Common::String &localPath) {
+bool Storage::startDownload(const Common::String &remotePath, const Common::Path &localPath) {
 	_runningRequestsMutex.lock();
 	if (_downloadFolderRequest) {
 		warning("Storage::startDownload: there is a download in progress already");
@@ -333,8 +333,8 @@ Common::String Storage::getDownloadRemoteDirectory() {
 	return result;
 }
 
-Common::String Storage::getDownloadLocalDirectory() {
-	Common::String result = "";
+Common::Path Storage::getDownloadLocalDirectory() {
+	Common::Path result;
 	_runningRequestsMutex.lock();
 	if (_downloadFolderRequest)
 		result = _downloadFolderRequest->getLocalPath();
diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h
index 9deccce3a50..0b8e0d3102b 100644
--- a/backends/cloud/storage.h
+++ b/backends/cloud/storage.h
@@ -29,6 +29,7 @@
 #include "common/array.h"
 #include "common/callback.h"
 #include "common/mutex.h"
+#include "common/path.h"
 #include "common/stream.h"
 #include "common/str.h"
 
@@ -140,7 +141,7 @@ public:
 
 	/** Returns StorageFile with info about uploaded file. */
 	virtual Networking::Request *upload(const Common::String &path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) = 0;
-	virtual Networking::Request *upload(const Common::String &remotePath, const Common::String &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback);
+	virtual Networking::Request *upload(const Common::String &remotePath, const Common::Path &localPath, UploadCallback callback, Networking::ErrorCallback errorCallback);
 
 	/** Returns whether Storage supports upload(ReadStream). */
 	virtual bool uploadStreamSupported();
@@ -150,11 +151,11 @@ public:
 	virtual Networking::Request *streamFileById(const Common::String &id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0;
 
 	/** Calls the callback when finished. */
-	virtual Networking::Request *download(const Common::String &remotePath, const Common::String &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback);
-	virtual Networking::Request *downloadById(const Common::String &remoteId, const Common::String &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback);
+	virtual Networking::Request *download(const Common::String &remotePath, const Common::Path &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback);
+	virtual Networking::Request *downloadById(const Common::String &remoteId, const Common::Path &localPath, BoolCallback callback, Networking::ErrorCallback errorCallback);
 
 	/** Returns Common::Array<StorageFile> with list of files, which were not downloaded. */
-	virtual Networking::Request *downloadFolder(const Common::String &remotePath, const Common::String &localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
+	virtual Networking::Request *downloadFolder(const Common::String &remotePath, const Common::Path &localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
 
 	/** Calls the callback when finished. */
 	virtual SavesSyncRequest *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback);
@@ -214,7 +215,7 @@ public:
 	///// DownloadFolderRequest-related /////
 
 	/** Starts a folder download. */
-	virtual bool startDownload(const Common::String &remotePath, const Common::String &localPath);
+	virtual bool startDownload(const Common::String &remotePath, const Common::Path &localPath);
 
 	/** Cancels running download. */
 	virtual void cancelDownload();
@@ -241,7 +242,7 @@ public:
 	virtual Common::String getDownloadRemoteDirectory();
 
 	/** Returns local directory path. */
-	virtual Common::String getDownloadLocalDirectory();
+	virtual Common::Path getDownloadLocalDirectory();
 
 protected:
 	/** Finishes the download. Shows an OSD message. */
diff --git a/gui/downloaddialog.cpp b/gui/downloaddialog.cpp
index 91fcb74806f..36d8b032448 100644
--- a/gui/downloaddialog.cpp
+++ b/gui/downloaddialog.cpp
@@ -159,24 +159,8 @@ bool DownloadDialog::selectDirectories() {
 	}
 
 	//make a local path
-	Common::String localPath = dir.getPath();
-
-	//simple heuristic to determine which path separator to use
-	if (localPath.size() && localPath.lastChar() != '/' && localPath.lastChar() != '\\') {
-		int backslashes = 0;
-		for (uint32 i = 0; i < localPath.size(); ++i)
-			if (localPath[i] == '/')
-				--backslashes;
-			else if (localPath[i] == '\\')
-				++backslashes;
-
-		if (backslashes > 0)
-			localPath += '\\' + remoteDirectory.name();
-		else
-			localPath += '/' + remoteDirectory.name();
-	} else {
-		localPath += remoteDirectory.name();
-	}
+	Common::Path localPath = dir.getPath();
+	localPath.appendComponent(remoteDirectory.name());
 
 	CloudMan.startDownload(remoteDirectory.path(), localPath);
 	CloudMan.setDownloadTarget(this);
@@ -187,7 +171,7 @@ bool DownloadDialog::selectDirectories() {
 void DownloadDialog::handleTickle() {
 	if (_close) {
 		if (_launcher)
-			_launcher->doGameDetection(_localDirectory);
+			_launcher->doGameDetection(_localDirectory.toString('/'));
 		close();
 		_close = false;
 		return;
@@ -223,7 +207,7 @@ Common::U32String DownloadDialog::getSpeedLabelText() {
 void DownloadDialog::refreshWidgets() {
 	_localDirectory = CloudMan.getDownloadLocalDirectory();
 	_remoteDirectoryLabel->setLabel(_("From: ") + Common::U32String(CloudMan.getDownloadRemoteDirectory()));
-	_localDirectoryLabel->setLabel(_("To: ") + Common::U32String(_localDirectory));
+	_localDirectoryLabel->setLabel(_("To: ") + Common::U32String(_localDirectory.toString(Common::Path::kNativeSeparator)));
 	uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
 	_percentLabel->setLabel(Common::String::format("%u %%", progress));
 	_downloadSizeLabel->setLabel(getSizeLabelText());
diff --git a/gui/downloaddialog.h b/gui/downloaddialog.h
index e32889a0a80..21ced017108 100644
--- a/gui/downloaddialog.h
+++ b/gui/downloaddialog.h
@@ -56,7 +56,7 @@ class DownloadDialog : public Dialog {
 	ButtonWidget *_cancelButton;
 	ButtonWidget *_closeButton;
 
-	Common::String _localDirectory;
+	Common::Path _localDirectory;
 	bool _close;
 
 	Common::U32String getSizeLabelText();
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 65e21c09fe5..af74fabe5e5 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -400,18 +400,11 @@ void LauncherDialog::addGame() {
 		if (_browser->runModal() > 0) {
 			// User made his choice...
 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
-			Common::String selectedDirectory = _browser->getResult().getPath();
-			Common::String bannedDirectory = CloudMan.getDownloadLocalDirectory();
-			if (selectedDirectory.size() && selectedDirectory.lastChar() != '/' && selectedDirectory.lastChar() != '\\')
-				selectedDirectory += '/';
-			if (bannedDirectory.size() && bannedDirectory.lastChar() != '/' && bannedDirectory.lastChar() != '\\') {
-				if (selectedDirectory.size()) {
-					bannedDirectory += selectedDirectory.lastChar();
-				} else {
-					bannedDirectory += '/';
-				}
-			}
-			if (selectedDirectory.size() && bannedDirectory.size() && selectedDirectory.equalsIgnoreCase(bannedDirectory)) {
+			Common::Path selectedDirectory = _browser->getResult().getPath();
+			Common::Path bannedDirectory = CloudMan.getDownloadLocalDirectory();
+			selectedDirectory.removeTrailingSeparators();
+			bannedDirectory.removeTrailingSeparators();
+			if (!selectedDirectory.empty() && !bannedDirectory.empty() && selectedDirectory.equalsIgnoreCase(bannedDirectory)) {
 				MessageDialog alert(_("This directory cannot be used yet, it is being downloaded into!"));
 				alert.runModal();
 				return;


Commit: 87e9a406fa4e6e948a0af349f0d6133b44e73df1
    https://github.com/scummvm/scummvm/commit/87e9a406fa4e6e948a0af349f0d6133b44e73df1
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: NETWORKING: Use Path instead of String for local files

Use references when applicable too.

Changed paths:
    backends/networking/curl/session.cpp
    backends/networking/curl/session.h
    backends/networking/curl/sessionrequest.cpp
    backends/networking/curl/sessionrequest.h
    gui/downloadpacksdialog.cpp


diff --git a/backends/networking/curl/session.cpp b/backends/networking/curl/session.cpp
index 8712c82f916..39421b6c041 100644
--- a/backends/networking/curl/session.cpp
+++ b/backends/networking/curl/session.cpp
@@ -36,9 +36,9 @@ static Common::String constructUrl(const Common::String &prefix, const Common::S
 	// check url prefix
 	if (!prefix.empty()) {
 		if (url.contains("://")) {
-			if (url.size() < prefix.size() || url.find(prefix) != 0) {
+			if (!url.hasPrefix(prefix)) {
 				warning("Session: given URL does not match the prefix!\n\t%s\n\t%s", url.c_str(), prefix.c_str());
-				return "";
+				return Common::String();
 			}
 		} else {
 			// if no schema given, just append <url> to <_prefix>
@@ -53,7 +53,7 @@ static Common::String constructUrl(const Common::String &prefix, const Common::S
 	return url;
 }
 
-SessionRequest *Session::get(const Common::String &url, const Common::String &localFile, DataCallback cb, ErrorCallback ecb, bool binary) {
+SessionRequest *Session::get(const Common::String &url, const Common::Path &localFile, DataCallback cb, ErrorCallback ecb, bool binary) {
 	Common::String builtUrl = constructUrl(_prefix, url);
 
 	if (builtUrl.empty())
diff --git a/backends/networking/curl/session.h b/backends/networking/curl/session.h
index 34142b7e233..5f5a36393f6 100644
--- a/backends/networking/curl/session.h
+++ b/backends/networking/curl/session.h
@@ -35,7 +35,7 @@ public:
 	Session(const Common::String &prefix = Common::String());
 	~Session();
 
-	SessionRequest *get(const Common::String &url, const Common::String &localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
+	SessionRequest *get(const Common::String &url, const Common::Path &localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 	/**
 	 * @brief Gracefully close the session
 	 *
diff --git a/backends/networking/curl/sessionrequest.cpp b/backends/networking/curl/sessionrequest.cpp
index 8633fccc3aa..cd449a3da60 100644
--- a/backends/networking/curl/sessionrequest.cpp
+++ b/backends/networking/curl/sessionrequest.cpp
@@ -31,7 +31,7 @@
 
 namespace Networking {
 
-SessionRequest::SessionRequest(const Common::String &url, const Common::String &localFile, DataCallback cb, ErrorCallback ecb, bool binary):
+SessionRequest::SessionRequest(const Common::String &url, const Common::Path &localFile, DataCallback cb, ErrorCallback ecb, bool binary):
 	CurlRequest(cb, ecb, url), _contentsStream(DisposeAfterUse::YES),
 	_buffer(new byte[CURL_SESSION_REQUEST_BUFFER_SIZE]), _text(nullptr), _localFile(nullptr),
 	_started(false), _complete(false), _success(false), _binary(binary) {
@@ -48,7 +48,7 @@ SessionRequest::~SessionRequest() {
 	delete[] _buffer;
 }
 
-void SessionRequest::openLocalFile(const Common::String &localFile) {
+void SessionRequest::openLocalFile(const Common::Path &localFile) {
 	if (localFile.empty())
 		return;
 
@@ -62,7 +62,7 @@ void SessionRequest::openLocalFile(const Common::String &localFile) {
 		return;
 	}
 
-	debug(5, "SessionRequest: opened localfile %s", localFile.c_str());
+	debug(5, "SessionRequest: opened localfile %s", localFile.toString(Common::Path::kNativeSeparator).c_str());
 
 	_binary = true; // Enforce binary
 }
@@ -137,7 +137,7 @@ void SessionRequest::startAndWait() {
 	wait();
 }
 
-void SessionRequest::reuse(const Common::String &url, const Common::String &localFile, DataCallback cb, ErrorCallback ecb, bool binary) {
+void SessionRequest::reuse(const Common::String &url, const Common::Path &localFile, DataCallback cb, ErrorCallback ecb, bool binary) {
 	_url = url;
 
 	delete _callback;
diff --git a/backends/networking/curl/sessionrequest.h b/backends/networking/curl/sessionrequest.h
index 3ca22772591..8d0e52d3710 100644
--- a/backends/networking/curl/sessionrequest.h
+++ b/backends/networking/curl/sessionrequest.h
@@ -28,6 +28,7 @@
 namespace Common {
 class DumpFile;
 class JSONValue;
+class Path;
 }
 
 namespace Networking {
@@ -63,16 +64,16 @@ protected:
 
 	void finishError(const ErrorResponse &error, RequestState state = PAUSED) override;
 	void finishSuccess() override;
-	void openLocalFile(const Common::String &localFile);
+	void openLocalFile(const Common::Path &localFile);
 
 public:
-	SessionRequest(const Common::String &url, const Common::String &localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
+	SessionRequest(const Common::String &url, const Common::Path &localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 	~SessionRequest() override;
 
 	void start();
 	void startAndWait();
 
-	void reuse(const Common::String &url, const Common::String &localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
+	void reuse(const Common::String &url, const Common::Path &localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 
 	void handle() override;
 	void restart() override;
diff --git a/gui/downloadpacksdialog.cpp b/gui/downloadpacksdialog.cpp
index 228f7a0baf4..cf1a0222c8f 100644
--- a/gui/downloadpacksdialog.cpp
+++ b/gui/downloadpacksdialog.cpp
@@ -78,7 +78,7 @@ private:
 
 
 void DialogState::downloadList() {
-	Networking::SessionRequest *rq = session.get(Common::String::format("https://downloads.scummvm.org/frs/icons/%s", listfname), "",
+	Networking::SessionRequest *rq = session.get(Common::String::format("https://downloads.scummvm.org/frs/icons/%s", listfname), Common::Path(),
 		new Common::Callback<DialogState, const Networking::DataResponse &>(this, &DialogState::downloadListCallback),
 		new Common::Callback<DialogState, const Networking::ErrorResponse &>(this, &DialogState::errorCallback),
 		true);


Commit: d8db629cd550852023bd98f9c740ee9efef06e0c
    https://github.com/scummvm/scummvm/commit/d8db629cd550852023bd98f9c740ee9efef06e0c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: NETWORKING: Make rootpath a Path and use Path everywhere

Changed paths:
    backends/networking/sdl_net/handlers/createdirectoryhandler.cpp
    backends/networking/sdl_net/handlers/downloadfilehandler.cpp
    backends/networking/sdl_net/handlers/filesbasehandler.cpp
    backends/networking/sdl_net/handlers/filesbasehandler.h
    backends/networking/sdl_net/handlers/filespagehandler.cpp
    backends/networking/sdl_net/handlers/listajaxhandler.cpp
    backends/networking/sdl_net/handlers/uploadfilehandler.cpp
    backends/networking/sdl_net/handlerutils.cpp
    backends/networking/sdl_net/handlerutils.h
    backends/networking/sdl_net/uploadfileclienthandler.cpp
    backends/networking/sdl_net/uploadfileclienthandler.h


diff --git a/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp b/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp
index a97174688fe..0acff90a6fb 100644
--- a/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp
+++ b/backends/networking/sdl_net/handlers/createdirectoryhandler.cpp
@@ -20,7 +20,6 @@
  */
 
 #include "backends/networking/sdl_net/handlers/createdirectoryhandler.h"
-#include "backends/fs/fs-factory.h"
 #include "backends/networking/sdl_net/handlerutils.h"
 #include "backends/networking/sdl_net/localwebserver.h"
 #include "common/translation.h"
@@ -67,39 +66,38 @@ void CreateDirectoryHandler::handle(Client &client) {
 	}
 
 	// transform virtual path to actual file system one
-	Common::String prefixToRemove = "", prefixToAdd = "";
-	if (!transformPath(path, prefixToRemove, prefixToAdd) || path.empty()) {
+	Common::String basePath;
+	Common::Path baseFSPath, fsPath;
+	if (!urlToPath(path, fsPath, basePath, baseFSPath) || path.empty()) {
 		handleError(client, Common::convertFromU32String(_("Invalid path!")));
 		return;
 	}
 
 	// check that <path> exists, is directory and isn't forbidden
-	AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path);
-	if (!HandlerUtils::permittedPath(node->getPath())) {
+	Common::FSNode node(fsPath);
+	if (!HandlerUtils::permittedPath(node.getPath())) {
 		handleError(client, Common::convertFromU32String(_("Invalid path!")));
 		return;
 	}
-	if (!node->exists()) {
+	if (!node.exists()) {
 		handleError(client, Common::convertFromU32String(_("Parent directory doesn't exists!")));
 		return;
 	}
-	if (!node->isDirectory()) {
+	if (!node.isDirectory()) {
 		handleError(client, Common::convertFromU32String(_("Can't create a directory within a file!")));
 		return;
 	}
 
 	// check that <directory_name> doesn't exist or is directory
-	if (path.lastChar() != '/' && path.lastChar() != '\\')
-		path += '/';
-	node = g_system->getFilesystemFactory()->makeFileNodePath(path + name);
-	if (node->exists()) {
-		if (!node->isDirectory()) {
+	node = Common::FSNode(fsPath.appendComponent(name));
+	if (node.exists()) {
+		if (!node.isDirectory()) {
 			handleError(client, Common::convertFromU32String(_("There is a file with that name in the parent directory!")));
 			return;
 		}
 	} else {
 		// create the <directory_name> in <path>
-		if (!node->createDirectory()) {
+		if (!node.createDirectory()) {
 			handleError(client, Common::convertFromU32String(_("Failed to create the directory!")));
 			return;
 		}
diff --git a/backends/networking/sdl_net/handlers/downloadfilehandler.cpp b/backends/networking/sdl_net/handlers/downloadfilehandler.cpp
index 6419fd2e0cd..fa1d9f2786c 100644
--- a/backends/networking/sdl_net/handlers/downloadfilehandler.cpp
+++ b/backends/networking/sdl_net/handlers/downloadfilehandler.cpp
@@ -20,7 +20,6 @@
  */
 
 #include "backends/networking/sdl_net/handlers/downloadfilehandler.h"
-#include "backends/fs/fs-factory.h"
 #include "backends/networking/sdl_net/getclienthandler.h"
 #include "backends/networking/sdl_net/handlerutils.h"
 #include "backends/networking/sdl_net/localwebserver.h"
@@ -50,27 +49,28 @@ void DownloadFileHandler::handle(Client &client) {
 	}
 
 	// transform virtual path to actual file system one
-	Common::String prefixToRemove = "", prefixToAdd = "";
-	if (!transformPath(path, prefixToRemove, prefixToAdd, false) || path.empty()) {
+	Common::String basePath;
+	Common::Path baseFSPath, fsPath;
+	if (!urlToPath(path, fsPath, basePath, baseFSPath, false) || path.empty()) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
 		return;
 	}
 
 	// check that <path> exists, is directory and isn't forbidden
-	AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path);
-	if (!HandlerUtils::permittedPath(node->getPath())) {
+	Common::FSNode node(fsPath);
+	if (!HandlerUtils::permittedPath(node.getPath())) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
 		return;
 	}
-	if (!node->exists()) {
+	if (!node.exists()) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("The file doesn't exist!")));
 		return;
 	}
-	if (node->isDirectory()) {
+	if (node.isDirectory()) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Can't download a directory!")));
 		return;
 	}
-	Common::SeekableReadStream *stream = node->createReadStream();
+	Common::SeekableReadStream *stream = node.createReadStream();
 	if (stream == nullptr) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Failed to read the file!")));
 		return;
@@ -79,7 +79,7 @@ void DownloadFileHandler::handle(Client &client) {
 	GetClientHandler *handler = new GetClientHandler(stream);
 	handler->setResponseCode(200);
 	handler->setHeader("Content-Type", "application/force-download");
-	handler->setHeader("Content-Disposition", "attachment; filename=\"" + node->getName() + "\"");
+	handler->setHeader("Content-Disposition", "attachment; filename=\"" + node.getName() + "\"");
 	handler->setHeader("Content-Transfer-Encoding", "binary");
 	client.setHandler(handler);
 }
diff --git a/backends/networking/sdl_net/handlers/filesbasehandler.cpp b/backends/networking/sdl_net/handlers/filesbasehandler.cpp
index c5be2932225..6750985c65f 100644
--- a/backends/networking/sdl_net/handlers/filesbasehandler.cpp
+++ b/backends/networking/sdl_net/handlers/filesbasehandler.cpp
@@ -45,43 +45,35 @@ Common::String FilesBaseHandler::parentPath(const Common::String &path) {
 	return result;
 }
 
-bool FilesBaseHandler::transformPath(Common::String &path, Common::String &prefixToRemove, Common::String &prefixToAdd, bool isDirectory) {
-	// <path> is not empty, but could lack the trailing slash
-	if (isDirectory && path.lastChar() != '/' && path.lastChar() != '\\')
-		path += '/';
+bool FilesBaseHandler::urlToPath(Common::String &url, Common::Path &path, Common::String &baseUrl, Common::Path &basePath, bool isDirectory) {
+	// <url> is not empty, but could lack the trailing slash
+	if (isDirectory && url.lastChar() != '/')
+		url += '/';
 
-	if (path.hasPrefix("/root") && ConfMan.hasKey("rootpath", "cloud")) {
-		prefixToAdd = "/root/";
-		prefixToRemove = ConfMan.get("rootpath", "cloud");
-		if (prefixToRemove.size() && prefixToRemove.lastChar() != '/' && prefixToRemove.lastChar() != '\\')
-			prefixToRemove += '/';
-		if (prefixToRemove == "/") prefixToRemove = "";
-		path.erase(0, 5);
-		if (path.size() && (path[0] == '/' || path[0] == '\\'))
-			path.deleteChar(0); // if that was "/root/ab/c", it becomes "/ab/c", but we need "ab/c"
-		path = prefixToRemove + path;
-		if (path == "")
-			path = "/"; // absolute root is '/'
+	if (url.hasPrefix("/root") && ConfMan.hasKey("rootpath", "cloud")) {
+		baseUrl = "/root/";
+		basePath = ConfMan.getPath("rootpath", "cloud");
+		url.erase(0, 5);
+		if (url.size() && url[0] == '/')
+			url.deleteChar(0); // if that was "/root/ab/c", it becomes "/ab/c", but we need "ab/c"
+		path = basePath.join(url, '/');
 		return true;
 	}
 
-	if (path.hasPrefix("/saves")) {
-		prefixToAdd = "/saves/";
+	if (url.hasPrefix("/saves")) {
+		baseUrl = "/saves/";
 
 		// determine savepath (prefix to remove)
 #ifdef USE_LIBCURL
 		DefaultSaveFileManager *manager = dynamic_cast<DefaultSaveFileManager *>(g_system->getSavefileManager());
-		prefixToRemove = (manager ? manager->concatWithSavesPath("") : ConfMan.get("savepath"));
+		basePath = (manager ? manager->concatWithSavesPath("") : ConfMan.getPath("savepath"));
 #else
-		prefixToRemove = ConfMan.get("savepath");
+		basePath = ConfMan.getPath("savepath");
 #endif
-		if (prefixToRemove.size() && prefixToRemove.lastChar() != '/' && prefixToRemove.lastChar() != '\\')
-			prefixToRemove += '/';
-
-		path.erase(0, 6);
-		if (path.size() && (path[0] == '/' || path[0] == '\\'))
-			path.deleteChar(0);
-		path = prefixToRemove + path;
+		url.erase(0, 6);
+		if (url.size() && url[0] == '/')
+			url.deleteChar(0);
+		path = basePath.join(url, '/');
 		return true;
 	}
 
diff --git a/backends/networking/sdl_net/handlers/filesbasehandler.h b/backends/networking/sdl_net/handlers/filesbasehandler.h
index 9a330d8e8e4..434be8eea6e 100644
--- a/backends/networking/sdl_net/handlers/filesbasehandler.h
+++ b/backends/networking/sdl_net/handlers/filesbasehandler.h
@@ -24,6 +24,10 @@
 
 #include "backends/networking/sdl_net/handlers/basehandler.h"
 
+namespace Common {
+class Path;
+}
+
 namespace Networking {
 
 class FilesBaseHandler: public BaseHandler {
@@ -31,14 +35,14 @@ protected:
 	Common::String parentPath(const Common::String &path);
 
 	/**
-	* Transforms virtual <path> into actual file system path.
+	* Transforms virtual <url> into actual file system path.
 	*
-	* Fills prefixes with actual file system prefix ("to remove")
-	* and virtual path prefix ("to add").
+	* Fills base path with actual file system prefix
+	* and base URL with virtual prefix
 	*
 	* Returns true on success.
 	*/
-	bool transformPath(Common::String &path, Common::String &prefixToRemove, Common::String &prefixToAdd, bool isDirectory = true);
+	bool urlToPath(Common::String &url, Common::Path &path, Common::String &baseUrl, Common::Path &basePath, bool isDirectory = true);
 public:
 	FilesBaseHandler();
 	~FilesBaseHandler() override;
diff --git a/backends/networking/sdl_net/handlers/filespagehandler.cpp b/backends/networking/sdl_net/handlers/filespagehandler.cpp
index 6b02f653823..dacc645f513 100644
--- a/backends/networking/sdl_net/handlers/filespagehandler.cpp
+++ b/backends/networking/sdl_net/handlers/filespagehandler.cpp
@@ -86,13 +86,12 @@ bool FilesPageHandler::listDirectory(const Common::String &path_, Common::String
 		return false;
 
 	Common::String path = path_;
-	Common::String prefixToRemove = "", prefixToAdd = "";
-	if (!transformPath(path, prefixToRemove, prefixToAdd))
+	Common::String basePath;
+	Common::Path baseFSPath, fsPath;
+	if (!urlToPath(path, fsPath, basePath, baseFSPath))
 		return false;
 
-	Common::FSNode node = Common::FSNode(path);
-	if (path == "/")
-		node = node.getParent(); // absolute root
+	Common::FSNode node = Common::FSNode(fsPath);
 
 	if (!HandlerUtils::permittedPath(node.getPath()))
 		return false;
@@ -109,13 +108,11 @@ bool FilesPageHandler::listDirectory(const Common::String &path_, Common::String
 
 	// add parent directory link
 	{
-		Common::String filePath = path;
-		if (filePath.hasPrefix(prefixToRemove))
-			filePath.erase(0, prefixToRemove.size());
-		if (filePath == "" || filePath == "/" || filePath == "\\")
-			filePath = "/";
-		else
-			filePath = parentPath(prefixToAdd + filePath);
+		Common::Path relPath = fsPath.relativeTo(baseFSPath);
+		relPath = relPath.getParent();
+		Common::String filePath("/");
+		if (!relPath.empty())
+			filePath = basePath + relPath.toString('/');
 		addItem(content, itemTemplate, IT_PARENT_DIRECTORY, filePath, Common::convertFromU32String(_("Parent directory")));
 	}
 
@@ -125,10 +122,9 @@ bool FilesPageHandler::listDirectory(const Common::String &path_, Common::String
 		if (i->isDirectory())
 			name += "/";
 
-		Common::String filePath = i->getPath();
-		if (filePath.hasPrefix(prefixToRemove))
-			filePath.erase(0, prefixToRemove.size());
-		filePath = prefixToAdd + filePath;
+		Common::Path relPath = i->getPath().relativeTo(baseFSPath);
+		Common::String filePath(basePath);
+		filePath += relPath.toString('/');
 
 		addItem(content, itemTemplate, detectType(i->isDirectory(), name), filePath, name);
 	}
diff --git a/backends/networking/sdl_net/handlers/listajaxhandler.cpp b/backends/networking/sdl_net/handlers/listajaxhandler.cpp
index 8f939e778a4..5323c7d68bc 100644
--- a/backends/networking/sdl_net/handlers/listajaxhandler.cpp
+++ b/backends/networking/sdl_net/handlers/listajaxhandler.cpp
@@ -50,14 +50,13 @@ Common::JSONObject ListAjaxHandler::listDirectory(const Common::String &path_) {
 	if (HandlerUtils::hasForbiddenCombinations(path_))
 		return errorResult;
 
-	Common::String prefixToRemove = "", prefixToAdd = "";
 	Common::String path = path_;
-	if (!transformPath(path, prefixToRemove, prefixToAdd))
+	Common::String basePath;
+	Common::Path baseFSPath, fsPath;
+	if (!urlToPath(path, fsPath, basePath, baseFSPath))
 		return errorResult;
 
-	Common::FSNode node = Common::FSNode(path);
-	if (path == "/")
-		node = node.getParent(); // absolute root
+	Common::FSNode node = Common::FSNode(fsPath);
 
 	if (!HandlerUtils::permittedPath(node.getPath()))
 		return errorResult;
@@ -74,25 +73,24 @@ Common::JSONObject ListAjaxHandler::listDirectory(const Common::String &path_) {
 
 	// add parent directory link
 	{
-		Common::String filePath = path;
-		if (filePath.hasPrefix(prefixToRemove))
-			filePath.erase(0, prefixToRemove.size());
-		if (filePath == "" || filePath == "/" || filePath == "\\")
-			filePath = "/";
-		else
-			filePath = parentPath(prefixToAdd + filePath);
+		Common::Path relPath = fsPath.relativeTo(baseFSPath);
+		relPath = relPath.getParent();
+		Common::String filePath("/");
+		if (!relPath.empty())
+			filePath = basePath + relPath.toString('/');
+
 		addItem(itemsList, IT_PARENT_DIRECTORY, filePath, Common::convertFromU32String(_("Parent directory")));
 	}
 
 	// fill the content
 	for (Common::FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
 		Common::String name = i->getName();
-		if (i->isDirectory()) name += "/";
+		if (i->isDirectory())
+			name += "/";
 
-		Common::String filePath = i->getPath();
-		if (filePath.hasPrefix(prefixToRemove))
-			filePath.erase(0, prefixToRemove.size());
-		filePath = prefixToAdd + filePath;
+		Common::Path relPath = i->getPath().relativeTo(baseFSPath);
+		Common::String filePath(basePath);
+		filePath += relPath.toString('/');
 
 		addItem(itemsList, detectType(i->isDirectory(), name), filePath, name);
 	}
diff --git a/backends/networking/sdl_net/handlers/uploadfilehandler.cpp b/backends/networking/sdl_net/handlers/uploadfilehandler.cpp
index f5045796f45..0213a6b43fc 100644
--- a/backends/networking/sdl_net/handlers/uploadfilehandler.cpp
+++ b/backends/networking/sdl_net/handlers/uploadfilehandler.cpp
@@ -22,7 +22,6 @@
 #include "backends/networking/sdl_net/handlers/uploadfilehandler.h"
 #include "backends/networking/sdl_net/handlerutils.h"
 #include "backends/networking/sdl_net/uploadfileclienthandler.h"
-#include "backends/fs/fs-factory.h"
 #include "common/system.h"
 #include "common/translation.h"
 
@@ -50,29 +49,30 @@ void UploadFileHandler::handle(Client &client) {
 	}
 
 	// transform virtual path to actual file system one
-	Common::String prefixToRemove = "", prefixToAdd = "";
-	if (!transformPath(path, prefixToRemove, prefixToAdd, false) || path.empty()) {
+	Common::String basePath;
+	Common::Path baseFSPath, fsPath;
+	if (!urlToPath(path, fsPath, basePath, baseFSPath, false) || path.empty()) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
 		return;
 	}
 
 	// check that <path> exists, is directory and isn't forbidden
-	AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path);
-	if (!HandlerUtils::permittedPath(node->getPath())) {
+	Common::FSNode node(fsPath);
+	if (!HandlerUtils::permittedPath(node.getPath())) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Invalid path!")));
 		return;
 	}
-	if (!node->exists()) {
+	if (!node.exists()) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("The parent directory doesn't exist!")));
 		return;
 	}
-	if (!node->isDirectory()) {
+	if (!node.isDirectory()) {
 		HandlerUtils::setFilesManagerErrorMessageHandler(client, Common::convertFromU32String(_("Can't upload into a file!")));
 		return;
 	}
 
 	// if all OK, set special handler
-	client.setHandler(new UploadFileClientHandler(path));
+	client.setHandler(new UploadFileClientHandler(fsPath));
 }
 
 } // End of namespace Networking
diff --git a/backends/networking/sdl_net/handlerutils.cpp b/backends/networking/sdl_net/handlerutils.cpp
index 51ce98ef0fd..b9789547654 100644
--- a/backends/networking/sdl_net/handlerutils.cpp
+++ b/backends/networking/sdl_net/handlerutils.cpp
@@ -78,7 +78,7 @@ Common::SeekableReadStream *HandlerUtils::getArchiveFile(const Common::String &n
 	Common::SeekableReadStream *result = nullptr;
 	Common::Archive *zipArchive = getZipArchive();
 	if (zipArchive) {
-		const Common::ArchiveMemberPtr ptr = zipArchive->getMember(name);
+		const Common::ArchiveMemberPtr ptr = zipArchive->getMember(Common::Path(name, '/'));
 		if (ptr.get() == nullptr)
 			return nullptr;
 		result = ptr->createReadStream();
@@ -133,7 +133,7 @@ bool HandlerUtils::hasForbiddenCombinations(const Common::String &path) {
 	return (path.contains("/../") || path.contains("\\..\\") || path.contains("\\../") || path.contains("/..\\"));
 }
 
-bool HandlerUtils::isBlacklisted(const Common::String &path) {
+bool HandlerUtils::isBlacklisted(const Common::Path &path) {
 	const char *blacklist[] = {
 		"/etc",
 		"/bin",
@@ -141,40 +141,40 @@ bool HandlerUtils::isBlacklisted(const Common::String &path) {
 	};
 
 	// normalize path
-	Common::String normalized = normalizePath(path);
+	Common::Path normalized = path.normalize();
 
 	uint32 size = sizeof(blacklist) / sizeof(const char *);
 	for (uint32 i = 0; i < size; ++i)
-		if (normalized.hasPrefix(blacklist[i]))
+		if (normalized.isRelativeTo(Common::Path(blacklist[i], '/')))
 			return true;
 
 	return false;
 }
 
-bool HandlerUtils::hasPermittedPrefix(const Common::String &path) {
+bool HandlerUtils::hasPermittedPrefix(const Common::Path &path) {
 	// normalize path
-	Common::String normalized = normalizePath(path);
+	Common::Path normalized = path.normalize();
 
 	// prefix for /root/
-	Common::String prefix;
+	Common::Path prefix;
 	if (ConfMan.hasKey("rootpath", "cloud")) {
-		prefix = normalizePath(ConfMan.get("rootpath", "cloud"));
-		if (prefix == "/" || normalized.hasPrefix(prefix))
+		prefix = ConfMan.getPath("rootpath", "cloud").normalize();
+		if (normalized.isRelativeTo(prefix))
 			return true;
 	}
 
 	// prefix for /saves/
 #ifdef USE_LIBCURL
 	DefaultSaveFileManager *manager = dynamic_cast<DefaultSaveFileManager *>(g_system->getSavefileManager());
-	prefix = (manager ? manager->concatWithSavesPath("") : ConfMan.get("savepath"));
+	prefix = (manager ? manager->concatWithSavesPath("") : ConfMan.getPath("savepath"));
 #else
-	prefix = ConfMan.get("savepath");
+	prefix = ConfMan.getPath("savepath");
 #endif
-	return normalized.hasPrefix(normalizePath(prefix))
-	       || normalizePath(prefix).compareTo(normalized + "/") == 0;
+	prefix = prefix.normalize();
+	return normalized.isRelativeTo(prefix);
 }
 
-bool HandlerUtils::permittedPath(const Common::String &path) {
+bool HandlerUtils::permittedPath(const Common::Path &path) {
 	return hasPermittedPrefix(path) && !isBlacklisted(path);
 }
 
diff --git a/backends/networking/sdl_net/handlerutils.h b/backends/networking/sdl_net/handlerutils.h
index ab4a327e0be..c5559c0b8e2 100644
--- a/backends/networking/sdl_net/handlerutils.h
+++ b/backends/networking/sdl_net/handlerutils.h
@@ -37,9 +37,9 @@ public:
 
 	static Common::String normalizePath(const Common::String &path);
 	static bool hasForbiddenCombinations(const Common::String &path);
-	static bool isBlacklisted(const Common::String &path);
-	static bool hasPermittedPrefix(const Common::String &path);
-	static bool permittedPath(const Common::String &path);
+	static bool isBlacklisted(const Common::Path &path);
+	static bool hasPermittedPrefix(const Common::Path &path);
+	static bool permittedPath(const Common::Path &path);
 
 	static void setMessageHandler(Client &client, const Common::String &message, const Common::String &redirectTo = "");
 	static void setFilesManagerErrorMessageHandler(Client &client, const Common::String &message, const Common::String &redirectTo = "");
diff --git a/backends/networking/sdl_net/uploadfileclienthandler.cpp b/backends/networking/sdl_net/uploadfileclienthandler.cpp
index dfb69abf020..8c8ea808b1b 100644
--- a/backends/networking/sdl_net/uploadfileclienthandler.cpp
+++ b/backends/networking/sdl_net/uploadfileclienthandler.cpp
@@ -20,7 +20,6 @@
  */
 
 #include "backends/networking/sdl_net/uploadfileclienthandler.h"
-#include "backends/fs/fs-factory.h"
 #include "backends/networking/sdl_net/handlerutils.h"
 #include "backends/networking/sdl_net/localwebserver.h"
 #include "backends/networking/sdl_net/reader.h"
@@ -30,7 +29,7 @@
 
 namespace Networking {
 
-UploadFileClientHandler::UploadFileClientHandler(const Common::String &parentDirectoryPath):
+UploadFileClientHandler::UploadFileClientHandler(const Common::Path &parentDirectoryPath):
 	_state(UFH_READING_CONTENT), _headersStream(nullptr), _contentStream(nullptr),
 	_parentDirectoryPath(parentDirectoryPath), _uploadedFiles(0) {}
 
@@ -128,15 +127,13 @@ void UploadFileClientHandler::handleBlockHeaders(Client *client) {
 		return;
 
 	// check that <path>/<filename> doesn't exist
-	Common::String path = _parentDirectoryPath;
-	if (path.lastChar() != '/' && path.lastChar() != '\\')
-		path += '/';
-	AbstractFSNode *originalNode = g_system->getFilesystemFactory()->makeFileNodePath(path + filename);
-	if (!HandlerUtils::permittedPath(originalNode->getPath())) {
+	Common::Path path = _parentDirectoryPath.appendComponent(filename);
+	Common::FSNode originalNode(path);
+	if (!HandlerUtils::permittedPath(originalNode.getPath())) {
 		setErrorMessageHandler(*client, Common::convertFromU32String(_("Invalid path!")));
 		return;
 	}
-	if (originalNode->exists()) {
+	if (originalNode.exists()) {
 		setErrorMessageHandler(*client, Common::convertFromU32String(_("There is a file with that name in the parent directory!")));
 		return;
 	}
@@ -149,7 +146,7 @@ void UploadFileClientHandler::handleBlockHeaders(Client *client) {
 
 	// create file stream (and necessary subdirectories)
 	Common::DumpFile *f = new Common::DumpFile();
-	if (!f->open(originalNode->getPath(), true)) {
+	if (!f->open(originalNode.getPath(), true)) {
 		delete f;
 		setErrorMessageHandler(*client, Common::convertFromU32String(_("Failed to upload the file!")));
 		return;
diff --git a/backends/networking/sdl_net/uploadfileclienthandler.h b/backends/networking/sdl_net/uploadfileclienthandler.h
index 2ebb5642086..ef14826a12a 100644
--- a/backends/networking/sdl_net/uploadfileclienthandler.h
+++ b/backends/networking/sdl_net/uploadfileclienthandler.h
@@ -23,6 +23,7 @@
 #define BACKENDS_NETWORKING_SDL_NET_UPLOADFILECLIENTHANDLER_H
 
 #include "backends/networking/sdl_net/client.h"
+#include "common/path.h"
 #include "common/stream.h"
 
 namespace Networking {
@@ -49,7 +50,7 @@ class UploadFileClientHandler: public ClientHandler {
 	UploadFileHandlerState _state;
 	Common::MemoryReadWriteStream *_headersStream;
 	Common::WriteStream *_contentStream;
-	Common::String _parentDirectoryPath;
+	Common::Path _parentDirectoryPath;
 	uint32 _uploadedFiles;
 
 	void handleBlockHeaders(Client *client);
@@ -58,7 +59,7 @@ class UploadFileClientHandler: public ClientHandler {
 	void setSuccessHandler(Client &client);
 
 public:
-	UploadFileClientHandler(const Common::String &parentDirectoryPath);
+	UploadFileClientHandler(const Common::Path &parentDirectoryPath);
 	~UploadFileClientHandler() override;
 
 	void handle(Client *client) override;


Commit: e689166a2c561bd10d7cf3f4531afe7ed704dc2d
    https://github.com/scummvm/scummvm/commit/e689166a2c561bd10d7cf3f4531afe7ed704dc2d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: Make screenshots use the Path class

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h
    backends/graphics/sdl/sdl-graphics.cpp
    backends/graphics/sdl/sdl-graphics.h
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp
    backends/graphics/surfacesdl/surfacesdl-graphics.h
    backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
    backends/graphics3d/openglsdl/openglsdl-graphics3d.h
    backends/platform/sdl/kolibrios/kolibrios.cpp
    backends/platform/sdl/kolibrios/kolibrios.h
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx.h
    backends/platform/sdl/posix/posix.cpp
    backends/platform/sdl/posix/posix.h
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h
    backends/platform/sdl/win32/win32.cpp
    backends/platform/sdl/win32/win32.h


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index e35eebfd41a..85cd020f9f1 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -1739,7 +1739,7 @@ const Graphics::Font *OpenGLGraphicsManager::getFontOSD() const {
 }
 #endif
 
-bool OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const {
+bool OpenGLGraphicsManager::saveScreenshot(const Common::Path &filename) const {
 	const uint width  = _windowWidth;
 	const uint height = _windowHeight;
 
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index cdedb1d0d81..659b9b65464 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -286,7 +286,7 @@ protected:
 	 * @param filename The output filename.
 	 * @return true on success, false otherwise
 	 */
-	bool saveScreenshot(const Common::String &filename) const;
+	bool saveScreenshot(const Common::Path &filename) const;
 
 	// Do not hide the argument-less saveScreenshot from the base class
 	using WindowedGraphicsManager::saveScreenshot;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index b5a78517608..aae6035c19b 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -449,7 +449,7 @@ void OpenGLSdlGraphicsManager::handleResizeImpl(const int width, const int heigh
 	SdlGraphicsManager::handleResizeImpl(width, height);
 }
 
-bool OpenGLSdlGraphicsManager::saveScreenshot(const Common::String &filename) const {
+bool OpenGLSdlGraphicsManager::saveScreenshot(const Common::Path &filename) const {
 	return OpenGLGraphicsManager::saveScreenshot(filename);
 }
 
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index 322138e2cb5..712ca26c540 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -57,7 +57,7 @@ protected:
 
 	void handleResizeImpl(const int width, const int height) override;
 
-	bool saveScreenshot(const Common::String &filename) const override;
+	bool saveScreenshot(const Common::Path &filename) const override;
 
 private:
 	bool setupMode(uint width, uint height);
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index e007defccef..ec25f84d576 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -328,7 +328,7 @@ bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint3
 void SdlGraphicsManager::saveScreenshot() {
 	Common::String filename;
 
-	Common::String screenshotsPath;
+	Common::Path screenshotsPath;
 	OSystem_SDL *sdl_g_system = dynamic_cast<OSystem_SDL*>(g_system);
 	if (sdl_g_system)
 		screenshotsPath = sdl_g_system->getScreenshotsPath();
@@ -346,17 +346,18 @@ void SdlGraphicsManager::saveScreenshot() {
 		filename = Common::String::format("scummvm%s%s-%05d.%s", currentTarget.empty() ? "" : "-",
 		                                  currentTarget.c_str(), n, extension);
 
-		Common::FSNode file = Common::FSNode(screenshotsPath + filename);
+		Common::FSNode file = Common::FSNode(screenshotsPath.appendComponent(filename));
 		if (!file.exists()) {
 			break;
 		}
 	}
 
-	if (saveScreenshot(screenshotsPath + filename)) {
+	if (saveScreenshot(screenshotsPath.appendComponent(filename))) {
 		if (screenshotsPath.empty())
 			debug("Saved screenshot '%s' in current directory", filename.c_str());
 		else
-			debug("Saved screenshot '%s' in directory '%s'", filename.c_str(), screenshotsPath.c_str());
+			debug("Saved screenshot '%s' in directory '%s'", filename.c_str(),
+					screenshotsPath.toString(Common::Path::kNativeSeparator).c_str());
 
 #ifdef USE_OSD
 		if (!ConfMan.getBool("disable_saved_screenshot_osd"))
@@ -366,7 +367,7 @@ void SdlGraphicsManager::saveScreenshot() {
 		if (screenshotsPath.empty())
 			warning("Could not save screenshot in current directory");
 		else
-			warning("Could not save screenshot in directory '%s'", screenshotsPath.c_str());
+			warning("Could not save screenshot in directory '%s'", screenshotsPath.toString(Common::Path::kNativeSeparator).c_str());
 
 #ifdef USE_OSD
 		displayMessageOnOSD(_("Could not save screenshot"));
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index a391bc59fad..a846c500ab4 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -94,7 +94,7 @@ public:
 	virtual bool showMouse(bool visible) override;
 	bool lockMouse(bool lock) override;
 
-	virtual bool saveScreenshot(const Common::String &filename) const { return false; }
+	virtual bool saveScreenshot(const Common::Path &filename) const { return false; }
 	void saveScreenshot() override;
 
 	// Override from Common::EventObserver
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 6d9d8d062dd..ec40c7918b1 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -1526,7 +1526,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
 #endif
 }
 
-bool SurfaceSdlGraphicsManager::saveScreenshot(const Common::String &filename) const {
+bool SurfaceSdlGraphicsManager::saveScreenshot(const Common::Path &filename) const {
 	assert(_hwScreen != nullptr);
 
 	Common::StackLock lock(_graphicsMutex);
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 25f00da2ddc..57afc8f0622 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -434,7 +434,7 @@ protected:
 	void setFilteringMode(bool enable);
 	void setVSync(bool enable);
 
-	bool saveScreenshot(const Common::String &filename) const override;
+	bool saveScreenshot(const Common::Path &filename) const override;
 	virtual void setGraphicsModeIntern();
 	virtual void getDefaultResolution(uint &w, uint &h);
 
diff --git a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp b/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
index 81c53b3cf4b..e1974ba4f87 100644
--- a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
+++ b/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
@@ -789,7 +789,7 @@ void OpenGLSdlGraphics3dManager::deinitializeRenderer() {
 }
 #endif // SDL_VERSION_ATLEAST(2, 0, 0)
 
-bool OpenGLSdlGraphics3dManager::saveScreenshot(const Common::String &filename) const {
+bool OpenGLSdlGraphics3dManager::saveScreenshot(const Common::Path &filename) const {
 	// Largely based on the implementation from ScummVM
 	uint width = _overlayScreen->getWidth();
 	uint height = _overlayScreen->getHeight();
diff --git a/backends/graphics3d/openglsdl/openglsdl-graphics3d.h b/backends/graphics3d/openglsdl/openglsdl-graphics3d.h
index 6fc94e5d9ea..d83e19715cc 100644
--- a/backends/graphics3d/openglsdl/openglsdl-graphics3d.h
+++ b/backends/graphics3d/openglsdl/openglsdl-graphics3d.h
@@ -151,7 +151,7 @@ protected:
 
 	void handleResizeImpl(const int width, const int height) override;
 
-	bool saveScreenshot(const Common::String &filename) const override;
+	bool saveScreenshot(const Common::Path &filename) const override;
 
 	uint _engineRequestedWidth, _engineRequestedHeight;
 
diff --git a/backends/platform/sdl/kolibrios/kolibrios.cpp b/backends/platform/sdl/kolibrios/kolibrios.cpp
index bc777f11d61..4cf2448cb3e 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.cpp
+++ b/backends/platform/sdl/kolibrios/kolibrios.cpp
@@ -93,19 +93,19 @@ Common::String OSystem_KolibriOS::getDefaultIconsPath() {
 	return _exePath.join("icons").toString();
 }
 
-Common::String OSystem_KolibriOS::getScreenshotsPath() {
+Common::Path OSystem_KolibriOS::getScreenshotsPath() {
 	// If the user has configured a screenshots path, use it
-	const Common::String path = OSystem_SDL::getScreenshotsPath();
+	const Common::Path path = OSystem_SDL::getScreenshotsPath();
 	if (!path.empty()) {
 		return path;
 	}
 
 	static const char *SCREENSHOTS_DIR_NAME = "ScummVM Screenshots";
-	if (!KolibriOS::assureDirectoryExists(SCREENSHOTS_DIR_NAME, _writablePath.toString().c_str())) {
+	if (!KolibriOS::assureDirectoryExists(SCREENSHOTS_DIR_NAME, _writablePath.toString(Common::Path::kNativeSeparator).c_str())) {
 		return "";
 	}
 
-	return _writablePath.join(SCREENSHOTS_DIR_NAME).toString();
+	return _writablePath.join(SCREENSHOTS_DIR_NAME);
 }
 
 Common::Path OSystem_KolibriOS::getDefaultLogFileName() {
diff --git a/backends/platform/sdl/kolibrios/kolibrios.h b/backends/platform/sdl/kolibrios/kolibrios.h
index 44e39b1cbae..5d6492fc5d5 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.h
+++ b/backends/platform/sdl/kolibrios/kolibrios.h
@@ -33,7 +33,7 @@ public:
 
 	// Default paths
 	Common::String getDefaultIconsPath() override;
-	Common::String getScreenshotsPath() override;
+	Common::Path getScreenshotsPath() override;
 	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
 	const Common::Path& getExePath() const { return _exePath; }
 
diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index f462e842fc0..eae539590b5 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -272,15 +272,13 @@ Common::Path OSystem_MacOSX::getDefaultDLCsPath() {
 	return defaultDLCsPath;
 }
 
-Common::String OSystem_MacOSX::getScreenshotsPath() {
+Common::Path OSystem_MacOSX::getScreenshotsPath() {
 	// If the user has configured a screenshots path, use it
-	const Common::String path = OSystem_SDL::getScreenshotsPath();
+	const Common::Path path = OSystem_SDL::getScreenshotsPath();
 	if (!path.empty())
 		return path;
 
-	Common::String desktopPath = getDesktopPathMacOSX();
-	if (!desktopPath.empty() && !desktopPath.hasSuffix("/"))
-		desktopPath += "/";
+	Common::Path desktopPath(getDesktopPathMacOSX(), Common::Path::kNativeSeparator);
 	return desktopPath;
 }
 
diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h
index eb2eaa72cf4..1bf75730940 100644
--- a/backends/platform/sdl/macosx/macosx.h
+++ b/backends/platform/sdl/macosx/macosx.h
@@ -52,7 +52,7 @@ public:
 	// Default paths
 	Common::String getDefaultIconsPath() override;
 	Common::Path getDefaultDLCsPath() override;
-	Common::String getScreenshotsPath() override;
+	Common::Path getScreenshotsPath() override;
 
 protected:
 	Common::Path getDefaultConfigFileName() override;
diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index 81f55f51446..076a24d481c 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -283,9 +283,9 @@ Common::Path OSystem_POSIX::getDefaultDLCsPath() {
 	return dlcsPath;
 }
 
-Common::String OSystem_POSIX::getScreenshotsPath() {
+Common::Path OSystem_POSIX::getScreenshotsPath() {
 	// If the user has configured a screenshots path, use it
-	const Common::String path = OSystem_SDL::getScreenshotsPath();
+	const Common::Path path = OSystem_SDL::getScreenshotsPath();
 	if (!path.empty()) {
 		return path;
 	}
@@ -307,7 +307,7 @@ Common::String OSystem_POSIX::getScreenshotsPath() {
 		return "";
 	}
 
-	return picturesPath + SCREENSHOTS_DIR_NAME + "/";
+	return Common::Path(picturesPath).join(SCREENSHOTS_DIR_NAME);
 }
 
 void OSystem_POSIX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
diff --git a/backends/platform/sdl/posix/posix.h b/backends/platform/sdl/posix/posix.h
index 0568fa2772d..ea1671caf67 100644
--- a/backends/platform/sdl/posix/posix.h
+++ b/backends/platform/sdl/posix/posix.h
@@ -38,7 +38,7 @@ public:
 	// Default paths
 	Common::String getDefaultIconsPath() override;
 	Common::Path getDefaultDLCsPath() override;
-	Common::String getScreenshotsPath() override;
+	Common::Path getScreenshotsPath() override;
 
 protected:
 	Common::Path getDefaultConfigFileName() override;
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index e920b6b55e0..caa11a9bae9 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -814,11 +814,8 @@ Common::Path OSystem_SDL::getDefaultDLCsPath() {
 }
 
 //Not specified in base class
-Common::String OSystem_SDL::getScreenshotsPath() {
-	Common::String path = ConfMan.get("screenshotpath");
-	if (!path.empty() && !path.hasSuffix("/"))
-		path += "/";
-	return path;
+Common::Path OSystem_SDL::getScreenshotsPath() {
+	return ConfMan.getPath("screenshotpath");
 }
 
 #ifdef USE_OPENGL
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 52c9da91f40..292195cec37 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -94,7 +94,7 @@ public:
 	// Default paths
 	virtual Common::String getDefaultIconsPath();
 	virtual Common::Path getDefaultDLCsPath();
-	virtual Common::String getScreenshotsPath();
+	virtual Common::Path getScreenshotsPath();
 
 #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
 	Common::Array<uint> getSupportedAntiAliasingLevels() const override;
diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp
index 6781f3085ac..86c488584c2 100644
--- a/backends/platform/sdl/win32/win32.cpp
+++ b/backends/platform/sdl/win32/win32.cpp
@@ -292,12 +292,10 @@ Common::Path OSystem_Win32::getDefaultDLCsPath() {
 	return Common::Path(Win32::tcharToString(dlcsPath));
 }
 
-Common::String OSystem_Win32::getScreenshotsPath() {
+Common::Path OSystem_Win32::getScreenshotsPath() {
 	// If the user has configured a screenshots path, use it
-	Common::String screenshotsPath = ConfMan.get("screenshotpath");
+	Common::Path screenshotsPath = ConfMan.getPath("screenshotpath");
 	if (!screenshotsPath.empty()) {
-		if (!screenshotsPath.hasSuffix("\\") && !screenshotsPath.hasSuffix("/"))
-			screenshotsPath += "\\";
 		return screenshotsPath;
 	}
 
@@ -312,7 +310,7 @@ Common::String OSystem_Win32::getScreenshotsPath() {
 			if (hr != E_NOTIMPL) {
 				warning("Unable to locate My Pictures directory");
 			}
-			return Common::String();
+			return Common::Path();
 		}
 		_tcscat(picturesPath, TEXT("\\ScummVM Screenshots\\"));
 	}
@@ -324,7 +322,7 @@ Common::String OSystem_Win32::getScreenshotsPath() {
 			error("Cannot create ScummVM Screenshots folder");
 	}
 
-	return Win32::tcharToString(picturesPath);
+	return Common::Path(Win32::tcharToString(picturesPath), Common::Path::kNativeSeparator);
 }
 
 Common::Path OSystem_Win32::getDefaultConfigFileName() {
diff --git a/backends/platform/sdl/win32/win32.h b/backends/platform/sdl/win32/win32.h
index 29934213747..0f3bc9e3f10 100644
--- a/backends/platform/sdl/win32/win32.h
+++ b/backends/platform/sdl/win32/win32.h
@@ -51,7 +51,7 @@ public:
 	// Default paths
 	Common::String getDefaultIconsPath() override;
 	Common::Path getDefaultDLCsPath() override;
-	Common::String getScreenshotsPath() override;
+	Common::Path getScreenshotsPath() override;
 
 protected:
 	Common::Path getDefaultConfigFileName() override;


Commit: b97da068760002d7ee848f45a73124e0d470e395
    https://github.com/scummvm/scummvm/commit/b97da068760002d7ee848f45a73124e0d470e395
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make taskbar use Path

Changed paths:
    backends/taskbar/macosx/macosx-taskbar.mm
    backends/taskbar/win32/win32-taskbar.cpp
    common/taskbar.h


diff --git a/backends/taskbar/macosx/macosx-taskbar.mm b/backends/taskbar/macosx/macosx-taskbar.mm
index 4255931352e..91f09d17077 100644
--- a/backends/taskbar/macosx/macosx-taskbar.mm
+++ b/backends/taskbar/macosx/macosx-taskbar.mm
@@ -125,13 +125,13 @@ void MacOSXTaskbarManager::setOverlayIcon(const Common::String &name, const Comm
 		return;
 	}
 
-	Common::String path = getIconPath(name, ".png");
+	Common::Path path = getIconPath(name, ".png");
 	if (path.empty())
 		return;
 
 	initOverlayIconView();
 
-	CFStringRef imageFile = CFStringCreateWithCString(0, path.c_str(), kCFStringEncodingASCII);
+	CFStringRef imageFile = CFStringCreateWithCString(0, path.toString(Common::Path::kNativeSeparator).c_str(), kCFStringEncodingASCII);
 	NSImage *image = [[NSImage alloc] initWithContentsOfFile:(NSString *)imageFile];
 	[_overlayIconView setImage:image];
 	[image release];
@@ -232,9 +232,9 @@ void MacOSXTaskbarManager::addRecent(const Common::String &name, const Common::S
 	[dict setObject:(NSString *)desc forKey:@"description"];
 
 	// Icon
-	Common::String iconPath = getIconPath(name, ".png");
+	Common::Path iconPath = getIconPath(name, ".png");
 	if (!iconPath.empty()) {
-		CFStringRef icon = CFStringCreateWithCString(0, iconPath.c_str(), kCFStringEncodingASCII);
+		CFStringRef icon = CFStringCreateWithCString(0, iconPath.toString(Common::Path::kNativeSeparator).c_str(), kCFStringEncodingASCII);
 		[dict setObject:(NSString *)icon forKey:@"icon"];
 		CFRelease(icon);
 	}
diff --git a/backends/taskbar/win32/win32-taskbar.cpp b/backends/taskbar/win32/win32-taskbar.cpp
index 1d147343179..50c3b94d1f3 100644
--- a/backends/taskbar/win32/win32-taskbar.cpp
+++ b/backends/taskbar/win32/win32-taskbar.cpp
@@ -121,11 +121,11 @@ void Win32TaskbarManager::setOverlayIcon(const Common::String &name, const Commo
 	}
 
 	// Compute full icon path
-	Common::String iconPath = getIconPath(name, ".ico");
+	Common::Path iconPath = getIconPath(name, ".ico");
 	if (iconPath.empty())
 		return;
 
-	TCHAR *tIconPath = Win32::stringToTchar(iconPath);
+	TCHAR *tIconPath = Win32::stringToTchar(iconPath.toString(Common::Path::kNativeSeparator));
 	HICON pIcon = (HICON)::LoadImage(nullptr, tIconPath, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
 	free(tIconPath);
 	if (!pIcon) {
@@ -298,11 +298,11 @@ void Win32TaskbarManager::addRecent(const Common::String &name, const Common::St
 		link->SetPath(path);
 		link->SetArguments(game);
 
-		Common::String iconPath = getIconPath(name, ".ico");
+		Common::Path iconPath = getIconPath(name, ".ico");
 		if (iconPath.empty()) {
 			link->SetIconLocation(path, 0); // No game-specific icon available
 		} else {
-			LPWSTR icon = Win32::ansiToUnicode(iconPath.c_str());
+			LPWSTR icon = Win32::ansiToUnicode(iconPath.toString(Common::Path::kNativeSeparator).c_str());
 
 			link->SetIconLocation(icon, 0);
 
diff --git a/common/taskbar.h b/common/taskbar.h
index 00c569460a8..3483ad96183 100644
--- a/common/taskbar.h
+++ b/common/taskbar.h
@@ -154,7 +154,7 @@ protected:
 	 * @param   extension  The icon extension
 	 * @return  The icon path (or "" if no icon was found)
 	 */
-	Common::String getIconPath(const Common::String &target, const Common::String &extension) {
+	Common::Path getIconPath(const Common::String &target, const Common::String &extension) {
 		// We first try to look for a iconspath configuration variable then
 		// fallback to the extra path
 		//
@@ -196,7 +196,7 @@ return (path); \
 		}
 #undef TRY_ICON_PATH
 
-		return "";
+		return Common::Path();
 	}
 };
 


Commit: dc7fadef28f97567e2b9c987da68c5c79026ca42
    https://github.com/scummvm/scummvm/commit/dc7fadef28f97567e2b9c987da68c5c79026ca42
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make iconspath a Path object

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/sdl/kolibrios/kolibrios.cpp
    backends/platform/sdl/kolibrios/kolibrios.h
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx.h
    backends/platform/sdl/posix/posix.cpp
    backends/platform/sdl/posix/posix.h
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h
    backends/platform/sdl/win32/win32.cpp
    backends/platform/sdl/win32/win32.h
    common/taskbar.h
    common/zip-set.cpp
    gui/downloadpacksdialog.cpp


diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index f1731d86e3f..5c562140bbb 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -542,9 +542,9 @@ void OSystem_Android::initBackend() {
 	LOGD("Setting DefaultSaveFileManager path to: %s", ConfMan.get("savepath").c_str());
 
 
-	ConfMan.registerDefault("iconspath", basePath + "/icons");
+	ConfMan.registerDefault("iconspath", Common::Path(basePath, Common::Path::kNativeSeparator).joinInPlace("icons"));
 	// TODO remove the debug message eventually
-	LOGD("Setting Default Icons and Shaders path to: %s", ConfMan.get("iconspath").c_str());
+	LOGD("Setting Default Icons and Shaders path to: %s", ConfMan.getPath("iconspath").toString(Common::Path::kNativeSeparator).c_str());
 
 	_timerManager = new DefaultTimerManager();
 
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index 18f472ccd66..7d5d28510be 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -137,7 +137,7 @@ void OSystem_iOS7::initBackend() {
 
 	setTimerCallback(&OSystem_iOS7::timerHandler, 10);
 
-	ConfMan.registerDefault("iconspath", "/");
+	ConfMan.registerDefault("iconspath", Common::Path("/"));
 
 	EventsBaseBackend::initBackend();
 }
diff --git a/backends/platform/sdl/kolibrios/kolibrios.cpp b/backends/platform/sdl/kolibrios/kolibrios.cpp
index 4cf2448cb3e..904271f6f8e 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.cpp
+++ b/backends/platform/sdl/kolibrios/kolibrios.cpp
@@ -89,8 +89,8 @@ Common::Path OSystem_KolibriOS::getDefaultConfigFileName() {
 	return _writablePath.join("scummvm.ini");
 }
 
-Common::String OSystem_KolibriOS::getDefaultIconsPath() {
-	return _exePath.join("icons").toString();
+Common::Path OSystem_KolibriOS::getDefaultIconsPath() {
+	return _exePath.join("icons");
 }
 
 Common::Path OSystem_KolibriOS::getScreenshotsPath() {
diff --git a/backends/platform/sdl/kolibrios/kolibrios.h b/backends/platform/sdl/kolibrios/kolibrios.h
index 5d6492fc5d5..34eeba61d95 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.h
+++ b/backends/platform/sdl/kolibrios/kolibrios.h
@@ -32,7 +32,7 @@ public:
 	void initBackend() override;
 
 	// Default paths
-	Common::String getDefaultIconsPath() override;
+	Common::Path getDefaultIconsPath() override;
 	Common::Path getScreenshotsPath() override;
 	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority) override;
 	const Common::Path& getExePath() const { return _exePath; }
diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index eae539590b5..689cbeb6736 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -252,14 +252,14 @@ Common::Path OSystem_MacOSX::getDefaultLogFileName() {
 	return Common::Path(prefix).join(Common::String("Library/Logs/") + appName + ".log");
 }
 
-Common::String OSystem_MacOSX::getDefaultIconsPath() {
+Common::Path OSystem_MacOSX::getDefaultIconsPath() {
 	const Common::String defaultIconsPath = getAppSupportPathMacOSX() + "/Icons";
 
 	if (!Posix::assureDirectoryExists(defaultIconsPath)) {
-		return Common::String();
+		return Common::Path();
 	}
 
-	return defaultIconsPath;
+	return Common::Path(defaultIconsPath);
 }
 
 Common::Path OSystem_MacOSX::getDefaultDLCsPath() {
diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h
index 1bf75730940..89bc1b62417 100644
--- a/backends/platform/sdl/macosx/macosx.h
+++ b/backends/platform/sdl/macosx/macosx.h
@@ -50,7 +50,7 @@ public:
 #endif
 
 	// Default paths
-	Common::String getDefaultIconsPath() override;
+	Common::Path getDefaultIconsPath() override;
 	Common::Path getDefaultDLCsPath() override;
 	Common::Path getScreenshotsPath() override;
 
diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index 076a24d481c..b79d2837a59 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -235,7 +235,7 @@ Common::String OSystem_POSIX::getXdgUserDir(const char *name) {
 	return directoryPath;
 }
 
-Common::String OSystem_POSIX::getDefaultIconsPath() {
+Common::Path OSystem_POSIX::getDefaultIconsPath() {
 	Common::String iconsPath;
 
 	// On POSIX systems we follow the XDG Base Directory Specification for
@@ -257,7 +257,7 @@ Common::String OSystem_POSIX::getDefaultIconsPath() {
 		return Common::String();
 	}
 
-	return Common::String::format("%s/%s", prefix, iconsPath.c_str());
+	return Common::Path(prefix).join(iconsPath);
 }
 
 Common::Path OSystem_POSIX::getDefaultDLCsPath() {
diff --git a/backends/platform/sdl/posix/posix.h b/backends/platform/sdl/posix/posix.h
index ea1671caf67..a86e3196cf0 100644
--- a/backends/platform/sdl/posix/posix.h
+++ b/backends/platform/sdl/posix/posix.h
@@ -36,7 +36,7 @@ public:
 	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0) override;
 
 	// Default paths
-	Common::String getDefaultIconsPath() override;
+	Common::Path getDefaultIconsPath() override;
 	Common::Path getDefaultDLCsPath() override;
 	Common::Path getScreenshotsPath() override;
 
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index caa11a9bae9..674e22ecc06 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -800,11 +800,8 @@ uint32 OSystem_SDL::getDoubleClickTime() const {
 }
 
 //Not specified in base class
-Common::String OSystem_SDL::getDefaultIconsPath() {
-	Common::String path = ConfMan.get("iconspath");
-	if (!path.empty() && !path.hasSuffix("/"))
-		path += "/";
-	return path;
+Common::Path OSystem_SDL::getDefaultIconsPath() {
+	return ConfMan.getPath("iconspath");
 }
 
 // Not specified in base class
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 292195cec37..d15559c6d3f 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -92,7 +92,7 @@ public:
 	uint32 getDoubleClickTime() const override;
 
 	// Default paths
-	virtual Common::String getDefaultIconsPath();
+	virtual Common::Path getDefaultIconsPath();
 	virtual Common::Path getDefaultDLCsPath();
 	virtual Common::Path getScreenshotsPath();
 
diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp
index 86c488584c2..e3cd617fd36 100644
--- a/backends/platform/sdl/win32/win32.cpp
+++ b/backends/platform/sdl/win32/win32.cpp
@@ -256,7 +256,7 @@ Common::String OSystem_Win32::getSystemLanguage() const {
 	return OSystem_SDL::getSystemLanguage();
 }
 
-Common::String OSystem_Win32::getDefaultIconsPath() {
+Common::Path OSystem_Win32::getDefaultIconsPath() {
 	TCHAR iconsPath[MAX_PATH];
 
 	if (_isPortable) {
@@ -265,13 +265,13 @@ Common::String OSystem_Win32::getDefaultIconsPath() {
 	} else {
 		// Use the Application Data directory of the user profile
 		if (!Win32::getApplicationDataDirectory(iconsPath)) {
-			return Common::String();
+			return Common::Path();
 		}
 		_tcscat(iconsPath, TEXT("\\Icons\\"));
 		CreateDirectory(iconsPath, nullptr);
 	}
 
-	return Win32::tcharToString(iconsPath);
+	return Common::Path(Win32::tcharToString(iconsPath), Common::Path::kNativeSeparator);
 }
 
 Common::Path OSystem_Win32::getDefaultDLCsPath() {
diff --git a/backends/platform/sdl/win32/win32.h b/backends/platform/sdl/win32/win32.h
index 0f3bc9e3f10..89324e6e20c 100644
--- a/backends/platform/sdl/win32/win32.h
+++ b/backends/platform/sdl/win32/win32.h
@@ -49,7 +49,7 @@ public:
 	Common::String getSystemLanguage() const override;
 
 	// Default paths
-	Common::String getDefaultIconsPath() override;
+	Common::Path getDefaultIconsPath() override;
 	Common::Path getDefaultDLCsPath() override;
 	Common::Path getScreenshotsPath() override;
 
diff --git a/common/taskbar.h b/common/taskbar.h
index 3483ad96183..274a8f3b991 100644
--- a/common/taskbar.h
+++ b/common/taskbar.h
@@ -160,7 +160,7 @@ protected:
 		//
 		// Icons can be either in a subfolder named "icons" or directly in the path
 
-		Common::String iconsPath = ConfMan.get("iconspath");
+		Common::Path iconsPath = ConfMan.getPath("iconspath");
 		Common::String extraPath = ConfMan.get("extrapath");
 
 		Common::String targetIcon = target + extension;
@@ -174,14 +174,14 @@ if (node.exists()) \
 return (path); \
 }
 		if (!iconsPath.empty()) {
-			TRY_ICON_PATH(iconsPath + "/" + targetIcon);
-			TRY_ICON_PATH(iconsPath + "/" + qualifiedIcon);
-			TRY_ICON_PATH(iconsPath + "/" + gameIcon);
-			TRY_ICON_PATH(iconsPath + "/" + engineIcon);
-			TRY_ICON_PATH(iconsPath + "/icons/" + targetIcon);
-			TRY_ICON_PATH(iconsPath + "/icons/" + qualifiedIcon);
-			TRY_ICON_PATH(iconsPath + "/icons/" + gameIcon);
-			TRY_ICON_PATH(iconsPath + "/icons/" + engineIcon);
+			TRY_ICON_PATH(iconsPath.join(targetIcon));
+			TRY_ICON_PATH(iconsPath.join(qualifiedIcon));
+			TRY_ICON_PATH(iconsPath.join(gameIcon));
+			TRY_ICON_PATH(iconsPath.join(engineIcon));
+			TRY_ICON_PATH(iconsPath.join("icons/" + targetIcon));
+			TRY_ICON_PATH(iconsPath.join("icons/" + qualifiedIcon));
+			TRY_ICON_PATH(iconsPath.join("icons/" + gameIcon));
+			TRY_ICON_PATH(iconsPath.join("icons/" + engineIcon));
 		}
 
 		if (!extraPath.empty()) {
diff --git a/common/zip-set.cpp b/common/zip-set.cpp
index 8e45e00d1d2..0391aed0c55 100644
--- a/common/zip-set.cpp
+++ b/common/zip-set.cpp
@@ -70,7 +70,7 @@ bool generateZipSet(SearchSet &searchSet, const char *defaultFile, const char *p
 	if (!dat) {
 		File *file = new File;
 		if (ConfMan.hasKey(packsPath)) {
-			String path(normalizePath(ConfMan.get(packsPath) + "/" + defaultFile, '/'));
+			Path path(ConfMan.getPath(packsPath).join(defaultFile).normalize());
 
 			if (File::exists(path))
 				file->open(path);
diff --git a/gui/downloadpacksdialog.cpp b/gui/downloadpacksdialog.cpp
index cf1a0222c8f..ed02282c5b6 100644
--- a/gui/downloadpacksdialog.cpp
+++ b/gui/downloadpacksdialog.cpp
@@ -101,7 +101,7 @@ bool DialogState::takeOneFile() {
 	fileHash.erase(fname);
 
 	Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", fname.c_str());
-	Common::String localFile = normalizePath(ConfMan.get("iconspath") + "/" + fname, '/');
+	Common::Path localFile = ConfMan.getPath("iconspath").join(fname).normalize();
 
 	Networking::SessionRequest *rq = session.get(url, localFile,
 		new Common::Callback<DialogState, const Networking::DataResponse &>(this, &DialogState::downloadFileCallback),
@@ -390,7 +390,7 @@ void DownloadPacksDialog::setError(Common::U32String &msg) {
 }
 
 void DownloadPacksDialog::calculateList() {
-	Common::String iconsPath = ConfMan.get("iconspath");
+	Common::Path iconsPath = ConfMan.getPath("iconspath");
 	if (iconsPath.empty()) {
 		Common::U32String str(_("ERROR: No icons path set"));
 		setError(str);
@@ -435,7 +435,7 @@ void DownloadPacksDialog::calculateList() {
 }
 
 void DownloadPacksDialog::clearCache() {
-	Common::String iconsPath = ConfMan.get("iconspath");
+	Common::Path iconsPath = ConfMan.getPath("iconspath");
 	if (iconsPath.empty()) {
 		Common::U32String str(_("ERROR: No icons path set"));
 		setError(str);
@@ -469,7 +469,7 @@ void DownloadPacksDialog::clearCache() {
 		// Build list of previously downloaded icon files
 		for (auto ic = iconFiles.begin(); ic != iconFiles.end(); ++ic) {
 			Common::String fname = (*ic)->getName();
-			Common::FSNode fs(Common::Path(iconsPath).join(fname));
+			Common::FSNode fs(iconsPath.join(fname));
 			Common::WriteStream *str = fs.createWriteStream();
 
 			// Overwrite previously downloaded pack files with dummy data


Commit: bfc61439fbe905db10da7eda3d4e53d01b8647cd
    https://github.com/scummvm/scummvm/commit/bfc61439fbe905db10da7eda3d4e53d01b8647cd
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make themepath a Path object

Changed paths:
    backends/graphics/atari/atari-graphics.cpp
    backends/networking/sdl_net/handlerutils.cpp
    backends/platform/sdl/amigaos/amigaos.cpp
    backends/platform/sdl/kolibrios/kolibrios.cpp
    backends/platform/sdl/miyoo/miyoo.cpp
    backends/platform/sdl/opendingux/opendingux.cpp
    common/translation.cpp
    common/zip-set.cpp
    gui/ThemeEngine.cpp


diff --git a/backends/graphics/atari/atari-graphics.cpp b/backends/graphics/atari/atari-graphics.cpp
index c77dbaabbca..4df8b3a43a8 100644
--- a/backends/graphics/atari/atari-graphics.cpp
+++ b/backends/graphics/atari/atari-graphics.cpp
@@ -206,7 +206,7 @@ AtariGraphicsManager::AtariGraphicsManager() {
 #ifndef DISABLE_FANCY_THEMES
 	// make "themes" the default theme path
 	if (!ConfMan.hasKey("themepath"))
-		ConfMan.set("themepath", "themes");
+		ConfMan.setPath("themepath", "themes");
 #endif
 
 	ConfMan.flushToDisk();
diff --git a/backends/networking/sdl_net/handlerutils.cpp b/backends/networking/sdl_net/handlerutils.cpp
index b9789547654..f32d51814ac 100644
--- a/backends/networking/sdl_net/handlerutils.cpp
+++ b/backends/networking/sdl_net/handlerutils.cpp
@@ -38,7 +38,7 @@ namespace Networking {
 Common::Archive *HandlerUtils::getZipArchive() {
 	// first search in themepath
 	if (ConfMan.hasKey("themepath")) {
-		const Common::FSNode &node = Common::FSNode(ConfMan.get("themepath"));
+		const Common::FSNode &node = Common::FSNode(ConfMan.getPath("themepath"));
 		if (node.exists() && node.isReadable() && node.isDirectory()) {
 			Common::FSNode fileNode = node.getChild(ARCHIVE_NAME);
 			if (fileNode.exists() && fileNode.isReadable() && !fileNode.isDirectory()) {
diff --git a/backends/platform/sdl/amigaos/amigaos.cpp b/backends/platform/sdl/amigaos/amigaos.cpp
index ac45cce1afa..64cd279c89a 100644
--- a/backends/platform/sdl/amigaos/amigaos.cpp
+++ b/backends/platform/sdl/amigaos/amigaos.cpp
@@ -109,7 +109,7 @@ void OSystem_AmigaOS::initBackend() {
 	ConfMan.registerDefault("gui_theme", "scummremastered");
 	ConfMan.registerDefault("gui_scale", "125");
 	ConfMan.registerDefault("extrapath", "extras/");
-	ConfMan.registerDefault("themepath", "themes/");
+	ConfMan.registerDefault("themepath", Common::Path("themes/"));
 	// First time .ini defaults
 	if (!ConfMan.hasKey("audio_buffer_size")) {
 		ConfMan.set("audio_buffer_size", "2048");
@@ -139,7 +139,7 @@ void OSystem_AmigaOS::initBackend() {
 		ConfMan.set("extrapath", "extras/");
 	}
 	if (!ConfMan.hasKey("themepath")) {
-		ConfMan.set("themepath", "themes/");
+		ConfMan.setPath("themepath", "themes/");
 	}
 	OSystem_SDL::initBackend();
 }
diff --git a/backends/platform/sdl/kolibrios/kolibrios.cpp b/backends/platform/sdl/kolibrios/kolibrios.cpp
index 904271f6f8e..6a6e1999348 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.cpp
+++ b/backends/platform/sdl/kolibrios/kolibrios.cpp
@@ -65,13 +65,13 @@ void OSystem_KolibriOS::addSysArchivesToSearchSet(Common::SearchSet &s, int prio
 }
 
 void OSystem_KolibriOS::initBackend() {
-	Common::String defaultThemePath = _exePath.join("themes").toString();
+	Common::Path defaultThemePath = _exePath.join("themes");
 	Common::String defaultEngineData = _exePath.join("engine-data").toString();
 	ConfMan.registerDefault("themepath", defaultThemePath);
 	ConfMan.registerDefault("extrapath", defaultEngineData);
 
 	if (!ConfMan.hasKey("themepath")) {
-		ConfMan.set("themepath", defaultThemePath);
+		ConfMan.setPath("themepath", defaultThemePath);
 	}
 	if (!ConfMan.hasKey("extrapath")) {
 		ConfMan.set("extrapath", defaultEngineData);
diff --git a/backends/platform/sdl/miyoo/miyoo.cpp b/backends/platform/sdl/miyoo/miyoo.cpp
index 036041c38dc..4de97f3ffcc 100644
--- a/backends/platform/sdl/miyoo/miyoo.cpp
+++ b/backends/platform/sdl/miyoo/miyoo.cpp
@@ -151,7 +151,7 @@ void OSystem_SDL_Miyoo::init() {
 void OSystem_SDL_Miyoo::initBackend() {
 	ConfMan.registerDefault("fullscreen", true);
 	ConfMan.registerDefault("aspect_ratio", true);
-	ConfMan.registerDefault("themepath", "./themes");
+	ConfMan.registerDefault("themepath", Common::Path("./themes"));
 	ConfMan.registerDefault("extrapath", "./engine-data");
 	ConfMan.registerDefault("gui_theme", "builtin");
 	ConfMan.registerDefault("scale_factor", "1");
@@ -163,7 +163,7 @@ void OSystem_SDL_Miyoo::initBackend() {
 		ConfMan.setBool("aspect_ratio", true);
 	}
 	if (!ConfMan.hasKey("themepath")) {
-		ConfMan.set("themepath", "./themes");
+		ConfMan.setPath("themepath", "./themes");
 	}
 	if (!ConfMan.hasKey("extrapath")) {
 		ConfMan.set("extrapath", "./engine-data");
diff --git a/backends/platform/sdl/opendingux/opendingux.cpp b/backends/platform/sdl/opendingux/opendingux.cpp
index 4819d542f5b..7fe4fa1a9f4 100644
--- a/backends/platform/sdl/opendingux/opendingux.cpp
+++ b/backends/platform/sdl/opendingux/opendingux.cpp
@@ -119,7 +119,7 @@ void OSystem_SDL_Opendingux::initBackend() {
 	ConfMan.registerDefault("fullscreen", true);
 #endif
 	ConfMan.registerDefault("aspect_ratio", true);
-	ConfMan.registerDefault("themepath", "./themes");
+	ConfMan.registerDefault("themepath", Common::Path("./themes"));
 	ConfMan.registerDefault("extrapath", "./engine-data");
 	ConfMan.registerDefault("gui_theme", "builtin");
 	ConfMan.registerDefault("scale_factor", "1");
@@ -131,7 +131,7 @@ void OSystem_SDL_Opendingux::initBackend() {
 		ConfMan.setBool("aspect_ratio", true);
 	}
 	if (!ConfMan.hasKey("themepath")) {
-		ConfMan.set("themepath", "./themes");
+		ConfMan.setPath("themepath", "./themes");
 	}
 	if (!ConfMan.hasKey("extrapath")) {
 		ConfMan.set("extrapath", "./engine-data");
diff --git a/common/translation.cpp b/common/translation.cpp
index 74993fc1ac2..a1ea14f8b6e 100644
--- a/common/translation.cpp
+++ b/common/translation.cpp
@@ -222,7 +222,7 @@ String TranslationManager::getLangById(int id) const {
 
 bool TranslationManager::openTranslationsFile(File &inFile) {
 	// First look in the Themepath if we can find the file.
-	if (ConfMan.hasKey("themepath") && openTranslationsFile(FSNode(ConfMan.get("themepath")), inFile))
+	if (ConfMan.hasKey("themepath") && openTranslationsFile(FSNode(ConfMan.getPath("themepath")), inFile))
 		return true;
 
 	// Then try to open it using the SearchMan.
diff --git a/common/zip-set.cpp b/common/zip-set.cpp
index 0391aed0c55..3cf1d2e811e 100644
--- a/common/zip-set.cpp
+++ b/common/zip-set.cpp
@@ -60,7 +60,7 @@ bool generateZipSet(SearchSet &searchSet, const char *defaultFile, const char *p
 	dat = nullptr;
 
 	if (ConfMan.hasKey("themepath")) {
-		FSNode *fs = new FSNode(normalizePath(ConfMan.get("themepath") + "/" + defaultFile, '/'));
+		FSNode *fs = new FSNode(ConfMan.getPath("themepath").join(defaultFile).normalize());
 		if (fs->exists()) {
 			dat = makeZipArchive(*fs);
 		}
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index bffdcbd9de0..7e982ff4fed 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -1941,7 +1941,7 @@ void ThemeEngine::listUsableThemes(Common::List<ThemeDescriptor> &list) {
 #endif
 
 	if (ConfMan.hasKey("themepath"))
-		listUsableThemes(Common::FSNode(ConfMan.get("themepath")), list);
+		listUsableThemes(Common::FSNode(ConfMan.getPath("themepath")), list);
 
 	listUsableThemes(SearchMan, list);
 


Commit: 802c91554fbdf83820f85cedb67bbf92554d9d43
    https://github.com/scummvm/scummvm/commit/802c91554fbdf83820f85cedb67bbf92554d9d43
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make extrapath a Path object

Changed paths:
    backends/events/sdl/sdl-events.cpp
    backends/platform/sdl/amigaos/amigaos.cpp
    backends/platform/sdl/kolibrios/kolibrios.cpp
    backends/platform/sdl/miyoo/miyoo.cpp
    backends/platform/sdl/opendingux/opendingux.cpp
    backends/vkeybd/virtual-keyboard.cpp
    base/main.cpp
    common/taskbar.h
    engines/achievements.cpp
    graphics/fonts/ttf.cpp
    graphics/opengl/shader.cpp
    gui/gui-manager.cpp


diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index e69f694ecaa..8f8a4d2ac2a 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -58,13 +58,13 @@ void SdlEventSource::loadGameControllerMappingFile() {
 			warning("Game controller DB file not found: %s", file.getPath().c_str());
 	}
 	if (!loaded && ConfMan.hasKey("extrapath")) {
-		Common::FSNode dir = Common::FSNode(ConfMan.get("extrapath"));
+		Common::FSNode dir = Common::FSNode(ConfMan.getPath("extrapath"));
 		Common::FSNode file = dir.getChild(GAMECONTROLLERDB_FILE);
 		if (file.exists()) {
-			if (SDL_GameControllerAddMappingsFromFile(file.getPath().c_str()) < 0)
-				error("File %s not valid: %s", file.getPath().c_str(), SDL_GetError());
+			if (SDL_GameControllerAddMappingsFromFile(file.getPath().toString(Common::Path::kNativeSeparator).c_str()) < 0)
+				error("File %s not valid: %s", file.getPath().toString(Common::Path::kNativeSeparator).c_str(), SDL_GetError());
 			else
-				debug("Game controller DB file loaded: %s", file.getPath().c_str());
+				debug("Game controller DB file loaded: %s", file.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		}
 	}
 }
diff --git a/backends/platform/sdl/amigaos/amigaos.cpp b/backends/platform/sdl/amigaos/amigaos.cpp
index 64cd279c89a..1ea26a0eade 100644
--- a/backends/platform/sdl/amigaos/amigaos.cpp
+++ b/backends/platform/sdl/amigaos/amigaos.cpp
@@ -108,7 +108,7 @@ void OSystem_AmigaOS::initBackend() {
 	ConfMan.registerDefault("gui_mode", "antialias");
 	ConfMan.registerDefault("gui_theme", "scummremastered");
 	ConfMan.registerDefault("gui_scale", "125");
-	ConfMan.registerDefault("extrapath", "extras/");
+	ConfMan.registerDefault("extrapath", Common::Path("extras/"));
 	ConfMan.registerDefault("themepath", Common::Path("themes/"));
 	// First time .ini defaults
 	if (!ConfMan.hasKey("audio_buffer_size")) {
@@ -136,7 +136,7 @@ void OSystem_AmigaOS::initBackend() {
 		ConfMan.set("gui_scale", "125");
 	}
 	if (!ConfMan.hasKey("extrapath")) {
-		ConfMan.set("extrapath", "extras/");
+		ConfMan.setPath("extrapath", "extras/");
 	}
 	if (!ConfMan.hasKey("themepath")) {
 		ConfMan.setPath("themepath", "themes/");
diff --git a/backends/platform/sdl/kolibrios/kolibrios.cpp b/backends/platform/sdl/kolibrios/kolibrios.cpp
index 6a6e1999348..51ed11b44f1 100644
--- a/backends/platform/sdl/kolibrios/kolibrios.cpp
+++ b/backends/platform/sdl/kolibrios/kolibrios.cpp
@@ -66,7 +66,7 @@ void OSystem_KolibriOS::addSysArchivesToSearchSet(Common::SearchSet &s, int prio
 
 void OSystem_KolibriOS::initBackend() {
 	Common::Path defaultThemePath = _exePath.join("themes");
-	Common::String defaultEngineData = _exePath.join("engine-data").toString();
+	Common::Path defaultEngineData = _exePath.join("engine-data");
 	ConfMan.registerDefault("themepath", defaultThemePath);
 	ConfMan.registerDefault("extrapath", defaultEngineData);
 
@@ -74,7 +74,7 @@ void OSystem_KolibriOS::initBackend() {
 		ConfMan.setPath("themepath", defaultThemePath);
 	}
 	if (!ConfMan.hasKey("extrapath")) {
-		ConfMan.set("extrapath", defaultEngineData);
+		ConfMan.setPath("extrapath", defaultEngineData);
 	}
 
 	// Create the savefile manager
diff --git a/backends/platform/sdl/miyoo/miyoo.cpp b/backends/platform/sdl/miyoo/miyoo.cpp
index 4de97f3ffcc..d61e3031770 100644
--- a/backends/platform/sdl/miyoo/miyoo.cpp
+++ b/backends/platform/sdl/miyoo/miyoo.cpp
@@ -152,7 +152,7 @@ void OSystem_SDL_Miyoo::initBackend() {
 	ConfMan.registerDefault("fullscreen", true);
 	ConfMan.registerDefault("aspect_ratio", true);
 	ConfMan.registerDefault("themepath", Common::Path("./themes"));
-	ConfMan.registerDefault("extrapath", "./engine-data");
+	ConfMan.registerDefault("extrapath", Common::Path("./engine-data"));
 	ConfMan.registerDefault("gui_theme", "builtin");
 	ConfMan.registerDefault("scale_factor", "1");
 
@@ -166,7 +166,7 @@ void OSystem_SDL_Miyoo::initBackend() {
 		ConfMan.setPath("themepath", "./themes");
 	}
 	if (!ConfMan.hasKey("extrapath")) {
-		ConfMan.set("extrapath", "./engine-data");
+		ConfMan.setPath("extrapath", "./engine-data");
 	}
 	if (!ConfMan.hasKey("savepath")) {
 		ConfMan.set("savepath", SAVE_PATH);
diff --git a/backends/platform/sdl/opendingux/opendingux.cpp b/backends/platform/sdl/opendingux/opendingux.cpp
index 7fe4fa1a9f4..716fdcde71a 100644
--- a/backends/platform/sdl/opendingux/opendingux.cpp
+++ b/backends/platform/sdl/opendingux/opendingux.cpp
@@ -120,7 +120,7 @@ void OSystem_SDL_Opendingux::initBackend() {
 #endif
 	ConfMan.registerDefault("aspect_ratio", true);
 	ConfMan.registerDefault("themepath", Common::Path("./themes"));
-	ConfMan.registerDefault("extrapath", "./engine-data");
+	ConfMan.registerDefault("extrapath", Common::Path("./engine-data"));
 	ConfMan.registerDefault("gui_theme", "builtin");
 	ConfMan.registerDefault("scale_factor", "1");
 
@@ -134,7 +134,7 @@ void OSystem_SDL_Opendingux::initBackend() {
 		ConfMan.setPath("themepath", "./themes");
 	}
 	if (!ConfMan.hasKey("extrapath")) {
-		ConfMan.set("extrapath", "./engine-data");
+		ConfMan.setPath("extrapath", "./engine-data");
 	}
 	if (!ConfMan.hasKey("savepath")) {
 		ConfMan.set("savepath", SAVE_PATH);
diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp
index 4e9ccf190e6..8d00eed1a1b 100644
--- a/backends/vkeybd/virtual-keyboard.cpp
+++ b/backends/vkeybd/virtual-keyboard.cpp
@@ -120,7 +120,7 @@ bool VirtualKeyboard::loadKeyboardPack(const String &packName) {
 	if (ConfMan.hasKey("vkeybdpath"))
 		opened = openPack(packName, new FSDirectory(ConfMan.get("vkeybdpath")), DisposeAfterUse::YES);
 	else if (ConfMan.hasKey("extrapath"))
-		opened = openPack(packName, new FSDirectory(ConfMan.get("extrapath")), DisposeAfterUse::YES);
+		opened = openPack(packName, new FSDirectory(ConfMan.getPath("extrapath")), DisposeAfterUse::YES);
 
 	// fallback to SearchMan
 	if (!opened)
diff --git a/base/main.cpp b/base/main.cpp
index df1ed029c1b..27d5166397f 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -277,7 +277,7 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 
 	// Add extrapath (if any) to the directory search list
 	if (ConfMan.hasKey("extrapath")) {
-		dir = Common::FSNode(ConfMan.get("extrapath"));
+		dir = Common::FSNode(ConfMan.getPath("extrapath"));
 		SearchMan.addDirectory(dir);
 	}
 
@@ -286,9 +286,9 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 	// verify that it's not already there before adding it. The search manager will
 	// check for that too, so this check is mostly to avoid a warning message.
 	if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationDomain)) {
-		Common::String extraPath = ConfMan.get("extrapath", Common::ConfigManager::kApplicationDomain);
-		if (!SearchMan.hasArchive(extraPath)) {
-			dir = Common::FSNode(extraPath);
+		Common::Path extraPath = ConfMan.getPath("extrapath", Common::ConfigManager::kApplicationDomain);
+		dir = Common::FSNode(extraPath);
+		if (!SearchMan.hasArchive(dir.getPath().toString())) {
 			SearchMan.addDirectory(dir);
 		}
 	}
diff --git a/common/taskbar.h b/common/taskbar.h
index 274a8f3b991..1823c55290b 100644
--- a/common/taskbar.h
+++ b/common/taskbar.h
@@ -161,7 +161,7 @@ protected:
 		// Icons can be either in a subfolder named "icons" or directly in the path
 
 		Common::Path iconsPath = ConfMan.getPath("iconspath");
-		Common::String extraPath = ConfMan.get("extrapath");
+		Common::Path extraPath = ConfMan.getPath("extrapath");
 
 		Common::String targetIcon = target + extension;
 		Common::String qualifiedIcon = ConfMan.get("engineid") + "-" + ConfMan.get("gameid") + extension;
@@ -185,14 +185,14 @@ return (path); \
 		}
 
 		if (!extraPath.empty()) {
-			TRY_ICON_PATH(extraPath + "/" + targetIcon);
-			TRY_ICON_PATH(extraPath + "/" + qualifiedIcon);
-			TRY_ICON_PATH(extraPath + "/" + gameIcon);
-			TRY_ICON_PATH(extraPath + "/" + engineIcon);
-			TRY_ICON_PATH(extraPath + "/icons/" + targetIcon);
-			TRY_ICON_PATH(extraPath + "/icons/" + qualifiedIcon);
-			TRY_ICON_PATH(extraPath + "/icons/" + gameIcon);
-			TRY_ICON_PATH(extraPath + "/icons/" + engineIcon);
+			TRY_ICON_PATH(extraPath.join(targetIcon));
+			TRY_ICON_PATH(extraPath.join(qualifiedIcon));
+			TRY_ICON_PATH(extraPath.join(gameIcon));
+			TRY_ICON_PATH(extraPath.join(engineIcon));
+			TRY_ICON_PATH(extraPath.join("icons/" + targetIcon));
+			TRY_ICON_PATH(extraPath.join("icons/" + qualifiedIcon));
+			TRY_ICON_PATH(extraPath.join("icons/" + gameIcon));
+			TRY_ICON_PATH(extraPath.join("icons/" + engineIcon));
 		}
 #undef TRY_ICON_PATH
 
diff --git a/engines/achievements.cpp b/engines/achievements.cpp
index 4d1d99b0440..13c8b3b6591 100644
--- a/engines/achievements.cpp
+++ b/engines/achievements.cpp
@@ -101,7 +101,7 @@ bool AchievementsManager::loadAchievementsData(const char *platform, const char
 	Archive *cfgZip = nullptr;
 
 	if (!cfgZip && ConfMan.hasKey("extrapath")) {
-		Common::FSDirectory extrapath(ConfMan.get("extrapath"));
+		Common::FSDirectory extrapath(ConfMan.getPath("extrapath"));
 		cfgZip = Common::makeZipArchive(extrapath.createReadStreamForMember("achievements.dat"));
 	}
 
diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index 940d4b0c8bc..44d6638ef03 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -893,7 +893,7 @@ Font *loadTTFFont(Common::SeekableReadStream &stream, int size, TTFSizeMode size
 Font *loadTTFFontFromArchive(const Common::String &filename, int size, TTFSizeMode sizeMode, uint dpi, TTFRenderMode renderMode, const uint32 *mapping) {
 	Common::SeekableReadStream *archiveStream = nullptr;
 	if (ConfMan.hasKey("extrapath")) {
-		Common::FSDirectory extrapath(ConfMan.get("extrapath"));
+		Common::FSDirectory extrapath(ConfMan.getPath("extrapath"));
 		archiveStream = extrapath.createReadStreamForMember("fonts.dat");
 	}
 
@@ -914,7 +914,7 @@ Font *loadTTFFontFromArchive(const Common::String &filename, int size, TTFSizeMo
 
 		// Trying fonts-cjk.dat
 		if (ConfMan.hasKey("extrapath")) {
-			Common::FSDirectory extrapath(ConfMan.get("extrapath"));
+			Common::FSDirectory extrapath(ConfMan.getPath("extrapath"));
 			archiveStream = extrapath.createReadStreamForMember("fonts-cjk.dat");
 		}
 
diff --git a/graphics/opengl/shader.cpp b/graphics/opengl/shader.cpp
index 99f23e3c14a..e13a9bb06de 100644
--- a/graphics/opengl/shader.cpp
+++ b/graphics/opengl/shader.cpp
@@ -97,7 +97,7 @@ static const GLchar *readFile(const Common::String &filename) {
 #endif
 
 	if (ConfMan.hasKey("extrapath")) {
-		SearchMan.addDirectory("EXTRA_PATH", Common::FSNode(ConfMan.get("extrapath")), 0, 2);
+		SearchMan.addDirectory("EXTRA_PATH", Common::FSNode(ConfMan.getPath("extrapath")), 0, 2);
 	}
 #if !defined(IPHONE)
 	shaderDir = "shaders/";
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 3f5959352e5..34627ade5ba 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -975,8 +975,8 @@ Graphics::MacWindowManager *GuiManager::getWM() {
 		return _wm;
 
 	if (ConfMan.hasKey("extrapath")) {
-		Common::FSNode dir(ConfMan.get("extrapath"));
-		SearchMan.addDirectory(dir.getPath(), dir);
+		Common::FSNode dir(ConfMan.getPath("extrapath"));
+		SearchMan.addDirectory(dir);
 	}
 
 	uint32 wmMode = Graphics::kWMModeNoDesktop | Graphics::kWMMode32bpp | Graphics::kWMModeNoCursorOverride;


Commit: db5041ecb09d568527aea61512440e8890e8d37a
    https://github.com/scummvm/scummvm/commit/db5041ecb09d568527aea61512440e8890e8d37a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make savepath a Path object

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/sdl/miyoo/miyoo.cpp
    backends/platform/sdl/opendingux/opendingux.cpp
    backends/platform/sdl/riscos/riscos.cpp
    backends/saves/default/default-saves.cpp
    backends/saves/default/default-saves.h
    backends/saves/kolibrios/kolibrios-saves.cpp
    backends/saves/posix/posix-saves.cpp
    backends/saves/windows/windows-saves.cpp
    engines/ags/shared/util/stdio_compat.cpp


diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 5c562140bbb..f945cc183e1 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -138,10 +138,10 @@ void checkGlError(const char *expr, const char *file, int line) {
 
 class AndroidSaveFileManager : public DefaultSaveFileManager {
 public:
-	AndroidSaveFileManager(const Common::String &defaultSavepath) : DefaultSaveFileManager(defaultSavepath) {}
+	AndroidSaveFileManager(const Common::Path &defaultSavepath) : DefaultSaveFileManager(defaultSavepath) {}
 
 	bool removeSavefile(const Common::String &filename) override {
-		Common::String path = getSavePath() + "/" + filename;
+		Common::String path = getSavePath().join(filename).toString(Common::Path::kNativeSeparator);
 		AbstractFSNode *node = AndroidFilesystemFactory::instance().makeFileNodePath(path);
 
 		if (!node) {
@@ -537,9 +537,9 @@ void OSystem_Android::initBackend() {
 
 	Common::String basePath = JNI::getScummVMBasePath();
 
-	_savefileManager = new AndroidSaveFileManager(basePath + "/saves");
+	_savefileManager = new AndroidSaveFileManager(Common::Path(basePath, Common::Path::kNativeSeparator).joinInPlace("saves"));
 	// TODO remove the debug message eventually
-	LOGD("Setting DefaultSaveFileManager path to: %s", ConfMan.get("savepath").c_str());
+	LOGD("Setting DefaultSaveFileManager path to: %s", ConfMan.getPath("savepath").toString(Common::Path::kNativeSeparator).c_str());
 
 
 	ConfMan.registerDefault("iconspath", Common::Path(basePath, Common::Path::kNativeSeparator).joinInPlace("icons"));
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index 7d5d28510be..52b5b9fa4b7 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -65,23 +65,23 @@ SoundProc OSystem_iOS7::s_soundCallback = NULL;
 void *OSystem_iOS7::s_soundParam = NULL;
 
 class SandboxedSaveFileManager : public DefaultSaveFileManager {
-	Common::String _sandboxRootPath;
+	Common::Path _sandboxRootPath;
 public:
 
-	SandboxedSaveFileManager(Common::String sandboxRootPath, Common::String defaultSavepath)
+	SandboxedSaveFileManager(const Common::Path &sandboxRootPath, const Common::Path &defaultSavepath)
 			: DefaultSaveFileManager(defaultSavepath), _sandboxRootPath(sandboxRootPath) {
 	}
 
 	bool removeSavefile(const Common::String &filename) override {
-		Common::String chrootedFile = getSavePath() + "/" + filename;
-		Common::String realFilePath = _sandboxRootPath + chrootedFile;
+		Common::Path chrootedFile = getSavePath().join(filename);
+		Common::Path realFilePath = _sandboxRootPath.join(chrootedFile);
 
-		if (remove(realFilePath.c_str()) != 0) {
+		if (remove(realFilePath.toString(Common::Path::kNativeSeparator).c_str()) != 0) {
 			if (errno == EACCES)
-				setError(Common::kWritePermissionDenied, "Search or write permission denied: "+chrootedFile);
+				setError(Common::kWritePermissionDenied, "Search or write permission denied: "+chrootedFile.toString(Common::Path::kNativeSeparator));
 
 			if (errno == ENOENT)
-				setError(Common::kPathDoesNotExist, "removeSavefile: '"+chrootedFile+"' does not exist or path is invalid");
+				setError(Common::kPathDoesNotExist, "removeSavefile: '"+chrootedFile.toString(Common::Path::kNativeSeparator)+"' does not exist or path is invalid");
 			return false;
 		} else {
 			return true;
@@ -125,7 +125,7 @@ int OSystem_iOS7::timerHandler(int t) {
 }
 
 void OSystem_iOS7::initBackend() {
-	_savefileManager = new SandboxedSaveFileManager(_chrootBasePath, "/Savegames");
+	_savefileManager = new SandboxedSaveFileManager(Common::Path(_chrootBasePath, Common::Path::kNativeSeparator), "/Savegames");
 
 	_timerManager = new DefaultTimerManager();
 
diff --git a/backends/platform/sdl/miyoo/miyoo.cpp b/backends/platform/sdl/miyoo/miyoo.cpp
index d61e3031770..bfb0ef43c3d 100644
--- a/backends/platform/sdl/miyoo/miyoo.cpp
+++ b/backends/platform/sdl/miyoo/miyoo.cpp
@@ -169,7 +169,7 @@ void OSystem_SDL_Miyoo::initBackend() {
 		ConfMan.setPath("extrapath", "./engine-data");
 	}
 	if (!ConfMan.hasKey("savepath")) {
-		ConfMan.set("savepath", SAVE_PATH);
+		ConfMan.setPath("savepath", SAVE_PATH);
 	}
 	if (!ConfMan.hasKey("gui_theme")) {
 		ConfMan.set("gui_theme", "builtin");
diff --git a/backends/platform/sdl/opendingux/opendingux.cpp b/backends/platform/sdl/opendingux/opendingux.cpp
index 716fdcde71a..3c0c7eaa255 100644
--- a/backends/platform/sdl/opendingux/opendingux.cpp
+++ b/backends/platform/sdl/opendingux/opendingux.cpp
@@ -137,7 +137,7 @@ void OSystem_SDL_Opendingux::initBackend() {
 		ConfMan.setPath("extrapath", "./engine-data");
 	}
 	if (!ConfMan.hasKey("savepath")) {
-		ConfMan.set("savepath", SAVE_PATH);
+		ConfMan.setPath("savepath", SAVE_PATH);
 	}
 	if (!ConfMan.hasKey("gui_theme")) {
 		ConfMan.set("gui_theme", "builtin");
diff --git a/backends/platform/sdl/riscos/riscos.cpp b/backends/platform/sdl/riscos/riscos.cpp
index 528a3c06c53..34ea7c86450 100644
--- a/backends/platform/sdl/riscos/riscos.cpp
+++ b/backends/platform/sdl/riscos/riscos.cpp
@@ -66,7 +66,7 @@ void OSystem_RISCOS::initBackend() {
 	if (_savefileManager == 0) {
 		Common::String savePath = "/<Choices$Write>/ScummVM/Saves";
 		if (Riscos::assureDirectoryExists(savePath))
-			_savefileManager = new DefaultSaveFileManager(savePath);
+			_savefileManager = new DefaultSaveFileManager(Common::Path(savePath));
 	}
 
 	// Invoke parent implementation of this method
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index 1306b3ddc18..4dc0ab79288 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -47,7 +47,7 @@ const char *DefaultSaveFileManager::TIMESTAMPS_FILENAME = "timestamps";
 DefaultSaveFileManager::DefaultSaveFileManager() {
 }
 
-DefaultSaveFileManager::DefaultSaveFileManager(const Common::String &defaultSavepath) {
+DefaultSaveFileManager::DefaultSaveFileManager(const Common::Path &defaultSavepath) {
 	ConfMan.registerDefault("savepath", defaultSavepath);
 }
 
@@ -56,10 +56,10 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) {
 	clearError();
 	if (!dir.exists()) {
 		if (!dir.createDirectory()) {
-			setError(Common::kPathDoesNotExist, "Failed to create directory '"+dir.getPath()+"'");
+			setError(Common::kPathDoesNotExist, Common::String::format("Failed to create directory '%s'", dir.getPath().toString(Common::Path::kNativeSeparator).c_str()));
 		}
 	} else if (!dir.isDirectory()) {
-		setError(Common::kPathNotDirectory, "The savepath '"+dir.getPath()+"' is not a directory");
+		setError(Common::kPathNotDirectory, Common::String::format("The savepath '%s' is not a directory", dir.getPath().toString(Common::Path::kNativeSeparator).c_str()));
 	}
 }
 
@@ -131,7 +131,7 @@ Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String
 
 Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename, bool compress) {
 	// Assure the savefile name cache is up-to-date.
-	const Common::String savePathName = getSavePath();
+	const Common::Path savePathName = getSavePath();
 	assureCached(savePathName);
 	if (getError().getCode() != Common::kNoError)
 		return nullptr;
@@ -199,7 +199,7 @@ bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
 		_saveFileCache.erase(file);
 		file = _saveFileCache.end();
 
-		Common::ErrorCode result = removeFile(fileNode.getPath());
+		Common::ErrorCode result = removeFile(fileNode);
 		if (result == Common::kNoError)
 			return true;
 		Common::Error error(result);
@@ -208,7 +208,8 @@ bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
 	}
 }
 
-Common::ErrorCode DefaultSaveFileManager::removeFile(const Common::String &filepath) {
+Common::ErrorCode DefaultSaveFileManager::removeFile(const Common::FSNode &fileNode) {
+	Common::String filepath(fileNode.getPath().toString(Common::Path::kNativeSeparator));
 	if (remove(filepath.c_str()) == 0)
 		return Common::kNoError;
 	if (errno == EACCES)
@@ -232,25 +233,25 @@ bool DefaultSaveFileManager::exists(const Common::String &filename) {
 	return _saveFileCache.contains(filename);
 }
 
-Common::String DefaultSaveFileManager::getSavePath() const {
+Common::Path DefaultSaveFileManager::getSavePath() const {
 
-	Common::String dir;
+	Common::Path dir;
 
 	// Try to use game specific savepath from config
-	dir = ConfMan.get("savepath");
+	dir = ConfMan.getPath("savepath");
 
 	// Work around a bug (#1689) in the original 0.6.1 release of
 	// ScummVM, which would insert a bad savepath value into config files.
 	if (dir == "None") {
 		ConfMan.removeKey("savepath", ConfMan.getActiveDomainName());
 		ConfMan.flushToDisk();
-		dir = ConfMan.get("savepath");
+		dir = ConfMan.getPath("savepath");
 	}
 
 	return dir;
 }
 
-void DefaultSaveFileManager::assureCached(const Common::String &savePathName) {
+void DefaultSaveFileManager::assureCached(const Common::Path &savePathName) {
 	// Check that path exists and is usable.
 	checkPath(Common::FSNode(savePathName));
 
@@ -268,7 +269,7 @@ void DefaultSaveFileManager::assureCached(const Common::String &savePathName) {
 	_cachedDirectory.clear();
 
 	if (getError().getCode() != Common::kNoError) {
-		warning("DefaultSaveFileManager::assureCached: Can not cache path '%s': '%s'", savePathName.c_str(), getErrorDesc().c_str());
+		warning("DefaultSaveFileManager::assureCached: Can not cache path '%s': '%s'", savePathName.toString(Common::Path::kNativeSeparator).c_str(), getErrorDesc().c_str());
 		return;
 	}
 
@@ -359,9 +360,9 @@ Common::HashMap<Common::String, uint32> DefaultSaveFileManager::loadTimestamps()
 
 void DefaultSaveFileManager::saveTimestamps(Common::HashMap<Common::String, uint32> &timestamps) {
 	Common::DumpFile f;
-	Common::String filename = concatWithSavesPath(TIMESTAMPS_FILENAME);
+	Common::Path filename = concatWithSavesPath(TIMESTAMPS_FILENAME);
 	if (!f.open(filename, true)) {
-		warning("DefaultSaveFileManager: failed to open '%s' file to save timestamps", filename.c_str());
+		warning("DefaultSaveFileManager: failed to open '%s' file to save timestamps", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
@@ -371,7 +372,7 @@ void DefaultSaveFileManager::saveTimestamps(Common::HashMap<Common::String, uint
 
 		Common::String data = i->_key + Common::String::format(" %u\n", v);
 		if (f.write(data.c_str(), data.size()) != data.size()) {
-			warning("DefaultSaveFileManager: failed to write timestamps data into '%s'", filename.c_str());
+			warning("DefaultSaveFileManager: failed to write timestamps data into '%s'", filename.toString(Common::Path::kNativeSeparator).c_str());
 			return;
 		}
 	}
@@ -383,20 +384,11 @@ void DefaultSaveFileManager::saveTimestamps(Common::HashMap<Common::String, uint
 
 #endif // ifdef USE_LIBCURL
 
-Common::String DefaultSaveFileManager::concatWithSavesPath(Common::String name) {
+Common::Path DefaultSaveFileManager::concatWithSavesPath(Common::String name) {
 	DefaultSaveFileManager *manager = dynamic_cast<DefaultSaveFileManager *>(g_system->getSavefileManager());
-	Common::String path = (manager ? manager->getSavePath() : ConfMan.get("savepath"));
-	if (path.size() > 0 && (path.lastChar() == '/' || path.lastChar() == '\\'))
-		return path + name;
-
-	//simple heuristic to determine which path separator to use
-	int backslashes = 0;
-	for (uint32 i = 0; i < path.size(); ++i)
-		if (path[i] == '/') --backslashes;
-		else if (path[i] == '\\') ++backslashes;
-
-	if (backslashes > 0) return path + '\\' + name;
-	return path + '/' + name;
+	Common::Path path = (manager ? manager->getSavePath() : ConfMan.getPath("savepath"));
+	path.joinInPlace(name);
+	return path;
 }
 
 #endif // !defined(DISABLE_DEFAULT_SAVEFILEMANAGER)
diff --git a/backends/saves/default/default-saves.h b/backends/saves/default/default-saves.h
index d0058e52774..5c420884ecf 100644
--- a/backends/saves/default/default-saves.h
+++ b/backends/saves/default/default-saves.h
@@ -34,7 +34,7 @@
 class DefaultSaveFileManager : public Common::SaveFileManager {
 public:
 	DefaultSaveFileManager();
-	DefaultSaveFileManager(const Common::String &defaultSavepath);
+	DefaultSaveFileManager(const Common::Path &defaultSavepath);
 
 	void updateSavefilesList(Common::StringArray &lockedFiles) override;
 	Common::StringArray listSavefiles(const Common::String &pattern) override;
@@ -53,7 +53,7 @@ public:
 	static void saveTimestamps(Common::HashMap<Common::String, uint32> &timestamps);
 #endif
 
-	static Common::String concatWithSavesPath(Common::String name);
+	static Common::Path concatWithSavesPath(Common::String name);
 
 protected:
 	/**
@@ -61,7 +61,7 @@ protected:
 	 * Should only be used internally since some platforms
 	 * might implement savefiles in a completely different way.
 	 */
-	virtual Common::String getSavePath() const;
+	virtual Common::Path getSavePath() const;
 
 	/**
 	 * Checks the given path for read access, existence, etc.
@@ -73,14 +73,14 @@ protected:
 	 * Removes the given file.
 	 * This is called from removeSavefile() with the full file path.
 	 */
-	virtual Common::ErrorCode removeFile(const Common::String &filepath);
+	virtual Common::ErrorCode removeFile(const Common::FSNode &fileNode);
 
 	/**
 	 * Assure that the given save path is cached.
 	 *
 	 * @param savePathName  String representation of save path to cache.
 	 */
-	void assureCached(const Common::String &savePathName);
+	void assureCached(const Common::Path &savePathName);
 
 	typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SaveFileCache;
 
@@ -103,7 +103,7 @@ private:
 	/**
 	 * The currently cached directory.
 	 */
-	Common::String _cachedDirectory;
+	Common::Path _cachedDirectory;
 };
 
 #endif
diff --git a/backends/saves/kolibrios/kolibrios-saves.cpp b/backends/saves/kolibrios/kolibrios-saves.cpp
index 34fe433293f..81a7b28af31 100644
--- a/backends/saves/kolibrios/kolibrios-saves.cpp
+++ b/backends/saves/kolibrios/kolibrios-saves.cpp
@@ -39,10 +39,10 @@
 
 KolibriOSSaveFileManager::KolibriOSSaveFileManager(const Common::Path& writeablePath) {
 	// Register default savepath.
-	Common::String savePath;
+	Common::Path savePath;
 
 	if (KolibriOS::assureDirectoryExists("saves", writeablePath.toString().c_str())) {
-		savePath = writeablePath.join("saves").toString().c_str();
+		savePath = writeablePath.join("saves");
 	}
 
 	if (!savePath.empty() && savePath.size() < MAXPATHLEN) {
@@ -65,7 +65,7 @@ KolibriOSSaveFileManager::KolibriOSSaveFileManager(const Common::Path& writeable
 			} else if (!saveDir.isWritable()) {
 				warning("Ignoring non-writable SCUMMVM_SAVEPATH '%s'", dir);
 			} else {
-				ConfMan.set("savepath", dir, Common::ConfigManager::kTransientDomain);
+				ConfMan.setPath("savepath", dir, Common::ConfigManager::kTransientDomain);
 			}
 		}
 	}
diff --git a/backends/saves/posix/posix-saves.cpp b/backends/saves/posix/posix-saves.cpp
index cb692fb37db..04cbcb335df 100644
--- a/backends/saves/posix/posix-saves.cpp
+++ b/backends/saves/posix/posix-saves.cpp
@@ -41,13 +41,13 @@
 
 POSIXSaveFileManager::POSIXSaveFileManager() {
 	// Register default savepath.
-	Common::String savePath;
+	Common::Path savePath;
 
 #if defined(MACOSX)
 	const char *home = getenv("HOME");
 	if (home && *home && strlen(home) < MAXPATHLEN) {
 		savePath = home;
-		savePath += "/Documents/ScummVM Savegames";
+		savePath.joinInPlace("Documents/ScummVM Savegames");
 
 		ConfMan.registerDefault("savepath", savePath);
 	}
@@ -60,10 +60,10 @@ POSIXSaveFileManager::POSIXSaveFileManager() {
 	envVar = getenv("HOME");
 	if (envVar && *envVar) {
 		savePath = envVar;
-		savePath += "/.scummvm";
+		savePath.joinInPlace("/.scummvm");
 
 		struct stat sb;
-		if (stat(savePath.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
+		if (stat(savePath.toString(Common::Path::kNativeSeparator).c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
 			savePath.clear();
 		}
 	}
@@ -79,23 +79,23 @@ POSIXSaveFileManager::POSIXSaveFileManager() {
 			envVar = getenv("HOME");
 			if (envVar && *envVar) {
 				prefix = envVar;
-				savePath = ".local/share/";
+				savePath = Common::Path(".local/share");
 			}
 		} else {
 			prefix = envVar;
 		}
 
 		// Our default save path is '$XDG_DATA_HOME/scummvm/saves'
-		savePath += "scummvm/saves";
+		savePath.joinInPlace("scummvm/saves");
 
-		if (!Posix::assureDirectoryExists(savePath, prefix.c_str())) {
+		if (!Posix::assureDirectoryExists(savePath.toString(Common::Path::kNativeSeparator), prefix.c_str())) {
 			savePath.clear();
 		} else {
-			savePath = prefix + '/' + savePath;
+			savePath = Common::Path(prefix).join(savePath);
 		}
 	}
 
-	if (!savePath.empty() && savePath.size() < MAXPATHLEN) {
+	if (!savePath.empty() && savePath.toString(Common::Path::kNativeSeparator).size() < MAXPATHLEN) {
 		ConfMan.registerDefault("savepath", savePath);
 	}
 #endif
@@ -116,7 +116,7 @@ POSIXSaveFileManager::POSIXSaveFileManager() {
 			} else if (!saveDir.isWritable()) {
 				warning("Ignoring non-writable SCUMMVM_SAVEPATH '%s'", dir);
 			} else {
-				ConfMan.set("savepath", dir, Common::ConfigManager::kTransientDomain);
+				ConfMan.setPath("savepath", dir, Common::ConfigManager::kTransientDomain);
 			}
 		}
 	}
diff --git a/backends/saves/windows/windows-saves.cpp b/backends/saves/windows/windows-saves.cpp
index 752529bd2f3..7f35c2853f0 100644
--- a/backends/saves/windows/windows-saves.cpp
+++ b/backends/saves/windows/windows-saves.cpp
@@ -51,7 +51,7 @@ WindowsSaveFileManager::WindowsSaveFileManager(bool isPortable) {
 			error("Cannot create ScummVM Saved games folder");
 	}
 
-	ConfMan.registerDefault("savepath", Win32::tcharToString(defaultSavepath));
+	ConfMan.registerDefault("savepath", Common::Path(Win32::tcharToString(defaultSavepath), Common::Path::kNativeSeparator));
 }
 
 #endif
diff --git a/engines/ags/shared/util/stdio_compat.cpp b/engines/ags/shared/util/stdio_compat.cpp
index b90f298f15a..c6f9d9fdc52 100644
--- a/engines/ags/shared/util/stdio_compat.cpp
+++ b/engines/ags/shared/util/stdio_compat.cpp
@@ -60,7 +60,7 @@ static Common::FSNode getFSNode(const char *path) {
 		node = Common::FSNode(ConfMan.get("path"));
 	} else if (filePath.hasPrefixIgnoreCase(AGS::Shared::SAVE_FOLDER_PREFIX)) {
 		filePath = filePath.substr(strlen(AGS::Shared::SAVE_FOLDER_PREFIX));
-		node = Common::FSNode(ConfMan.get("savepath"));
+		node = Common::FSNode(ConfMan.getPath("savepath"));
 	} else {
 		node = Common::FSNode(filePath);
 		if (node.isReadable())


Commit: 0a636d0d40be1edf0550dd5a3af7f934b7ed2697
    https://github.com/scummvm/scummvm/commit/0a636d0d40be1edf0550dd5a3af7f934b7ed2697
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make pluginspath a Path object

Changed paths:
    base/plugins.cpp


diff --git a/base/plugins.cpp b/base/plugins.cpp
index afeda97673c..a85daebd8c2 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -196,7 +196,7 @@ PluginList FilePluginProvider::getPlugins() {
 	addCustomDirectories(pluginDirs);
 
 	// Add the user specified directory
-	Common::String pluginsPath(ConfMan.get("pluginspath"));
+	Common::Path pluginsPath(ConfMan.getPath("pluginspath"));
 	if (!pluginsPath.empty())
 		pluginDirs.push_back(Common::FSNode(pluginsPath));
 


Commit: ce961cabbc969a80600689031e043cda309cff01
    https://github.com/scummvm/scummvm/commit/ce961cabbc969a80600689031e043cda309cff01
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make soundfont a Path object

Changed paths:
    audio/softsynth/eas.cpp
    audio/softsynth/fluidsynth.cpp
    backends/midi/coreaudio.cpp


diff --git a/audio/softsynth/eas.cpp b/audio/softsynth/eas.cpp
index 7b6cfe2d8a2..d40097108bf 100644
--- a/audio/softsynth/eas.cpp
+++ b/audio/softsynth/eas.cpp
@@ -180,9 +180,9 @@ int MidiDriver_EAS::open() {
 		warning("error setting EAS master volume: %d", (int32)res);
 
 	if (ConfMan.hasKey("soundfont")) {
-		const Common::String dls = ConfMan.get("soundfont");
+		const Common::Path dls = ConfMan.getPath("soundfont");
 
-		debug("loading DLS file '%s'", dls.c_str());
+		debug("loading DLS file '%s'", dls.toString(Common::Path::kNativeSeparator).c_str());
 		Common::FSNode fsnode(dls);
 		Common::SeekableReadStream *stream = fsnode.createReadStream();
 
@@ -200,13 +200,13 @@ int MidiDriver_EAS::open() {
 
 			res = EAS_LoadDLSCollection(_EASHandle, 0, &f);
 			if (res)
-				warning("error loading DLS file '%s': %d", dls.c_str(), (int32)res);
+				warning("error loading DLS file '%s': %d", dls.toString(Common::Path::kNativeSeparator).c_str(), (int32)res);
 			else
 				debug("DLS file loaded");
 
 			delete stream;
 		} else {
-			warning("error loading DLS file '%s': can't be opened", dls.c_str());
+			warning("error loading DLS file '%s': can't be opened", dls.toString(Common::Path::kNativeSeparator).c_str());
 		}
 	}
 
diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index 38036b0a54e..e4bf297fa8d 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -110,7 +110,7 @@ protected:
 
 	void generateSamples(int16 *buf, int len) override;
 
-	Common::String getSoundFontPath() const;
+	Common::Path getSoundFontPath() const;
 
 public:
 	MidiDriver_FluidSynth(Audio::Mixer *mixer);
@@ -280,22 +280,22 @@ static long SoundFontMemLoader_tell(void *handle) {
 
 #endif // USE_FLUIDLITE
 
-Common::String MidiDriver_FluidSynth::getSoundFontPath() const {
-	Common::String path = ConfMan.get("soundfont");
+Common::Path MidiDriver_FluidSynth::getSoundFontPath() const {
+	Common::Path path = ConfMan.getPath("soundfont");
 	if (path.empty())
 		return path;
 
 	// First check if this is a full path
-	Common::String fullPath = g_system->getFilesystemFactory()->getSystemFullPath(path);
+	Common::Path fullPath(g_system->getFilesystemFactory()->getSystemFullPath(path.toString(Common::Path::kNativeSeparator)), Common::Path::kNativeSeparator);
 	Common::FSNode fileNode(fullPath);
 	if (fileNode.exists())
 		return fullPath;
 
 	// Then check with soundfontpath
 	if (ConfMan.hasKey("soundfontpath")) {
-		Common::FSNode dirNode(ConfMan.get("soundfontpath"));
+		Common::FSNode dirNode(ConfMan.getPath("soundfontpath"));
 		if (dirNode.exists() && dirNode.isDirectory()) {
-			fileNode = dirNode.getChild(path);
+			fileNode = dirNode.getChild(path.baseName());
 			if (fileNode.exists())
 				return fileNode.getPath();
 		}
@@ -308,7 +308,7 @@ Common::String MidiDriver_FluidSynth::getSoundFontPath() const {
 		Common::FSDirectory* dir = dynamic_cast<Common::FSDirectory*>(SearchMan.getArchive(file.arcName));
 		if (!dir)
 			continue;
-		fileNode = dir->getFSNode().getChild(file.arcMember->getPathInArchive().toString());
+		fileNode = dir->getFSNode().getChild(file.arcMember->getPathInArchive().toString(Common::Path::kNativeSeparator));
 		if (fileNode.exists())
 			return fileNode.getPath();
 	}
@@ -476,7 +476,7 @@ int MidiDriver_FluidSynth::open() {
 #endif // FS_HAS_STREAM_SUPPORT
 	{
 //		soundfont = ConfMan.get("soundfont");
-		soundfont = getSoundFontPath();
+		soundfont = getSoundFontPath().toString(Common::Path::kNativeSeparator);
 	}
 
 	_soundFont = fluid_synth_sfload(_synth, soundfont.c_str(), 1);
diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp
index e94b2045639..2391ccb8244 100644
--- a/backends/midi/coreaudio.cpp
+++ b/backends/midi/coreaudio.cpp
@@ -154,7 +154,7 @@ int MidiDriver_CORE::open() {
 
 	// Load custom soundfont, if specified
 	if (ConfMan.hasKey("soundfont"))
-		loadSoundFont(ConfMan.get("soundfont").c_str());
+		loadSoundFont(ConfMan.getPath("soundfont").toString(Common::Path::kNativeSeparator).c_str());
 
 #ifdef COREAUDIO_DISABLE_REVERB
 	// Disable reverb mode, as that sucks up a lot of CPU power, which can


Commit: 2f34975164ea1353b6c2e05eec30a7696bf9b364
    https://github.com/scummvm/scummvm/commit/2f34975164ea1353b6c2e05eec30a7696bf9b364
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make shaders API use the Path class

Changed paths:
    backends/graphics/graphics.h
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro.h
    backends/modular-backend.cpp
    backends/modular-backend.h
    base/main.cpp
    common/system.h
    engines/engine.cpp
    gui/options.cpp


diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h
index d68a1ef3e38..b78e2a81a60 100644
--- a/backends/graphics/graphics.h
+++ b/backends/graphics/graphics.h
@@ -48,7 +48,7 @@ public:
 	virtual int getDefaultGraphicsMode() const { return 0; }
 	virtual bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) { return (mode == 0); }
 	virtual int getGraphicsMode() const { return 0; }
-	virtual bool setShader(const Common::String &fileName) { return false; }
+	virtual bool setShader(const Common::Path &fileName) { return false; }
 	virtual const OSystem::GraphicsMode *getSupportedStretchModes() const {
 		static const OSystem::GraphicsMode noStretchModes[] = {{"NONE", "Normal", 0}, {nullptr, nullptr, 0 }};
 		return noStretchModes;
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 85cd020f9f1..4c9970f722b 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -341,12 +341,12 @@ uint OpenGLGraphicsManager::getScaleFactor() const {
 #endif
 
 #if !USE_FORCED_GLES
-bool OpenGLGraphicsManager::setShader(const Common::String &fileName) {
+bool OpenGLGraphicsManager::setShader(const Common::Path &fileName) {
 	assert(_transactionMode != kTransactionNone);
 
 	// Special case for the 'default' shader
-	if (fileName == "default")
-		_currentState.shader = "";
+	if (fileName == Common::Path("default", Common::Path::kNoSeparator))
+		_currentState.shader.clear();
 	else
 		_currentState.shader = fileName;
 
@@ -354,7 +354,7 @@ bool OpenGLGraphicsManager::setShader(const Common::String &fileName) {
 }
 #endif
 
-bool OpenGLGraphicsManager::loadShader(const Common::String &fileName) {
+bool OpenGLGraphicsManager::loadShader(const Common::Path &fileName) {
 #if !USE_FORCED_GLES
 	if (!_libretroPipeline) {
 		warning("Libretro is not supported");
@@ -368,7 +368,7 @@ bool OpenGLGraphicsManager::loadShader(const Common::String &fileName) {
 	// Load selected shader preset
 	if (!fileName.empty()) {
 		if (!_libretroPipeline->open(fileName, shaderSet)) {
-			warning("Failed to load shader %s", fileName.c_str());
+			warning("Failed to load shader %s", fileName.toString().c_str());
 			return false;
 		}
 	} else {
@@ -489,7 +489,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 				}
 				// If the shader failed and we had not a valid old state, try to unset the shader and do it again
 				if (!shaderOK && !_currentState.shader.empty()) {
-					_currentState.shader = "";
+					_currentState.shader.clear();
 					_transactionMode = kTransactionRollback;
 					continue;
 				}
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 659b9b65464..8ed70349843 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -86,7 +86,7 @@ public:
 #endif
 
 #if !USE_FORCED_GLES
-	bool setShader(const Common::String &fileNode) override;
+	bool setShader(const Common::Path &fileNode) override;
 #endif
 
 	void beginGFXTransaction() override;
@@ -199,7 +199,7 @@ protected:
 		uint scalerIndex;
 		int scaleFactor;
 
-		Common::String shader;
+		Common::Path shader;
 
 		bool operator==(const VideoState &right) {
 			return gameWidth == right.gameWidth && gameHeight == right.gameHeight
@@ -273,7 +273,7 @@ protected:
 	 */
 	virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0;
 
-	bool loadShader(const Common::String &fileName);
+	bool loadShader(const Common::Path &fileName);
 
 	/**
 	 * Refresh the screen contents.
diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 65a8f9a3854..324547b62ab 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -345,7 +345,7 @@ void LibRetroPipeline::deactivateInternal() {
 	// Don't call Pipeline::deactivateInternal as our framebuffer is passed to _outputPipeline
 }
 
-bool LibRetroPipeline::open(const Common::String &shaderPreset, Common::SearchSet &archSet) {
+bool LibRetroPipeline::open(const Common::Path &shaderPreset, Common::SearchSet &archSet) {
 	close();
 
 	_shaderPreset = LibRetro::parsePreset(shaderPreset, archSet);
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index 5db0c260096..a8b82a163a8 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -55,7 +55,7 @@ public:
 	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
 	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
-	bool open(const Common::String &shaderPath, Common::SearchSet &archSet);
+	bool open(const Common::Path &shaderPath, Common::SearchSet &archSet);
 	void close();
 
 	/* Called by OpenGLGraphicsManager */
diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp
index e5b85c1485b..9cc446c6705 100644
--- a/backends/modular-backend.cpp
+++ b/backends/modular-backend.cpp
@@ -73,7 +73,7 @@ int ModularGraphicsBackend::getGraphicsMode() const {
 	return _graphicsManager->getGraphicsMode();
 }
 
-bool ModularGraphicsBackend::setShader(const Common::String &fileName) {
+bool ModularGraphicsBackend::setShader(const Common::Path &fileName) {
 	return _graphicsManager->setShader(fileName);
 }
 
diff --git a/backends/modular-backend.h b/backends/modular-backend.h
index 0c4ebe0f429..3231ffc3407 100644
--- a/backends/modular-backend.h
+++ b/backends/modular-backend.h
@@ -67,7 +67,7 @@ public:
 	int getDefaultGraphicsMode() const override;
 	bool setGraphicsMode(int mode, uint flags = kGfxModeNoFlags) override;
 	int getGraphicsMode() const override;
-	bool setShader(const Common::String &name) override final;
+	bool setShader(const Common::Path &name) override final;
 	const GraphicsMode *getSupportedStretchModes() const override final;
 	int getDefaultStretchMode() const override final;
 	bool setStretchMode(int mode) override final;
diff --git a/base/main.cpp b/base/main.cpp
index 27d5166397f..91c0d394a92 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -362,7 +362,7 @@ static void setupGraphics(OSystem &system) {
 		system.setGraphicsMode(ConfMan.get("gfx_mode").c_str());
 		system.setStretchMode(ConfMan.get("stretch_mode").c_str());
 		system.setScaler(ConfMan.get("scaler").c_str(), ConfMan.getInt("scale_factor"));
-		system.setShader(ConfMan.get("shader"));
+		system.setShader(ConfMan.getPath("shader"));
 
 #if defined(OPENDINGUX) || defined(MIYOO) || defined(MIYOOMINI)
 		// 0, 0 means "autodetect" but currently only SDL supports
diff --git a/common/system.h b/common/system.h
index 6b515342cff..7849c1db19d 100644
--- a/common/system.h
+++ b/common/system.h
@@ -916,7 +916,7 @@ public:
 	 *
 	 * @return True if the switch was successful, false otherwise.
 	 */
-	virtual bool setShader(const Common::String &fileName) { return false; }
+	virtual bool setShader(const Common::Path &fileName) { return false; }
 
 	/**
 	 * Retrieve a list of all stretch modes supported by this backend.
diff --git a/engines/engine.cpp b/engines/engine.cpp
index e94a92bc0bb..8f7525aef14 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -224,7 +224,7 @@ void initCommonGFX() {
 			g_system->setScaler(ConfMan.get("scaler").c_str(), ConfMan.getInt("scale_factor"));
 
 		if (gameDomain->contains("shader"))
-			g_system->setShader(ConfMan.get("shader"));
+			g_system->setShader(ConfMan.getPath("shader"));
 
 		// TODO: switching between OpenGL and SurfaceSDL is quite fragile
 		// and the SDL backend doesn't really need this so leave it out
diff --git a/gui/options.cpp b/gui/options.cpp
index 9311b7d5f74..aa7455c2967 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -771,7 +771,7 @@ void OptionsDialog::apply() {
 		g_system->setGraphicsMode(ConfMan.get("gfx_mode", _domain).c_str());
 		g_system->setStretchMode(ConfMan.get("stretch_mode", _domain).c_str());
 		g_system->setScaler(ConfMan.get("scaler", _domain).c_str(), ConfMan.getInt("scale_factor", _domain));
-		g_system->setShader(ConfMan.get("shader", _domain));
+		g_system->setShader(ConfMan.getPath("shader", _domain));
 
 		if (ConfMan.hasKey("aspect_ratio"))
 			g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio", _domain));
@@ -892,7 +892,7 @@ void OptionsDialog::apply() {
 					}
 
 					g_system->beginGFXTransaction();
-					g_system->setShader(ConfMan.get("shader", _domain));
+					g_system->setShader(ConfMan.getPath("shader", _domain));
 					g_system->endGFXTransaction();
 				}
 			}


Commit: 317432030d19655b826418b1d9c6d1d0356d4814
    https://github.com/scummvm/scummvm/commit/317432030d19655b826418b1d9c6d1d0356d4814
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: SDL: Make controller_map_db a Path object

Changed paths:
    backends/events/sdl/sdl-events.cpp


diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index 8f8a4d2ac2a..d5cbd95c64d 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -46,16 +46,16 @@ static uint32 convUTF8ToUTF32(const char *src) {
 void SdlEventSource::loadGameControllerMappingFile() {
 	bool loaded = false;
 	if (ConfMan.hasKey("controller_map_db")) {
-		Common::FSNode file = Common::FSNode(ConfMan.get("controller_map_db"));
+		Common::FSNode file = Common::FSNode(ConfMan.getPath("controller_map_db"));
 		if (file.exists()) {
-			if (SDL_GameControllerAddMappingsFromFile(file.getPath().c_str()) < 0)
-				error("File %s not valid: %s", file.getPath().c_str(), SDL_GetError());
+			if (SDL_GameControllerAddMappingsFromFile(file.getPath().toString(Common::Path::kNativeSeparator).c_str()) < 0)
+				error("File %s not valid: %s", file.getPath().toString(Common::Path::kNativeSeparator).c_str(), SDL_GetError());
 			else {
 				loaded = true;
-				debug("Game controller DB file loaded: %s", file.getPath().c_str());
+				debug("Game controller DB file loaded: %s", file.getPath().toString(Common::Path::kNativeSeparator).c_str());
 			}
 		} else
-			warning("Game controller DB file not found: %s", file.getPath().c_str());
+			warning("Game controller DB file not found: %s", file.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	}
 	if (!loaded && ConfMan.hasKey("extrapath")) {
 		Common::FSNode dir = Common::FSNode(ConfMan.getPath("extrapath"));


Commit: 0e1d950decb12dcb1d7c8b0d767fc630025e21eb
    https://github.com/scummvm/scummvm/commit/0e1d950decb12dcb1d7c8b0d767fc630025e21eb
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: SDL: Make vkeybdpath a Path object

Changed paths:
    backends/vkeybd/virtual-keyboard.cpp


diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp
index 8d00eed1a1b..6d6dde3c9dc 100644
--- a/backends/vkeybd/virtual-keyboard.cpp
+++ b/backends/vkeybd/virtual-keyboard.cpp
@@ -118,7 +118,7 @@ bool VirtualKeyboard::loadKeyboardPack(const String &packName) {
 
 	bool opened = false;
 	if (ConfMan.hasKey("vkeybdpath"))
-		opened = openPack(packName, new FSDirectory(ConfMan.get("vkeybdpath")), DisposeAfterUse::YES);
+		opened = openPack(packName, new FSDirectory(ConfMan.getPath("vkeybdpath")), DisposeAfterUse::YES);
 	else if (ConfMan.hasKey("extrapath"))
 		opened = openPack(packName, new FSDirectory(ConfMan.getPath("extrapath")), DisposeAfterUse::YES);
 


Commit: c34e475a0e0d4df02e47d4213b57715e664951ab
    https://github.com/scummvm/scummvm/commit/c34e475a0e0d4df02e47d4213b57715e664951ab
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
VKEYBD: Migrate virtual keyboard to Path class

Changed paths:
    backends/vkeybd/virtual-keyboard-parser.cpp
    backends/vkeybd/virtual-keyboard.cpp


diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp
index 5bbb72695d1..06682854c37 100644
--- a/backends/vkeybd/virtual-keyboard-parser.cpp
+++ b/backends/vkeybd/virtual-keyboard-parser.cpp
@@ -259,7 +259,7 @@ bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) {
 
 	_mode->bitmapName = node->values["bitmap"];
 
-	SeekableReadStream *file = _keyboard->_fileArchive->createReadStreamForMember(_mode->bitmapName);
+	SeekableReadStream *file = _keyboard->_fileArchive->createReadStreamForMember(Common::Path(_mode->bitmapName, '/'));
 	if (!file)
 		return parserError("Bitmap '" + _mode->bitmapName + "' not found");
 
diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp
index 6d6dde3c9dc..8bdf517b162 100644
--- a/backends/vkeybd/virtual-keyboard.cpp
+++ b/backends/vkeybd/virtual-keyboard.cpp
@@ -77,11 +77,15 @@ void VirtualKeyboard::reset() {
 }
 
 bool VirtualKeyboard::openPack(const String &packName, Archive *searchPath, DisposeAfterUse::Flag disposeSearchPath) {
-	if (searchPath->hasFile(packName + ".xml")) {
+	Common::Path xmlPackName(packName), zipPackName(packName);
+	xmlPackName.appendInPlace(".xml");
+	zipPackName.appendInPlace(".zip");
+
+	if (searchPath->hasFile(xmlPackName)) {
 		_fileArchive.reset(searchPath, disposeSearchPath);
 
 		// uncompressed keyboard pack
-		if (!_parser->loadStream(searchPath->createReadStreamForMember(packName + ".xml"))) {
+		if (!_parser->loadStream(searchPath->createReadStreamForMember(xmlPackName))) {
 			_fileArchive.reset();
 			return false;
 		}
@@ -89,12 +93,12 @@ bool VirtualKeyboard::openPack(const String &packName, Archive *searchPath, Disp
 		return true;
 	}
 
-	if (searchPath->hasFile(packName + ".zip")) {
+	if (searchPath->hasFile(zipPackName)) {
 		// compressed keyboard pack
-		Archive *zip = makeZipArchive(searchPath->createReadStreamForMember(packName + ".zip"));
+		Archive *zip = makeZipArchive(searchPath->createReadStreamForMember(zipPackName));
 		_fileArchive.reset(zip, DisposeAfterUse::YES);
-		if (_fileArchive && _fileArchive->hasFile(packName + ".xml")) {
-			if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) {
+		if (_fileArchive && _fileArchive->hasFile(xmlPackName)) {
+			if (!_parser->loadStream(_fileArchive->createReadStreamForMember(xmlPackName))) {
 				_fileArchive.reset();
 				return false;
 			}


Commit: db41390587614d5f3b1936a32bf4c87b6b19c59f
    https://github.com/scummvm/scummvm/commit/db41390587614d5f3b1936a32bf4c87b6b19c59f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: Make browser_lastpath a Path object

Changed paths:
    backends/dialogs/amigaos/amigaos-dialogs.cpp
    backends/dialogs/gtk/gtk-dialogs.cpp
    backends/dialogs/morphos/morphos-dialogs.cpp
    backends/dialogs/win32/win32-dialogs.cpp
    backends/platform/android/android.cpp
    gui/browser.cpp


diff --git a/backends/dialogs/amigaos/amigaos-dialogs.cpp b/backends/dialogs/amigaos/amigaos-dialogs.cpp
index cf9d32fc5d0..0f7fda892b7 100644
--- a/backends/dialogs/amigaos/amigaos-dialogs.cpp
+++ b/backends/dialogs/amigaos/amigaos-dialogs.cpp
@@ -55,7 +55,7 @@ Common::DialogManager::DialogResult AmigaOSDialogManager::showFileBrowser(const
 		struct FileRequester *fr = nullptr;
 
 		if (ConfMan.hasKey("browser_lastpath")) {
-			strncpy(pathBuffer, ConfMan.get("browser_lastpath").c_str(), sizeof(pathBuffer) - 1);
+			strncpy(pathBuffer, ConfMan.getPath("browser_lastpath").toString(Common::Path::kNativeSeparator).c_str(), sizeof(pathBuffer) - 1);
 		}
 
 		fr = (struct FileRequester *)IAsl->AllocAslRequestTags(ASL_FileRequest, TAG_DONE);
@@ -70,8 +70,9 @@ Common::DialogManager::DialogResult AmigaOSDialogManager::showFileBrowser(const
 				if (!isDirBrowser) {
 					IDOS->AddPart(pathBuffer, fr->fr_File, sizeof(pathBuffer));
 				}
-				choice = Common::FSNode(pathBuffer);
-				ConfMan.set("browser_lastpath", pathBuffer);
+				Common::Path path(pathBuffer);
+				choice = Common::FSNode(path);
+				ConfMan.setPath("browser_lastpath", path);
 				result = kDialogOk;
 			}
 			IAsl->FreeAslRequest((APTR)fr);
diff --git a/backends/dialogs/gtk/gtk-dialogs.cpp b/backends/dialogs/gtk/gtk-dialogs.cpp
index 8bbbb13c048..8aa3e867cf5 100644
--- a/backends/dialogs/gtk/gtk-dialogs.cpp
+++ b/backends/dialogs/gtk/gtk-dialogs.cpp
@@ -83,7 +83,7 @@ Common::DialogManager::DialogResult GtkDialogManager::showFileBrowser(const Comm
 	// Customize dialog
 	gtk_file_chooser_set_show_hidden(chooser, ConfMan.getBool("gui_browser_show_hidden", Common::ConfigManager::kApplicationDomain));
 	if (ConfMan.hasKey("browser_lastpath")) {
-		gtk_file_chooser_set_current_folder(chooser, ConfMan.get("browser_lastpath").c_str());
+		gtk_file_chooser_set_current_folder(chooser, ConfMan.getPath("browser_lastpath").toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	// Show dialog
@@ -99,11 +99,12 @@ Common::DialogManager::DialogResult GtkDialogManager::showFileBrowser(const Comm
 #endif
 	if (res == GTK_RESPONSE_ACCEPT) {
 		// Get the selection from the user
-		char *path = gtk_file_chooser_get_filename(chooser);
+		char *pathS = gtk_file_chooser_get_filename(chooser);
+		Common::Path path(pathS, Common::Path::kNativeSeparator);
 		choice = Common::FSNode(path);
-		ConfMan.set("browser_lastpath", path);
+		ConfMan.setPath("browser_lastpath", path);
 		result = kDialogOk;
-		g_free(path);
+		g_free(pathS);
 	}
 
 	_inDialog = FALSE;
diff --git a/backends/dialogs/morphos/morphos-dialogs.cpp b/backends/dialogs/morphos/morphos-dialogs.cpp
index 2029b7420da..9c70d5afd8f 100644
--- a/backends/dialogs/morphos/morphos-dialogs.cpp
+++ b/backends/dialogs/morphos/morphos-dialogs.cpp
@@ -46,7 +46,7 @@ Common::DialogManager::DialogResult MorphosDialogManager::showFileBrowser(const
 		struct FileRequester *fr = NULL;
 
 		if (ConfMan.hasKey("browser_lastpath")) {
-			strncpy(pathBuffer, ConfMan.get("browser_lastpath").c_str(), sizeof(pathBuffer) - 1);
+			strncpy(pathBuffer, ConfMan.getPath("browser_lastpath").toString(Common::Path::kNativeSeparator).c_str(), sizeof(pathBuffer) - 1);
 		}
 
 		fr = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest, TAG_DONE);
@@ -58,7 +58,7 @@ Common::DialogManager::DialogResult MorphosDialogManager::showFileBrowser(const
 
 			if (strlen(fr->fr_Drawer) < sizeof(pathBuffer)) {
 				strncpy(pathBuffer, fr->fr_Drawer, sizeof(pathBuffer));
-				ConfMan.set("browser_lastpath", pathBuffer); // only path
+				ConfMan.setPath("browser_lastpath", pathBuffer); // only path
 				if (!isDirBrowser) {
 					AddPart(pathBuffer, fr->fr_File, sizeof(pathBuffer));
 				}
diff --git a/backends/dialogs/win32/win32-dialogs.cpp b/backends/dialogs/win32/win32-dialogs.cpp
index 55e443536fb..edb36334c24 100644
--- a/backends/dialogs/win32/win32-dialogs.cpp
+++ b/backends/dialogs/win32/win32-dialogs.cpp
@@ -87,12 +87,12 @@ HRESULT winCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, REFIID riid,
 	return func(pszPath, pbc, riid, ppv);
 }
 
-HRESULT getShellPath(IShellItem *item, Common::String &path) {
+HRESULT getShellPath(IShellItem *item, Common::Path &path) {
 	LPWSTR name = nullptr;
 	HRESULT hr = item->GetDisplayName(SIGDN_FILESYSPATH, &name);
 	if (SUCCEEDED(hr)) {
 		char *str = Win32::unicodeToAnsi(name);
-		path = Common::String(str);
+		path = Common::Path(str, Common::Path::kNativeSeparator);
 		CoTaskMemFree(name);
 		free(str);
 	}
@@ -139,7 +139,7 @@ Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const Co
 
 		LPWSTR str;
 		if (ConfMan.hasKey("browser_lastpath")) {
-			str = Win32::ansiToUnicode(ConfMan.get("browser_lastpath").c_str());
+			str = Win32::ansiToUnicode(ConfMan.getPath("browser_lastpath").toString(Common::Path::kNativeSeparator).c_str());
 			IShellItem *item = nullptr;
 			hr = winCreateItemFromParsingName(str, nullptr, IID_IShellItem, reinterpret_cast<void **> (&(item)));
 			if (SUCCEEDED(hr)) {
@@ -156,7 +156,7 @@ Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const Co
 			IShellItem *selectedItem = nullptr;
 			hr = dialog->GetResult(&selectedItem);
 			if (SUCCEEDED(hr)) {
-				Common::String path;
+				Common::Path path;
 				hr = getShellPath(selectedItem, path);
 				if (SUCCEEDED(hr)) {
 					choice = Common::FSNode(path);
@@ -169,10 +169,10 @@ Common::DialogManager::DialogResult Win32DialogManager::showFileBrowser(const Co
 			IShellItem *lastFolder = nullptr;
 			hr = dialog->GetFolder(&lastFolder);
 			if (SUCCEEDED(hr)) {
-				Common::String path;
+				Common::Path path;
 				hr = getShellPath(lastFolder, path);
 				if (SUCCEEDED(hr)) {
-					ConfMan.set("browser_lastpath", path);
+					ConfMan.setPath("browser_lastpath", path);
 				}
 				lastFolder->Release();
 			}
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index f945cc183e1..fb01783888e 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -524,7 +524,7 @@ void OSystem_Android::initBackend() {
 	}
 
 	if (!ConfMan.hasKey("browser_lastpath")) {
-		ConfMan.set("browser_lastpath", "/");
+		ConfMan.setPath("browser_lastpath", "/");
 	}
 
 	if (!ConfMan.hasKey("gui_scale")) {
diff --git a/gui/browser.cpp b/gui/browser.cpp
index 418f970193e..3c1a0a94a9c 100644
--- a/gui/browser.cpp
+++ b/gui/browser.cpp
@@ -186,12 +186,12 @@ void BrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
 
 void BrowserDialog::updateListing() {
 	// Update the path display
-	_currentPath->setEditString(_node.getPath());
+	_currentPath->setEditString(_node.getPath().toString(Common::Path::kNativeSeparator));
 
 	// We memorize the last visited path.
 	// Don't memorize a path that is not a directory
 	if (_node.isDirectory()) {
-		ConfMan.set("browser_lastpath", _node.getPath());
+		ConfMan.setPath("browser_lastpath", _node.getPath());
 	}
 
 	// Read in the data from the file system


Commit: 3c5fe56de6e3f912d45039cb51584737c7f6bee3
    https://github.com/scummvm/scummvm/commit/3c5fe56de6e3f912d45039cb51584737c7f6bee3
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: OPENGL: Small cleanups on paths

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro/parser.cpp


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 324547b62ab..c5cfab26ff5 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -63,7 +63,7 @@ static Graphics::Surface *loadViaImageDecoder(const Common::Path &fileName, Comm
 		Common::FSNode fsnode(fileName);
 		if (!fsnode.exists() || !fsnode.isReadable() || fsnode.isDirectory()
 				|| !(stream = fsnode.createReadStream())) {
-			warning("LibRetroPipeline::loadViaImageDecoder: Invalid file path '%s'", fileName.toString().c_str());
+			warning("LibRetroPipeline::loadViaImageDecoder: Invalid file path '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 			return nullptr;
 		}
 	}
@@ -479,7 +479,7 @@ bool LibRetroPipeline::loadPasses(Common::SearchSet &archSet) {
 			Common::FSNode fsnode(fileName);
 			if (!fsnode.exists() || !fsnode.isReadable() || fsnode.isDirectory()
 					|| !(stream = fsnode.createReadStream())) {
-				warning("LibRetroPipeline::loadPasses: Invalid file path '%s'", fileName.toString().c_str());
+				warning("LibRetroPipeline::loadPasses: Invalid file path '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 				return false;
 			}
 		}
@@ -742,7 +742,7 @@ void LibRetroPipeline::setShaderTexUniforms(const Common::String &prefix, Shader
 }
 
 LibRetroPipeline::Texture LibRetroPipeline::loadTexture(const Common::Path &fileName, Common::Archive *container, Common::SearchSet &archSet) {
-	Common::String baseName(fileName.getLastComponent().toString());
+	Common::String baseName(fileName.baseName());
 	const char *extension = nullptr;
 	for (int dotPos = baseName.size() - 1; dotPos >= 0; --dotPos) {
 		if (baseName[dotPos] == '.') {
diff --git a/backends/graphics/opengl/pipelines/libretro/parser.cpp b/backends/graphics/opengl/pipelines/libretro/parser.cpp
index f66b3479e56..3a4afa1e335 100644
--- a/backends/graphics/opengl/pipelines/libretro/parser.cpp
+++ b/backends/graphics/opengl/pipelines/libretro/parser.cpp
@@ -547,15 +547,10 @@ ShaderPreset *parsePreset(const Common::Path &shaderPreset, Common::SearchSet &a
 		Common::FSNode fsnode(shaderPreset);
 		if (!fsnode.exists() || !fsnode.isReadable() || fsnode.isDirectory()
 				|| !(stream = fsnode.createReadStream())) {
-			warning("LibRetro Preset Parsing: Invalid file path '%s'", shaderPreset.toString().c_str());
+			warning("LibRetro Preset Parsing: Invalid file path '%s'", shaderPreset.toString(Common::Path::kNativeSeparator).c_str());
 			return nullptr;
 		}
-#if defined(WIN32)
-		static const char delimiter = '\\';
-#else
-		static const char delimiter = '/';
-#endif
-		basePath = Common::Path(fsnode.getParent().getPath(), delimiter);
+		basePath = fsnode.getParent().getPath();
 	}
 
 	PresetParser parser;


Commit: 93a8f7f4d652edc1ed90deefd88e3233f1560eec
    https://github.com/scummvm/scummvm/commit/93a8f7f4d652edc1ed90deefd88e3233f1560eec
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Move Archive API to Path

Changed paths:
    common/archive.cpp
    common/archive.h
    common/compression/clickteam.cpp
    common/compression/clickteam.h
    common/compression/gentee_installer.cpp
    common/compression/installshield_cab.cpp
    common/compression/installshield_cab.h
    common/compression/installshieldv3_archive.cpp
    common/compression/installshieldv3_archive.h
    common/compression/stuffit.cpp
    common/compression/stuffit.h
    common/compression/unarj.cpp
    common/compression/unarj.h
    common/compression/unzip.cpp
    common/compression/unzip.h
    common/formats/prodos.cpp
    common/formats/prodos.h
    common/formats/winexe.cpp
    common/formats/winexe.h
    common/formats/xmlparser.cpp
    common/formats/xmlparser.h
    common/lua/scummvm_file.cpp
    common/lua/scummvm_file.h
    common/macresman.cpp
    common/macresman.h
    common/translation.cpp
    engines/dreamweb/rnca_archive.cpp
    engines/dreamweb/rnca_archive.h
    engines/mads/mps_installer.cpp
    engines/mads/mps_installer.h
    engines/saga/saga.cpp
    engines/sci/resource/resource.cpp


diff --git a/common/archive.cpp b/common/archive.cpp
index 2df42fdd312..ca42afd3a0e 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -239,7 +239,7 @@ SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMemberI
 	return memStream;
 }
 
-SharedArchiveContents MemcachingCaseInsensitiveArchive::readContentsForPathAltStream(const String &translatedPath, AltStreamType altStreamType) const {
+SharedArchiveContents MemcachingCaseInsensitiveArchive::readContentsForPathAltStream(const Path &translatedPath, AltStreamType altStreamType) const {
 	return SharedArchiveContents();
 }
 
@@ -251,7 +251,7 @@ bool MemcachingCaseInsensitiveArchive::CacheKey_EqualTo::operator()(const CacheK
 }
 
 uint MemcachingCaseInsensitiveArchive::CacheKey_Hash::operator()(const CacheKey &x) const {
-	return static_cast<uint>(hashit_lower(x.path) * 1000003u) ^ static_cast<uint>(x.altStreamType);
+	return static_cast<uint>(x.path.hashIgnoreCase() * 1000003u) ^ static_cast<uint>(x.altStreamType);
 };
 
 SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {
diff --git a/common/archive.h b/common/archive.h
index fb066b8ff14..f46686e545b 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -272,20 +272,18 @@ public:
 	SeekableReadStream *createReadStreamForMember(const Path &path) const;
 	SeekableReadStream *createReadStreamForMemberAltStream(const Path &path, Common::AltStreamType altStreamType) const;
 
-	virtual String translatePath(const Path &path) const {
-		// Most of users of this class implement DOS-like archives.
-		// Others override this method.
-		return normalizePath(path.toString('\\'), '\\');
+	virtual Path translatePath(const Path &path) const {
+		return path.normalize();
 	}
 
-	virtual SharedArchiveContents readContentsForPath(const String &translatedPath) const = 0;
-	virtual SharedArchiveContents readContentsForPathAltStream(const String &translatedPath, AltStreamType altStreamType) const;
+	virtual SharedArchiveContents readContentsForPath(const Path &translatedPath) const = 0;
+	virtual SharedArchiveContents readContentsForPathAltStream(const Path &translatedPath, AltStreamType altStreamType) const;
 
 private:
 	struct CacheKey {
 		CacheKey();
 
-		String path;
+		Path path;
 		AltStreamType altStreamType;
 	};
 
diff --git a/common/compression/clickteam.cpp b/common/compression/clickteam.cpp
index 8a525ebd430..451bcf2ed47 100644
--- a/common/compression/clickteam.cpp
+++ b/common/compression/clickteam.cpp
@@ -61,7 +61,7 @@ ClickteamInstaller::ClickteamFileDescriptor::ClickteamFileDescriptor(const Click
 		char *strings = (char *)tag + stringsOffset;
 		char *p;
 		for (p = strings; p < (char*)tag + lmax && *p; p++);
-		_fileName = Common::String(strings, p - strings);
+		_fileName = Common::Path(Common::String(strings, p - strings), Common::Path::kNoSeparator);
 		_fileDescriptorOffset = off;
 		_supported = true;
 		_isPatchFile = false;
@@ -81,7 +81,7 @@ ClickteamInstaller::ClickteamFileDescriptor::ClickteamFileDescriptor(const Click
 		byte type = tag[7];
 		if (type != 0) {
 			_supported = false;
-			_fileName = "";
+			_fileName.clear();
 			_fileDataOffset = 0;
 			_fileDescriptorOffset = off;
 			_compressedSize = 0;
@@ -119,7 +119,7 @@ ClickteamInstaller::ClickteamFileDescriptor::ClickteamFileDescriptor(const Click
 		char *strings = (char *)tag + stringsOffset;
 		char *p;
 		for (p = strings; p < (char*)tag + lmax && *p; p++);
-		_fileName = Common::String(strings, p - strings);
+		_fileName = Common::Path(Common::String(strings, p - strings), Common::Path::kNoSeparator);
 		_fileDescriptorOffset = off;
 		_compressedSize = 0;
 		_fileDataOffset = 0;
@@ -305,7 +305,7 @@ struct TagHead {
 };
 
 int ClickteamInstaller::findPatchIdx(const ClickteamFileDescriptor &desc, Common::SeekableReadStream *refStream,
-				     const Common::String &fileName,
+				     const Common::Path &fileName,
 				     uint32 crcXor, bool doWarn) {
 	bool hasMatching = refStream->size() == desc._uncompressedSize; // Maybe already patched?
 	for (uint i = 0; !hasMatching && i < desc._patchEntries.size(); i++)
@@ -315,7 +315,7 @@ int ClickteamInstaller::findPatchIdx(const ClickteamFileDescriptor &desc, Common
 		}
 	if (!hasMatching) {
 		if (doWarn)
-			warning("Couldn't find matching patch entry for file %s size %d", fileName.c_str(), (int)refStream->size());
+			warning("Couldn't find matching patch entry for file %s size %d", fileName.toString().c_str(), (int)refStream->size());
 		return -1;
 	}
 	uint32 crcOriginal = 0;
@@ -336,7 +336,7 @@ int ClickteamInstaller::findPatchIdx(const ClickteamFileDescriptor &desc, Common
 	if (patchDescIdx == -1 && refStream->size() == desc._uncompressedSize && crcOriginal == desc._expectedCRC)
 		return -2;
 	if (patchDescIdx < 0 && doWarn) {
-		warning("Couldn't find matching patch entry for file %s size %d and CRC 0x%x", fileName.c_str(), (int)refStream->size(), crcOriginal);
+		warning("Couldn't find matching patch entry for file %s size %d and CRC 0x%x", fileName.toString().c_str(), (int)refStream->size(), crcOriginal);
 	}
 	return patchDescIdx;
 }
@@ -348,7 +348,7 @@ ClickteamInstaller* ClickteamInstaller::open(Common::SeekableReadStream *stream,
 
 ClickteamInstaller* ClickteamInstaller::openPatch(Common::SeekableReadStream *stream, bool verifyOriginal, bool verifyAllowSkip,
 						  Common::Archive *reference, DisposeAfterUse::Flag dispose) {
-	Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> files;
+	Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> files;
 	HashMap<uint16, Common::SharedPtr<ClickteamTag>> tags;
 	uint32 crc_xor;
 
@@ -435,10 +435,10 @@ ClickteamInstaller* ClickteamInstaller::openPatch(Common::SeekableReadStream *st
 		return nullptr;
 
 	if (verifyOriginal && reference) {
-		for (Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
+		for (Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
 		     i != end; ++i) {
 			if (i->_value._isPatchFile) {
-				Common::ScopedPtr<Common::SeekableReadStream> refStream(reference->createReadStreamForMember(Common::Path(i->_key, '\\')));
+				Common::ScopedPtr<Common::SeekableReadStream> refStream(reference->createReadStreamForMember(i->_key));
 				if (!refStream) {
 					if (verifyAllowSkip) {
 						i->_value._isReferenceMissing = true;
@@ -453,7 +453,7 @@ ClickteamInstaller* ClickteamInstaller::openPatch(Common::SeekableReadStream *st
 	}
 
 	if (!reference) {
-		for (Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
+		for (Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::iterator i = files.begin(), end = files.end();
 		     i != end; ++i) {
 			if (i->_value._isPatchFile) {
 				i->_value._isReferenceMissing = true;
@@ -471,7 +471,7 @@ bool ClickteamInstaller::hasFile(const Path &path) const {
 int ClickteamInstaller::listMembers(ArchiveMemberList &list) const {
 	int members = 0;
 
-	for (Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::const_iterator i = _files.begin(), end = _files.end();
+	for (Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::const_iterator i = _files.begin(), end = _files.end();
 	     i != end; ++i) {
 		if (!i->_value._isReferenceMissing) {
 			list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(i->_key, *this)));
@@ -483,7 +483,7 @@ int ClickteamInstaller::listMembers(ArchiveMemberList &list) const {
 }
 
 const ArchiveMemberPtr ClickteamInstaller::getMember(const Path &path) const {
-	Common::String translated = translatePath(path);
+	Common::Path translated = translatePath(path);
 	ClickteamFileDescriptor el;
 	if (!_files.tryGetVal(translated, el))
 		return nullptr;
@@ -494,7 +494,7 @@ const ArchiveMemberPtr ClickteamInstaller::getMember(const Path &path) const {
 	return Common::SharedPtr<Common::ArchiveMember>(new GenericArchiveMember(el._fileName, *this));
 }
 
-Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Common::String& translated) const {
+Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Common::Path &translated) const {
 	ClickteamFileDescriptor desc;
 	byte *uncompressedBuffer = nullptr;
 
@@ -504,9 +504,9 @@ Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Comm
 		return Common::SharedArchiveContents();
 
 	if (desc._isPatchFile) {
-		Common::ScopedPtr<Common::SeekableReadStream> refStream(_reference->createReadStreamForMemberNext(Common::Path(translated, '\\'), this));
+		Common::ScopedPtr<Common::SeekableReadStream> refStream(_reference->createReadStreamForMemberNext(translated, this));
 		if (!refStream) {
-			warning("Couldn't open reference file for %s. Skipping", translated.c_str());
+			warning("Couldn't open reference file for %s. Skipping", translated.toString('\\').c_str());
 			return Common::SharedArchiveContents();
 		}
 		int patchDescIdx = findPatchIdx(desc, refStream.get(), translated, _crcXor, true);
@@ -608,7 +608,7 @@ Common::SharedArchiveContents ClickteamInstaller::readContentsForPath(const Comm
 		uint32 actualCrc = computeCRC(uncompressedBuffer, desc._uncompressedSize, 0);
 
 		if (actualCrc != expectedCrc) {
-			warning("CRC mismatch for %s: expected=%08x (obfuscated %08x), actual=%08x (back %08x)", desc._fileName.c_str(), expectedCrc, desc._expectedCRC, actualCrc, actualCrc ^ _crcXor);
+			warning("CRC mismatch for %s: expected=%08x (obfuscated %08x), actual=%08x (back %08x)", desc._fileName.toString().c_str(), expectedCrc, desc._expectedCRC, actualCrc, actualCrc ^ _crcXor);
 			delete[] uncompressedBuffer;
 			return Common::SharedArchiveContents();
 		}
diff --git a/common/compression/clickteam.h b/common/compression/clickteam.h
index 20f6979fdf4..57e983369e1 100644
--- a/common/compression/clickteam.h
+++ b/common/compression/clickteam.h
@@ -57,7 +57,7 @@ public:
 	bool hasFile(const Common::Path &path) const override;
 	int listMembers(Common::ArchiveMemberList&) const override;
 	const ArchiveMemberPtr getMember(const Common::Path &path) const override;
-	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
 
 	ClickteamTag* getTag(ClickteamTagId tagId) const;
 
@@ -74,7 +74,7 @@ private:
 	};
 	class ClickteamFileDescriptor {
 	private:
-		Common::String _fileName;
+		Common::Path _fileName;
 
 		// Offset of the file contents relative to the beginning of block3
 		uint32 _fileDataOffset;
@@ -97,8 +97,8 @@ private:
 		ClickteamFileDescriptor() : _fileDataOffset(0), _fileDescriptorOffset(0), _compressedSize(0), _uncompressedSize(0) {}
 	};
 
-	ClickteamInstaller(Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> files,
-			   Common::HashMap<uint16, Common::SharedPtr<ClickteamTag>> tags,
+	ClickteamInstaller(const Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> &files,
+			   const Common::HashMap<uint16, Common::SharedPtr<ClickteamTag>> &tags,
 			   uint32 crcXor, uint32 block3Offset, uint32 block3Size, Common::SeekableReadStream *stream,
 			   Common::Archive *reference,
 			   DisposeAfterUse::Flag dispose)
@@ -106,9 +106,9 @@ private:
 		  _reference(reference) {
 	}
 
-	static int findPatchIdx(const ClickteamFileDescriptor &desc, Common::SeekableReadStream *refStream, const Common::String &fileName,
+	static int findPatchIdx(const ClickteamFileDescriptor &desc, Common::SeekableReadStream *refStream, const Common::Path &fileName,
 				uint32 crcXor, bool doWarn);
-	Common::HashMap<Common::String, ClickteamFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _files;
+	Common::HashMap<Common::Path, ClickteamFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _files;
 	Common::HashMap<uint16, Common::SharedPtr<ClickteamTag>> _tags;
 	Common::DisposablePtr<Common::SeekableReadStream> _stream;
 	uint32 _crcXor, _block3Offset/*, _block3Size*/;
diff --git a/common/compression/gentee_installer.cpp b/common/compression/gentee_installer.cpp
index 620482e2ab7..a8cf832a5e3 100644
--- a/common/compression/gentee_installer.cpp
+++ b/common/compression/gentee_installer.cpp
@@ -581,29 +581,26 @@ bool DecompressingStream::rewind() {
 
 class ArchiveItem : public Common::ArchiveMember {
 public:
-	ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::String &path, const Common::String &name, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed);
+	ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::Path &path, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed);
 
 	Common::SeekableReadStream *createReadStream() const override;
 	Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
-	Common::String getName() const override;
-	Common::Path getPathInArchive() const override { return getName(); }
-	Common::String getFileName() const override { return getName(); }
-
-	const Common::String &getPath() const;
+	Common::String getName() const override { return getFileName(); }
+	Common::Path getPathInArchive() const override { return _path; }
+	Common::String getFileName() const override { return _path.getLastComponent().toString(); }
 
 private:
 	Common::SeekableReadStream *_stream;
 	Common::Mutex *_guardMutex;
-	Common::String _path;
-	Common::String _name;
+	Common::Path _path;
 	int64 _filePos;
 	uint _compressedSize;
 	uint _decompressedSize;
 	bool _isCompressed;
 };
 
-ArchiveItem::ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::String &path, const Common::String &name, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed)
-	: _stream(stream), _guardMutex(guardMutex), _path(path), _name(name), _filePos(filePos), _compressedSize(compressedSize), _decompressedSize(decompressedSize), _isCompressed(isCompressed) {
+ArchiveItem::ArchiveItem(Common::SeekableReadStream *stream, Common::Mutex *guardMutex, const Common::Path &path, int64 filePos, uint compressedSize, uint decompressedSize, bool isCompressed)
+	: _stream(stream), _guardMutex(guardMutex), _path(path), _filePos(filePos), _compressedSize(compressedSize), _decompressedSize(decompressedSize), _isCompressed(isCompressed) {
 }
 
 Common::SeekableReadStream *ArchiveItem::createReadStream() const {
@@ -627,14 +624,6 @@ Common::SeekableReadStream *ArchiveItem::createReadStreamForAltStream(Common::Al
 	return nullptr;
 }
 
-Common::String ArchiveItem::getName() const {
-	return _name;
-}
-
-const Common::String &ArchiveItem::getPath() const {
-	return _path;
-}
-
 class PackageArchive : public Common::Archive {
 public:
 	explicit PackageArchive(Common::SeekableReadStream *stream);
@@ -656,7 +645,7 @@ private:
 	static Common::String normalizePath(const Common::Path &path);
 
 	Common::Array<Common::SharedPtr<ArchiveItem> > _items;
-	Common::HashMap<Common::String, uint> _pathToItemIndex;
+	Common::HashMap<Common::Path, uint, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _pathToItemIndex;
 
 	Common::SeekableReadStream *_stream;
 };
@@ -792,23 +781,12 @@ bool PackageArchive::load(const char *prefix) {
 
 			if (fileName.hasPrefix(prefix)) {
 				fileName = fileName.substr(strlen(prefix));
+				fileName.replace('\\', '/');
+				Common::Path path(fileName, '/');
 
-				size_t bsPos = fileName.findFirstOf('\\');
-				while (bsPos != Common::String::npos) {
-					fileName.replace(bsPos, 1, "/");
-					bsPos = fileName.findFirstOf('\\');
-				}
-
-				Common::String fileNameNoDir = fileName;
-
-				size_t lastSlashPos = fileNameNoDir.findLastOf('/');
-				if (lastSlashPos != Common::String::npos)
-					fileNameNoDir = fileNameNoDir.substr(lastSlashPos + 1);
-
-				Common::SharedPtr<ArchiveItem> item(new ArchiveItem(_stream, getGuardMutex(), fileName, fileNameNoDir, dataStart, static_cast<uint>(dataEnd - dataStart), decompressedSize, isCompressed));
+				Common::SharedPtr<ArchiveItem> item(new ArchiveItem(_stream, getGuardMutex(), path, dataStart, static_cast<uint>(dataEnd - dataStart), decompressedSize, isCompressed));
 
-				fileName.toLowercase();
-				_pathToItemIndex[fileName] = _items.size();
+				_pathToItemIndex[path] = _items.size();
 
 				_items.push_back(item);
 			}
@@ -852,7 +830,7 @@ Common::String PackageArchive::normalizePath(const Common::Path &path) {
 }
 
 bool PackageArchive::hasFile(const Common::Path &path) const {
-	return _pathToItemIndex.find(normalizePath(path)) != _pathToItemIndex.end();
+	return _pathToItemIndex.find(path) != _pathToItemIndex.end();
 }
 
 int PackageArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -863,12 +841,11 @@ int PackageArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 int PackageArchive::listMatchingMembers(Common::ArchiveMemberList &list, const Common::Path &pattern, bool matchPathComponents) const {
-	Common::String patternString = pattern.toString();
 	int matches = 0;
 	const char *wildcardExclusions = matchPathComponents ? NULL : "/";
 
 	for (const Common::SharedPtr<ArchiveItem> &item : _items) {
-		if (item->getPath().matchString(patternString, true, wildcardExclusions)) {
+		if (normalizePath(item->getPathInArchive()).matchString(normalizePath(pattern), false, wildcardExclusions)) {
 			list.push_back(item.staticCast<Common::ArchiveMember>());
 			matches++;
 		}
@@ -878,7 +855,7 @@ int PackageArchive::listMatchingMembers(Common::ArchiveMemberList &list, const C
 }
 
 const Common::ArchiveMemberPtr PackageArchive::getMember(const Common::Path &path) const {
-	Common::HashMap<Common::String, uint>::const_iterator it = _pathToItemIndex.find(normalizePath(path));
+	Common::HashMap<Common::Path, uint, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo>::const_iterator it = _pathToItemIndex.find(path);
 	if (it == _pathToItemIndex.end())
 		return nullptr;
 
diff --git a/common/compression/installshield_cab.cpp b/common/compression/installshield_cab.cpp
index 52319028407..45bd16e23a2 100644
--- a/common/compression/installshield_cab.cpp
+++ b/common/compression/installshield_cab.cpp
@@ -87,7 +87,7 @@ class InstallShieldCabinet : public Archive {
 public:
 	InstallShieldCabinet();
 
-	bool open(const String *baseName, const FSNode *node);
+	bool open(const Path *baseName, const FSNode *node);
 	void close();
 
 	// Archive API implementation
@@ -123,22 +123,22 @@ private:
 	};
 
 	int _version;
-	typedef HashMap<String, FileEntry, IgnoreCase_Hash, IgnoreCase_EqualTo> FileMap;
+	typedef HashMap<Path, FileEntry, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _map;
-	String _baseName;
+	Path _baseName;
 	Common::Array<VolumeHeader> _volumeHeaders;
 	bool _useSearchMan;
 
 	static bool readVolumeHeader(SeekableReadStream *volumeStream, VolumeHeader &inVolumeHeader);
 
-	String getHeaderName() const;
-	String getVolumeName(uint volume) const;
+	Path getHeaderName() const;
+	Path getVolumeName(uint volume) const;
 };
 
 InstallShieldCabinet::InstallShieldCabinet() : _version(0), _useSearchMan(false) {
 }
 
-bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
+bool InstallShieldCabinet::open(const Path *baseName, const FSNode *node) {
 	// Store the base name so we can generate file names
 	if (baseName) {
 		_baseName = *baseName;
@@ -150,8 +150,10 @@ bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
 		return false;
 	}
 
-	if (_baseName.hasSuffix(".cab") || _baseName.hasSuffix(".hdr")) {
-		_baseName.erase(_baseName.size() - 5, String::npos);
+	String strippedName = _baseName.baseName();
+	if (strippedName.hasSuffix(".cab") || strippedName.hasSuffix(".hdr")) {
+		strippedName.erase(strippedName.size() - 5, String::npos);
+		_baseName = _baseName.getParent().appendComponent(strippedName);
 	}
 
 	uint fileIndex = 0;
@@ -250,7 +252,7 @@ bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
 
 			// Then let's get the string
 			file->seek(headerHeader.cabDescriptorOffset + fileTableOffset + nameOffset);
-			String fileName = file->readString();
+			Path fileName(file->readString(), '\\');
 
 			// Entries can appear in multiple volumes (sometimes erroneously).
 			// We keep the one with the lowest volume ID
@@ -303,10 +305,10 @@ bool InstallShieldCabinet::open(const String *baseName, const FSNode *node) {
 
 			// Then let's get the string
 			file->seek(headerHeader.cabDescriptorOffset + fileTableOffset + nameOffset);
-			String fileName = file->readString();
+			Path fileName(file->readString(), '\\');
 
 			if (entry.volume == 0) {
-				warning("Couldn't find the volume for file %s", fileName.c_str());
+				warning("Couldn't find the volume for file %s", fileName.toString('\\').c_str());
 				close();
 				return false;
 			}
@@ -331,8 +333,7 @@ void InstallShieldCabinet::close() {
 }
 
 bool InstallShieldCabinet::hasFile(const Path &path) const {
-	String name = path.toString();
-	return _map.contains(name);
+	return _map.contains(path);
 }
 
 int InstallShieldCabinet::listMembers(ArchiveMemberList &list) const {
@@ -347,14 +348,13 @@ const ArchiveMemberPtr InstallShieldCabinet::getMember(const Path &path) const {
 }
 
 SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &path) const {
-	String name = path.toString();
-	if (!_map.contains(name))
+	if (!_map.contains(path))
 		return nullptr;
 
-	const FileEntry &entry = _map[name];
+	const FileEntry &entry = _map[path];
 
 	if (entry.flags & kObfuscated) {
-		warning("Cannot extract obfuscated file %s", name.c_str());
+		warning("Cannot extract obfuscated file %s", path.toString().c_str());
 		return nullptr;
 	}
 
@@ -369,7 +369,7 @@ SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &
 	}
 
 	if (!stream) {
-		warning("Failed to open volume for file '%s'", name.c_str());
+		warning("Failed to open volume for file '%s'", path.toString().c_str());
 		return nullptr;
 	}
 
@@ -396,7 +396,7 @@ SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &
 			}
 			
 			if (!stream.get()) {
-				warning("Failed to read split file %s", name.c_str());
+				warning("Failed to read split file %s", path.toString().c_str());
 				free(src);
 				return nullptr;
 			}
@@ -428,7 +428,7 @@ SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Path &
 	// Entries with size 0 are valid, and do not need to be inflated
 	if (entry.compressedSize != 0) {
 		if (!inflateZlibInstallShield(dst, entry.uncompressedSize, src, entry.compressedSize)) {
-			warning("failed to inflate CAB file '%s'", name.c_str());
+			warning("failed to inflate CAB file '%s'", path.toString().c_str());
 			free(dst);
 			free(src);
 			return nullptr;
@@ -499,17 +499,17 @@ bool InstallShieldCabinet::readVolumeHeader(SeekableReadStream *volumeStream, In
 	return true;
 }
 
-String InstallShieldCabinet::getHeaderName() const {
-	return _baseName + "1.hdr";
+Path InstallShieldCabinet::getHeaderName() const {
+	return _baseName.append("1.hdr");
 }
 
-String InstallShieldCabinet::getVolumeName(uint volume) const {
-	return String::format("%s%d.cab", _baseName.c_str(), volume);
+Path InstallShieldCabinet::getVolumeName(uint volume) const {
+	return _baseName.append(String::format("%d.cab", volume));
 }
 
 } // End of anonymous namespace
 
-Archive *makeInstallShieldArchive(const String &baseName) {
+Archive *makeInstallShieldArchive(const Path &baseName) {
 	InstallShieldCabinet *cab = new InstallShieldCabinet();
 	if (!cab->open(&baseName, nullptr)) {
 		delete cab;
diff --git a/common/compression/installshield_cab.h b/common/compression/installshield_cab.h
index 1115429f67d..b6ef5dcb82f 100644
--- a/common/compression/installshield_cab.h
+++ b/common/compression/installshield_cab.h
@@ -49,7 +49,7 @@ class SeekableReadStream;
  * 
  * @param baseName The base filename, e.g. the "data" in "data1.cab"
  */
-Archive *makeInstallShieldArchive(const Common::String &baseName);
+Archive *makeInstallShieldArchive(const Common::Path &baseName);
 
 /**
  * This factory method creates an Archive instance corresponding to the content
diff --git a/common/compression/installshieldv3_archive.cpp b/common/compression/installshieldv3_archive.cpp
index 3a8354b1387..47205249c6c 100644
--- a/common/compression/installshieldv3_archive.cpp
+++ b/common/compression/installshieldv3_archive.cpp
@@ -34,7 +34,7 @@ InstallShieldV3::~InstallShieldV3() {
 	close();
 }
 
-bool InstallShieldV3::open(const Common::String &filename) {
+bool InstallShieldV3::open(const Common::Path &filename) {
 	close();
 
 	_stream = SearchMan.createReadStreamForMember(filename);
@@ -74,8 +74,7 @@ void InstallShieldV3::close() {
 }
 
 bool InstallShieldV3::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return _map.contains(name);
+	return _map.contains(path);
 }
 
 int InstallShieldV3::listMembers(Common::ArchiveMemberList &list) const {
@@ -86,20 +85,14 @@ int InstallShieldV3::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr InstallShieldV3::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *InstallShieldV3::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	// Make sure "/" is converted to "\"
-	while (name.contains("/"))
-		Common::replace(name, "/", "\\");
-
-	if (!_stream || !_map.contains(name))
+	if (!_stream || !_map.contains(path))
 		return nullptr;
 
-	const FileEntry &entry = _map[name];
+	const FileEntry &entry = _map[path];
 
 	// Seek to our offset and then send it off to the decompressor
 	_stream->seek(entry.offset);
@@ -178,7 +171,7 @@ bool InstallShieldV3::read() {
 			if (!dirNames[i].empty())
 				name = dirNames[i] + "\\" + name;
 
-			_map[name] = entry;
+			_map[Path(name, '\\')] = entry;
 			debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
 					entry.offset, entry.compressedSize, entry.uncompressedSize);
 		}
diff --git a/common/compression/installshieldv3_archive.h b/common/compression/installshieldv3_archive.h
index 34318f1228c..98df7de7a0c 100644
--- a/common/compression/installshieldv3_archive.h
+++ b/common/compression/installshieldv3_archive.h
@@ -37,7 +37,7 @@ public:
 	InstallShieldV3();
 	~InstallShieldV3() override;
 
-	bool open(const Common::String &filename);
+	bool open(const Common::Path &filename);
 	bool open(const Common::FSNode &node);
 	bool open(Common::SeekableReadStream *stream);
 	void close();
@@ -61,7 +61,7 @@ private:
 
 	Common::SeekableReadStream *_stream;
 
-	typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Path, FileEntry, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _map;
 };
 
diff --git a/common/compression/stuffit.cpp b/common/compression/stuffit.cpp
index 704b1882d5c..dddfa254a29 100644
--- a/common/compression/stuffit.cpp
+++ b/common/compression/stuffit.cpp
@@ -43,7 +43,7 @@ public:
 	StuffItArchive();
 	~StuffItArchive() override;
 
-	bool open(const Common::String &filename, bool flattenTree);
+	bool open(const Common::Path &filename, bool flattenTree);
 	bool open(Common::SeekableReadStream *stream, bool flattenTree);
 	void close();
 	bool isOpen() const { return _stream != nullptr; }
@@ -52,9 +52,9 @@ public:
 	bool hasFile(const Common::Path &path) const override;
 	int listMembers(Common::ArchiveMemberList &list) const override;
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
-	Common::SharedArchiveContents readContentsForPath(const Common::String &name) const override;
-	Common::SharedArchiveContents readContentsForPathAltStream(const String &translatedPath, Common::AltStreamType altStreamType) const override;
-	Common::String translatePath(const Common::Path &path) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::Path &name) const override;
+	Common::SharedArchiveContents readContentsForPathAltStream(const Common::Path &translatedPath, Common::AltStreamType altStreamType) const override;
+	Common::Path translatePath(const Common::Path &path) const override;
 	char getPathSeparator() const override;
 
 private:
@@ -82,10 +82,10 @@ private:
 
 	Common::SeekableReadStream *_stream;
 
-	typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, FileEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _map;
 
-	typedef Common::HashMap<Common::String, Common::MacFinderInfoData, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> MetadataMap;
+	typedef Common::HashMap<Common::Path, Common::MacFinderInfoData, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> MetadataMap;
 	MetadataMap _metadataMap;
 
 	bool _flattenTree;
@@ -98,7 +98,7 @@ private:
 	void update14(uint16 first, uint16 last, byte *code, uint16 *freq) const;
 	void readTree14(Common::BitStream8LSB *bits, SIT14Data *dat, uint16 codesize, uint16 *result) const;
 
-	Common::SharedArchiveContents readContentsForPathFork(const String &translatedPath, bool isResFork) const;
+	Common::SharedArchiveContents readContentsForPathFork(const Common::Path &translatedPath, bool isResFork) const;
 };
 
 StuffItArchive::StuffItArchive() : Common::MemcachingCaseInsensitiveArchive(), _flattenTree(false) {
@@ -117,7 +117,7 @@ static const uint32 s_magicNumbers[] = {
 	MKTAG('S', 'T', 'i', '3'), MKTAG('S', 'T', 'i', '4'), MKTAG('S', 'T', '4', '6')
 };
 
-bool StuffItArchive::open(const Common::String &filename, bool flattenTree) {
+bool StuffItArchive::open(const Common::Path &filename, bool flattenTree) {
 	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(filename);
 	return open(stream, flattenTree);
 }
@@ -237,12 +237,14 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream, bool flattenTree)
 		if (!flattenTree)
 			name = dirPrefix + name;
 
-		_metadataMap[name] = finfo.toData();
+		Common::Path path(name, ':');
+
+		_metadataMap[path] = finfo.toData();
 
 		if (dataForkUncompressedSize != 0) {
 			// We have a data fork
 
-			FileEntryFork &entryFork = _map[name].dataFork;
+			FileEntryFork &entryFork = _map[path].dataFork;
 			entryFork.compression = dataForkCompression;
 			entryFork.uncompressedSize = dataForkUncompressedSize;
 			entryFork.compressedSize = dataForkCompressedSize;
@@ -255,7 +257,7 @@ bool StuffItArchive::open(Common::SeekableReadStream *stream, bool flattenTree)
 		if (resForkUncompressedSize != 0) {
 			// We have a resource fork
 
-			FileEntryFork &entryFork = _map[name].resFork;
+			FileEntryFork &entryFork = _map[path].resFork;
 			entryFork.compression = resForkCompression;
 			entryFork.uncompressedSize = resForkUncompressedSize;
 			entryFork.compressedSize = resForkCompressedSize;
@@ -279,8 +281,7 @@ void StuffItArchive::close() {
 }
 
 bool StuffItArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString(':');
-	return _map.contains(name);
+	return _map.contains(path);
 }
 
 int StuffItArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -294,11 +295,11 @@ const Common::ArchiveMemberPtr StuffItArchive::getMember(const Common::Path &pat
 	return Common::ArchiveMemberPtr(new StuffItArchiveMember(path, *this));
 }
 
-Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::String &name) const {
-	return readContentsForPathFork(name, false);
+Common::SharedArchiveContents StuffItArchive::readContentsForPath(const Common::Path &path) const {
+	return readContentsForPathFork(path, false);
 }
 
-Common::SharedArchiveContents StuffItArchive::readContentsForPathAltStream(const String &translatedPath, Common::AltStreamType altStreamType) const {
+Common::SharedArchiveContents StuffItArchive::readContentsForPathAltStream(const Common::Path &translatedPath, Common::AltStreamType altStreamType) const {
 	if (altStreamType == Common::AltStreamType::MacFinderInfo) {
 		if (_metadataMap.contains(translatedPath)) {
 			const Common::MacFinderInfoData &metadata = _metadataMap[translatedPath];
@@ -315,13 +316,13 @@ Common::SharedArchiveContents StuffItArchive::readContentsForPathAltStream(const
 	return Common::SharedArchiveContents();
 }
 
-Common::SharedArchiveContents StuffItArchive::readContentsForPathFork(const Common::String &name, bool isResFork) const {
-	FileMap::const_iterator entryIt = _map.find(name);
+Common::SharedArchiveContents StuffItArchive::readContentsForPathFork(const Common::Path &path, bool isResFork) const {
+	FileMap::const_iterator entryIt = _map.find(path);
 
 	if (entryIt == _map.end())
 		return Common::SharedArchiveContents();
 
-	const FileEntry &entry = _map[name];
+	const FileEntry &entry = entryIt->_value;
 	const FileEntryFork &entryFork = isResFork ? entry.resFork : entry.dataFork;
 
 	if (entryFork.uncompressedSize == 0) {
@@ -358,14 +359,14 @@ Common::SharedArchiveContents StuffItArchive::readContentsForPathFork(const Comm
 	uint16 actualCRC = Common::CRC16().crcFast(uncompressedBlock, entryFork.uncompressedSize);
 
 	if (actualCRC != entryFork.crc) {
-		error("StuffItArchive::readContentsForPath(): CRC mismatch: %04x vs %04x for file %s %s fork", actualCRC, entryFork.crc, name.c_str(), (isResFork ? "res" : "data"));
+		error("StuffItArchive::readContentsForPath(): CRC mismatch: %04x vs %04x for file %s %s fork", actualCRC, entryFork.crc, path.toString().c_str(), (isResFork ? "res" : "data"));
 	}
 
 	return Common::SharedArchiveContents(uncompressedBlock, entryFork.uncompressedSize);
 }
 
-Common::String StuffItArchive::translatePath(const Common::Path &path) const {
-	return _flattenTree ? path.getLastComponent().toString() : path.toString(':');
+Common::Path StuffItArchive::translatePath(const Common::Path &path) const {
+	return _flattenTree ? path.getLastComponent() : path;
 }
 
 char StuffItArchive::getPathSeparator() const {
@@ -1133,7 +1134,7 @@ bool StuffItArchive::StuffItArchiveMember::isInMacArchive() const {
 	return true;
 }
 
-Common::Archive *createStuffItArchive(const Common::String &fileName, bool flattenTree) {
+Common::Archive *createStuffItArchive(const Common::Path &fileName, bool flattenTree) {
 	StuffItArchive *archive = new StuffItArchive();
 
 	if (!archive->open(fileName, flattenTree)) {
diff --git a/common/compression/stuffit.h b/common/compression/stuffit.h
index fa234106e71..2e74f2fbaf5 100644
--- a/common/compression/stuffit.h
+++ b/common/compression/stuffit.h
@@ -43,7 +43,7 @@ namespace Common {
  */
 
 class Archive;
-class String;
+class Path;
 class SeekableReadStream;
 
 /**
@@ -55,7 +55,7 @@ class SeekableReadStream;
  *
  * @return                The StuffIt archive
  */
-Archive *createStuffItArchive(const String &fileName, bool flattenTree = false);
+Archive *createStuffItArchive(const Path &fileName, bool flattenTree = false);
 Archive *createStuffItArchive(SeekableReadStream *stream, bool flattenTree = false);
 
 /** @} */
diff --git a/common/compression/unarj.cpp b/common/compression/unarj.cpp
index 4329877809f..007f4018a15 100644
--- a/common/compression/unarj.cpp
+++ b/common/compression/unarj.cpp
@@ -697,24 +697,24 @@ struct ArjFileChunk {
 	ArjFileChunk(ArjHeader* header, uint volume) : _header(header), _volume(volume) {}
 };
 
-typedef HashMap<String, Array<ArjFileChunk>, IgnoreCase_Hash, IgnoreCase_EqualTo> ArjHeadersMap;
+typedef HashMap<Path, Array<ArjFileChunk>, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> ArjHeadersMap;
 
 class ArjArchive : public MemcachingCaseInsensitiveArchive {
 	ArjHeadersMap _headers;
-	Array<String> _arjFilenames;
+	Array<Path> _arjFilenames;
 	bool _flattenTree;
 
 public:
-	ArjArchive(const Array<String> &names, bool flattenTree);
+	ArjArchive(const Array<Path> &names, bool flattenTree);
 	virtual ~ArjArchive();
 
 	// Archive implementation
 	bool hasFile(const Path &path) const override;
 	int listMembers(ArchiveMemberList &list) const override;
 	const ArchiveMemberPtr getMember(const Path &path) const override;
-	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
-	Common::String translatePath(const Common::Path &path) const override {
-		return _flattenTree ? path.getLastComponent().toString() : path.toString();
+	Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
+	Common::Path translatePath(const Common::Path &path) const override {
+		return _flattenTree ? path.getLastComponent() : path;
 	}
 };
 
@@ -727,7 +727,7 @@ ArjArchive::~ArjArchive() {
        }
 }
 
-ArjArchive::ArjArchive(const Array<String> &filenames, bool flattenTree) : _arjFilenames(filenames), _flattenTree(flattenTree) {
+ArjArchive::ArjArchive(const Array<Path> &filenames, bool flattenTree) : _arjFilenames(filenames), _flattenTree(flattenTree) {
 	for (uint i = 0; i < _arjFilenames.size(); i++) {
 		File arjFile;
 
@@ -753,21 +753,28 @@ ArjArchive::ArjArchive(const Array<String> &filenames, bool flattenTree) : _arjF
 		while ((header = readHeader(arjFile)) != nullptr) {
 			const char *name = header->filename;
 
-			if (_flattenTree)
-				for (const char *p = header->filename; *p; p++)
-					if (*p == '\\' || *p == '/')
+			if (_flattenTree) {
+				for (const char *p = header->filename; *p; p++) {
+					if (*p == '\\' || *p == '/') {
 						name = p + 1;
-			_headers[name].push_back(ArjFileChunk(header, i));
+					}
+				}
+			} else {
+				for (char *p = header->filename; *p; p++) {
+					if (*p == '\\')
+						*p = '/';
+				}
+			}
+			_headers[Path(name)].push_back(ArjFileChunk(header, i));
 			arjFile.seek(header->compSize, SEEK_CUR);
 		}
 	}
 
-	debug(0, "ArjArchive::ArjArchive(%d volume(s) starting with %s): Located %d files", filenames.size(), filenames.empty() ? "" : filenames[0].c_str(), _headers.size());
+	debug(0, "ArjArchive::ArjArchive(%d volume(s) starting with %s): Located %d files", filenames.size(), filenames.empty() ? "" : filenames[0].toString(Common::Path::kNativeSeparator).c_str(), _headers.size());
 }
 
 bool ArjArchive::hasFile(const Path &path) const {
-	String name = path.toString();
-	return _headers.contains(name);
+	return _headers.contains(path);
 }
 
 int ArjArchive::listMembers(ArchiveMemberList &list) const {
@@ -775,7 +782,7 @@ int ArjArchive::listMembers(ArchiveMemberList &list) const {
 
 	ArjHeadersMap::const_iterator it = _headers.begin();
 	for ( ; it != _headers.end(); ++it) {
-		list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(Common::String(it->_value[0]._header->filename), *this)));
+		list.push_back(ArchiveMemberList::value_type(new GenericArchiveMember(Path(it->_value[0]._header->filename), *this)));
 		matches++;
 	}
 
@@ -783,19 +790,18 @@ int ArjArchive::listMembers(ArchiveMemberList &list) const {
 }
 
 const ArchiveMemberPtr ArjArchive::getMember(const Path &path) const {
-	String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return ArchiveMemberPtr();
 
-	return ArchiveMemberPtr(new GenericArchiveMember(name, *this));
+	return ArchiveMemberPtr(new GenericArchiveMember(path, *this));
 }
 
-Common::SharedArchiveContents ArjArchive::readContentsForPath(const Common::String& name) const {
-	if (!_headers.contains(name)) {
+Common::SharedArchiveContents ArjArchive::readContentsForPath(const Common::Path &path) const {
+	if (!_headers.contains(path)) {
 		return Common::SharedArchiveContents();
 	}
 
-	const Array <ArjFileChunk>& hdrs = _headers[name];
+	const Array <ArjFileChunk>& hdrs = _headers[path];
 
 	uint64 uncompressedSize = 0;
 	uint totalChunks;
@@ -848,11 +854,11 @@ Common::SharedArchiveContents ArjArchive::readContentsForPath(const Common::Stri
 	return Common::SharedArchiveContents(uncompressedData, uncompressedSize);
 }
 
-Archive *makeArjArchive(const String &name, bool flattenTree) {
+Archive *makeArjArchive(const Path &name, bool flattenTree) {
 	return new ArjArchive({name}, flattenTree);
 }
 
-Archive *makeArjArchive(const Array<String> &names, bool flattenTree) {
+Archive *makeArjArchive(const Array<Path> &names, bool flattenTree) {
 	return new ArjArchive(names, flattenTree);
 }
 
diff --git a/common/compression/unarj.h b/common/compression/unarj.h
index ba90f028de8..8773a01fc5b 100644
--- a/common/compression/unarj.h
+++ b/common/compression/unarj.h
@@ -49,12 +49,12 @@ class Archive;
  *
  * May return 0 in case of a failure.
  */
-Archive *makeArjArchive(const String &name, bool flattenTree = false);
+Archive *makeArjArchive(const Path &name, bool flattenTree = false);
 
 /**
  * Similar to previous but for multi-volume archives
  */
-Archive *makeArjArchive(const Array<String> &names, bool flattenTree = false);
+Archive *makeArjArchive(const Array<Path> &names, bool flattenTree = false);
 
 /** @} */
 
diff --git a/common/compression/unzip.cpp b/common/compression/unzip.cpp
index df49edcca57..39276b1699d 100644
--- a/common/compression/unzip.cpp
+++ b/common/compression/unzip.cpp
@@ -318,8 +318,8 @@ typedef struct {
 	unz_file_info_internal cur_file_info_internal;	/* private info about it*/
 } cached_file_in_zip;
 
-typedef Common::HashMap<Common::String, cached_file_in_zip, Common::IgnoreCase_Hash,
-	Common::IgnoreCase_EqualTo> ZipHash;
+typedef Common::HashMap<Common::Path, cached_file_in_zip, Common::Path::IgnoreCase_Hash,
+	Common::Path::IgnoreCase_EqualTo> ZipHash;
 
 /* unz_s contain internal information about the zipfile
 */
@@ -535,12 +535,14 @@ unzFile unzOpen(Common::SeekableReadStream *stream, bool flattenTree) {
 		fe.cur_file_info = us->cur_file_info;
 		fe.cur_file_info_internal = us->cur_file_info_internal;
 
-		Common::String name(szCurrentFileName);
-
 		bool isDirectory = false;
-		if (name.hasSuffix("/") || name.hasSuffix("\\")) {
-			isDirectory = true;
-			name = name.substr(0, name.size() - 1);
+		if (*szCurrentFileName) {
+			char *szCurrentFileNameSuffix = szCurrentFileName + strlen(szCurrentFileName) - 1;
+			if (*szCurrentFileNameSuffix == '/' || *szCurrentFileNameSuffix == '\\') {
+				isDirectory = true;
+				// Strip trailing path terminator
+				*szCurrentFileNameSuffix = '\0';
+			}
 		}
 
 		// If platform is specified as MS-DOS or Unix, check the directory flag
@@ -564,20 +566,21 @@ unzFile unzOpen(Common::SeekableReadStream *stream, bool flattenTree) {
 			}
 		}
 
+		const char *name = szCurrentFileName;
 		if (flattenTree) {
 			if (isDirectory)
 				continue;
 
-			size_t slashPos = name.findLastOf('\\');
-			if (slashPos != Common::String::npos)
-				name = name.substr(slashPos + 1);
-
-			slashPos = name.findLastOf('/');
-			if (slashPos != Common::String::npos)
-				name = name.substr(slashPos + 1);
+			for (const char *p = szCurrentFileName; *p; p++)
+				if (*p == '\\' || *p == '/')
+					name = p + 1;
+		} else {
+			for (char *p = szCurrentFileName; *p; p++)
+				if (*p == '\\')
+					*p = '/';
 		}
 
-		us->_hash[name] = fe;
+		us->_hash[Common::Path(name)] = fe;
 
 		// Move to the next file
 		err = unzGoToNextFile((unzFile)us);
@@ -832,21 +835,18 @@ int unzGoToNextFile(unzFile file) {
   UNZ_OK if the file is found. It becomes the current file.
   UNZ_END_OF_LIST_OF_FILE if the file is not found
 */
-int unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) {
+int unzLocateFile(unzFile file, const Common::Path &szFileName, int iCaseSensitivity) {
 	unz_s *s;
 
 	if (file == nullptr)
 		return UNZ_PARAMERROR;
 
-	if (strlen(szFileName) >= UNZ_MAXFILENAMEINZIP)
-		return UNZ_PARAMERROR;
-
 	s=(unz_s *)file;
 	if (!s->current_file_ok)
 		return UNZ_END_OF_LIST_OF_FILE;
 
 	// Check to see if the entry exists
-	ZipHash::iterator i = s->_hash.find(Common::String(szFileName));
+	ZipHash::iterator i = s->_hash.find(szFileName);
 	if (i == s->_hash.end())
 		return UNZ_END_OF_LIST_OF_FILE;
 
@@ -1039,9 +1039,9 @@ public:
 	bool isPathDirectory(const Path &path) const override;
 	int listMembers(ArchiveMemberList &list) const override;
 	const ArchiveMemberPtr getMember(const Path &path) const override;
-	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
-	Common::String translatePath(const Common::Path &path) const override {
-		return _flattenTree ? path.getLastComponent().toString() : path.toString();
+	Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
+	Common::Path translatePath(const Common::Path &path) const override {
+		return _flattenTree ? path.getLastComponent() : path;
 	}
 };
 
@@ -1072,14 +1072,11 @@ ZipArchive::~ZipArchive() {
 }
 
 bool ZipArchive::hasFile(const Path &path) const {
-	String name = path.toString();
-	return (unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK);
+	return (unzLocateFile(_zipFile, path, 2) == UNZ_OK);
 }
 
 bool ZipArchive::isPathDirectory(const Path &path) const {
-	String name = path.toString();
-
-	if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
+	if (unzLocateFile(_zipFile, path, 2) != UNZ_OK)
 		return false;
 
 	unz_file_info fi;
@@ -1103,15 +1100,14 @@ int ZipArchive::listMembers(ArchiveMemberList &list) const {
 }
 
 const ArchiveMemberPtr ZipArchive::getMember(const Path &path) const {
-	String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return ArchiveMemberPtr();
 
 	return ArchiveMemberPtr(new GenericArchiveMember(path, *this));
 }
 
-Common::SharedArchiveContents ZipArchive::readContentsForPath(const Common::String& name) const {
-	if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
+Common::SharedArchiveContents ZipArchive::readContentsForPath(const Common::Path &path) const {
+	if (unzLocateFile(_zipFile, path, 2) != UNZ_OK)
 		return Common::SharedArchiveContents();
 #ifndef USE_ZLIB
 	return unzOpenCurrentFile(_zipFile, _crc);
@@ -1120,7 +1116,7 @@ Common::SharedArchiveContents ZipArchive::readContentsForPath(const Common::Stri
 #endif
 }
 
-Archive *makeZipArchive(const String &name, bool flattenTree) {
+Archive *makeZipArchive(const Path &name, bool flattenTree) {
 	return makeZipArchive(SearchMan.createReadStreamForMember(name), flattenTree);
 }
 
diff --git a/common/compression/unzip.h b/common/compression/unzip.h
index ee9b070faa3..3e942802b59 100644
--- a/common/compression/unzip.h
+++ b/common/compression/unzip.h
@@ -45,7 +45,7 @@ class SeekableReadStream;
  *
  * May return 0 in case of a failure.
  */
-Archive *makeZipArchive(const String &name, bool flattenTree = false);
+Archive *makeZipArchive(const Path &name, bool flattenTree = false);
 
 /**
  * This factory method creates an Archive instance corresponding to the content
diff --git a/common/formats/prodos.cpp b/common/formats/prodos.cpp
index 78b7c0ad2c0..29c78088825 100644
--- a/common/formats/prodos.cpp
+++ b/common/formats/prodos.cpp
@@ -351,7 +351,7 @@ void ProDOSDisk::getVolumeBitmap(VolHeader *h) {
 
 /* Gets the volume information and parses the filesystem, adding file objects to a map as it goes */
 
-bool ProDOSDisk::open(const Common::String filename) {
+bool ProDOSDisk::open(const Common::Path &filename) {
 	_disk.open(filename);
 	_disk.read(_loader1, kBlockSize);
 	_disk.read(_loader2, kBlockSize);
@@ -371,7 +371,7 @@ bool ProDOSDisk::open(const Common::String filename) {
 
 /* Constructor simply calls open(), and if it is successful it prints a statement */
 
-ProDOSDisk::ProDOSDisk(const Common::String filename) {
+ProDOSDisk::ProDOSDisk(const Common::Path &filename) {
 	if (open(filename)) {
 		//debug("%s has been loaded", filename.c_str());
 	}
diff --git a/common/formats/prodos.h b/common/formats/prodos.h
index f71db7ebfea..92502e96e4f 100644
--- a/common/formats/prodos.h
+++ b/common/formats/prodos.h
@@ -116,11 +116,11 @@ class ProDOSDisk : public Common::Archive {
 public:
 	static const int kBlockSize = 512;		// A ProDOS block is always 512 bytes (should this be an enum?)
 
-	ProDOSDisk(const Common::String filename);
+	ProDOSDisk(const Common::Path &filename);
 	~ProDOSDisk();							// Frees the memory used in the dictionary and the volume bitmap
 
 	// Called from the constructor, it parses the volume and fills the hashmap with files
-	bool open(const Common::String filename);
+	bool open(const Common::Path &filename);
 
 	// These are the Common::Archive related methods
 	bool hasFile(const Common::Path &path) const override;
diff --git a/common/formats/winexe.cpp b/common/formats/winexe.cpp
index 510ef615856..a34e4302514 100644
--- a/common/formats/winexe.cpp
+++ b/common/formats/winexe.cpp
@@ -82,7 +82,7 @@ String WinResourceID::toString() const {
 	return "";
 }
 
-bool WinResources::loadFromEXE(const String &fileName) {
+bool WinResources::loadFromEXE(const Path &fileName) {
 	if (fileName.empty())
 		return false;
 
@@ -96,7 +96,7 @@ bool WinResources::loadFromEXE(const String &fileName) {
 	return loadFromEXE(file);
 }
 
-bool WinResources::loadFromCompressedEXE(const String &fileName) {
+bool WinResources::loadFromCompressedEXE(const Path &fileName) {
 	// Based on http://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html
 
 	// TODO: Merge this with with loadFromEXE() so the handling of the compressed
@@ -172,7 +172,7 @@ bool WinResources::loadFromCompressedEXE(const String &fileName) {
 }
 
 
-WinResources *WinResources::createFromEXE(const String &fileName) {
+WinResources *WinResources::createFromEXE(const Path &fileName) {
 	WinResources *exe;
 
 	// First try loading via the NE code
diff --git a/common/formats/winexe.h b/common/formats/winexe.h
index 93ca7a0f83d..0ca57d58319 100644
--- a/common/formats/winexe.h
+++ b/common/formats/winexe.h
@@ -37,6 +37,7 @@ namespace Common {
  * @{
  */
 
+class Path;
 class SeekableReadStream;
 
 /** The default Windows resources. */
@@ -114,10 +115,10 @@ public:
 	virtual void clear() = 0;
 
 	/** Load from an EXE file. */
-	virtual bool loadFromEXE(const String &fileName);
+	virtual bool loadFromEXE(const Path &fileName);
 
 	/** Load from a Windows compressed EXE file. */
-	virtual bool loadFromCompressedEXE(const String &fileName);
+	virtual bool loadFromCompressedEXE(const Path &fileName);
 
 	/** Load from a stream. */
 	virtual bool loadFromEXE(SeekableReadStream *stream, DisposeAfterUse::Flag disposeFileHandle = DisposeAfterUse::YES) = 0;
@@ -139,7 +140,7 @@ public:
 		return getResource(type, id);
 	}
 
-	static WinResources *createFromEXE(const String &fileName);
+	static WinResources *createFromEXE(const Path &fileName);
 	static WinResources *createFromEXE(SeekableReadStream *stream);
 
 	typedef Common::HashMap<Common::String, Common::U32String, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> VersionHash;
diff --git a/common/formats/xmlparser.cpp b/common/formats/xmlparser.cpp
index 66026a8f549..22a25764e39 100644
--- a/common/formats/xmlparser.cpp
+++ b/common/formats/xmlparser.cpp
@@ -41,7 +41,7 @@ XMLParser::~XMLParser() {
 	_layoutList.clear();
 }
 
-bool XMLParser::loadFile(const String &filename) {
+bool XMLParser::loadFile(const Path &filename) {
 	_stream = SearchMan.createReadStreamForMember(filename);
 	if (!_stream)
 		return false;
@@ -96,7 +96,7 @@ bool XMLParser::parserError(const String &errStr) {
 	assert(_stream->pos() == startPosition);
 	currentPosition = startPosition;
 
-	Common::String errorMessage = Common::String::format("\n  File <%s>, line %d:\n", _fileName.c_str(), lineCount);
+	Common::String errorMessage = Common::String::format("\n  File <%s>, line %d:\n", _fileName.toString().c_str(), lineCount);
 
 	if (startPosition > 1) {
 		int keyOpening = 0;
diff --git a/common/formats/xmlparser.h b/common/formats/xmlparser.h
index 49b4b5c8915..db68719145f 100644
--- a/common/formats/xmlparser.h
+++ b/common/formats/xmlparser.h
@@ -168,7 +168,7 @@ public:
 	 *
 	 * @param filename Name of the file to load.
 	 */
-	bool loadFile(const String &filename);
+	bool loadFile(const Path &filename);
 
 	bool loadFile(const FSNode &node);
 
@@ -377,7 +377,7 @@ private:
 	char _char;
 	bool _allowText; /** Allow text nodes in the doc (default false) */
 	SeekableReadStream *_stream;
-	String _fileName;
+	Path _fileName;
 
 	ParserState _state; /** Internal state of the parser */
 
diff --git a/common/lua/scummvm_file.cpp b/common/lua/scummvm_file.cpp
index 1c651c85ab7..ca2fc12ddd1 100644
--- a/common/lua/scummvm_file.cpp
+++ b/common/lua/scummvm_file.cpp
@@ -29,7 +29,7 @@ LuaFileProxy *LuaFileProxy::create(const Common::String &filename, const Common:
 	if (filename.contains("config.lua"))
 		return new LuaFileConfig(filename, mode);
 
-	return new LuaFileRead(filename, mode);
+	return new LuaFileRead(Common::Path(filename, '/'), mode);
 }
 
 LuaFileConfig::LuaFileConfig(const Common::String &filename, const Common::String &mode) : _readPos(0) {
@@ -235,10 +235,10 @@ void LuaFileConfig::setLanguage(const Common::String &lang) {
 }
 
 
-LuaFileRead::LuaFileRead(const Common::String &filename, const Common::String &mode) {
+LuaFileRead::LuaFileRead(const Common::Path &filename, const Common::String &mode) {
 	assert(mode == "r");
 	if (!_file.open(filename))
-		error("Could not open file %s", filename.c_str());
+		error("Could not open file %s", filename.toString().c_str());
 
 	_size = _file.size();
 }
diff --git a/common/lua/scummvm_file.h b/common/lua/scummvm_file.h
index 51cb771dca3..35a95f13c1b 100644
--- a/common/lua/scummvm_file.h
+++ b/common/lua/scummvm_file.h
@@ -69,7 +69,7 @@ private:
 	Common::File _file;
 	int32 _size;
 public:
-	LuaFileRead(const Common::String &filename, const Common::String &mode);
+	LuaFileRead(const Common::Path &filename, const Common::String &mode);
 public:
 	virtual ~LuaFileRead() {}
 
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 5432e82d367..8a26d448b2a 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -177,7 +177,7 @@ SeekableReadStream *MacResManager::openAppleDoubleWithAppleOrOSXNaming(Archive&
         const Common::FSNode *plainFsNode = dynamic_cast<const Common::FSNode *>(archiveMember.get());
 
 	// Try finding __MACOSX
-	Common::StringArray components = (plainFsNode ? Common::Path(plainFsNode->getPath(), '/') : fileName).splitComponents();
+	Common::StringArray components = (plainFsNode ? plainFsNode->getPath() : fileName).splitComponents();
 	if (components.empty() || components[components.size() - 1].empty())
 		return nullptr;
 	for (int i = components.size() - 1; i >= 0; i--) {
@@ -512,20 +512,20 @@ bool MacResManager::getFileFinderInfo(const Path &fileName, MacFinderInfo &outFi
 	return getFileFinderInfo(fileName, SearchMan, outFinderInfo, outFinderExtendedInfo);
 }
 
-void MacResManager::listFiles(StringArray &files, const String &pattern) {
+void MacResManager::listFiles(Array<Path> &files, const Path &pattern) {
 	// Base names discovered so far.
-	typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> BaseNameSet;
+	typedef HashMap<Path, bool, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> BaseNameSet;
 	BaseNameSet baseNames;
 
 	// List files itself.
 	ArchiveMemberList memberList;
 	SearchMan.listMatchingMembers(memberList, pattern);
-	SearchMan.listMatchingMembers(memberList, pattern + ".rsrc");
-	SearchMan.listMatchingMembers(memberList, pattern + ".bin");
+	SearchMan.listMatchingMembers(memberList, pattern.append(".rsrc"));
+	SearchMan.listMatchingMembers(memberList, pattern.append(".bin"));
 	SearchMan.listMatchingMembers(memberList, constructAppleDoubleName(pattern));
 
 	for (ArchiveMemberList::const_iterator i = memberList.begin(), end = memberList.end(); i != end; ++i) {
-		String filename = (*i)->getName();
+		String filename = (*i)->getFileName();
 
 		// For raw resource forks and MacBinary files we strip the extension
 		// here to obtain a valid base name.
@@ -560,12 +560,13 @@ void MacResManager::listFiles(StringArray &files, const String &pattern) {
 
 		// Strip AppleDouble '._' prefix if applicable.
 		bool isAppleDoubleName = false;
-		const String filenameAppleDoubleStripped = disassembleAppleDoubleName(filename, &isAppleDoubleName).toString();
+		const Path filenameAppleDoubleStripped = disassembleAppleDoubleName(
+				Common::Path(filename, Common::Path::kNoSeparator), &isAppleDoubleName);
 
 		if (isAppleDoubleName) {
 			SeekableReadStream *stream = (*i)->createReadStream();
 			if (stream->readUint32BE() == 0x00051607) {
-				filename = filenameAppleDoubleStripped;
+				filename = filenameAppleDoubleStripped.baseName();
 			}
 			// TODO: Should we really keep filenames suggesting AppleDouble
 			// but not being AppleDouble around? This might depend on the
@@ -573,7 +574,8 @@ void MacResManager::listFiles(StringArray &files, const String &pattern) {
 			delete stream;
 		}
 
-		baseNames[filename] = true;
+		Common::Path basePath((*i)->getPathInArchive().getParent().appendComponent(filename));
+		baseNames[basePath] = true;
 	}
 
 	// Append resulting base names to list to indicate found files.
@@ -1011,25 +1013,28 @@ void MacResManager::readMap() {
 	}
 }
 
-Path MacResManager::constructAppleDoubleName(Path name) {
+Path MacResManager::constructAppleDoubleName(const Path &name) {
 	// Insert "._" before the last portion of a path name
-	Path parent = name.getParent();
+	Path ret = name.getParent();
 	Path lastComponent = name.getLastComponent();
-	return parent.append("._").append(lastComponent);
+	return ret.appendInPlace("._").appendInPlace(lastComponent);
 }
 
-Path MacResManager::disassembleAppleDoubleName(Path name, bool *isAppleDouble) {
+Path MacResManager::disassembleAppleDoubleName(const Path &name, bool *isAppleDouble) {
 	if (isAppleDouble) {
 		*isAppleDouble = false;
 	}
 
 	// Remove "._" before the last portion of a path name.
-	Path parent = name.getParent();
-	Path lastComponent = name.getLastComponent();
-	String lastComponentString = lastComponent.toString();
-	if (!lastComponentString.hasPrefix("._"))
+	Path ret = name.getParent();
+	String lastComponent = name.baseName();
+	if (!lastComponent.hasPrefix("._"))
 		return name;
-	return parent.appendComponent(lastComponentString.substr(2));
+	ret = ret.appendComponent(lastComponent.substr(2));
+	if (name.isSeparatorTerminated()) {
+		ret.appendInPlace("/");
+	}
+	return ret;
 }
 
 void MacResManager::dumpRaw() {
@@ -1048,10 +1053,10 @@ void MacResManager::dumpRaw() {
 				dataSize = len;
 			}
 
-			Common::String filename = Common::String::format("./dumps/%s-%s-%d", _baseFileName.toString().c_str(), tag2str(_resTypes[i].id), j);
+			Common::String filename = Common::String::format("./dumps/%s-%s-%d", _baseFileName.baseName().c_str(), tag2str(_resTypes[i].id), j);
 			_stream->read(data, len);
 
-			if (!out.open(filename)) {
+			if (!out.open(Common::Path(filename, '/'))) {
 				warning("MacResManager::dumpRaw(): Can not open dump file %s", filename.c_str());
 				return;
 			}
diff --git a/common/macresman.h b/common/macresman.h
index 8bc20dcf082..68cc593716c 100644
--- a/common/macresman.h
+++ b/common/macresman.h
@@ -193,7 +193,7 @@ public:
 	 * @param pattern Pattern to match against. Taking String::matchPattern's
 	 *                format.
 	 */
-	static void listFiles(StringArray &files, const String &pattern);
+	static void listFiles(Array<Path> &files, const Path &pattern);
 
 	/**
 	 * Close the Mac data/resource fork pair.
@@ -321,8 +321,8 @@ private:
 
 	static bool readAndValidateMacBinaryHeader(SeekableReadStream &stream, byte (&outMacBinaryHeader)[MBI_INFOHDR]);
 
-	static Path constructAppleDoubleName(Path name);
-	static Path disassembleAppleDoubleName(Path name, bool *isAppleDouble);
+	static Path constructAppleDoubleName(const Path &name);
+	static Path disassembleAppleDoubleName(const Path &name, bool *isAppleDouble);
 
 	static SeekableReadStream *openAppleDoubleWithAppleOrOSXNaming(Archive& archive, const Path &fileName);
 
diff --git a/common/translation.cpp b/common/translation.cpp
index a1ea14f8b6e..a829f28ce1d 100644
--- a/common/translation.cpp
+++ b/common/translation.cpp
@@ -227,7 +227,7 @@ bool TranslationManager::openTranslationsFile(File &inFile) {
 
 	// Then try to open it using the SearchMan.
 	ArchiveMemberList fileList;
-	SearchMan.listMatchingMembers(fileList, _translationsFileName);
+	SearchMan.listMatchingMembers(fileList, Common::Path(_translationsFileName, Common::Path::kNoSeparator));
 	for (ArchiveMemberList::iterator it = fileList.begin(); it != fileList.end(); ++it) {
 		ArchiveMember       const &m      = **it;
 		SeekableReadStream *const  stream = m.createReadStream();
diff --git a/engines/dreamweb/rnca_archive.cpp b/engines/dreamweb/rnca_archive.cpp
index d90c15a4dd3..806bc8ef780 100644
--- a/engines/dreamweb/rnca_archive.cpp
+++ b/engines/dreamweb/rnca_archive.cpp
@@ -59,7 +59,7 @@ RNCAArchive* RNCAArchive::open(Common::SeekableReadStream *stream, DisposeAfterU
 		ptr++;
 		uint32 off = READ_BE_UINT32(ptr);
 		eptr = ptr + 4;
-		files[fileName] = RNCAFileDescriptor(fileName, off);
+		files[Common::Path(fileName, Common::Path::kNoSeparator)] = RNCAFileDescriptor(fileName, off);
 	}
 
 	delete[] metadata;
@@ -80,14 +80,14 @@ int RNCAArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr RNCAArchive::getMember(const Common::Path &path) const {
-	Common::String translated = translatePath(path);
+	Common::Path translated = translatePath(path);
 	if (!_files.contains(translated))
 		return nullptr;
 
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_files.getVal(translated)._fileName, *this));
 }
 
-Common::SharedArchiveContents RNCAArchive::readContentsForPath(const Common::String& translated) const {
+Common::SharedArchiveContents RNCAArchive::readContentsForPath(const Common::Path &translated) const {
 	if (!_files.contains(translated))
 		return Common::SharedArchiveContents();
 	const RNCAFileDescriptor& desc = _files.getVal(translated);
diff --git a/engines/dreamweb/rnca_archive.h b/engines/dreamweb/rnca_archive.h
index e808f8d6972..090a1158aa3 100644
--- a/engines/dreamweb/rnca_archive.h
+++ b/engines/dreamweb/rnca_archive.h
@@ -34,7 +34,7 @@ public:
 	bool hasFile(const Common::Path &path) const override;
 	int listMembers(Common::ArchiveMemberList&) const override;
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
-	Common::SharedArchiveContents readContentsForPath(const Common::String& translated) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::Path &translated) const override;
 
 	static RNCAArchive* open(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose = DisposeAfterUse::NO);
 	
@@ -53,7 +53,7 @@ private:
 		RNCAFileDescriptor() : _fileDataOffset(0) {}
 	};
 
-	typedef Common::HashMap<Common::String, RNCAFileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, RNCAFileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 
 	RNCAArchive(FileMap files, Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose)
 		: _files(files), _stream(stream, dispose) {
diff --git a/engines/mads/mps_installer.cpp b/engines/mads/mps_installer.cpp
index 06d52e1bbf0..c640c608faf 100644
--- a/engines/mads/mps_installer.cpp
+++ b/engines/mads/mps_installer.cpp
@@ -76,14 +76,14 @@ int MpsInstaller::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr MpsInstaller::getMember(const Common::Path &path) const {
-	Common::String translated = translatePath(path);
+	Common::Path translated = translatePath(path);
 	if (!_files.contains(translated))
 		return nullptr;
 
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(_files.getVal(translated)._fileName, *this));
 }
 
-Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::String& translated) const {
+Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::Path &translated) const {
 	if (!_files.contains(translated))
 		return Common::SharedArchiveContents();
 	FileDescriptor desc = _files.getVal(translated);
diff --git a/engines/mads/mps_installer.h b/engines/mads/mps_installer.h
index 487ffa076c1..46cef05d95e 100644
--- a/engines/mads/mps_installer.h
+++ b/engines/mads/mps_installer.h
@@ -33,11 +33,11 @@ namespace MADS {
 class MpsInstaller : public Common::MemcachingCaseInsensitiveArchive {
 public:
 	bool hasFile(const Common::Path &path) const override;
-	int listMembers(Common::ArchiveMemberList&) const override;
+	int listMembers(Common::ArchiveMemberList &) const override;
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
-	Common::SharedArchiveContents readContentsForPath(const Common::String& translatedPath) const override;
+	Common::SharedArchiveContents readContentsForPath(const Common::Path &translatedPath) const override;
 
-	static MpsInstaller* open(const Common::Path& baseName);
+	static MpsInstaller* open(const Common::Path &baseName);
 
 private:
 	// Similar to FileDescriptionBin but in native-endian and native strings.
@@ -73,7 +73,7 @@ private:
 		friend class MpsInstaller;
 	};
 
-    	typedef Common::HashMap<Common::String, FileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, FileDescriptor, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 
 	MpsInstaller(const FileMap& files,
 		     const Common::Path& baseName) : _files(files), _baseName(baseName) {}
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 76b2dd71e37..561f2caa225 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -349,12 +349,12 @@ Common::Error SagaEngine::run() {
 	setTotalPlayTime(0);
 
 	if (getFeatures() & GF_INSTALLER) {
-		Common::Array<Common::String> filenames;
+		Common::Array<Common::Path> filenames;
 		for (const ADGameFileDescription *gameArchiveDescription = getArchivesDescriptions();
 		     gameArchiveDescription->fileName; gameArchiveDescription++)
 			filenames.push_back(gameArchiveDescription->fileName);
 		Common::Archive *archive = nullptr;
-		if (filenames.size() == 1 && filenames[0].hasSuffix(".exe"))
+		if (filenames.size() == 1 && filenames[0].baseName().hasSuffix(".exe"))
 			archive = Common::makeZipArchive(filenames[0], true);
 		else
 			archive = Common::makeArjArchive(filenames, true);
diff --git a/engines/sci/resource/resource.cpp b/engines/sci/resource/resource.cpp
index 59ae2119701..c328004ffdb 100644
--- a/engines/sci/resource/resource.cpp
+++ b/engines/sci/resource/resource.cpp
@@ -655,12 +655,13 @@ int ResourceManager::addAppropriateSources() {
 #endif
 	} else if (Common::MacResManager::exists("Data1")) {
 		// Mac SCI1.1+ file naming scheme
-		Common::StringArray files;
+		Common::Array<Common::Path> files;
 		Common::MacResManager::listFiles(files, "Data#");
 		Common::MacResManager::listFiles(files, "Data##");
 
-		for (Common::StringArray::const_iterator x = files.begin(); x != files.end(); ++x) {
-			addSource(new MacResourceForkResourceSource(*x, atoi(x->c_str() + 4)));
+		for (Common::Array<Common::Path>::const_iterator x = files.begin(); x != files.end(); ++x) {
+			Common::String path(x->toString());
+			addSource(new MacResourceForkResourceSource(path, atoi(path.c_str() + 4)));
 		}
 
 #ifdef ENABLE_SCI32


Commit: e0fd69bda0f4164939c2b1b28ab05d2762d56242
    https://github.com/scummvm/scummvm/commit/e0fd69bda0f4164939c2b1b28ab05d2762d56242
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make INIFile use Path

Changed paths:
    common/formats/ini-file.cpp
    common/formats/ini-file.h


diff --git a/common/formats/ini-file.cpp b/common/formats/ini-file.cpp
index 55fc5c83bbe..a45ca600a96 100644
--- a/common/formats/ini-file.cpp
+++ b/common/formats/ini-file.cpp
@@ -60,7 +60,7 @@ void INIFile::clear() {
 	_sections.clear();
 }
 
-bool INIFile::loadFromFile(const String &filename) {
+bool INIFile::loadFromFile(const Path &filename) {
 	File file;
 	if (file.open(filename))
 		return loadFromStream(file);
@@ -68,7 +68,7 @@ bool INIFile::loadFromFile(const String &filename) {
 		return false;
 }
 
-bool INIFile::loadFromFileOrDataFork(const String &filename) {
+bool INIFile::loadFromFileOrDataFork(const Path &filename) {
 	SeekableReadStream *file = Common::MacResManager::openFileOrDataFork(filename);
 	if (file)
 		return loadFromStream(*file);
@@ -212,7 +212,7 @@ bool INIFile::loadFromStream(SeekableReadStream &stream) {
 	return (!stream.err() || stream.eos());
 }
 
-bool INIFile::saveToFile(const String &filename) {
+bool INIFile::saveToFile(const Path &filename) {
 	DumpFile file;
 	if (file.open(filename))
 		return saveToStream(file);
diff --git a/common/formats/ini-file.h b/common/formats/ini-file.h
index 119f9da6523..2d97b361a1a 100644
--- a/common/formats/ini-file.h
+++ b/common/formats/ini-file.h
@@ -24,6 +24,7 @@
 
 #include "common/hash-str.h"
 #include "common/list.h"
+#include "common/path.h"
 #include "common/str.h"
 
 namespace Common {
@@ -105,11 +106,11 @@ public:
 	/** Reset everything stored in this INI file. */
 	void	clear();
 
-	bool	loadFromFile(const String &filename); /*!< Load configuration from a file. */
-	bool	loadFromFileOrDataFork(const String &filename); /*!< Load configuration from a file in MacBinary format. */
+	bool	loadFromFile(const Path &filename); /*!< Load configuration from a file. */
+	bool	loadFromFileOrDataFork(const Path &filename); /*!< Load configuration from a file in MacBinary format. */
 	bool	loadFromSaveFile(const String &filename); /*!< Load configuration from a save file. */
 	bool	loadFromStream(SeekableReadStream &stream); /*!< Load configuration from a @ref SeekableReadStream. */
-	bool	saveToFile(const String &filename); /*!< Save the current configuration to a file. */
+	bool	saveToFile(const Path &filename); /*!< Save the current configuration to a file. */
 	bool	saveToSaveFile(const String &filename); /*!< Save the current configuration to a save file. */
 	bool	saveToStream(WriteStream &stream); /*!< Save the current configuration to a @ref WriteStream. */
 


Commit: fc3f03d21d574637f8fb948d91a8b18f83599a52
    https://github.com/scummvm/scummvm/commit/fc3f03d21d574637f8fb948d91a8b18f83599a52
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make EVENT_DROP_FILE use a Path

Changed paths:
    backends/events/riscossdl/riscossdl-events.cpp
    backends/events/sdl/sdl-events.cpp
    common/events.h
    gui/downloaddialog.cpp
    gui/launcher.cpp
    gui/launcher.h


diff --git a/backends/events/riscossdl/riscossdl-events.cpp b/backends/events/riscossdl/riscossdl-events.cpp
index 4bd5682dedb..77f94042e09 100644
--- a/backends/events/riscossdl/riscossdl-events.cpp
+++ b/backends/events/riscossdl/riscossdl-events.cpp
@@ -51,7 +51,7 @@ bool RISCOSSdlEventSource::handleSysWMEvent(SDL_Event &ev, Common::Event &event)
 		case 3: // Message_DataLoad
 			filename = (char *)(pollBlock) + 44;
 			event.type = Common::EVENT_DROP_FILE;
-			event.path = RISCOS_Utils::toUnix(Common::String(filename));
+			event.path = Common::Path(RISCOS_Utils::toUnix(Common::String(filename)));
 
 			// Acknowledge that the event has been received
 			pollBlock[4] = 4; // Message_DataLoadAck
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index d5cbd95c64d..127855c6ec5 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -554,7 +554,7 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
 
 	case SDL_DROPFILE:
 		event.type = Common::EVENT_DROP_FILE;
-		event.path = Common::String(ev.drop.file);
+		event.path = Common::Path(ev.drop.file, Common::Path::kNativeSeparator);
 		SDL_free(ev.drop.file);
 		return true;
 
diff --git a/common/events.h b/common/events.h
index 97b0ef4396c..cbb77fb7123 100644
--- a/common/events.h
+++ b/common/events.h
@@ -225,7 +225,7 @@ struct Event {
 	CustomEventType customType;
 
 	/** The path of the file or directory dragged to the ScummVM window. */
-	Common::String path;
+	Common::Path path;
 
 	/**
 	 * Mouse movement since the last mouse movement event.
diff --git a/gui/downloaddialog.cpp b/gui/downloaddialog.cpp
index 36d8b032448..e42853721d2 100644
--- a/gui/downloaddialog.cpp
+++ b/gui/downloaddialog.cpp
@@ -171,7 +171,7 @@ bool DownloadDialog::selectDirectories() {
 void DownloadDialog::handleTickle() {
 	if (_close) {
 		if (_launcher)
-			_launcher->doGameDetection(_localDirectory.toString('/'));
+			_launcher->doGameDetection(_localDirectory);
 		close();
 		_close = false;
 		return;
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index af74fabe5e5..8e6a53b5c0b 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -623,7 +623,7 @@ void LauncherDialog::handleOtherEvent(const Common::Event &evt) {
 	Dialog::handleOtherEvent(evt);
 	if (evt.type == Common::EVENT_DROP_FILE) {
 		// If the path is a file, take the parent directory for the detection
-		Common::String path = evt.path;
+		Common::Path path = evt.path;
 		Common::FSNode node(path);
 		if (!node.isDirectory())
 			path = node.getParent().getPath();
@@ -631,7 +631,7 @@ void LauncherDialog::handleOtherEvent(const Common::Event &evt) {
 	}
 }
 
-bool LauncherDialog::doGameDetection(const Common::String &path) {
+bool LauncherDialog::doGameDetection(const Common::Path &path) {
 	// Allow user to add a new game to the list.
 	// 2) try to auto detect which game is in the directory, if we cannot
 	//    determine it uniquely present a list of candidates to the user
diff --git a/gui/launcher.h b/gui/launcher.h
index 9b7b93ccc61..0b0c4442e96 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -120,7 +120,7 @@ public:
 	void handleKeyDown(Common::KeyState state) override;
 	void handleKeyUp(Common::KeyState state) override;
 	void handleOtherEvent(const Common::Event &evt) override;
-	bool doGameDetection(const Common::String &path);
+	bool doGameDetection(const Common::Path &path);
 	Common::String getGameConfig(int item, Common::String key);
 protected:
 	EditTextWidget  *_searchWidget;


Commit: 226de788c89fecdaf5f102e6ef13ec498e9f028e
    https://github.com/scummvm/scummvm/commit/226de788c89fecdaf5f102e6ef13ec498e9f028e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GRAPHICS: Make API use the Path class

Changed paths:
    engines/cryomni3d/font_manager.cpp
    graphics/fonts/bdf.cpp
    graphics/fonts/bdf.h
    graphics/fonts/ttf.cpp
    graphics/fonts/ttf.h
    graphics/fonts/winfont.cpp
    graphics/fonts/winfont.h
    graphics/macgui/datafiles.cpp
    graphics/macgui/macfontmanager.cpp
    graphics/macgui/macfontmanager.h
    graphics/macgui/mactext-canvas.h
    graphics/macgui/mactext.cpp
    graphics/macgui/mactext.h
    graphics/macgui/macwindowmanager.h
    graphics/opengl/shader.cpp


diff --git a/engines/cryomni3d/font_manager.cpp b/engines/cryomni3d/font_manager.cpp
index f3b01a7fa66..fad6efa7b5b 100644
--- a/engines/cryomni3d/font_manager.cpp
+++ b/engines/cryomni3d/font_manager.cpp
@@ -142,9 +142,9 @@ void FontManager::loadTTFList(const Common::Path &ttfList, Common::CodePage code
 		bool bold = sizeFlags.contains('B');
 		bool italic = sizeFlags.contains('I');
 
-		Common::Array<Common::String> fontFiles;
+		Common::Array<Common::Path> fontFiles;
 		fontFiles.push_back(fontFile);
-		fontFiles.push_back(ttfParentDir.appendComponent(fontFile).toString());
+		fontFiles.push_back(ttfParentDir.appendComponent(fontFile));
 
 		// Use 96 dpi as it's the default under Windows
 		Graphics::Font *font = Graphics::findTTFace(fontFiles, uniFontFace, bold, italic, -(int)size,
diff --git a/graphics/fonts/bdf.cpp b/graphics/fonts/bdf.cpp
index 0acac2701fc..12f3197fa93 100644
--- a/graphics/fonts/bdf.cpp
+++ b/graphics/fonts/bdf.cpp
@@ -584,10 +584,10 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) {
 #define BDF_FONTCACHE_TAG MKTAG('S', 'V', 'F', 'C')
 #define BDF_FONTCACHE_VERSION 1
 
-bool BdfFont::cacheFontData(const BdfFont &font, const Common::String &filename) {
+bool BdfFont::cacheFontData(const BdfFont &font, const Common::Path &filename) {
 	Common::DumpFile cacheFile;
 	if (!cacheFile.open(filename)) {
-		warning("BdfFont::cacheFontData: Couldn't open file '%s' for writing", filename.c_str());
+		warning("BdfFont::cacheFontData: Couldn't open file '%s' for writing", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/graphics/fonts/bdf.h b/graphics/fonts/bdf.h
index 2811560b108..93e64fdb40a 100644
--- a/graphics/fonts/bdf.h
+++ b/graphics/fonts/bdf.h
@@ -74,7 +74,7 @@ public:
 	int getFontSize() const;
 
 	static BdfFont *loadFont(Common::SeekableReadStream &stream);
-	static bool cacheFontData(const BdfFont &font, const Common::String &filename);
+	static bool cacheFontData(const BdfFont &font, const Common::Path &filename);
 	static BdfFont *loadFromCache(Common::SeekableReadStream &stream);
 	static BdfFont *scaleFont(const BdfFont *src, int newSize);
 private:
diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index 44d6638ef03..5c81795ea6d 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -908,7 +908,7 @@ Font *loadTTFFontFromArchive(const Common::String &filename, int size, TTFSizeMo
 
 	Common::File f;
 
-	if (!f.open(filename, *archive)) {
+	if (!f.open(Common::Path(filename, Common::Path::kNoSeparator), *archive)) {
 		delete archive;
 		archiveStream = nullptr;
 
@@ -927,7 +927,7 @@ Font *loadTTFFontFromArchive(const Common::String &filename, int size, TTFSizeMo
 			return nullptr;
 		}
 
-		if (!f.open(filename, *archive)) {
+		if (!f.open(Common::Path(filename, Common::Path::kNoSeparator), *archive)) {
 			delete archive;
 			return nullptr;
 		}
@@ -985,7 +985,7 @@ static bool matchFaceName(const Common::U32String &faceName, const FT_Face &face
 	return false;
 }
 
-Font *findTTFace(const Common::Array<Common::String> &files, const Common::U32String &faceName,
+Font *findTTFace(const Common::Array<Common::Path> &files, const Common::U32String &faceName,
 				 bool bold, bool italic, int size, uint dpi, TTFRenderMode renderMode, const uint32 *mapping) {
 	if (!g_ttf.isInitialized())
 		return nullptr;
@@ -995,7 +995,7 @@ Font *findTTFace(const Common::Array<Common::String> &files, const Common::U32St
 	uint32 bestFaceId = (uint32) -1;
 	uint32 bestPenalty = (uint32) -1;
 
-	for (Common::Array<Common::String>::const_iterator it = files.begin(); it != files.end(); it++) {
+	for (Common::Array<Common::Path>::const_iterator it = files.begin(); it != files.end(); it++) {
 		Common::File ttf;
 		if (!ttf.open(*it)) {
 			continue;
diff --git a/graphics/fonts/ttf.h b/graphics/fonts/ttf.h
index 4e79820d9ae..c82ac5d7615 100644
--- a/graphics/fonts/ttf.h
+++ b/graphics/fonts/ttf.h
@@ -30,6 +30,10 @@
 #include "common/stream.h"
 #include "common/ustr.h"
 
+namespace Common {
+class Path;
+}
+
 namespace Graphics {
 
 class Font;
@@ -136,7 +140,7 @@ Font *loadTTFFontFromArchive(const Common::String &filename, int size, TTFSizeMo
  *                   supported.
  * @return 0 in case loading fails, otherwise a pointer to the Font object.
  */
-Font *findTTFace(const Common::Array<Common::String> &files, const Common::U32String &faceName, bool bold, bool italic, int size, uint dpi = 0, TTFRenderMode renderMode = kTTFRenderModeLight, const uint32 *mapping = 0);
+Font *findTTFace(const Common::Array<Common::Path> &files, const Common::U32String &faceName, bool bold, bool italic, int size, uint dpi = 0, TTFRenderMode renderMode = kTTFRenderModeLight, const uint32 *mapping = 0);
 
 void shutdownTTF();
 
diff --git a/graphics/fonts/winfont.cpp b/graphics/fonts/winfont.cpp
index 4447f954bd5..1bcf9f51461 100644
--- a/graphics/fonts/winfont.cpp
+++ b/graphics/fonts/winfont.cpp
@@ -75,7 +75,7 @@ static WinFontDirEntry readDirEntry(Common::SeekableReadStream &stream) {
 	return entry;
 }
 
-bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry &dirEntry) {
+bool WinFont::loadFromFON(const Common::Path &fileName, const WinFontDirEntry &dirEntry) {
 	Common::WinResources *exe = Common::WinResources::createFromEXE(fileName);
 	if (!exe)
 		return false;
@@ -90,16 +90,16 @@ bool WinFont::loadFromFON(Common::SeekableReadStream &stream, const WinFontDirEn
 	if (!exe)
 		return false;
 
-	bool ok = loadFromEXE(exe, Common::String("stream"), dirEntry);
+	bool ok = loadFromEXE(exe, Common::Path("stream"), dirEntry);
 	delete exe;
 	return ok;
 }
 
-bool WinFont::loadFromEXE(Common::WinResources *exe, const Common::String &fileName, const WinFontDirEntry &dirEntry) {
+bool WinFont::loadFromEXE(Common::WinResources *exe, const Common::Path &fileName, const WinFontDirEntry &dirEntry) {
 	// Let's pull out the font directory
 	Common::SeekableReadStream *fontDirectory = exe->getResource(Common::kWinFontDir, Common::String("FONTDIR"));
 	if (!fontDirectory) {
-		warning("No font directory in '%s'", fileName.c_str());
+		warning("No font directory in '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -109,14 +109,16 @@ bool WinFont::loadFromEXE(Common::WinResources *exe, const Common::String &fileN
 
 	// Couldn't match the face name
 	if (fontId == 0xffffffff) {
-		warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(), fileName.c_str());
+		warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(),
+				fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	// Actually go get our font now...
 	Common::SeekableReadStream *fontStream = exe->getResource(Common::kWinFont, fontId);
 	if (!fontStream) {
-		warning("Could not find font %d in %s", fontId, fileName.c_str());
+		warning("Could not find font %d in %s", fontId,
+				fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -162,7 +164,7 @@ Common::String WinFont::getFONFontName(Common::SeekableReadStream& stream) {
 	return fontName;
 }
 
-bool WinFont::loadFromFNT(const Common::String &fileName) {
+bool WinFont::loadFromFNT(const Common::Path &fileName) {
 	Common::File file;
 
 	return file.open(fileName) && loadFromFNT(file);
diff --git a/graphics/fonts/winfont.h b/graphics/fonts/winfont.h
index 9ee87aa1ae1..a7f53d9f643 100644
--- a/graphics/fonts/winfont.h
+++ b/graphics/fonts/winfont.h
@@ -52,11 +52,11 @@ public:
 	 *
 	 * If dirEntry is not given, the first font in the FONTDIR will be loaded
 	 */
-	bool loadFromFON(const Common::String &fileName, const WinFontDirEntry &dirEntry = WinFontDirEntry());
+	bool loadFromFON(const Common::Path &fileName, const WinFontDirEntry &dirEntry = WinFontDirEntry());
 	bool loadFromFON(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry = WinFontDirEntry());
 
 	/** Open a font from an FNT file */
-	bool loadFromFNT(const Common::String &fileName);
+	bool loadFromFNT(const Common::Path &fileName);
 
 	/** Close this font */
 	void close();
@@ -72,7 +72,7 @@ public:
 
 	static WinFont *scaleFont(const WinFont *src, int newSize);
 private:
-	bool loadFromEXE(Common::WinResources *exe, const Common::String &fileName, const WinFontDirEntry &dirEntry);
+	bool loadFromEXE(Common::WinResources *exe, const Common::Path &fileName, const WinFontDirEntry &dirEntry);
 
 	uint32 getFontIndex(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry);
 	Common::String getFONFontName(Common::SeekableReadStream &stream);
diff --git a/graphics/macgui/datafiles.cpp b/graphics/macgui/datafiles.cpp
index bd81dfccd99..6c371afd7f9 100644
--- a/graphics/macgui/datafiles.cpp
+++ b/graphics/macgui/datafiles.cpp
@@ -34,7 +34,7 @@
 
 namespace Graphics {
 
-#define MACGUI_DATA_BUNDLE Common::String("macgui.dat")
+static const char * const MACGUI_DATA_BUNDLE = "macgui.dat";
 
 struct BorderName {
 	uint32 type;
@@ -80,7 +80,7 @@ Common::String windowTypeName(uint32 windowType) {
 void MacWindowManager::loadDataBundle() {
 	_dataBundle = Common::makeZipArchive(MACGUI_DATA_BUNDLE);
 	if (!_dataBundle) {
-		warning("MACGUI: Couldn't load data bundle '%s'.", MACGUI_DATA_BUNDLE.c_str());
+		warning("MACGUI: Couldn't load data bundle '%s'.", MACGUI_DATA_BUNDLE);
 	}
 }
 
@@ -106,20 +106,21 @@ Common::SeekableReadStream *MacWindowManager::getBorderFile(uint32 windowType, u
 	filename += (flags & kWindowBorderActive) ? "_act" : "_inac";
 	filename += (flags & kWindowBorderTitle) ? "_title" : "";
 	filename += ".bmp";
-	if (!_dataBundle->hasFile(filename)) {
+	Common::Path path(filename, Common::Path::kNoSeparator);
+	if (!_dataBundle->hasFile(path)) {
 		warning("Missing border file '%s' in data bundle", filename.c_str());
 		return NULL;
 	}
 
-	return _dataBundle->createReadStreamForMember(filename);
+	return _dataBundle->createReadStreamForMember(path);
 }
 
-Common::SeekableReadStream *MacWindowManager::getFile(const Common::String &filename) {
+Common::SeekableReadStream *MacWindowManager::getFile(const Common::Path &filename) {
 	if (!_dataBundle)
 		return NULL;
 
 	if (!_dataBundle->hasFile(filename)) {
-		warning("Missing file '%s' in data bundle", filename.c_str());
+		warning("Missing file '%s' in data bundle", filename.toString().c_str());
 		return NULL;
 	}
 
diff --git a/graphics/macgui/macfontmanager.cpp b/graphics/macgui/macfontmanager.cpp
index 224080d89ad..6220e5d2542 100644
--- a/graphics/macgui/macfontmanager.cpp
+++ b/graphics/macgui/macfontmanager.cpp
@@ -229,7 +229,7 @@ void MacFontManager::loadFontsBDF() {
 	dat->listMembers(list);
 
 	for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) {
-		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName());
+		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getPathInArchive());
 
 		Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream);
 
@@ -287,7 +287,7 @@ void MacFontManager::loadFonts() {
 	dat->listMembers(list);
 
 	for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) {
-		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName());
+		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getPathInArchive());
 
 		loadFonts(stream);
 	}
@@ -315,7 +315,7 @@ void MacFontManager::loadJapaneseFonts() {
 	dat->listMembers(list);
 
 	for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) {
-		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName());
+		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getPathInArchive());
 		Common::String fontName = (*it)->getName();
 
 		// Trim the .ttf extension
@@ -349,7 +349,7 @@ void MacFontManager::loadFonts(Common::SeekableReadStream *stream) {
 	loadFonts(&fontFile);
 }
 
-void MacFontManager::loadFonts(const Common::String &fileName) {
+void MacFontManager::loadFonts(const Common::Path &fileName) {
 	Common::MacResManager fontFile;
 
 	if (!fontFile.open(fileName))
@@ -436,12 +436,13 @@ void MacFontManager::loadFonts(Common::MacResManager *fontFile) {
 	}
 }
 
-void MacFontManager::loadWindowsFont(const Common::String fileName) {
+void MacFontManager::loadWindowsFont(const Common::Path &fileName) {
 	Graphics::WinFont *winFont = new Graphics::WinFont();
 	bool isLoaded = winFont->loadFromFON(fileName);
 
 	if (!isLoaded) {
-		warning("MacFontManager::loadWindowsFont(): Windows Font data from file %s not loaded", fileName.c_str());
+		warning("MacFontManager::loadWindowsFont(): Windows Font data from file %s not loaded",
+				fileName.toString(Common::Path::kNativeSeparator).c_str());
 		delete winFont;
 		return;
 	}
diff --git a/graphics/macgui/macfontmanager.h b/graphics/macgui/macfontmanager.h
index c140665fde4..3af8864e264 100644
--- a/graphics/macgui/macfontmanager.h
+++ b/graphics/macgui/macfontmanager.h
@@ -156,9 +156,9 @@ public:
 	Common::String getFontName(uint16 id);
 
 	void loadFonts(Common::SeekableReadStream *stream);
-	void loadFonts(const Common::String &fileName);
+	void loadFonts(const Common::Path &fileName);
 	void loadFonts(Common::MacResManager *fontFile);
-	void loadWindowsFont(const Common::String fileName);
+	void loadWindowsFont(const Common::Path &fileName);
 
 	/**
 	 * Register a font name if it doesn't already exist.
diff --git a/graphics/macgui/mactext-canvas.h b/graphics/macgui/mactext-canvas.h
index 311a2aa7aed..501ab0d722d 100644
--- a/graphics/macgui/mactext-canvas.h
+++ b/graphics/macgui/mactext-canvas.h
@@ -182,7 +182,7 @@ struct MacTextLine {
 	bool wordContinuation = false;
 	int indent = 0; // in units
 	int firstLineIndent = 0; // in pixels
-	Common::String picfname;
+	Common::Path picfname;
 	Common::U32String picalt, pictitle, picext;
 	uint16 picpercent = 50;
 	Common::Array<MacTextTableRow> *table = nullptr;
diff --git a/graphics/macgui/mactext.cpp b/graphics/macgui/mactext.cpp
index 0b6b169a8dc..35e3c440a03 100644
--- a/graphics/macgui/mactext.cpp
+++ b/graphics/macgui/mactext.cpp
@@ -1994,16 +1994,16 @@ void MacText::undrawCursor() {
 	_composeSurface->blitFrom(*_cursorSurface2, *_cursorRect, Common::Point(_cursorX + offset.x, _cursorY + offset.y));
 }
 
-void MacText::setImageArchive(Common::String fname) {
+void MacText::setImageArchive(const Common::Path &fname) {
 	_imageArchive = Common::makeZipArchive(fname);
 
 	if (!_imageArchive)
-		warning("MacText::setImageArchive(): Could not find %s. Images will not be rendered", fname.c_str());
+		warning("MacText::setImageArchive(): Could not find %s. Images will not be rendered", fname.toString().c_str());
 }
 
-const Surface *MacText::getImageSurface(Common::String &fname) {
+const Surface *MacText::getImageSurface(const Common::Path &fname) {
 #ifndef USE_PNG
-	warning("MacText::getImageSurface(): PNG support not compiled. Cannot load file %s", fname.c_str());
+	warning("MacText::getImageSurface(): PNG support not compiled. Cannot load file %s", fname.toString().c_str());
 
 	return nullptr;
 #else
@@ -2018,7 +2018,7 @@ const Surface *MacText::getImageSurface(Common::String &fname) {
 	Common::SeekableReadStream *stream = _imageArchive->createReadStreamForMember(fname);
 
 	if (!stream) {
-		warning("MacText::getImageSurface(): Cannot open file %s", fname.c_str());
+		warning("MacText::getImageSurface(): Cannot open file %s", fname.toString().c_str());
 		return nullptr;
 	}
 
@@ -2027,7 +2027,7 @@ const Surface *MacText::getImageSurface(Common::String &fname) {
 	if (!_imageCache[fname]->loadStream(*stream)) {
 		delete _imageCache[fname];
 
-		warning("MacText::getImageSurface(): Cannot load file %s", fname.c_str());
+		warning("MacText::getImageSurface(): Cannot load file %s", fname.toString().c_str());
 
 		return nullptr;
 	}
diff --git a/graphics/macgui/mactext.h b/graphics/macgui/mactext.h
index 8fcd3539cf5..1e0dfb2c545 100644
--- a/graphics/macgui/mactext.h
+++ b/graphics/macgui/mactext.h
@@ -122,7 +122,7 @@ public:
 	int getMouseLine(int x, int y);
 	Common::U32String getMouseLink(int x, int y);
 
-	void setImageArchive(Common::String name);
+	void setImageArchive(const Common::Path &name);
 
 private:
 	MacFontRun getTextChunks(int start, int end);
@@ -184,7 +184,7 @@ public:
 	// Markdown
 public:
 	void setMarkdownText(const Common::U32String &str);
-	const Surface *getImageSurface(Common::String &fname);
+	const Surface *getImageSurface(const Common::Path &fname);
 
 private:
 	void init(uint32 fgcolor, uint32 bgcolor, int maxWidth, TextAlign textAlignment, int interlinear, uint16 textShadow, bool macFontMode);
@@ -238,7 +238,7 @@ private:
 	MacMenu *_menu;
 
 #ifdef USE_PNG
-	Common::HashMap<Common::String, Image::PNGDecoder *> _imageCache;
+	Common::HashMap<Common::Path, Image::PNGDecoder *, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _imageCache;
 #endif
 	Common::Archive *_imageArchive = nullptr;
 };
diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h
index 6dbc3f56f12..22a128c77a0 100644
--- a/graphics/macgui/macwindowmanager.h
+++ b/graphics/macgui/macwindowmanager.h
@@ -364,7 +364,7 @@ public:
 
 	BorderOffsets getBorderOffsets(uint32 windowType);
 	Common::SeekableReadStream *getBorderFile(uint32 windowType, uint32 flags);
-	Common::SeekableReadStream *getFile(const Common::String &filename);
+	Common::SeekableReadStream *getFile(const Common::Path &filename);
 
 	void setTextInClipboard(const Common::U32String &str);
 	/**
diff --git a/graphics/opengl/shader.cpp b/graphics/opengl/shader.cpp
index e13a9bb06de..e5ed1611aed 100644
--- a/graphics/opengl/shader.cpp
+++ b/graphics/opengl/shader.cpp
@@ -80,7 +80,7 @@ static const char *compatUniformBool =
 
 static const GLchar *readFile(const Common::String &filename) {
 	Common::File file;
-	Common::String shaderDir;
+	Common::Path shaderDir;
 
 #ifndef RELEASE_BUILD
 	// Allow load shaders from source code directory without install them.
@@ -100,9 +100,9 @@ static const GLchar *readFile(const Common::String &filename) {
 		SearchMan.addDirectory("EXTRA_PATH", Common::FSNode(ConfMan.getPath("extrapath")), 0, 2);
 	}
 #if !defined(IPHONE)
-	shaderDir = "shaders/";
+	shaderDir = Common::Path("shaders/", '/');
 #endif
-	file.open(shaderDir + filename);
+	file.open(shaderDir.appendComponent(filename));
 	if (!file.isOpen())
 		error("Could not open shader %s!", filename.c_str());
 


Commit: 4ecccceca60df6349b6640bc168da7d404757b22
    https://github.com/scummvm/scummvm/commit/4ecccceca60df6349b6640bc168da7d404757b22
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
AUDIO: Move API to Path

Changed paths:
    audio/audiostream.cpp
    audio/audiostream.h
    audio/decoders/quicktime.cpp
    audio/decoders/quicktime.h
    audio/decoders/quicktime_intern.h
    audio/midiparser_qt.cpp
    audio/midiparser_qt.h
    audio/miles.h
    audio/miles_adlib.cpp
    audio/miles_midi.cpp


diff --git a/audio/audiostream.cpp b/audio/audiostream.cpp
index 4624ee437bd..d75fb947044 100644
--- a/audio/audiostream.cpp
+++ b/audio/audiostream.cpp
@@ -65,12 +65,12 @@ static const StreamFileFormat STREAM_FILEFORMATS[] = {
 	{ "WAV",          ".wav",  makeWAVStream },
 };
 
-SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::String &basename) {
+SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::Path &basename) {
 	SeekableAudioStream *stream = nullptr;
 	Common::File *fileHandle = new Common::File();
 
 	for (int i = 0; i < ARRAYSIZE(STREAM_FILEFORMATS); ++i) {
-		Common::String filename = basename + STREAM_FILEFORMATS[i].fileExtension;
+		Common::Path filename = basename.append(STREAM_FILEFORMATS[i].fileExtension);
 		fileHandle->open(filename);
 		if (fileHandle->isOpen()) {
 			// Create the stream object
@@ -83,7 +83,7 @@ SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::String &b
 	delete fileHandle;
 
 	if (stream == nullptr)
-		debug(1, "SeekableAudioStream::openStreamFile: Could not open compressed AudioFile %s", basename.c_str());
+		debug(1, "SeekableAudioStream::openStreamFile: Could not open compressed AudioFile %s", basename.toString(Common::Path::kNativeSeparator).c_str());
 
 	return stream;
 }
diff --git a/audio/audiostream.h b/audio/audiostream.h
index 0de0ce45404..1f7127e4fc6 100644
--- a/audio/audiostream.h
+++ b/audio/audiostream.h
@@ -24,12 +24,12 @@
 
 #include "common/ptr.h"
 #include "common/scummsys.h"
-#include "common/str.h"
 #include "common/types.h"
 
 #include "audio/timestamp.h"
 
 namespace Common {
+class Path;
 class SeekableReadStream;
 }
 
@@ -222,7 +222,7 @@ public:
 	 * @return  A SeekableAudioStream ready to use in case of success.
 	 *          NULL in case of an error (e.g. invalid/non-existing file).
 	 */
-	static SeekableAudioStream *openStreamFile(const Common::String &basename);
+	static SeekableAudioStream *openStreamFile(const Common::Path &basename);
 
 	/**
 	 * Seek to a given offset in the stream.
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp
index 41c29c249e7..0c1db3b7469 100644
--- a/audio/decoders/quicktime.cpp
+++ b/audio/decoders/quicktime.cpp
@@ -85,7 +85,7 @@ QuickTimeAudioDecoder::~QuickTimeAudioDecoder() {
 		delete _audioTracks[i];
 }
 
-bool QuickTimeAudioDecoder::loadAudioFile(const Common::String &filename) {
+bool QuickTimeAudioDecoder::loadAudioFile(const Common::Path &filename) {
 	if (!Common::QuickTimeParser::parseFile(filename))
 		return false;
 
@@ -657,7 +657,7 @@ public:
 	QuickTimeAudioStream() {}
 	~QuickTimeAudioStream() {}
 
-	bool openFromFile(const Common::String &filename) {
+	bool openFromFile(const Common::Path &filename) {
 		return QuickTimeAudioDecoder::loadAudioFile(filename) && !_audioTracks.empty();
 	}
 
@@ -687,7 +687,7 @@ public:
 	Timestamp getLength() const override { return _audioTracks[0]->getLength(); }
 };
 
-SeekableAudioStream *makeQuickTimeStream(const Common::String &filename) {
+SeekableAudioStream *makeQuickTimeStream(const Common::Path &filename) {
 	QuickTimeAudioStream *audioStream = new QuickTimeAudioStream();
 
 	if (!audioStream->openFromFile(filename)) {
diff --git a/audio/decoders/quicktime.h b/audio/decoders/quicktime.h
index 299c7d82e52..3cc3391dac3 100644
--- a/audio/decoders/quicktime.h
+++ b/audio/decoders/quicktime.h
@@ -50,7 +50,7 @@ class SeekableAudioStream;
  * @param filename          the filename of the file from which to read the data
  * @return  a new SeekableAudioStream, or NULL, if an error occurred
  */
-SeekableAudioStream *makeQuickTimeStream(const Common::String &filename);
+SeekableAudioStream *makeQuickTimeStream(const Common::Path &filename);
 
 /**
  * Try to load a QuickTime sound file from the given seekable stream and create a SeekableAudioStream
diff --git a/audio/decoders/quicktime_intern.h b/audio/decoders/quicktime_intern.h
index 81d89542a83..7fde52e5343 100644
--- a/audio/decoders/quicktime_intern.h
+++ b/audio/decoders/quicktime_intern.h
@@ -53,7 +53,7 @@ public:
 	 * Load a QuickTime audio file
 	 * @param filename	the filename to load
 	 */
-	bool loadAudioFile(const Common::String &filename);
+	bool loadAudioFile(const Common::Path &filename);
 
 	/**
 	 * Load a QuickTime audio file from a SeekableReadStream
diff --git a/audio/midiparser_qt.cpp b/audio/midiparser_qt.cpp
index c5407f6e01a..83ca3c1746b 100644
--- a/audio/midiparser_qt.cpp
+++ b/audio/midiparser_qt.cpp
@@ -95,7 +95,7 @@ bool MidiParser_QT::loadFromContainerStream(Common::SeekableReadStream *stream,
 	return true;
 }
 
-bool MidiParser_QT::loadFromContainerFile(const Common::String &fileName) {
+bool MidiParser_QT::loadFromContainerFile(const Common::Path &fileName) {
 	unloadMusic();
 
 	if (!parseFile(fileName))
diff --git a/audio/midiparser_qt.h b/audio/midiparser_qt.h
index 5edfc6543b5..58d3fd40bc7 100644
--- a/audio/midiparser_qt.h
+++ b/audio/midiparser_qt.h
@@ -74,7 +74,7 @@ public:
 	/**
 	 * Load the MIDI from a QuickTime file
 	 */
-	bool loadFromContainerFile(const Common::String &fileName);
+	bool loadFromContainerFile(const Common::Path &fileName);
 
 protected:
 	// MidiParser
diff --git a/audio/miles.h b/audio/miles.h
index 11dcc2fbeb8..1203e1731d8 100644
--- a/audio/miles.h
+++ b/audio/miles.h
@@ -304,11 +304,11 @@ private:
 	MilesMT32SysExQueueEntry _milesSysExQueues[MILES_CONTROLLER_SYSEX_QUEUE_COUNT];
 };
 
-extern MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::String &filenameAdLib, const Common::String &filenameOPL3, Common::SeekableReadStream *streamAdLib = nullptr, Common::SeekableReadStream *streamOPL3 = nullptr);
+extern MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::Path &filenameAdLib, const Common::Path &filenameOPL3, Common::SeekableReadStream *streamAdLib = nullptr, Common::SeekableReadStream *streamOPL3 = nullptr);
 
-extern MidiDriver_Miles_Midi *MidiDriver_Miles_MT32_create(const Common::String &instrumentDataFilename);
+extern MidiDriver_Miles_Midi *MidiDriver_Miles_MT32_create(const Common::Path &instrumentDataFilename);
 
-extern MidiDriver_Miles_Midi *MidiDriver_Miles_MIDI_create(MusicType midiType, const Common::String &instrumentDataFilename);
+extern MidiDriver_Miles_Midi *MidiDriver_Miles_MIDI_create(MusicType midiType, const Common::Path &instrumentDataFilename);
 /** @} */
 } // End of namespace Audio
 
diff --git a/audio/miles_adlib.cpp b/audio/miles_adlib.cpp
index dd500445aa5..af36f1e9ac3 100644
--- a/audio/miles_adlib.cpp
+++ b/audio/miles_adlib.cpp
@@ -1271,9 +1271,9 @@ void MidiDriver_Miles_AdLib::setRegisterStereo(uint8 reg, uint8 valueLeft, uint8
 	_opl->write(0x223, valueRight);
 }
 
-MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::String &filenameAdLib, const Common::String &filenameOPL3, Common::SeekableReadStream *streamAdLib, Common::SeekableReadStream *streamOPL3) {
+MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::Path &filenameAdLib, const Common::Path &filenameOPL3, Common::SeekableReadStream *streamAdLib, Common::SeekableReadStream *streamOPL3) {
 	// Load adlib instrument data from file SAMPLE.AD (OPL3: SAMPLE.OPL)
-	Common::String              timbreFilename;
+	Common::Path                timbreFilename;
 	Common::SeekableReadStream *timbreStream = nullptr;
 
 	bool          preferOPL3 = false;
@@ -1374,12 +1374,12 @@ MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::String &file
 			// If none of them exists and also no stream was passed, we can't do anything about it
 			if (!filenameAdLib.empty()) {
 				if (!filenameOPL3.empty()) {
-					error("MILES-ADLIB: could not open timbre file (%s or %s)", filenameAdLib.c_str(), filenameOPL3.c_str());
+					error("MILES-ADLIB: could not open timbre file (%s or %s)", filenameAdLib.toString(Common::Path::kNativeSeparator).c_str(), filenameOPL3.toString(Common::Path::kNativeSeparator).c_str());
 				} else {
-					error("MILES-ADLIB: could not open timbre file (%s)", filenameAdLib.c_str());
+					error("MILES-ADLIB: could not open timbre file (%s)", filenameAdLib.toString(Common::Path::kNativeSeparator).c_str());
 				}
 			} else {
-				error("MILES-ADLIB: could not open timbre file (%s)", filenameOPL3.c_str());
+				error("MILES-ADLIB: could not open timbre file (%s)", filenameOPL3.toString(Common::Path::kNativeSeparator).c_str());
 			}
 		}
 	}
@@ -1389,14 +1389,14 @@ MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::String &file
 		// We prefer this situation
 
 		if (!fileStream->open(timbreFilename))
-			error("MILES-ADLIB: could not open timbre file (%s)", timbreFilename.c_str());
+			error("MILES-ADLIB: could not open timbre file (%s)", timbreFilename.toString(Common::Path::kNativeSeparator).c_str());
 
 		streamSize = fileStream->size();
 
 		streamDataPtr = new byte[streamSize];
 
 		if (fileStream->read(streamDataPtr, streamSize) != streamSize)
-			error("MILES-ADLIB: error while reading timbre file (%s)", timbreFilename.c_str());
+			error("MILES-ADLIB: error while reading timbre file (%s)", timbreFilename.toString(Common::Path::kNativeSeparator).c_str());
 		fileStream->close();
 
 	} else if (timbreStream) {
diff --git a/audio/miles_midi.cpp b/audio/miles_midi.cpp
index 3b5cd968780..f8fc91e8b5c 100644
--- a/audio/miles_midi.cpp
+++ b/audio/miles_midi.cpp
@@ -794,11 +794,11 @@ void MidiDriver_Miles_Midi::writeToSystemArea(byte index, byte value) {
 	sysExMT32(sysExData, 1, targetAddress);
 }
 
-MidiDriver_Miles_Midi *MidiDriver_Miles_MT32_create(const Common::String &instrumentDataFilename) {
+MidiDriver_Miles_Midi *MidiDriver_Miles_MT32_create(const Common::Path &instrumentDataFilename) {
 	return MidiDriver_Miles_MIDI_create(MT_MT32, instrumentDataFilename);
 }
 
-MidiDriver_Miles_Midi *MidiDriver_Miles_MIDI_create(MusicType midiType, const Common::String &instrumentDataFilename) {
+MidiDriver_Miles_Midi *MidiDriver_Miles_MIDI_create(MusicType midiType, const Common::Path &instrumentDataFilename) {
 	assert(midiType == MT_MT32 || midiType == MT_GM || midiType == MT_GS);
 
 	MilesMT32InstrumentEntry *instrumentTablePtr = nullptr;
@@ -820,7 +820,7 @@ MidiDriver_Miles_Midi *MidiDriver_Miles_MIDI_create(MusicType midiType, const Co
 		uint16                    instrumentDataSize;
 
 		if (!fileStream->open(instrumentDataFilename))
-			error("MILES-MIDI: could not open instrument file '%s'", instrumentDataFilename.c_str());
+			error("MILES-MIDI: could not open instrument file '%s'", instrumentDataFilename.toString(Common::Path::kNativeSeparator).c_str());
 
 		fileSize = fileStream->size();
 


Commit: 85952c72bfd4cd6d0f298d7a9191b38054cb3585
    https://github.com/scummvm/scummvm/commit/85952c72bfd4cd6d0f298d7a9191b38054cb3585
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
VIDEO: Move API to Path

Changed paths:
    video/subtitles.cpp
    video/subtitles.h
    video/video_decoder.cpp
    video/video_decoder.h


diff --git a/video/subtitles.cpp b/video/subtitles.cpp
index 19b12075891..99e9f0f25d3 100644
--- a/video/subtitles.cpp
+++ b/video/subtitles.cpp
@@ -114,7 +114,7 @@ int SRTEntryComparatorBSearch(const void *item1, const void *item2) {
 	return 0;
 }
 
-bool SRTParser::parseFile(const char *fname) {
+bool SRTParser::parseFile(const Common::Path &fname) {
 	Common::File f;
 
 	cleanup();
@@ -144,13 +144,13 @@ bool SRTParser::parseFile(const char *fname) {
 				// Normal end of stream
 				break;
 			} else {
-				warning("Bad SRT file format (spec): %s at line %d", fname, line);
+				warning("Bad SRT file format (spec): %s at line %d", fname.toString().c_str(), line);
 				break;
 			}
 		}
 
 		if (stimespec.empty() || text.empty()) {
-			warning("Bad SRT file format (spec): %s at line %d", fname, line);
+			warning("Bad SRT file format (spec): %s at line %d", fname.toString().c_str(), line);
 			break;
 		}
 
@@ -168,20 +168,20 @@ bool SRTParser::parseFile(const char *fname) {
 
 		uint32 seq = atol(sseq.c_str());
 		if (seq == 0) {
-			warning("Bad SRT file format (seq): %s at line %d", fname, line);
+			warning("Bad SRT file format (seq): %s at line %d", fname.toString().c_str(), line);
 			break;
 		}
 
 		// 00:20:41,150 --> 00:20:45,109
 		if (stimespec.size() < 29) {
-			warning("Bad SRT file format (timespec length %d): %s at line %d", stimespec.size(), fname, line);
+			warning("Bad SRT file format (timespec length %d): %s at line %d", stimespec.size(), fname.toString().c_str(), line);
 			break;
 		}
 
 		const char *ptr = stimespec.c_str();
 		uint32 start, end;
 		if (!parseTime(&ptr, &start)) {
-			warning("Bad SRT file format (timespec start): %s at line %d", fname, line);
+			warning("Bad SRT file format (timespec start): %s at line %d", fname.toString().c_str(), line);
 			break;
 		}
 
@@ -192,7 +192,7 @@ bool SRTParser::parseFile(const char *fname) {
 			ptr++;
 
 		if (*ptr != '>') {
-			warning("Bad SRT file format (timespec middle ('%c')): %s at line %d", *ptr, fname, line);
+			warning("Bad SRT file format (timespec middle ('%c')): %s at line %d", *ptr, fname.toString().c_str(), line);
 			break;
 		}
 
@@ -202,7 +202,7 @@ bool SRTParser::parseFile(const char *fname) {
 			ptr++;
 
 		if (!parseTime(&ptr, &end)) {
-			warning("Bad SRT file format (timespec end): %s at line %d", fname, line);
+			warning("Bad SRT file format (timespec end): %s at line %d", fname.toString().c_str(), line);
 			break;
 		}
 
@@ -268,8 +268,8 @@ void Subtitles::setFont(const char *fontname, int height) {
 
 }
 
-void Subtitles::loadSRTFile(const char *fname) {
-	debug(1, "loadSRTFile('%s')", fname);
+void Subtitles::loadSRTFile(const Common::Path &fname) {
+	debug(1, "loadSRTFile('%s')", fname.toString().c_str());
 
 	if (_subtitleDev) {
 		_fname = fname;
@@ -304,7 +304,7 @@ bool Subtitles::drawSubtitle(uint32 timestamp, bool force) const {
 	if (_loaded) {
 		subtitle = _srtParser.getSubtitle(timestamp);
 	} else if (_subtitleDev) {
-		subtitle = _fname;
+		subtitle = _fname.toString('/');
 		uint32 hours, mins, secs, msecs;
 		secs = timestamp / 1000;
 		hours = secs / 3600;
diff --git a/video/subtitles.h b/video/subtitles.h
index 0060e610fd1..473bdc983ce 100644
--- a/video/subtitles.h
+++ b/video/subtitles.h
@@ -51,7 +51,7 @@ public:
 	~SRTParser();
 
 	void cleanup();
-	bool parseFile(const char *fname);
+	bool parseFile(const Common::Path &fname);
 	Common::String getSubtitle(uint32 timestamp) const;
 
 private:
@@ -63,7 +63,7 @@ public:
 	Subtitles();
 	~Subtitles();
 
-	void loadSRTFile(const char *fname);
+	void loadSRTFile(const Common::Path &fname);
 	void close() { _loaded = false; _subtitle.clear(); _fname.clear(); _srtParser.cleanup(); }
 	void setFont(const char *fontname, int height = 18);
 	void setBBox(const Common::Rect bbox);
@@ -90,7 +90,7 @@ private:
 	mutable Common::Rect _realBBox;
 	mutable int16 _lastOverlayWidth, _lastOverlayHeight;
 
-	Common::String _fname;
+	Common::Path _fname;
 	mutable Common::String _subtitle;
 	uint32 _color;
 	uint32 _blackColor;
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index e7d84497a7b..43dadbc7fdd 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -777,7 +777,7 @@ VideoDecoder::StreamFileAudioTrack::~StreamFileAudioTrack() {
 	delete _stream;
 }
 
-bool VideoDecoder::StreamFileAudioTrack::loadFromFile(const Common::String &baseName) {
+bool VideoDecoder::StreamFileAudioTrack::loadFromFile(const Common::Path &baseName) {
 	// TODO: Make sure the stream isn't being played
 	delete _stream;
 	_stream = Audio::SeekableAudioStream::openStreamFile(baseName);
@@ -832,7 +832,7 @@ bool VideoDecoder::addStreamTrack(Audio::SeekableAudioStream *stream) {
 	return true;
 }
 
-bool VideoDecoder::addStreamFileTrack(const Common::String &baseName) {
+bool VideoDecoder::addStreamFileTrack(const Common::Path &baseName) {
 	// Only allow adding external tracks if a video is already loaded
 	if (!isVideoLoaded())
 		return false;
diff --git a/video/video_decoder.h b/video/video_decoder.h
index bd9585cce17..f7e6c78922d 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -451,7 +451,7 @@ public:
 	 *
 	 * This calls SeekableAudioStream::openStreamFile() internally
 	 */
-	bool addStreamFileTrack(const Common::String &baseName);
+	bool addStreamFileTrack(const Common::Path &baseName);
 
 	/**
 	 * Set the internal audio track.
@@ -842,7 +842,7 @@ protected:
 		 *
 		 * @return true on success, false otherwise
 		 */
-		bool loadFromFile(const Common::String &baseName);
+		bool loadFromFile(const Common::Path &baseName);
 
 	protected:
 		Audio::SeekableAudioStream *_stream;


Commit: 645a35c05b0d12dbe3443faa75cd2067ff4588c1
    https://github.com/scummvm/scummvm/commit/645a35c05b0d12dbe3443faa75cd2067ff4588c1
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ENGINES: Migrate to Path class

Changed paths:
    base/commandLine.cpp
    base/plugins.cpp
    engines/achievements.cpp
    engines/advancedDetector.cpp
    engines/advancedDetector.h
    engines/engine.cpp
    engines/game.cpp
    engines/game.h


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index a36f3755b5c..03ce45409dc 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1512,7 +1512,7 @@ static Common::String detectGames(const Common::String &path, const Common::Stri
 		printf("%-30s %-58s %s\n",
 		       buildQualifiedGameName(v->engineId, v->gameId).c_str(),
 		       v->description.c_str(),
-		       v->path.c_str());
+		       v->path.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	return buildQualifiedGameName(candidates[0].engineId, candidates[0].gameId);
diff --git a/base/plugins.cpp b/base/plugins.cpp
index a85daebd8c2..07e5a30cb6d 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -787,7 +787,7 @@ Common::String EngineManager::createTargetForGame(const DetectedGame &game) {
 	addStringToConf("description", game.description, domain);
 	addStringToConf("language", Common::getLanguageCode(game.language), domain);
 	addStringToConf("platform", Common::getPlatformCode(game.platform), domain);
-	addStringToConf("path", game.path, domain);
+	addStringToConf("path", game.path.toString(Common::Path::kNativeSeparator), domain);
 	addStringToConf("extra", game.extra, domain);
 	addStringToConf("guioptions", game.getGUIOptions(), domain);
 
diff --git a/engines/achievements.cpp b/engines/achievements.cpp
index 13c8b3b6591..f6c13f23f1a 100644
--- a/engines/achievements.cpp
+++ b/engines/achievements.cpp
@@ -131,7 +131,7 @@ bool AchievementsManager::loadAchievementsData(const char *platform, const char
 	}
 
 	String cfgFileName = String::format("%s-%s.ini", platform, appId);
-	SeekableReadStream *stream = cfgZip->createReadStreamForMember(cfgFileName);
+	SeekableReadStream *stream = cfgZip->createReadStreamForMember(Common::Path(cfgFileName));
 	if (!stream) {
 		delete cfgZip;
 		warning("%s is not found in achievements.dat. Achievements messages are unavailable", cfgFileName.c_str());
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index b8a420a4411..ca89caf534a 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -48,8 +48,7 @@ public:
 	FileMapArchive(const AdvancedMetaEngineDetection::FileMap &fileMap) : _fileMap(fileMap) {}
 
 	bool hasFile(const Common::Path &path) const override {
-		Common::String name = path.toString();
-		return _fileMap.contains(name);
+		return _fileMap.contains(path);
 	}
 
 	int listMembers(Common::ArchiveMemberList &list) const override {
@@ -63,8 +62,7 @@ public:
 	}
 
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override {
-		Common::String name = path.toString();
-		AdvancedMetaEngineDetection::FileMap::const_iterator it = _fileMap.find(name);
+		AdvancedMetaEngineDetection::FileMap::const_iterator it = _fileMap.find(path);
 		if (it == _fileMap.end()) {
 			return Common::ArchiveMemberPtr();
 		}
@@ -73,8 +71,7 @@ public:
 	}
 
 	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override {
-		Common::String name = path.toString();
-		Common::FSNode fsNode = _fileMap.getValOrDefault(name);
+		Common::FSNode fsNode = _fileMap.getValOrDefault(path);
 		return fsNode.createReadStream();
 	}
 
@@ -355,17 +352,17 @@ Common::Error AdvancedMetaEngineDetection::createInstance(OSystem *syst, Engine
 
 	Common::String gameid = ConfMan.get("gameid");
 
-	Common::String path;
+	Common::Path path;
 	if (ConfMan.hasKey("path")) {
-		path = ConfMan.get("path");
+		path = ConfMan.getPath("path");
 	} else {
-		path = ".";
+		path = Common::Path(".");
 		warning("No path was provided. Assuming the data files are in the current directory");
 	}
 	Common::FSNode dir(path);
 	Common::FSList files;
 	if (!dir.isDirectory() || !dir.getChildren(files, Common::FSNode::kListAll)) {
-		warning("Game data path does not exist or is not a directory (%s)", path.c_str());
+		warning("Game data path does not exist or is not a directory (%s)", path.toString(Common::Path::kNativeSeparator).c_str());
 		return Common::kNoGameDataFoundError;
 	}
 
@@ -443,14 +440,14 @@ Common::Error AdvancedMetaEngineDetection::createInstance(OSystem *syst, Engine
 	}
 
 	debug("Running %s", gameDescriptor.description.c_str());
-	Common::StringArray filenames;
+	Common::Array<Common::Path> filenames;
 	for (FilePropertiesMap::const_iterator i = gameDescriptor.matchedFiles.begin(); i != gameDescriptor.matchedFiles.end(); ++i) {
 		filenames.push_back(i->_key);
 	}
 	Common::sort(filenames.begin(), filenames.end());
 	for (uint i = 0; i < filenames.size(); ++i) {
 		const FileProperties &file = gameDescriptor.matchedFiles[filenames[i]];
-		debug("%s: %s, %llu bytes.", filenames[i].c_str(), file.md5.c_str(), (unsigned long long)file.size);
+		debug("%s: %s, %llu bytes.", filenames[i].toString().c_str(), file.md5.c_str(), (unsigned long long)file.size);
 	}
 	initSubSystems(agdDesc.desc);
 
@@ -465,7 +462,7 @@ Common::Error AdvancedMetaEngineDetection::createInstance(OSystem *syst, Engine
 	if (plugin) {
 		if (_flags & kADFlagMatchFullPaths) {
 			Common::StringArray dirs = getPathsFromEntry(agdDesc.desc);
-			Common::FSNode gameDataDir = Common::FSNode(ConfMan.get("path"));
+			Common::FSNode gameDataDir = Common::FSNode(ConfMan.getPath("path"));
 
 			for (auto d = dirs.begin(); d != dirs.end(); ++d)
 				SearchMan.addSubDirectoryMatching(gameDataDir, *d, 0, _fullPathGlobsDepth);
@@ -478,7 +475,7 @@ Common::Error AdvancedMetaEngineDetection::createInstance(OSystem *syst, Engine
 	return Common::Error(Common::kEnginePluginNotFound);
 }
 
-void AdvancedMetaEngineDetection::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName) const {
+void AdvancedMetaEngineDetection::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::Path &parentName) const {
 	if (depth <= 0)
 		return;
 
@@ -487,7 +484,7 @@ void AdvancedMetaEngineDetection::composeFileHashMap(FileMap &allFiles, const Co
 
 	for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
 		Common::String efname = Common::punycode_encodefilename(file->getName());
-		Common::String tstr = ((_flags & kADFlagMatchFullPaths) && !parentName.empty() ? parentName + "/" : "") + efname;
+		Common::Path tstr = ((_flags & kADFlagMatchFullPaths) ? parentName : Common::Path()).appendComponent(efname);
 
 		if (file->isDirectory()) {
 			if (!_globsMap.contains(efname))
@@ -502,16 +499,15 @@ void AdvancedMetaEngineDetection::composeFileHashMap(FileMap &allFiles, const Co
 		}
 
 		// Strip any trailing dot
-		if (tstr.lastChar() == '.')
-			tstr.deleteLastChar();
-
-		if (efname.lastChar() == '.')
+		if (efname.lastChar() == '.') {
 			efname.deleteLastChar();
+			tstr = ((_flags & kADFlagMatchFullPaths) ? parentName : Common::Path()).appendComponent(efname);
+		}
 
-		debugC(9, kDebugGlobalDetection, "$$ ['%s'] ['%s'] in '%s", tstr.c_str(), efname.c_str(), firstPathComponents(fslist.front().getPath(), '/').c_str());
+		debugC(9, kDebugGlobalDetection, "$$ ['%s'] ['%s'] in '%s", tstr.toString().c_str(), efname.c_str(), firstPathComponents(fslist.front().getPath().toString(), '/').c_str());
 
 		allFiles[tstr] = *file;		// Record the presence of this file
-		allFiles[efname] = *file;	// ...and its file name
+		allFiles[Common::Path(efname, Common::Path::kNoSeparator)] = *file;	// ...and its file name
 	}
 }
 
@@ -583,12 +579,12 @@ Common::String md5PropToGameFile(MD5Properties flags) {
 	return res;
 }
 
-static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::String &fname, FileProperties &fileProps);
+static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps);
 
-bool AdvancedMetaEngineDetection::getFileProperties(const FileMap &allFiles, MD5Properties md5prop, const Common::String &fname, FileProperties &fileProps) const {
+bool AdvancedMetaEngineDetection::getFileProperties(const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const {
 	Common::String hashname = md5PropToCachePrefix(md5prop);
 		hashname += ':';
-		hashname += fname;
+		hashname += fname.toString('/');
 		hashname += ':';
 		hashname += Common::String::format("%d", _md5Bytes);
 
@@ -608,11 +604,11 @@ bool AdvancedMetaEngineDetection::getFileProperties(const FileMap &allFiles, MD5
 	return res;
 }
 
-bool AdvancedMetaEngine::getFilePropertiesExtern(uint md5Bytes, const FileMap &allFiles, MD5Properties md5prop, const Common::String &fname, FileProperties &fileProps) const {
+bool AdvancedMetaEngine::getFilePropertiesExtern(uint md5Bytes, const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const {
 	return getFilePropertiesIntern(md5Bytes, allFiles, md5prop, fname, fileProps);
 }
 
-static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::String &fname, FileProperties &fileProps) {
+static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) {
 	if (md5prop & (kMD5MacResFork | kMD5MacDataFork)) {
 		FileMapArchive fileMapArchive(allFiles);
 		bool is_legacy = ((md5prop & kMD5MacMask) == kMD5MacResOrDataFork);
@@ -655,10 +651,10 @@ static bool getFilePropertiesIntern(uint md5Bytes, const AdvancedMetaEngine::Fil
 		// The desired file is inside an archive
 
 		// First, split the file string
-		Common::StringTokenizer tok(fname, ":");
+		Common::StringTokenizer tok(fname.toString(), ":");
 		Common::String archiveType = tok.nextToken();
-		Common::String archiveName = tok.nextToken();
-		Common::String fileName = tok.nextToken();
+		Common::Path archiveName(tok.nextToken());
+		Common::Path fileName(tok.nextToken());
 
 		if (!allFiles.contains(archiveName))
 			return false;
@@ -768,14 +764,14 @@ void AdvancedMetaEngineDetection::dumpDetectionEntries() const {
 }
 
 ADDetectedGames AdvancedMetaEngineDetection::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, uint32 skipADFlags, bool skipIncomplete) {
-	FilePropertiesMap filesProps;
+	CachedPropertiesMap filesProps;
 	ADDetectedGames matched;
 
 	const ADGameFileDescription *fileDesc;
 	const ADGameDescription *g;
 	const byte *descPtr;
 
-	debugC(3, kDebugGlobalDetection, "Starting detection for engine '%s' in dir '%s'", getName(), parent.getPath().c_str());
+	debugC(3, kDebugGlobalDetection, "Starting detection for engine '%s' in dir '%s'", getName(), parent.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	preprocessDescriptions();
 
@@ -795,7 +791,7 @@ ADDetectedGames AdvancedMetaEngineDetection::detectGame(const Common::FSNode &pa
 				continue;
 
 			FileProperties tmp;
-			if (getFileProperties(allFiles, md5prop, fname, tmp)) {
+			if (getFileProperties(allFiles, md5prop, Common::Path(fname), tmp)) {
 				debugC(3, kDebugGlobalDetection, "> '%s': '%s' %ld", key.c_str(), tmp.md5.c_str(), long(tmp.size));
 			}
 
@@ -846,7 +842,7 @@ ADDetectedGames AdvancedMetaEngineDetection::detectGame(const Common::FSNode &pa
 				break;
 			}
 
-			game.matchedFiles[tstr] = filesProps[key];
+			game.matchedFiles[Common::Path(tstr)] = filesProps[key];
 
 			if (game.hasUnknownFiles)
 				continue;
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 673c1393d87..eb22b435fe0 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -409,7 +409,7 @@ protected:
 	/**
 	 * A hashmap of files and their MD5 checksums.
 	 */
-	typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, Common::FSNode, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 
 	/**
 	 * An (optional) generic fallback detection function that is invoked
@@ -467,10 +467,10 @@ protected:
 	 *
 	 * Removes trailing dots and ignores case in the process.
 	 */
-	void composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName = Common::String()) const;
+	void composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::Path &parentName = Common::Path()) const;
 
 	/** Get the properties (size and MD5) of this file. */
-	bool getFileProperties(const FileMap &allFiles, MD5Properties md5prop, const Common::String &fname, FileProperties &fileProps) const;
+	bool getFileProperties(const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const;
 
 	/** Convert an AD game description into the shared game description format. */
 	virtual DetectedGame toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo = nullptr) const;
@@ -515,7 +515,7 @@ public:
 	/**
 	 * A hashmap of files and their MD5 checksums.
 	 */
-	typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, Common::FSNode, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 
 	/**
 	 * An (optional) generic fallback detection function that is invoked
@@ -539,7 +539,7 @@ public:
 	 *
 	 * Based on @ref MetaEngine::getFileProperties.
 	 */
-	bool getFilePropertiesExtern(uint md5Bytes, const FileMap &allFiles, MD5Properties md5prop, const Common::String &fname, FileProperties &fileProps) const;
+	bool getFilePropertiesExtern(uint md5Bytes, const FileMap &allFiles, MD5Properties md5prop, const Common::Path &fname, FileProperties &fileProps) const;
 
 protected:
 	/**
@@ -575,23 +575,23 @@ protected:
  */
 class AdvancedDetectorCacheManager : public Common::Singleton<AdvancedDetectorCacheManager> {
 public:
-	void setMD5(Common::String fname, Common::String md5) {
+	void setMD5(const Common::String &fname, const Common::String &md5) {
 		md5HashMap.setVal(fname, md5);
 	}
 
-	Common::String getMD5(Common::String fname) {
+	const Common::String &getMD5(const Common::String &fname) const {
 		return md5HashMap.getVal(fname);
 	}
 
-	void setSize(Common::String fname, int64 size) {
+	void setSize(const Common::String &fname, int64 size) {
 		sizeHashMap.setVal(fname, size);
 	}
 
-	int64 getSize(Common::String fname) {
+	int64 getSize(const Common::String &fname) const {
 		return sizeHashMap.getVal(fname);
 	}
 
-	bool containsMD5(Common::String fname) {
+	bool containsMD5(const Common::String &fname) const {
 		return (md5HashMap.contains(fname) && sizeHashMap.contains(fname));
 	}
 
@@ -599,7 +599,7 @@ public:
 		if (!archivePtr)
 			return;
 
-		Common::String filename = node.getPath();
+		Common::Path filename = node.getPath();
 		
 		if (archiveHashMap.contains(filename)) {
 			delete archiveHashMap[filename];
@@ -608,9 +608,8 @@ public:
 		archiveHashMap.setVal(filename, archivePtr);
 	}
 
-	Common::Archive *getArchive(const Common::FSNode &node) {
-		Common::Archive *ret = nullptr;
-		return archiveHashMap.tryGetVal(node.getPath(), ret) ? ret : nullptr;
+	Common::Archive *getArchive(const Common::FSNode &node) const {
+		return archiveHashMap.getValOrDefault(node.getPath(), nullptr);
 	}
 
 	AdvancedDetectorCacheManager() {
@@ -635,7 +634,7 @@ private:
 
 	typedef Common::HashMap<Common::String, Common::String, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileHashMap;
 	typedef Common::HashMap<Common::String, int64, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SizeHashMap;
-	typedef Common::HashMap<Common::String, Common::Archive *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ArchiveHashMap;
+	typedef Common::HashMap<Common::Path, Common::Archive *, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> ArchiveHashMap;
 	FileHashMap md5HashMap;
 	SizeHashMap sizeHashMap;
 	ArchiveHashMap archiveHashMap;
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 8f7525aef14..58223e8d41a 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -195,7 +195,7 @@ Engine::~Engine() {
 }
 
 void Engine::initializePath(const Common::FSNode &gamePath) {
-	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 4);
+	SearchMan.addDirectory(gamePath, 0, 4);
 }
 
 void initCommonGFX() {
diff --git a/engines/game.cpp b/engines/game.cpp
index be6bd6163c2..016c3e48688 100644
--- a/engines/game.cpp
+++ b/engines/game.cpp
@@ -208,12 +208,12 @@ Common::U32String generateUnknownGameReport(const DetectedGames &detectedGames,
 
 	Common::U32String report = Common::U32String::format(
 			translate ? _(reportStart) : Common::U32String(reportStart),
-			fullPath ? detectedGames[0].path.c_str() : detectedGames[0].shortPath.c_str(),
+			fullPath ? detectedGames[0].path.toString(Common::Path::kNativeSeparator).c_str() : detectedGames[0].shortPath.c_str(),
 			"https://bugs.scummvm.org/"
 	);
 	report += Common::U32String("\n");
 
-	FilePropertiesMap matchedFiles;
+	CachedPropertiesMap matchedFiles;
 
 	Common::String currentEngineId;
 	for (uint i = 0; i < detectedGames.size(); i++) {
@@ -243,7 +243,7 @@ Common::U32String generateUnknownGameReport(const DetectedGames &detectedGames,
 
 		// Consolidate matched files across all engines and detection entries
 		for (FilePropertiesMap::const_iterator it = game.matchedFiles.begin(); it != game.matchedFiles.end(); it++) {
-			Common::String key = Common::String::format("%s:%s", md5PropToCachePrefix(it->_value.md5prop).c_str(), it->_key.c_str());
+			Common::String key = Common::String::format("%s:%s", md5PropToCachePrefix(it->_value.md5prop).c_str(), it->_key.punycodeEncode().toString('/').c_str());
 			matchedFiles.setVal(key, it->_value);
 		}
 	}
@@ -255,7 +255,7 @@ Common::U32String generateUnknownGameReport(const DetectedGames &detectedGames,
 	report += Common::U32String("\n\n");
 
 	Common::StringArray filenames;
-	for (FilePropertiesMap::const_iterator file = matchedFiles.begin(); file != matchedFiles.end(); ++file) {
+	for (CachedPropertiesMap::const_iterator file = matchedFiles.begin(); file != matchedFiles.end(); ++file) {
 		filenames.push_back(file->_key);
 	}
 	Common::sort(filenames.begin(), filenames.end());
diff --git a/engines/game.h b/engines/game.h
index aa3a91cdf40..326d1a16299 100644
--- a/engines/game.h
+++ b/engines/game.h
@@ -24,11 +24,12 @@
 
 #include "common/array.h"
 #include "common/hash-str.h"
-#include "common/str.h"
-#include "common/ustr.h"
-#include "common/str-array.h"
 #include "common/language.h"
+#include "common/path.h"
 #include "common/platform.h"
+#include "common/str.h"
+#include "common/str-array.h"
+#include "common/ustr.h"
 
 /**
  * @defgroup engines_game Games
@@ -129,7 +130,12 @@ struct FileProperties {
 /**
  * A map of all relevant existing files while detecting.
  */
-typedef Common::HashMap<Common::String, FileProperties, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FilePropertiesMap;
+typedef Common::HashMap<Common::Path, FileProperties, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FilePropertiesMap;
+
+/**
+ * A map using a composed key to cache file properties
+ */
+typedef Common::HashMap<Common::String, FileProperties, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CachedPropertiesMap;
 
 /**
  * Details about a given game.
@@ -181,7 +187,7 @@ struct DetectedGame {
 	Common::String description;
 	Common::Language language;
 	Common::Platform platform;
-	Common::String path;
+	Common::Path path;
 	Common::String shortPath;
 	Common::String extra;
 


Commit: d931c58b5b43d0cf74d0361644441b2c1fc952c4
    https://github.com/scummvm/scummvm/commit/d931c58b5b43d0cf74d0361644441b2c1fc952c4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BASE: Start considering game paths as Path class

As it's still stored as String, this is still safe for every legacy use

Changed paths:
    base/commandLine.cpp
    base/main.cpp
    base/plugins.cpp
    common/forbidden.h


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 03ce45409dc..765a90da5d5 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1658,9 +1658,9 @@ static void runDetectorTest() {
 	for (iter = domains.begin(); iter != domains.end(); ++iter) {
 		Common::String name(iter->_key);
 		Common::String gameid(iter->_value.getVal("gameid"));
-		Common::String path(iter->_value.getVal("path"));
+		Common::Path path(Common::Path::fromConfig(iter->_value.getVal("path")));
 		printf("Looking at target '%s', gameid '%s', path '%s' ...\n",
-				name.c_str(), gameid.c_str(), path.c_str());
+				name.c_str(), gameid.c_str(), path.toString(Common::Path::kNativeSeparator).c_str());
 		if (path.empty()) {
 			printf(" ... no path specified, skipping\n");
 			continue;
@@ -1733,7 +1733,7 @@ void upgradeTargets() {
 		Common::ConfigManager::Domain &dom = iter->_value;
 		Common::String name(iter->_key);
 		Common::String gameid(dom.getVal("gameid"));
-		Common::String path(dom.getVal("path"));
+		Common::Path path(Common::Path::fromConfig(iter->_value.getVal("path")));
 		printf("Looking at target '%s', gameid '%s' ...\n",
 				name.c_str(), gameid.c_str());
 		if (path.empty()) {
diff --git a/base/main.cpp b/base/main.cpp
index 91c0d394a92..fd5cc35504f 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -173,7 +173,7 @@ static Common::Error runGame(const Plugin *plugin, const Plugin *enginePlugin, O
 	assert(enginePlugin);
 
 	// Determine the game data path, for validation and error messages
-	Common::FSNode dir(ConfMan.get("path"));
+	Common::FSNode dir(ConfMan.getPath("path"));
 	Common::String target = ConfMan.getActiveDomainName();
 	Common::Error err = Common::kNoError;
 	Engine *engine = nullptr;
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 07e5a30cb6d..ce2f6ecee36 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -919,7 +919,7 @@ void EngineManager::upgradeTargetForEngineId(const Common::String &target) const
 	debug("Target '%s' lacks an engine ID, upgrading...", target.c_str());
 
 	Common::String oldGameId = domain->getVal("gameid");
-	Common::String path = domain->getVal("path");
+	Common::Path path = Common::Path::fromConfig(domain->getVal("path"));
 
 	// At this point the game ID and game path must be known
 	if (oldGameId.empty()) {
@@ -943,7 +943,7 @@ void EngineManager::upgradeTargetForEngineId(const Common::String &target) const
 		Common::FSNode dir(path);
 		Common::FSList files;
 		if (!dir.getChildren(files, Common::FSNode::kListAll)) {
-			warning("Failed to access path '%s' when upgrading target '%s'", path.c_str(), target.c_str());
+			warning("Failed to access path '%s' when upgrading target '%s'", path.toString(Common::Path::kNativeSeparator).c_str(), target.c_str());
 			return;
 		}
 
@@ -956,7 +956,7 @@ void EngineManager::upgradeTargetForEngineId(const Common::String &target) const
 		DetectedGames candidates = metaEngine.detectGames(files);
 		if (candidates.empty()) {
 			warning("No games supported by the engine '%s' were found in path '%s' when upgrading target '%s'",
-			        metaEngine.getName(), path.c_str(), target.c_str());
+			        metaEngine.getName(), path.toString(Common::Path::kNativeSeparator).c_str(), target.c_str());
 			return;
 		}
 
diff --git a/common/forbidden.h b/common/forbidden.h
index 21fc6453082..7826f6af396 100644
--- a/common/forbidden.h
+++ b/common/forbidden.h
@@ -352,7 +352,7 @@
 	#endif
 
 	// ScummVM has no equivalent for getting the current directory.
-	// However, you can use ConfMan.get("path") to get the
+	// However, you can use ConfMan.getPath("path") to get the
 	// running game's directory
 	#ifndef FORBIDDEN_SYMBOL_EXCEPTION_getcwd
 	#undef getcwd
@@ -360,7 +360,7 @@
 	#endif
 
 	// ScummVM has no equivalent for getting the current directory.
-	// However, you can use ConfMan.get("path") to get the
+	// However, you can use ConfMan.getPath("path") to get the
 	// running game's directory
 #ifndef FORBIDDEN_SYMBOL_EXCEPTION_getwd
 	#undef getwd


Commit: 339cff9358688c7a470e4d39ff365a4d44b0c72b
    https://github.com/scummvm/scummvm/commit/339cff9358688c7a470e4d39ff365a4d44b0c72b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: Make audio CD use Path class

Changed paths:
    backends/audiocd/default/default-audiocd.cpp
    backends/audiocd/default/default-audiocd.h
    backends/audiocd/linux/linux-audiocd.cpp
    backends/audiocd/macosx/macosx-audiocd.cpp
    backends/audiocd/win32/win32-audiocd.cpp


diff --git a/backends/audiocd/default/default-audiocd.cpp b/backends/audiocd/default/default-audiocd.cpp
index 3988eebd8b4..dc685744646 100644
--- a/backends/audiocd/default/default-audiocd.cpp
+++ b/backends/audiocd/default/default-audiocd.cpp
@@ -87,7 +87,7 @@ bool DefaultAudioCDManager::existExtractedCDAudioFiles(uint track) {
 	for (Common::Array<Common::String>::iterator i = trackNames.begin(); i != trackNames.end(); ++i) {
 		for (const char **ext = extensions; *ext; ++ext) {
 			const Common::String &filename = Common::String::format("%s.%s", i->c_str(), *ext);
-			if (Common::File::exists(filename)) {
+			if (Common::File::exists(Common::Path(filename, '/'))) {
 				return true;
 			}
 		}
@@ -113,7 +113,7 @@ bool DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int du
 		Audio::SeekableAudioStream *stream = nullptr;
 
 		for (Common::Array<Common::String>::iterator i = trackNames.begin(); !stream && i != trackNames.end(); ++i) {
-			stream = Audio::SeekableAudioStream::openStreamFile(*i);
+			stream = Audio::SeekableAudioStream::openStreamFile(Common::Path(*i, '/'));
 		}
 
 		if (stream != nullptr) {
@@ -219,7 +219,7 @@ bool DefaultAudioCDManager::openRealCD() {
 
 	// If not an integer, treat as a drive path
 	if (endPos == cdrom.c_str())
-		return openCD(cdrom);
+		return openCD(Common::Path::fromConfig(cdrom));
 
 	if (drive < 0)
 		return false;
diff --git a/backends/audiocd/default/default-audiocd.h b/backends/audiocd/default/default-audiocd.h
index af18d30fb2c..28d76d8e214 100644
--- a/backends/audiocd/default/default-audiocd.h
+++ b/backends/audiocd/default/default-audiocd.h
@@ -73,7 +73,7 @@ protected:
 	 * @param drive The name of the drive/path
 	 * @note The drive parameter is platform-specific
 	 */
-	virtual bool openCD(const Common::String &drive) { return false; }
+	virtual bool openCD(const Common::Path &drive) { return false; }
 
 	Audio::SoundHandle _handle;
 	bool _emulating;
diff --git a/backends/audiocd/linux/linux-audiocd.cpp b/backends/audiocd/linux/linux-audiocd.cpp
index 056b6c6a585..bf6015baa48 100644
--- a/backends/audiocd/linux/linux-audiocd.cpp
+++ b/backends/audiocd/linux/linux-audiocd.cpp
@@ -183,21 +183,21 @@ public:
 
 protected:
 	bool openCD(int drive) override;
-	bool openCD(const Common::String &drive) override;
+	bool openCD(const Common::Path &drive) override;
 
 private:
 	struct Device {
-		Device(const Common::String &n, dev_t d) : name(n), device(d) {}
-		Common::String name;
+		Device(const Common::Path &n, dev_t d) : name(n), device(d) {}
+		Common::Path name;
 		dev_t device;
 	};
 
 	typedef Common::Array<Device> DeviceList;
 	DeviceList scanDevices();
-	bool tryAddDrive(DeviceList &devices, const Common::String &drive);
-	bool tryAddDrive(DeviceList &devices, const Common::String &drive, dev_t device);
+	bool tryAddDrive(DeviceList &devices, const Common::Path &drive);
+	bool tryAddDrive(DeviceList &devices, const Common::Path &drive, dev_t device);
 	bool tryAddDrive(DeviceList &devices, dev_t device);
-	bool tryAddPath(DeviceList &devices, const Common::String &path);
+	bool tryAddPath(DeviceList &devices, const Common::Path &path);
 	bool tryAddGamePath(DeviceList &devices);
 	bool loadTOC();
 	static bool hasDevice(const DeviceList &devices, dev_t device);
@@ -256,7 +256,7 @@ bool LinuxAudioCDManager::openCD(int drive) {
 	if (drive >= (int)devices.size())
 		return false;
 
-	_fd = ::open(devices[drive].name.c_str(), O_RDONLY | O_NONBLOCK, 0);
+	_fd = ::open(devices[drive].name.toString('/').c_str(), O_RDONLY | O_NONBLOCK, 0);
 	if (_fd < 0)
 		return false;
 
@@ -268,12 +268,12 @@ bool LinuxAudioCDManager::openCD(int drive) {
 	return true;
 }
 
-bool LinuxAudioCDManager::openCD(const Common::String &drive) {
+bool LinuxAudioCDManager::openCD(const Common::Path &drive) {
 	DeviceList devices;
 	if (!tryAddDrive(devices, drive) && !tryAddPath(devices, drive))
 		return false;
 
-	_fd = ::open(devices[0].name.c_str(), O_RDONLY | O_NONBLOCK, 0);
+	_fd = ::open(devices[0].name.toString('/').c_str(), O_RDONLY | O_NONBLOCK, 0);
 	if (_fd < 0)
 		return false;
 
@@ -347,9 +347,9 @@ LinuxAudioCDManager::DeviceList LinuxAudioCDManager::scanDevices() {
 	return devices;
 }
 
-bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, const Common::String &drive) {
+bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, const Common::Path &drive) {
 	struct stat stbuf;
-	if (stat(drive.c_str(), &stbuf) < 0)
+	if (stat(drive.toString('/').c_str(), &stbuf) < 0)
 		return false;
 
 	// Must be a character or block device
@@ -359,12 +359,12 @@ bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, const Common::String
 	return tryAddDrive(devices, drive, stbuf.st_rdev);
 }
 
-bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, const Common::String &drive, dev_t device) {
+bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, const Common::Path &drive, dev_t device) {
 	if (hasDevice(devices, device))
 		return true;
 
 	// Try opening the device and seeing if it is a CD-ROM drve
-	int fd = ::open(drive.c_str(), O_RDONLY | O_NONBLOCK, 0);
+	int fd = ::open(drive.toString('/').c_str(), O_RDONLY | O_NONBLOCK, 0);
 	if (fd >= 0) {
 		cdrom_subchnl info;
 		info.cdsc_format = CDROM_MSF;
@@ -384,14 +384,14 @@ bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, dev_t device) {
 	// Construct the block name
 	// TODO: libblkid's blkid_devno_to_devname is exactly what we look for.
 	// This requires an external dependency though.
-	Common::String name = Common::String::format("/dev/block/%d:%d", major(device), minor(device));
+	Common::Path name(Common::String::format("/dev/block/%d:%d", major(device), minor(device)), '/');
 
 	return tryAddDrive(devices, name, device);
 }
 
-bool LinuxAudioCDManager::tryAddPath(DeviceList &devices, const Common::String &path) {
+bool LinuxAudioCDManager::tryAddPath(DeviceList &devices, const Common::Path &path) {
 	struct stat stbuf;
-	if (stat(path.c_str(), &stbuf) < 0)
+	if (stat(path.toString(Common::Path::kNativeSeparator).c_str(), &stbuf) < 0)
 		return false;
 
 	return tryAddDrive(devices, stbuf.st_dev);
@@ -401,7 +401,7 @@ bool LinuxAudioCDManager::tryAddGamePath(DeviceList &devices) {
 	if (!ConfMan.hasKey("path"))
 		return false;
 
-	return tryAddPath(devices, ConfMan.get("path"));
+	return tryAddPath(devices, ConfMan.getPath("path"));
 }
 
 bool LinuxAudioCDManager::loadTOC() {
diff --git a/backends/audiocd/macosx/macosx-audiocd.cpp b/backends/audiocd/macosx/macosx-audiocd.cpp
index 511c43f2b34..c55c767058d 100644
--- a/backends/audiocd/macosx/macosx-audiocd.cpp
+++ b/backends/audiocd/macosx/macosx-audiocd.cpp
@@ -76,25 +76,24 @@ public:
 
 protected:
 	bool openCD(int drive) override;
-	bool openCD(const Common::String &drive) override;
+	bool openCD(const Common::Path &drive) override;
 
 private:
 	struct Drive {
-		Drive(const Common::String &m, const Common::String &d, const Common::String &f) :
+		Drive(const Common::Path &m, const Common::Path &d, const Common::String &f) :
 			mountPoint(m), deviceName(d), fsType(f) {}
 
-		Common::String mountPoint;
-		Common::String deviceName;
+		Common::Path mountPoint;
+		Common::Path deviceName;
 		Common::String fsType;
 	};
 
 	typedef Common::Array<Drive> DriveList;
 	DriveList detectAllDrives();
-	DriveList detectCDDADrives();
 
-	bool findTrackNames(const Common::String &drivePath);
+	bool findTrackNames(const Common::Path &drivePath);
 
-	Common::HashMap<uint, Common::String> _trackMap;
+	Common::HashMap<uint, Common::Path> _trackMap;
 };
 
 MacOSXAudioCDManager::~MacOSXAudioCDManager() {
@@ -114,7 +113,8 @@ bool MacOSXAudioCDManager::open() {
  * Find the base disk number of device name.
  * Returns -1 if mount point is not /dev/disk*
  */
-static int findBaseDiskNumber(const Common::String &diskName) {
+static int findBaseDiskNumber(const Common::Path &diskPath) {
+	Common::String diskName(diskPath.toString('/'));
 	if (!diskName.hasPrefix("/dev/disk"))
 		return -1;
 
@@ -136,7 +136,7 @@ bool MacOSXAudioCDManager::openCD(int drive) {
 
 	// Try to get the volume related to the game's path
 	if (ConfMan.hasKey("path")) {
-		Common::String gamePath = ConfMan.get("path");
+		Common::String gamePath = ConfMan.getPath("path").toString(Common::Path::kNativeSeparator);
 		struct statfs gamePathStat;
 		if (statfs(gamePath.c_str(), &gamePathStat) == 0) {
 			int baseDiskNumber = findBaseDiskNumber(gamePathStat.f_mntfromname);
@@ -144,7 +144,7 @@ bool MacOSXAudioCDManager::openCD(int drive) {
 				// Look for a CDDA drive with the same base disk number
 				for (uint32 i = 0; i < allDrives.size(); i++) {
 					if (allDrives[i].fsType == "cddafs" && findBaseDiskNumber(allDrives[i].deviceName) == baseDiskNumber) {
-						debug(1, "Preferring drive '%s'", allDrives[i].mountPoint.c_str());
+						debug(1, "Preferring drive '%s'", allDrives[i].mountPoint.toString(Common::Path::kNativeSeparator).c_str());
 						cddaDrives.push_back(allDrives[i]);
 						allDrives.remove_at(i);
 						break;
@@ -162,12 +162,12 @@ bool MacOSXAudioCDManager::openCD(int drive) {
 	if (drive >= (int)cddaDrives.size())
 		return false;
 
-	debug(1, "Using '%s' as the CD drive", cddaDrives[drive].mountPoint.c_str());
+	debug(1, "Using '%s' as the CD drive", cddaDrives[drive].mountPoint.toString(Common::Path::kNativeSeparator).c_str());
 
 	return findTrackNames(cddaDrives[drive].mountPoint);
 }
 
-bool MacOSXAudioCDManager::openCD(const Common::String &drive) {
+bool MacOSXAudioCDManager::openCD(const Common::Path &drive) {
 	DriveList drives = detectAllDrives();
 
 	for (uint32 i = 0; i < drives.size(); i++) {
@@ -175,7 +175,7 @@ bool MacOSXAudioCDManager::openCD(const Common::String &drive) {
 			continue;
 
 		if (drives[i].mountPoint == drive || drives[i].deviceName == drive) {
-			debug(1, "Using '%s' as the CD drive", drives[i].mountPoint.c_str());
+			debug(1, "Using '%s' as the CD drive", drives[i].mountPoint.toString(Common::Path::kNativeSeparator).c_str());
 			return findTrackNames(drives[i].mountPoint);
 		}
 	}
@@ -202,7 +202,8 @@ MacOSXAudioCDManager::DriveList MacOSXAudioCDManager::detectAllDrives() {
 
 	DriveList drives;
 	for (int i = 0; i < foundDrives; i++)
-		drives.push_back(Drive(driveStats[i].f_mntonname, driveStats[i].f_mntfromname, driveStats[i].f_fstypename));
+		drives.push_back(Drive(Common::Path(driveStats[i].f_mntonname, Common::Path::kNativeSeparator),
+			Common::Path(driveStats[i].f_mntfromname, Common::Path::kNativeSeparator), driveStats[i].f_fstypename));
 
 	return drives;
 }
@@ -221,23 +222,23 @@ bool MacOSXAudioCDManager::play(int track, int numLoops, int startFrame, int dur
 		return false;
 
 	// Now load the AIFF track from the name
-	Common::String fileName = _trackMap[track];
-	Common::SeekableReadStream *stream = StdioStream::makeFromPath(fileName.c_str(), false);
+	Common::Path fileName = _trackMap[track];
+	Common::SeekableReadStream *stream = StdioStream::makeFromPath(fileName.toString(Common::Path::kNativeSeparator).c_str(), false);
 
 	if (!stream) {
-		warning("Failed to open track '%s'", fileName.c_str());
+		warning("Failed to open track '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	Audio::AudioStream *audioStream = Audio::makeAIFFStream(stream, DisposeAfterUse::YES);
 	if (!audioStream) {
-		warning("Track '%s' is not an AIFF track", fileName.c_str());
+		warning("Track '%s' is not an AIFF track", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	Audio::SeekableAudioStream *seekStream = dynamic_cast<Audio::SeekableAudioStream *>(audioStream);
 	if (!seekStream) {
-		warning("Track '%s' is not seekable", fileName.c_str());
+		warning("Track '%s' is not seekable", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -252,28 +253,28 @@ bool MacOSXAudioCDManager::play(int track, int numLoops, int startFrame, int dur
 	return true;
 }
 
-bool MacOSXAudioCDManager::findTrackNames(const Common::String &drivePath) {
+bool MacOSXAudioCDManager::findTrackNames(const Common::Path &drivePath) {
 	Common::FSNode directory(drivePath);
 
 	if (!directory.exists()) {
-		warning("Directory '%s' does not exist", drivePath.c_str());
+		warning("Directory '%s' does not exist", drivePath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	if (!directory.isDirectory()) {
-		warning("'%s' is not a directory", drivePath.c_str());
+		warning("'%s' is not a directory", drivePath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	Common::FSList children;
 	if (!directory.getChildren(children, Common::FSNode::kListFilesOnly)) {
-		warning("Failed to find children for '%s'", drivePath.c_str());
+		warning("Failed to find children for '%s'", drivePath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	for (uint32 i = 0; i < children.size(); i++) {
 		if (!children[i].isDirectory()) {
-			Common::String fileName = children[i].getName();
+			Common::String fileName = children[i].getFileName();
 
 			if (fileName.hasSuffix(".aiff") || fileName.hasSuffix(".cdda")) {
 				uint j = 0;
@@ -287,7 +288,7 @@ bool MacOSXAudioCDManager::findTrackNames(const Common::String &drivePath) {
 				long trackID = strtol(trackIDString, &endPtr, 10);
 
 				if (trackIDString != endPtr && trackID > 0 && trackID < UINT_MAX) {
-					_trackMap[trackID - 1] = drivePath + '/' + fileName;
+					_trackMap[trackID - 1] = drivePath.appendComponent(fileName);
 				} else {
 					warning("Invalid track file name: '%s'", fileName.c_str());
 				}
diff --git a/backends/audiocd/win32/win32-audiocd.cpp b/backends/audiocd/win32/win32-audiocd.cpp
index aeb17eb7cba..52c01ff078e 100644
--- a/backends/audiocd/win32/win32-audiocd.cpp
+++ b/backends/audiocd/win32/win32-audiocd.cpp
@@ -155,7 +155,7 @@ public:
 
 protected:
 	bool openCD(int drive) override;
-	bool openCD(const Common::String &drive) override;
+	bool openCD(const Common::Path &drive) override;
 
 private:
 	bool loadTOC();
@@ -213,19 +213,24 @@ bool Win32AudioCDManager::openCD(int drive) {
 	return true;
 }
 
-bool Win32AudioCDManager::openCD(const Common::String &drive) {
+bool Win32AudioCDManager::openCD(const Common::Path &drive) {
 	// Just some bounds checking
-	if (drive.empty() || drive.size() > 3)
+	if (drive.empty())
 		return false;
 
-	if (!Common::isAlpha(drive[0]) || drive[1] != ':')
+	Common::String driveS(drive.toString(Common::Path::kNativeSeparator));
+
+	if (driveS.size() > 3)
+		return false;
+
+	if (!Common::isAlpha(driveS[0]) || driveS[1] != ':')
 		return false;
 
-	if (drive[2] != 0 && drive[2] != '\\')
+	if (driveS[2] != 0 && driveS[2] != '\\')
 		return false;
 
 	DriveList drives;
-	if (!tryAddDrive(toupper(drive[0]), drives))
+	if (!tryAddDrive(toupper(driveS[0]), drives))
 		return false;
 
 	// Construct the drive path and try to open it
@@ -358,8 +363,8 @@ Win32AudioCDManager::DriveList Win32AudioCDManager::detectDrives() {
 	// Try to get the game path's drive
 	char gameDrive = 0;
 	if (ConfMan.hasKey("path")) {
-		Common::String gamePath = ConfMan.get("path");
-		TCHAR *tGamePath = Win32::stringToTchar(gamePath);
+		Common::Path gamePath = ConfMan.getPath("path");
+		TCHAR *tGamePath = Win32::stringToTchar(gamePath.toString(Common::Path::kNativeSeparator));
 		TCHAR fullPath[MAX_PATH];
 		DWORD result = GetFullPathName(tGamePath, MAX_PATH, fullPath, nullptr);
 		free(tGamePath);
@@ -390,14 +395,15 @@ bool Win32AudioCDManager::isDataAndCDAudioReadFromSameCD() {
 	// It is a known bug under Windows that games that play CD audio cause
 	// ScummVM to crash if the data files are read from the same CD.
 	char driveLetter;
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
-	if (!gameDataDir.getPath().empty()) {
-		driveLetter = gameDataDir.getPath()[0];
+	Common::Path gameDataDir(ConfMan.getPath("path"));
+	if (!gameDataDir.empty()) {
+		driveLetter = gameDataDir.toString(Common::Path::kNativeSeparator)[0];
 	} else {
 		// That's it! I give up!
 		Common::FSNode currentDir(".");
-		if (!currentDir.getPath().empty()) {
-			driveLetter = currentDir.getPath()[0];
+		gameDataDir = currentDir.getPath();
+		if (!gameDataDir.empty()) {
+			driveLetter = gameDataDir.toString(Common::Path::kNativeSeparator)[0];
 		} else {
 			return false;
 		}


Commit: b3fbce77823843a3a6485fde7151810649091b1a
    https://github.com/scummvm/scummvm/commit/b3fbce77823843a3a6485fde7151810649091b1a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: Migrate plugins to Path API

Changed paths:
    backends/platform/dc/plugins.cpp
    backends/plugins/dynamic-plugin.h
    backends/plugins/elf/elf-loader.cpp
    backends/plugins/elf/elf-loader.h
    backends/plugins/elf/elf-provider.cpp
    backends/plugins/elf/elf-provider.h
    backends/plugins/kolibrios/kolibrios-provider.cpp
    backends/plugins/posix/posix-provider.cpp
    backends/plugins/psp2/psp2-provider.cpp
    backends/plugins/sdl/sdl-provider.cpp
    backends/plugins/win32/win32-provider.cpp
    base/plugins.cpp
    base/plugins.h


diff --git a/backends/platform/dc/plugins.cpp b/backends/platform/dc/plugins.cpp
index 38dbb6fc691..03f48c81651 100644
--- a/backends/platform/dc/plugins.cpp
+++ b/backends/platform/dc/plugins.cpp
@@ -68,7 +68,7 @@ protected:
 	virtual VoidFunc findSymbol(const char *symbol) {
 		void *func = dlsym(_dlHandle, symbol);
 		if (!func)
-			warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.c_str(), dlerror());
+			warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
 
 		// FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
 		// standard and POSIX: ISO C++ disallows casting between function pointers
@@ -83,19 +83,19 @@ protected:
 	void checkDisc(const DiscLabel &);
 
 public:
-	DCPlugin(const Common::String &filename)
+	DCPlugin(const Common::Path &filename)
 		: DynamicPlugin(filename), _dlHandle(0) {}
 
 	bool loadPlugin() {
 		assert(!_dlHandle);
 		DiscLabel original;
 		checkDisc(_label);
-		drawPluginProgress(_filename);
-		_dlHandle = dlopen(_filename.c_str(), RTLD_LAZY);
+		drawPluginProgress(_filename.toString(Common::Path::kNativeSeparator));
+		_dlHandle = dlopen(_filename.toString(Common::Path::kNativeSeparator).c_str(), RTLD_LAZY);
 
 		if (!_dlHandle) {
 			checkDisc(original);
-			warning("Failed loading plugin '%s' (%s)", _filename.c_str(), dlerror());
+			warning("Failed loading plugin '%s' (%s)", _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
 			return false;
 		}
 
@@ -112,7 +112,7 @@ public:
 		DynamicPlugin::unloadPlugin();
 		if (_dlHandle) {
 			if (dlclose(_dlHandle) != 0)
-				warning("Failed unloading plugin '%s' (%s)", _filename.c_str(), dlerror());
+				warning("Failed unloading plugin '%s' (%s)", _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
 			_dlHandle = 0;
 		}
 	}
diff --git a/backends/plugins/dynamic-plugin.h b/backends/plugins/dynamic-plugin.h
index 2026d149a2b..66e70ec8bc3 100644
--- a/backends/plugins/dynamic-plugin.h
+++ b/backends/plugins/dynamic-plugin.h
@@ -34,10 +34,10 @@ protected:
 
 	virtual VoidFunc findSymbol(const char *symbol) = 0;
 
-	const Common::String _filename;
+	const Common::Path _filename;
 
 public:
-	DynamicPlugin(const Common::String &filename) :
+	DynamicPlugin(const Common::Path &filename) :
 		_filename(filename) {}
 
 	virtual bool loadPlugin() {
@@ -100,8 +100,8 @@ public:
 		delete _pluginObject;
 	}
 
-	virtual const char *getFileName() const {
-		return _filename.c_str();
+	virtual Common::Path getFileName() const override {
+		return _filename;
 	}
 };
 
diff --git a/backends/plugins/elf/elf-loader.cpp b/backends/plugins/elf/elf-loader.cpp
index cbf67f7e876..c63aab130b8 100644
--- a/backends/plugins/elf/elf-loader.cpp
+++ b/backends/plugins/elf/elf-loader.cpp
@@ -325,12 +325,11 @@ void DLObject::relocateSymbols(ptrdiff_t offset) {
 // Track the size of the plugin through memory manager without loading
 // the plugin into memory.
 //
-void DLObject::trackSize(const char *path) {
-
+void DLObject::trackSize(const Common::Path &path) {
 	_file = Common::FSNode(path).createReadStream();
 
 	if (!_file) {
-		warning("elfloader: File %s not found.", path);
+		warning("elfloader: File %s not found.", path.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
@@ -415,19 +414,21 @@ bool DLObject::load() {
 	return true;
 }
 
-bool DLObject::open(const char *path) {
+bool DLObject::open(const Common::Path &path) {
+	Common::String pathS(path.toString(Common::Path::kNativeSeparator));
+
 	void *ctors_start, *ctors_end;
 
-	debug(2, "elfloader: open(\"%s\")", path);
+	debug(2, "elfloader: open(\"%s\")", pathS.c_str());
 
 	_file = Common::FSNode(path).createReadStream();
 
 	if (!_file) {
-		warning("elfloader: File %s not found.", path);
+		warning("elfloader: File %s not found.", pathS.c_str());
 		return false;
 	}
 
-	debug(2, "elfloader: %s found!", path);
+	debug(2, "elfloader: %s found!", pathS.c_str());
 
 	/*Try to load and relocate*/
 	if (!load()) {
@@ -458,7 +459,7 @@ bool DLObject::open(const char *path) {
 	for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++)
 		(**f)();
 
-	debug(2, "elfloader: %s opened ok.", path);
+	debug(2, "elfloader: %s opened ok.", pathS.c_str());
 
 	return true;
 }
diff --git a/backends/plugins/elf/elf-loader.h b/backends/plugins/elf/elf-loader.h
index 03490ef17f6..c033f791a33 100644
--- a/backends/plugins/elf/elf-loader.h
+++ b/backends/plugins/elf/elf-loader.h
@@ -95,8 +95,8 @@ public:
 	 * Test the size of the plugin in memory using the memory manager.
 	 * @param path			Path of file
 	 */
-	void trackSize(const char *path);
-	bool open(const char *path);
+	void trackSize(const Common::Path &path);
+	bool open(const Common::Path &path);
 	bool close();
 	void *symbol(const char *name);
 	void discardSymtab();
diff --git a/backends/plugins/elf/elf-provider.cpp b/backends/plugins/elf/elf-provider.cpp
index f644785097e..94b8730e84d 100644
--- a/backends/plugins/elf/elf-provider.cpp
+++ b/backends/plugins/elf/elf-provider.cpp
@@ -78,9 +78,9 @@ DynamicPlugin::VoidFunc ELFPlugin::findSymbol(const char *symbol) {
 
 	if (!func) {
 		if (!_dlHandle)
-			warning("elfloader: Failed loading symbol '%s' from plugin '%s' (Handle is NULL)", symbol, _filename.c_str());
+			warning("elfloader: Failed loading symbol '%s' from plugin '%s' (Handle is NULL)", symbol, _filename.toString(Common::Path::kNativeSeparator).c_str());
 		else
-			warning("elfloader: Failed loading symbol '%s' from plugin '%s'", symbol, _filename.c_str());
+			warning("elfloader: Failed loading symbol '%s' from plugin '%s'", symbol, _filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	// FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
@@ -100,7 +100,7 @@ void ELFPlugin::trackSize() {
 	// All we need to do is create our object, track its size, then delete it
 	DLObject *obj = makeDLObject();
 
-	obj->trackSize(_filename.c_str());
+	obj->trackSize(_filename);
 	delete obj;
 }
 
@@ -108,7 +108,7 @@ bool ELFPlugin::loadPlugin() {
 	assert(!_dlHandle);
 
 	DLObject *obj = makeDLObject();
-	if (obj->open(_filename.c_str())) {
+	if (obj->open(_filename)) {
 		_dlHandle = obj;
 	} else {
 		delete obj;
@@ -116,20 +116,20 @@ bool ELFPlugin::loadPlugin() {
 	}
 
 	if (!_dlHandle) {
-		warning("elfloader: Failed loading plugin '%s'", _filename.c_str());
+		warning("elfloader: Failed loading plugin '%s'", _filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	CharFunc buildDateFunc = (CharFunc)findSymbol("PLUGIN_getBuildDate");
 	if (!buildDateFunc) {
 		unloadPlugin();
-		warning("elfloader: plugin '%s' is missing symbols", _filename.c_str());
+		warning("elfloader: plugin '%s' is missing symbols", _filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	if (strncmp(gScummVMPluginBuildDate, buildDateFunc(), strlen(gScummVMPluginBuildDate))) {
 		unloadPlugin();
-		warning("elfloader: plugin '%s' has a different build date", _filename.c_str());
+		warning("elfloader: plugin '%s' has a different build date", _filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -163,7 +163,7 @@ void ELFPlugin::unloadPlugin() {
 #endif
 
 		if (!_dlHandle->close())
-			warning("elfloader: Failed unloading plugin '%s'", _filename.c_str());
+			warning("elfloader: Failed unloading plugin '%s'", _filename.toString(Common::Path::kNativeSeparator).c_str());
 
 		delete _dlHandle;
 		_dlHandle = 0;
@@ -198,7 +198,7 @@ PluginList ELFPluginProvider::getPlugins() {
 
 bool ELFPluginProvider::isPluginFilename(const Common::FSNode &node) const {
 	// Check the plugin suffix
-	Common::String filename = node.getName();
+	Common::String filename = node.getFileName();
 
 	if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg") &&
 			!filename.hasSuffix(".PLUGIN") && !filename.hasSuffix(".plugin"))
diff --git a/backends/plugins/elf/elf-provider.h b/backends/plugins/elf/elf-provider.h
index 94f62f34778..90a80b64598 100644
--- a/backends/plugins/elf/elf-provider.h
+++ b/backends/plugins/elf/elf-provider.h
@@ -49,7 +49,7 @@ protected:
 	virtual VoidFunc findSymbol(const char *symbol);
 
 public:
-	ELFPlugin(const Common::String &filename) :
+	ELFPlugin(const Common::Path &filename) :
 		DynamicPlugin(filename),
 		_dlHandle(0),
 		_dso_handle(0) {
@@ -70,7 +70,7 @@ public:
 template<class T>
 class TemplatedELFPlugin : public ELFPlugin {
 public:
-	TemplatedELFPlugin(const Common::String &filename) :
+	TemplatedELFPlugin(const Common::Path &filename) :
 		ELFPlugin(filename) {
 	}
 
diff --git a/backends/plugins/kolibrios/kolibrios-provider.cpp b/backends/plugins/kolibrios/kolibrios-provider.cpp
index 0327273a948..7f5de38f3e0 100644
--- a/backends/plugins/kolibrios/kolibrios-provider.cpp
+++ b/backends/plugins/kolibrios/kolibrios-provider.cpp
@@ -46,19 +46,19 @@ protected:
 	}
 
 public:
-	KolibriOSPlugin(const Common::String &filename)
+	KolibriOSPlugin(const Common::Path &filename)
 		: DynamicPlugin(filename), _dlHandle(0) {}
 
 	bool loadPlugin() override {
 		if (_dlHandle)
 			return true;
-		_dlHandle = load_library(_filename.c_str());
+		_dlHandle = load_library(_filename.toString(Common::Path::kNativeSeparator).c_str());
 
 		if (!_dlHandle) {
-			debug("Failed loading plugin '%s' (error code %d)", _filename.c_str(), errno);
+			debug("Failed loading plugin '%s' (error code %d)", _filename.toString(Common::Path::kNativeSeparator).c_str(), errno);
 			return false;
 		} else {
-			debug(1, "Success loading plugin '%s', handle %p", _filename.c_str(), _dlHandle);
+			debug(1, "Success loading plugin '%s', handle %p", _filename.toString(Common::Path::kNativeSeparator).c_str(), _dlHandle);
 		}
 
 		return DynamicPlugin::loadPlugin();
diff --git a/backends/plugins/posix/posix-provider.cpp b/backends/plugins/posix/posix-provider.cpp
index a83e031b287..c8eb827ae31 100644
--- a/backends/plugins/posix/posix-provider.cpp
+++ b/backends/plugins/posix/posix-provider.cpp
@@ -37,7 +37,7 @@ protected:
 	virtual VoidFunc findSymbol(const char *symbol) {
 		void *func = dlsym(_dlHandle, symbol);
 		if (!func)
-			warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.c_str(), dlerror());
+			warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
 
 		// FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
 		// standard and POSIX: ISO C++ disallows casting between function pointers
@@ -50,15 +50,15 @@ protected:
 	}
 
 public:
-	POSIXPlugin(const Common::String &filename)
+	POSIXPlugin(const Common::Path &filename)
 		: DynamicPlugin(filename), _dlHandle(0) {}
 
 	bool loadPlugin() {
 		assert(!_dlHandle);
-		_dlHandle = dlopen(_filename.c_str(), RTLD_LAZY);
+		_dlHandle = dlopen(_filename.toString(Common::Path::kNativeSeparator).c_str(), RTLD_LAZY);
 
 		if (!_dlHandle) {
-			warning("Failed loading plugin '%s' (%s)", _filename.c_str(), dlerror());
+			warning("Failed loading plugin '%s' (%s)", _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
 			return false;
 		}
 
@@ -69,7 +69,7 @@ public:
 		DynamicPlugin::unloadPlugin();
 		if (_dlHandle) {
 			if (dlclose(_dlHandle) != 0)
-				warning("Failed unloading plugin '%s' (%s)", _filename.c_str(), dlerror());
+				warning("Failed unloading plugin '%s' (%s)", _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
 			_dlHandle = 0;
 		}
 	}
diff --git a/backends/plugins/psp2/psp2-provider.cpp b/backends/plugins/psp2/psp2-provider.cpp
index e67a6ea64db..b9aec769b88 100644
--- a/backends/plugins/psp2/psp2-provider.cpp
+++ b/backends/plugins/psp2/psp2-provider.cpp
@@ -62,10 +62,10 @@ void *forceLinkFunctions[] = {
 class PSP2Plugin final : public Plugin {
 protected:
 	SceUID _modId;
-	const Common::String _filename;
+	const Common::Path _filename;
 
 public:
-	PSP2Plugin(const Common::String &filename)
+	PSP2Plugin(const Common::Path &filename)
 		: _filename(filename), _modId(0) {}
 
 	bool loadPlugin() override {
@@ -74,23 +74,23 @@ public:
 		PSP2FunctionPointers **arg = &functions;
 
 		int status = 0;
-		_modId = sceKernelLoadStartModule(_filename.c_str(), sizeof( arg ), &arg, 0, NULL, &status );
+		_modId = sceKernelLoadStartModule(_filename.toString(Common::Path::kNativeSeparator).c_str(), sizeof( arg ), &arg, 0, NULL, &status );
 
 		if (!_modId) {
-			debug("Failed loading plugin '%s' (error code %d)", _filename.c_str(), status);
+			debug("Failed loading plugin '%s' (error code %d)", _filename.toString(Common::Path::kNativeSeparator).c_str(), status);
 			return false;
 		} else {
-			debug(1, "Success loading plugin '%s', handle %08x", _filename.c_str(), _modId);
+			debug(1, "Success loading plugin '%s', handle %08x", _filename.toString(Common::Path::kNativeSeparator).c_str(), _modId);
 		}
 
 		// Validate the Vita version
 		if (!functions) {
-			debug("Failed loading plugin '%s': no pointer", _filename.c_str());
+			debug("Failed loading plugin '%s': no pointer", _filename.toString(Common::Path::kNativeSeparator).c_str());
 			unloadPlugin();
 			return false;
 		}
 		if (functions->version != PSP2FunctionPointers_VERSION) {
-			debug("Failed loading plugin '%s': unexpected version %d", _filename.c_str(), functions->version);
+			debug("Failed loading plugin '%s': unexpected version %d", _filename.toString(Common::Path::kNativeSeparator).c_str(), functions->version);
 			unloadPlugin();
 			return false;
 		}
@@ -127,7 +127,7 @@ public:
 			return false;
 		}
 
-		debug(1, "Successfully loaded plugin '%s'", _filename.c_str());
+		debug(1, "Successfully loaded plugin '%s'", _filename.toString(Common::Path::kNativeSeparator).c_str());
 		return true;
 	}
 
@@ -138,14 +138,14 @@ public:
 			int status = 0;
 			int ret = sceKernelStopUnloadModule(_modId, 0, NULL, 0, NULL, &status);
 			if (ret != SCE_OK) {
-				debug("Failed unloading plugin '%s': %d/%d", _filename.c_str(), ret, status);
+				debug("Failed unloading plugin '%s': %d/%d", _filename.toString(Common::Path::kNativeSeparator).c_str(), ret, status);
 			}
 			_modId = 0;
 		}
 	}
 
-	virtual const char *getFileName() const {
-		return _filename.c_str();
+	Common::Path getFileName() const override {
+		return _filename;
 	}
 };
 
diff --git a/backends/plugins/sdl/sdl-provider.cpp b/backends/plugins/sdl/sdl-provider.cpp
index 75c51dfe0de..ad1da0091aa 100644
--- a/backends/plugins/sdl/sdl-provider.cpp
+++ b/backends/plugins/sdl/sdl-provider.cpp
@@ -37,7 +37,7 @@ protected:
 	virtual VoidFunc findSymbol(const char *symbol) {
 		void *func = SDL_LoadFunction(_dlHandle, symbol);
 		if (!func)
-			warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.c_str(), SDL_GetError());
+			warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.toString(Common::Path::kNativeSeparator).c_str(), SDL_GetError());
 
 		// FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
 		// standard and POSIX: ISO C++ disallows casting between function pointers
@@ -50,15 +50,15 @@ protected:
 	}
 
 public:
-	SDLPlugin(const Common::String &filename)
+	SDLPlugin(const Common::Path &filename)
 		: DynamicPlugin(filename), _dlHandle(0) {}
 
 	bool loadPlugin() {
 		assert(!_dlHandle);
-		_dlHandle = SDL_LoadObject(_filename.c_str());
+		_dlHandle = SDL_LoadObject(_filename.toString(Common::Path::kNativeSeparator).c_str());
 
 		if (!_dlHandle) {
-			warning("Failed loading plugin '%s' (%s)", _filename.c_str(), SDL_GetError());
+			warning("Failed loading plugin '%s' (%s)", _filename.toString(Common::Path::kNativeSeparator).c_str(), SDL_GetError());
 			return false;
 		}
 
diff --git a/backends/plugins/win32/win32-provider.cpp b/backends/plugins/win32/win32-provider.cpp
index 818b58b2e89..01bc8579b30 100644
--- a/backends/plugins/win32/win32-provider.cpp
+++ b/backends/plugins/win32/win32-provider.cpp
@@ -43,13 +43,13 @@ protected:
 	VoidFunc findSymbol(const char *symbol) override {
 		FARPROC func = GetProcAddress((HMODULE)_dlHandle, symbol);
 		if (!func)
-			debug("Failed loading symbol '%s' from plugin '%s'", symbol, _filename.c_str());
+			debug("Failed loading symbol '%s' from plugin '%s'", symbol, _filename.toString(Common::Path::kNativeSeparator).c_str());
 
 		return (void (*)())func;
 	}
 
 public:
-	Win32Plugin(const Common::String &filename)
+	Win32Plugin(const Common::Path &filename)
 		: DynamicPlugin(filename), _dlHandle(0) {}
 
 	bool loadPlugin() override {
@@ -59,10 +59,10 @@ public:
 		free(tFilename);
 
 		if (!_dlHandle) {
-			warning("Failed loading plugin '%s' (error code %d)", _filename.c_str(), (int32) GetLastError());
+			warning("Failed loading plugin '%s' (error code %d)", _filename.toString(Common::Path::kNativeSeparator).c_str(), (int32) GetLastError());
 			return false;
 		} else {
-			debug(1, "Success loading plugin '%s', handle %p", _filename.c_str(), _dlHandle);
+			debug(1, "Success loading plugin '%s', handle %p", _filename.toString(Common::Path::kNativeSeparator).c_str(), _dlHandle);
 		}
 
 		return DynamicPlugin::loadPlugin();
@@ -72,9 +72,9 @@ public:
 		DynamicPlugin::unloadPlugin();
 		if (_dlHandle) {
 			if (!FreeLibrary((HMODULE)_dlHandle))
-				warning("Failed unloading plugin '%s'", _filename.c_str());
+				warning("Failed unloading plugin '%s'", _filename.toString(Common::Path::kNativeSeparator).c_str());
 			else
-				debug(1, "Success unloading plugin '%s'", _filename.c_str());
+				debug(1, "Success unloading plugin '%s'", _filename.toString(Common::Path::kNativeSeparator).c_str());
 			_dlHandle = 0;
 		}
 	}
diff --git a/base/plugins.cpp b/base/plugins.cpp
index ce2f6ecee36..5b7a438fde4 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -206,10 +206,10 @@ PluginList FilePluginProvider::getPlugins() {
 		// Scan for all plugins in this directory
 		Common::FSList files;
 		if (!dir->getChildren(files, Common::FSNode::kListFilesOnly)) {
-			debug(1, "Couldn't open plugin directory '%s'", dir->getPath().c_str());
+			debug(1, "Couldn't open plugin directory '%s'", dir->getPath().toString().c_str());
 			continue;
 		} else {
-			debug(1, "Reading plugins from plugin directory '%s'", dir->getPath().c_str());
+			debug(1, "Reading plugins from plugin directory '%s'", dir->getPath().toString().c_str());
 		}
 
 		for (Common::FSList::const_iterator i = files.begin(); i != files.end(); ++i) {
@@ -296,7 +296,7 @@ const Plugin *PluginManager::getEngineFromMetaEngine(const Plugin *plugin) {
 	enginePlugin = PluginMan.findEnginePlugin(metaEnginePluginName);
 
 	if (enginePlugin) {
-		debug(9, "MetaEngine: %s \t matched to \t Engine: %s", plugin->get<MetaEngineDetection>().getEngineName(), enginePlugin->getFileName());
+		debug(9, "MetaEngine: %s \t matched to \t Engine: %s", plugin->get<MetaEngineDetection>().getEngineName(), enginePlugin->getFileName().toString().c_str());
 		return enginePlugin;
 	}
 
@@ -325,11 +325,11 @@ const Plugin *PluginManager::getMetaEngineFromEngine(const Plugin *plugin) {
 	}
 
 	if (metaEngine) {
-		debug(9, "Engine: %s matched to MetaEngine: %s", plugin->getFileName(), metaEngine->get<MetaEngineDetection>().getEngineName());
+		debug(9, "Engine: %s matched to MetaEngine: %s", plugin->getFileName().toString().c_str(), metaEngine->get<MetaEngineDetection>().getEngineName());
 		return metaEngine;
 	}
 
-	debug(9, "Engine: %s couldn't find a match for a MetaEngine plugin.", plugin->getFileName());
+	debug(9, "Engine: %s couldn't find a match for a MetaEngine plugin.", plugin->getFileName().toString().c_str());
 	return nullptr;
 }
 
@@ -364,8 +364,8 @@ void PluginManagerUncached::init() {
 			// music or an engine plugin.
 #ifndef DETECTION_STATIC
 			if (!foundDetectPlugin && (*pp)->isFilePluginProvider()) {
-				Common::String pName = (*p)->getFileName();
-				if (pName.hasSuffixIgnoreCase(detectPluginName)) {
+				Common::Path pName = (*p)->getFileName();
+				if (pName.baseName().hasSuffixIgnoreCase(detectPluginName)) {
 					_detectionPlugin = (*p);
 					foundDetectPlugin = true;
 					debug(9, "Detection plugin found!");
@@ -398,7 +398,7 @@ bool PluginManagerUncached::loadPluginFromEngineId(const Common::String &engineI
 
 	if (domain) {
 		if (domain->contains(engineId)) {
-			Common::String filename = (*domain)[engineId];
+			Common::Path filename(Common::Path::fromConfig((*domain)[engineId]));
 
 			if (loadPluginByFileName(filename)) {
 				return true;
@@ -412,8 +412,8 @@ bool PluginManagerUncached::loadPluginFromEngineId(const Common::String &engineI
 	tentativeEnginePluginFilename += PLUGIN_SUFFIX;
 #endif
 	for (PluginList::iterator p = _allEnginePlugins.begin(); p != _allEnginePlugins.end(); ++p) {
-		Common::String filename = (*p)->getFileName();
-		if (filename.hasSuffixIgnoreCase(tentativeEnginePluginFilename)) {
+		Common::Path filename = (*p)->getFileName();
+		if (filename.baseName().hasSuffixIgnoreCase(tentativeEnginePluginFilename)) {
 			if (loadPluginByFileName(filename)) {
 				return true;
 			}
@@ -425,7 +425,7 @@ bool PluginManagerUncached::loadPluginFromEngineId(const Common::String &engineI
 /**
  * Load a plugin with a filename taken from ConfigManager.
  **/
-bool PluginManagerUncached::loadPluginByFileName(const Common::String &filename) {
+bool PluginManagerUncached::loadPluginByFileName(const Common::Path &filename) {
 	if (filename.empty())
 		return false;
 
@@ -433,7 +433,7 @@ bool PluginManagerUncached::loadPluginByFileName(const Common::String &filename)
 
 	PluginList::iterator i;
 	for (i = _allEnginePlugins.begin(); i != _allEnginePlugins.end(); ++i) {
-		if (Common::String((*i)->getFileName()) == filename && (*i)->loadPlugin()) {
+		if ((*i)->getFileName() == filename && (*i)->loadPlugin()) {
 			addToPluginsInMemList(*i);
 			_currentPlugin = i;
 			return true;
@@ -448,13 +448,13 @@ bool PluginManagerUncached::loadPluginByFileName(const Common::String &filename)
  **/
 void PluginManagerUncached::updateConfigWithFileName(const Common::String &engineId) {
 	// Check if we have a filename for the current plugin
-	if ((*_currentPlugin)->getFileName()) {
+	if (!(*_currentPlugin)->getFileName().empty()) {
 		if (!ConfMan.hasMiscDomain("engine_plugin_files"))
 			ConfMan.addMiscDomain("engine_plugin_files");
 
 		Common::ConfigManager::Domain *domain = ConfMan.getDomain("engine_plugin_files");
 		assert(domain);
-		(*domain).setVal(engineId, (*_currentPlugin)->getFileName());
+		(*domain).setVal(engineId, (*_currentPlugin)->getFileName().toConfig());
 
 		ConfMan.flushToDisk();
 	}
diff --git a/base/plugins.h b/base/plugins.h
index c5c9721d187..f2624e7aec4 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -178,7 +178,7 @@ public:
 	 * plugins that have files (ie. not static). It doesn't require the plugin
 	 * object to be loaded into memory, unlike getName()
 	 **/
-	virtual const char *getFileName() const { return 0; }
+	virtual Common::Path getFileName() const { return Common::Path(); }
 };
 
 class StaticPlugin : public Plugin {
@@ -362,7 +362,7 @@ protected:
 	bool _isDetectionLoaded;
 
 	PluginManagerUncached() : _isDetectionLoaded(false), _detectionPlugin(nullptr) {}
-	bool loadPluginByFileName(const Common::String &filename);
+	bool loadPluginByFileName(const Common::Path &filename);
 
 public:
 	void init() override;


Commit: 40dcce567bb4494eab0435eeea35ccd9f30f731f
    https://github.com/scummvm/scummvm/commit/40dcce567bb4494eab0435eeea35ccd9f30f731f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: DC: Start considering game paths as Path class

Changed paths:
    backends/platform/dc/selector.cpp


diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp
index 7b558bad9dd..53f3dda0858 100644
--- a/backends/platform/dc/selector.cpp
+++ b/backends/platform/dc/selector.cpp
@@ -132,9 +132,7 @@ static int findGames(Game *games, int max, bool use_ini)
 	const Common::ConfigManager::DomainMap &game_domains = ConfMan.getGameDomains();
 	for(Common::ConfigManager::DomainMap::const_iterator i =
 	  game_domains.begin(); curr_game < max && i != game_domains.end(); i++) {
-	  Common::String path = (*i)._value["path"];
-	  if (path.size() && path.lastChar() != '/')
-	path += "/";
+	  Common::Path path(Common::Path::fromConfig((*i)._value["path"]));
 	  int j;
 	  for (j=0; j<num_dirs; j++)
 	if (path.equals(dirs[j].node.getPath()))
@@ -148,7 +146,7 @@ static int findGames(Game *games, int max, bool use_ini)
 	Common::strcpy_s(games[curr_game].filename_base, (*i)._key.c_str());
 	strncpy(games[curr_game].engine_id, (*i)._value["engineid"].c_str(), 256);
 	games[curr_game].engine_id[255] = '\0';
-	strncpy(games[curr_game].dir, dirs[j].node.getPath().c_str(), 256);
+	strncpy(games[curr_game].dir, dirs[j].node.getPath().toString().c_str(), 256);
 	games[curr_game].dir[255] = '\0';
 	games[curr_game].language = Common::UNK_LANG;
 	games[curr_game].platform = Common::kPlatformUnknown;
@@ -161,7 +159,7 @@ static int findGames(Game *games, int max, bool use_ini)
   }
 
   while ((curr_game < max || use_ini) && curr_dir < num_dirs) {
-	strncpy(dirs[curr_dir].name, dirs[curr_dir].node.getPath().c_str(), 251);
+	strncpy(dirs[curr_dir].name, dirs[curr_dir].node.getPath().toString().c_str(), 251);
 	dirs[curr_dir].name[250] = '\0';
 	if (!dirs[curr_dir].name[0] ||
 	dirs[curr_dir].name[strlen(dirs[curr_dir].name)-1] != '/')
@@ -421,7 +419,7 @@ static int findPluginDirs(Game *plugin_dirs, int max, const Common::FSNode &base
 	if (entry->isDirectory()) {
 	  if (curr_dir >= max)
 	break;
-	  strncpy(plugin_dirs[curr_dir].dir, (*entry).getPath().c_str(), 256);
+	  strncpy(plugin_dirs[curr_dir].dir, (*entry).getPath().toString().c_str(), 256);
 	  strncpy(plugin_dirs[curr_dir].text, (*entry).getName().c_str(), 256);
 	  plugin_dirs[curr_dir].icon.load(NULL, 0, 0);
 	  curr_dir++;


Commit: 7853b05482e1d36254d41d321c460c2ef00427c1
    https://github.com/scummvm/scummvm/commit/7853b05482e1d36254d41d321c460c2ef00427c1
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: WII: Start considering game paths as Path class

Changed paths:
    backends/platform/wii/osystem.cpp


diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp
index 070ca17d7a0..282718e5cbd 100644
--- a/backends/platform/wii/osystem.cpp
+++ b/backends/platform/wii/osystem.cpp
@@ -163,7 +163,7 @@ void OSystem_Wii::quit() {
 
 void OSystem_Wii::engineInit() {
 	_gameRunning = true;
-	WiiFilesystemFactory::instance().umountUnused(ConfMan.get("path"));
+	WiiFilesystemFactory::instance().umountUnused(ConfMan.getPath("path").toString(Common::Path::kNativeSeparator));
 }
 
 void OSystem_Wii::engineDone() {


Commit: e1aeab81f5695ec28f93ff0f891a75662876bf81
    https://github.com/scummvm/scummvm/commit/e1aeab81f5695ec28f93ff0f891a75662876bf81
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ACCESS: Migrate engine to Path

Changed paths:
    engines/access/access.cpp
    engines/access/access.h
    engines/access/debugger.h
    engines/access/files.cpp
    engines/access/files.h
    engines/access/player.cpp
    engines/access/player.h
    engines/access/resources.h
    engines/access/video.cpp
    engines/access/video.h
    engines/access/video/movie_decoder.cpp


diff --git a/engines/access/access.cpp b/engines/access/access.cpp
index 29c34ea3091..20ea2827c00 100644
--- a/engines/access/access.cpp
+++ b/engines/access/access.cpp
@@ -154,7 +154,7 @@ void AccessEngine::setVGA() {
 
 void AccessEngine::initialize() {
 	if (isCD()) {
-		const Common::FSNode gameDataDir(ConfMan.get("path"));
+		const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 		// The CD version contains two versions of the game.
 		// - The MCGA version, in the CDROM folder
 		// - The VESA version, in the TDROM folder
diff --git a/engines/access/access.h b/engines/access/access.h
index a77a4f4ac98..776915095ca 100644
--- a/engines/access/access.h
+++ b/engines/access/access.h
@@ -303,7 +303,7 @@ public:
 	void SPRINTCHR(char c, int fontNum);
 	void PRINTCHR(Common::String msg, int fontNum);
 
-	bool playMovie(const Common::String &filename, const Common::Point &pos);
+	bool playMovie(const Common::Path &filename, const Common::Point &pos);
 };
 
 } // End of namespace Access
diff --git a/engines/access/debugger.h b/engines/access/debugger.h
index 071463ed83a..e2f9b83ce81 100644
--- a/engines/access/debugger.h
+++ b/engines/access/debugger.h
@@ -34,7 +34,7 @@ class AccessEngine;
 class Debugger : public GUI::Debugger {
 protected:
 	AccessEngine *_vm;
-	Common::String _playMovieFile;
+	Common::Path _playMovieFile;
 
 	bool Cmd_LoadScene(int argc, const char **argv);
 	bool Cmd_Cheat(int argc, const char **argv);
diff --git a/engines/access/files.cpp b/engines/access/files.cpp
index af51ed8e212..09b9cc798fa 100644
--- a/engines/access/files.cpp
+++ b/engines/access/files.cpp
@@ -103,7 +103,7 @@ Resource *FileManager::loadFile(const FileIdent &fileIdent) {
 	return loadFile(fileIdent._fileNum, fileIdent._subfile);
 }
 
-Resource *FileManager::loadFile(const Common::String &filename) {
+Resource *FileManager::loadFile(const Common::Path &filename) {
 	Resource *res = new Resource();
 
 	// Open the file
@@ -117,16 +117,15 @@ Resource *FileManager::loadFile(const Common::String &filename) {
 	return res;
 }
 
-bool FileManager::existFile(const Common::String &filename) {
-	Common::File f;
-	return f.exists(filename);
+bool FileManager::existFile(const Common::Path &filename) {
+	return Common::File::exists(filename);
 }
 
-void FileManager::openFile(Resource *res, const Common::String &filename) {
+void FileManager::openFile(Resource *res, const Common::Path &filename) {
 	// Open up the file
 	_fileNumber = -1;
 	if (!res->_file.open(filename))
-		error("Could not open file - %s", filename.c_str());
+		error("Could not open file - %s", filename.toString().c_str());
 }
 
 void FileManager::loadScreen(Graphics::ManagedSurface *dest, int fileNum, int subfile) {
@@ -163,7 +162,7 @@ void FileManager::loadScreen(int fileNum, int subfile) {
 	loadScreen(_vm->_screen, fileNum, subfile);
 }
 
-void FileManager::loadScreen(const Common::String &filename) {
+void FileManager::loadScreen(const Common::Path &filename) {
 	Resource *res = loadFile(filename);
 	handleScreen(_vm->_screen, res);
 	delete res;
@@ -198,7 +197,7 @@ void FileManager::handleFile(Resource *res) {
 void FileManager::setAppended(Resource *res, int fileNum) {
 	// Open the file for access
 	if (!res->_file.open(_vm->_res->FILENAMES[fileNum]))
-		error("Could not open file %s", _vm->_res->FILENAMES[fileNum].c_str());
+		error("Could not open file %s", _vm->_res->FILENAMES[fileNum].toString().c_str());
 
 	// If a different file has been opened then previously, load its index
 	if (_fileNumber != fileNum) {
diff --git a/engines/access/files.h b/engines/access/files.h
index 043624b9e5b..d1b8631bde6 100644
--- a/engines/access/files.h
+++ b/engines/access/files.h
@@ -70,7 +70,7 @@ class FileManager {
 private:
 	AccessEngine *_vm;
 
-	void openFile(Resource *res, const Common::String &filename);
+	void openFile(Resource *res, const Common::Path &filename);
 
 	/**
 	 * Handles setting up the resource with a stream for the located resource
@@ -102,7 +102,7 @@ public:
 	/**
 	 * Check the existence of a given file
 	 */
-	bool existFile(const Common::String &filename);
+	bool existFile(const Common::Path &filename);
 
 	/**
 	 * Load a given subfile from a container file
@@ -117,7 +117,7 @@ public:
 	/**
 	 * Load a given file by name
 	 */
-	Resource *loadFile(const Common::String &filename);
+	Resource *loadFile(const Common::Path &filename);
 
 	/**
 	 * Load a given scren from a container file
@@ -127,7 +127,7 @@ public:
 	/**
 	* Load a given screen by name
 	*/
-	void loadScreen(const Common::String &filename);
+	void loadScreen(const Common::Path &filename);
 
 	/**
 	 * Load a screen resource onto a designated surface
diff --git a/engines/access/player.cpp b/engines/access/player.cpp
index 825b0bd51c6..efba602317a 100644
--- a/engines/access/player.cpp
+++ b/engines/access/player.cpp
@@ -144,7 +144,7 @@ void Player::loadTexPalette() {
 	memcpy(_manPal1, texPal->data(), size);
 }
 
-void Player::loadSprites(const Common::String &name) {
+void Player::loadSprites(const Common::Path &name) {
 	freeSprites();
 
 	Resource *data = _vm->_files->loadFile(name);
diff --git a/engines/access/player.h b/engines/access/player.h
index 7a048964293..9093c15f845 100644
--- a/engines/access/player.h
+++ b/engines/access/player.h
@@ -121,7 +121,7 @@ public:
 
 	void loadTexPalette();
 
-	void loadSprites(const Common::String &name);
+	void loadSprites(const Common::Path &name);
 
 	void freeSprites();
 
diff --git a/engines/access/resources.h b/engines/access/resources.h
index d7432dc89cf..40b22a70538 100644
--- a/engines/access/resources.h
+++ b/engines/access/resources.h
@@ -80,7 +80,7 @@ protected:
 	 */
 	virtual void load(Common::SeekableReadStream &s);
 public:
-	Common::StringArray FILENAMES;
+	Common::Array<Common::Path> FILENAMES;
 	Common::Array< Common::Array<byte> > CHARTBL;
 	Common::Array<RoomEntry> ROOMTBL;
 	Common::Array<DeathEntry> DEATHS;
diff --git a/engines/access/video.cpp b/engines/access/video.cpp
index 94b96eb36a9..9a857b39c25 100644
--- a/engines/access/video.cpp
+++ b/engines/access/video.cpp
@@ -86,7 +86,7 @@ void VideoPlayer::setVideo(BaseSurface *vidSurface, const Common::Point &pt, int
 	_videoEnd = false;
 }
 
-void VideoPlayer::setVideo(BaseSurface *vidSurface, const Common::Point &pt, const Common::String filename, int rate) {
+void VideoPlayer::setVideo(BaseSurface *vidSurface, const Common::Point &pt, const Common::Path &filename, int rate) {
 	// Open up video stream
 	_videoData = _vm->_files->loadFile(filename);
 
diff --git a/engines/access/video.h b/engines/access/video.h
index cf19ed3c405..d5825c25e9c 100644
--- a/engines/access/video.h
+++ b/engines/access/video.h
@@ -64,7 +64,7 @@ public:
 	 * Start up a video
 	 */
 	void setVideo(BaseSurface *vidSurface, const Common::Point &pt, const FileIdent &videoFile, int rate);
-	void setVideo(BaseSurface *vidSurface, const Common::Point &pt, const Common::String filename, int rate);
+	void setVideo(BaseSurface *vidSurface, const Common::Point &pt, const Common::Path &filename, int rate);
 
 	/**
 	 * Decodes a frame of the video
diff --git a/engines/access/video/movie_decoder.cpp b/engines/access/video/movie_decoder.cpp
index b22788fa445..b760eb8586e 100644
--- a/engines/access/video/movie_decoder.cpp
+++ b/engines/access/video/movie_decoder.cpp
@@ -692,13 +692,13 @@ Audio::AudioStream *AccessVIDMovieDecoder::StreamAudioTrack::getAudioStream() co
 	return _audioStream;
 }
 
-bool AccessEngine::playMovie(const Common::String &filename, const Common::Point &pos) {
+bool AccessEngine::playMovie(const Common::Path &filename, const Common::Point &pos) {
 	AccessVIDMovieDecoder videoDecoder;
 
 	Common::Point framePos(pos.x, pos.y);
 
 	if (!videoDecoder.loadFile(filename)) {
-		warning("AccessVIDMoviePlay: could not open '%s'", filename.c_str());
+		warning("AccessVIDMoviePlay: could not open '%s'", filename.toString().c_str());
 		return false;
 	}
 


Commit: 4b00b7e83d1554898ab26db0123f397034dd426e
    https://github.com/scummvm/scummvm/commit/4b00b7e83d1554898ab26db0123f397034dd426e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ADL: Migrate engine to Path

Changed paths:
    engines/adl/adl.h
    engines/adl/console.cpp
    engines/adl/console.h
    engines/adl/detection.cpp
    engines/adl/disk.cpp
    engines/adl/disk.h
    engines/adl/hires1.cpp
    engines/adl/hires2.cpp
    engines/adl/hires4.cpp
    engines/adl/metaengine.cpp


diff --git a/engines/adl/adl.h b/engines/adl/adl.h
index bd886d681e4..4c0d54d99a4 100644
--- a/engines/adl/adl.h
+++ b/engines/adl/adl.h
@@ -54,7 +54,7 @@ class RandomSource;
 
 namespace Adl {
 
-Common::String getDiskImageName(const AdlGameDescription &adlDesc, byte volume);
+Common::Path getDiskImageName(const AdlGameDescription &adlDesc, byte volume);
 GameType getGameType(const AdlGameDescription &desc);
 GameVersion getGameVersion(const AdlGameDescription &desc);
 Common::Language getLanguage(const AdlGameDescription &desc);
@@ -267,7 +267,7 @@ protected:
 	Common::String getSaveStateName(int slot) const override;
 	int getAutosaveSlot() const override { return 15; }
 
-	Common::String getDiskImageName(byte volume) const { return Adl::getDiskImageName(*_gameDescription, volume); }
+	Common::Path getDiskImageName(byte volume) const { return Adl::getDiskImageName(*_gameDescription, volume); }
 	GameType getGameType() const { return Adl::getGameType(*_gameDescription); }
 	GameVersion getGameVersion() const { return Adl::getGameVersion(*_gameDescription); }
 	Common::Language getLanguage() const { return Adl::getLanguage(*_gameDescription); }
diff --git a/engines/adl/console.cpp b/engines/adl/console.cpp
index b475191b515..48d7a0c386d 100644
--- a/engines/adl/console.cpp
+++ b/engines/adl/console.cpp
@@ -118,22 +118,22 @@ bool Console::Cmd_ValidCommands(int argc, const char **argv) {
 	return true;
 }
 
-void Console::dumpScripts(const Common::String &prefix) {
+void Console::dumpScripts(const Common::Path &prefix) {
 	for (byte roomNr = 1; roomNr <= _engine->_state.rooms.size(); ++roomNr) {
 		_engine->loadRoom(roomNr);
 		if (_engine->_roomData.commands.size() != 0) {
-			_engine->_dumpFile->open(prefix + Common::String::format("%03d.ADL", roomNr).c_str());
+			_engine->_dumpFile->open(prefix.append(Common::String::format("%03d.ADL", roomNr)));
 			_engine->doAllCommands(_engine->_roomData.commands, IDI_ANY, IDI_ANY);
 			_engine->_dumpFile->close();
 		}
 	}
 	_engine->loadRoom(_engine->_state.room);
 
-	_engine->_dumpFile->open(prefix + "GLOBAL.ADL");
+	_engine->_dumpFile->open(prefix.append("GLOBAL.ADL"));
 	_engine->doAllCommands(_engine->_globalCommands, IDI_ANY, IDI_ANY);
 	_engine->_dumpFile->close();
 
-	_engine->_dumpFile->open(prefix + "RESPONSE.ADL");
+	_engine->_dumpFile->open(prefix.append("RESPONSE.ADL"));
 	_engine->doAllCommands(_engine->_roomCommands, IDI_ANY, IDI_ANY);
 	_engine->_dumpFile->close();
 }
@@ -159,7 +159,7 @@ bool Console::Cmd_DumpScripts(int argc, const char **argv) {
 
 		for (byte regionNr = 1; regionNr <= _engine->_state.regions.size(); ++regionNr) {
 			_engine->switchRegion(regionNr);
-			dumpScripts(Common::String::format("%03d-", regionNr));
+			dumpScripts(Common::Path(Common::String::format("%03d-", regionNr)));
 		}
 
 		_engine->switchRegion(oldRegion);
diff --git a/engines/adl/console.h b/engines/adl/console.h
index d50e2198f41..0f0f8a19b30 100644
--- a/engines/adl/console.h
+++ b/engines/adl/console.h
@@ -60,7 +60,7 @@ private:
 
 	void printItem(const Item &item);
 	void printWordMap(const Common::HashMap<Common::String, uint> &wordMap);
-	void dumpScripts(const Common::String &prefix = Common::String());
+	void dumpScripts(const Common::Path &prefix = Common::Path());
 	void prepareGame();
 
 	AdlEngine *_engine;
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index fab2d7964dd..dd409bfd4cc 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -465,10 +465,10 @@ public:
 
 	ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra, uint32 skipADFlags, bool skipIncomplete) override;
 
-	bool addFileProps(const FileMap &allFiles, Common::String fname, FilePropertiesMap &filePropsMap) const;
+	bool addFileProps(const FileMap &allFiles, const Common::Path &fname, FilePropertiesMap &filePropsMap) const;
 };
 
-bool AdlMetaEngineDetection::addFileProps(const FileMap &allFiles, Common::String fname, FilePropertiesMap &filePropsMap) const {
+bool AdlMetaEngineDetection::addFileProps(const FileMap &allFiles, const Common::Path &fname, FilePropertiesMap &filePropsMap) const {
 	if (filePropsMap.contains(fname))
 		return true;
 
@@ -479,7 +479,7 @@ bool AdlMetaEngineDetection::addFileProps(const FileMap &allFiles, Common::Strin
 	fileProps.size = computeMD5(allFiles[fname], fileProps.md5, 16384);
 
 	if (fileProps.size != -1) {
-		debugC(3, kDebugGlobalDetection, "> '%s': '%s'", fname.c_str(), fileProps.md5.c_str());
+		debugC(3, kDebugGlobalDetection, "> '%s': '%s'", fname.toString().c_str(), fileProps.md5.c_str());
 		filePropsMap[fname] = fileProps;
 	}
 
@@ -494,7 +494,7 @@ ADDetectedGames AdlMetaEngineDetection::detectGame(const Common::FSNode &parent,
 	if (!matched.empty())
 		return matched;
 
-	debugC(3, kDebugGlobalDetection, "Starting disk image detection in dir '%s'", parent.getPath().c_str());
+	debugC(3, kDebugGlobalDetection, "Starting disk image detection in dir '%s'", parent.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	FilePropertiesMap filesProps;
 
@@ -517,17 +517,17 @@ ADDetectedGames AdlMetaEngineDetection::detectGame(const Common::FSNode &parent,
 
 		for (uint f = 0; game.desc->filesDescriptions[f].fileName; ++f) {
 			const ADGameFileDescription &fDesc = game.desc->filesDescriptions[f];
-			Common::String fileName;
+			Common::Path fileName;
 			bool foundDiskImage = false;
 
 			for (uint e = 0; e < ARRAYSIZE(diskImageExts); ++e) {
 				if (diskImageExts[e].platform == game.desc->platform) {
-					Common::String testFileName(fDesc.fileName);
-					testFileName += diskImageExts[e].extension;
+					Common::Path testFileName(fDesc.fileName, Common::Path::kNoSeparator);
+					testFileName.appendInPlace(diskImageExts[e].extension);
 
 					if (addFileProps(allFiles, testFileName, filesProps)) {
 						if (foundDiskImage) {
-							warning("Ignoring '%s' (already found '%s')", testFileName.c_str(), fileName.c_str());
+							warning("Ignoring '%s' (already found '%s')", testFileName.toString().c_str(), fileName.toString().c_str());
 							filesProps.erase(testFileName);
 						} else {
 							foundDiskImage = true;
@@ -559,7 +559,7 @@ ADDetectedGames AdlMetaEngineDetection::detectGame(const Common::FSNode &parent,
 				continue;
 			}
 
-			debugC(3, kDebugGlobalDetection, "Matched file: %s", fileName.c_str());
+			debugC(3, kDebugGlobalDetection, "Matched file: %s", fileName.toString().c_str());
 		}
 
 		// This assumes that the detection table groups together games that have the same gameId and platform
diff --git a/engines/adl/disk.cpp b/engines/adl/disk.cpp
index 93788404b98..6c830113526 100644
--- a/engines/adl/disk.cpp
+++ b/engines/adl/disk.cpp
@@ -468,18 +468,18 @@ static Common::SeekableReadStream *readImage_WOZ(Common::File &f, bool dos33, ui
 	return new Common::MemoryReadStream(diskImage, imageSize, DisposeAfterUse::YES);
 }
 
-bool DiskImage::open(const Common::String &filename) {
+bool DiskImage::open(const Common::Path &filename) {
 	Common::File *f = new Common::File;
 
-	debug(1, "Opening '%s'", filename.c_str());
+	debug(1, "Opening '%s'", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (!f->open(filename)) {
-		warning("Failed to open '%s'", filename.c_str());
+		warning("Failed to open '%s'", filename.toString(Common::Path::kNativeSeparator).c_str());
 		delete f;
 		return false;
 	}
 
-	Common::String lcName(filename);
+	Common::String lcName(filename.baseName());
 	lcName.toLowercase();
 
 	if (lcName.hasSuffix(".dsk")) {
@@ -542,7 +542,7 @@ bool DiskImage::open(const Common::String &filename) {
 		return false;
 
 	if (_stream->size() != expectedSize)
-		error("Unrecognized disk image '%s' of size %d bytes (expected %d bytes)", filename.c_str(), (int)_stream->size(), expectedSize);
+		error("Unrecognized disk image '%s' of size %d bytes (expected %d bytes)", filename.toString(Common::Path::kNativeSeparator).c_str(), (int)_stream->size(), expectedSize);
 
 	return true;
 }
@@ -627,15 +627,15 @@ int32 computeMD5(const Common::FSNode &node, Common::String &md5, uint32 md5Byte
 	}
 }
 
-const DataBlockPtr Files_Plain::getDataBlock(const Common::String &filename, uint offset) const {
+const DataBlockPtr Files_Plain::getDataBlock(const Common::Path &filename, uint offset) const {
 	return Common::SharedPtr<Files::DataBlock>(new Files::DataBlock(this, filename, offset));
 }
 
-Common::SeekableReadStream *Files_Plain::createReadStream(const Common::String &filename, uint offset) const {
+Common::SeekableReadStream *Files_Plain::createReadStream(const Common::Path &filename, uint offset) const {
 	Common::File *f(new Common::File());
 
 	if (!f->open(filename))
-		error("Failed to open '%s'", filename.c_str());
+		error("Failed to open '%s'", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (offset == 0)
 		return f;
@@ -740,7 +740,7 @@ void Files_AppleDOS::readVTOC() {
 	}
 }
 
-const DataBlockPtr Files_AppleDOS::getDataBlock(const Common::String &filename, uint offset) const {
+const DataBlockPtr Files_AppleDOS::getDataBlock(const Common::Path &filename, uint offset) const {
 	return Common::SharedPtr<Files::DataBlock>(new Files::DataBlock(this, filename, offset));
 }
 
@@ -802,9 +802,9 @@ Common::SeekableReadStream *Files_AppleDOS::createReadStreamBinary(const TOCEntr
 	return new Common::MemoryReadStream(buf, size, DisposeAfterUse::YES);
 }
 
-Common::SeekableReadStream *Files_AppleDOS::createReadStream(const Common::String &filename, uint offset) const {
+Common::SeekableReadStream *Files_AppleDOS::createReadStream(const Common::Path &filename, uint offset) const {
 	if (!_toc.contains(filename))
-		error("Failed to locate '%s'", filename.c_str());
+		error("Failed to locate '%s'", filename.toString().c_str());
 
 	const TOCEntry &entry = _toc[filename];
 
@@ -825,7 +825,7 @@ Common::SeekableReadStream *Files_AppleDOS::createReadStream(const Common::Strin
 	return new Common::SeekableSubReadStream(stream, offset, stream->size(), DisposeAfterUse::YES);
 }
 
-bool Files_AppleDOS::open(const Common::String &filename) {
+bool Files_AppleDOS::open(const Common::Path &filename) {
 	_disk = new DiskImage();
 	if (!_disk->open(filename))
 		return false;
diff --git a/engines/adl/disk.h b/engines/adl/disk.h
index 350b4a370bc..a3ddc64f4f4 100644
--- a/engines/adl/disk.h
+++ b/engines/adl/disk.h
@@ -50,14 +50,14 @@ class Files {
 public:
 	virtual ~Files() { }
 
-	virtual const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const = 0;
-	virtual Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const = 0;
-	virtual bool exists(const Common::String &filename) const = 0;
+	virtual const DataBlockPtr getDataBlock(const Common::Path &filename, uint offset = 0) const = 0;
+	virtual Common::SeekableReadStream *createReadStream(const Common::Path &filename, uint offset = 0) const = 0;
+	virtual bool exists(const Common::Path &filename) const = 0;
 
 protected:
 	class DataBlock : public Adl::DataBlock {
 	public:
-		DataBlock(const Files *files, const Common::String &filename, uint offset) :
+		DataBlock(const Files *files, const Common::Path &filename, uint offset) :
 				_files(files),
 				_filename(filename),
 				_offset(offset) { }
@@ -67,7 +67,7 @@ protected:
 		}
 
 	private:
-		const Common::String _filename;
+		const Common::Path _filename;
 		uint _offset;
 		const Files *_files;
 	};
@@ -87,7 +87,7 @@ public:
 		delete _stream;
 	}
 
-	bool open(const Common::String &filename);
+	bool open(const Common::Path &filename);
 	const DataBlockPtr getDataBlock(uint track, uint sector, uint offset = 0, uint size = 0) const;
 	Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0, uint sectorsUsed = 0) const;
 	void setSectorLimit(uint sectorLimit) { _sectorLimit = sectorLimit; } // Maximum number of sectors to read per track before stepping
@@ -124,9 +124,9 @@ protected:
 // Data in plain files
 class Files_Plain : public Files {
 public:
-	const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const override;
-	Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const override;
-	bool exists(const Common::String &filename) const override { return Common::File::exists(filename); }
+	const DataBlockPtr getDataBlock(const Common::Path &filename, uint offset = 0) const override;
+	Common::SeekableReadStream *createReadStream(const Common::Path &filename, uint offset = 0) const override;
+	bool exists(const Common::Path &filename) const override { return Common::File::exists(filename); }
 };
 
 // Data in files contained in Apple DOS 3.3 disk image
@@ -135,10 +135,10 @@ public:
 	Files_AppleDOS();
 	~Files_AppleDOS() override;
 
-	bool open(const Common::String &filename);
-	const DataBlockPtr getDataBlock(const Common::String &filename, uint offset = 0) const override;
-	Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const override;
-	bool exists(const Common::String &filename) const override { return _toc.contains(filename); }
+	bool open(const Common::Path &filename);
+	const DataBlockPtr getDataBlock(const Common::Path &filename, uint offset = 0) const override;
+	Common::SeekableReadStream *createReadStream(const Common::Path &filename, uint offset = 0) const override;
+	bool exists(const Common::Path &filename) const override { return _toc.contains(filename); }
 
 private:
 	enum FileType {
@@ -169,7 +169,7 @@ private:
 	Common::SeekableReadStream *createReadStreamBinary(const TOCEntry &entry) const;
 
 	DiskImage *_disk;
-	Common::HashMap<Common::String, TOCEntry> _toc;
+	Common::HashMap<Common::Path, TOCEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _toc;
 };
 
 // On the Apple II, sector headers contain a disk volume number. This number
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 6a0fa6d3cd5..d3b95b9a6d4 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -273,7 +273,7 @@ void HiRes1Engine::init() {
 	} else {
 		Files_AppleDOS *files = new Files_AppleDOS();
 		if (!files->open(getDiskImageName(0)))
-			error("Failed to open '%s'", getDiskImageName(0).c_str());
+			error("Failed to open '%s'", getDiskImageName(0).toString(Common::Path::kNativeSeparator).c_str());
 		_files = files;
 	}
 
@@ -330,7 +330,7 @@ void HiRes1Engine::init() {
 		byte block = stream->readByte();
 		Common::String name = Common::String::format("BLOCK%i", block);
 		uint16 offset = stream->readUint16LE();
-		_pictures[i] = _files->getDataBlock(name, offset);
+		_pictures[i] = _files->getDataBlock(Common::Path(name), offset);
 	}
 
 	// Load commands from executable
diff --git a/engines/adl/hires2.cpp b/engines/adl/hires2.cpp
index 9b11f6db616..e87ff449f9f 100644
--- a/engines/adl/hires2.cpp
+++ b/engines/adl/hires2.cpp
@@ -62,7 +62,7 @@ void HiResBaseEngine::init() {
 
 	_disk = new DiskImage();
 	if (!_disk->open(getDiskImageName(0)))
-		error("Failed to open disk image '%s'", getDiskImageName(0).c_str());
+		error("Failed to open disk image '%s'", getDiskImageName(0).toString(Common::Path::kNativeSeparator).c_str());
 
 	_disk->setSectorLimit(13);
 
diff --git a/engines/adl/hires4.cpp b/engines/adl/hires4.cpp
index 49a2a2dcf00..a6147f7082e 100644
--- a/engines/adl/hires4.cpp
+++ b/engines/adl/hires4.cpp
@@ -83,7 +83,7 @@ void HiRes4BaseEngine::init() {
 
 	_boot = new DiskImage();
 	if (!_boot->open(getDiskImageName(0)))
-		error("Failed to open disk image '%s'", getDiskImageName(0).c_str());
+		error("Failed to open disk image '%s'", getDiskImageName(0).toString(Common::Path::kNativeSeparator).c_str());
 
 	insertDisk(1);
 }
diff --git a/engines/adl/metaengine.cpp b/engines/adl/metaengine.cpp
index 3469d772f67..509149577dd 100644
--- a/engines/adl/metaengine.cpp
+++ b/engines/adl/metaengine.cpp
@@ -101,7 +101,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
 	AD_EXTRA_GUI_OPTIONS_TERMINATOR
 };
 
-Common::String getDiskImageName(const AdlGameDescription &adlDesc, byte volume) {
+Common::Path getDiskImageName(const AdlGameDescription &adlDesc, byte volume) {
 	const ADGameDescription &desc = adlDesc.desc;
 	for (uint i = 0; desc.filesDescriptions[i].fileName; ++i) {
 		const ADGameFileDescription &fDesc = desc.filesDescriptions[i];
@@ -109,8 +109,8 @@ Common::String getDiskImageName(const AdlGameDescription &adlDesc, byte volume)
 		if (fDesc.fileType == volume) {
 			for (uint e = 0; e < ARRAYSIZE(diskImageExts); ++e) {
 				if (diskImageExts[e].platform == desc.platform) {
-					Common::String testFileName(fDesc.fileName);
-					testFileName += diskImageExts[e].extension;
+					Common::Path testFileName(fDesc.fileName);
+					testFileName.appendInPlace(diskImageExts[e].extension);
 					if (Common::File::exists(testFileName))
 						return testFileName;
 				}


Commit: 3457d49fd564cf007af141ab8dde17a3eac16599
    https://github.com/scummvm/scummvm/commit/3457d49fd564cf007af141ab8dde17a3eac16599
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
AGI: Migrate engine to Path

Changed paths:
    engines/agi/agi.h
    engines/agi/font.cpp
    engines/agi/font.h
    engines/agi/loader_v2.cpp
    engines/agi/loader_v3.cpp
    engines/agi/op_cmd.cpp
    engines/agi/preagi/winnie.cpp
    engines/agi/sound_2gs.cpp
    engines/agi/sound_2gs.h
    engines/agi/wagparser.cpp


diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 33f2f90cb42..ac78d7c37ee 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -617,8 +617,8 @@ public:
 class AgiLoader_v1 : public AgiLoader {
 private:
 	AgiEngine *_vm;
-	Common::String _filenameDisk0;
-	Common::String _filenameDisk1;
+	Common::Path _filenameDisk0;
+	Common::Path _filenameDisk1;
 
 	int loadDir_DDP(AgiDir *agid, int offset, int max);
 	int loadDir_BC(AgiDir *agid, int offset, int max);
diff --git a/engines/agi/font.cpp b/engines/agi/font.cpp
index 6a7f8fe8426..f3dcbff8f6e 100644
--- a/engines/agi/font.cpp
+++ b/engines/agi/font.cpp
@@ -167,7 +167,7 @@ void GfxFont::overwriteExtendedWithRussianSet() {
 //  Atari ST - "agi-font-atarist.bin" -> should be the Atari ST 8x8 system font
 //  Amiga    - "agi-font-amiga.bin"   -> should be the Amiga 8x8 Topaz font
 //  DOS      - "agi-font-dos.bin"
-void GfxFont::loadFontScummVMFile(Common::String fontFilename) {
+void GfxFont::loadFontScummVMFile(const Common::Path &fontFilename) {
 	Common::File fontFile;
 	int32 fontFileSize = 0;
 
@@ -181,7 +181,7 @@ void GfxFont::loadFontScummVMFile(Common::String fontFilename) {
 	if (fontFileSize != (256 * 8)) {
 		// unexpected file size
 		fontFile.close();
-		warning("Fontfile '%s': unexpected file size", fontFilename.c_str());
+		warning("Fontfile '%s': unexpected file size", fontFilename.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
@@ -460,7 +460,7 @@ void GfxFont::loadFontAppleIIgs() {
 
 // Loads Atari ST font file
 // It's found inside Atari ST ROMs. Just search for "8x8 system font". Font starts 4 bytes before that.
-void GfxFont::loadFontAtariST(Common::String fontFilename) {
+void GfxFont::loadFontAtariST(const Common::Path &fontFilename) {
 	Common::File fontFile;
 	uint16 header_FirstChar = 0;
 	uint16 header_LastChar = 0;
diff --git a/engines/agi/font.h b/engines/agi/font.h
index a55c79c4d50..d9d6b54f132 100644
--- a/engines/agi/font.h
+++ b/engines/agi/font.h
@@ -41,11 +41,11 @@ private:
 	void overwriteSaveRestoreDialogCharacter();
 	void overwriteExtendedWithRussianSet();
 
-	void loadFontScummVMFile(Common::String fontFilename);
+	void loadFontScummVMFile(const Common::Path &fontFilename);
 	void loadFontMickey();
 	void loadFontAmigaPseudoTopaz();
 	void loadFontAppleIIgs();
-	void loadFontAtariST(Common::String fontFilename);
+	void loadFontAtariST(const Common::Path &fontFilename);
 	void loadFontHercules();
 
 	const uint8 *_fontData; // pointer to the currently used font
diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp
index 5121711febe..6af7a657958 100644
--- a/engines/agi/loader_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -145,10 +145,9 @@ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) {
 	char x[6];
 	Common::File fp;
 	unsigned int sig;
-	Common::String path;
+	Common::Path path(Common::String::format("vol.%i", agid->volume));
 
-	path = Common::String::format("vol.%i", agid->volume);
-	debugC(3, kDebugLevelResources, "Vol res: path = %s", path.c_str());
+	debugC(3, kDebugLevelResources, "Vol res: path = %s", path.toString().c_str());
 
 	if (agid->offset != _EMPTY && fp.open(path)) {
 		debugC(3, kDebugLevelResources, "loading resource at offset %d", agid->offset);
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index 4684864d530..e5409a8c076 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -34,10 +34,10 @@ int AgiLoader_v3::detectGame() {
 	bool found = false;
 
 	Common::FSList fslist;
-	Common::FSNode dir(ConfMan.get("path"));
+	Common::FSNode dir(ConfMan.getPath("path"));
 
 	if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) {
-		warning("AgiEngine: invalid game path '%s'", dir.getPath().c_str());
+		warning("AgiEngine: invalid game path '%s'", dir.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		return errInvalidAGIFile;
 	}
 
@@ -106,17 +106,17 @@ int AgiLoader_v3::init() {
 	int i;
 	uint16 xd[4];
 	Common::File fp;
-	Common::String path;
+	Common::Path path;
 
 	if (_vm->getPlatform() == Common::kPlatformAmiga) {
-		path = Common::String("dirs");
+		path = Common::Path("dirs");
 		_vm->_game.name[0] = 0; // Empty prefix
 	} else {
-		path = Common::String(_vm->_game.name) + DIR_;
+		path = Common::Path(Common::String(_vm->_game.name) + DIR_);
 	}
 
 	if (!fp.open(path)) {
-		warning("Failed to open '%s'", path.c_str());
+		warning("Failed to open '%s'", path.toString().c_str());
 		return errBadFileOpen;
 	}
 	// build offset table for v3 directory format
@@ -200,7 +200,7 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) {
 	char x[8];
 	uint8 *data = nullptr, *compBuffer;
 	Common::File fp;
-	Common::String path;
+	Common::Path path;
 
 	debugC(3, kDebugLevelResources, "(%p)", (void *)agid);
 	if (_vm->getPlatform() == Common::kPlatformMacintosh) {
@@ -214,7 +214,7 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) {
 		fp.read(&x, 7);
 
 		if (READ_BE_UINT16((uint8 *) x) != 0x1234) {
-			debugC(3, kDebugLevelResources, "path = %s", path.c_str());
+			debugC(3, kDebugLevelResources, "path = %s", path.toString().c_str());
 			debugC(3, kDebugLevelResources, "offset = %d", agid->offset);
 			debugC(3, kDebugLevelResources, "x = %x %x", x[0], x[1]);
 			error("ACK! BAD RESOURCE");
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 9c383f70546..6388dffa62f 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -41,17 +41,17 @@ namespace {
 // based on the current game and system time.
 //
 // For example: dumps/agi.kq.20221013214511.log
-Common::String generateLogFileName(Agi::AgiGame *state, Agi::AgiEngine *vm) {
+Common::Path generateLogFileName(Agi::AgiGame *state, Agi::AgiEngine *vm) {
 	TimeDate date;
 	vm->_system->getTimeAndDate(date, true);
-	return Common::String::format("dumps/agi.%s.%d%02d%02d%02d%02d%02d.log",
+	return Common::Path(Common::String::format("dumps/agi.%s.%d%02d%02d%02d%02d%02d.log",
 								  vm->getTargetName().c_str(),
 								  date.tm_year + 1900,
 								  date.tm_mon + 1,
 								  date.tm_mday,
 								  date.tm_hour,
 								  date.tm_min,
-								  date.tm_sec);
+								  date.tm_sec), '/');
 }
 } // namespace
 
@@ -833,7 +833,7 @@ void cmdLog(AgiGame *state, AgiEngine *vm, uint8 *parameter) {
 		Common::DumpFile *&dumpFile = vm->_logFile;
 		if (!dumpFile) {
 			dumpFile = new Common::DumpFile();
-			Common::String logFileName = generateLogFileName(state, vm);
+			Common::Path logFileName = generateLogFileName(state, vm);
 			dumpFile->open(logFileName);
 		}
 		// The logs will only be written if the "dumps" folder has been created by
diff --git a/engines/agi/preagi/winnie.cpp b/engines/agi/preagi/winnie.cpp
index 7ce80222cf0..a970eed7359 100644
--- a/engines/agi/preagi/winnie.cpp
+++ b/engines/agi/preagi/winnie.cpp
@@ -87,20 +87,20 @@ void WinnieEngine::parseObjHeader(WTP_OBJ_HDR *objHdr, byte *buffer, int len) {
 }
 
 uint32 WinnieEngine::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
-	Common::String fileName;
+	Common::Path fileName;
 
 	if (getPlatform() == Common::kPlatformDOS)
-		fileName = Common::String::format(IDS_WTP_ROOM_DOS, iRoom);
+		fileName = Common::Path(Common::String::format(IDS_WTP_ROOM_DOS, iRoom));
 	else if (getPlatform() == Common::kPlatformAmiga)
-		fileName = Common::String::format(IDS_WTP_ROOM_AMIGA, iRoom);
+		fileName = Common::Path(Common::String::format(IDS_WTP_ROOM_AMIGA, iRoom));
 	else if (getPlatform() == Common::kPlatformC64)
-		fileName = Common::String::format(IDS_WTP_ROOM_C64, iRoom);
+		fileName = Common::Path(Common::String::format(IDS_WTP_ROOM_C64, iRoom));
 	else if (getPlatform() == Common::kPlatformApple2)
-		fileName = Common::String::format(IDS_WTP_ROOM_APPLE, iRoom);
+		fileName = Common::Path(Common::String::format(IDS_WTP_ROOM_APPLE, iRoom));
 
 	Common::File file;
 	if (!file.open(fileName)) {
-		warning("Could not open file \'%s\'", fileName.c_str());
+		warning("Could not open file \'%s\'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return 0;
 	}
 
@@ -120,20 +120,20 @@ uint32 WinnieEngine::readRoom(int iRoom, uint8 *buffer, WTP_ROOM_HDR &roomHdr) {
 }
 
 uint32 WinnieEngine::readObj(int iObj, uint8 *buffer) {
-	Common::String fileName;
+	Common::Path fileName;
 
 	if (getPlatform() == Common::kPlatformDOS)
-		fileName = Common::String::format(IDS_WTP_OBJ_DOS, iObj);
+		fileName = Common::Path(Common::String::format(IDS_WTP_OBJ_DOS, iObj));
 	else if (getPlatform() == Common::kPlatformAmiga)
-		fileName = Common::String::format(IDS_WTP_OBJ_AMIGA, iObj);
+		fileName = Common::Path(Common::String::format(IDS_WTP_OBJ_AMIGA, iObj));
 	else if (getPlatform() == Common::kPlatformC64)
-		fileName = Common::String::format(IDS_WTP_OBJ_C64, iObj);
+		fileName = Common::Path(Common::String::format(IDS_WTP_OBJ_C64, iObj));
 	else if (getPlatform() == Common::kPlatformApple2)
-		fileName = Common::String::format(IDS_WTP_OBJ_APPLE, iObj);
+		fileName = Common::Path(Common::String::format(IDS_WTP_OBJ_APPLE, iObj));
 
 	Common::File file;
 	if (!file.open(fileName)) {
-		warning("Could not open file \'%s\'", fileName.c_str());
+		warning("Could not open file \'%s\'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return 0;
 	}
 
@@ -1062,17 +1062,17 @@ void WinnieEngine::gameLoop() {
 }
 
 void WinnieEngine::drawPic(const char *szName) {
-	Common::String fileName = szName;
+	Common::Path fileName(szName);
 
 	if (getPlatform() != Common::kPlatformAmiga)
-		fileName += ".pic";
+		fileName.appendInPlace(".pic");
 	else
-		fileName = "misc/" + fileName;
+		fileName = Common::Path("misc/").append(fileName);
 
 	Common::File file;
 
 	if (!file.open(fileName)) {
-		warning("Could not open file \'%s\'", fileName.c_str());
+		warning("Could not open file \'%s\'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
@@ -1136,7 +1136,7 @@ bool WinnieEngine::playSound(ENUM_WTP_SOUND iSound) {
 		return false;
 	}
 
-	Common::String fileName = Common::String::format(IDS_WTP_SND_DOS, iSound);
+	Common::Path fileName(Common::String::format(IDS_WTP_SND_DOS, iSound));
 
 	Common::File file;
 	if (!file.open(fileName))
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
index 1c2f877c68f..838449e3491 100644
--- a/engines/agi/sound_2gs.cpp
+++ b/engines/agi/sound_2gs.cpp
@@ -644,8 +644,8 @@ bool SoundGen2GS::loadInstruments() {
 		return false;
 	}
 
-	Common::String exeName  = exeNames.front()->getName();
-	Common::String waveName = waveNames.front()->getName();
+	Common::Path exeName  = exeNames.front()->getPathInArchive();
+	Common::Path waveName = waveNames.front()->getPathInArchive();
 
 	// Set the MIDI program change to instrument number mapping and
 	// load the instrument headers and their sample data.
@@ -742,14 +742,14 @@ const IIgsExeInfo *SoundGen2GS::getIIgsExeInfo(enum AgiGameID gameid) const {
 	return nullptr;
 }
 
-bool SoundGen2GS::loadInstrumentHeaders(Common::String &exePath, const IIgsExeInfo &exeInfo) {
+bool SoundGen2GS::loadInstrumentHeaders(const Common::Path &exePath, const IIgsExeInfo &exeInfo) {
 	Common::File file;
 
 	// Open the executable file and check that it has correct size
 	file.open(exePath);
 	if (file.size() != (int32)exeInfo.exeSize) {
 		debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)",
-		       exePath.c_str(), (int)file.size(), exeInfo.exeSize);
+		       exePath.toString(Common::Path::kNativeSeparator).c_str(), (int)file.size(), exeInfo.exeSize);
 	}
 
 	// Read the whole executable file into memory
@@ -761,7 +761,7 @@ bool SoundGen2GS::loadInstrumentHeaders(Common::String &exePath, const IIgsExeIn
 
 	// Check that we got enough data to be able to parse the instruments
 	if (!data || data->size() < (int32)(exeInfo.instSetStart + exeInfo.instSet->byteCount)) {
-		warning("Error loading instruments from Apple IIGS executable (%s)", exePath.c_str());
+		warning("Error loading instruments from Apple IIGS executable (%s)", exePath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -770,7 +770,7 @@ bool SoundGen2GS::loadInstrumentHeaders(Common::String &exePath, const IIgsExeIn
 	uint16 instSetByteCount = data->readUint16LE();
 	if (instSetByteCount != exeInfo.instSet->byteCount) {
 		debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)",
-		       instSetByteCount, exeInfo.instSet->byteCount, exePath.c_str());
+		       instSetByteCount, exeInfo.instSet->byteCount, exePath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	// Check instrument set's md5sum
@@ -778,7 +778,7 @@ bool SoundGen2GS::loadInstrumentHeaders(Common::String &exePath, const IIgsExeIn
 	Common::String md5str = Common::computeStreamMD5AsString(*data, exeInfo.instSet->byteCount);
 	if (md5str != exeInfo.instSet->md5) {
 		warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
-		        md5str.c_str(), exePath.c_str());
+		        md5str.c_str(), exePath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	// Read in the instrument set one instrument at a time
@@ -791,7 +791,7 @@ bool SoundGen2GS::loadInstrumentHeaders(Common::String &exePath, const IIgsExeIn
 	for (uint i = 0; i < exeInfo.instSet->instCount; i++) {
 		if (!instrument.read(*data)) {
 			warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments",
-			        i + 1, exeInfo.instSet->instCount, exePath.c_str());
+			        i + 1, exeInfo.instSet->instCount, exePath.toString(Common::Path::kNativeSeparator).c_str());
 			break;
 		}
 		instrument.finalize(_wavetable, SIERRASTANDARD_SIZE);
@@ -802,7 +802,7 @@ bool SoundGen2GS::loadInstrumentHeaders(Common::String &exePath, const IIgsExeIn
 	return (_instruments.size() == exeInfo.instSet->instCount);
 }
 
-bool SoundGen2GS::loadWaveFile(Common::String &wavePath, const IIgsExeInfo &exeInfo) {
+bool SoundGen2GS::loadWaveFile(const Common::Path &wavePath, const IIgsExeInfo &exeInfo) {
 	Common::File file;
 
 	// Open the wave file and read it into memory
@@ -815,7 +815,7 @@ bool SoundGen2GS::loadWaveFile(Common::String &wavePath, const IIgsExeInfo &exeI
 
 	// Check that we got the whole wave file
 	if (!uint8Wave || (uint8Wave->size() != SIERRASTANDARD_SIZE)) {
-		warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.c_str());
+		warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h
index b6413b05fc9..c52e14e4418 100644
--- a/engines/agi/sound_2gs.h
+++ b/engines/agi/sound_2gs.h
@@ -233,8 +233,8 @@ public:
 private:
 	// Loader methods
 	bool loadInstruments();
-	bool loadInstrumentHeaders(Common::String &exePath, const IIgsExeInfo &exeInfo);
-	bool loadWaveFile(Common::String &wavePath, const IIgsExeInfo &exeInfo);
+	bool loadInstrumentHeaders(const Common::Path &exePath, const IIgsExeInfo &exeInfo);
+	bool loadWaveFile(const Common::Path &wavePath, const IIgsExeInfo &exeInfo);
 
 	const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const;
 	void setProgramChangeMapping(const IIgsMidiProgramMapping *mapping);
diff --git a/engines/agi/wagparser.cpp b/engines/agi/wagparser.cpp
index 2872efb3827..54d5536fafe 100644
--- a/engines/agi/wagparser.cpp
+++ b/engines/agi/wagparser.cpp
@@ -207,7 +207,7 @@ bool WagFileParser::parse(const Common::FSNode &node) {
 			_parsedOk = endOfProperties(*stream) && property.readOk();
 
 			if (!_parsedOk) // Error parsing stream
-				warning("Error parsing WAG file (%s). WAG file ignored", node.getPath().c_str());
+				warning("Error parsing WAG file (%s). WAG file ignored", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		} else {
 			// Invalid WinAGI version string or it couldn't be read
 			// Let's try to read WAG file as newer INI format
@@ -220,11 +220,11 @@ bool WagFileParser::parse(const Common::FSNode &node) {
 				addPropFromIni(iniWagFile, "General", "GameVersion", WagProperty::PC_GAMEVERSION);
 				addPropFromIni(iniWagFile, "General", "LastEdit", WagProperty::PC_GAMELAST);
 			} else
-				warning("Invalid WAG file (%s) version or error reading it. WAG file ignored", node.getPath().c_str());
+				warning("Invalid WAG file (%s) version or error reading it. WAG file ignored", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		}
 
 	} else // Couldn't open file
-		warning("Couldn't open WAG file (%s). WAG file ignored", node.getPath().c_str());
+		warning("Couldn't open WAG file (%s). WAG file ignored", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	delete stream;
 	return _parsedOk;


Commit: d614b5d31c990c8b63479f1872be3036d4cd28e9
    https://github.com/scummvm/scummvm/commit/d614b5d31c990c8b63479f1872be3036d4cd28e9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
AGOS: Migrate engine to Path

Changed paths:
    engines/agos/agos.cpp
    engines/agos/animation.cpp
    engines/agos/drivers/accolade/driverfile.cpp
    engines/agos/res_snd.cpp
    engines/agos/saveload.cpp
    engines/agos/sound.cpp
    engines/agos/sound.h
    engines/agos/subroutine.cpp


diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 45be407a0d5..7200935b7c3 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -566,7 +566,7 @@ AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd)
 	memcpy (_hebrewCharWidths,
 		"\x5\x5\x4\x6\x5\x3\x4\x5\x6\x3\x5\x5\x4\x6\x5\x3\x4\x6\x5\x6\x6\x6\x5\x5\x5\x6\x5\x6\x6\x6\x6\x6", 32);
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	// Add default file directories for Acorn version of
 	// Simon the Sorcerer 1
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 8625fa6d606..d0befbff2d4 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -250,14 +250,14 @@ bool MoviePlayerDXA::load() {
 		}
 	}
 
-	Common::String videoName = Common::String::format("%s.dxa", baseName);
+	Common::Path videoName(Common::String::format("%s.dxa", baseName));
 	Common::File *videoStream = new Common::File();
 	if (!videoStream->open(videoName))
-		error("Failed to load video file %s", videoName.c_str());
+		error("Failed to load video file %s", videoName.toString(Common::Path::kNativeSeparator).c_str());
 	if (!loadStream(videoStream))
-		error("Failed to load video stream from file %s", videoName.c_str());
+		error("Failed to load video stream from file %s", videoName.toString(Common::Path::kNativeSeparator).c_str());
 
-	debug(0, "Playing video %s", videoName.c_str());
+	debug(0, "Playing video %s", videoName.toString(Common::Path::kNativeSeparator).c_str());
 
 	CursorMan.showMouse(false);
 	return true;
@@ -425,15 +425,15 @@ MoviePlayerSMK::MoviePlayerSMK(AGOSEngine_Feeble *vm, const char *name)
 }
 
 bool MoviePlayerSMK::load() {
-	Common::String videoName = Common::String::format("%s.smk", baseName);
+	Common::Path videoName(Common::String::format("%s.smk", baseName));
 
 	Common::File *videoStream = new Common::File();
 	if (!videoStream->open(videoName))
-		error("Failed to load video file %s", videoName.c_str());
+		error("Failed to load video file %s", videoName.toString(Common::Path::kNativeSeparator).c_str());
 	if (!loadStream(videoStream))
-		error("Failed to load video stream from file %s", videoName.c_str());
+		error("Failed to load video stream from file %s", videoName.toString(Common::Path::kNativeSeparator).c_str());
 
-	debug(0, "Playing video %s", videoName.c_str());
+	debug(0, "Playing video %s", videoName.toString(Common::Path::kNativeSeparator).c_str());
 
 	CursorMan.showMouse(false);
 
diff --git a/engines/agos/drivers/accolade/driverfile.cpp b/engines/agos/drivers/accolade/driverfile.cpp
index 12c65debb84..75f531f67c2 100644
--- a/engines/agos/drivers/accolade/driverfile.cpp
+++ b/engines/agos/drivers/accolade/driverfile.cpp
@@ -33,7 +33,7 @@ void MidiDriver_Accolade_readDriver(Common::String filename, MusicType requested
 
 	isMusicDrvFile = false;
 
-	if (!driverStream->open(filename)) {
+	if (!driverStream->open(Common::Path(filename))) {
 		error("%s: unable to open file", filename.c_str());
 	}
 
diff --git a/engines/agos/res_snd.cpp b/engines/agos/res_snd.cpp
index 7ef511b29eb..a7e91b02c34 100644
--- a/engines/agos/res_snd.cpp
+++ b/engines/agos/res_snd.cpp
@@ -376,7 +376,7 @@ void AGOSEngine::playMusic(uint16 music, uint16 track) {
 				error("playMusic: Can't load music from 'MOD%d.PAK'", music);
 		} else {
 			Common::File *file = new Common::File();
-			if (!file->open(Common::String::format("MOD%d.MUS", music)))
+			if (!file->open(Common::Path(Common::String::format("MOD%d.MUS", music))))
 				error("playMusic: Can't load music from 'MOD%d.MUS'", music);
 			str = file;
 		}
@@ -655,7 +655,7 @@ void AGOSEngine::loadMidiSfx() {
 	Common::File fxb_file;
 
 	Common::String filename = getGameType() == GType_ELVIRA2 ? "MYLIB.FXB" : "WAX.FXB";
-	fxb_file.open(filename);
+	fxb_file.open(Common::Path(filename));
 	if (!fxb_file.isOpen())
 		error("loadMidiSfx: Can't open sound effect bank '%s'", filename.c_str());
 
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index b89d78896aa..d84364de10e 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -1053,7 +1053,7 @@ bool AGOSEngine::loadGame(const Common::String &filename, bool restartMode) {
 			f = createPak98FileStream("START.PAK");
 		} else {
 			Common::File *file = new Common::File();
-			if (!file->open(filename)) {
+			if (!file->open(Common::Path(filename))) {
 				delete file;
 				file = nullptr;
 			}
@@ -1233,7 +1233,7 @@ bool AGOSEngine_Elvira2::loadGame(const Common::String &filename, bool restartMo
 	if (restartMode) {
 		// Load restart state
 		Common::File *file = new Common::File();
-		if (!file->open(filename)) {
+		if (!file->open(Common::Path(filename))) {
 			delete file;
 			file = nullptr;
 		}
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index eb2f60e3182..9db03cc4097 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -43,15 +43,15 @@ namespace AGOS {
 
 class BaseSound : Common::NonCopyable {
 protected:
-	const Common::String _filename;
+	const Common::Path _filename;
 	uint32 *_offsets;
 	Audio::Mixer *_mixer;
 	bool _freeOffsets;
 
 	Common::SeekableReadStream *getSoundStream(uint sound) const;
 public:
-	BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base, bool bigEndian);
-	BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 *offsets);
+	BaseSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 base, bool bigEndian);
+	BaseSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 *offsets);
 	virtual ~BaseSound();
 
 	void playSound(uint sound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0) {
@@ -61,7 +61,7 @@ public:
 	virtual Audio::RewindableAudioStream *makeAudioStream(uint sound) = 0;
 };
 
-BaseSound::BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base, bool bigEndian)
+BaseSound::BaseSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 base, bool bigEndian)
 	: _mixer(mixer), _filename(filename), _offsets(nullptr) {
 
 	uint res = 0;
@@ -69,7 +69,7 @@ BaseSound::BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32
 
 	Common::File file;
 	if (!file.open(_filename))
-		error("BaseSound: Could not open file \"%s\"", filename.c_str());
+		error("BaseSound: Could not open file \"%s\"", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	file.seek(base + sizeof(uint32), SEEK_SET);
 	if (bigEndian)
@@ -98,7 +98,7 @@ BaseSound::BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32
 	_offsets[res] = file.size();
 }
 
-BaseSound::BaseSound(Audio::Mixer *mixer, const Common::String &filename, uint32 *offsets)
+BaseSound::BaseSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 *offsets)
 	: _mixer(mixer), _filename(filename), _offsets(offsets), _freeOffsets(false) {
 }
 
@@ -113,7 +113,7 @@ Common::SeekableReadStream *BaseSound::getSoundStream(uint sound) const {
 
 	Common::File *file = new Common::File();
 	if (!file->open(_filename)) {
-		warning("BaseSound::getSoundStream: Could not open file \"%s\"", _filename.c_str());
+		warning("BaseSound::getSoundStream: Could not open file \"%s\"", _filename.toString(Common::Path::kNativeSeparator).c_str());
 		delete file;
 		return nullptr;
 	}
@@ -189,9 +189,9 @@ void BaseSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType ty
 
 class WavSound : public BaseSound {
 public:
-	WavSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0)
+	WavSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 base = 0)
 		: BaseSound(mixer, filename, base, false) {}
-	WavSound(Audio::Mixer *mixer, const Common::String &filename, uint32 *offsets) : BaseSound(mixer, filename, offsets) {}
+	WavSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 *offsets) : BaseSound(mixer, filename, offsets) {}
 	Audio::RewindableAudioStream *makeAudioStream(uint sound) override;
 };
 
@@ -208,7 +208,7 @@ Audio::RewindableAudioStream *WavSound::makeAudioStream(uint sound) {
 class VocSound : public BaseSound {
 	const byte _flags;
 public:
-	VocSound(Audio::Mixer *mixer, const Common::String &filename, bool isUnsigned, uint32 base = 0, bool bigEndian = false)
+	VocSound(Audio::Mixer *mixer, const Common::Path &filename, bool isUnsigned, uint32 base = 0, bool bigEndian = false)
 		: BaseSound(mixer, filename, base, bigEndian), _flags(isUnsigned ? Audio::FLAG_UNSIGNED : 0) {}
 	Audio::RewindableAudioStream *makeAudioStream(uint sound) override;
 };
@@ -227,7 +227,7 @@ Audio::RewindableAudioStream *VocSound::makeAudioStream(uint sound) {
 class RawSound : public BaseSound {
 	const byte _flags;
 public:
-	RawSound(Audio::Mixer *mixer, const Common::String &filename, bool isUnsigned)
+	RawSound(Audio::Mixer *mixer, const Common::Path &filename, bool isUnsigned)
 		: BaseSound(mixer, filename, 0, SOUND_BIG_ENDIAN), _flags(isUnsigned ? Audio::FLAG_UNSIGNED : 0) {}
 	Audio::RewindableAudioStream *makeAudioStream(uint sound) override;
 	void playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, bool loop, int vol = 0) override;
@@ -239,7 +239,7 @@ Audio::RewindableAudioStream *RawSound::makeAudioStream(uint sound) {
 
 	Common::File *file = new Common::File();
 	if (!file->open(_filename)) {
-		warning("RawSound::makeAudioStream: Could not open file \"%s\"", _filename.c_str());
+		warning("RawSound::makeAudioStream: Could not open file \"%s\"", _filename.toString(Common::Path::kNativeSeparator).c_str());
 		delete file;
 		return nullptr;
 	}
@@ -263,7 +263,7 @@ void RawSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType typ
 #ifdef USE_MAD
 class MP3Sound : public BaseSound {
 public:
-	MP3Sound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
+	MP3Sound(Audio::Mixer *mixer, const Common::Path &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
 	Audio::RewindableAudioStream *makeAudioStream(uint sound) override {
 		Common::SeekableReadStream *tmp = getSoundStream(sound);
 		if (!tmp)
@@ -279,7 +279,7 @@ public:
 #ifdef USE_VORBIS
 class VorbisSound : public BaseSound {
 public:
-	VorbisSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
+	VorbisSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
 	Audio::RewindableAudioStream *makeAudioStream(uint sound) override {
 		Common::SeekableReadStream *tmp = getSoundStream(sound);
 		if (!tmp)
@@ -295,7 +295,7 @@ public:
 #ifdef USE_FLAC
 class FLACSound : public BaseSound {
 public:
-	FLACSound(Audio::Mixer *mixer, const Common::String &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
+	FLACSound(Audio::Mixer *mixer, const Common::Path &filename, uint32 base = 0) : BaseSound(mixer, filename, base, false) {}
 	Audio::RewindableAudioStream *makeAudioStream(uint sound) override {
 		Common::SeekableReadStream *tmp = getSoundStream(sound);
 		if (!tmp)
@@ -308,23 +308,29 @@ public:
 ///////////////////////////////////////////////////////////////////////////////
 #pragma mark -
 
-static BaseSound *makeSound(Audio::Mixer *mixer, const Common::String &basename) {
+static BaseSound *makeSound(Audio::Mixer *mixer, const Common::Path &basename) {
+	Common::Path tmp;
 #ifdef USE_FLAC
-	if (Common::File::exists(basename + ".fla"))
-		return new FLACSound(mixer, basename + ".fla");
+	tmp = basename.append(".fla");
+	if (Common::File::exists(tmp))
+		return new FLACSound(mixer, tmp);
 #endif
 #ifdef USE_VORBIS
-	if (Common::File::exists(basename + ".ogg"))
-		return new VorbisSound(mixer, basename + ".ogg");
+	tmp = basename.append(".ogg");
+	if (Common::File::exists(tmp))
+		return new VorbisSound(mixer, tmp);
 #endif
 #ifdef USE_MAD
-	if (Common::File::exists(basename + ".mp3"))
-		return new MP3Sound(mixer, basename + ".mp3");
+	tmp = basename.append(".mp3");
+	if (Common::File::exists(tmp))
+		return new MP3Sound(mixer, tmp);
 #endif
-	if (Common::File::exists(basename + ".wav"))
-		return new WavSound(mixer, basename + ".wav");
-	if (Common::File::exists(basename + ".voc"))
-		return new VocSound(mixer, basename + ".voc", true);
+	tmp = basename.append(".wav");
+	if (Common::File::exists(tmp))
+		return new WavSound(mixer, tmp);
+	tmp = basename.append(".voc");
+	if (Common::File::exists(tmp))
+		return new VocSound(mixer, tmp, true);
 	return nullptr;
 }
 
@@ -430,14 +436,14 @@ void Sound::loadSfxFile(const GameSpecificSettings *gss) {
 }
 
 // This method is only used by Simon1 Amiga CD32 & Windows
-void Sound::readSfxFile(const Common::String &filename) {
+void Sound::readSfxFile(const Common::Path &filename) {
 	if (_hasEffectsFile)
 		return;
 
 	_mixer->stopHandle(_effectsHandle);
 
 	if (!Common::File::exists(filename)) {
-		error("readSfxFile: Can't load sfx file %s", filename.c_str());
+		error("readSfxFile: Can't load sfx file %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	const bool dataIsUnsigned = (_vm->getGameId() != GID_SIMON1CD32);
@@ -462,11 +468,11 @@ void Sound::loadSfxTable(const char *gameFilename, uint32 base) {
 }
 
 // This method is only used by Simon1 Amiga CD32
-void Sound::readVoiceFile(const Common::String &filename) {
+void Sound::readVoiceFile(const Common::Path &filename) {
 	_mixer->stopHandle(_voiceHandle);
 
 	if (!Common::File::exists(filename))
-		error("readVoiceFile: Can't load voice file %s", filename.c_str());
+		error("readVoiceFile: Can't load voice file %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	const bool dataIsUnsigned = false;
 
diff --git a/engines/agos/sound.h b/engines/agos/sound.h
index 8334384a734..8eb674e37b1 100644
--- a/engines/agos/sound.h
+++ b/engines/agos/sound.h
@@ -79,9 +79,9 @@ protected:
 	void loadSfxFile(const GameSpecificSettings *gss);
 
 public:
-	void readSfxFile(const Common::String &filename);
+	void readSfxFile(const Common::Path &filename);
 	void loadSfxTable(const char *gameFilename, uint32 base);
-	void readVoiceFile(const Common::String &filename);
+	void readVoiceFile(const Common::Path &filename);
 
 	void playVoice(uint sound);
 	void playEffects(uint sound);
diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp
index c66f8e4830e..738744d7984 100644
--- a/engines/agos/subroutine.cpp
+++ b/engines/agos/subroutine.cpp
@@ -381,7 +381,7 @@ bool AGOSEngine_Waxworks::loadTablesIntoMem(uint16 subrId) {
 					filename.setChar('X', 4);
 					filename.setChar('X', 5);
 					if (atoi(filename.c_str() + 6) != 1 && atoi(filename.c_str() + 6) != 30)
-						_sound->readSfxFile(filename);
+						_sound->readSfxFile(Common::Path(filename));
 				}
 
 				alignTableMem();


Commit: 728b2cbac7b6defc343778d6bf1720cc18ab98b5
    https://github.com/scummvm/scummvm/commit/728b2cbac7b6defc343778d6bf1720cc18ab98b5
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
AGS: Migrate engine to Path

Changed paths:
    engines/ags/ags.cpp
    engines/ags/console.cpp
    engines/ags/detection.cpp
    engines/ags/detection.h
    engines/ags/dialogs.cpp
    engines/ags/engine/ac/listbox.cpp
    engines/ags/game_scanner.cpp
    engines/ags/game_scanner.h
    engines/ags/shared/game/main_game_file.cpp
    engines/ags/shared/util/directory.cpp
    engines/ags/shared/util/stdio_compat.cpp


diff --git a/engines/ags/ags.cpp b/engines/ags/ags.cpp
index 648dfca0242..d1d4b6c7f97 100644
--- a/engines/ags/ags.cpp
+++ b/engines/ags/ags.cpp
@@ -124,7 +124,7 @@ Common::Error AGSEngine::run() {
 	if (debugChannelSet(-1, kDebugScan)) {
 		// Scan the given folder and subfolders for unknown games
 		AGS3::GameScanner scanner;
-		scanner.scan(ConfMan.get("path"));
+		scanner.scan(ConfMan.getPath("path"));
 		return Common::kNoError;
 	}
 
@@ -295,7 +295,7 @@ bool AGSEngine::is64BitGame() const {
 }
 
 Common::FSNode AGSEngine::getGameFolder() {
-	return Common::FSNode(ConfMan.get("path"));
+	return Common::FSNode(ConfMan.getPath("path"));
 }
 
 bool AGSEngine::canLoadGameStateCurrently(Common::U32String *msg) {
diff --git a/engines/ags/console.cpp b/engines/ags/console.cpp
index 02a274d832f..87c74be2372 100644
--- a/engines/ags/console.cpp
+++ b/engines/ags/console.cpp
@@ -225,7 +225,7 @@ bool AGSConsole::Cmd_dumpSprite(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::String pngFile = Common::String::format("%s-sprite%03d.png", _vm->getGameId().c_str(), spriteId);
+	Common::Path pngFile(Common::String::format("%s-sprite%03d.png", _vm->getGameId().c_str(), spriteId));
 	Common::DumpFile df;
 	if (df.open(pngFile)) {
 		byte *palette = nullptr;
diff --git a/engines/ags/detection.cpp b/engines/ags/detection.cpp
index 0424c837538..f6139c73b38 100644
--- a/engines/ags/detection.cpp
+++ b/engines/ags/detection.cpp
@@ -147,14 +147,14 @@ ADDetectedGame AGSMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 		if (file->isDirectory())
 			continue;
 
-		Common::String filename = file->getName();
-		if (!filename.hasSuffixIgnoreCase(".exe") &&
-		        !filename.hasSuffixIgnoreCase(".ags") &&
+		Common::Path filename = file->getPathInArchive();
+		if (!filename.baseName().hasSuffixIgnoreCase(".exe") &&
+		        !filename.baseName().hasSuffixIgnoreCase(".ags") &&
 		        !filename.equalsIgnoreCase("ac2game.dat"))
 			// Neither, so move on
 			continue;
 
-		filename = Common::punycode_encodefilename(filename);
+		filename = filename.punycodeEncode();
 		Common::File f;
 		if (!allFiles.contains(filename) || !f.open(allFiles[filename]))
 			continue;
@@ -177,7 +177,7 @@ ADDetectedGame AGSMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 
 			AGS::g_fallbackDesc.desc.gameId = _gameid.c_str();
 			AGS::g_fallbackDesc.desc.extra = _extra.c_str();
-			AGS::g_fallbackDesc.desc.filesDescriptions[0].fileName = _filename.c_str();
+			AGS::g_fallbackDesc.desc.filesDescriptions[0].fileName = _filename.toString('/').c_str();
 			AGS::g_fallbackDesc.desc.filesDescriptions[0].fileSize = f.size();
 			AGS::g_fallbackDesc.desc.filesDescriptions[0].md5 = _md5.c_str();
 
diff --git a/engines/ags/detection.h b/engines/ags/detection.h
index e7adc087cdf..6a11772c2dd 100644
--- a/engines/ags/detection.h
+++ b/engines/ags/detection.h
@@ -67,7 +67,7 @@ enum AGSSpriteFontVersion { kAGSSpriteFont = 0, kClifftopGames = 1 };
 class AGSMetaEngineDetection : public AdvancedMetaEngineDetection {
 	mutable Common::String _gameid;
 	mutable Common::String _extra;
-	mutable Common::String _filename;
+	mutable Common::Path _filename;
 	mutable Common::String _md5;
 
 	static const DebugChannelDef debugFlagList[];
diff --git a/engines/ags/dialogs.cpp b/engines/ags/dialogs.cpp
index ee0bebb1901..fdd205f112e 100644
--- a/engines/ags/dialogs.cpp
+++ b/engines/ags/dialogs.cpp
@@ -64,7 +64,7 @@ AGSOptionsWidget::AGSOptionsWidget(GuiObject *boss, const Common::String &name,
 	_langPopUp = new GUI::PopUpWidget(widgetsBoss(), _dialogLayout + ".translation");
 	_langPopUp->appendEntry(_("<default>"), (uint32) - 1);
 
-	Common::String path = ConfMan.get("path", _domain);
+	Common::Path path = ConfMan.getPath("path", _domain);
 	Common::FSDirectory dir(path);
 	Common::ArchiveMemberList traFileList;
 	dir.listMatchingMembers(traFileList, "*.tra");
diff --git a/engines/ags/engine/ac/listbox.cpp b/engines/ags/engine/ac/listbox.cpp
index 0c3a572b06f..daaaa85ecbc 100644
--- a/engines/ags/engine/ac/listbox.cpp
+++ b/engines/ags/engine/ac/listbox.cpp
@@ -86,7 +86,7 @@ void FillDirList(std::set<String> &files, const String &path) {
 		String subDir = dirName.Mid(_GP(ResPaths).DataDir.GetLength());
 		if (!subDir.IsEmpty() && subDir[0u] == '/')
 			subDir.ClipLeft(1);
-		dirName = ConfMan.get("path");
+		dirName = ConfMan.getPath("path").toString('/');
 	} else if (dirName.CompareLeftNoCase(get_save_game_directory()) == 0) {
 		// Save files listing
 		FillSaveList(files, filePattern);
diff --git a/engines/ags/game_scanner.cpp b/engines/ags/game_scanner.cpp
index 55cb2fd78b9..825b8f967f6 100644
--- a/engines/ags/game_scanner.cpp
+++ b/engines/ags/game_scanner.cpp
@@ -46,7 +46,7 @@ extern bool define_gamedata_location(const AGS::Shared::String &exe_path);
 extern bool engine_try_init_gamedata(AGS::Shared::String gamepak_path);
 
 
-void GameScanner::scan(const Common::String &startFolder) {
+void GameScanner::scan(const Common::Path &startFolder) {
 	detectClashes();
 
 	Common::FSNode folder(startFolder);
@@ -91,13 +91,13 @@ void GameScanner::scanFolder(const Common::FSNode &folder) {
 		} else if (filename.hasSuffixIgnoreCase(".exe") ||
 		           filename.hasSuffixIgnoreCase(".ags") ||
 		           filename.equalsIgnoreCase("ac2game.dat")) {
-			Common::String path = node.getPath();
+			Common::Path path = node.getPath();
 			scanFile(path);
 		}
 	}
 }
 
-void GameScanner::scanFile(const Common::String &filename) {
+void GameScanner::scanFile(const Common::Path &filename) {
 #ifdef TODO
 	Common::File f;
 	Common::FSNode fsNode(filename);
diff --git a/engines/ags/game_scanner.h b/engines/ags/game_scanner.h
index e6591812fc0..1d5f60366af 100644
--- a/engines/ags/game_scanner.h
+++ b/engines/ags/game_scanner.h
@@ -50,7 +50,7 @@ private:
 	/**
 	 * Scans a single file that may be an AGS game
 	 */
-	void scanFile(const Common::String &filename);
+	void scanFile(const Common::Path &filename);
 
 	/**
 	 * Convert a game name to an appropriate game Id
@@ -65,7 +65,7 @@ public:
 	/**
 	 * Main execution method
 	 */
-	void scan(const Common::String &startFolder);
+	void scan(const Common::Path &startFolder);
 };
 
 } // namespace AGS3
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index f827e815f52..01ed8390957 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -132,12 +132,12 @@ String FindGameData(const String &path, bool(*fn_testfile)(const String &)) {
 	if (folder.getChildren(files, Common::FSNode::kListFilesOnly)) {
 		for (Common::FSList::iterator it = files.begin(); it != files.end(); ++it) {
 			Common::String test_file = it->getName();
-			Common::String filePath = it->getPath();
+			Common::Path filePath = it->getPath();
 
 			if (test_file.hasSuffixIgnoreCase(".ags") ||
 			        test_file.equalsIgnoreCase("ac2game.dat") ||
 			        test_file.hasSuffixIgnoreCase(".exe")) {
-				if (IsMainGameLibrary(test_file.c_str()) && fn_testfile(filePath.c_str())) {
+				if (IsMainGameLibrary(test_file.c_str()) && fn_testfile(filePath.toString('/'))) {
 					Debug::Printf("Found game data pak: %s", test_file.c_str());
 					return test_file.c_str();
 				}
diff --git a/engines/ags/shared/util/directory.cpp b/engines/ags/shared/util/directory.cpp
index 802033c19ba..dfd970070cf 100644
--- a/engines/ags/shared/util/directory.cpp
+++ b/engines/ags/shared/util/directory.cpp
@@ -86,7 +86,8 @@ String GetCurrentDirectory() {
 	Path::FixupPath(str);
 	return str;
 #else
-	return ConfMan.get("path");
+	// Use / separator
+	return ConfMan.getPath("path").toString('/');
 #endif
 }
 
diff --git a/engines/ags/shared/util/stdio_compat.cpp b/engines/ags/shared/util/stdio_compat.cpp
index c6f9d9fdc52..e1fca841892 100644
--- a/engines/ags/shared/util/stdio_compat.cpp
+++ b/engines/ags/shared/util/stdio_compat.cpp
@@ -54,18 +54,18 @@ static Common::FSNode getFSNode(const char *path) {
 	Common::FSNode node;
 	Common::String filePath(path);
 	if (filePath.empty() || filePath == "." || filePath == "./")
-		return Common::FSNode(ConfMan.get("path"));
+		return Common::FSNode(ConfMan.getPath("path"));
 	else if (filePath.hasPrefix("./")) {
 		filePath = filePath.substr(2);
-		node = Common::FSNode(ConfMan.get("path"));
+		node = Common::FSNode(ConfMan.getPath("path"));
 	} else if (filePath.hasPrefixIgnoreCase(AGS::Shared::SAVE_FOLDER_PREFIX)) {
 		filePath = filePath.substr(strlen(AGS::Shared::SAVE_FOLDER_PREFIX));
 		node = Common::FSNode(ConfMan.getPath("savepath"));
 	} else {
-		node = Common::FSNode(filePath);
+		node = Common::FSNode(Common::Path(filePath, '/'));
 		if (node.isReadable())
 			return node;
-		node = Common::FSNode(ConfMan.get("path"));
+		node = Common::FSNode(ConfMan.getPath("path"));
 	}
 
 	// Use FSDirectory for case-insensitive search
@@ -74,7 +74,8 @@ static Common::FSNode getFSNode(const char *path) {
 	// Iterate through any further subfolders or filename
 	size_t separator;
 	while ((separator = filePath.find('/')) != Common::String::npos) {
-		dir.reset(dir->getSubDirectory(filePath.substr(0, separator)));
+		Common::Path member(filePath.substr(0, separator));
+		dir.reset(dir->getSubDirectory(member));
 		if (!dir)
 			return Common::FSNode();
 		filePath = Common::String(filePath.c_str() + separator + 1);
@@ -83,13 +84,14 @@ static Common::FSNode getFSNode(const char *path) {
 	if (filePath.empty())
 		return dir->getFSNode();
 
-	if (dir->hasFile(filePath)) {
-		Common::ArchiveMemberPtr file = dir->getMember(filePath);
+	Common::Path member(filePath);
+	if (dir->hasFile(member)) {
+		Common::ArchiveMemberPtr file = dir->getMember(member);
 		if (file)
 			return dir->getFSNode().getChild(file->getName());
 	}
 
-	Common::FSDirectory *subDir = dir->getSubDirectory(filePath);
+	Common::FSDirectory *subDir = dir->getSubDirectory(member);
 	if (subDir) {
 		dir.reset(subDir);
 		return dir->getFSNode();


Commit: 979b7f36696bd64baa04475631a134158677ed88
    https://github.com/scummvm/scummvm/commit/979b7f36696bd64baa04475631a134158677ed88
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ASYLUM: Migrate engine to Path

Changed paths:
    engines/asylum/asylum.cpp
    engines/asylum/console.cpp
    engines/asylum/respack.cpp
    engines/asylum/respack.h
    engines/asylum/views/video.cpp
    engines/asylum/views/video.h


diff --git a/engines/asylum/asylum.cpp b/engines/asylum/asylum.cpp
index 8f00d620214..fc906601ca1 100644
--- a/engines/asylum/asylum.cpp
+++ b/engines/asylum/asylum.cpp
@@ -73,7 +73,7 @@ AsylumEngine::AsylumEngine(OSystem *system, const ADGameDescription *gd) : Engin
 	_previousScene = nullptr;
 
 	// Add default search directories
-	const Common::FSNode gamePath(ConfMan.get("path"));
+	const Common::FSNode gamePath(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gamePath, "vids");
 	SearchMan.addSubDirectoryMatching(gamePath, "music");
 
diff --git a/engines/asylum/console.cpp b/engines/asylum/console.cpp
index 626bd7472ba..3d51c766b84 100644
--- a/engines/asylum/console.cpp
+++ b/engines/asylum/console.cpp
@@ -371,7 +371,7 @@ bool Console::cmdListFiles(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::String filter(const_cast<char *>(argv[1]));
+	Common::Path filter(const_cast<char *>(argv[1]), Common::Path::kNativeSeparator);
 
 	Common::ArchiveMemberList list;
 	int count = SearchMan.listMatchingMembers(list, filter);
diff --git a/engines/asylum/respack.cpp b/engines/asylum/respack.cpp
index 9a5d7a8ec55..650d38caadc 100644
--- a/engines/asylum/respack.cpp
+++ b/engines/asylum/respack.cpp
@@ -74,7 +74,7 @@ ResourceEntry *ResourceManager::get(ResourceId id) {
 			if (_vm->checkGameVersion("Demo"))
 				pack = new ResourcePack("res.002");
 			else
-				pack = new ResourcePack(Common::String::format("mus.%03d", _musicPackId));
+				pack = new ResourcePack(Common::Path(Common::String::format("mus.%03d", _musicPackId)));
 		} else {
 			if (packId == kResourcePackSharedSound) {
 				if (_vm->checkGameVersion("Demo")) {
@@ -86,7 +86,7 @@ ResourceEntry *ResourceManager::get(ResourceId id) {
 				if (_cdNumber == -1)
 					error("[ResourceManager::get] Cd number has not been set!");
 
-				pack = new ResourcePack(Common::String::format("res.%01d%02d", _cdNumber, packId));
+				pack = new ResourcePack(Common::Path(Common::String::format("res.%01d%02d", _cdNumber, packId)));
 
 				// WORKAROUND to support combined resource packs (used by GOG and Steam versions)
 				if (pack->_packFile.size() == 299872422)
@@ -94,7 +94,7 @@ ResourceEntry *ResourceManager::get(ResourceId id) {
 						if (_cdNumber == patchedSizes[i].cdNumber)
 							pack->_resources[RESOURCE_INDEX(patchedSizes[i].resourceId)].size = patchedSizes[i].size;
 			} else {
-				pack = new ResourcePack(Common::String::format("res.%03d", packId));
+				pack = new ResourcePack(Common::Path(Common::String::format("res.%03d", packId)));
 			}
 		}
 
@@ -119,7 +119,7 @@ void ResourceManager::unload(ResourcePackId id) {
 //////////////////////////////////////////////////////////////////////////
 // ResourcePack
 //////////////////////////////////////////////////////////////////////////
-ResourcePack::ResourcePack(const Common::String &filename) {
+ResourcePack::ResourcePack(const Common::Path &filename) {
 	init(filename);
 }
 
@@ -131,9 +131,9 @@ ResourcePack::~ResourcePack() {
 	_packFile.close();
 }
 
-void ResourcePack::init(const Common::String &filename) {
+void ResourcePack::init(const Common::Path &filename) {
 	if (!_packFile.open(filename))
-		error("[ResourcePack::init] Could not open resource file: %s", filename.c_str());
+		error("[ResourcePack::init] Could not open resource file: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	uint32 entryCount = _packFile.readUint32LE();
 	_resources.resize(entryCount);
diff --git a/engines/asylum/respack.h b/engines/asylum/respack.h
index b4f62097236..40ca662d509 100644
--- a/engines/asylum/respack.h
+++ b/engines/asylum/respack.h
@@ -57,14 +57,14 @@ public:
 	ResourceEntry *get(uint16 index);
 
 protected:
-	ResourcePack(const Common::String &filename);
+	ResourcePack(const Common::Path &filename);
 	~ResourcePack();
 
 private:
 	Common::Array<ResourceEntry> _resources;
 	Common::File _packFile;
 
-	void init(const Common::String &filename);
+	void init(const Common::Path &filename);
 
 	friend class ResourceManager;
 };
diff --git a/engines/asylum/views/video.cpp b/engines/asylum/views/video.cpp
index 1fc55147b3a..f44e9264702 100644
--- a/engines/asylum/views/video.cpp
+++ b/engines/asylum/views/video.cpp
@@ -159,7 +159,7 @@ void VideoPlayer::play(uint32 videoNumber, EventHandler *handler) {
 		filename = Common::String::format("mov%03d.avi", videoNumber);
 	else
 		filename = Common::String::format("mov%03d.smk", videoNumber);
-	play(filename, Config.showMovieSubtitles);
+	play(Common::Path(filename), Config.showMovieSubtitles);
 
 	// Cleanup and switch to previous event handler
 	getCursor()->show();
@@ -167,7 +167,7 @@ void VideoPlayer::play(uint32 videoNumber, EventHandler *handler) {
 	_vm->switchEventHandler(handler);
 }
 
-void VideoPlayer::play(const Common::String &filename, bool showSubtitles) {
+void VideoPlayer::play(const Common::Path &filename, bool showSubtitles) {
 	if (!_decoder->loadFile(filename))
 		error("[Video::playVideo] Invalid video index (%d)", _currentMovie);
 
@@ -218,7 +218,7 @@ void VideoPlayer::play(const Common::String &filename, bool showSubtitles) {
 
 			if (showSubtitles) {
 				int32 currentFrame = _decoder->getCurFrame() + 1;
-				debugC(kDebugLevelVideo, "[Video] {%s} Playing Frame %d", filename.c_str(), currentFrame);
+				debugC(kDebugLevelVideo, "[Video] {%s} Playing Frame %d", filename.toString(Common::Path::kNativeSeparator).c_str(), currentFrame);
 				// Check for next frame
 				if (currentFrame > frameEnd) {
 					if (index < _subtitles.size()) {
diff --git a/engines/asylum/views/video.h b/engines/asylum/views/video.h
index e795ff67445..fe614efe881 100644
--- a/engines/asylum/views/video.h
+++ b/engines/asylum/views/video.h
@@ -92,7 +92,7 @@ private:
 	 * @param filename 		Filename of the file.
 	 * @param showSubtitles true to show, false to hide the subtitles.
 	 */
-	void play(const Common::String &filename, bool showSubtitles);
+	void play(const Common::Path &filename, bool showSubtitles);
 
 	/**
 	 * Sets up the palette.


Commit: 905ea1386ef8179f1efe34fd77c656be1be4c947
    https://github.com/scummvm/scummvm/commit/905ea1386ef8179f1efe34fd77c656be1be4c947
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
AVALANCHE: Migrate engine to Path

Changed paths:
    engines/avalanche/animation.cpp
    engines/avalanche/avalot.cpp
    engines/avalanche/background.cpp
    engines/avalanche/background.h
    engines/avalanche/graphics.cpp
    engines/avalanche/graphics.h


diff --git a/engines/avalanche/animation.cpp b/engines/avalanche/animation.cpp
index 6eb9ce0b0a4..a3c5b05d2fa 100644
--- a/engines/avalanche/animation.cpp
+++ b/engines/avalanche/animation.cpp
@@ -93,9 +93,9 @@ void AnimationType::init(byte spritenum, bool doCheck) {
 		return; // Already running!
 
 	Common::File inf;
-	Common::String filename = Common::String::format("sprite%d.avd", spritenum);
+	Common::Path filename(Common::String::format("sprite%d.avd", spritenum));
 	if (!inf.open(filename))
-		error("AVALANCHE: Trip: File not found: %s", filename.c_str());
+		error("AVALANCHE: Trip: File not found: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	inf.seek(177);
 
diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp
index 3673c485d86..7a0f3fb1bba 100644
--- a/engines/avalanche/avalot.cpp
+++ b/engines/avalanche/avalot.cpp
@@ -325,11 +325,10 @@ void AvalancheEngine::loadAlso(byte num) {
 			}
 		}
 	}
-	Common::String filename;
-	filename = Common::String::format("also%d.avd", num);
+	Common::Path filename(Common::String::format("also%d.avd", num));
 	Common::File file;
 	if (!file.open(filename))
-		error("AVALANCHE: File not found: %s", filename.c_str());
+		error("AVALANCHE: File not found: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	file.seek(128);
 
@@ -416,10 +415,10 @@ void AvalancheEngine::loadAlso(byte num) {
 }
 
 void AvalancheEngine::loadBackground(byte num) {
-	Common::String filename = Common::String::format("place%d.avd", num);
+	Common::Path filename(Common::String::format("place%d.avd", num));
 	Common::File file;
 	if (!file.open(filename))
-		error("AVALANCHE: File not found: %s", filename.c_str());
+		error("AVALANCHE: File not found: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	file.seek(146);
 	if (!_roomnName.empty())
@@ -925,7 +924,7 @@ void AvalancheEngine::thinkAbout(byte object, bool type) {
 	_thinks = object;
 	object--;
 
-	Common::String filename;
+	Common::Path filename;
 	if (type == kThing) {
 		filename = "thinks.avd";
 	} else { // kPerson
diff --git a/engines/avalanche/background.cpp b/engines/avalanche/background.cpp
index e8b5a0716c4..8d635719b0c 100644
--- a/engines/avalanche/background.cpp
+++ b/engines/avalanche/background.cpp
@@ -277,7 +277,7 @@ void Background::update() {
 
 void Background::loadSprites(byte number) {
 	Common::File f;
-	_filename = _filename.format("chunk%d.avd", number);
+	_filename = Common::Path(Common::String::format("chunk%d.avd", number));
 	if (!f.open(_filename))
 		return; // We skip because some rooms don't have sprites in the background.
 
diff --git a/engines/avalanche/background.h b/engines/avalanche/background.h
index f3faaf27dff..8f94850e776 100644
--- a/engines/avalanche/background.h
+++ b/engines/avalanche/background.h
@@ -67,7 +67,7 @@ private:
 	int32 _offsets[40];
 	byte _spriteNum;
 	SpriteType _sprites[40];
-	Common::String _filename;
+	Common::Path _filename;
 	static const int16 kOnDisk; // Value of _sprites[fv]._x when it's not in memory.
 
 	void drawSprite(int16 x, int16 y, SpriteType &sprite);
diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp
index ba44005ca7f..32595c44589 100644
--- a/engines/avalanche/graphics.cpp
+++ b/engines/avalanche/graphics.cpp
@@ -167,11 +167,11 @@ void GraphicManager::loadMouse(byte which) {
 	cursor.free();
 }
 
-void GraphicManager::drawThinkPic(Common::String filename, int id) {
+void GraphicManager::drawThinkPic(const Common::Path &filename, int id) {
 	static const int16 picSize = 966;
 	Common::File file;
 	if (!file.open(filename))
-		error("drawThinkPic(): File not found: %s", filename.c_str());
+		error("drawThinkPic(): File not found: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	file.seek(id * picSize + 65);
 	Graphics::Surface picture = loadPictureGraphic(file);
@@ -492,10 +492,10 @@ void GraphicManager::blackOutScreen() {
 
 void GraphicManager::nimLoad() {
 	Common::File file;
-	Common::String filename = "nim.avd";
+	Common::Path filename("nim.avd");
 
 	if (!file.open(filename))
-		error("AVALANCHE: Scrolls: File not found: %s", filename.c_str());
+		error("AVALANCHE: Scrolls: File not found: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	file.seek(41);
 
@@ -1111,10 +1111,10 @@ void GraphicManager::drawErrorLight(bool state) {
  */
 void GraphicManager::drawSign(Common::String fn, int16 xl, int16 yl, int16 y) {
 	Common::File file;
-	Common::String filename = Common::String::format("%s.avd", fn.c_str());
+	Common::Path filename(Common::String::format("%s.avd", fn.c_str()));
 
 	if (!file.open(filename))
-		error("AVALANCHE: Scrolls: File not found: %s", filename.c_str());
+		error("AVALANCHE: Scrolls: File not found: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	Graphics::Surface sign; // We make a Surface object for the picture itself.
 	sign = loadPictureSign(file, xl, yl);
diff --git a/engines/avalanche/graphics.h b/engines/avalanche/graphics.h
index 5dc5841888f..4f63cf5d3d7 100644
--- a/engines/avalanche/graphics.h
+++ b/engines/avalanche/graphics.h
@@ -136,7 +136,7 @@ public:
 	Graphics::Surface loadPictureRaw(Common::File &file, uint16 width, uint16 height);
 
 	void drawSprite(AnimationType *sprite, byte picnum, int16 x, int16 y);
-	void drawThinkPic(Common::String filename, int id);
+	void drawThinkPic(const Common::Path &filename, int id);
 	void drawToolbar();
 	void drawCursor(byte pos);
 	void drawReadyLight(Color color);


Commit: 6cfc214d5b406a4b9485c3a4731593b08234b14f
    https://github.com/scummvm/scummvm/commit/6cfc214d5b406a4b9485c3a4731593b08234b14f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BBVS: Migrate engine to Path

Changed paths:
    engines/bbvs/bbvs.cpp
    engines/bbvs/gamemodule.cpp
    engines/bbvs/gamemodule.h
    engines/bbvs/scene.cpp
    engines/bbvs/sound.cpp
    engines/bbvs/sound.h
    engines/bbvs/spritemodule.cpp
    engines/bbvs/spritemodule.h
    engines/bbvs/videoplayer.cpp


diff --git a/engines/bbvs/bbvs.cpp b/engines/bbvs/bbvs.cpp
index 1a1091f229a..6839beeb802 100644
--- a/engines/bbvs/bbvs.cpp
+++ b/engines/bbvs/bbvs.cpp
@@ -1310,7 +1310,7 @@ void BbvsEngine::updateDialogConditions() {
 
 void BbvsEngine::playSpeech(int soundNum) {
 	debug(5, "playSpeech(%0d)", soundNum);
-	Common::String sndFilename = Common::String::format("snd/snd%05d.aif", soundNum);
+	Common::Path sndFilename(Common::String::format("snd/snd%05d.aif", soundNum));
 	Common::File *fd = new Common::File();
 	fd->open(sndFilename);
 	Audio::AudioStream *audioStream = Audio::makeAIFFStream(fd, DisposeAfterUse::YES);
diff --git a/engines/bbvs/gamemodule.cpp b/engines/bbvs/gamemodule.cpp
index 1c909938c55..4e7de0377a2 100644
--- a/engines/bbvs/gamemodule.cpp
+++ b/engines/bbvs/gamemodule.cpp
@@ -36,7 +36,7 @@ GameModule::~GameModule() {
 	unload();
 }
 
-void GameModule::load(const char *filename) {
+void GameModule::load(const Common::Path &filename) {
 	debug(0, "GameModule::load()");
 
 	unload();
@@ -44,7 +44,7 @@ void GameModule::load(const char *filename) {
 	Common::File fd;
 
 	if (!fd.open(filename))
-		error("GameModule::load() Could not open %s", filename);
+		error("GameModule::load() Could not open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	loadBgSprites(fd);
 	loadCameraInits(fd);
diff --git a/engines/bbvs/gamemodule.h b/engines/bbvs/gamemodule.h
index 59e6ad20e28..f5a6cd6e6a4 100644
--- a/engines/bbvs/gamemodule.h
+++ b/engines/bbvs/gamemodule.h
@@ -134,7 +134,7 @@ public:
 	GameModule();
 	~GameModule();
 
-	void load(const char *filename);
+	void load(const Common::Path &filename);
 
 	int getFieldC();
 	int getButtheadObjectIndex();
diff --git a/engines/bbvs/scene.cpp b/engines/bbvs/scene.cpp
index 45669238187..d302ca5cc35 100644
--- a/engines/bbvs/scene.cpp
+++ b/engines/bbvs/scene.cpp
@@ -41,20 +41,20 @@ static const int kAfterVideoSceneNumDemo[] = {
 void BbvsEngine::loadScene(int sceneNum) {
 	debug(0, "BbvsEngine::loadScene() sceneNum: %d", sceneNum);
 
-	Common::String sprFilename = Common::String::format("vnm/vspr%04d.vnm", sceneNum);
-	Common::String gamFilename = Common::String::format("vnm/game%04d.vnm", sceneNum);
+	Common::Path sprFilename(Common::String::format("vnm/vspr%04d.vnm", sceneNum));
+	Common::Path gamFilename(Common::String::format("vnm/game%04d.vnm", sceneNum));
 
 	_screen->clear();
 
-	_spriteModule->load(sprFilename.c_str());
-	_gameModule->load(gamFilename.c_str());
+	_spriteModule->load(sprFilename);
+	_gameModule->load(gamFilename);
 
 	Palette palette = _spriteModule->getPalette();
 	_screen->setPalette(palette);
 
 	// Preload sounds
 	for (uint i = 0; i < _gameModule->getPreloadSoundsCount(); ++i) {
-		Common::String filename = Common::String::format("snd/snd%05d.aif", _gameModule->getPreloadSound(i));
+		Common::Path filename(Common::String::format("snd/snd%05d.aif", _gameModule->getPreloadSound(i)));
 		_sound->loadSound(filename);
 	}
 
diff --git a/engines/bbvs/sound.cpp b/engines/bbvs/sound.cpp
index 13f6b4dcdd0..009fe49af3c 100644
--- a/engines/bbvs/sound.cpp
+++ b/engines/bbvs/sound.cpp
@@ -36,18 +36,18 @@ Sound::~Sound() {
 	delete _stream;
 }
 
-void Sound::load(const Common::String &filename) {
+void Sound::load(const Common::Path &filename) {
 	Common::File *fd = new Common::File();
 	if (!fd->open(filename)) {
 		delete fd;
-		error("SoundMan::loadSound() Could not load %s", filename.c_str());
+		error("SoundMan::loadSound() Could not load %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	_stream = Audio::makeAIFFStream(fd, DisposeAfterUse::YES);
 	_filename = filename;
 }
 
 void Sound::play(bool loop) {
-	debug(0, "Sound::play() [%s] loop:%d", _filename.c_str(), loop);
+	debug(0, "Sound::play() [%s] loop:%d", _filename.toString(Common::Path::kNativeSeparator).c_str(), loop);
 
 	stop();
 	_stream->rewind();
@@ -75,7 +75,7 @@ SoundMan::~SoundMan() {
 	unloadSounds();
 }
 
-void SoundMan::loadSound(const Common::String &filename) {
+void SoundMan::loadSound(const Common::Path &filename) {
 	Sound *sound = new Sound();
 	sound->load(filename);
 	_sounds.push_back(sound);
diff --git a/engines/bbvs/sound.h b/engines/bbvs/sound.h
index fddb3e78da2..b03568651f6 100644
--- a/engines/bbvs/sound.h
+++ b/engines/bbvs/sound.h
@@ -35,7 +35,7 @@ class Sound {
 public:
 	Sound();
 	~Sound();
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 	void play(bool loop);
 	void stop();
 	bool isPlaying();
@@ -43,13 +43,13 @@ protected:
 	Audio::RewindableAudioStream *_stream;
 	Audio::SoundHandle _handle;
 	// Keep the filename for debugging purposes
-	Common::String _filename;
+	Common::Path _filename;
 };
 
 class SoundMan {
 public:
 	~SoundMan();
-	void loadSound(const Common::String &fileName);
+	void loadSound(const Common::Path &fileName);
 	void playSound(uint index, bool loop = false);
 	void stopSound(uint index);
 	bool isSoundPlaying(uint index);
diff --git a/engines/bbvs/spritemodule.cpp b/engines/bbvs/spritemodule.cpp
index 0abb3de8a32..f4f4e0766a6 100644
--- a/engines/bbvs/spritemodule.cpp
+++ b/engines/bbvs/spritemodule.cpp
@@ -39,12 +39,12 @@ SpriteModule::~SpriteModule() {
 	unload();
 }
 
-void SpriteModule::load(const char *filename) {
+void SpriteModule::load(const Common::Path &filename) {
 	unload();
 
 	Common::File fd;
 	if (!fd.open(filename))
-		error("SpriteModule::load() Could not open %s", filename);
+		error("SpriteModule::load() Could not open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	fd.readUint32LE(); // Skip magic
 	fd.readUint32LE(); // Skip unused
diff --git a/engines/bbvs/spritemodule.h b/engines/bbvs/spritemodule.h
index 5023b0f9f3f..67cbca23ee2 100644
--- a/engines/bbvs/spritemodule.h
+++ b/engines/bbvs/spritemodule.h
@@ -48,7 +48,7 @@ class SpriteModule {
 public:
 	SpriteModule();
 	~SpriteModule();
-	void load(const char *filename);
+	void load(const Common::Path &filename);
 	int getSpriteCount() { return _spritesCount; }
 	Sprite getSprite(int index);
 	Palette getPalette();
diff --git a/engines/bbvs/videoplayer.cpp b/engines/bbvs/videoplayer.cpp
index 908f4788abf..63e5d2052a6 100644
--- a/engines/bbvs/videoplayer.cpp
+++ b/engines/bbvs/videoplayer.cpp
@@ -28,16 +28,16 @@
 namespace Bbvs {
 
 void BbvsEngine::playVideo(int videoNum) {
-	Common::String videoFilename;
+	Common::Path videoFilename;
 
 	if (videoNum >= 100)
-		videoFilename = Common::String::format("snd/snd%05d.aif", videoNum + 1400);
+		videoFilename = Common::Path(Common::String::format("snd/snd%05d.aif", videoNum + 1400));
 	else
-		videoFilename = Common::String::format("vid/video%03d.avi", videoNum - 1);
+		videoFilename = Common::Path(Common::String::format("vid/video%03d.avi", videoNum - 1));
 
 	Video::AVIDecoder videoDecoder;
 	if (!videoDecoder.loadFile(videoFilename)) {
-		warning("Unable to open video %s", videoFilename.c_str());
+		warning("Unable to open video %s", videoFilename.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 


Commit: db6fcfcc24c88bd0698f15b75e07c842ed49f6b4
    https://github.com/scummvm/scummvm/commit/db6fcfcc24c88bd0698f15b75e07c842ed49f6b4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BLADERUNNER: Migrate engine to Path

Changed paths:
    engines/bladerunner/archive.cpp
    engines/bladerunner/archive.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/debugger.cpp
    engines/bladerunner/slice_animations.cpp
    engines/bladerunner/slice_animations.h


diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp
index e9913700b25..7a98e491a7f 100644
--- a/engines/bladerunner/archive.cpp
+++ b/engines/bladerunner/archive.cpp
@@ -37,17 +37,17 @@ MIXArchive::~MIXArchive() {
 	}
 }
 
-bool MIXArchive::exists(const Common::String &filename) {
+bool MIXArchive::exists(const Common::Path &filename) {
 	return Common::File::exists(filename);
 }
 
-bool MIXArchive::open(const Common::String &filename) {
+bool MIXArchive::open(const Common::Path &filename) {
 	if (!_fd.open(filename)) {
-		error("MIXArchive::open(): Can not open %s", filename.c_str());
+		error("MIXArchive::open(): Can not open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
-	_isTLK = filename.hasSuffix(".TLK");
+	_isTLK = filename.baseName().hasSuffix(".TLK");
 
 	_entryCount = _fd.readUint16LE();
 	_size       = _fd.readUint32LE();
@@ -66,7 +66,7 @@ bool MIXArchive::open(const Common::String &filename) {
 	}
 
 	if (_fd.err()) {
-		error("MIXArchive::open(): Error reading entries in %s", filename.c_str());
+		error("MIXArchive::open(): Error reading entries in %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 		_fd.close();
 		return false;
 	}
@@ -140,13 +140,13 @@ uint32 MIXArchive::indexForHash(int32 hash) const {
 	return _entryCount;
 }
 
-Common::SeekableReadStream *MIXArchive::createReadStreamForMember(const Common::String &name) {
+Common::SeekableReadStream *MIXArchive::createReadStreamForMember(const Common::Path &name) {
 	int32 hash;
 
 	if (_isTLK) {
-		hash = tlk_id(name);
+		hash = tlk_id(name.baseName());
 	} else {
-		hash = MIXArchive::getHash(name);
+		hash = MIXArchive::getHash(name.baseName());
 	}
 
 	uint32 i = indexForHash(hash);
diff --git a/engines/bladerunner/archive.h b/engines/bladerunner/archive.h
index c5fec3e8d11..29c99abf89e 100644
--- a/engines/bladerunner/archive.h
+++ b/engines/bladerunner/archive.h
@@ -34,15 +34,15 @@ public:
 	~MIXArchive();
 
 	static int32 getHash(const Common::String &name);
-	static bool exists(const Common::String &filename);
+	static bool exists(const Common::Path &filename);
 
-	bool open(const Common::String &filename);
+	bool open(const Common::Path &filename);
 	void close();
 	bool isOpen() const;
 
 	Common::String getName() const { return _fd.getName(); }
 
-	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name);
+	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &name);
 
 private:
 	Common::File _fd;
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index a62c825da23..61047eafb64 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -352,7 +352,7 @@ void BladeRunnerEngine::pauseEngineIntern(bool pause) {
 
 Common::Error BladeRunnerEngine::run() {
 	Common::Array<Common::String> missingFiles;
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "base");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "cd1");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "cd2");
@@ -531,7 +531,7 @@ Common::Error BladeRunnerEngine::run() {
 bool BladeRunnerEngine::checkFiles(Common::Array<Common::String> &missingFiles) {
 	missingFiles.clear();
 
-	Common::Array<Common::String> requiredFiles;
+	Common::Array<const char *> requiredFiles;
 
 	if (_enhancedEdition) {
 		requiredFiles.push_back("BladeRunner.kpf");
@@ -565,7 +565,7 @@ bool BladeRunnerEngine::checkFiles(Common::Array<Common::String> &missingFiles)
 
 	if (!hasHdFrames) {
 		for (uint i = 1; i <= 4; ++i) {
-			if (!Common::File::exists(Common::String::format("CDFRAMES%d.DAT", i)) && !Common::File::exists(Common::String::format("CD%d/CDFRAMES.DAT", i))) {
+			if (!Common::File::exists(Common::Path(Common::String::format("CDFRAMES%d.DAT", i))) && !Common::File::exists(Common::Path(Common::String::format("CD%d/CDFRAMES.DAT", i)))) {
 				missingFiles.push_back(Common::String::format("CD%d/CDFRAMES.DAT", i));
 			}
 		}
@@ -2421,7 +2421,7 @@ bool BladeRunnerEngine::openArchive(const Common::String &name) {
 		error("openArchive: No more archive slots");
 	}
 
-	_archives[i].open(name);
+	_archives[i].open(Common::Path(name));
 	return _archives[i].isOpen();
 }
 
@@ -2514,10 +2514,11 @@ void BladeRunnerEngine::setSubtitlesEnabled(bool newVal) {
 }
 
 Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::String &name) {
+	Common::Path path(name);
 	// If the file is extracted from MIX files use it directly, it is used by Russian translation patched by Siberian Studio
-	if (Common::File::exists(name)) {
+	if (Common::File::exists(path)) {
 		Common::File directFile;
-		if (directFile.open(name)) {
+		if (directFile.open(path)) {
 			Common::SeekableReadStream *stream = directFile.readStream(directFile.size());
 			directFile.close();
 			return stream;
@@ -2526,7 +2527,7 @@ Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::S
 
 	if (_enhancedEdition) {
 		assert(_archive != nullptr);
-		return _archive->createReadStreamForMember(name);
+		return _archive->createReadStreamForMember(path);
 	}
 
 	for (int i = 0; i != kArchiveCount; ++i) {
@@ -2535,7 +2536,7 @@ Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::S
 		}
 
 		// debug("getResource: Searching archive %s for %s.", _archives[i].getName().c_str(), name.c_str());
-		Common::SeekableReadStream *stream = _archives[i].createReadStreamForMember(name);
+		Common::SeekableReadStream *stream = _archives[i].createReadStreamForMember(path);
 		if (stream) {
 			return stream;
 		}
diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp
index f9248d83c97..2a9c70b0c24 100644
--- a/engines/bladerunner/debugger.cpp
+++ b/engines/bladerunner/debugger.cpp
@@ -3073,8 +3073,8 @@ bool Debugger::cmdPlayVqa(int argc, const char** argv) {
 		basename.erase(startOfExt);
 	}
 
-	Common::String basenameVQA = Common::String::format("%s.VQA", basename.c_str());
-	Common::String basenameVQP = Common::String::format("%s.VQP", basename.c_str());
+	Common::Path basenameVQA(Common::String::format("%s.VQA", basename.c_str()));
+	Common::Path basenameVQP(Common::String::format("%s.VQP", basename.c_str()));
 
 	// Check for existence of VQP
 	bool vqpFileExists = false;
@@ -3082,13 +3082,13 @@ bool Debugger::cmdPlayVqa(int argc, const char** argv) {
 	// Use Common::File exists() check instead of Common::FSNode directly
 	// to allow the file to be placed within SearchMan accessible locations
 	if (!Common::File::exists(basenameVQP)) {
-		debugPrintf("Warning: VQP file %s does not exist\n", basenameVQP.c_str());
+		debugPrintf("Warning: VQP file %s does not exist\n", basenameVQP.toString(Common::Path::kNativeSeparator).c_str());
 	} else {
 		vqpFileExists = true;
 	}
 
 	if (!Common::File::exists(basenameVQA)) {
-		debugPrintf("Warning: VQA file %s does not exist\n", basenameVQA.c_str());
+		debugPrintf("Warning: VQA file %s does not exist\n", basenameVQA.toString(Common::Path::kNativeSeparator).c_str());
 		return true;
 	}
 
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index 744091c8167..e43a5399cd7 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -136,7 +136,7 @@ bool SliceAnimations::openFrames(int fileNumber) {
 		}
 		_framesPageFile._fileNumber = fileNumber;
 
-		if (_framesPageFile.open(Common::String::format("CD%d/CDFRAMES.DAT", fileNumber), fileNumber)) {
+		if (_framesPageFile.open(Common::Path(Common::String::format("CD%d/CDFRAMES.DAT", fileNumber)), fileNumber)) {
 			return true;
 		}
 
@@ -145,7 +145,7 @@ bool SliceAnimations::openFrames(int fileNumber) {
 			return true;
 		}
 
-		if (_framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", fileNumber), fileNumber)) {
+		if (_framesPageFile.open(Common::Path(Common::String::format("CDFRAMES%d.DAT", fileNumber)), fileNumber)) {
 			return true;
 		}
 	} else {
@@ -156,14 +156,14 @@ bool SliceAnimations::openFrames(int fileNumber) {
 			_framesPageFile.close(i);
 			if (i == 1
 			    && (!_framesPageFile.open("CDFRAMES.DAT", i))
-			    && (!_framesPageFile.open(Common::String::format("CD%d/CDFRAMES.DAT", i), i))
-			    && (!_framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", i), i))
+			    && (!_framesPageFile.open(Common::Path(Common::String::format("CD%d/CDFRAMES.DAT", i)), i))
+			    && (!_framesPageFile.open(Common::Path(Common::String::format("CDFRAMES%d.DAT", i)), i))
 			) {
 				// For Chapter1 we try both CDFRAMES.DAT and CDFRAMES1.DAT
 				return false;
 			} else if (i != 1 &&
-				   (!_framesPageFile.open(Common::String::format("CD%d/CDFRAMES.DAT", i), i)) &&
-			          !_framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", i), i)
+				   (!_framesPageFile.open(Common::Path(Common::String::format("CD%d/CDFRAMES.DAT", i)), i)) &&
+			          !_framesPageFile.open(Common::Path(Common::String::format("CDFRAMES%d.DAT", i)), i)
 			) {
 				return false;
 			}
@@ -174,7 +174,7 @@ bool SliceAnimations::openFrames(int fileNumber) {
 	return false;
 }
 
-bool SliceAnimations::PageFile::open(const Common::String &name, int8 fileIdx) {
+bool SliceAnimations::PageFile::open(const Common::Path &name, int8 fileIdx) {
 	if (!_files[fileIdx].open(name))
 		return false;
 
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index 61796c17499..a0fd8091a0c 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -71,7 +71,7 @@ class SliceAnimations {
 
 		PageFile(SliceAnimations *sliceAnimations) : _sliceAnimations(sliceAnimations), _fileNumber(-1) {}
 
-		bool  open(const Common::String &name, int8 fileIdx);
+		bool  open(const Common::Path &name, int8 fileIdx);
 		void  close(int8 fileIdx);
 		void *loadPage(uint32 page);
 	};


Commit: e90ae68c5848367464682274f87114a50df53326
    https://github.com/scummvm/scummvm/commit/e90ae68c5848367464682274f87114a50df53326
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BURIED: Migrate engine to Path

Changed paths:
    engines/buried/avi_frames.cpp
    engines/buried/avi_frames.h
    engines/buried/buried.cpp
    engines/buried/buried.h
    engines/buried/demo/movie_scene.cpp
    engines/buried/demo/movie_scene.h
    engines/buried/frame_window.cpp
    engines/buried/frame_window.h
    engines/buried/graphics.cpp
    engines/buried/graphics.h
    engines/buried/inventory_window.cpp
    engines/buried/metaengine.cpp
    engines/buried/scene_view.cpp
    engines/buried/scene_view.h
    engines/buried/sound.cpp
    engines/buried/sound.h
    engines/buried/video_window.cpp
    engines/buried/video_window.h


diff --git a/engines/buried/avi_frames.cpp b/engines/buried/avi_frames.cpp
index 001a2cbe07c..5aff1f55204 100644
--- a/engines/buried/avi_frames.cpp
+++ b/engines/buried/avi_frames.cpp
@@ -32,7 +32,7 @@
 
 namespace Buried {
 
-AVIFrames::AVIFrames(const Common::String &fileName, uint cachedFrames) {
+AVIFrames::AVIFrames(const Common::Path &fileName, uint cachedFrames) {
 	_maxCachedFrames = 0;
 	_video = nullptr;
 	_cacheEnabled = false;
@@ -48,7 +48,7 @@ AVIFrames::~AVIFrames() {
 	close();
 }
 
-bool AVIFrames::open(const Common::String &fileName, uint cachedFrames) {
+bool AVIFrames::open(const Common::Path &fileName, uint cachedFrames) {
 	if (fileName.empty())
 		return false;
 
diff --git a/engines/buried/avi_frames.h b/engines/buried/avi_frames.h
index 70af1d38772..e31620fdf16 100644
--- a/engines/buried/avi_frames.h
+++ b/engines/buried/avi_frames.h
@@ -27,7 +27,7 @@
 
 #include "common/list.h"
 #include "common/scummsys.h"
-#include "common/str.h"
+#include "common/path.h"
 
 namespace Graphics {
 struct Surface;
@@ -41,10 +41,10 @@ namespace Buried {
 
 class AVIFrames {
 public:
-	AVIFrames(const Common::String &fileName = "", uint cachedFrames = 0);
+	AVIFrames(const Common::Path &fileName = Common::Path(), uint cachedFrames = 0);
 	~AVIFrames();
 
-	bool open(const Common::String &fileName, uint cachedFrames = 0);
+	bool open(const Common::Path &fileName, uint cachedFrames = 0);
 	void close();
 
 	const Graphics::Surface *getFrame(int frameIndex);
@@ -68,7 +68,7 @@ private:
 
 	typedef Common::List<CachedFrame> FrameList;
 
-	Common::String _fileName;
+	Common::Path _fileName;
 	FrameList _cachedFrames;
 	uint _maxCachedFrames;
 	Video::VideoDecoder *_video;
diff --git a/engines/buried/buried.cpp b/engines/buried/buried.cpp
index ffeb8c36533..960fe253e84 100644
--- a/engines/buried/buried.cpp
+++ b/engines/buried/buried.cpp
@@ -66,7 +66,7 @@ BuriedEngine::BuriedEngine(OSystem *syst, const ADGameDescription *gameDesc) : E
 	_yielding = false;
 	_allowVideoSkip = true;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "WIN31/MANUAL", 0, 2); // v1.05 era
 	SearchMan.addSubDirectoryMatching(gameDataDir, "WIN95/MANUAL", 0, 2); // v1.10 era (Trilogy release)
 
@@ -114,16 +114,16 @@ Common::Error BuriedEngine::run() {
 
 	if (isCompressed()) {
 		if (!_mainEXE->loadFromCompressedEXE(getEXEName()))
-			error("Failed to load main EXE '%s'", getEXEName().c_str());
+			error("Failed to load main EXE '%s'", getEXEName().toString(Common::Path::kNativeSeparator).c_str());
 
 		if (_library && !_library->loadFromCompressedEXE(getLibraryName()))
-			error("Failed to load library DLL '%s'", getLibraryName().c_str());
+			error("Failed to load library DLL '%s'", getLibraryName().toString(Common::Path::kNativeSeparator).c_str());
 	} else {
 		if (!_mainEXE->loadFromEXE(getEXEName()))
-			error("Failed to load main EXE '%s'", getEXEName().c_str());
+			error("Failed to load main EXE '%s'", getEXEName().toString(Common::Path::kNativeSeparator).c_str());
 
 		if (_library && !_library->loadFromEXE(getLibraryName()))
-			error("Failed to load library DLL '%s'", getLibraryName().c_str());
+			error("Failed to load library DLL '%s'", getLibraryName().toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	syncSoundSettings();
@@ -198,13 +198,13 @@ Common::String BuriedEngine::getString(uint32 stringID) {
 	return result;
 }
 
-Common::String BuriedEngine::getFilePath(uint32 stringID) {
+Common::Path BuriedEngine::getFilePath(uint32 stringID) {
 	Common::String path = getString(stringID);
-	Common::String output;
 
 	if (path.empty())
-		return output;
+		return Common::Path();
 
+	Common::String output;
 	uint i = 0;
 
 	// The non-demo paths have CD info followed by a backslash.
@@ -229,7 +229,7 @@ Common::String BuriedEngine::getFilePath(uint32 stringID) {
 			output += path[i];
 	}
 
-	return output;
+	return Common::Path(output, '/');
 }
 
 Graphics::WinCursorGroup *BuriedEngine::getCursorGroup(uint32 cursorGroupID) {
@@ -543,7 +543,7 @@ uint32 BuriedEngine::getVersion() {
 	return result;
 }
 
-Common::String BuriedEngine::getFilePath(int timeZone, int environment, int fileOffset) {
+Common::Path BuriedEngine::getFilePath(int timeZone, int environment, int fileOffset) {
 	return getFilePath(computeFileNameResourceID(timeZone, environment, fileOffset));
 }
 
diff --git a/engines/buried/buried.h b/engines/buried/buried.h
index 52296a21774..8a812d38f6e 100644
--- a/engines/buried/buried.h
+++ b/engines/buried/buried.h
@@ -26,6 +26,7 @@
 #include "common/array.h"
 #include "common/list.h"
 #include "common/hashmap.h"
+#include "common/path.h"
 #include "common/str-array.h"
 
 #include "engines/engine.h"
@@ -78,8 +79,8 @@ public:
 	bool isTrueColor() const;
 	bool isWin95() const;
 	bool isCompressed() const;
-	Common::String getEXEName() const;
-	Common::String getLibraryName() const;
+	Common::Path getEXEName() const;
+	Common::Path getLibraryName() const;
 	Common::Language getLanguage() const;
 
 	bool hasFeature(EngineFeature f) const override;
@@ -87,8 +88,8 @@ public:
 
 	// Resources
 	Common::String getString(uint32 stringID);
-	Common::String getFilePath(uint32 stringID);
-	Common::String getFilePath(int timeZone, int environment, int fileOffset);
+	Common::Path getFilePath(uint32 stringID);
+	Common::Path getFilePath(int timeZone, int environment, int fileOffset);
 	Graphics::WinCursorGroup *getCursorGroup(uint32 cursorGroupID);
 	Common::SeekableReadStream *getBitmapStream(uint32 bitmapID);
 	Common::SeekableReadStream *getNavData(uint32 resourceID);
diff --git a/engines/buried/demo/movie_scene.cpp b/engines/buried/demo/movie_scene.cpp
index dc4fe0b2720..a2719a808b2 100644
--- a/engines/buried/demo/movie_scene.cpp
+++ b/engines/buried/demo/movie_scene.cpp
@@ -32,7 +32,7 @@
 
 namespace Buried {
 
-MovieDisplayWindow::MovieDisplayWindow(BuriedEngine *vm, Window *parent, const Common::String &background, const Common::String &movie, int movieLeft, int movieTop)
+MovieDisplayWindow::MovieDisplayWindow(BuriedEngine *vm, Window *parent, const Common::Path &background, const Common::Path &movie, int movieLeft, int movieTop)
 		: Window(vm, parent) {
 	_background = _vm->_gfx->getBitmap(background);
 
@@ -47,7 +47,7 @@ MovieDisplayWindow::MovieDisplayWindow(BuriedEngine *vm, Window *parent, const C
 	_movie = new VideoWindow(_vm, this);
 
 	if (!_movie->openVideo(movie))
-		error("Failed to open movie '%s'", movie.c_str());
+		error("Failed to open movie '%s'", movie.toString(Common::Path::kNativeSeparator).c_str());
 
 	_movie->setWindowPos(nullptr, movieLeft, movieTop, 0, 0, kWindowPosNoSize | kWindowPosNoZOrder);
 	_movie->enableWindow(false);
diff --git a/engines/buried/demo/movie_scene.h b/engines/buried/demo/movie_scene.h
index 76a21c81a65..4c9f4fc8f80 100644
--- a/engines/buried/demo/movie_scene.h
+++ b/engines/buried/demo/movie_scene.h
@@ -35,7 +35,7 @@ namespace Buried {
 
 class MovieDisplayWindow : public Window {
 public:
-	MovieDisplayWindow(BuriedEngine *vm, Window *parent, const Common::String &background, const Common::String &movie, int movieLeft, int movieTop);
+	MovieDisplayWindow(BuriedEngine *vm, Window *parent, const Common::Path &background, const Common::Path &movie, int movieLeft, int movieTop);
 	~MovieDisplayWindow();
 
 	bool showMovieInWindow();
diff --git a/engines/buried/frame_window.cpp b/engines/buried/frame_window.cpp
index 8f41892b185..ad3881ec69b 100644
--- a/engines/buried/frame_window.cpp
+++ b/engines/buried/frame_window.cpp
@@ -180,7 +180,7 @@ bool FrameWindow::returnToMainMenu() {
 	return true;
 }
 
-bool FrameWindow::playMovie(const Common::String &background, const Common::String &movie, int movieLeft, int movieTop) {
+bool FrameWindow::playMovie(const Common::Path &background, const Common::Path &movie, int movieLeft, int movieTop) {
 	_vm->removeMouseMessages(this);
 	_vm->removeMouseMessages(_mainChildWindow);
 
diff --git a/engines/buried/frame_window.h b/engines/buried/frame_window.h
index a2ad6110b7f..f6c1d2cfd1a 100644
--- a/engines/buried/frame_window.h
+++ b/engines/buried/frame_window.h
@@ -40,7 +40,7 @@ public:
 	bool showTitleSequence();
 	bool showMainMenu();
 	bool returnToMainMenu();
-	bool playMovie(const Common::String &background, const Common::String &movie, int movieLeft, int movieTop);
+	bool playMovie(const Common::Path &background, const Common::Path &movie, int movieLeft, int movieTop);
 	bool showClosingScreen();
 	bool showFeaturesScreen();
 	bool startNewGame(bool walkthrough = false, bool introMovie = false);
diff --git a/engines/buried/graphics.cpp b/engines/buried/graphics.cpp
index e8d0d69af8e..34554d0a2da 100644
--- a/engines/buried/graphics.cpp
+++ b/engines/buried/graphics.cpp
@@ -81,7 +81,7 @@ Graphics::Font *GraphicsManager::createFont(int size, bool bold) const {
 }
 
 Graphics::Font *GraphicsManager::createArialFont(int size, bool bold) const {
-	Common::String defaultBaseName = bold ? "arialbd.ttf" : "arial.ttf";
+	const char *defaultBaseName = bold ? "arialbd.ttf" : "arial.ttf";
 
 	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(defaultBaseName);
 
@@ -185,19 +185,19 @@ Graphics::Surface *GraphicsManager::getBitmap(uint32 bitmapID) {
 	return surface;
 }
 
-Graphics::Surface *GraphicsManager::getBitmap(const Common::String &fileName, bool required) {
+Graphics::Surface *GraphicsManager::getBitmap(const Common::Path &fileName, bool required) {
 	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName);
 
 	if (!stream) {
 		if (required)
-			error("Could not find bitmap '%s'", fileName.c_str());
+			error("Could not find bitmap '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return nullptr;
 	}
 
 	Graphics::Surface *surface = getBitmap(stream);
 	if (!surface) {
 		if (required)
-			error("Failed to decode bitmap '%s'", fileName.c_str());
+			error("Failed to decode bitmap '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return nullptr;
 	}
 
diff --git a/engines/buried/graphics.h b/engines/buried/graphics.h
index fb79e248147..2187abb0aab 100644
--- a/engines/buried/graphics.h
+++ b/engines/buried/graphics.h
@@ -83,7 +83,7 @@ public:
 	Cursor setCursor(Cursor newCursor);
 	void toggleCursor(bool show);
 	Graphics::Surface *getBitmap(uint32 bitmapID);
-	Graphics::Surface *getBitmap(const Common::String &fileName, bool required = true);
+	Graphics::Surface *getBitmap(const Common::Path &fileName, bool required = true);
 	uint32 getColor(byte r, byte g, byte b);
 
 	void invalidateRect(const Common::Rect &rect, bool erase = true);
diff --git a/engines/buried/inventory_window.cpp b/engines/buried/inventory_window.cpp
index dbc735a74a7..9232aec37ab 100644
--- a/engines/buried/inventory_window.cpp
+++ b/engines/buried/inventory_window.cpp
@@ -85,7 +85,7 @@ InventoryWindow::InventoryWindow(BuriedEngine *vm, Window *parent) : Window(vm,
 
 	if (_vm->isDemo()) {
 		// The demo uses a video for drag frames
-		Common::String dragFramesFileName;
+		const char *dragFramesFileName;
 		if (_vm->isTrueColor())
 			dragFramesFileName = "COMMON/INVDRAG.BTV";
 		else
diff --git a/engines/buried/metaengine.cpp b/engines/buried/metaengine.cpp
index a4484e2b8dd..043295251c1 100644
--- a/engines/buried/metaengine.cpp
+++ b/engines/buried/metaengine.cpp
@@ -76,11 +76,11 @@ bool BuriedEngine::isCompressed() const {
 	return (_gameDescription->flags & GF_COMPRESSED) != 0;
 }
 
-Common::String BuriedEngine::getEXEName() const {
+Common::Path BuriedEngine::getEXEName() const {
 	return _gameDescription->filesDescriptions[0].fileName;
 }
 
-Common::String BuriedEngine::getLibraryName() const {
+Common::Path BuriedEngine::getLibraryName() const {
 	return _gameDescription->filesDescriptions[1].fileName;
 }
 
diff --git a/engines/buried/scene_view.cpp b/engines/buried/scene_view.cpp
index abc40d9a7ec..984acef979e 100644
--- a/engines/buried/scene_view.cpp
+++ b/engines/buried/scene_view.cpp
@@ -761,7 +761,7 @@ bool SceneViewWindow::timeSuitJump(int destination) {
 	_vm->_sound->timerCallback();
 	jumpMovie.reset(new VideoWindow(_vm, this));
 
-	Common::String fileName;
+	Common::Path fileName;
 	switch (destination) {
 	case 0:
 		fileName = _vm->getFilePath(IDS_MAYAN_JUMP_MOVIE_FILENAME);
@@ -781,7 +781,7 @@ bool SceneViewWindow::timeSuitJump(int destination) {
 	}
 
 	if (!jumpMovie->openVideo(fileName))
-		error("Failed to play movie '%s'", fileName.c_str());
+		error("Failed to play movie '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	jumpMovie->setWindowPos(nullptr, 0, 0, 0, 0, kWindowPosNoSize | kWindowPosNoZOrder | kWindowPosHideWindow);
 
@@ -1046,9 +1046,9 @@ bool SceneViewWindow::videoTransition(const Location &location, DestinationScene
 	// Open the movie
 	Common::ScopedPtr<VideoWindow> animationMovie(new VideoWindow(_vm, this));
 
-	Common::String fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, destinationData.transitionData);
+	Common::Path fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, destinationData.transitionData);
 	if (!animationMovie->openVideo(fileName))
-		error("Failed to open video transition movie '%s'", fileName.c_str());
+		error("Failed to open video transition movie '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (audioStream)
 		_vm->_sound->stop();
@@ -1095,14 +1095,14 @@ bool SceneViewWindow::walkTransition(const Location &location, const Destination
 		newBackground = getStillFrameCopy(navFrame);
 	}
 
-	Common::String walkFileName = _vm->getFilePath(location.timeZone, location.environment, SF_NAVIGATION);
+	Common::Path walkFileName = _vm->getFilePath(location.timeZone, location.environment, SF_NAVIGATION);
 	if (_walkMovieFileName != walkFileName) {
 		delete _walkMovie;
 		_walkMovie = new VideoWindow(_vm, this);
 		_walkMovie->setWindowPos(kWindowPosTop, 0, 0, 0, 0, kWindowPosNoActivate | kWindowPosNoZOrder | kWindowPosNoSize);
 
 		if (!_walkMovie->openVideo(walkFileName))
-			error("Failed to open walk movie '%s'", walkFileName.c_str());
+			error("Failed to open walk movie '%s'", walkFileName.toString(Common::Path::kNativeSeparator).c_str());
 
 		_walkMovieFileName = walkFileName;
 	}
@@ -1323,11 +1323,11 @@ bool SceneViewWindow::slideOutTransition(Graphics::Surface *newBackground, int d
 	return true;
 }
 
-bool SceneViewWindow::changeStillFrameMovie(const Common::String &fileName) {
+bool SceneViewWindow::changeStillFrameMovie(const Common::Path &fileName) {
 	return _stillFrames->open(fileName);
 }
 
-bool SceneViewWindow::changeCycleFrameMovie(const Common::String &fileName) {
+bool SceneViewWindow::changeCycleFrameMovie(const Common::Path &fileName) {
 	// Only continue if cycling is enabled
 	if (!isCyclingEnabled()) {
 		return false;
@@ -1470,9 +1470,9 @@ bool SceneViewWindow::playSynchronousAnimation(int animationID) {
 		return false;
 
 	Common::ScopedPtr<VideoWindow> animationMovie(new VideoWindow(_vm, this));
-	Common::String fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animDatabase[i].fileNameID);
+	Common::Path fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animDatabase[i].fileNameID);
 	if (!animationMovie->openVideo(fileName))
-		error("Failed to open video '%s'", fileName.c_str());
+		error("Failed to open video '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	// Switch to the second audio stream if translation is enabled
 	if (_globalFlags.bcTranslateEnabled == 1 && animDatabase[i].audioStreamCount > 1)
@@ -1521,9 +1521,9 @@ bool SceneViewWindow::playSynchronousAnimationExtern(int animationID) {
 	TempCursorChange cursorChange(kCursorWait);
 
 	Common::ScopedPtr<VideoWindow> animationMovie(new VideoWindow(_vm, this));
-	Common::String fileName = _vm->getFilePath(animationID);
+	Common::Path fileName = _vm->getFilePath(animationID);
 	if (!animationMovie->openVideo(fileName))
-		error("Failed to open video '%s'", fileName.c_str());
+		error("Failed to open video '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (_currentScene && _currentScene->movieCallback(this, animationMovie.get(), animationID, MOVIE_START) == SC_FALSE)
 		return false;
@@ -1578,9 +1578,9 @@ bool SceneViewWindow::playPlacedSynchronousAnimation(int animationID, int left,
 		return false;
 
 	Common::ScopedPtr<VideoWindow> animationMovie(new VideoWindow(_vm, this));
-	Common::String fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animDatabase[i].fileNameID);
+	Common::Path fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animDatabase[i].fileNameID);
 	if (!animationMovie->openVideo(fileName))
-		error("Failed to open video '%s'", fileName.c_str());
+		error("Failed to open video '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	animationMovie->setWindowPos(kWindowPosTopMost, left, top, 0, 0, kWindowPosNoSize | kWindowPosNoActivate | kWindowPosNoZOrder);
 
@@ -1648,9 +1648,9 @@ bool SceneViewWindow::playClippedSynchronousAnimation(int animationID, int left,
 		return false;
 
 	Common::ScopedPtr<VideoWindow> animationMovie(new VideoWindow(_vm, this));
-	Common::String fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animDatabase[i].fileNameID);
+	Common::Path fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animDatabase[i].fileNameID);
 	if (!animationMovie->openVideo(fileName))
-		error("Failed to open video '%s'", fileName.c_str());
+		error("Failed to open video '%s'", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	animationMovie->setWindowPos(kWindowPosTopMost, left, top, right - left, bottom - top, kWindowPosNoActivate | kWindowPosNoZOrder);
 
@@ -1800,7 +1800,7 @@ bool SceneViewWindow::startPlacedAsynchronousAnimation(int left, int top, int wi
 	if (!animData)
 		return false;
 
-	Common::String fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animData->fileNameID);
+	Common::Path fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, animData->fileNameID);
 
 	if (fileName != _asyncMovieFileName) {
 		_asyncMovieFileName.clear();
@@ -1845,7 +1845,7 @@ bool SceneViewWindow::startPlacedAsynchronousAnimation(int left, int top, int wi
 		_walkMovieFileName.clear();
 	}
 
-	Common::String fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, fileNameID);
+	Common::Path fileName = _vm->getFilePath(_currentScene->_staticData.location.timeZone, _currentScene->_staticData.location.environment, fileNameID);
 
 	if (fileName != _asyncMovieFileName) {
 		_asyncMovieFileName.clear();
@@ -1890,7 +1890,7 @@ bool SceneViewWindow::startPlacedAsynchronousAnimationExtern(int left, int top,
 		_walkMovieFileName.clear();
 	}
 
-	Common::String fileName = _vm->getFilePath(fileNameID);
+	Common::Path fileName = _vm->getFilePath(fileNameID);
 
 	if (fileName != _asyncMovieFileName) {
 		_asyncMovieFileName.clear();
@@ -2073,12 +2073,14 @@ bool SceneViewWindow::playAICommentFromData(const AIComment &commentData) {
 
 	commentFileName += Common::String::format("%02d.BTA", commentData.commentID);
 
+	Common::Path commentPath(commentFileName, '/');
+
 	Cursor currentCursor = _vm->_gfx->setCursor(kCursorWait);
-	bool playedSuccessfully = _vm->_sound->playAsynchronousAIComment(commentFileName);
+	bool playedSuccessfully = _vm->_sound->playAsynchronousAIComment(commentPath);
 	_vm->_gfx->setCursor(currentCursor);
 
 	if (playedSuccessfully) {
-		_lastAICommentFileName = commentFileName;
+		_lastAICommentFileName = commentPath;
 
 		byte flagValue = 0;
 		if (commentData.commentFlags & AI_STATUS_FLAG_NON_BASE_DERIVED)
diff --git a/engines/buried/scene_view.h b/engines/buried/scene_view.h
index 5a13d5fe5b0..037f36961f7 100644
--- a/engines/buried/scene_view.h
+++ b/engines/buried/scene_view.h
@@ -83,8 +83,8 @@ public:
 	bool slideInTransition(Graphics::Surface *newBackground, int direction, int stripSize, int totalTime);
 	bool slideOutTransition(Graphics::Surface *newBackground, int direction, int stripSize, int totalTime);
 
-	bool changeStillFrameMovie(const Common::String &fileName = "");
-	bool changeCycleFrameMovie(const Common::String &fileName = "");
+	bool changeStillFrameMovie(const Common::Path &fileName = Common::Path());
+	bool changeCycleFrameMovie(const Common::Path &fileName = Common::Path());
 
 	Graphics::Surface *getStillFrameCopy(int frameIndex);
 	const Graphics::Surface *getStillFrame(int frameIndex);
@@ -169,7 +169,7 @@ private:
 	GlobalFlags _globalFlags;
 	VideoWindow *_walkMovie;
 
-	Common::String _walkMovieFileName;
+	Common::Path _walkMovieFileName;
 
 	AVIFrames *_stillFrames;
 	AVIFrames *_cycleFrames;
@@ -187,12 +187,12 @@ private:
 	bool _burnedLetterDisplayed;
 
 	VideoWindow *_asyncMovie;
-	Common::String _asyncMovieFileName;
+	Common::Path _asyncMovieFileName;
 	int _asyncMovieStartFrame;
 	int _asyncMovieFrameCount;
 	bool _loopAsyncMovie;
 
-	Common::String _lastAICommentFileName;
+	Common::Path _lastAICommentFileName;
 
 	// Special sound handling for the demo
 	uint _demoSoundTimer;
diff --git a/engines/buried/sound.cpp b/engines/buried/sound.cpp
index 834e7bc5eac..86ec6362c59 100644
--- a/engines/buried/sound.cpp
+++ b/engines/buried/sound.cpp
@@ -80,7 +80,7 @@ void SoundManager::pause(bool shouldPause) {
 		_soundData[i]->pause(shouldPause);
 }
 
-bool SoundManager::setAmbientSound(const Common::String &fileName, bool fade, byte finalVolumeLevel) {
+bool SoundManager::setAmbientSound(const Common::Path &fileName, bool fade, byte finalVolumeLevel) {
 	// Determine which of the two ambient tracks to use
 	int newAmbientTrack = (_lastAmbient == 0) ? 1 : 0;
 
@@ -221,7 +221,7 @@ bool SoundManager::isAmbientSoundPlaying() {
 	return _soundData[kAmbientIndexBase + _lastAmbient]->_handle != nullptr;
 }
 
-bool SoundManager::setSecondaryAmbientSound(const Common::String &fileName, bool fade, byte finalVolumeLevel) {
+bool SoundManager::setSecondaryAmbientSound(const Common::Path &fileName, bool fade, byte finalVolumeLevel) {
 	if (fileName.empty())
 		return false;
 
@@ -337,7 +337,7 @@ bool SoundManager::restartSecondaryAmbientSound() {
 	return true;
 }
 
-bool SoundManager::playSynchronousAIComment(const Common::String &fileName) {
+bool SoundManager::playSynchronousAIComment(const Common::Path &fileName) {
 	if (_paused)
 		return false;
 
@@ -363,7 +363,7 @@ bool SoundManager::playSynchronousAIComment(const Common::String &fileName) {
 	return true;
 }
 
-bool SoundManager::playAsynchronousAIComment(const Common::String &fileName) {
+bool SoundManager::playAsynchronousAIComment(const Common::Path &fileName) {
 	if (_paused)
 		return false;
 
@@ -393,7 +393,7 @@ void SoundManager::stopAsynchronousAIComment() {
 	}
 }
 
-int SoundManager::playSoundEffect(const Common::String &fileName, int volume, bool loop, bool oneShot) {
+int SoundManager::playSoundEffect(const Common::Path &fileName, int volume, bool loop, bool oneShot) {
 	if (fileName.empty())
 		return -1;
 
@@ -431,7 +431,7 @@ int SoundManager::playSoundEffect(const Common::String &fileName, int volume, bo
 	return effectChannel;
 }
 
-bool SoundManager::playSynchronousSoundEffect(const Common::String &fileName, int volume) {
+bool SoundManager::playSynchronousSoundEffect(const Common::Path &fileName, int volume) {
 	// Reset the cursor
 	Cursor oldCursor = _vm->_gfx->setCursor(kCursorWait);
 	g_system->updateScreen();
@@ -528,7 +528,7 @@ bool SoundManager::adjustSoundEffectSoundVolume(int effectID, byte newVolumeLeve
 	return true;
 }
 
-bool SoundManager::playInterfaceSound(const Common::String &fileName) {
+bool SoundManager::playInterfaceSound(const Common::Path &fileName) {
 	if (_paused)
 		return false;
 
@@ -722,7 +722,7 @@ SoundManager::Sound::~Sound() {
 	delete _soundData;
 }
 
-bool SoundManager::Sound::load(const Common::String &fileName) {
+bool SoundManager::Sound::load(const Common::Path &fileName) {
 	if (fileName.empty())
 		return false;
 
diff --git a/engines/buried/sound.h b/engines/buried/sound.h
index bfcd6d1d86b..23bda0b2f66 100644
--- a/engines/buried/sound.h
+++ b/engines/buried/sound.h
@@ -47,30 +47,30 @@ public:
 	void shutDown();
 
 	// AMBIENT SOUND CHANNEL FUNCTIONS
-	bool setAmbientSound(const Common::String &fileName = "", bool fade = false, byte finalVolumeLevel = 64);
+	bool setAmbientSound(const Common::Path &fileName = Common::Path(), bool fade = false, byte finalVolumeLevel = 64);
 	bool adjustAmbientSoundVolume(byte newVolumeLevel, bool fade, byte steps, uint32 fadeLength);
 	bool isAmbientSoundPlaying();
 
-	bool setSecondaryAmbientSound(const Common::String &fileName = "", bool fade = false, byte finalVolumeLevel = 64);
+	bool setSecondaryAmbientSound(const Common::Path &fileName = Common::Path(), bool fade = false, byte finalVolumeLevel = 64);
 	bool adjustSecondaryAmbientSoundVolume(byte newVolumeLevel, bool fade, byte steps, uint32 fadeLength);
 	uint32 getSecondaryAmbientPosition();
 	bool restartSecondaryAmbientSound();
 
 	// AI SOUND CHANNEL FUNCTIONS
-	bool playSynchronousAIComment(const Common::String &fileName);
-	bool playAsynchronousAIComment(const Common::String &fileName);
+	bool playSynchronousAIComment(const Common::Path &fileName);
+	bool playAsynchronousAIComment(const Common::Path &fileName);
 	bool isAsynchronousAICommentPlaying();
 	void stopAsynchronousAIComment();
 
 	// SOUND EFFECTS FUNCTIONS
-	int playSoundEffect(const Common::String &fileName, int volume = 127, bool loop = false, bool oneShot = true);
-	bool playSynchronousSoundEffect(const Common::String &fileName, int volume = 127);
+	int playSoundEffect(const Common::Path &fileName, int volume = 127, bool loop = false, bool oneShot = true);
+	bool playSynchronousSoundEffect(const Common::Path &fileName, int volume = 127);
 	bool stopSoundEffect(int effectID);
 	bool isSoundEffectPlaying (int effectID);
 	bool adjustSoundEffectSoundVolume(int effectID, byte newVolumeLevel, bool fade, byte steps, uint32 fadeLength);
 
 	// Interface sound functions
-	bool playInterfaceSound(const Common::String &fileName);
+	bool playInterfaceSound(const Common::Path &fileName);
 	bool stopInterfaceSound();
 	bool isInterfaceSoundPlaying();
 
@@ -115,7 +115,7 @@ private:
 		Sound();
 		~Sound();
 
-		bool load(const Common::String &fileName);
+		bool load(const Common::Path &fileName);
 		bool start();
 		bool isPlaying() const;
 		bool stop();
@@ -145,11 +145,11 @@ private:
 	bool _paused;
 
 	int _fileIDFootsteps;
-	Common::String _ambientFileNames[2];
+	Common::Path _ambientFileNames[2];
 	int _lastAmbient;
-	Common::String _effectsFileNames[2];
-	Common::String _interfaceFileName;
-	Common::String _arthurFileName;
+	Common::Path _effectsFileNames[2];
+	Common::Path _interfaceFileName;
+	Common::Path _arthurFileName;
 };
 
 } // End of namespace Buried
diff --git a/engines/buried/video_window.cpp b/engines/buried/video_window.cpp
index 54ea0c2fb3d..d26969ddeea 100644
--- a/engines/buried/video_window.cpp
+++ b/engines/buried/video_window.cpp
@@ -100,7 +100,7 @@ int VideoWindow::getFrameCount() {
 	return 0;
 }
 
-bool VideoWindow::openVideo(const Common::String &fileName) {
+bool VideoWindow::openVideo(const Common::Path &fileName) {
 	closeVideo();
 
 	_video = new Video::AVIDecoder();
diff --git a/engines/buried/video_window.h b/engines/buried/video_window.h
index 9fa5a860f5e..6a006800d0f 100644
--- a/engines/buried/video_window.h
+++ b/engines/buried/video_window.h
@@ -55,7 +55,7 @@ public:
 	void setDestRect(const Common::Rect &dstRect); // MCIWndPutDest
 	void setAudioTrack(int track); // MCIWndSendString + "setaudio stream to %d"
 
-	bool openVideo(const Common::String &fileName); // MCIWndOpen
+	bool openVideo(const Common::Path &fileName); // MCIWndOpen
 	void closeVideo(); // MCIWndClose
 
 	enum Mode {


Commit: 430d0dedd2620e51ed49b395856e3f57a64d02e2
    https://github.com/scummvm/scummvm/commit/430d0dedd2620e51ed49b395856e3f57a64d02e2
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
CHAMBER: Migrate engine to Path

Changed paths:
    engines/chamber/chamber.cpp


diff --git a/engines/chamber/chamber.cpp b/engines/chamber/chamber.cpp
index 8c8fa04e744..266657611b3 100644
--- a/engines/chamber/chamber.cpp
+++ b/engines/chamber/chamber.cpp
@@ -42,7 +42,7 @@ ChamberEngine::ChamberEngine(OSystem *syst, const ADGameDescription *desc)
 	g_vm = this;
 	_gameDescription = desc;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	// Don't forget to register your random source
 	_rnd = new Common::RandomSource("chamber");


Commit: e9e09319e46cf1639de001b9e23318fc5de65983
    https://github.com/scummvm/scummvm/commit/e9e09319e46cf1639de001b9e23318fc5de65983
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
CHEWY: Migrate engine to Path

Changed paths:
    engines/chewy/chewy.cpp
    engines/chewy/detail.cpp
    engines/chewy/detail.h
    engines/chewy/font.cpp
    engines/chewy/font.h
    engines/chewy/resource.cpp
    engines/chewy/resource.h


diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 00d125059eb..91dd6ed661b 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -45,7 +45,7 @@ ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
 
 	g_engine = this;
 	g_screen = nullptr;
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	SearchMan.addSubDirectoryMatching(gameDataDir, "back");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "cut");
diff --git a/engines/chewy/detail.cpp b/engines/chewy/detail.cpp
index 2551a4ec473..e16e0a99a3f 100644
--- a/engines/chewy/detail.cpp
+++ b/engines/chewy/detail.cpp
@@ -195,7 +195,7 @@ void Detail::load_rdi(const char *fname_, int16 room_nr) {
 }
 
 void Detail::load_rdi_taf(const char *filename, int16 load_flag) {
-	if (_tafName.compareToIgnoreCase(filename)) {
+	if (!_tafName.equalsIgnoreCase(filename)) {
 		if (_rdi.dptr) {
 			if (_fullTaf) {
 				free(_rdi.dptr);
@@ -224,7 +224,7 @@ void Detail::del_dptr() {
 		else {
 			del_taf_tbl(_rdi.dptr);
 			_rdi.dptr = nullptr;
-			_tafName = "";
+			_tafName.clear();
 		}
 		_rdi.dptr = nullptr;
 	}
diff --git a/engines/chewy/detail.h b/engines/chewy/detail.h
index 11ec7bba2f3..57f4665a50e 100644
--- a/engines/chewy/detail.h
+++ b/engines/chewy/detail.h
@@ -229,7 +229,7 @@ private:
 	int16 _globalDelay = 0;
 	bool _aniFreezeflag = false;
 	bool _fullTaf = false;
-	Common::String _tafName;
+	Common::Path _tafName;
 	byte *_tafLoadBuffer = nullptr;
 	int16 _directTafAni = 0;
 };
diff --git a/engines/chewy/font.cpp b/engines/chewy/font.cpp
index 320cc5999f7..d2dc91ed13d 100644
--- a/engines/chewy/font.cpp
+++ b/engines/chewy/font.cpp
@@ -25,7 +25,7 @@
 
 namespace Chewy {
 
-ChewyFont::ChewyFont(Common::String filename) {
+ChewyFont::ChewyFont(const Common::Path &filename) {
 	const uint32 headerFont = MKTAG('T', 'F', 'F', '\0');
 	Common::File stream;
 
@@ -34,7 +34,7 @@ ChewyFont::ChewyFont(Common::String filename) {
 	uint32 header = stream.readUint32BE();
 
 	if (header != headerFont)
-		error("Invalid resource - %s", filename.c_str());
+		error("Invalid resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	stream.skip(4);	// total memory
 	_count = stream.readUint16LE();
diff --git a/engines/chewy/font.h b/engines/chewy/font.h
index 7edf91e8e30..6d2e72db1e7 100644
--- a/engines/chewy/font.h
+++ b/engines/chewy/font.h
@@ -29,7 +29,7 @@ namespace Chewy {
 
 class ChewyFont {
 public:
-	ChewyFont(Common::String filename);
+	ChewyFont(const Common::Path &filename);
 	virtual ~ChewyFont();
 
 	Graphics::Surface *getLine(const Common::String &texts);
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 087be70e7d1..ac8d2242bb2 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -31,24 +31,27 @@
 
 namespace Chewy {
 
-Resource::Resource(Common::String filename) {
+Resource::Resource(const Common::Path &filename) {
 	const uint32 headerGeneric = MKTAG('N', 'G', 'S', '\0');
 	const uint32 headerTxtDec  = MKTAG('T', 'C', 'F', '\0');
 	const uint32 headerTxtEnc  = MKTAG('T', 'C', 'F', '\1');
 	const uint32 headerSprite  = MKTAG('T', 'A', 'F', '\0');
 	const uint32 headerBarrier = MKTAG('G', 'E', 'P', '\0');
 
-	filename.toLowercase();
+
 	_stream.open(filename);
 
+	Common::String basename = filename.baseName();
+	basename.toLowercase();
+
 	const uint32 header = _stream.readUint32BE();
 	const bool isText = (header == headerTxtDec || header == headerTxtEnc);
 	const bool isSprite = (header == headerSprite);
-	//const bool isSpeech = filename.contains("speech.tvp");
+	//const bool isSpeech = basename.contains("speech.tvp");
 	const bool isBarrier = (header == headerBarrier);
 
 	if (header != headerGeneric && !isSprite && !isText && !isBarrier)
-		error("Invalid resource - %s", filename.c_str());
+		error("Invalid resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (isText) {
 		_resType = kResourceTCF;
@@ -64,7 +67,7 @@ Resource::Resource(Common::String filename) {
 		_encrypted = false;
 	}
 
-	if (filename.contains("atds.tap"))
+	if (basename.contains("atds.tap"))
 		_encrypted = true;
 
 	_chunkCount = _stream.readUint16LE();
@@ -162,7 +165,7 @@ uint8 *Resource::getChunkData(uint num) {
 	return data;
 }
 
-void Resource::initSprite(Common::String filename) {
+void Resource::initSprite(const Common::Path &filename) {
 	_resType = kResourceTAF;
 	_encrypted = false;
 	/*screenMode = */_stream.readUint16LE();
@@ -177,7 +180,7 @@ void Resource::initSprite(Common::String filename) {
 		_stream.skip(1);
 
 	if ((int32)nextSpriteOffset != _stream.pos())
-		error("Invalid sprite resource - %s", filename.c_str());
+		error("Invalid sprite resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	for (uint i = 0; i < _chunkCount; i++) {
 		Chunk cur;
@@ -191,7 +194,7 @@ void Resource::initSprite(Common::String filename) {
 		_stream.skip(1);
 
 		if ((int32)spriteImageOffset != _stream.pos())
-			error("Invalid sprite resource - %s", filename.c_str());
+			error("Invalid sprite resource - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 		cur.size = nextSpriteOffset - cur.pos - 15;
 
@@ -199,7 +202,7 @@ void Resource::initSprite(Common::String filename) {
 		_chunkList.push_back(cur);
 
 		if (_stream.err())
-			error("Sprite stream error - %s", filename.c_str());
+			error("Sprite stream error - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	_spriteCorrectionsTable = new uint16[_chunkCount * 2];
@@ -340,7 +343,7 @@ Common::SeekableReadStream *VideoResource::getVideoStream(uint num) {
 	return new Common::SeekableSubReadStream(&_stream, chunk->pos, chunk->pos + chunk->size);
 }
 
-DialogResource::DialogResource(Common::String filename) : Resource(filename) {
+DialogResource::DialogResource(const Common::Path &filename) : Resource(filename) {
 	_dialogBuffer = new byte[_stream.size()];
 	_stream.seek(0, SEEK_SET);
 	_dialogStream = new Common::MemorySeekableReadWriteStream(_dialogBuffer, _stream.size());
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 51cae9b405a..104108beff5 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -130,7 +130,7 @@ typedef Common::Array<TBFChunk> TBFChunkList;
 
 class Resource {
 public:
-	Resource(Common::String filename);
+	Resource(const Common::Path &filename);
 	virtual ~Resource();
 
 	ResourceType getType() const {
@@ -145,7 +145,7 @@ public:
 	virtual uint8 *getChunkData(uint num);
 
 protected:
-	void initSprite(Common::String filename);
+	void initSprite(const Common::Path &filename);
 	void unpackRLE(uint8 *buffer, uint32 compressedSize, uint32 uncompressedSize);
 	void decrypt(uint8 *data, uint32 size);
 
@@ -165,7 +165,7 @@ protected:
 
 class SpriteResource : public Resource {
 public:
-	SpriteResource(Common::String filename) : Resource(filename) {}
+	SpriteResource(const Common::Path &filename) : Resource(filename) {}
 	virtual ~SpriteResource() {}
 
 	TAFChunk *getSprite(uint num);
@@ -178,7 +178,7 @@ public:
 
 class BackgroundResource : public Resource {
 public:
-	BackgroundResource(Common::String filename) : Resource(filename) {}
+	BackgroundResource(const Common::Path &filename) : Resource(filename) {}
 	virtual ~BackgroundResource() {}
 
 	TBFChunk *getImage(uint num, bool fixPalette);
@@ -186,7 +186,7 @@ public:
 
 class SoundResource : public Resource {
 public:
-	SoundResource(Common::String filename) : Resource(filename) {}
+	SoundResource(const Common::Path &filename) : Resource(filename) {}
 	virtual ~SoundResource() {}
 
 	SoundChunk *getSound(uint num);
@@ -194,7 +194,7 @@ public:
 
 class VideoResource : public Resource {
 public:
-	VideoResource(Common::String filename) : Resource(filename) {}
+	VideoResource(const Common::Path &filename) : Resource(filename) {}
 	virtual ~VideoResource() {}
 
 	VideoChunk *getVideoHeader(uint num);
@@ -203,7 +203,7 @@ public:
 
 class DialogResource : public Resource {
 public:
-	DialogResource(Common::String filename);
+	DialogResource(const Common::Path &filename);
 	virtual ~DialogResource();
 
 	DialogChunk *getDialog(uint dialog, uint block);
@@ -228,7 +228,7 @@ private:
 
 class BarrierResource : public Resource {
 public:
-	BarrierResource(Common::String filename) : Resource(filename) {}
+	BarrierResource(const Common::Path &filename) : Resource(filename) {}
 	virtual ~BarrierResource() {}
 
 	void init(int16 room, int16 bgWidth, int16 bgHeight);


Commit: f3c7cd639380578ed520fa2498c575f32ff8df42
    https://github.com/scummvm/scummvm/commit/f3c7cd639380578ed520fa2498c575f32ff8df42
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
CINE: Migrate engine to Path

Changed paths:
    engines/cine/part.cpp


diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index d38cf513685..44f6fe680f7 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -363,7 +363,7 @@ void dumpBundle(const char *fileName) {
 		debug(0, "%s", g_cine->_partBuffer[i].partName);
 
 		Common::DumpFile out;
-		if (out.open(Common::String("dumps/") + g_cine->_partBuffer[i].partName)) {
+		if (out.open(Common::Path("dumps/").appendInPlace(g_cine->_partBuffer[i].partName))) {
 			out.write(data, g_cine->_partBuffer[i].unpackedSize);
 			out.close();
 		}


Commit: bbc4d51fc432c9d6c1ba77eb7c46be3dd69a181d
    https://github.com/scummvm/scummvm/commit/bbc4d51fc432c9d6c1ba77eb7c46be3dd69a181d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMPOSER: Migrate engine to Path

Changed paths:
    engines/composer/composer.cpp
    engines/composer/composer.h
    engines/composer/resource.cpp
    engines/composer/resource.h
    engines/composer/scripting.cpp


diff --git a/engines/composer/composer.cpp b/engines/composer/composer.cpp
index 337847aa8bd..12ebb355f64 100644
--- a/engines/composer/composer.cpp
+++ b/engines/composer/composer.cpp
@@ -94,7 +94,7 @@ Common::Error ComposerEngine::run() {
 	}
 
 	if (getPlatform() == Common::kPlatformMacintosh) {
-		const Common::FSNode gameDataDir(ConfMan.get("path"));
+		const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 		if (gameId == "sleepingcub")
 			SearchMan.addSubDirectoryMatching(gameDataDir, "sleepcub");
 		if (gameId == "princess")
@@ -348,14 +348,14 @@ Common::String ComposerEngine::getStringFromConfig(const Common::String &section
 	return value;
 }
 
-Common::String ComposerEngine::getFilename(const Common::String &section, uint id) {
+Common::Path ComposerEngine::getFilename(const Common::String &section, uint id) {
 	Common::String key = Common::String::format("%d", id);
 	Common::String filename = getStringFromConfig(section, key);
 
 	return mangleFilename(filename);
 }
 
-Common::String ComposerEngine::mangleFilename(Common::String filename) {
+Common::Path ComposerEngine::mangleFilename(Common::String filename) {
 	while (filename.size() && (filename[0] == '~' || filename[0] == ':' || filename[0] == '\\'))
 		filename = filename.c_str() + 1;
 
@@ -380,7 +380,7 @@ Common::String ComposerEngine::mangleFilename(Common::String filename) {
 		else
 			outFilename += filename[i];
 	}
-	return outFilename;
+	return Common::Path(outFilename, '/');
 }
 
 void ComposerEngine::loadLibrary(uint id) {
@@ -395,9 +395,10 @@ void ComposerEngine::loadLibrary(uint id) {
 		unloadLibrary(library->_id);
 	}
 
-	Common::String filename;
+	Common::Path path;
 	Common::String oldGroup = _bookGroup;
 	if (getGameType() == GType_ComposerV1) {
+		Common::String filename;
 		if (getPlatform() == Common::kPlatformMacintosh) {
 			if (!id || _bookGroup.empty())
 				filename = getStringFromConfig("splash.rsc", "100");
@@ -410,7 +411,7 @@ void ComposerEngine::loadLibrary(uint id) {
 			else
 				filename = getStringFromConfig(_bookGroup, Common::String::format("%d", id));
 		}
-		filename = mangleFilename(filename);
+		path = mangleFilename(filename);
 
 		// bookGroup is the basename of the path.
 		// TODO: tidy this up.
@@ -432,7 +433,7 @@ void ComposerEngine::loadLibrary(uint id) {
 	} else {
 		if (!id)
 			id = atoi(getStringFromConfig("Common", "StartUp").c_str());
-		filename = getFilename("Libs", id);
+		path = getFilename("Libs", id);
 	}
 
 	Library library;
@@ -440,8 +441,8 @@ void ComposerEngine::loadLibrary(uint id) {
 	library._id = id;
 	library._group = oldGroup;
 	library._archive = new ComposerArchive();
-	if (!library._archive->openFile(filename))
-		error("failed to open '%s'", filename.c_str());
+	if (!library._archive->openFile(path))
+		error("failed to open '%s'", path.toString(Common::Path::kNativeSeparator).c_str());
 	_libraries.push_front(library);
 
 	Library &newLib = _libraries.front();
diff --git a/engines/composer/composer.h b/engines/composer/composer.h
index 22e86a734fc..34db78d4e80 100644
--- a/engines/composer/composer.h
+++ b/engines/composer/composer.h
@@ -219,8 +219,8 @@ private:
 
 	Common::String getSaveStateName(int slot) const override;
 	Common::String getStringFromConfig(const Common::String &section, const Common::String &key);
-	Common::String getFilename(const Common::String &section, uint id);
-	Common::String mangleFilename(Common::String filename);
+	Common::Path getFilename(const Common::String &section, uint id);
+	Common::Path mangleFilename(Common::String filename);
 	void loadLibrary(uint id);
 	void unloadLibrary(uint id);
 
diff --git a/engines/composer/resource.cpp b/engines/composer/resource.cpp
index cb97f0614bc..d3890b83710 100644
--- a/engines/composer/resource.cpp
+++ b/engines/composer/resource.cpp
@@ -41,7 +41,7 @@ Archive::~Archive() {
 	close();
 }
 
-bool Archive::openFile(const Common::String &fileName) {
+bool Archive::openFile(const Common::Path &fileName) {
 	Common::SeekableReadStream *file
 		= Common::MacResManager::openFileOrDataFork(fileName);
 
diff --git a/engines/composer/resource.h b/engines/composer/resource.h
index b9a1d02426c..d6d9e7be9f9 100644
--- a/engines/composer/resource.h
+++ b/engines/composer/resource.h
@@ -54,7 +54,7 @@ public:
 	Archive();
 	virtual ~Archive();
 
-	bool openFile(const Common::String &fileName);
+	bool openFile(const Common::Path &fileName);
 	virtual bool openStream(Common::SeekableReadStream *stream) = 0;
 	void close();
 
diff --git a/engines/composer/scripting.cpp b/engines/composer/scripting.cpp
index 4f79da6f3e1..36db4308f81 100644
--- a/engines/composer/scripting.cpp
+++ b/engines/composer/scripting.cpp
@@ -616,9 +616,10 @@ int16 ComposerEngine::scriptFuncCall(uint16 id, int16 param1, int16 param2, int1
 		if (!stream) {
 			if (!_bookIni.hasKey(Common::String::format("%d", param1), "Data"))
 				return 0;
-			filename = getFilename("Data", param1);
+			Common::Path path = getFilename("Data", param1);
 			Common::SeekableReadStream *file =
-				Common::MacResManager::openFileOrDataFork(filename);
+				Common::MacResManager::openFileOrDataFork(path);
+			filename = path.toString(Common::Path::kNativeSeparator);
 			if (!file)
 				error("couldn't open '%s' to get vars id '%d'", filename.c_str(), param1);
 			stream = file;
@@ -684,14 +685,14 @@ int16 ComposerEngine::scriptFuncCall(uint16 id, int16 param1, int16 param2, int1
 	case kFuncLoadData:
 		debug(3, "kFuncLoadData(%d, %d, %d)", param1, param2, param3);
 		{
-		Common::String filename = getFilename("Data", param1);
+		Common::Path filename = getFilename("Data", param1);
 		Common::File *file = new Common::File();
 		if (!file->open(filename))
-			error("couldn't open '%s' to get data id '%d'", filename.c_str(), param1);
+			error("couldn't open '%s' to get data id '%d'", filename.toString(Common::Path::kNativeSeparator).c_str(), param1);
 		if (param3 == 0)
 			param3 = 1000;
 		if (param2 < 0 || param3 < 0 || param2 + param3 > 1000)
-			error("can't read %d entries into %d from file '%s' for data id '%d'", param3, param2, filename.c_str(), param1);
+			error("can't read %d entries into %d from file '%s' for data id '%d'", param3, param2, filename.toString(Common::Path::kNativeSeparator).c_str(), param1);
 		for (uint i = 0; i < (uint)param3; i++) {
 			if (file->pos() + 1 > file->size())
 				break;


Commit: 724ccbd1c6dee4061680f45239968b81cc0f31ab
    https://github.com/scummvm/scummvm/commit/724ccbd1c6dee4061680f45239968b81cc0f31ab
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
CRAB: Migrate engine to Path

Changed paths:
    engines/crab/GameParam.cpp
    engines/crab/GameParam.h
    engines/crab/LoadingScreen.cpp
    engines/crab/TMX/TMXLayer.cpp
    engines/crab/TMX/TMXLayer.h
    engines/crab/TMX/TMXMap.cpp
    engines/crab/TMX/TMXMap.h
    engines/crab/TMX/TMXTileSet.cpp
    engines/crab/TMX/TMXTileSet.h
    engines/crab/XMLDoc.cpp
    engines/crab/XMLDoc.h
    engines/crab/animation/animset.cpp
    engines/crab/animation/animset.h
    engines/crab/animation/sprite.cpp
    engines/crab/animation/sprite.h
    engines/crab/app.cpp
    engines/crab/app.h
    engines/crab/crab.cpp
    engines/crab/event/EventSeqGroup.cpp
    engines/crab/event/EventSeqGroup.h
    engines/crab/event/EventSequence.cpp
    engines/crab/event/EventSequence.h
    engines/crab/event/GameEventInfo.cpp
    engines/crab/event/GameEventInfo.h
    engines/crab/event/eventstore.cpp
    engines/crab/event/eventstore.h
    engines/crab/event/gameeventmanager.cpp
    engines/crab/filesystem.cpp
    engines/crab/filesystem.h
    engines/crab/game.cpp
    engines/crab/game.h
    engines/crab/image/Image.cpp
    engines/crab/image/Image.h
    engines/crab/image/ImageManager.cpp
    engines/crab/image/ImageManager.h
    engines/crab/level/level.h
    engines/crab/level/level_load.cpp
    engines/crab/loaders.cpp
    engines/crab/loaders.h
    engines/crab/music/MusicManager.cpp
    engines/crab/music/musicparam.h
    engines/crab/stat/StatTemplate.cpp
    engines/crab/stat/StatTemplate.h
    engines/crab/text/color.cpp
    engines/crab/text/color.h
    engines/crab/ui/CreditScreen.cpp
    engines/crab/ui/CreditScreen.h
    engines/crab/ui/DevConsole.cpp
    engines/crab/ui/DevConsole.h
    engines/crab/ui/FileData.cpp
    engines/crab/ui/FileData.h
    engines/crab/ui/FileMenu.h
    engines/crab/ui/Inventory.cpp
    engines/crab/ui/Inventory.h
    engines/crab/ui/MapData.cpp
    engines/crab/ui/MapData.h
    engines/crab/ui/ModMenu.cpp
    engines/crab/ui/ModMenu.h
    engines/crab/ui/OptionMenu.cpp
    engines/crab/ui/OptionMenu.h
    engines/crab/ui/PersonScreen.cpp
    engines/crab/ui/PersonScreen.h
    engines/crab/ui/ReplyMenu.cpp
    engines/crab/ui/ReplyMenu.h
    engines/crab/ui/SlideShow.cpp
    engines/crab/ui/SlideShow.h
    engines/crab/ui/hud.cpp
    engines/crab/ui/hud.h
    engines/crab/ui/journal.cpp
    engines/crab/ui/journal.h
    engines/crab/ui/map.cpp
    engines/crab/ui/map.h


diff --git a/engines/crab/GameParam.cpp b/engines/crab/GameParam.cpp
index 7d06163c2ea..50e0afb187b 100644
--- a/engines/crab/GameParam.cpp
+++ b/engines/crab/GameParam.cpp
@@ -57,7 +57,7 @@ FilePaths::FilePaths() : _common("res/levels/common.xml"),
 	_appdata = "./";
 }
 
-void FilePaths::loadLevel(const Common::String &filename) {
+void FilePaths::loadLevel(const Common::Path &filename) {
 	_level.clear();
 	XMLDoc lev_list(filename);
 	if (lev_list.ready()) {
@@ -75,7 +75,7 @@ void FilePaths::loadLevel(const Common::String &filename) {
 	}
 }
 
-void FilePaths::load(const Common::String &filename) {
+void FilePaths::load(const Common::Path &filename) {
 	XMLDoc settings(filename);
 	if (settings.ready()) {
 		rapidxml::xml_node<char> *node = settings.doc()->first_node("paths");
@@ -108,27 +108,27 @@ void FilePaths::load(const Common::String &filename) {
 
 			if (nodeValid("mod", node)) {
 				rapidxml::xml_node<char> *modnode = node->first_node("mod");
-				loadStr(_modPath, "path", modnode);
+				loadPath(_modPath, "path", modnode);
+				loadPath(_modCur, "cur", modnode);
 				loadStr(_modExt, "ext", modnode);
-				loadStr(_modCur, "cur", modnode);
 			}
 
 			if (nodeValid("main_menu", node)) {
 				rapidxml::xml_node<char> *menunode = node->first_node("main_menu");
-				loadStr(_mainmenuL, "l", menunode);
-				loadStr(_mainmenuR, "r", menunode);
+				loadPath(_mainmenuL, "l", menunode);
+				loadPath(_mainmenuR, "r", menunode);
 				_currentR = _mainmenuR;
 			}
 
 			if (nodeValid("sound", node)) {
 				rapidxml::xml_node<char> *soundnode = node->first_node("sound");
-				loadStr(_soundEffect, "effect", soundnode);
-				loadStr(_soundMusic, "music", soundnode);
+				loadPath(_soundEffect, "effect", soundnode);
+				loadPath(_soundMusic, "music", soundnode);
 			}
 
 			if (nodeValid("save", node)) {
 				rapidxml::xml_node<char> *savenode = node->first_node("save");
-				loadStr(_saveDir, "dir", savenode);
+				loadPath(_saveDir, "dir", savenode);
 				loadStr(_saveExt, "ext", savenode);
 
 				Common::String custom_path;
diff --git a/engines/crab/GameParam.h b/engines/crab/GameParam.h
index 08c17e54500..51edfd70f10 100644
--- a/engines/crab/GameParam.h
+++ b/engines/crab/GameParam.h
@@ -42,7 +42,7 @@ namespace Crab {
 // The index for all levels in the game
 struct LevelPath {
 	// The file paths
-	Common::String _layout, _asset;
+	Common::Path _layout, _asset;
 
 	// The name of the level
 	Common::String _name;
@@ -51,52 +51,54 @@ struct LevelPath {
 
 	void load(rapidxml::xml_node<char> *node) {
 		loadStr(_name, "name", node);
-		loadStr(_layout, "layout", node);
-		loadStr(_asset, "res", node);
+		loadPath(_layout, "layout", node);
+		loadPath(_asset, "res", node);
 	}
 };
 
 // Stores all layout paths for the game
 struct FilePaths {
 	// Resources common to all levels and states
-	Common::String _common;
+	Common::Path _common;
 
 	// Mod file location, current mod and their extension
-	Common::String _modPath, _modExt, _modCur;
+	Common::Path _modPath, _modCur;
+	Common::String _modExt;
 
 	// Main menu resources
-	Common::String _mainmenuL, _mainmenuR;
+	Common::Path _mainmenuL, _mainmenuR;
 
 	// Sounds
-	Common::String _soundEffect, _soundMusic;
+	Common::Path _soundEffect, _soundMusic;
 
 	// Fonts and window icon file
-	Common::String _font, _icon;
+	Common::Path _font, _icon;
 
 	// Save directory and extension
-	Common::String _saveDir, _saveExt;
+	Common::Path _saveDir;
+	Common::String _saveExt;
 
 	// The location of the shader index file
-	Common::String _shaders;
+	Common::Path _shaders;
 
 	// The location of the color index file
-	Common::String _colors;
+	Common::Path _colors;
 
 	// The list of levels in the game
 	Common::HashMap<Common::String, LevelPath> _level;
 
 	// The file path of the current resource file
-	Common::String _currentR;
+	Common::Path _currentR;
 
 	// The application data path (where saves and settings are stored)
-	Common::String _appdata;
+	Common::Path _appdata;
 
 	// Has this been loaded?
 	bool _loaded;
 
 	FilePaths();
-	void load(const Common::String &filename);
-	void loadLevel(const Common::String &filename);
+	void load(const Common::Path &filename);
+	void loadLevel(const Common::Path &filename);
 };
 
 // Storage pool used for saving numbers as strings
diff --git a/engines/crab/LoadingScreen.cpp b/engines/crab/LoadingScreen.cpp
index 921da780d72..b9b150cc6b5 100644
--- a/engines/crab/LoadingScreen.cpp
+++ b/engines/crab/LoadingScreen.cpp
@@ -36,7 +36,7 @@
 namespace Crab {
 
 void LoadingScreen::load() {
-	const Common::String &filename = "res/layout/loading.xml";
+	Common::Path filename("res/layout/loading.xml");
 	XMLDoc doc(filename);
 	if (doc.ready()) {
 		rapidxml::xml_node<char> *node = doc.doc()->first_node("loading");
diff --git a/engines/crab/TMX/TMXLayer.cpp b/engines/crab/TMX/TMXLayer.cpp
index cbac1efb95b..89aa8748a89 100644
--- a/engines/crab/TMX/TMXLayer.cpp
+++ b/engines/crab/TMX/TMXLayer.cpp
@@ -41,14 +41,14 @@ bool Layer::load(rapidxml::xml_node<char> *node) {
 	return false;
 }
 
-bool MapLayer::load(const Common::String &path, rapidxml::xml_node<char> *node) {
+bool MapLayer::load(const Common::Path &path, rapidxml::xml_node<char> *node) {
 	if (Layer::load(node)) {
 		if (nodeValid("image", node, false)) {
 			_type = LAYER_IMAGE;
 			rapidxml::xml_node<char> *imgnode = node->first_node("image");
 
 			if (imgnode->first_attribute("source") != nullptr)
-				_img.load((path + imgnode->first_attribute("source")->value()));
+				_img.load(path.append(imgnode->first_attribute("source")->value()));
 		} else {
 			_type = LAYER_NORMAL;
 			int i = 0;
diff --git a/engines/crab/TMX/TMXLayer.h b/engines/crab/TMX/TMXLayer.h
index b2f6c84f7ae..d0069b231cf 100644
--- a/engines/crab/TMX/TMXLayer.h
+++ b/engines/crab/TMX/TMXLayer.h
@@ -104,7 +104,7 @@ public:
 		_type = LAYER_NORMAL;
 		_collide = false;
 	}
-	bool load(const Common::String &path, rapidxml::xml_node<char> *node);
+	bool load(const Common::Path &path, rapidxml::xml_node<char> *node);
 };
 } // End of namespace TMX
 
diff --git a/engines/crab/TMX/TMXMap.cpp b/engines/crab/TMX/TMXMap.cpp
index 99ca5efed88..c87904af2a9 100644
--- a/engines/crab/TMX/TMXMap.cpp
+++ b/engines/crab/TMX/TMXMap.cpp
@@ -61,8 +61,8 @@ TMXMap::TMXMap() {
 // Purpose: Load stuff via a .tmx file set to xml storage (no compression)
 //------------------------------------------------------------------------
 
-void TMXMap::load(const Common::String &path, const Common::String &filename) {
-	XMLDoc conf((path + filename));
+void TMXMap::load(const Common::Path &path, const Common::String &filename) {
+	XMLDoc conf(path.appendComponent(filename));
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("map");
 		if (nodeValid(node)) {
diff --git a/engines/crab/TMX/TMXMap.h b/engines/crab/TMX/TMXMap.h
index 4ba61663897..90071ac1700 100644
--- a/engines/crab/TMX/TMXMap.h
+++ b/engines/crab/TMX/TMXMap.h
@@ -104,7 +104,7 @@ public:
 	~TMXMap() {}
 
 	void reset();
-	void load(const Common::String &path, const Common::String &filename);
+	void load(const Common::Path &path, const Common::String &filename);
 
 	void drawDebug(const Rect &camera);
 
diff --git a/engines/crab/TMX/TMXTileSet.cpp b/engines/crab/TMX/TMXTileSet.cpp
index 48923b61e95..18d55b784d7 100644
--- a/engines/crab/TMX/TMXTileSet.cpp
+++ b/engines/crab/TMX/TMXTileSet.cpp
@@ -37,7 +37,7 @@ namespace Crab {
 
 using namespace TMX;
 
-void TileSet::load(const Common::String &path, rapidxml::xml_node<char> *node) {
+void TileSet::load(const Common::Path &path, rapidxml::xml_node<char> *node) {
 	if (nodeValid(node)) {
 		loadNum(_firstGid, "firstgid", node);
 		loadStr(_name, "name", node);
@@ -51,7 +51,7 @@ void TileSet::load(const Common::String &path, rapidxml::xml_node<char> *node) {
 			rapidxml::xml_node<char> *imgnode = node->first_node("image");
 			Common::String filename;
 			loadStr(filename, "source", imgnode);
-			_loc = path + filename;
+			_loc = path.appendComponent(filename);
 
 			_img.load(_loc);
 			_totalRows = _img.h() / _tileH;
@@ -73,7 +73,7 @@ void TileSetGroup::reset() {
 	_tileset.clear();
 }
 
-void TileSetGroup::load(const Common::String &path, rapidxml::xml_node<char> *node) {
+void TileSetGroup::load(const Common::Path &path, rapidxml::xml_node<char> *node) {
 	reset();
 	for (auto n = node->first_node("tileset"); n != nullptr; n = n->next_sibling("tileset")) {
 		TileSet t;
diff --git a/engines/crab/TMX/TMXTileSet.h b/engines/crab/TMX/TMXTileSet.h
index 83511cfb6ed..80db9dcba78 100644
--- a/engines/crab/TMX/TMXTileSet.h
+++ b/engines/crab/TMX/TMXTileSet.h
@@ -42,7 +42,7 @@ struct TileSet {
 	Common::String _name;
 
 	// The location of the tileset image on the disk
-	Common::String _loc;
+	Common::Path _loc;
 
 	// The first gid of the tileset
 	GidFormat _firstGid;
@@ -73,12 +73,12 @@ struct TileSet {
 		init();
 	}
 
-	TileSet(const Common::String &path, rapidxml::xml_node<char> *node) {
+	TileSet(const Common::Path &path, rapidxml::xml_node<char> *node) {
 		init();
 		load(path, node);
 	}
 
-	void load(const Common::String &path, rapidxml::xml_node<char> *node);
+	void load(const Common::Path &path, rapidxml::xml_node<char> *node);
 	void draw(const Vector2i &pos, const TileInfo &tile);
 	void preDraw(const Vector2i &pos, const TileInfo &tile, Graphics::ManagedSurface *surf);
 };
@@ -97,7 +97,7 @@ public:
 
 	void reset();
 
-	void load(const Common::String &path, rapidxml::xml_node<char> *node);
+	void load(const Common::Path &path, rapidxml::xml_node<char> *node);
 	void draw(MapLayer &layer, const Rect &camera, const Vector2i &tileSize, const Rect &playerPos, pyrodactyl::image::Image &img);
 	void preDraw(MapLayer &layer, const Vector2i &tileSize, Graphics::ManagedSurface *surf);
 	void forceDraw(MapLayer &layer, const Rect &camera, const Vector2i &tileSize, const Rect &playerPos);
diff --git a/engines/crab/XMLDoc.cpp b/engines/crab/XMLDoc.cpp
index e656dd65d36..2a2bfc70a18 100644
--- a/engines/crab/XMLDoc.cpp
+++ b/engines/crab/XMLDoc.cpp
@@ -38,13 +38,11 @@ namespace rapidxml {
 
 namespace Crab {
 
-void XMLDoc::load(const Common::String &filename) {
-	const Common::Path path(filename);
-
+void XMLDoc::load(const Common::Path &filename) {
 	if (ready())
 		_doc.clear();
 
-	if (fileOpen(path, _text) && _text)
+	if (fileOpen(filename, _text) && _text)
 		_doc.parse<0>(_text);
 }
 
diff --git a/engines/crab/XMLDoc.h b/engines/crab/XMLDoc.h
index 8a349d12f02..a151104e40a 100644
--- a/engines/crab/XMLDoc.h
+++ b/engines/crab/XMLDoc.h
@@ -45,7 +45,7 @@ public:
 		_text = nullptr;
 	}
 
-	XMLDoc(const Common::String &filename) {
+	XMLDoc(const Common::Path &filename) {
 		_text = nullptr;
 		load(filename);
 	}
@@ -61,7 +61,7 @@ public:
 
 	// Load the text from the specified file into the rapidxml format
 	// Each function that references it must parse it there
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	// Check if document is ready for parsing
 	bool ready() const {
diff --git a/engines/crab/animation/animset.cpp b/engines/crab/animation/animset.cpp
index d108d1f5c3f..554d249311f 100644
--- a/engines/crab/animation/animset.cpp
+++ b/engines/crab/animation/animset.cpp
@@ -35,7 +35,7 @@ namespace Crab {
 
 using namespace pyrodactyl::anim;
 
-void AnimSet::load(const Common::String &filename) {
+void AnimSet::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node();
diff --git a/engines/crab/animation/animset.h b/engines/crab/animation/animset.h
index 083e923d9d0..9a0c18600c1 100644
--- a/engines/crab/animation/animset.h
+++ b/engines/crab/animation/animset.h
@@ -58,7 +58,7 @@ struct AnimSet {
 
 	AnimSet() {}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	TextureFlipType flip(const Direction &dir);
 	const ShadowOffset &shadow(const Direction &dir);
diff --git a/engines/crab/animation/sprite.cpp b/engines/crab/animation/sprite.cpp
index 32865eb698f..e9f71a7c959 100644
--- a/engines/crab/animation/sprite.cpp
+++ b/engines/crab/animation/sprite.cpp
@@ -54,7 +54,7 @@ Sprite::Sprite() : _imgSize(1, 1), _velMod(1.0f, 1.0f) {
 //------------------------------------------------------------------------
 // Purpose: Load sprite from XML and animations from the index of all animation files
 //------------------------------------------------------------------------
-void Sprite::load(rapidxml::xml_node<char> *node, Common::Array<Common::String> &animations) {
+void Sprite::load(rapidxml::xml_node<char> *node, Common::Array<Common::Path> &animations) {
 	using namespace pyrodactyl::image;
 
 	if (nodeValid(node)) {
diff --git a/engines/crab/animation/sprite.h b/engines/crab/animation/sprite.h
index daee17b60fa..6bb6e9c01e6 100644
--- a/engines/crab/animation/sprite.h
+++ b/engines/crab/animation/sprite.h
@@ -235,7 +235,7 @@ public:
 	void takeDamage(pyrodactyl::event::Info &info, Sprite &s);
 	void exchangeDamage(pyrodactyl::event::Info &info, Sprite &s, const pyrodactyl::ai::SpriteConstant &sc);
 
-	void load(rapidxml::xml_node<char> *node, Common::Array<Common::String> &animations);
+	void load(rapidxml::xml_node<char> *node, Common::Array<Common::Path> &animations);
 	void internalEvents(pyrodactyl::event::Info &info, const Common::String &player_id,
 						Common::Array<pyrodactyl::event::EventResult> &result, Common::Array<pyrodactyl::event::EventSeqInfo> &end_seq);
 
diff --git a/engines/crab/app.cpp b/engines/crab/app.cpp
index c8d5e166199..37f2bc50dc4 100644
--- a/engines/crab/app.cpp
+++ b/engines/crab/app.cpp
@@ -167,7 +167,7 @@ void App::run() {
 	delete _game;
 }
 
-void App::loadSettings(const Common::String &filename) {
+void App::loadSettings(const Common::Path &filename) {
 	XMLDoc settings(filename);
 	if (settings.ready()) {
 		rapidxml::xml_node<char> *node = settings.doc()->first_node("settings");
diff --git a/engines/crab/app.h b/engines/crab/app.h
index f7a42742ae2..bee558c400b 100644
--- a/engines/crab/app.h
+++ b/engines/crab/app.h
@@ -31,7 +31,7 @@
 #ifndef CRAB_APP_H
 #define CRAB_APP_H
 
-#include "common/str.h"
+#include "common/path.h"
 
 namespace Crab {
 class Game;
@@ -39,7 +39,7 @@ class Game;
 class App {
 private:
 	Game *_game;
-	void loadSettings(const Common::String &filename);
+	void loadSettings(const Common::Path &filename);
 public:
 	~App();
 
diff --git a/engines/crab/crab.cpp b/engines/crab/crab.cpp
index 8f07ec2535d..0ea9f803342 100644
--- a/engines/crab/crab.cpp
+++ b/engines/crab/crab.cpp
@@ -130,7 +130,7 @@ Common::Error CrabEngine::run() {
 }
 
 void CrabEngine::initializePath(const Common::FSNode &gamePath) {
-	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 5);
+	SearchMan.addDirectory(gamePath, 0, 5);
 }
 
 Common::Error CrabEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
diff --git a/engines/crab/event/EventSeqGroup.cpp b/engines/crab/event/EventSeqGroup.cpp
index c1fb6c61f83..623032789c1 100644
--- a/engines/crab/event/EventSeqGroup.cpp
+++ b/engines/crab/event/EventSeqGroup.cpp
@@ -40,7 +40,7 @@ void EventSeqGroup::endSeq(const uint &id) {
 	_end.push_back(id);
 }
 
-void EventSeqGroup::addSeq(const uint &id, Common::String &path) {
+void EventSeqGroup::addSeq(const uint &id, const Common::Path &path) {
 	_seq[id].load(path);
 }
 
diff --git a/engines/crab/event/EventSeqGroup.h b/engines/crab/event/EventSeqGroup.h
index cd505293481..6a644590e21 100644
--- a/engines/crab/event/EventSeqGroup.h
+++ b/engines/crab/event/EventSeqGroup.h
@@ -50,7 +50,7 @@ public:
 	EventSeqGroup() {}
 	~EventSeqGroup() {}
 
-	void addSeq(const uint &id, Common::String &path);
+	void addSeq(const uint &id, const Common::Path &path);
 	void endSeq(const uint &id);
 	bool eventInProgress(const uint &id);
 	bool activeSeq(uint &activeSeq);
diff --git a/engines/crab/event/EventSequence.cpp b/engines/crab/event/EventSequence.cpp
index c9b6e096a2b..f8e64aaee14 100644
--- a/engines/crab/event/EventSequence.cpp
+++ b/engines/crab/event/EventSequence.cpp
@@ -38,7 +38,7 @@ using namespace pyrodactyl::event;
 //------------------------------------------------------------------------
 // Purpose: Load
 //------------------------------------------------------------------------
-void EventSequence::load(const Common::String &filename) {
+void EventSequence::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("events");
diff --git a/engines/crab/event/EventSequence.h b/engines/crab/event/EventSequence.h
index 73324944cca..5aed25be069 100644
--- a/engines/crab/event/EventSequence.h
+++ b/engines/crab/event/EventSequence.h
@@ -76,7 +76,7 @@ public:
 	}
 
 	// Load and save
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	void saveState(rapidxml::xml_document<char> &doc, rapidxml::xml_node<char> *root, const char *name);
 	void loadState(rapidxml::xml_node<char> *node);
diff --git a/engines/crab/event/GameEventInfo.cpp b/engines/crab/event/GameEventInfo.cpp
index e94e25f829e..4d8cb8b33be 100644
--- a/engines/crab/event/GameEventInfo.cpp
+++ b/engines/crab/event/GameEventInfo.cpp
@@ -81,7 +81,7 @@ void Info::load(rapidxml::xml_node<char> *node) {
 	_inv.itemFile(node->first_node("item")->first_attribute("list")->value());
 }
 
-void Info::loadPeople(const Common::String &filename) {
+void Info::loadPeople(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("people");
diff --git a/engines/crab/event/GameEventInfo.h b/engines/crab/event/GameEventInfo.h
index 5107879d83a..4d4a8dba04d 100644
--- a/engines/crab/event/GameEventInfo.h
+++ b/engines/crab/event/GameEventInfo.h
@@ -73,7 +73,7 @@ class Info {
 	// This image changes to reflect the playable character
 	int _playerImg;
 
-	void loadPeople(const Common::String &filename);
+	void loadPeople(const Common::Path &filename);
 
 public:
 	// The player's one stop shop for objectives and lore
diff --git a/engines/crab/event/eventstore.cpp b/engines/crab/event/eventstore.cpp
index a4b81b99d0a..2c727a9cfeb 100644
--- a/engines/crab/event/eventstore.cpp
+++ b/engines/crab/event/eventstore.cpp
@@ -44,7 +44,7 @@ void GameEventStore::addConv(rapidxml::xml_node<char> *node, uint &index) {
 	_con.push_back(c);
 }
 
-void GameEventStore::load(const Common::String &filename) {
+void GameEventStore::load(const Common::Path &filename) {
 
 	// Request current user stats from Steam
 	// m_pSteamUserStats = SteamUserStats();
diff --git a/engines/crab/event/eventstore.h b/engines/crab/event/eventstore.h
index 49026c88786..1fc303ebde9 100644
--- a/engines/crab/event/eventstore.h
+++ b/engines/crab/event/eventstore.h
@@ -77,7 +77,7 @@ struct GameEventStore {
 		_anim.clear();
 	}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	void addConv(rapidxml::xml_node<char> *node, uint &index);
 	void setAchievement(const int &id);
diff --git a/engines/crab/event/gameeventmanager.cpp b/engines/crab/event/gameeventmanager.cpp
index 75d3ded4be8..d1fb695548b 100644
--- a/engines/crab/event/gameeventmanager.cpp
+++ b/engines/crab/event/gameeventmanager.cpp
@@ -61,9 +61,9 @@ void Manager::load(rapidxml::xml_node<char> *node, ParagraphData &popup) {
 
 				for (auto n = loc->first_node("file"); n != nullptr; n = n->next_sibling("file")) {
 					uint id;
-					Common::String path;
+					Common::Path path;
 					loadNum(id, "name", n);
-					loadStr(path, "path", n);
+					loadPath(path, "path", n);
 					_eventMap[locName].addSeq(id, path);
 				}
 			}
diff --git a/engines/crab/filesystem.cpp b/engines/crab/filesystem.cpp
index fcc21a37062..fbd5ca33d7a 100644
--- a/engines/crab/filesystem.cpp
+++ b/engines/crab/filesystem.cpp
@@ -33,11 +33,9 @@
 
 namespace Crab {
 
-Common::String cleansePath(const Common::String &path) {
-	if (path.hasPrefix("res/"))
-		return Common::String(&path.c_str()[4]);
-
-	return path;
+Common::Path cleansePath(const Common::Path &path) {
+	// If the path doesn't begin with res it will return the same
+	return path.relativeTo("res");
 }
 
 bool fileOpen(const Common::Path &path, char *&data) {
@@ -48,9 +46,9 @@ bool fileOpen(const Common::Path &path, char *&data) {
 		delete[] data;
 
 	Common::File file;
-	Common::String cleansedPath = cleansePath(path.toString());
+	Common::Path cleansedPath = cleansePath(path);
 	if (!file.open(cleansedPath)) {
-		warning("Unable to open file %s", cleansedPath.c_str());
+		warning("Unable to open file %s", cleansedPath.toString(Common::Path::kNativeSeparator).c_str());
 		data = nullptr;
 		return false;
 	}
@@ -74,9 +72,9 @@ bool fileOpen(const Common::Path &path, Common::File *file) {
 	if (file->isOpen())
 		file->close();
 
-	Common::String cleansedPath = cleansePath(path.toString());
+	Common::Path cleansedPath = cleansePath(path);
 	if (!file->open(cleansedPath)) {
-		warning("Unable to open file %s", cleansedPath.c_str());
+		warning("Unable to open file %s", cleansedPath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/engines/crab/filesystem.h b/engines/crab/filesystem.h
index b2b20bbc0f5..a149ec74a97 100644
--- a/engines/crab/filesystem.h
+++ b/engines/crab/filesystem.h
@@ -38,7 +38,7 @@ class File;
 
 namespace Crab {
 
-Common::String cleansePath(const Common::String &path);
+Common::Path cleansePath(const Common::Path &path);
 bool fileOpen(const Common::Path &path, char *&data);
 bool fileOpen(const Common::Path &path, Common::File *file);
 
diff --git a/engines/crab/game.cpp b/engines/crab/game.cpp
index a2014321c6b..317fca9a08f 100644
--- a/engines/crab/game.cpp
+++ b/engines/crab/game.cpp
@@ -60,7 +60,7 @@ void Game::loadGame() {
 	init(g_engine->_filePath->_modCur);
 }
 
-void Game::init(const Common::String &filename) {
+void Game::init(const Common::Path &filename) {
 	g_engine->_loadingScreen->dim();
 	g_engine->_eventStore->clear();
 	_gameOver.clear(false);
@@ -75,34 +75,34 @@ void Game::init(const Common::String &filename) {
 
 		_info.load(node);
 
-		Common::String path;
+		Common::Path path;
 		if (nodeValid("level", node)) {
-			loadStr(path, "list", node->first_node("level"));
+			loadPath(path, "list", node->first_node("level"));
 			g_engine->_filePath->loadLevel(path);
 		}
 
 		if (nodeValid("hud", node)) {
-			loadStr(path, "layout", node->first_node("hud"));
+			loadPath(path, "layout", node->first_node("hud"));
 			_hud.load(path, _level._talkNotify, _level._destMarker);
 		}
 
 		if (nodeValid("sprite", node)) {
-			loadStr(path, "animation", node->first_node("sprite"));
+			loadPath(path, "animation", node->first_node("sprite"));
 			_level.loadMoves(path);
 
-			loadStr(path, "constant", node->first_node("sprite"));
+			loadPath(path, "constant", node->first_node("sprite"));
 			_level.loadConst(path);
 		}
 
 		if (nodeValid("event", node)) {
 			_gem.load(node->first_node("event"), _popDefault);
 
-			loadStr(path, "store", node->first_node("event"));
+			loadPath(path, "store", node->first_node("event"));
 			g_engine->_eventStore->load(path);
 		}
 
 		if (nodeValid("map", node)) {
-			loadStr(path, "layout", node->first_node("map"));
+			loadPath(path, "layout", node->first_node("map"));
 			_map.load(path, _info);
 		}
 
@@ -110,7 +110,7 @@ void Game::init(const Common::String &filename) {
 			_savefile.load(node->first_node("save"));
 
 		if (nodeValid("debug", node)) {
-			loadStr(path, "layout", node->first_node("debug"));
+			loadPath(path, "layout", node->first_node("debug"));
 			_debugConsole.load(path);
 		}
 	}
@@ -760,7 +760,7 @@ void Game::saveState(Common::SeekableWriteStream *stream) {
 	root->append_attribute(doc.allocate_attribute("file", _savefile._ironman.c_str()));
 
 	// Preview image used
-	root->append_attribute(doc.allocate_attribute("preview", _level._previewPath.c_str()));
+	root->append_attribute(doc.allocate_attribute("preview", _level._previewPath.toString('/').c_str()));
 
 	// Time played
 	Common::String playtime = _clock.getTime();
diff --git a/engines/crab/game.h b/engines/crab/game.h
index cacb0ccba32..042ee8106b3 100644
--- a/engines/crab/game.h
+++ b/engines/crab/game.h
@@ -121,7 +121,7 @@ private:
 public:
 	Game() : _isInited(false), _state(STATE_GAME) {}
 
-	void init(const Common::String &filename);
+	void init(const Common::Path &filename);
 
 	void startNewGame();
 	void loadGame();
diff --git a/engines/crab/image/Image.cpp b/engines/crab/image/Image.cpp
index 2aa9f075a4c..6a149167421 100644
--- a/engines/crab/image/Image.cpp
+++ b/engines/crab/image/Image.cpp
@@ -67,7 +67,7 @@ bool Image::load(Graphics::ManagedSurface *surface) {
 	return true;
 }
 
-bool Image::load(const Common::String &path) {
+bool Image::load(const Common::Path &path) {
 	// Get rid of preexisting texture
 	deleteImage();
 
@@ -83,7 +83,7 @@ bool Image::load(const Common::String &path) {
 
 		file.close();
 
-		debugC(kDebugFilePath, "Image::load() Image Texture(%s): w: %d h: %d", path.c_str(), _w, _h);
+		debugC(kDebugFilePath, "Image::load() Image Texture(%s): w: %d h: %d", path.toString(Common::Path::kNativeSeparator).c_str(), _w, _h);
 	}
 
 	return _texture != nullptr;
diff --git a/engines/crab/image/Image.h b/engines/crab/image/Image.h
index d7adadb79e4..35f459e8ac1 100644
--- a/engines/crab/image/Image.h
+++ b/engines/crab/image/Image.h
@@ -98,7 +98,7 @@ public:
 	}
 
 	// Load the image
-	bool load(const Common::String &path);
+	bool load(const Common::Path &path);
 	bool load(rapidxml::xml_node<char> *node, const char *name);
 	bool load(Graphics::Surface *surface);
 	bool load(Graphics::ManagedSurface *surface);
diff --git a/engines/crab/image/ImageManager.cpp b/engines/crab/image/ImageManager.cpp
index ffb7e461a0c..47bac147dd7 100644
--- a/engines/crab/image/ImageManager.cpp
+++ b/engines/crab/image/ImageManager.cpp
@@ -46,7 +46,7 @@ using namespace pyrodactyl::image;
 //------------------------------------------------------------------------
 // Purpose: Load assets here.
 //------------------------------------------------------------------------
-void ImageManager::loadMap(const Common::String &filename, const MapID &mapid) {
+void ImageManager::loadMap(const Common::Path &filename, const MapID &mapid) {
 	for (auto &it : _map[mapid])
 		it._value.deleteImage();
 
@@ -62,18 +62,18 @@ void ImageManager::loadMap(const Common::String &filename, const MapID &mapid) {
 				// if yes, load it  - if no, just load the higher quality one
 
 				bool valid = false;
-				Common::String path;
+				Common::Path path;
 
 				if (!g_engine->_screenSettings->_quality)
-					valid = loadStr(path, "path_low", n, false);
+					valid = loadPath(path, "path_low", n, false);
 
 				if (!valid)
-					valid = loadStr(path, "path", n, false);
+					valid = loadPath(path, "path", n, false);
 
 				if (valid)
 					_map[mapid][key].load(path);
 				else
-					error("ImageManager::loadMap : Unable to load image id %u from %s!", key, path.c_str());
+					error("ImageManager::loadMap : Unable to load image id %u from %s!", key, path.toString(Common::Path::kNativeSeparator).c_str());
 			}
 		}
 
diff --git a/engines/crab/image/ImageManager.h b/engines/crab/image/ImageManager.h
index 0a5c1d614c6..699845a1c83 100644
--- a/engines/crab/image/ImageManager.h
+++ b/engines/crab/image/ImageManager.h
@@ -85,7 +85,7 @@ public:
 	// image related stuff
 
 	// Load all images specified in an xml file in a map
-	void loadMap(const Common::String &filename, const MapID &mapid = MAP_CURRENT);
+	void loadMap(const Common::Path &filename, const MapID &mapid = MAP_CURRENT);
 
 	void getTexture(const ImageKey &id, Image &data);
 	Image &getTexture(const ImageKey &id);
diff --git a/engines/crab/level/level.h b/engines/crab/level/level.h
index 54ec707ca05..3a2fb72cf93 100644
--- a/engines/crab/level/level.h
+++ b/engines/crab/level/level.h
@@ -59,7 +59,7 @@ class Level {
 	Common::MultiMap<int, pyrodactyl::anim::Sprite *> _objSeq;
 
 	// The file index which contains the fighting moves of all characters
-	Common::Array<Common::String> _animSet;
+	Common::Array<Common::Path> _animSet;
 
 	// The movement sets for sprites in levels
 	Common::Array<pyrodactyl::ai::MovementSet> _moveSet;
@@ -133,7 +133,7 @@ public:
 	pyrodactyl::ui::ParagraphData _pop;
 
 	// The path of the preview image
-	Common::String _previewPath;
+	Common::Path _previewPath;
 
 	// A full rendered image of the level
 	pyrodactyl::image::Image _img;
@@ -183,12 +183,12 @@ public:
 	void calcProperties(pyrodactyl::event::Info &info);
 
 	// Loading function
-	void load(const Common::String &filename, pyrodactyl::event::Info &info, pyrodactyl::event::TriggerSet &gameOver,
+	void load(const Common::Path &filename, pyrodactyl::event::Info &info, pyrodactyl::event::TriggerSet &gameOver,
 			  const int &playerX = -1, const int &playerY = -1);
 
 	// One time load called first-time
-	void loadMoves(const Common::String &filename);
-	void loadConst(const Common::String &filename);
+	void loadMoves(const Common::Path &filename);
+	void loadConst(const Common::Path &filename);
 
 	// Used to see if a sprite collides with a rectangle
 	void calcTrigCollide(pyrodactyl::event::Info &info);
diff --git a/engines/crab/level/level_load.cpp b/engines/crab/level/level_load.cpp
index 336728166ce..945636e87ec 100644
--- a/engines/crab/level/level_load.cpp
+++ b/engines/crab/level/level_load.cpp
@@ -52,7 +52,7 @@ static bool compSpriteLayer(const Sprite &a, const Sprite &b) {
 //------------------------------------------------------------------------
 // Purpose: Load the level
 //------------------------------------------------------------------------
-void Level::load(const Common::String &filename, pyrodactyl::event::Info &info,
+void Level::load(const Common::Path &filename, pyrodactyl::event::Info &info,
 				 pyrodactyl::event::TriggerSet &gameOver, const int &playerX, const int &playerY) {
 	reset();
 	XMLDoc conf(filename);
@@ -67,7 +67,7 @@ void Level::load(const Common::String &filename, pyrodactyl::event::Info &info,
 				_showmap.set(true);
 
 			if (nodeValid("preview", node))
-				loadStr(_previewPath, "path", node->first_node("preview"));
+				loadPath(_previewPath, "path", node->first_node("preview"));
 
 			if (nodeValid("music", node)) {
 				loadNum(_music._id, "id", node->first_node("music"));
@@ -76,8 +76,9 @@ void Level::load(const Common::String &filename, pyrodactyl::event::Info &info,
 
 			if (nodeValid("map", node)) {
 				rapidxml::xml_node<char> *mapnode = node->first_node("map");
-				Common::String path, tmxfile;
-				loadStr(path, "path", mapnode);
+				Common::Path path;
+				Common::String tmxfile;
+				loadPath(path, "path", mapnode);
 				loadStr(tmxfile, "file", mapnode);
 
 				_terrain.load(path, tmxfile);
@@ -176,7 +177,7 @@ void Level::load(const Common::String &filename, pyrodactyl::event::Info &info,
 //------------------------------------------------------------------------
 // Purpose: Build an index of all animation files, called once at start
 //------------------------------------------------------------------------
-void Level::loadMoves(const Common::String &filename) {
+void Level::loadMoves(const Common::Path &filename) {
 	XMLDoc movList(filename);
 	if (movList.ready()) {
 		rapidxml::xml_node<char> *node = movList.doc()->first_node("movelist");
@@ -190,10 +191,10 @@ void Level::loadMoves(const Common::String &filename) {
 			// See if there is an alternate moveset for low quality setting
 			// If no, just load the regular one
 			if (!g_engine->_screenSettings->_quality) {
-				if (!loadStr(_animSet[pos], "path_low", n))
-					loadStr(_animSet[pos], "path", n);
+				if (!loadPath(_animSet[pos], "path_low", n))
+					loadPath(_animSet[pos], "path", n);
 			} else
-				loadStr(_animSet[pos], "path", n);
+				loadPath(_animSet[pos], "path", n);
 		}
 	}
 }
@@ -201,7 +202,7 @@ void Level::loadMoves(const Common::String &filename) {
 //------------------------------------------------------------------------
 // Purpose: Load the default sprite constant parameters
 //------------------------------------------------------------------------
-void Level::loadConst(const Common::String &filename) {
+void Level::loadConst(const Common::Path &filename) {
 	XMLDoc doc(filename);
 	if (doc.ready()) {
 		rapidxml::xml_node<char> *node = doc.doc()->first_node("constant");
diff --git a/engines/crab/loaders.cpp b/engines/crab/loaders.cpp
index 6e38ccbdeca..a02339a1335 100644
--- a/engines/crab/loaders.cpp
+++ b/engines/crab/loaders.cpp
@@ -68,6 +68,15 @@ bool loadStr(Common::String &val, const Common::String &name, rapidxml::xml_node
 	return true;
 }
 
+bool loadPath(Common::Path &val, const Common::String &name, rapidxml::xml_node<char> *node, const bool &echo) {
+	Common::String str;
+	if (!loadStr(str, name, node, echo)) {
+		return false;
+	}
+	val = Common::Path(str, '/');
+	return true;
+}
+
 bool loadColor(Color &col, rapidxml::xml_node<char> *node, const bool &echo,
 	const Common::String &rName, const Common::String &gName, const Common::String &bName) {
 	int r = 0, g = 0, b = 0;
@@ -175,7 +184,7 @@ bool loadTextureFlipType(TextureFlipType &flip, rapidxml::xml_node<char> *node,
 	return false;
 }
 
-uint version(const Common::String &filename) {
+uint version(const Common::Path &filename) {
 	uint version = 0;
 
 	XMLDoc doc(filename);
diff --git a/engines/crab/loaders.h b/engines/crab/loaders.h
index 4e334b2117c..b0b3ed65f6a 100644
--- a/engines/crab/loaders.h
+++ b/engines/crab/loaders.h
@@ -48,6 +48,7 @@ bool nodeValid(const Common::String &name, rapidxml::xml_node<char> *parentNode,
 // Functions to load attributes from xml files
 // return true on success, false on failure
 bool loadStr(Common::String &val, const Common::String &name, rapidxml::xml_node<char> *node, const bool &echo = true);
+bool loadPath(Common::Path &val, const Common::String &name, rapidxml::xml_node<char> *node, const bool &echo = true);
 
 // Used for loading numerical types
 template<typename T>
@@ -118,7 +119,7 @@ bool loadDirection(Direction &dir, rapidxml::xml_node<char> *node, const bool &e
 bool loadTextureFlipType(TextureFlipType &flip, rapidxml::xml_node<char> *node, const bool &echo = true);
 
 // Check the version of a file
-uint version(const Common::String &filename);
+uint version(const Common::Path &filename);
 
 } // End of namespace Crab
 
diff --git a/engines/crab/music/MusicManager.cpp b/engines/crab/music/MusicManager.cpp
index 9ae77dd66e0..d454561e389 100644
--- a/engines/crab/music/MusicManager.cpp
+++ b/engines/crab/music/MusicManager.cpp
@@ -131,14 +131,14 @@ bool MusicManager::load(rapidxml::xml_node<char> *node) {
 				rapidxml::xml_attribute<char> *id = n->first_attribute("id"), *path = n->first_attribute("path");
 				if (id != nullptr && path != nullptr) {
 					EffectAudio *audio = new EffectAudio();
-					Common::String cleansedPath = cleansePath(path->value());
+					Common::Path cleansedPath = cleansePath(Common::Path(path->value(), '/'));
 					if (audio->_file.open(cleansedPath)) {
 						audio->_handle = new Audio::SoundHandle();
 						audio->_stream = Audio::makeWAVStream(&audio->_file, DisposeAfterUse::NO);
 						_effects[stringToNumber<ChunkKey>(id->value())] = audio;
 					} else {
 						delete audio;
-						warning("Could not open audio file : %s", cleansedPath.c_str());
+						warning("Could not open audio file : %s", cleansedPath.toString().c_str());
 						return false;
 					}
 				}
diff --git a/engines/crab/music/musicparam.h b/engines/crab/music/musicparam.h
index d1cb8ea5e5e..21d81d4ca83 100644
--- a/engines/crab/music/musicparam.h
+++ b/engines/crab/music/musicparam.h
@@ -75,13 +75,13 @@ struct MusicData {
 		loadNum(_id, "id", node);
 		loadNum(_fadeInDuration, "fade_in", node);
 
-		Common::String cleansedPath = cleansePath(node->first_attribute("path")->value());
+		Common::Path cleansedPath = cleansePath(Common::Path(node->first_attribute("path")->value(), '/'));
 		if (_file.open(cleansedPath)) {
 			Audio::SeekableAudioStream *stream = Audio::makeVorbisStream(&_file, DisposeAfterUse::NO);
 			// loops=0 means infinite here.
 			_track = Audio::makeLoopingAudioStream(stream, 0, 0, 0);
 		} else {
-			warning("Could not open file %s", cleansedPath.c_str());
+			warning("Could not open file %s", cleansedPath.toString().c_str());
 		}
 	}
 };
diff --git a/engines/crab/stat/StatTemplate.cpp b/engines/crab/stat/StatTemplate.cpp
index f00ffd6f86b..81c68626f50 100644
--- a/engines/crab/stat/StatTemplate.cpp
+++ b/engines/crab/stat/StatTemplate.cpp
@@ -36,7 +36,7 @@ namespace Crab {
 
 using namespace pyrodactyl::stat;
 
-void StatTemplates::load(const Common::String &filename) {
+void StatTemplates::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("templates");
diff --git a/engines/crab/stat/StatTemplate.h b/engines/crab/stat/StatTemplate.h
index 451a9f12ba9..bb6edb0947b 100644
--- a/engines/crab/stat/StatTemplate.h
+++ b/engines/crab/stat/StatTemplate.h
@@ -32,6 +32,7 @@
 #define CRAB_STATTEMPLATE_H
 
 #include "common/array.h"
+#include "common/path.h"
 #include "crab/stat/Stat.h"
 
 namespace Crab {
@@ -45,7 +46,7 @@ public:
 	StatTemplates() {}
 	~StatTemplates() {}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 };
 } // End of namespace stat
 } // End of namespace pyrodactyl
diff --git a/engines/crab/text/color.cpp b/engines/crab/text/color.cpp
index 6a1a8a7ee71..d1392eb490b 100644
--- a/engines/crab/text/color.cpp
+++ b/engines/crab/text/color.cpp
@@ -35,7 +35,7 @@ namespace Crab {
 
 using namespace pyrodactyl::text;
 
-void ColorPool::load(const Common::String &filename) {
+void ColorPool::load(const Common::Path &filename) {
 	_pool.clear();
 	XMLDoc colList(filename);
 	if (colList.ready()) {
diff --git a/engines/crab/text/color.h b/engines/crab/text/color.h
index e78cff048b8..9cbd387c9b5 100644
--- a/engines/crab/text/color.h
+++ b/engines/crab/text/color.h
@@ -57,7 +57,7 @@ public:
 	}
 
 	Color &get(const int &num);
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 };
 } // End of namespace text
 } // End of namespace pyrodactyl
diff --git a/engines/crab/ui/CreditScreen.cpp b/engines/crab/ui/CreditScreen.cpp
index 22958e70953..4f3a3a81a51 100644
--- a/engines/crab/ui/CreditScreen.cpp
+++ b/engines/crab/ui/CreditScreen.cpp
@@ -44,7 +44,7 @@ void CreditScreen::reset() {
 	_speed._cur = _speed._slow;
 }
 
-void CreditScreen::load(const Common::String &filename) {
+void CreditScreen::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("credits");
diff --git a/engines/crab/ui/CreditScreen.h b/engines/crab/ui/CreditScreen.h
index cc47c2ea82c..b46466bbb00 100644
--- a/engines/crab/ui/CreditScreen.h
+++ b/engines/crab/ui/CreditScreen.h
@@ -111,7 +111,7 @@ public:
 
 	~CreditScreen() {}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 	void reset();
 
 	bool handleEvents(Common::Event &event);
diff --git a/engines/crab/ui/DevConsole.cpp b/engines/crab/ui/DevConsole.cpp
index e56571e599d..75ae7eff6b6 100644
--- a/engines/crab/ui/DevConsole.cpp
+++ b/engines/crab/ui/DevConsole.cpp
@@ -35,7 +35,7 @@ namespace Crab {
 
 using namespace pyrodactyl::ui;
 
-void DebugConsole::load(const Common::String &filename) {
+void DebugConsole::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("debug");
diff --git a/engines/crab/ui/DevConsole.h b/engines/crab/ui/DevConsole.h
index a8b415b73ee..31db5eeede0 100644
--- a/engines/crab/ui/DevConsole.h
+++ b/engines/crab/ui/DevConsole.h
@@ -73,7 +73,7 @@ public:
 
 	void handleEvents(const Common::Event &event);
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 	void draw(pyrodactyl::event::Info &info);
 
 	void internalEvents();
diff --git a/engines/crab/ui/FileData.cpp b/engines/crab/ui/FileData.cpp
index 39f4f860b55..6ffdf7a15b6 100644
--- a/engines/crab/ui/FileData.cpp
+++ b/engines/crab/ui/FileData.cpp
@@ -65,7 +65,7 @@ SaveFileData::SaveFileData(const Common::String &file) {
 				loadStr(_locName, "loc_name", node);
 				loadStr(_charName, "char_name", node);
 				loadStr(_time, "time", node);
-				loadStr(_preview, "preview", node);
+				loadPath(_preview, "preview", node);
 				_blank = false;
 			}
 		}
diff --git a/engines/crab/ui/FileData.h b/engines/crab/ui/FileData.h
index bccabce749d..09258d0f183 100644
--- a/engines/crab/ui/FileData.h
+++ b/engines/crab/ui/FileData.h
@@ -44,7 +44,8 @@ public:
 
 class SaveFileData : public FileData {
 public:
-	Common::String _locId, _locName, _charName, _diff, _time, _preview;
+	Common::String _locId, _locName, _charName, _diff, _time;
+	Common::Path _preview;
 
 	// This is to account for the first save slot, called "New Save", which doesn't actually have a file
 	bool _blank;
@@ -55,7 +56,8 @@ public:
 
 class ModFileData : public FileData {
 public:
-	Common::String _author, _version, _info, _website, _preview;
+	Common::String _author, _version, _info, _website;
+	Common::Path _preview;
 	ModFileData(const Common::String &filepath);
 };
 
diff --git a/engines/crab/ui/FileMenu.h b/engines/crab/ui/FileMenu.h
index 525e70adcbc..a741ee29990 100644
--- a/engines/crab/ui/FileMenu.h
+++ b/engines/crab/ui/FileMenu.h
@@ -56,7 +56,8 @@ protected:
 	Common::String _selected;
 
 	// The extension and directory used by this menu
-	Common::String _extension, _directory;
+	Common::String _extension;
+	Common::Path _directory;
 
 	// The save information for each slot
 	Common::Array<FileType> _slotInfo;
@@ -72,7 +73,7 @@ protected:
 		pyrodactyl::image::Image _preview;
 
 		// Fallback path if there is no preview image or if we fail to load it
-		Common::String _noPreviewPath;
+		Common::Path _noPreviewPath;
 
 		// Position of image
 		Element _pos;
@@ -140,7 +141,7 @@ public:
 		if (nodeValid("preview", node)) {
 			auto prnode = node->first_node("preview");
 			_img._pos.load(prnode);
-			loadStr(_img._noPreviewPath, "path", prnode);
+			loadPath(_img._noPreviewPath, "path", prnode);
 		}
 
 		if (nodeValid("offset", node)) {
@@ -164,7 +165,7 @@ public:
 		}
 
 		_extension = g_engine->_filePath->_saveExt;
-		_directory = (g_engine->_filePath->_appdata + g_engine->_filePath->_saveDir);
+		_directory = g_engine->_filePath->_appdata.join(g_engine->_filePath->_saveDir);
 		scanDir();
 	}
 
@@ -199,8 +200,8 @@ public:
 			if (!_img._loaded || _prevHover != i) {
 				_img._loaded = true;
 				_prevHover = i;
-				if (!_img._preview.load(_slotInfo[i]._preview))
-					_img._preview.load(_img._noPreviewPath);
+				if (!_img._preview.load(Common::Path(_slotInfo[i]._preview)))
+					_img._preview.load(Common::Path(_img._noPreviewPath));
 			}
 
 			_hover = true;
diff --git a/engines/crab/ui/Inventory.cpp b/engines/crab/ui/Inventory.cpp
index 3566e5888e5..a2a78d01473 100644
--- a/engines/crab/ui/Inventory.cpp
+++ b/engines/crab/ui/Inventory.cpp
@@ -41,7 +41,7 @@ using namespace pyrodactyl::people;
 //------------------------------------------------------------------------
 // Purpose: Load layout
 //------------------------------------------------------------------------
-void Inventory::load(const Common::String &filename) {
+void Inventory::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("inventory");
diff --git a/engines/crab/ui/Inventory.h b/engines/crab/ui/Inventory.h
index f1b3e98f596..54d6e1b6206 100644
--- a/engines/crab/ui/Inventory.h
+++ b/engines/crab/ui/Inventory.h
@@ -51,7 +51,7 @@ class Inventory {
 	// pyrodactyl::stat::StatDrawHelper helper;
 
 	// The file where all the item information is stored
-	Common::String _itemfile;
+	Common::Path _itemfile;
 
 	// Used to draw the money value
 	Button _money;
@@ -69,7 +69,7 @@ public:
 	void delItem(const Common::String &charId, const Common::String &itemId);
 	bool hasItem(const Common::String &charId, const Common::String &container, const Common::String &itemId);
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 	void draw(pyrodactyl::people::Person &obj, const int &moneyVal);
 
 	void handleEvents(const Common::String &string, const Common::Event &Event);
diff --git a/engines/crab/ui/MapData.cpp b/engines/crab/ui/MapData.cpp
index 73689e9a4ad..ecac57ba839 100644
--- a/engines/crab/ui/MapData.cpp
+++ b/engines/crab/ui/MapData.cpp
@@ -37,8 +37,8 @@ namespace Crab {
 using namespace pyrodactyl::ui;
 
 void MapData::load(rapidxml::xml_node<char> *node) {
-	loadStr(_pathBg, "bg", node);
-	loadStr(_pathOverlay, "overlay", node);
+	loadPath(_pathBg, "bg", node);
+	loadPath(_pathOverlay, "overlay", node);
 }
 
 void MapData::destAdd(const Common::String &name, const int &x, const int &y) {
diff --git a/engines/crab/ui/MapData.h b/engines/crab/ui/MapData.h
index 43edbab9798..3767aaef65b 100644
--- a/engines/crab/ui/MapData.h
+++ b/engines/crab/ui/MapData.h
@@ -39,7 +39,7 @@ namespace pyrodactyl {
 namespace ui {
 struct MapData {
 	// The paths of set of map images - background and the fully revealed map overlay
-	Common::String _pathBg, _pathOverlay;
+	Common::Path _pathBg, _pathOverlay;
 
 	// The places the player has revealed in this world map
 	Common::Array<Rect> _reveal;
diff --git a/engines/crab/ui/ModMenu.cpp b/engines/crab/ui/ModMenu.cpp
index 34d1b07ae1a..4a9855a9bf1 100644
--- a/engines/crab/ui/ModMenu.cpp
+++ b/engines/crab/ui/ModMenu.cpp
@@ -35,7 +35,7 @@ namespace Crab {
 
 using namespace pyrodactyl::ui;
 
-void ModMenu::load(const Common::String &filename) {
+void ModMenu::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("mod_menu");
@@ -49,7 +49,7 @@ void ModMenu::load(const Common::String &filename) {
 		if (nodeValid("preview", node)) {
 			auto prnode = node->first_node("preview");
 			_img._pos.load(prnode);
-			loadStr(_img._noPreviewPath, "path", prnode);
+			loadPath(_img._noPreviewPath, "path", prnode);
 		}
 
 		if (nodeValid("offset", node)) {
diff --git a/engines/crab/ui/ModMenu.h b/engines/crab/ui/ModMenu.h
index db555fc2101..2897fd0d46c 100644
--- a/engines/crab/ui/ModMenu.h
+++ b/engines/crab/ui/ModMenu.h
@@ -42,7 +42,7 @@ public:
 	ModMenu() {}
 	~ModMenu() {}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	bool handleEvents(const Common::Event &event);
 	void draw();
diff --git a/engines/crab/ui/OptionMenu.cpp b/engines/crab/ui/OptionMenu.cpp
index 0799fc4d33b..5508057961b 100644
--- a/engines/crab/ui/OptionMenu.cpp
+++ b/engines/crab/ui/OptionMenu.cpp
@@ -38,7 +38,7 @@ using namespace pyrodactyl::ui;
 using namespace pyrodactyl::image;
 using namespace pyrodactyl::music;
 
-void OptionMenu::load(const Common::String &filename) {
+void OptionMenu::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("option");
diff --git a/engines/crab/ui/OptionMenu.h b/engines/crab/ui/OptionMenu.h
index 9ee04b2c25f..3ec8145795c 100644
--- a/engines/crab/ui/OptionMenu.h
+++ b/engines/crab/ui/OptionMenu.h
@@ -105,7 +105,7 @@ public:
 		return _keybind.disableHotkeys();
 	}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 	void draw(Button &back);
 	bool handleEvents(Button &back, const Common::Event &event);
 	void internalEvents();
diff --git a/engines/crab/ui/PersonScreen.cpp b/engines/crab/ui/PersonScreen.cpp
index 1d2a7149a43..a05ecf8b381 100644
--- a/engines/crab/ui/PersonScreen.cpp
+++ b/engines/crab/ui/PersonScreen.cpp
@@ -37,7 +37,7 @@ using namespace pyrodactyl::event;
 using namespace pyrodactyl::image;
 using namespace pyrodactyl::people;
 
-void PersonScreen::load(const Common::String &filename) {
+void PersonScreen::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("character");
diff --git a/engines/crab/ui/PersonScreen.h b/engines/crab/ui/PersonScreen.h
index 4d78944f854..cdef93ca682 100644
--- a/engines/crab/ui/PersonScreen.h
+++ b/engines/crab/ui/PersonScreen.h
@@ -68,7 +68,7 @@ public:
 
 	~PersonScreen() {}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 	void Cache(pyrodactyl::event::Info &info, const Common::String &id, pyrodactyl::level::Level &level);
 
 	void handleEvents(pyrodactyl::event::Info &info, const Common::String &id, const Common::Event &event);
diff --git a/engines/crab/ui/ReplyMenu.cpp b/engines/crab/ui/ReplyMenu.cpp
index f3dc02c4a1c..b10903c8a9d 100644
--- a/engines/crab/ui/ReplyMenu.cpp
+++ b/engines/crab/ui/ReplyMenu.cpp
@@ -41,7 +41,7 @@ using namespace pyrodactyl::music;
 using namespace pyrodactyl::event;
 using namespace pyrodactyl::people;
 
-void ReplyMenu::load(const Common::String &filename) {
+void ReplyMenu::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("conversation");
diff --git a/engines/crab/ui/ReplyMenu.h b/engines/crab/ui/ReplyMenu.h
index e44fb2d4cab..de6acc43c4e 100644
--- a/engines/crab/ui/ReplyMenu.h
+++ b/engines/crab/ui/ReplyMenu.h
@@ -61,7 +61,7 @@ public:
 
 	~ReplyMenu() {}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	int handleEvents(pyrodactyl::event::Info &info, pyrodactyl::event::ConversationData &dat,
 					 const Common::String &curId, PersonHandler &oh, const Common::Event &Event);
diff --git a/engines/crab/ui/SlideShow.cpp b/engines/crab/ui/SlideShow.cpp
index fd8da76ea10..39a4a5db166 100644
--- a/engines/crab/ui/SlideShow.cpp
+++ b/engines/crab/ui/SlideShow.cpp
@@ -56,8 +56,8 @@ void SlideShow::load(rapidxml::xml_node<char> *node) {
 
 		_path.clear();
 		for (auto n = node->first_node("slide"); n != nullptr; n = n->next_sibling("slide")) {
-			Common::String p;
-			loadStr(p, "path", n);
+			Common::Path p;
+			loadPath(p, "path", n);
 			_path.push_back(p);
 		}
 
diff --git a/engines/crab/ui/SlideShow.h b/engines/crab/ui/SlideShow.h
index aba7ec62c61..dfccdd29f27 100644
--- a/engines/crab/ui/SlideShow.h
+++ b/engines/crab/ui/SlideShow.h
@@ -41,7 +41,7 @@ namespace pyrodactyl {
 namespace ui {
 class SlideShow {
 	// The list of images and where they are located, and the current image
-	Common::Array<Common::String> _path;
+	Common::Array<Common::Path> _path;
 
 	// We only load the current image in memory
 	pyrodactyl::image::Image _img;
diff --git a/engines/crab/ui/hud.cpp b/engines/crab/ui/hud.cpp
index 37dcd18b118..1760876a376 100644
--- a/engines/crab/ui/hud.cpp
+++ b/engines/crab/ui/hud.cpp
@@ -42,7 +42,7 @@ using namespace pyrodactyl::ui;
 using namespace pyrodactyl::image;
 using namespace pyrodactyl::input;
 
-void HUD::load(const Common::String &filename, pyrodactyl::level::TalkNotify &tn, pyrodactyl::level::PlayerDestMarker &pdm) {
+void HUD::load(const Common::Path &filename, pyrodactyl::level::TalkNotify &tn, pyrodactyl::level::PlayerDestMarker &pdm) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("hud");
diff --git a/engines/crab/ui/hud.h b/engines/crab/ui/hud.h
index 2d26b5f1fdc..a39ac84e39d 100644
--- a/engines/crab/ui/hud.h
+++ b/engines/crab/ui/hud.h
@@ -97,7 +97,7 @@ public:
 
 	void State(const int &val);
 
-	void load(const Common::String &filename, pyrodactyl::level::TalkNotify &tn, pyrodactyl::level::PlayerDestMarker &pdm);
+	void load(const Common::Path &filename, pyrodactyl::level::TalkNotify &tn, pyrodactyl::level::PlayerDestMarker &pdm);
 
 	HUDSignal handleEvents(pyrodactyl::event::Info &info, const Common::Event &event);
 
diff --git a/engines/crab/ui/journal.cpp b/engines/crab/ui/journal.cpp
index bb2dec34475..3d05549def9 100644
--- a/engines/crab/ui/journal.cpp
+++ b/engines/crab/ui/journal.cpp
@@ -40,7 +40,7 @@ using namespace pyrodactyl::ui;
 //------------------------------------------------------------------------
 // Purpose: Load game
 //------------------------------------------------------------------------
-void Journal::load(const Common::String &filename) {
+void Journal::load(const Common::Path &filename) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("objectives");
diff --git a/engines/crab/ui/journal.h b/engines/crab/ui/journal.h
index 05dce6d269e..0eff1527ad0 100644
--- a/engines/crab/ui/journal.h
+++ b/engines/crab/ui/journal.h
@@ -95,7 +95,7 @@ public:
 
 	~Journal() {}
 
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 	void draw(const Common::String &id);
 
 	// Return true if "go to map" is selected
diff --git a/engines/crab/ui/map.cpp b/engines/crab/ui/map.cpp
index 630db45873a..a01aa056d48 100644
--- a/engines/crab/ui/map.cpp
+++ b/engines/crab/ui/map.cpp
@@ -42,7 +42,7 @@ using namespace pyrodactyl::input;
 //------------------------------------------------------------------------
 // Purpose: Load stuff that can't be modified by the user
 //------------------------------------------------------------------------
-void Map::load(const Common::String &filename, pyrodactyl::event::Info &info) {
+void Map::load(const Common::Path &filename, pyrodactyl::event::Info &info) {
 	XMLDoc conf(filename);
 	if (conf.ready()) {
 		rapidxml::xml_node<char> *node = conf.doc()->first_node("map");
diff --git a/engines/crab/ui/map.h b/engines/crab/ui/map.h
index e219c62329e..51cf4bd5773 100644
--- a/engines/crab/ui/map.h
+++ b/engines/crab/ui/map.h
@@ -116,7 +116,7 @@ public:
 		_imgOverlay.deleteImage();
 	}
 
-	void load(const Common::String &filename, pyrodactyl::event::Info &info);
+	void load(const Common::Path &filename, pyrodactyl::event::Info &info);
 
 	void draw(pyrodactyl::event::Info &info);
 	bool handleEvents(pyrodactyl::event::Info &info, const Common::Event &event);


Commit: 94f6c8852b246c01a34dc0f7f147da8bad47d7a2
    https://github.com/scummvm/scummvm/commit/94f6c8852b246c01a34dc0f7f147da8bad47d7a2
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
CRYOMNI3D: Migrate engine to Path

Changed paths:
    engines/cryomni3d/cryomni3d.cpp
    engines/cryomni3d/dialogs_manager.cpp
    engines/cryomni3d/fixed_image.cpp
    engines/cryomni3d/font_manager.cpp
    engines/cryomni3d/fonts/cryoextfont.cpp
    engines/cryomni3d/fonts/cryofont.cpp
    engines/cryomni3d/versailles/dialogs_manager.cpp
    engines/cryomni3d/versailles/documentation.cpp
    engines/cryomni3d/versailles/engine.cpp
    engines/cryomni3d/versailles/menus.cpp
    engines/cryomni3d/versailles/music.cpp


diff --git a/engines/cryomni3d/cryomni3d.cpp b/engines/cryomni3d/cryomni3d.cpp
index fb9649a0d65..1270758fb5f 100644
--- a/engines/cryomni3d/cryomni3d.cpp
+++ b/engines/cryomni3d/cryomni3d.cpp
@@ -110,7 +110,7 @@ void CryOmni3DEngine::playHNM(const Common::Path &filepath, Audio::Mixer::SoundT
 	videoDecoder->setSoundType(soundType);
 
 	if (!videoDecoder->loadFile(filepath)) {
-		warning("Failed to open movie file %s", filepath.toString().c_str());
+		warning("Failed to open movie file %s", filepath.toString(Common::Path::kNativeSeparator).c_str());
 		delete videoDecoder;
 		return;
 	}
@@ -167,14 +167,14 @@ Image::ImageDecoder *CryOmni3DEngine::loadHLZ(const Common::Path &filepath) {
 	Common::File file;
 
 	if (!file.open(filepath)) {
-		warning("Failed to open hlz file %s", filepath.toString().c_str());
+		warning("Failed to open hlz file %s", filepath.toString(Common::Path::kNativeSeparator).c_str());
 		return nullptr;
 	}
 
 	Image::ImageDecoder *imageDecoder = new Image::HLZFileDecoder();
 
 	if (!imageDecoder->loadStream(file)) {
-		warning("Failed to load hlz file %s", filepath.toString().c_str());
+		warning("Failed to load hlz file %s", filepath.toString(Common::Path::kNativeSeparator).c_str());
 		delete imageDecoder;
 		imageDecoder = nullptr;
 		return nullptr;
diff --git a/engines/cryomni3d/dialogs_manager.cpp b/engines/cryomni3d/dialogs_manager.cpp
index 9911ef510a1..54fbc809379 100644
--- a/engines/cryomni3d/dialogs_manager.cpp
+++ b/engines/cryomni3d/dialogs_manager.cpp
@@ -33,7 +33,7 @@ DialogsManager::~DialogsManager() {
 void DialogsManager::loadGTO(const Common::Path &gtoFilePath) {
 	Common::File gtoFile;
 	if (!gtoFile.open(gtoFilePath)) {
-		error("Can't open GTO file '%s'", gtoFilePath.toString().c_str());
+		error("Can't open GTO file '%s'", gtoFilePath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	_labels.clear();
diff --git a/engines/cryomni3d/fixed_image.cpp b/engines/cryomni3d/fixed_image.cpp
index 66111ce21d2..f69bbdd731a 100644
--- a/engines/cryomni3d/fixed_image.cpp
+++ b/engines/cryomni3d/fixed_image.cpp
@@ -118,7 +118,7 @@ void ZonFixedImage::display() const {
 void ZonFixedImage::loadZones(const Common::Path &image) {
 	_zones.clear();
 
-	Common::String fname(image.getLastComponent().toString());
+	Common::String fname(image.baseName());
 	int lastDotPos = fname.findLastOf('.');
 	assert(lastDotPos > -1);
 	fname.erase(lastDotPos + 1);
@@ -128,7 +128,7 @@ void ZonFixedImage::loadZones(const Common::Path &image) {
 
 	Common::File zonFile;
 	if (!zonFile.open(zonPath)) {
-		error("Can't open ZON file '%s'", zonPath.toString().c_str());
+		error("Can't open ZON file '%s'", zonPath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	int32 zonesNumber = zonFile.size() / 26;
diff --git a/engines/cryomni3d/font_manager.cpp b/engines/cryomni3d/font_manager.cpp
index fad6efa7b5b..083b1172020 100644
--- a/engines/cryomni3d/font_manager.cpp
+++ b/engines/cryomni3d/font_manager.cpp
@@ -67,7 +67,7 @@ void FontManager::loadFonts(const Common::Array<Common::Path> &fontFiles,
 	_fonts.reserve(fontFiles.size());
 
 	Common::HashMap<Common::Path, Graphics::Font *,
-		Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualTo> fontsCache;
+		Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> fontsCache;
 
 	for (Common::Array<Common::Path>::const_iterator it = fontFiles.begin(); it != fontFiles.end();
 	        it++) {
@@ -108,7 +108,7 @@ void FontManager::loadTTFList(const Common::Path &ttfList, Common::CodePage code
 	Common::File list;
 
 	if (!list.open(ttfList)) {
-		error("can't open file %s", ttfList.toString().c_str());
+		error("can't open file %s", ttfList.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	Common::Path ttfParentDir(ttfList.getParent());
@@ -143,7 +143,7 @@ void FontManager::loadTTFList(const Common::Path &ttfList, Common::CodePage code
 		bool italic = sizeFlags.contains('I');
 
 		Common::Array<Common::Path> fontFiles;
-		fontFiles.push_back(fontFile);
+		fontFiles.push_back(Common::Path(fontFile));
 		fontFiles.push_back(ttfParentDir.appendComponent(fontFile));
 
 		// Use 96 dpi as it's the default under Windows
diff --git a/engines/cryomni3d/fonts/cryoextfont.cpp b/engines/cryomni3d/fonts/cryoextfont.cpp
index 7bc8d132b63..9151cf38fc3 100644
--- a/engines/cryomni3d/fonts/cryoextfont.cpp
+++ b/engines/cryomni3d/fonts/cryoextfont.cpp
@@ -40,7 +40,7 @@ void CryoExtFont::load(const Common::Path &fontFile, Common::CodePage codepage)
 	Common::File *crf = new Common::File();
 
 	if (!crf->open(fontFile)) {
-		error("can't open file %s", fontFile.toString().c_str());
+		error("can't open file %s", fontFile.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	_crf = crf;
@@ -63,7 +63,7 @@ void CryoExtFont::load(const Common::Path &fontFile, Common::CodePage codepage)
 	_crf->read(_comment, sizeof(_comment));
 	//debug("Comment %s", _comment);
 
-	Common::String offsetsFile = fontFile.getLastComponent().toString();
+	Common::String offsetsFile = fontFile.baseName();
 	offsetsFile.setChar('I', offsetsFile.size() - 1);
 	loadOffsets(fontFile.getParent().appendComponent(offsetsFile));
 }
@@ -72,7 +72,7 @@ void CryoExtFont::loadOffsets(const Common::Path &offsetsFile) {
 	Common::File cri;
 
 	if (!cri.open(offsetsFile)) {
-		error("can't open file %s", offsetsFile.toString().c_str());
+		error("can't open file %s", offsetsFile.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	uint32 counts = cri.size() / sizeof(uint32);
diff --git a/engines/cryomni3d/fonts/cryofont.cpp b/engines/cryomni3d/fonts/cryofont.cpp
index fa53c92ce4e..c9ae8000daa 100644
--- a/engines/cryomni3d/fonts/cryofont.cpp
+++ b/engines/cryomni3d/fonts/cryofont.cpp
@@ -31,7 +31,7 @@ void CryoFont::load(const Common::Path &fontFile) {
 	Common::File crf;
 
 	if (!crf.open(fontFile)) {
-		error("can't open file %s", fontFile.toString().c_str());
+		error("can't open file %s", fontFile.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	byte magic[8];
diff --git a/engines/cryomni3d/versailles/dialogs_manager.cpp b/engines/cryomni3d/versailles/dialogs_manager.cpp
index d4cbac70498..508957b23fc 100644
--- a/engines/cryomni3d/versailles/dialogs_manager.cpp
+++ b/engines/cryomni3d/versailles/dialogs_manager.cpp
@@ -106,14 +106,14 @@ void Versailles_DialogsManager::playDialog(const Common::String &video, const Co
 	Video::HNMDecoder *videoDecoder = new Video::HNMDecoder(g_system->getScreenFormat(), true);
 
 	if (!videoDecoder->loadFile(videoPath)) {
-		warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString().c_str());
+		warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString(Common::Path::kNativeSeparator).c_str());
 		delete videoDecoder;
 		return;
 	}
 
 	Common::File *audioFile = new Common::File();
 	if (!audioFile->open(soundPath)) {
-		warning("Failed to open sound file %s/%s", sound.c_str(), soundPath.toString().c_str());
+		warning("Failed to open sound file %s/%s", sound.c_str(), soundPath.toString(Common::Path::kNativeSeparator).c_str());
 		delete videoDecoder;
 		delete audioFile;
 		return;
@@ -357,7 +357,7 @@ void Versailles_DialogsManager::loadFrame(const Common::String &video) {
 	Video::HNMDecoder videoDecoder(g_system->getScreenFormat());
 
 	if (!videoDecoder.loadFile(videoPath)) {
-		warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString().c_str());
+		warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
diff --git a/engines/cryomni3d/versailles/documentation.cpp b/engines/cryomni3d/versailles/documentation.cpp
index 11225a3f641..c301c300084 100644
--- a/engines/cryomni3d/versailles/documentation.cpp
+++ b/engines/cryomni3d/versailles/documentation.cpp
@@ -97,7 +97,7 @@ void Versailles_Documentation::init(const Sprites *sprites, FontManager *fontMan
 	Common::File allDocsFile;
 
 	if (!allDocsFile.open(_allDocsFilePath)) {
-		error("Can't open %s", _allDocsFilePath.toString().c_str());
+		error("Can't open %s", _allDocsFilePath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	uint allDocsSize = allDocsFile.size();
@@ -1972,7 +1972,7 @@ Common::String Versailles_Documentation::getRecordTitle(const Common::String &re
 	Common::File allDocsFile;
 
 	if (!allDocsFile.open(_allDocsFilePath)) {
-		error("Can't open %s", _allDocsFilePath.toString().c_str());
+		error("Can't open %s", _allDocsFilePath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	allDocsFile.seek(recordInfo.position);
 
@@ -2001,7 +2001,7 @@ Common::String Versailles_Documentation::getRecordData(const Common::String &rec
 	Common::File allDocsFile;
 
 	if (!allDocsFile.open(_allDocsFilePath)) {
-		error("Can't open %s", _allDocsFilePath.toString().c_str());
+		error("Can't open %s", _allDocsFilePath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	allDocsFile.seek(recordInfo.position);
 
@@ -2055,7 +2055,7 @@ void Versailles_Documentation::loadLinksFile() {
 
 	Common::File linksFile;
 	if (!linksFile.open(_linksDocsFilePath)) {
-		error("Can't open links file: %s", _linksDocsFilePath.toString().c_str());
+		error("Can't open links file: %s", _linksDocsFilePath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	_linksSize = linksFile.size();
diff --git a/engines/cryomni3d/versailles/engine.cpp b/engines/cryomni3d/versailles/engine.cpp
index 772b81c2b56..d503703f0d6 100644
--- a/engines/cryomni3d/versailles/engine.cpp
+++ b/engines/cryomni3d/versailles/engine.cpp
@@ -80,7 +80,7 @@ bool CryOmni3DEngine_Versailles::hasFeature(EngineFeature f) const {
 
 void CryOmni3DEngine_Versailles::initializePath(const Common::FSNode &gamePath) {
 	// This works if the user has installed the game as required in the Wiki
-	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 4, false);
+	SearchMan.addDirectory(gamePath, 0, 4, false);
 
 	// CDs/DVD path
 	SearchMan.addSubDirectoryMatching(gamePath, "datas_v", 0, 4, false);
@@ -285,7 +285,7 @@ bool CryOmni3DEngine_Versailles::shouldAbort() {
 static bool checkFilePath(const Common::Path &basePath, Common::String &baseName, const char * const *extensions, Common::Path &fullPath) {
 	if (!extensions) {
 		fullPath = basePath.appendComponent(baseName);
-		debug(3, "Trying file %s", fullPath.toString().c_str());
+		debug(3, "Trying file %s", fullPath.toString(Common::Path::kNativeSeparator).c_str());
 		return Common::File::exists(fullPath);
 	}
 
@@ -293,7 +293,7 @@ static bool checkFilePath(const Common::Path &basePath, Common::String &baseName
 	while (*extensions != nullptr) {
 		baseName += *extensions;
 		fullPath = basePath.appendComponent(baseName);
-		debug(3, "Trying file %s", fullPath.toString().c_str());
+		debug(3, "Trying file %s", fullPath.toString(Common::Path::kNativeSeparator).c_str());
 		if (Common::File::exists(fullPath)) {
 			return true;
 		}
@@ -456,7 +456,7 @@ Common::Path CryOmni3DEngine_Versailles::getFilePath(FileType fileType,
 
 	if (!hasLevel) {
 		warning("Failed to find file %s in %s", baseName.c_str(), baseDir);
-		return baseName;
+		return Common::Path(baseName);
 	}
 
 	assert(baseName_.size() > 0);
@@ -464,7 +464,7 @@ Common::Path CryOmni3DEngine_Versailles::getFilePath(FileType fileType,
 			baseName_[0] > '7' ||
 			uint(baseName_[0] - '0') == _currentLevel) {
 		warning("Failed to find file %s in %s (level %d)", baseName.c_str(), baseDir, _currentLevel);
-		return baseName;
+		return Common::Path(baseName);
 	}
 
 	int fileLevel = baseName_[0] - '0';
@@ -475,7 +475,7 @@ Common::Path CryOmni3DEngine_Versailles::getFilePath(FileType fileType,
 	}
 
 	warning("Failed to find file %s in %s (levels %d and %d)", baseName.c_str(), baseDir, _currentLevel, fileLevel);
-	return baseName;
+	return Common::Path(baseName);
 }
 
 void CryOmni3DEngine_Versailles::setupFonts() {
@@ -987,7 +987,7 @@ void CryOmni3DEngine_Versailles::setupLevelWarps(int level) {
 	Common::File wamFile;
 	Common::Path wamPath = getFilePath(kFileTypeWAM, Common::String::format("level%d.wam", level));
 	if (!wamFile.open(wamPath)) {
-		error("Can't open WAM file '%s'", wamPath.toString().c_str());
+		error("Can't open WAM file '%s'", wamPath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	_wam.loadStream(wamFile);
 
@@ -1943,10 +1943,10 @@ void CryOmni3DEngine_Versailles::loadBMPs(const char *pattern, Graphics::Surface
 		Common::Path bmp = getFilePath(kFileTypeSpriteBmp, Common::String::format(pattern, i));
 
 		if (!file.open(bmp)) {
-			error("Failed to open BMP file: %s", bmp.toString().c_str());
+			error("Failed to open BMP file: %s", bmp.toString(Common::Path::kNativeSeparator).c_str());
 		}
 		if (!bmpDecoder.loadStream(file)) {
-			error("Failed to load BMP file: %s", bmp.toString().c_str());
+			error("Failed to load BMP file: %s", bmp.toString(Common::Path::kNativeSeparator).c_str());
 		}
 		bmps[i].copyFrom(*bmpDecoder.getSurface());
 		bmpDecoder.destroy();
diff --git a/engines/cryomni3d/versailles/menus.cpp b/engines/cryomni3d/versailles/menus.cpp
index d79e40001f9..e1013c20250 100644
--- a/engines/cryomni3d/versailles/menus.cpp
+++ b/engines/cryomni3d/versailles/menus.cpp
@@ -303,7 +303,7 @@ uint CryOmni3DEngine_Versailles::displayOptions() {
 							Common::Path orguePath(getFilePath(kFileTypeSound, "ORGUE.WAV"));
 							Common::File *audioFile = new Common::File();
 							if (!audioFile->open(orguePath)) {
-								warning("Failed to open sound file %s", orguePath.toString().c_str());
+								warning("Failed to open sound file %s", orguePath.toString(Common::Path::kNativeSeparator).c_str());
 								delete audioFile;
 								break;
 							}
diff --git a/engines/cryomni3d/versailles/music.cpp b/engines/cryomni3d/versailles/music.cpp
index a02dd878f1f..a7cc9a34831 100644
--- a/engines/cryomni3d/versailles/music.cpp
+++ b/engines/cryomni3d/versailles/music.cpp
@@ -71,7 +71,7 @@ void CryOmni3DEngine_Versailles::musicUpdate() {
 
 	Common::File *musicFile = new Common::File();
 	if (!musicFile->open(musicPath)) {
-		warning("Failed to open music file %s/%s", musicBName, musicPath.toString().c_str());
+		warning("Failed to open music file %s/%s", musicBName, musicPath.toString(Common::Path::kNativeSeparator).c_str());
 		delete musicFile;
 		return;
 	}
@@ -81,7 +81,7 @@ void CryOmni3DEngine_Versailles::musicUpdate() {
 	musicFile = nullptr;
 
 	if (!musicDecoder) {
-		warning("Failed to decode music file %s/%s", musicBName, musicPath.toString().c_str());
+		warning("Failed to decode music file %s/%s", musicBName, musicPath.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 


Commit: cf3eac29c3f5add0bcf2e17bcf270cb934bfde69
    https://github.com/scummvm/scummvm/commit/cf3eac29c3f5add0bcf2e17bcf270cb934bfde69
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
DIRECTOR: Migrate engine to Path

Changed paths:
    engines/director/archive.cpp
    engines/director/archive.h
    engines/director/cast.cpp
    engines/director/castmember/bitmap.cpp
    engines/director/castmember/digitalvideo.cpp
    engines/director/debugger.cpp
    engines/director/debugger.h
    engines/director/detection.cpp
    engines/director/director.cpp
    engines/director/director.h
    engines/director/game-quirks.cpp
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-funcs.cpp
    engines/director/lingo/lingo-mci.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/xlibs/fileio.cpp
    engines/director/lingo/xlibs/misc.cpp
    engines/director/lingo/xlibs/unittest.cpp
    engines/director/movie.cpp
    engines/director/resource.cpp
    engines/director/score.cpp
    engines/director/tests.cpp
    engines/director/util.cpp
    engines/director/util.h
    engines/director/window.cpp
    engines/director/window.h


diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 0d63c825ccb..9cdcf7ef044 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -43,13 +43,13 @@ Archive::~Archive() {
 	close();
 }
 
-Common::String Archive::getFileName() const { return Director::getFileName(_pathName); }
+Common::String Archive::getFileName() const { return Director::getFileName(_pathName.toString(g_director->_dirSeparator)); }
 
 bool Archive::openFile(const Common::Path &path) {
 	Common::File *file = new Common::File();
 
 	if (path.empty() || !file->open(path)) {
-		warning("Archive::openFile(): Error opening file %s", path.toString().c_str());
+		warning("Archive::openFile(): Error opening file %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		delete file;
 		return false;
 	}
@@ -57,7 +57,7 @@ bool Archive::openFile(const Common::Path &path) {
 	_pathName = path.toString(g_director->_dirSeparator);
 
 	if (!openStream(file)) {
-		warning("Archive::openFile(): Error loading stream from file %s", path.toString().c_str());
+		warning("Archive::openFile(): Error loading stream from file %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		close();
 		return false;
 	}
@@ -107,7 +107,7 @@ void Archive::listUnaccessedChunks() {
 	}
 
 	if (!s.empty())
-		debugC(5, kDebugLoading, "Unaccessed Chunks in '%s':\n%s", _pathName.c_str(), s.c_str());
+		debugC(5, kDebugLoading, "Unaccessed Chunks in '%s':\n%s", _pathName.toString(g_director->_dirSeparator).c_str(), s.c_str());
 }
 
 int Archive::getFileSize() {
@@ -267,12 +267,12 @@ void Archive::dumpChunk(Resource &res, Common::DumpFile &out) {
 		dataSize = resStream->size();
 	}
 
-	Common::String prepend = _pathName.size() ? _pathName : "stream";
-	Common::String filename = Common::String::format("./dumps/%s-%s-%d", encodePathForDump(prepend).c_str(), tag2str(res.tag), res.index);
+	Common::Path prepend = _pathName.empty() ? _pathName : "stream";
+	Common::Path filename(Common::String::format("./dumps/%s-%s-%d", encodePathForDump(prepend.toString(g_director->_dirSeparator)).c_str(), tag2str(res.tag), res.index), '/');
 	resStream->read(data, len);
 
 	if (!out.open(filename, true)) {
-		warning("Archive::dumpChunk(): Can not open dump file %s", filename.c_str());
+		warning("Archive::dumpChunk(): Can not open dump file %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	} else {
 		out.write(data, len);
 		out.flush();
@@ -317,10 +317,12 @@ bool MacArchive::openFile(const Common::Path &path) {
 		return false;
 	}
 
-	_pathName = _resFork->getBaseFileName().toString(g_director->_dirSeparator);
-	if (_pathName.hasSuffix(".bin")) {
+	_pathName = _resFork->getBaseFileName();
+	Common::String basename(_pathName.baseName());
+	if (basename.hasSuffix(".bin")) {
 		for (int i = 0; i < 4; i++)
-			_pathName.deleteLastChar();
+			basename.deleteLastChar();
+		_pathName = _pathName.getParent().appendComponent(basename);
 	}
 
 	readTags();
@@ -344,7 +346,7 @@ bool MacArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffs
 	}
 
 	_pathName = "<stream>";
-	_resFork->setBaseFileName(_pathName);
+	_resFork->setBaseFileName(Common::Path(_pathName));
 
 	readTags();
 
diff --git a/engines/director/archive.h b/engines/director/archive.h
index 6553437566c..a537287c29d 100644
--- a/engines/director/archive.h
+++ b/engines/director/archive.h
@@ -59,9 +59,9 @@ public:
 	virtual bool openStream(Common::SeekableReadStream *stream, uint32 offset = 0) = 0;
 	virtual void close();
 
-	Common::String getPathName() const { return _pathName; }
+	Common::Path getPathName() const { return _pathName; }
 	Common::String getFileName() const;
-	void setPathName(const Common::String &name) { _pathName = name; }
+	void setPathName(const Common::Path &name) { _pathName = name; }
 	int getFileSize();
 
 	bool isOpen() const { return _stream != 0; }
@@ -94,7 +94,7 @@ protected:
 	TypeMap _types;
 	MovieChunkMap _movieChunks;
 
-	Common::String _pathName;
+	Common::Path _pathName;
 };
 
 class MacArchive : public Archive {
@@ -179,7 +179,7 @@ private:
 		uint32 offset;
 		uint32 size;
 	};
-	typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, Entry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _files;
 	Common::Path _path;
 
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 90a753f8294..3e3cd664389 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -1123,10 +1123,10 @@ void Cast::loadScriptV2(Common::SeekableReadStreamEndian &stream, uint16 id) {
 
 void Cast::dumpScript(const char *script, ScriptType type, uint16 id) {
 	Common::DumpFile out;
-	Common::String buf = dumpScriptName(encodePathForDump(_macName).c_str(), type, id, "txt");
+	Common::Path buf(dumpScriptName(encodePathForDump(_macName).c_str(), type, id, "txt"));
 
 	if (!out.open(buf, true)) {
-		warning("Cast::dumpScript(): Can not open dump file %s", buf.c_str());
+		warning("Cast::dumpScript(): Can not open dump file %s", buf.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index 9a4626e1b8c..866e36683d8 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -553,10 +553,10 @@ void BitmapCastMember::load() {
 					return;
 				} else {
 					delete decoder;
-					warning("BUILDBOT: BitmapCastMember::load(): wrong format for external picture '%s'", location.toString().c_str());
+					warning("BUILDBOT: BitmapCastMember::load(): wrong format for external picture '%s'", location.toString(Common::Path::kNativeSeparator).c_str());
 				}
 			} else {
-				warning("BitmapCastMember::load(): cannot open external picture '%s'", location.toString().c_str());
+				warning("BitmapCastMember::load(): cannot open external picture '%s'", location.toString(Common::Path::kNativeSeparator).c_str());
 			}
 		}
 	} else {
diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index 31cac08e901..5273cd525d2 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -105,7 +105,7 @@ bool DigitalVideoCastMember::loadVideo(Common::String path) {
 		return false;
 	}
 
-	debugC(2, kDebugLoading | kDebugImages, "Loading video %s -> %s", path.c_str(), location.toString().c_str());
+	debugC(2, kDebugLoading | kDebugImages, "Loading video %s -> %s", path.c_str(), location.toString(Common::Path::kNativeSeparator).c_str());
 	bool result = _video->loadFile(location);
 	if (!result) {
 		delete _video;
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 0d5dfb00057..42b3534bd4a 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -262,7 +262,7 @@ bool Debugger::cmdInfo(int argc, const char **argv) {
 	Score *score = movie->getScore();
 	Archive *archive = movie->getArchive();
 	Cast *cast = movie->getCast();
-	debugPrintf("Movie path: %s\n", archive->getPathName().c_str());
+	debugPrintf("Movie path: %s\n", archive->getPathName().toString(g_director->_dirSeparator).c_str());
 	debugPrintf("Movie file size: %d\n", archive->getFileSize());
 	debugPrintf("Movie archive format: %s\n", archive->formatArchiveInfo().c_str());
 	debugPrintf("Movie platform: %s (%s)\n", Common::getPlatformCode(movie->_platform), Common::getPlatformDescription(movie->_platform));
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index bfdea47549d..c75cb3caa69 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -125,7 +125,7 @@ private:
 
 
 	Common::DumpFile _out;
-	Common::String _outName;
+	Common::Path _outName;
 
 	bool _nextFrame;
 	int _nextFrameCounter;
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index d1c489e1222..1ea6dfd31cf 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -289,9 +289,10 @@ ADDetectedGame DirectorMetaEngineDetection::fallbackDetect(const FileMap &allFil
 		ADDetectedGame game(&desc->desc);
 
 		FileProperties tmp;
-		if (getFileProperties(allFiles, kMD5Tail, file->getName(), tmp)) {
+		Common::Path filename(file->getPathInArchive());
+		if (getFileProperties(allFiles, kMD5Tail, filename, tmp)) {
 			game.hasUnknownFiles = true;
-			game.matchedFiles[file->getName()] = tmp;
+			game.matchedFiles[filename] = tmp;
 		}
 
 		return game;
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 62cfa5a329f..e51c1083584 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -104,9 +104,9 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
 
 	_wm = nullptr;
 
-	_gameDataDir = Common::FSNode(ConfMan.get("path"));
+	_gameDataDir = Common::FSNode(ConfMan.getPath("path"));
 
-	SearchMan.addDirectory(_gameDataDir.getPath(), _gameDataDir, 0, 5);
+	SearchMan.addDirectory(_gameDataDir, 0, 5);
 
 	for (uint i = 0; Director::directoryGlobs[i]; i++) {
 		Common::String directoryGlob = directoryGlobs[i];
@@ -390,8 +390,8 @@ StartMovie DirectorEngine::getStartMovie() const {
 	return _options.startMovie;
 }
 
-Common::String DirectorEngine::getStartupPath() const {
-	return _options.startupPath;
+Common::Path DirectorEngine::getStartupPath() const {
+	return Common::Path(_options.startupPath, g_director->_dirSeparator);
 }
 
 bool DirectorEngine::desktopEnabled() {
diff --git a/engines/director/director.h b/engines/director/director.h
index 014d75e0d6e..e5155108851 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -177,7 +177,7 @@ public:
 	void setCurrentMovie(Movie *movie);
 	Common::String getCurrentPath() const;
 	Common::String getCurrentAbsolutePath();
-	Common::String getStartupPath() const;
+	Common::Path getStartupPath() const;
 
 	// graphics.cpp
 	bool hasFeature(EngineFeature f) const override;
@@ -308,7 +308,7 @@ private:
 
 public:
 	int _tickBaseline;
-	Common::String _traceLogFile;
+	Common::Path _traceLogFile;
 
 	uint16 _framesRan = 0; // used by kDebugFewFramesOnly
 };
diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index 2f46608f633..5ed1c48b6a2 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -30,7 +30,7 @@ namespace Director {
 class CachedArchive : public Common::Archive {
 public:
 	struct InputEntry {
-		Common::String name;
+		Common::Path name;
 
 		const byte *data;
 		uint32 size;
@@ -53,7 +53,7 @@ private:
 		uint32 size;
 	};
 
-	typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, Entry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _files;
 };
 
@@ -265,7 +265,7 @@ CachedArchive::CachedArchive(const FileInputList &files)
 		entry.data = i->data;
 		entry.size = i->size;
 
-		Common::String name = i->name;
+		Common::Path name = i->name;
 		name.toLowercase();
 		_files[name] = entry;
 	}
@@ -276,8 +276,7 @@ CachedArchive::~CachedArchive() {
 }
 
 bool CachedArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return (_files.find(name) != _files.end());
+	return (_files.find(path) != _files.end());
 }
 
 int CachedArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -292,16 +291,14 @@ int CachedArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr CachedArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *CachedArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	FileMap::const_iterator fDesc = _files.find(name);
+	FileMap::const_iterator fDesc = _files.find(path);
 	if (fDesc == _files.end())
 		return nullptr;
 
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 78f5a440177..b923c824c6a 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1181,7 +1181,7 @@ void LB::b_closeResFile(int nargs) {
 	}
 
 	Datum d = g_lingo->pop();
-	Common::String resFileName = g_director->getCurrentWindow()->getCurrentPath() + d.asString();
+	Common::Path resFileName(g_director->getCurrentWindow()->getCurrentPath() + d.asString(), g_director->_dirSeparator);
 
 	if (g_director->_openResFiles.contains(resFileName)) {
 		g_director->_openResFiles.erase(resFileName);
@@ -1230,7 +1230,7 @@ void LB::b_getNthFileNameInFolder(int nargs) {
 	if (cache) {
 		Common::ArchiveMemberList files;
 
-		cache->listMatchingMembers(files, path.toString() + (path.empty() ? "*" : "/*"), true);
+		cache->listMatchingMembers(files, path.append(path.empty() ? "*" : "/*", '/'), true);
 
 		for (auto &fi : files) {
 			fileNameList.push_back(Common::lastPathComponent(fi->getName(), '/'));
@@ -1241,7 +1241,7 @@ void LB::b_getNthFileNameInFolder(int nargs) {
 	if (d.exists()) {
 		Common::FSList f;
 		if (!d.getChildren(f, Common::FSNode::kListAll)) {
-			warning("Cannot access directory %s", path.toString().c_str());
+			warning("Cannot access directory %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		} else {
 			for (uint i = 0; i < f.size(); i++)
 				fileNameList.push_back(f[i].getName());
@@ -1279,7 +1279,7 @@ void LB::b_openDA(int nargs) {
 
 void LB::b_openResFile(int nargs) {
 	Datum d = g_lingo->pop();
-	Common::String resPath = g_director->getCurrentWindow()->getCurrentPath() + d.asString();
+	Common::Path resPath(g_director->getCurrentWindow()->getCurrentPath() + d.asString(), g_director->_dirSeparator);
 
 	if (g_director->getPlatform() == Common::kPlatformWindows) {
  		warning("STUB: BUILDBOT: b_openResFile(%s) on Windows", d.asString().c_str());
@@ -1288,7 +1288,7 @@ void LB::b_openResFile(int nargs) {
 
 	if (!g_director->_allSeenResFiles.contains(resPath)) {
 		MacArchive *arch = new MacArchive();
-		if (arch->openFile(findPath(resPath).toString())) {
+		if (arch->openFile(findPath(resPath))) {
 			g_director->_openResFiles.setVal(resPath, arch);
 			g_director->_allSeenResFiles.setVal(resPath, arch);
 			g_director->addArchiveToOpenList(resPath);
@@ -1306,7 +1306,7 @@ void LB::b_openXlib(int nargs) {
 	Datum d = g_lingo->pop();
 	if (g_director->getPlatform() == Common::kPlatformMacintosh) {
 		// try opening the file as a Macintosh resource fork
-		Common::String resPath = g_director->getCurrentWindow()->getCurrentPath() + d.asString();
+		Common::Path resPath(g_director->getCurrentWindow()->getCurrentPath() + d.asString(), g_director->_dirSeparator);
 		MacArchive *resFile = new MacArchive();
 		if (resFile->openFile(resPath)) {
 			uint32 XCOD = MKTAG('X', 'C', 'O', 'D');
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index a4ffdfc3fd4..94889525c5a 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -1277,7 +1277,7 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
 	bool skipdump = false;
 
 	if (ConfMan.getBool("dump_scripts")) {
-		Common::String buf;
+		Common::Path buf;
 		if (scriptFlags & kScriptFlagFactoryDef) {
 			buf = dumpFactoryName(encodePathForDump(archName).c_str(), factoryName.c_str(), "lscr");
 		} else {
@@ -1285,10 +1285,10 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
 		}
 
 		if (!out.open(buf, true)) {
-			warning("Lingo::addCodeV4(): Can not open dump file %s", buf.c_str());
+			warning("Lingo::addCodeV4(): Can not open dump file %s", buf.toString(Common::Path::kNativeSeparator).c_str());
 			skipdump = true;
 		} else {
-			warning("Lingo::addCodeV4(): Dumping Lscr to %s", buf.c_str());
+			warning("Lingo::addCodeV4(): Dumping Lscr to %s", buf.toString(Common::Path::kNativeSeparator).c_str());
 		}
 	}
 
diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp
index b3f19d1d494..d748084a3db 100644
--- a/engines/director/lingo/lingo-funcs.cpp
+++ b/engines/director/lingo/lingo-funcs.cpp
@@ -178,7 +178,7 @@ void Lingo::func_play(Datum &frame, Datum &movie) {
 	}
 
 	if (movie.type != VOID) {
-		ref.movie = _vm->getCurrentMovie()->_movieArchive->getPathName();
+		ref.movie = _vm->getCurrentMovie()->_movieArchive->getPathName().toString(g_director->_dirSeparator);
 	}
 	ref.frameI = _vm->getCurrentMovie()->getScore()->getCurrentFrameNum();
 
diff --git a/engines/director/lingo/lingo-mci.cpp b/engines/director/lingo/lingo-mci.cpp
index 0464dea8b10..e35e60e340c 100644
--- a/engines/director/lingo/lingo-mci.cpp
+++ b/engines/director/lingo/lingo-mci.cpp
@@ -433,7 +433,7 @@ void Lingo::func_mci(const Common::String &name) {
     case MCI_OPEN: {
         Common::File *file = new Common::File();
 
-        if (!file->open(parsedCmd.device)) {
+        if (!file->open(Common::Path(parsedCmd.device, g_director->_dirSeparator))) {
             warning("func_mci(): Failed to open %s", parsedCmd.device.c_str());
             delete file;
             return;
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index c51534815cd..13d21e1a0f0 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -886,7 +886,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 		break;
 	case kTheTraceLogFile:
 		d.type = STRING;
-		d.u.s = new Common::String(g_director->_traceLogFile);
+		d.u.s = new Common::String(g_director->_traceLogFile.toString(Common::Path::kNativeSeparator));
 		break;
 	case kTheUpdateMovieEnabled:
 		d = g_lingo->_updateMovieEnabled;
@@ -1195,14 +1195,14 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
 	case kTheTraceLogFile:
 	{
 		if (d.asString().size()) {
-			Common::String logPath = ConfMan.get("path") + "/" + d.asString();
+			Common::Path logPath = ConfMan.getPath("path").appendComponent(d.asString());
 			Common::FSNode out(logPath);
 			if (!out.exists())
 				out.createWriteStream();
 			if (out.isWritable())
 				g_director->_traceLogFile = logPath;
 			else
-				warning("traceLogFile '%s' is not writeable", logPath.c_str());
+				warning("traceLogFile '%s' is not writeable", logPath.toString(Common::Path::kNativeSeparator).c_str());
 		} else {
 			g_director->_traceLogFile.clear();
 		}
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 077d19e5114..ac81bf5f6df 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1389,16 +1389,16 @@ void Lingo::runTests() {
 	Common::File inFile;
 	Common::ArchiveMemberList fsList;
 	SearchMan.listMatchingMembers(fsList, "*.lingo");
-	Common::StringArray fileList;
+	Common::Array<Common::Path> fileList;
 
 	LingoArchive *mainArchive = g_director->getCurrentMovie()->getMainLingoArch();
 
-	Common::String startMovie = _vm->getStartMovie().startMovie;
-	if (startMovie.size() > 0) {
+	Common::Path startMovie = Common::Path(_vm->getStartMovie().startMovie, g_director->_dirSeparator);
+	if (!startMovie.empty()) {
 		fileList.push_back(startMovie);
 	} else {
 		for (auto &it : fsList)
-			fileList.push_back(it->getName());
+			fileList.push_back(it->getPathInArchive());
 	}
 
 	Common::sort(fileList.begin(), fileList.end());
@@ -1414,7 +1414,7 @@ void Lingo::runTests() {
 
 			stream->read(script, size);
 
-			debug(">> Compiling file %s of size %d, id: %d", fileList[i].c_str(), size, counter);
+			debug(">> Compiling file %s of size %d, id: %d", fileList[i].toString(g_director->_dirSeparator).c_str(), size, counter);
 
 			mainArchive->addCode(Common::U32String(script, Common::kMacRoman), kTestScript, counter);
 
diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index 0300d5b137a..ec08637e0dd 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -275,7 +275,7 @@ void FileIO::m_new(int nargs) {
 		if (!inFile) {
 			Common::File *f = new Common::File;
 
-			if (!f->open(origpath)) {
+			if (!f->open(Common::Path(origpath, g_director->_dirSeparator))) {
 				delete f;
 				saveFileError();
 				me->dispose();
diff --git a/engines/director/lingo/xlibs/misc.cpp b/engines/director/lingo/xlibs/misc.cpp
index 1741814a62a..050f5b5aa0b 100644
--- a/engines/director/lingo/xlibs/misc.cpp
+++ b/engines/director/lingo/xlibs/misc.cpp
@@ -81,7 +81,7 @@ void Misc::m_getProfileString(int nargs) {
     }
 
     Common::INIFile config;
-    config.loadFromFile(filePath.toString());
+    config.loadFromFile(filePath);
 
     Common::String value;
     if (config.getKey(entry, section, value)) {
diff --git a/engines/director/lingo/xlibs/unittest.cpp b/engines/director/lingo/xlibs/unittest.cpp
index e12666a2f8e..a2fe7bfe0c2 100644
--- a/engines/director/lingo/xlibs/unittest.cpp
+++ b/engines/director/lingo/xlibs/unittest.cpp
@@ -99,7 +99,7 @@ void UnitTest::m_UTScreenshot(int nargs) {
 
 	Common::SeekableWriteStream *stream = file.createWriteStream();
 	if (!stream) {
-		warning("UnitTest::b_UTScreenshot(): could not open file %s", file.getPath().c_str());
+		warning("UnitTest::b_UTScreenshot(): could not open file %s", file.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
@@ -114,7 +114,7 @@ void UnitTest::m_UTScreenshot(int nargs) {
 	success = Image::writeBMP(*stream, *windowSurface);
 #endif
 	if (!success) {
-		warning("UnitTest::b_UTScreenshot(): error writing screenshot data to file %s", file.getPath().c_str());
+		warning("UnitTest::b_UTScreenshot(): error writing screenshot data to file %s", file.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	}
 	stream->finalize();
 	delete stream;
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index cc2adceed34..e8965fef860 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -373,7 +373,7 @@ void Movie::loadSharedCastsFrom(Common::Path &filename) {
 
 		return;
 	}
-	sharedCast->setPathName(filename.toString(g_director->_dirSeparator));
+	sharedCast->setPathName(filename);
 
 	debug(0, "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 	debug(0, "@@@@   Loading shared cast '%s'", sharedCast->getFileName().c_str());
diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index 49459fa3c5e..f93317cb2ed 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -85,7 +85,7 @@ Common::Error Window::loadInitialMovie() {
 		_currentMovie->loadSharedCastsFrom(sharedCastPath);
 
 	// load startup movie
-	Common::String startupPath = g_director->getStartupPath();
+	Common::Path startupPath = g_director->getStartupPath();
 	if (!startupPath.empty()) {
 		Common::SeekableReadStream *const stream = SearchMan.createReadStreamForMember(startupPath);
 		if (stream) {
@@ -158,7 +158,7 @@ void Window::probeResources(Archive *archive) {
 					_currentMovie = nullptr;
 				}
 
-				Archive *subMovie = g_director->openArchive(moviePath.toString());
+				Archive *subMovie = g_director->openArchive(moviePath);
 				if (subMovie) {
 					probeResources(subMovie);
 				}
@@ -174,8 +174,8 @@ void Window::probeResources(Archive *archive) {
 		// fork of the file to state which XObject or HyperCard XCMD/XFCNs
 		// need to be loaded in.
 		MacArchive *resFork = new MacArchive();
-		Common::String resForkPathName = archive->getPathName();
-		if (resFork->openFile(findPath(resForkPathName).toString())) {
+		Common::Path resForkPathName = archive->getPathName();
+		if (resFork->openFile(findPath(resForkPathName))) {
 			if (resFork->hasResource(MKTAG('X', 'C', 'O', 'D'), -1)) {
 				Common::Array<uint16> xcod = resFork->getResourceIDList(MKTAG('X', 'C', 'O', 'D'));
 				for (auto &iterator : xcod) {
@@ -237,7 +237,7 @@ Archive *DirectorEngine::openArchive(const Common::Path &path) {
 			return nullptr;
 		}
 	}
-	result->setPathName(path.toString(g_director->_dirSeparator));
+	result->setPathName(path);
 	_allSeenResFiles.setVal(path, result);
 
 	addArchiveToOpenList(path);
@@ -286,7 +286,7 @@ Archive *DirectorEngine::loadEXE(const Common::Path &movie) {
 			return nullptr;
 		}
 	} else {
-		Common::WinResources *exe = Common::WinResources::createFromEXE(movie.toString());
+		Common::WinResources *exe = Common::WinResources::createFromEXE(movie);
 		if (!exe) {
 			debugC(5, kDebugLoading, "DirectorEngine::loadEXE(): Failed to open EXE '%s'", movie.toString().c_str());
 			delete exeStream;
@@ -330,14 +330,14 @@ Archive *DirectorEngine::loadEXE(const Common::Path &movie) {
 		}
 
 		if (result) {
-			result->setPathName(movie.toString(g_director->_dirSeparator));
+			result->setPathName(movie);
 		}
 
 		return result;
 	}
 
 	if (result)
-		result->setPathName(movie.toString(g_director->_dirSeparator));
+		result->setPathName(movie);
 	else
 		delete exeStream;
 
@@ -533,7 +533,7 @@ Archive *DirectorEngine::loadMac(const Common::Path &movie) {
 			return nullptr;
 		}
 		result = new RIFXArchive();
-		result->setPathName(movie.toString(g_director->_dirSeparator));
+		result->setPathName(movie);
 
 		// First we need to detect PPC vs. 68k
 
@@ -717,7 +717,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 		// subtract 8 since we want to include tag and size as well
 		entry.offset = static_cast<uint32>(stream->pos() - 8);
 		entry.size = size + 8;
-		_files[path.toString()] = entry;
+		_files[path] = entry;
 
 		// Align size for the next seek.
 		size += (size % 2);
@@ -734,8 +734,7 @@ bool ProjectorArchive::loadArchive(Common::SeekableReadStream *stream) {
 }
 
 bool ProjectorArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return (_files.find(name) != _files.end());
+	return (_files.find(path) != _files.end());
 }
 
 int ProjectorArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -750,17 +749,14 @@ int ProjectorArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr ProjectorArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *ProjectorArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	FileMap::const_iterator fDesc = _files.find(name);
+	FileMap::const_iterator fDesc = _files.find(path);
 
 	if (fDesc == _files.end())
 		return nullptr;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 9b436664487..a71483ec787 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -1201,7 +1201,7 @@ void Score::screenShot() {
 	Common::String currentPath = _vm->getCurrentPath().c_str();
 	Common::replace(currentPath, Common::String(g_director->_dirSeparator), "-"); // exclude dir separator from screenshot filename prefix
 	Common::String prefix = Common::String::format("%s%s", currentPath.c_str(), Common::punycode_encodefilename(_movie->getMacName()).c_str());
-	Common::String filename = dumpScriptName(prefix.c_str(), kMovieScript, g_director->_framesRan, "png");
+	Common::Path filename = dumpScriptName(prefix.c_str(), kMovieScript, g_director->_framesRan, "png");
 
 	const char *buildNumber = getenv("BUILD_NUMBER");
 
@@ -1210,8 +1210,8 @@ void Score::screenShot() {
 		// The filename is in the form:
 		// ./dumps/theapartment/25/xn--Main Menu-zd0e-19.png
 
-		Common::String buildDir = Common::String::format("%s/%s", ConfMan.get("screenshotpath").c_str(),
-			g_director->getTargetName().c_str());
+		Common::Path buildDir(Common::String::format("%s/%s", ConfMan.get("screenshotpath").c_str(),
+			g_director->getTargetName().c_str()), '/');
 
 		// We run for the first time, let's check if we had the directory previously
 		if (_previousBuildBotBuild == -1) {
@@ -1227,7 +1227,7 @@ void Score::screenShot() {
 
 		// Now we try to find any previous dump
 		while (prevbuild > 0) {
-			filename = Common::String::format("%s/%d/%s-%d.png", buildDir.c_str(), prevbuild, prefix.c_str(), g_director->_framesRan);
+			filename = buildDir.join(Common::Path(Common::String::format("%d/%s-%d.png", prevbuild, prefix.c_str(), g_director->_framesRan), '/'));
 
 			Common::FSNode fs(filename);
 
@@ -1245,14 +1245,14 @@ void Score::screenShot() {
 
 			if (stream && decoder.loadStream(*stream)) {
 				if (checkShotSimilarity(decoder.getSurface(), newSurface)) {
-					warning("Screenshot is equal to previous one, skipping: %s", filename.c_str());
+					warning("Screenshot is equal to previous one, skipping: %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 					newSurface->free();
 					delete newSurface;
 					delete stream;
 					return;
 				}
 			} else {
-				warning("Error loading previous screenshot %s", filename.c_str());
+				warning("Error loading previous screenshot %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 			}
 
 			delete stream;
@@ -1262,16 +1262,16 @@ void Score::screenShot() {
 		// the screenshot was different from the previous one.
 		//
 		// Regenerate file name with the correct build number
-		filename = Common::String::format("%s/%s/%s-%d.png", buildDir.c_str(), buildNumber, prefix.c_str(), g_director->_framesRan);
+		filename = buildDir.join(Common::Path(Common::String::format("%s/%s-%d.png", buildNumber, prefix.c_str(), g_director->_framesRan), '/'));
 	}
 
 	Common::DumpFile screenshotFile;
 	if (screenshotFile.open(filename, true)) {
-		debug("Dumping screenshot to %s", filename.c_str());
+		debug("Dumping screenshot to %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 		Image::writePNG(screenshotFile, *newSurface);
 	} else {
-		warning("Cannot write screenshot to %s", filename.c_str());
+		warning("Cannot write screenshot to %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	newSurface->free();
diff --git a/engines/director/tests.cpp b/engines/director/tests.cpp
index 320d09119fd..6bfd9f5b127 100644
--- a/engines/director/tests.cpp
+++ b/engines/director/tests.cpp
@@ -142,11 +142,11 @@ void Window::testFontScaling() {
 }
 
 void Window::testFonts() {
-	Common::String fontName("Helvetica");
+	Common::Path fontName("Helvetica");
 
 	Common::MacResManager *fontFile = new Common::MacResManager();
 	if (!fontFile->open(fontName))
-		error("testFonts(): Could not open %s as a resource fork", fontName.c_str());
+		error("testFonts(): Could not open %s as a resource fork", fontName.toString(Common::Path::kNativeSeparator).c_str());
 
 	Common::MacResIDArray fonds = fontFile->getResIDArray(MKTAG('F','O','N','D'));
 	if (fonds.size() > 0) {
@@ -167,7 +167,7 @@ void Window::testFonts() {
 //////////////////////
 // Movie iteration
 //////////////////////
-Common::HashMap<Common::String, Movie *> *Window::scanMovies(const Common::String &folder) {
+Common::HashMap<Common::String, Movie *> *Window::scanMovies(const Common::Path &folder) {
 	Common::FSNode directory(folder);
 	Common::FSList movies;
 	const char *sharedMMMname;
@@ -192,7 +192,7 @@ Common::HashMap<Common::String, Movie *> *Window::scanMovies(const Common::Strin
 			}
 
 			warning("name: %s", i->getName().c_str());
-			Archive *arc = _vm->openArchive(i->getName());
+			Archive *arc = _vm->openArchive(i->getPathInArchive());
 			Movie *m = new Movie(this);
 			m->setArchive(arc);
 			nameMap->setVal(m->getMacName(), m);
@@ -205,7 +205,7 @@ Common::HashMap<Common::String, Movie *> *Window::scanMovies(const Common::Strin
 }
 
 void Window::enqueueAllMovies() {
-	Common::FSNode dir(ConfMan.get("path"));
+	Common::FSNode dir(ConfMan.getPath("path"));
 	Common::FSList files;
 	if (!dir.getChildren(files, Common::FSNode::kListFilesOnly)) {
 		warning("DirectorEngine::enqueueAllMovies(): Failed inquiring file list");
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 9e4f67e339e..73e6809f896 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -439,7 +439,7 @@ const char *recIndent() {
 	return tabs[recLevel];
 }
 
-bool isAbsolutePath(Common::String &path) {
+bool isAbsolutePath(const Common::String &path) {
 	// Starts with Mac directory notation for the game root
 	if (path.hasPrefix(Common::String("@") + g_director->_dirSeparator))
 		return true;
@@ -452,7 +452,7 @@ bool isAbsolutePath(Common::String &path) {
 	return false;
 }
 
-Common::Path toSafePath(Common::String &path) {
+Common::Path toSafePath(const Common::String &path) {
 	// Encode a Director raw path as a platform-independent path.
 	// This needs special care, as Mac filenames allow using '/' in them!
 	// - Scrub the pathname to be relative with the correct dir separator
@@ -471,7 +471,7 @@ Common::Path toSafePath(Common::String &path) {
 	return result;
 }
 
-Common::String convertPath(Common::String &path) {
+Common::String convertPath(const Common::String &path) {
 	if (path.empty())
 		return path;
 
@@ -520,7 +520,7 @@ Common::String unixToMacPath(const Common::String &path) {
 	return res;
 }
 
-Common::String getPath(Common::String path, Common::String cwd) {
+Common::String getPath(const Common::String &path, const Common::String &cwd) {
 	const char *s;
 	if ((s = strrchr(path.c_str(), g_director->_dirSeparator))) {
 		return Common::String(path.c_str(), s + 1);
@@ -529,7 +529,7 @@ Common::String getPath(Common::String path, Common::String cwd) {
 	return cwd; // The path is not altered
 }
 
-Common::String convert83Path(Common::String &path) {
+Common::String convert83Path(const Common::String &path) {
 	Common::String addedexts;
 	Common::String convPath;
 
@@ -564,9 +564,9 @@ Common::String convert83Path(Common::String &path) {
 	return convPath;
 }
 
-Common::Path resolveFSPath(Common::String &path, Common::Path &base, bool directory) {
+Common::Path resolveFSPath(const Common::String &path, const Common::Path &base, bool directory) {
 	// Path is the raw input from Director. Scrub it to be a clean relative path.
-	path = convertPath(path);
+	Common::String converted = convertPath(path);
 
 	// Absolute path to the game directory
 	Common::Path gamePath = Common::Path(g_director->getGameDataDir()->getPath());
@@ -580,7 +580,7 @@ Common::Path resolveFSPath(Common::String &path, Common::Path &base, bool direct
 	Common::FSNode filesystem(testPath);
 
 	// Split this into a component list for iteration.
-	Common::StringTokenizer directory_list(path, Common::String(g_director->_dirSeparator));
+	Common::StringTokenizer directory_list(converted, Common::String(g_director->_dirSeparator));
 	// newPath is our final result; construct this based on successful filesystem tests
 	Common::Path newPath = Common::Path(base);
 	if (!base.empty())
@@ -633,7 +633,7 @@ Common::Path resolveFSPath(Common::String &path, Common::Path &base, bool direct
 	return Common::Path();
 }
 
-Common::Path resolvePath(Common::String &path, Common::Path &base, bool directory, const char **exts) {
+Common::Path resolvePath(const Common::String &path, const Common::Path &base, bool directory, const char **exts) {
 	Common::Path result = resolveFSPath(path, base, directory);
 	if (!result.empty()) {
 		return result;
@@ -705,8 +705,8 @@ Common::Path resolvePath(Common::String &path, Common::Path &base, bool director
 	return Common::Path();
 }
 
-Common::Path resolvePartialPath(Common::String &path, Common::Path &base, bool directory, const char **exts) {
-	path = convertPath(path);
+Common::Path resolvePartialPath(const Common::String &path, const Common::Path &base, bool directory, const char **exts) {
+	Common::String converted = convertPath(path);
 	Common::Path result;
 
 	Common::StringArray baseTokens = base.splitComponents();
@@ -715,7 +715,7 @@ Common::Path resolvePartialPath(Common::String &path, Common::Path &base, bool d
 		Common::Path testBase = Common::Path::joinComponents(baseTokens);
 
 		// Try removing leading components of the target path
-		Common::StringArray tokens = Common::StringTokenizer(path, Common::String(g_director->_dirSeparator)).split();
+		Common::StringArray tokens = Common::StringTokenizer(converted, Common::String(g_director->_dirSeparator)).split();
 
 		while (tokens.size()) {
 			Common::String subpath;
@@ -742,7 +742,7 @@ Common::Path resolvePartialPath(Common::String &path, Common::Path &base, bool d
 	return result;
 }
 
-Common::Path resolvePathWithFuzz(Common::String &path, Common::Path &base, bool directory, const char **exts) {
+Common::Path resolvePathWithFuzz(const Common::String &path, const Common::Path &base, bool directory, const char **exts) {
 	Common::Path result = resolvePath(path, base, directory, exts);
 	if (result.empty()) {
 		// Try again with all non-FAT compatible characters stripped
@@ -759,7 +759,7 @@ Common::Path resolvePathWithFuzz(Common::String &path, Common::Path &base, bool
 	return result;
 }
 
-Common::Path resolvePartialPathWithFuzz(Common::String &path, Common::Path &base, bool directory, const char **exts) {
+Common::Path resolvePartialPathWithFuzz(const Common::String &path, const Common::Path &base, bool directory, const char **exts) {
 	Common::Path result = resolvePartialPath(path, base, directory, exts);
 	if (result.empty()) {
 		// Try again with all non-FAT compatible characters stripped
@@ -776,7 +776,11 @@ Common::Path resolvePartialPathWithFuzz(Common::String &path, Common::Path &base
 	return result;
 }
 
-Common::Path findPath(Common::String &path, bool currentFolder, bool searchPaths, bool directory, const char **exts) {
+Common::Path findPath(const Common::Path &path, bool currentFolder, bool searchPaths, bool directory, const char **exts) {
+	return findPath(path.toString(g_director->_dirSeparator), currentFolder, searchPaths, directory, exts);
+}
+
+Common::Path findPath(const Common::String &path, bool currentFolder, bool searchPaths, bool directory, const char **exts) {
 	Common::Path result, base;
 	debugN(9, "%s", recIndent());
 	debug(9, "findPath(): beginning search for \"%s\"", path.c_str());
@@ -853,7 +857,7 @@ Common::Path findPath(Common::String &path, bool currentFolder, bool searchPaths
 	return Common::Path();
 }
 
-Common::Path findMoviePath(Common::String &path, bool currentFolder, bool searchPaths) {
+Common::Path findMoviePath(const Common::String &path, bool currentFolder, bool searchPaths) {
 	const char *extsD3[] = { ".MMM", nullptr };
 	const char *extsD4[] = { ".DIR", ".DXR", ".EXE", nullptr };
 	const char *extsD5[] = { ".DIR", ".DXR", ".CST", ".CXT", ".EXE", nullptr };
@@ -874,7 +878,7 @@ Common::Path findMoviePath(Common::String &path, bool currentFolder, bool search
 	return result;
 }
 
-Common::Path findAudioPath(Common::String &path, bool currentFolder, bool searchPaths) {
+Common::Path findAudioPath(const Common::String &path, bool currentFolder, bool searchPaths) {
 	const char *exts[] = { ".AIF", ".WAV", nullptr };
 
 	Common::Path result = findPath(path, currentFolder, searchPaths, false, exts);
@@ -1026,7 +1030,7 @@ Common::String convertMacFilename(const char *name) {
 	return res;
 }
 
-Common::String dumpScriptName(const char *prefix, int type, int id, const char *ext) {
+Common::Path dumpScriptName(const char *prefix, int type, int id, const char *ext) {
 	Common::String typeName;
 
 	switch (type) {
@@ -1053,11 +1057,11 @@ Common::String dumpScriptName(const char *prefix, int type, int id, const char *
 		break;
 	}
 
-	return Common::String::format("./dumps/%s-%s-%d.%s", prefix, typeName.c_str(), id, ext);
+	return Common::Path(Common::String::format("./dumps/%s-%s-%d.%s", prefix, typeName.c_str(), id, ext), '/');
 }
 
-Common::String dumpFactoryName(const char *prefix, const char *name, const char *ext) {
-	return Common::String::format("./dumps/%s-factory-%s.%s", prefix, name, ext);
+Common::Path dumpFactoryName(const char *prefix, const char *name, const char *ext) {
+	return Common::Path(Common::String::format("./dumps/%s-factory-%s.%s", prefix, name, ext), '/');
 }
 
 void RandomState::setSeed(int seed) {
diff --git a/engines/director/util.h b/engines/director/util.h
index 8ae168ff38b..96ff52658cc 100644
--- a/engines/director/util.h
+++ b/engines/director/util.h
@@ -33,23 +33,24 @@ namespace Director {
 int castNumToNum(const char *str);
 char *numToCastNum(int num);
 
-bool isAbsolutePath(Common::String &path);
+bool isAbsolutePath(const Common::String &path);
 
-Common::Path toSafePath(Common::String &path);
-Common::String convertPath(Common::String &path);
+Common::Path toSafePath(const Common::String &path);
+Common::String convertPath(const Common::String &path);
 
 Common::String unixToMacPath(const Common::String &path);
 
-Common::String getPath(Common::String path, Common::String cwd);
+Common::String getPath(const Common::String &path, const Common::String &cwd);
 
-Common::Path resolveFSPath(Common::String &path, Common::Path &base, bool directory);
-Common::Path resolvePath(Common::String &path, Common::Path &base, bool directory, const char **exts);
-Common::Path resolvePartialPath(Common::String &path, Common::Path &base, bool directory, const char **exts);
-Common::Path resolvePathWithFuzz(Common::String &path, Common::Path &base, bool directory, const char **exts);
-Common::Path resolvePartialPathWithFuzz(Common::String &path, Common::Path &base, bool directory, const char **exts);
-Common::Path findPath(Common::String &path, bool currentFolder = true, bool searchPaths = true, bool directory = false, const char **exts = nullptr);
-Common::Path findMoviePath(Common::String &path, bool currentFolder = true, bool searchPaths = true);
-Common::Path findAudioPath(Common::String &path, bool currentFolder = true, bool searchPaths = true);
+Common::Path resolveFSPath(const Common::String &path, const Common::Path &base, bool directory);
+Common::Path resolvePath(const Common::String &path, const Common::Path &base, bool directory, const char **exts);
+Common::Path resolvePartialPath(const Common::String &path, const Common::Path &base, bool directory, const char **exts);
+Common::Path resolvePathWithFuzz(const Common::String &path, const Common::Path &base, bool directory, const char **exts);
+Common::Path resolvePartialPathWithFuzz(const Common::String &path, const Common::Path &base, bool directory, const char **exts);
+Common::Path findPath(const Common::Path &path, bool currentFolder = true, bool searchPaths = true, bool directory = false, const char **exts = nullptr);
+Common::Path findPath(const Common::String &path, bool currentFolder = true, bool searchPaths = true, bool directory = false, const char **exts = nullptr);
+Common::Path findMoviePath(const Common::String &path, bool currentFolder = true, bool searchPaths = true);
+Common::Path findAudioPath(const Common::String &path, bool currentFolder = true, bool searchPaths = true);
 
 
 bool hasExtension(Common::String filename);
@@ -60,8 +61,8 @@ Common::String stripMacPath(const char *name);
 
 Common::String convertMacFilename(const char *name);
 
-Common::String dumpScriptName(const char *prefix, int type, int id, const char *ext);
-Common::String dumpFactoryName(const char *prefix, const char *name, const char *ext);
+Common::Path dumpScriptName(const char *prefix, int type, int id, const char *ext);
+Common::Path dumpFactoryName(const char *prefix, const char *name, const char *ext);
 
 bool isButtonSprite(SpriteType spriteType);
 
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 2458e703126..e0954e71c6a 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -365,11 +365,11 @@ bool Window::setNextMovie(Common::String &movieFilenameRaw) {
 		file.close();
 	}
 
-	debug(1, "Window::setNextMovie: '%s' -> '%s' -> '%s'", movieFilenameRaw.c_str(), convertPath(movieFilenameRaw).c_str(), _fileName.toString().c_str());
+	debug(1, "Window::setNextMovie: '%s' -> '%s' -> '%s'", movieFilenameRaw.c_str(), convertPath(movieFilenameRaw).c_str(), _fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (!fileExists) {
-		warning("Movie %s does not exist", _fileName.toString().c_str());
-		_fileName.set("");
+		warning("Movie %s does not exist", _fileName.toString(Common::Path::kNativeSeparator).c_str());
+		_fileName.clear();
 		return false;
 	}
 
@@ -392,7 +392,7 @@ void Window::loadNewSharedCast(Cast *previousSharedCast) {
 	Common::Path previousSharedCastPath;
 	Common::Path newSharedCastPath = getSharedCastPath();
 	if (previousSharedCast && previousSharedCast->getArchive()) {
-		previousSharedCastPath = Common::Path(previousSharedCast->getArchive()->getPathName(), g_director->_dirSeparator);
+		previousSharedCastPath = previousSharedCast->getArchive()->getPathName();
 	}
 
 	// Check if previous and new sharedCasts are the same
@@ -401,7 +401,7 @@ void Window::loadNewSharedCast(Cast *previousSharedCast) {
 		previousSharedCast->releaseCastMemberWidget();
 		_currentMovie->_sharedCast = previousSharedCast;
 
-		debugC(1, kDebugLoading, "Skipping loading already loaded shared cast, path: %s", previousSharedCastPath.toString().c_str());
+		debugC(1, kDebugLoading, "Skipping loading already loaded shared cast, path: %s", previousSharedCastPath.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
diff --git a/engines/director/window.h b/engines/director/window.h
index 689a6a79e55..4fe7dbc3bde 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -167,7 +167,7 @@ public:
 	bool processEvent(Common::Event &event) override;
 
 	// tests.cpp
-	Common::HashMap<Common::String, Movie *> *scanMovies(const Common::String &folder);
+	Common::HashMap<Common::String, Movie *> *scanMovies(const Common::Path &folder);
 	void testFontScaling();
 	void testFonts();
 	void enqueueAllMovies();


Commit: 80827c49f0e939b3b733ca8b511344ffef102b6e
    https://github.com/scummvm/scummvm/commit/80827c49f0e939b3b733ca8b511344ffef102b6e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
DRACI: Migrate engine to Path

Changed paths:
    engines/draci/barchive.cpp
    engines/draci/barchive.h
    engines/draci/draci.cpp
    engines/draci/font.cpp
    engines/draci/font.h
    engines/draci/game.cpp
    engines/draci/sound.cpp


diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp
index cf366e84166..16b3bbb038b 100644
--- a/engines/draci/barchive.cpp
+++ b/engines/draci/barchive.cpp
@@ -59,7 +59,7 @@ const char BArchive::_dfwMagicNumber[] = "BS";
  *                 [multiple bytes] compressed data
  */
 
-void BArchive::openDFW(const Common::String &path) {
+void BArchive::openDFW(const Common::Path &path) {
 	byte *table;
 	uint16 tableSize;
 	byte buf[2];
@@ -140,7 +140,7 @@ void BArchive::openDFW(const Common::String &path) {
  *                (last entry is footer offset again)
  */
 
-void BArchive::openArchive(const Common::String &path) {
+void BArchive::openArchive(const Common::Path &path) {
 	byte buf[4];
 	byte *footer;
 	uint32 footerOffset, footerSize;
@@ -148,7 +148,7 @@ void BArchive::openArchive(const Common::String &path) {
 	// Close previously opened archive (if any)
 	closeArchive();
 
-	debugCN(2, kDraciArchiverDebugLevel, "Loading archive %s: ", path.c_str());
+	debugCN(2, kDraciArchiverDebugLevel, "Loading archive %s: ", path.toString(Common::Path::kNativeSeparator).c_str());
 
 	_f.open(path);
 	if (_f.isOpen()) {
@@ -378,7 +378,7 @@ const BAFile *BArchive::getFile(uint i) {
 	}
 
 	debugCN(2, kDraciArchiverDebugLevel, "Accessing file %d from archive %s... ",
-		i, _path.c_str());
+		i, _path.toString(Common::Path::kNativeSeparator).c_str());
 
 	// Check if file has already been opened and return that
 	if (_files[i]._data) {
diff --git a/engines/draci/barchive.h b/engines/draci/barchive.h
index 338e64fb906..2954fe0889d 100644
--- a/engines/draci/barchive.h
+++ b/engines/draci/barchive.h
@@ -49,14 +49,14 @@ class BArchive {
 public:
 	BArchive() : _files(NULL), _fileCount(0), _opened(false) {}
 
-	BArchive(const Common::String &path) :
+	BArchive(const Common::Path &path) :
 	_files(NULL), _fileCount(0), _opened(false) {
 		openArchive(path);
 	}
 
 	~BArchive() { closeArchive(); }
 
-	void openArchive(const Common::String &path);
+	void openArchive(const Common::Path &path);
 	void closeArchive();
 	uint size() const { return _fileCount; }
 
@@ -79,14 +79,14 @@ private:
 	// File stream header data
 	static const uint _fileHeaderSize = 6;
 
-	Common::String _path;    ///< Path to file
+	Common::Path _path;    ///< Path to file
 	BAFile *_files;          ///< Internal array of files
 	uint _fileCount;         ///< Number of files in archive
 	bool _isDFW;             ///< True if the archive is in DFW format, false otherwise
 	bool _opened;            ///< True if the archive is opened, false otherwise
 	Common::File _f;         ///< Opened file handle
 
-	void openDFW(const Common::String &path);
+	void openDFW(const Common::Path &path);
 	BAFile *loadFileDFW(uint i);
 	BAFile *loadFileBAR(uint i);
 };
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp
index 96e1a71020b..4989175585e 100644
--- a/engines/draci/draci.cpp
+++ b/engines/draci/draci.cpp
@@ -230,7 +230,7 @@ int DraciEngine::init() {
 
 	// Basic archive test
 	debugC(2, kDraciGeneralDebugLevel, "Running archive tests...");
-	Common::String path("INIT.DFW");
+	Common::Path path("INIT.DFW");
 	BArchive ar(path);
 	const BAFile *f;
 	debugC(3, kDraciGeneralDebugLevel, "Number of file streams in archive: %d", ar.size());
diff --git a/engines/draci/font.cpp b/engines/draci/font.cpp
index 2bdb9dc1e53..96fb2243f66 100644
--- a/engines/draci/font.cpp
+++ b/engines/draci/font.cpp
@@ -30,7 +30,7 @@ namespace Draci {
 const char * const kFontSmall = "Small.fon";
 const char * const kFontBig = "Big.fon";
 
-Font::Font(const Common::String &filename) {
+Font::Font(const Common::Path &filename) {
 	_fontHeight = 0;
 	_maxCharWidth = 0;
 	_charWidths = nullptr;
@@ -61,7 +61,7 @@ Font::~Font() {
  *              [138 * fontHeight * maxWidth bytes] character data, stored row-wise
  */
 
-bool Font::loadFont(const Common::String &filename) {
+bool Font::loadFont(const Common::Path &filename) {
 	// Free previously loaded font (if any)
 	freeFont();
 
@@ -70,10 +70,10 @@ bool Font::loadFont(const Common::String &filename) {
 	f.open(filename);
 	if (f.isOpen()) {
 		debugC(6, kDraciGeneralDebugLevel, "Opened font file %s",
-			filename.c_str());
+			filename.toString(Common::Path::kNativeSeparator).c_str());
 	} else {
 		debugC(6, kDraciGeneralDebugLevel, "Error opening font file %s",
-			filename.c_str());
+			filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -93,7 +93,7 @@ bool Font::loadFont(const Common::String &filename) {
 	_charData = new byte[fontDataSize];
 	f.read(_charData, fontDataSize);
 
-	debugC(5, kDraciGeneralDebugLevel, "Font %s loaded", filename.c_str());
+	debugC(5, kDraciGeneralDebugLevel, "Font %s loaded", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	return true;
 }
diff --git a/engines/draci/font.h b/engines/draci/font.h
index da86b8275ec..00c8702ea8c 100644
--- a/engines/draci/font.h
+++ b/engines/draci/font.h
@@ -53,10 +53,10 @@ enum {
 class Font {
 
 public:
-	Font(const Common::String &filename);
+	Font(const Common::Path &filename);
 	~Font();
 
-	bool loadFont(const Common::String &filename);
+	bool loadFont(const Common::Path &filename);
 	uint8 getFontHeight() const { return _fontHeight; }
 	uint8 getMaxCharWidth() const { return _maxCharWidth; }
 	uint8 getCharWidth(byte chr) const;
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp
index e2b03affdf5..b52e813a47a 100644
--- a/engines/draci/game.cpp
+++ b/engines/draci/game.cpp
@@ -1011,12 +1011,11 @@ void Game::inventorySwitch(int keycode) {
 void Game::dialogueMenu(int dialogueID) {
 	int oldLines, hit;
 
-	Common::String name;
-	name = dialoguePath + Common::String::format("%d.dfw", dialogueID + 1);
+	Common::Path name(Common::String::format("%s%d.dfw", dialoguePath, dialogueID + 1));
 	_dialogueArchive = new BArchive(name);
 
 	debugC(4, kDraciLogicDebugLevel, "Starting dialogue (ID: %d, Archive: %s)",
-	    dialogueID, name.c_str());
+	    dialogueID, name.toString().c_str());
 
 	_currentDialogue = dialogueID;
 	oldLines = 255;
diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp
index fba0ca3f893..ffb300cf119 100644
--- a/engines/draci/sound.cpp
+++ b/engines/draci/sound.cpp
@@ -258,7 +258,7 @@ SoundSample *ZipSoundArchive::getSample(int i, uint freq) {
 	sample._frequency = freq ? freq : _defaultFreq;
 	sample._format = _format;
 	// Read in the file (without the file header)
-	Common::String filename = Common::String::format("%d.%s", i+1, _extension);
+	Common::Path filename(Common::String::format("%d.%s", i+1, _extension));
 	sample._stream = _archive->createReadStreamForMember(filename);
 	if (!sample._stream) {
 		debugC(2, kDraciArchiverDebugLevel, "Doesn't exist");


Commit: d4242bf32af5261a9893159edd5bc638b524620e
    https://github.com/scummvm/scummvm/commit/d4242bf32af5261a9893159edd5bc638b524620e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
DRAGONS: Migrate engine to Path

Changed paths:
    engines/dragons/strplayer.cpp
    engines/dragons/strplayer.h


diff --git a/engines/dragons/strplayer.cpp b/engines/dragons/strplayer.cpp
index 5b789124e23..6d6432efb78 100644
--- a/engines/dragons/strplayer.cpp
+++ b/engines/dragons/strplayer.cpp
@@ -29,11 +29,11 @@ StrPlayer::StrPlayer(DragonsEngine *vm, Screen *screen) : _vm(vm), _screen(scree
 	_decoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x);
 }
 
-void StrPlayer::playVideo(const Common::String &filename) {
+void StrPlayer::playVideo(const Common::Path &filename) {
 	bool skipped = false;
 
 	if (!_decoder->loadFile(filename)) {
-		error("Error playing video from %s", filename.c_str());
+		error("Error playing video from %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	_decoder->start();
 
diff --git a/engines/dragons/strplayer.h b/engines/dragons/strplayer.h
index ce0584dedf8..e776f7bcdf5 100644
--- a/engines/dragons/strplayer.h
+++ b/engines/dragons/strplayer.h
@@ -36,7 +36,7 @@ public:
 	StrPlayer(DragonsEngine *vm, Screen *screen);
 	~StrPlayer();
 
-	void playVideo(const Common::String &filename);
+	void playVideo(const Common::Path &filename);
 private:
 };
 


Commit: 2d0659156417139d3e6cec0f2f4e3abc59e42766
    https://github.com/scummvm/scummvm/commit/2d0659156417139d3e6cec0f2f4e3abc59e42766
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
DRASCULA: Migrate engine to Path

Changed paths:
    engines/drascula/drascula.cpp
    engines/drascula/drascula.h
    engines/drascula/resource.cpp


diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index 9d24c332274..6be1142deac 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -165,7 +165,7 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam
 
 	_rnd = new Common::RandomSource("drascula");
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "audio");
 
 	_system->getAudioCDManager()->open();
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index fbddd5cfb95..0e752ece238 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -257,9 +257,9 @@ public:
 
 	void enableFallback(bool val) { _fallBack = val; }
 
-	void registerArchive(const Common::String &filename, int priority);
+	void registerArchive(const Common::Path &filename, int priority);
 
-	Common::SeekableReadStream *open(const Common::String &filename);
+	Common::SeekableReadStream *open(const Common::Path &filename);
 
 private:
 	bool _fallBack;
diff --git a/engines/drascula/resource.cpp b/engines/drascula/resource.cpp
index 60f2a95d4f5..952472f4cfd 100644
--- a/engines/drascula/resource.cpp
+++ b/engines/drascula/resource.cpp
@@ -28,11 +28,11 @@ ArchiveMan::ArchiveMan() {
 	_fallBack = false;
 }
 
-void ArchiveMan::registerArchive(const Common::String &filename, int priority) {
-	add(filename, Common::makeArjArchive(filename), priority);
+void ArchiveMan::registerArchive(const Common::Path &filename, int priority) {
+	add(filename.toString(), Common::makeArjArchive(filename), priority);
 }
 
-Common::SeekableReadStream *ArchiveMan::open(const Common::String &filename) {
+Common::SeekableReadStream *ArchiveMan::open(const Common::Path &filename) {
 	if (_fallBack && SearchMan.hasFile(filename)) {
 		return SearchMan.createReadStreamForMember(filename);
 	}


Commit: 678c63ad1eb4d206280c5e3a324f520d5ce41598
    https://github.com/scummvm/scummvm/commit/678c63ad1eb4d206280c5e3a324f520d5ce41598
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
DREAMWEB: Migrate engine to Path

Changed paths:
    engines/dreamweb/dreamweb.cpp
    engines/dreamweb/dreamweb.h
    engines/dreamweb/sound.cpp
    engines/dreamweb/stubs.cpp
    engines/dreamweb/vgagrafx.cpp


diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp
index 2aabec79240..0aaac3ce1eb 100644
--- a/engines/dreamweb/dreamweb.cpp
+++ b/engines/dreamweb/dreamweb.cpp
@@ -434,7 +434,7 @@ Common::Error DreamWebEngine::run() {
 	setDebugger(new DreamWebConsole(this));
 	_sound = new DreamWebSound(this);
 
-	_hasSpeech = Common::File::exists(_speechDirName + "/r01c0000.raw") && !ConfMan.getBool("speech_mute");
+	_hasSpeech = Common::File::exists(_speechDirName.appendComponent("r01c0000.raw")) && !ConfMan.getBool("speech_mute");
 	_brightPalette = ConfMan.getBool("bright_palette");
 	_copyProtection = ConfMan.getBool("copy_protection");
 
@@ -609,17 +609,17 @@ uint8 DreamWebEngine::modifyChar(uint8 c) const {
 	}
 }
 
-Common::String DreamWebEngine::modifyFileName(const char *name) {
+Common::Path DreamWebEngine::modifyFileName(const char *name) {
 	Common::String fileName(name);
 
 	// Sanity check
 	if (!fileName.hasPrefix("DREAMWEB."))
-		return fileName;
+		return Common::Path(fileName);
 
 	// Make sure we use the correct file name as it differs depending on the game variant
 	fileName = _datafilePrefix;
 	fileName += name + 9;
-	return fileName;
+	return Common::Path(fileName);
 }
 
 bool DreamWebEngine::hasSpeech() {
diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h
index bc9dd90cdb4..acfabdb11ef 100644
--- a/engines/dreamweb/dreamweb.h
+++ b/engines/dreamweb/dreamweb.h
@@ -140,10 +140,10 @@ public:
 
 	Common::Language getLanguage() const;
 	uint8 modifyChar(uint8 c) const;
-	Common::String modifyFileName(const char *);
+	Common::Path modifyFileName(const char *);
 
 	const Common::String& getDatafilePrefix() { return _datafilePrefix; }
-	const Common::String& getSpeechDirName() { return _speechDirName; }
+	const Common::Path& getSpeechDirName() { return _speechDirName; }
 
 private:
 	// Keyboard buffer. _bufferIn and _bufferOut are indexes
@@ -159,7 +159,7 @@ private:
 	Graphics::Surface				_thumbnail;
 	Common::RandomSource			_rnd;
 	Common::String _datafilePrefix;
-	Common::String _speechDirName;
+	Common::Path _speechDirName;
 
 	uint _speed;
 	bool _turbo;
diff --git a/engines/dreamweb/sound.cpp b/engines/dreamweb/sound.cpp
index bb1f87df389..5eadb42b7a1 100644
--- a/engines/dreamweb/sound.cpp
+++ b/engines/dreamweb/sound.cpp
@@ -189,7 +189,7 @@ bool DreamWebSound::loadSpeech(const Common::String &filename) {
 		return false;
 
 	Common::File file;
-	if (!file.open(_vm->getSpeechDirName() + "/" + filename))
+	if (!file.open(_vm->getSpeechDirName().appendComponent(filename)))
 		return false;
 
 	debug(1, "loadSpeech(%s)", filename.c_str());
@@ -243,11 +243,11 @@ void DreamWebSound::soundHandler() {
 }
 
 void DreamWebSound::loadSounds(uint bank, const Common::String &suffix) {
-	Common::String filename = _vm->getDatafilePrefix() + suffix;
-	debug(1, "loadSounds(%u, %s)", bank, filename.c_str());
+	Common::Path filename(_vm->getDatafilePrefix() + suffix);
+	debug(1, "loadSounds(%u, %s)", bank, filename.toString(Common::Path::kNativeSeparator).c_str());
 	Common::File file;
 	if (!file.open(filename)) {
-		warning("cannot open %s", filename.c_str());
+		warning("cannot open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp
index 8ed56af527e..86db5966c9a 100644
--- a/engines/dreamweb/stubs.cpp
+++ b/engines/dreamweb/stubs.cpp
@@ -730,7 +730,7 @@ void DreamWebEngine::dreamweb() {
 }
 
 void DreamWebEngine::loadTextFile(TextFile &file, const char *suffix) {
-	Common::String fileName = getDatafilePrefix() + suffix;
+	Common::Path fileName(getDatafilePrefix() + suffix);
 	FileHeader header;
 
 	Common::File f;
@@ -836,7 +836,7 @@ void DreamWebEngine::switchRyanOff() {
 }
 
 void DreamWebEngine::loadGraphicsFile(GraphicsFile &file, const char *suffix) {
-	Common::String fileName = getDatafilePrefix() + suffix;
+	Common::Path fileName(getDatafilePrefix() + suffix);
 	FileHeader header;
 
 	Common::File f;
@@ -2035,7 +2035,7 @@ void DreamWebEngine::loadRoomData(const Room &room, bool skipDat) {
 	processEvents();
 	Common::File file;
 	if (!file.open(modifyFileName(room.name)))
-		error("cannot open file %s", modifyFileName(room.name).c_str());
+		error("cannot open file %s", modifyFileName(room.name).toString(Common::Path::kNativeSeparator).c_str());
 
 	FileHeader header;
 	file.read((uint8 *)&header, sizeof(FileHeader));
@@ -2121,7 +2121,7 @@ void DreamWebEngine::restoreReels() {
 	processEvents();
 	Common::File file;
 	if (!file.open(modifyFileName(room.name)))
-		error("cannot open file %s", modifyFileName(room.name).c_str());
+		error("cannot open file %s", modifyFileName(room.name).toString(Common::Path::kNativeSeparator).c_str());
 
 	FileHeader header;
 	file.read((uint8 *)&header, sizeof(FileHeader));
diff --git a/engines/dreamweb/vgagrafx.cpp b/engines/dreamweb/vgagrafx.cpp
index a0523bfd5d9..9a54359ab07 100644
--- a/engines/dreamweb/vgagrafx.cpp
+++ b/engines/dreamweb/vgagrafx.cpp
@@ -155,16 +155,16 @@ void DreamWebEngine::setMode() {
 }
 
 void DreamWebEngine::showPCX(const Common::String &suffix) {
-	Common::String name = getDatafilePrefix() + suffix;
+	Common::Path name(getDatafilePrefix() + suffix);
 	Common::File pcxFile;
 	if (!pcxFile.open(name)) {
-		warning("showpcx: Could not open '%s'", name.c_str());
+		warning("showpcx: Could not open '%s'", name.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
 	Image::PCXDecoder pcx;
 	if (!pcx.loadStream(pcxFile)) {
-		warning("showpcx: Could not process '%s'", name.c_str());
+		warning("showpcx: Could not process '%s'", name.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
@@ -379,7 +379,7 @@ bool DreamWebEngine::pixelCheckSet(const ObjPos *pos, uint8 x, uint8 y) {
 void DreamWebEngine::loadPalFromIFF() {
 	Common::File palFile;
 	uint8* buf = new uint8[2000];
-	palFile.open(getDatafilePrefix() + "PAL");
+	palFile.open(Common::Path(getDatafilePrefix() + "PAL"));
 	palFile.read(buf, 2000);
 	palFile.close();
 


Commit: 6ef53571fb56011f4da7416a150dd54f914b2241
    https://github.com/scummvm/scummvm/commit/6ef53571fb56011f4da7416a150dd54f914b2241
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
EFH: Migrate engine to Path

Changed paths:
    engines/efh/efh.cpp
    engines/efh/efh.h
    engines/efh/files.cpp
    engines/efh/init.cpp
    engines/efh/utils.cpp


diff --git a/engines/efh/efh.cpp b/engines/efh/efh.cpp
index 60d5da08f5f..5aa48025e2f 100644
--- a/engines/efh/efh.cpp
+++ b/engines/efh/efh.cpp
@@ -420,11 +420,11 @@ void EfhEngine::initEngine() {
 	loadImageSetToTileBank(2, 5);
 
 	// Load 320*200 Menu screen
-	Common::String fileName = Common::String::format("imageset.%d", 10);
+	Common::Path fileName(Common::String::format("imageset.%d", 10));
 	readFileToBuffer(fileName, _menuBuf);
 
 	// Load 96*64 Window with pink border and yellow bottom
-	fileName = Common::String::format("imageset.%d", 12);
+	fileName = Common::Path(Common::String::format("imageset.%d", 12));
 	readFileToBuffer(fileName, _windowWithBorderBuf);
 
 	readAnimInfo();
@@ -2497,11 +2497,11 @@ void EfhEngine::loadEfhGame() {
 	// The savegame is used to initialize the engine, so this part is reimplemented.
 	// The check for existence is replaced by an error.
 
-	Common::String fileName("savegame");
+	Common::Path fileName("savegame");
 	Common::File f;
 
 	if (!f.open(fileName))
-		error("Missing file %s", fileName.c_str());
+		error("Missing file %s", fileName.toString().c_str());
 
 	_techId = f.readSint16LE();
 	_fullPlaceId = f.readUint16LE();
diff --git a/engines/efh/efh.h b/engines/efh/efh.h
index aa944792542..f83a1a5b769 100644
--- a/engines/efh/efh.h
+++ b/engines/efh/efh.h
@@ -413,10 +413,10 @@ private:
 	void handleDamageOnArmor(int16 charId, int16 damage);
 
 	// Files
-	int32 readFileToBuffer(Common::String &filename, uint8 *destBuffer);
+	int32 readFileToBuffer(const Common::Path &filename, uint8 *destBuffer);
 	void readAnimInfo();
 	void findMapFile(int16 mapId);
-	void rImageFile(Common::String filename, uint8 *targetBuffer, uint8 **subFilesArray, uint8 *packedBuffer);
+	void rImageFile(const Common::Path &filename, uint8 *targetBuffer, uint8 **subFilesArray, uint8 *packedBuffer);
 	void readItems();
 	void readImpFile(int16 id, bool techMapFl);
 	void loadNewPortrait();
diff --git a/engines/efh/files.cpp b/engines/efh/files.cpp
index 907cc11ca7f..b9d593c40fd 100644
--- a/engines/efh/files.cpp
+++ b/engines/efh/files.cpp
@@ -24,11 +24,11 @@
 
 namespace Efh {
 
-int32 EfhEngine::readFileToBuffer(Common::String &filename, uint8 *destBuffer) {
-	debugC(1, kDebugUtils, "readFileToBuffer %s", filename.c_str());
+int32 EfhEngine::readFileToBuffer(const Common::Path &filename, uint8 *destBuffer) {
+	debugC(1, kDebugUtils, "readFileToBuffer %s", filename.toString().c_str());
 	Common::File f;
 	if (!f.open(filename))
-		error("Unable to find file %s", filename.c_str());
+		error("Unable to find file %s", filename.toString().c_str());
 
 	int size = f.size();
 
@@ -38,10 +38,10 @@ int32 EfhEngine::readFileToBuffer(Common::String &filename, uint8 *destBuffer) {
 void EfhEngine::readAnimInfo() {
 	debugC(6, kDebugEngine, "readAnimInfo");
 
-	Common::String fileName = "animinfo";
+	Common::Path fileName("animinfo");
 	Common::File f;
 	if (!f.open(fileName))
-		error("Unable to find file %s", fileName.c_str());
+		error("Unable to find file %s", fileName.toString().c_str());
 
 	for (int i = 0; i < 100; ++i) {
 		for (int id = 0; id < 15; ++id) {
@@ -77,24 +77,24 @@ void EfhEngine::findMapFile(int16 mapId) {
 	if (!_introDoneFl)
 		return;
 
-	Common::String fileName = Common::String::format("map.%d", mapId);
+	Common::Path fileName(Common::String::format("map.%d", mapId));
 	Common::File f;
 	// The original was checking for the file and eventually asking to change floppies
 	if (!f.open(fileName))
-		error("File not found: %s", fileName.c_str());
+		error("File not found: %s", fileName.toString().c_str());
 
 	f.close();
 }
 
-void EfhEngine::rImageFile(Common::String filename, uint8 *targetBuffer, uint8 **subFilesArray, uint8 *packedBuffer) {
-	debugC(1, kDebugUtils, "rImageFile %s", filename.c_str());
+void EfhEngine::rImageFile(const Common::Path &filename, uint8 *targetBuffer, uint8 **subFilesArray, uint8 *packedBuffer) {
+	debugC(1, kDebugUtils, "rImageFile %s", filename.toString().c_str());
 	readFileToBuffer(filename, packedBuffer);
 
 	uint32 size = uncompressBuffer(packedBuffer, targetBuffer);
 	if (ConfMan.getBool("dump_scripts")) {
 		// dump a decompressed image file
 		Common::DumpFile dump;
-		dump.open(filename + ".dump");
+		dump.open(filename.append(".dump"));
 		dump.write(targetBuffer, size);
 		dump.flush();
 		dump.close();
@@ -119,7 +119,7 @@ void EfhEngine::rImageFile(Common::String filename, uint8 *targetBuffer, uint8 *
 void EfhEngine::readImpFile(int16 id, bool techMapFl) {
 	debugC(6, kDebugEngine, "readImpFile %d %s", id, techMapFl ? "True" : "False");
 
-	Common::String fileName = Common::String::format("imp.%d", id);
+	Common::Path fileName(Common::String::format("imp.%d", id));
 
 	if (techMapFl)
 		readFileToBuffer(fileName, _imp1);
@@ -132,10 +132,10 @@ void EfhEngine::readImpFile(int16 id, bool techMapFl) {
 void EfhEngine::readItems() {
 	debugC(7, kDebugEngine, "readItems");
 
-	Common::String fileName = "items";
+	Common::Path fileName("items");
 	Common::File f;
 	if (!f.open(fileName))
-		error("Unable to find file %s", fileName.c_str());
+		error("Unable to find file %s", fileName.toString().c_str());
 
 	for (int i = 0; i < 300; ++i) {
 		for (uint idx = 0; idx < 15; ++idx)
@@ -191,7 +191,7 @@ void EfhEngine::loadAnimImageSet() {
 void EfhEngine::loadHistory() {
 	debugC(2, kDebugEngine, "loadHistory");
 
-	Common::String fileName = "history";
+	Common::Path fileName("history");
 	readFileToBuffer(fileName, _history);
 }
 
@@ -232,7 +232,7 @@ void EfhEngine::loadPlacesFile(uint16 fullPlaceId, bool forceReloadFl) {
 
 	if (_fullPlaceId < minPlace || _fullPlaceId > maxPlace || forceReloadFl) {
 		_lastMainPlaceId = _fullPlaceId / 20;
-		Common::String fileName = Common::String::format("places.%d", _lastMainPlaceId);
+		Common::Path fileName(Common::String::format("places.%d", _lastMainPlaceId));
 		readFileToBuffer(fileName, _decompBuf);
 		uncompressBuffer(_decompBuf, _places);
 	}
@@ -242,10 +242,10 @@ void EfhEngine::loadPlacesFile(uint16 fullPlaceId, bool forceReloadFl) {
 void EfhEngine::readTileFact() {
 	debugC(7, kDebugEngine, "readTileFact");
 
-	Common::String fileName = "tilefact";
+	Common::Path fileName("tilefact");
 	Common::File f;
 	if (!f.open(fileName))
-		error("Unable to find file %s", fileName.c_str());
+		error("Unable to find file %s", fileName.toString().c_str());
 
 	for (int i = 0; i < 432; ++i) {
 		_tileFact[i]._status = f.readByte();
@@ -256,10 +256,10 @@ void EfhEngine::readTileFact() {
 void EfhEngine::loadNPCS() {
 	debugC(7, kDebugEngine, "loadNPCS");
 
-	Common::String fileName("npcs");
+	Common::Path fileName("npcs");
 	Common::File f;
 	if (!f.open(fileName))
-		error("Unable to find file %s", fileName.c_str());
+		error("Unable to find file %s", fileName.toString().c_str());
 
 	for (int i = 0; i < 99; ++i) {
 		for (int idx = 0; idx < 11; ++idx)
@@ -328,11 +328,11 @@ void EfhEngine::preLoadMaps() {
 		dump.open("efhMaps.dump");
 
 	for (int idx = 0; idx < 19; ++idx) {
-		Common::String fileName = Common::String::format("tech.%d", idx);
+		Common::Path fileName(Common::String::format("tech.%d", idx));
 		readFileToBuffer(fileName, _decompBuf);
 		uncompressBuffer(_decompBuf, _techDataArr[idx]);
 
-		fileName = Common::String::format("map.%d", idx);
+		fileName = Common::Path(Common::String::format("map.%d", idx));
 		readFileToBuffer(fileName, _decompBuf);
 		uncompressBuffer(_decompBuf, _mapArr[idx]);
 
diff --git a/engines/efh/init.cpp b/engines/efh/init.cpp
index fc7431c2a2c..f33a75aafbf 100644
--- a/engines/efh/init.cpp
+++ b/engines/efh/init.cpp
@@ -230,7 +230,7 @@ void TeamChar::init() {
 }
 
 EfhEngine::EfhEngine(OSystem *syst, const ADGameDescription *gd) : Engine(syst), _gameDescription(gd) {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	SearchMan.addSubDirectoryMatching(gameDataDir, "gendata");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "images");
diff --git a/engines/efh/utils.cpp b/engines/efh/utils.cpp
index 4f6582906db..87f607d50b7 100644
--- a/engines/efh/utils.cpp
+++ b/engines/efh/utils.cpp
@@ -78,7 +78,7 @@ void EfhEngine::decryptImpFile(bool techMapFl) {
 
 void EfhEngine::loadImageSet(int16 imageSetId, uint8 *buffer, uint8 **subFilesArray, uint8 *destBuffer) {
 	debugC(1, kDebugUtils, "loadImageSet %d", imageSetId);
-	Common::String fileName = Common::String::format("imageset.%d", imageSetId);
+	Common::Path fileName(Common::String::format("imageset.%d", imageSetId));
 	rImageFile(fileName, buffer, subFilesArray, destBuffer);
 }
 


Commit: a8e11a06115c99046d944de4cc4bc6572b735d54
    https://github.com/scummvm/scummvm/commit/a8e11a06115c99046d944de4cc4bc6572b735d54
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
FREESCAPE: Migrate engine to Path

Changed paths:
    engines/freescape/assets.cpp
    engines/freescape/freescape.h
    engines/freescape/games/castle.cpp
    engines/freescape/games/dark/amiga.cpp
    engines/freescape/games/dark/dark.h
    engines/freescape/games/driller/atari.cpp
    engines/freescape/games/driller/driller.h
    engines/freescape/sound.cpp


diff --git a/engines/freescape/assets.cpp b/engines/freescape/assets.cpp
index e8dd4e27d89..01dc36c26c2 100644
--- a/engines/freescape/assets.cpp
+++ b/engines/freescape/assets.cpp
@@ -111,11 +111,11 @@ void FreescapeEngine::loadAssetsC64FullGame() {
 void FreescapeEngine::loadDataBundle() {
 	_dataBundle = Common::makeZipArchive(FREESCAPE_DATA_BUNDLE);
 	if (!_dataBundle) {
-		error("ENGINE: Couldn't load data bundle '%s'.", FREESCAPE_DATA_BUNDLE.c_str());
+		error("ENGINE: Couldn't load data bundle '%s'.", FREESCAPE_DATA_BUNDLE);
 	}
-	Common::String versionFilename = "version";
+	Common::Path versionFilename("version");
 	if (!_dataBundle->hasFile(versionFilename))
-		error("No version number in %s", FREESCAPE_DATA_BUNDLE.c_str());
+		error("No version number in %s", FREESCAPE_DATA_BUNDLE);
 
 	Common::SeekableReadStream *versionFile = _dataBundle->createReadStreamForMember(versionFilename);
 	char *versionData = (char *)malloc((versionFile->size() + 1) * sizeof(char));
@@ -129,14 +129,14 @@ void FreescapeEngine::loadDataBundle() {
 
 Graphics::Surface *FreescapeEngine::loadBundledImage(const Common::String &name) {
 	Image::BitmapDecoder decoder;
-	Common::String bmpFilename = name + "_" + Common::getRenderModeDescription(_renderMode) + ".bmp";
-	debugC(1, kFreescapeDebugParser, "Loading %s from bundled archive", bmpFilename.c_str());
+	Common::Path bmpFilename(name + "_" + Common::getRenderModeDescription(_renderMode) + ".bmp");
+	debugC(1, kFreescapeDebugParser, "Loading %s from bundled archive", bmpFilename.toString().c_str());
 	if (!_dataBundle->hasFile(bmpFilename))
-		error("Failed to open file %s from bundle", bmpFilename.c_str());
+		error("Failed to open file %s from bundle", bmpFilename.toString().c_str());
 
 	Common::SeekableReadStream *bmpFile = _dataBundle->createReadStreamForMember(bmpFilename);
 	if (!decoder.loadStream(*bmpFile))
-		error("Failed to decode bmp file %s from bundle", bmpFilename.c_str());
+		error("Failed to decode bmp file %s from bundle", bmpFilename.toString().c_str());
 
 	Graphics::Surface *surface = new Graphics::Surface();
 	surface->copyFrom(*decoder.getSurface());
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index e88cceeb846..78b4db50cea 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -47,7 +47,7 @@ namespace Freescape {
 
 class Renderer;
 
-#define FREESCAPE_DATA_BUNDLE Common::String("freescape.dat")
+#define FREESCAPE_DATA_BUNDLE "freescape.dat"
 
 enum CameraMovement {
 	kForwardMovement,
@@ -343,8 +343,8 @@ public:
 	void stopAllSounds();
 	bool isPlayingSound();
 	void playSound(int index, bool sync);
-	void playWav(const Common::String filename);
-	void playMusic(const Common::String filename);
+	void playWav(const Common::Path &filename);
+	void playMusic(const Common::Path &filename);
 	void queueSoundConst(double hzFreq, int duration);
 	void playSilence(int duration, bool sync);
 	void playSoundConst(double hzFreq, int duration, bool sync);
@@ -462,7 +462,7 @@ public:
 	Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
 	Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
 private:
-	Common::SeekableReadStream *decryptFile(const Common::String filename);
+	Common::SeekableReadStream *decryptFile(const Common::Path &filename);
 };
 
 extern FreescapeEngine *g_freescape;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 01e7147e6b2..d1b95a2ed6e 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -108,11 +108,11 @@ byte kFreescapeCastleFont[] = {
 	0x7f, 0x87, 0x0e, 0x1c, 0x38, 0x71, 0xfd, 0xe6,
 };
 
-Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filename) {
+Common::SeekableReadStream *CastleEngine::decryptFile(const Common::Path &filename) {
 	Common::File file;
 	file.open(filename);
 	if (!file.isOpen())
-		error("Failed to open %s", filename.c_str());
+		error("Failed to open %s", filename.toString().c_str());
 
 	int size = file.size();
 	byte *encryptedBuffer = (byte *)malloc(size);
diff --git a/engines/freescape/games/dark/amiga.cpp b/engines/freescape/games/dark/amiga.cpp
index ee233b02144..a00e8f5dd26 100644
--- a/engines/freescape/games/dark/amiga.cpp
+++ b/engines/freescape/games/dark/amiga.cpp
@@ -27,11 +27,11 @@
 
 namespace Freescape {
 
-Common::SeekableReadStream *DarkEngine::decryptFile(const Common::String filename) {
+Common::SeekableReadStream *DarkEngine::decryptFile(const Common::Path &filename) {
 	Common::File file;
 	file.open(filename);
 	if (!file.isOpen())
-		error("Failed to open %s", filename.c_str());
+		error("Failed to open %s", filename.toString().c_str());
 
 	int size = file.size();
 	byte *encryptedBuffer = (byte *)malloc(size);
@@ -94,4 +94,4 @@ void DarkEngine::initAmigaAtari() {
 	_viewArea = Common::Rect(32, 33, 287, 130);
 }
 
-} // End of namespace Freescape
\ No newline at end of file
+} // End of namespace Freescape
diff --git a/engines/freescape/games/dark/dark.h b/engines/freescape/games/dark/dark.h
index c2ef4bdb764..016eb317417 100644
--- a/engines/freescape/games/dark/dark.h
+++ b/engines/freescape/games/dark/dark.h
@@ -96,8 +96,8 @@ private:
 	bool tryDestroyECD(int index);
 	bool tryDestroyECDFullGame(int index);
 	void addWalls(Area *area);
-	Common::SeekableReadStream *decryptFile(const Common::String filename);
+	Common::SeekableReadStream *decryptFile(const Common::Path &filename);
 	Common::HashMap<uint16, bool> _exploredAreas;
 };
 
-}
\ No newline at end of file
+}
diff --git a/engines/freescape/games/driller/atari.cpp b/engines/freescape/games/driller/atari.cpp
index 0c6ca8888fc..c4bad291d8d 100644
--- a/engines/freescape/games/driller/atari.cpp
+++ b/engines/freescape/games/driller/atari.cpp
@@ -27,11 +27,11 @@
 
 namespace Freescape {
 
-Common::SeekableReadStream *DrillerEngine::decryptFileAtari(const Common::String filename) {
+Common::SeekableReadStream *DrillerEngine::decryptFileAtari(const Common::Path &filename) {
 	Common::File file;
 	file.open(filename);
 	if (!file.isOpen())
-		error("Failed to open %s", filename.c_str());
+		error("Failed to open %s", filename.toString().c_str());
 
 	int size = file.size();
 	byte *encryptedBuffer = (byte *)malloc(size);
@@ -178,4 +178,4 @@ void DrillerEngine::loadAssetsAtariDemo() {
 	loadSoundsFx(&file, 0, 25);
 }
 
-} // End of namespace Freescape
\ No newline at end of file
+} // End of namespace Freescape
diff --git a/engines/freescape/games/driller/driller.h b/engines/freescape/games/driller/driller.h
index 7905b838b43..92aa02bf590 100644
--- a/engines/freescape/games/driller/driller.h
+++ b/engines/freescape/games/driller/driller.h
@@ -101,7 +101,7 @@ private:
 	uint32 getPixel8bitTitleImage(int index);
 	void renderPixels8bitTitleImage(Graphics::ManagedSurface *surface, int &i, int &j, int pixels);
 
-	Common::SeekableReadStream *decryptFileAtari(const Common::String filename);
+	Common::SeekableReadStream *decryptFileAtari(const Common::Path &filename);
 };
 
 enum DrillerReleaseFlags {
@@ -120,4 +120,4 @@ enum DrillerReleaseFlags {
 		GF_ATARI_MAGAZINE_DEMO = (1 << 12),
 };
 
-}
\ No newline at end of file
+}
diff --git a/engines/freescape/sound.cpp b/engines/freescape/sound.cpp
index 016be2cb3fc..ed4ee058169 100644
--- a/engines/freescape/sound.cpp
+++ b/engines/freescape/sound.cpp
@@ -221,7 +221,7 @@ void FreescapeEngine::playSound(int index, bool sync) {
 	}
 	_syncSound = sync;
 }
-void FreescapeEngine::playWav(const Common::String filename) {
+void FreescapeEngine::playWav(const Common::Path &filename) {
 
 	Common::SeekableReadStream *s = _dataBundle->createReadStreamForMember(filename);
 	assert(s);
@@ -229,7 +229,7 @@ void FreescapeEngine::playWav(const Common::String filename) {
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundFxHandle, stream);
 }
 
-void FreescapeEngine::playMusic(const Common::String filename) {
+void FreescapeEngine::playMusic(const Common::Path &filename) {
 	Audio::SeekableAudioStream *stream = nullptr;
 	stream = Audio::SeekableAudioStream::openStreamFile(filename);
 	if (stream) {


Commit: ff87ff4e241539643f0931c4a424bc39130daba2
    https://github.com/scummvm/scummvm/commit/ff87ff4e241539643f0931c4a424bc39130daba2
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GLK: Migrate engine to Path

Changed paths:
    engines/glk/adrift/sxutils.cpp
    engines/glk/alan2/alan2.cpp
    engines/glk/alan3/alan3.cpp
    engines/glk/archetype/misc.cpp
    engines/glk/blorb.cpp
    engines/glk/blorb.h
    engines/glk/comprehend/file_buf.cpp
    engines/glk/comprehend/pics.cpp
    engines/glk/comprehend/pics.h
    engines/glk/debugger.cpp
    engines/glk/detection.cpp
    engines/glk/glk.cpp
    engines/glk/hugo/resource_archive.cpp
    engines/glk/jacl/types.h
    engines/glk/magnetic/glk.cpp
    engines/glk/metaengine.cpp
    engines/glk/picture.cpp
    engines/glk/quest/geas_glk.cpp
    engines/glk/sound.cpp
    engines/glk/streams.cpp
    engines/glk/zcode/glk_interface.cpp
    engines/glk/zcode/pics.cpp
    engines/glk/zcode/sound_folder.cpp
    engines/glk/zcode/sound_folder.h


diff --git a/engines/glk/adrift/sxutils.cpp b/engines/glk/adrift/sxutils.cpp
index f7fd0795477..00334e58569 100644
--- a/engines/glk/adrift/sxutils.cpp
+++ b/engines/glk/adrift/sxutils.cpp
@@ -144,7 +144,7 @@ void sx_free(void *pointer) {
 Common::SeekableReadStream *sx_fopen(const sc_char *name, const sc_char *extension, const sc_char *mode) {
 	assert(name && extension && mode);
 
-	Common::String filename = Common::String::format("%s.%s", name, extension);
+	Common::Path filename(Common::String::format("%s.%s", name, extension));
 	Common::File *f = new Common::File();
 
 	if (f->open(filename))
diff --git a/engines/glk/alan2/alan2.cpp b/engines/glk/alan2/alan2.cpp
index 177884a571e..a08775b89e7 100644
--- a/engines/glk/alan2/alan2.cpp
+++ b/engines/glk/alan2/alan2.cpp
@@ -84,7 +84,7 @@ bool Alan2::initialize() {
 
 	// Open up the text file
 	txtfil = new Common::File();
-	if (!txtfil->open(Common::String::format("%s.dat", _advName.c_str()))) {
+	if (!txtfil->open(Common::Path(Common::String::format("%s.dat", _advName.c_str())))) {
 		GUIErrorMessage("Could not open adventure text data file");
 		delete txtfil;
 		return false;
diff --git a/engines/glk/alan3/alan3.cpp b/engines/glk/alan3/alan3.cpp
index a873f359a5b..5d78bf5abdb 100644
--- a/engines/glk/alan3/alan3.cpp
+++ b/engines/glk/alan3/alan3.cpp
@@ -92,7 +92,7 @@ bool Alan3::initialize() {
 
 	// In Alan 3, the text data comes from the adventure file itself
 	Common::File *txt = new Common::File();
-	if (!txt->open(getFilename())) {
+	if (!txt->open(Common::Path(getFilename()))) {
 	    GUIErrorMessage("Could not open adventure file for text data");
 	    delete txt;
 	    return false;
diff --git a/engines/glk/archetype/misc.cpp b/engines/glk/archetype/misc.cpp
index 750ae52c010..ff08f77e477 100644
--- a/engines/glk/archetype/misc.cpp
+++ b/engines/glk/archetype/misc.cpp
@@ -51,7 +51,7 @@ void misc_init() {
 bool progfile::open(const String &name) {
 	filename = name;
 
-	if (!_file.open(name)) {
+	if (!_file.open(Common::Path(name))) {
 		return false;
 
 	} else {
diff --git a/engines/glk/blorb.cpp b/engines/glk/blorb.cpp
index 6dad4516ccb..c81ccaecfe3 100644
--- a/engines/glk/blorb.cpp
+++ b/engines/glk/blorb.cpp
@@ -26,7 +26,7 @@ namespace Glk {
 
 /*--------------------------------------------------------------------------*/
 
-Blorb::Blorb(const Common::String &filename, InterpreterType interpType) :
+Blorb::Blorb(const Common::Path &filename, InterpreterType interpType) :
 		Common::Archive(), _filename(filename), _interpType(interpType) {
 	if (load() != Common::kNoError)
 		error("Could not parse blorb file");
@@ -39,9 +39,8 @@ Blorb::Blorb(const Common::FSNode &fileNode, InterpreterType interpType) :
 }
 
 bool Blorb::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (uint idx = 0; idx < _chunks.size(); ++idx) {
-		if (_chunks[idx]._filename.equalsIgnoreCase(name))
+		if (_chunks[idx]._filename.equalsIgnoreCase(path))
 			return true;
 	}
 
@@ -57,19 +56,17 @@ int Blorb::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr Blorb::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *Blorb::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (uint idx = 0; idx < _chunks.size(); ++idx) {
 		const ChunkEntry &ce = _chunks[idx];
 
-		if (ce._filename.equalsIgnoreCase(name)) {
+		if (ce._filename.equalsIgnoreCase(path)) {
 			Common::File f;
 			if ((!_filename.empty() && !f.open(_filename)) ||
 					(_filename.empty() && !f.open(_fileNode)))
@@ -116,32 +113,33 @@ Common::ErrorCode Blorb::load() {
 	for (uint idx = 0; idx < _chunks.size(); ++idx) {
 		ChunkEntry &ce = _chunks[idx];
 
+		Common::String filename;
 		if (ce._type == ID_Pict) {
-			ce._filename = Common::String::format("pic%u", ce._number);
+			filename = Common::String::format("pic%u", ce._number);
 			if (ce._id == ID_JPEG)
-				ce._filename += ".jpg";
+				filename += ".jpg";
 			else if (ce._id == ID_PNG)
-				ce._filename += ".png";
+				filename += ".png";
 			else if (ce._id == ID_Rect)
-				ce._filename += ".rect";
+				filename += ".rect";
 
 		} else if (ce._type == ID_Snd) {
-			ce._filename = Common::String::format("sound%u", ce._number);
+			filename = Common::String::format("sound%u", ce._number);
 			if (ce._id == ID_MIDI)
-				ce._filename += ".midi";
+				filename += ".midi";
 			else if (ce._id == ID_MP3)
-				ce._filename += ".mp3";
+				filename += ".mp3";
 			else if (ce._id == ID_WAVE)
-				ce._filename += ".wav";
+				filename += ".wav";
 			else if (ce._id == ID_AIFF || ce._id == ID_FORM)
-				ce._filename += ".aiff";
+				filename += ".aiff";
 			else if (ce._id == ID_OGG)
-				ce._filename += ".ogg";
+				filename += ".ogg";
 			else if (ce._id == ID_MOD)
-				ce._filename += ".mod";
+				filename += ".mod";
 
 		} else if (ce._type == ID_Data) {
-			ce._filename = Common::String::format("data%u", ce._number);
+			filename = Common::String::format("data%u", ce._number);
 
 		} else if (ce._type == ID_Exec) {
 			if (
@@ -154,15 +152,15 @@ Common::ErrorCode Blorb::load() {
 				(_interpType == INTERPRETER_ZCODE && ce._id == ID_ZCOD)
 			) {
 				// Game executable
-				ce._filename = "game";
+				filename = "game";
 			} else {
 				char buffer[5];
 				WRITE_BE_UINT32(buffer, ce._id);
 				buffer[4] = '\0';
-				Common::String type(buffer);
-				ce._filename = type;
+				filename = Common::String(buffer);
 			}
 		}
+		ce._filename = Common::Path(filename);
 	}
 
 	// Check through any optional remaining chunks for an adaptive palette list
@@ -251,7 +249,7 @@ bool Blorb::isBlorb(Common::SeekableReadStream &stream, uint32 type) {
 	return false;
 }
 
-bool Blorb::isBlorb(const Common::String &filename, uint32 type) {
+bool Blorb::isBlorb(const Common::Path &filename, uint32 type) {
 	Common::File f;
 	if (!filename.empty() && !f.open(filename))
 		return false;
@@ -265,10 +263,10 @@ bool Blorb::hasBlorbExt(const Common::String &filename) {
 		|| filename.hasSuffixIgnoreCase(".zlb") || filename.hasSuffixIgnoreCase(".a3r");
 }
 
-void Blorb::getBlorbFilenames(const Common::String &srcFilename, Common::StringArray &filenames,
+void Blorb::getBlorbFilenames(const Common::Path &srcFilename, Common::Array<Common::Path> &filenames,
 		InterpreterType interpType, const Common::String &gameId) {
 	// Strip off the source filename extension
-	Common::String filename = srcFilename;
+	Common::String filename = srcFilename.baseName();
 	if (!filename.contains('.')) {
 		filename += '.';
 	} else {
@@ -278,18 +276,18 @@ void Blorb::getBlorbFilenames(const Common::String &srcFilename, Common::StringA
 
 	// Add in the different possible filenames
 	filenames.clear();
-	filenames.push_back(filename + "blorb");
-	filenames.push_back(filename + "blb");
+	filenames.push_back(srcFilename.getParent().appendComponent(filename + "blorb"));
+	filenames.push_back(srcFilename.getParent().appendComponent(filename + "blb"));
 
 	switch (interpType) {
 	case INTERPRETER_ALAN3:
-		filenames.push_back(filename + "a3r");
+		filenames.push_back(srcFilename.getParent().appendComponent(filename + "a3r"));
 		break;
 	case INTERPRETER_GLULX:
-		filenames.push_back(filename + "gblorb");
+		filenames.push_back(srcFilename.getParent().appendComponent(filename + "gblorb"));
 		break;
 	case INTERPRETER_ZCODE:
-		filenames.push_back(filename + "zblorb");
+		filenames.push_back(srcFilename.getParent().appendComponent(filename + "zblorb"));
 		getInfocomBlorbFilenames(filenames, gameId);
 		break;
 	default:
@@ -297,7 +295,7 @@ void Blorb::getBlorbFilenames(const Common::String &srcFilename, Common::StringA
 	}
 }
 
-void Blorb::getInfocomBlorbFilenames(Common::StringArray &filenames, const Common::String &gameId) {
+void Blorb::getInfocomBlorbFilenames(Common::Array<Common::Path> &filenames, const Common::String &gameId) {
 	if (gameId == "beyondzork")
 		filenames.push_back("beyondzork.blb");
 	else if (gameId == "journey")
diff --git a/engines/glk/blorb.h b/engines/glk/blorb.h
index 1105fb96fc2..9c90edb530b 100644
--- a/engines/glk/blorb.h
+++ b/engines/glk/blorb.h
@@ -38,7 +38,7 @@ struct ChunkEntry {
 	uint _id;
 	size_t _offset;
 	size_t _size;
-	Common::String _filename;
+	Common::Path _filename;
 };
 
 enum {
@@ -81,7 +81,7 @@ enum {
  */
 class Blorb : public Common::Archive {
 private:
-	Common::String _filename;
+	Common::Path _filename;
 	Common::FSNode _fileNode;
 	InterpreterType _interpType;
 	Common::Array<ChunkEntry> _chunks;	///< list of chunk descriptors
@@ -94,12 +94,12 @@ private:
 	/**
 	 * Add possible Blorb filenames for Infocom games
 	 */
-	static void getInfocomBlorbFilenames(Common::StringArray &filenames, const Common::String &gameId);
+	static void getInfocomBlorbFilenames(Common::Array<Common::Path> &filenames, const Common::String &gameId);
 public:
 	/**
 	 * Constructor
 	 */
-	Blorb(const Common::String &filename, InterpreterType interpType);
+	Blorb(const Common::Path &filename, InterpreterType interpType);
 
 	/**
 	 * Constructor
@@ -146,7 +146,7 @@ public:
 	/**
 	 * Returns true if a given filename specifies a Blorb file
 	 */
-	static bool isBlorb(const Common::String &filename, uint32 type = 0);
+	static bool isBlorb(const Common::Path &filename, uint32 type = 0);
 
 	/**
 	 * Returns true if a given filename has a Blorb file extension
@@ -156,7 +156,7 @@ public:
 	/**
 	 * Return a list of possible filenames for blorb files
 	 */
-	static void getBlorbFilenames(const Common::String &srcFilename, Common::StringArray &filenames,
+	static void getBlorbFilenames(const Common::Path &srcFilename, Common::Array<Common::Path> &filenames,
 		InterpreterType interpType, const Common::String &gameId);
 };
 
diff --git a/engines/glk/comprehend/file_buf.cpp b/engines/glk/comprehend/file_buf.cpp
index 88135ac6c16..84a45cad132 100644
--- a/engines/glk/comprehend/file_buf.cpp
+++ b/engines/glk/comprehend/file_buf.cpp
@@ -29,7 +29,7 @@ namespace Comprehend {
 FileBuffer::FileBuffer(const Common::String &filename) : _pos(0) {
 	// Open the file
 	Common::File f;
-	if (!f.open(filename))
+	if (!f.open(Common::Path(filename)))
 		error("Could not open - %s", filename.c_str());
 
 	_data.resize(f.size());
@@ -45,7 +45,7 @@ FileBuffer::FileBuffer(Common::ReadStream *stream, size_t size) : _pos(0) {
 
 
 bool FileBuffer::exists(const Common::String &filename) {
-	return Common::File::exists(filename);
+	return Common::File::exists(Common::Path(filename));
 }
 
 void FileBuffer::close() {
diff --git a/engines/glk/comprehend/pics.cpp b/engines/glk/comprehend/pics.cpp
index e0a5a74966d..903886f50d3 100644
--- a/engines/glk/comprehend/pics.cpp
+++ b/engines/glk/comprehend/pics.cpp
@@ -100,13 +100,12 @@ void Pics::ImageContext::lineFixes() {
 
 /*-------------------------------------------------------*/
 
-Pics::ImageFile::ImageFile(const Common::String &filename, bool isSingleImage) {
+Pics::ImageFile::ImageFile(const Common::String &filename, bool isSingleImage) : _filename(filename) {
 	Common::File f;
 	uint16 version;
 	int i;
 
-	_filename = filename;
-	if (!f.open(filename))
+	if (!f.open(_filename))
 		error("Could not open file - %s", filename.c_str());
 
 	if (isSingleImage) {
@@ -363,7 +362,7 @@ int Pics::getPictureNumber(const Common::String &filename) const {
 }
 
 bool Pics::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
+	Common::String name = path.baseName();
 	int num = getPictureNumber(name);
 	if (num == -1)
 		return false;
@@ -383,18 +382,17 @@ int Pics::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr Pics::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
+	Common::String name = path.baseName();
 	// Get the picture number
 	int num = getPictureNumber(name);
-	if (num == -1 || !hasFile(name))
+	if (num == -1 || !hasFile(path))
 		return nullptr;
 
 	// Draw the image
diff --git a/engines/glk/comprehend/pics.h b/engines/glk/comprehend/pics.h
index c1a1aeef4d9..cc982db16aa 100644
--- a/engines/glk/comprehend/pics.h
+++ b/engines/glk/comprehend/pics.h
@@ -76,7 +76,7 @@ class Pics : public Common::Archive {
 	struct ImageFile {
 	private:
 		Common::Array<uint16> _imageOffsets;
-		Common::String _filename;
+		Common::Path _filename;
 
 	private:
 		bool doImageOp(ImageContext *ctx) const;
diff --git a/engines/glk/debugger.cpp b/engines/glk/debugger.cpp
index f7eae41c248..6d8a193a32f 100644
--- a/engines/glk/debugger.cpp
+++ b/engines/glk/debugger.cpp
@@ -55,9 +55,9 @@ bool Debugger::cmdDumpPic(int argc, const char **argv) {
 		Common::File f;
 		int picNum = strToInt(argv[1]);
 
-		Common::String filename = Common::String::format("pic%d.png", picNum);
+		Common::Path filename(Common::String::format("pic%d.png", picNum));
 		if (!f.exists(filename))
-			filename = Common::String::format("pic%d.jpg", picNum);
+			filename = Common::Path(Common::String::format("pic%d.jpg", picNum));
 
 		if (f.open(filename)) {
 			// png or jpeg file
@@ -74,15 +74,15 @@ bool Debugger::cmdDumpPic(int argc, const char **argv) {
 			} else {
 				debugPrintf("Could not find specified picture\n");
 			}
-		} else if (f.exists(Common::String::format("pic%d.rect", picNum))) {
+		} else if (f.exists(Common::Path(Common::String::format("pic%d.rect", picNum)))) {
 			debugPrintf("Picture is only a placeholder rectangle\n");
-		} else if (f.open(Common::String::format("pic%d.raw", picNum))) {
+		} else if (f.open(Common::Path(Common::String::format("pic%d.raw", picNum)))) {
 			// Raw picture
 #ifdef USE_PNG
 			Common::DumpFile df;
 			RawDecoder rd;
 
-			if (rd.loadStream(f) && df.open(Common::String::format("pic%d.png", picNum))) {
+			if (rd.loadStream(f) && df.open(Common::Path(Common::String::format("pic%d.png", picNum)))) {
 				saveRawPicture(rd, df);
 				debugPrintf("Dumped picture\n");
 			} else {
diff --git a/engines/glk/detection.cpp b/engines/glk/detection.cpp
index 5ee75a09500..fe87cca019b 100644
--- a/engines/glk/detection.cpp
+++ b/engines/glk/detection.cpp
@@ -116,7 +116,7 @@ GlkDetectedGame::GlkDetectedGame(const char *id, const char *desc, const Common:
 	FileProperties fp;
 	fp.md5 = md5;
 	fp.size = filesize;
-	matchedFiles[filename] = fp;
+	matchedFiles[Common::Path(filename)] = fp;
 }
 
 } // End of namespace Glk
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 1a2af57355a..8acb805a1b8 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -111,7 +111,7 @@ void GlkEngine::createConfiguration() {
 
 Common::Error GlkEngine::run() {
 	// Open up the game file
-	Common::String filename = getFilename();
+	Common::Path filename(getFilename());
 	if (!Common::File::exists(filename))
 		return Common::kNoGameDataFoundError;
 
@@ -124,7 +124,7 @@ Common::Error GlkEngine::run() {
 			return Common::kNoGameDataFoundError;
 	} else {
 		// Check for a secondary blorb file with the same filename
-		Common::StringArray blorbFilenames;
+		Common::Array<Common::Path> blorbFilenames;
 		Blorb::getBlorbFilenames(filename, blorbFilenames, getInterpreterType(), getGameID());
 
 		for (uint idx = 0; idx < blorbFilenames.size(); ++idx) {
diff --git a/engines/glk/hugo/resource_archive.cpp b/engines/glk/hugo/resource_archive.cpp
index a6546a452fb..d6f610bbc42 100644
--- a/engines/glk/hugo/resource_archive.cpp
+++ b/engines/glk/hugo/resource_archive.cpp
@@ -48,10 +48,9 @@ bool ResourceArchive::splitName(const Common::String &name,
 
 
 bool ResourceArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	Common::String filename, resName;
 
-	if (!splitName(name, filename, resName))
+	if (!splitName(path.baseName(), filename, resName))
 		return false;
 	size_t resLength = g_vm->FindResource(filename.c_str(), resName.c_str());
 	g_vm->hugo_fclose(g_vm->resource_file);
@@ -60,19 +59,17 @@ bool ResourceArchive::hasFile(const Common::Path &path) const {
 }
 
 const Common::ArchiveMemberPtr ResourceArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *ResourceArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	Common::String filename, resName;
 
 	// Split up the file and resource entry; return if it's not one
-	if (!splitName(name, filename, resName))
+	if (!splitName(path.baseName(), filename, resName))
 		return nullptr;
 
 	// Try and get the entry details from the given file
diff --git a/engines/glk/jacl/types.h b/engines/glk/jacl/types.h
index 74f5e6046d6..5f81b5ba10b 100644
--- a/engines/glk/jacl/types.h
+++ b/engines/glk/jacl/types.h
@@ -196,7 +196,7 @@ class File : public Common::File {
 public:
 	static File *openForReading(const Common::String &name) {
 		File *f = new File();
-		if (f->open(name))
+		if (f->open(Common::Path(name)))
 			return f;
 
 		delete f;
@@ -205,7 +205,7 @@ public:
 
 	static Common::WriteStream *openForWriting(const Common::String &name) {
 		Common::DumpFile *df = new Common::DumpFile();
-		if (df->open(name))
+		if (df->open(Common::Path(name)))
 			return df;
 
 		delete df;
@@ -213,7 +213,7 @@ public:
 	}
 public:
 	File() : Common::File() {}
-	File(const Common::String &name) {
+	File(const Common::Path &name) {
 		Common::File::open(name);
 		assert(isOpen());
 	}
diff --git a/engines/glk/magnetic/glk.cpp b/engines/glk/magnetic/glk.cpp
index babd1cf15e4..075eb6be943 100644
--- a/engines/glk/magnetic/glk.cpp
+++ b/engines/glk/magnetic/glk.cpp
@@ -301,7 +301,7 @@ type32 Magnetic::gms_gameid_read_uint32(int offset, Common::SeekableReadStream *
 void Magnetic::gms_gameid_identify_game(const Common::String &text_file) {
 	Common::File stream;
 
-	if (!stream.open(text_file))
+	if (!stream.open(Common::Path(text_file)))
 		error("Error opening game file");
 
 	type32 game_size, game_pc;
diff --git a/engines/glk/metaengine.cpp b/engines/glk/metaengine.cpp
index 13693dcbfe5..3831e8fe367 100644
--- a/engines/glk/metaengine.cpp
+++ b/engines/glk/metaengine.cpp
@@ -141,7 +141,7 @@ template<class META, class ENG>bool create(OSystem *syst,
 
 Common::String GlkMetaEngine::findFileByGameId(const Common::String &gameId) const {
 	// Get the list of files in the folder and return detection against them
-	Common::FSNode folder = Common::FSNode(ConfMan.get("path"));
+	Common::FSNode folder = Common::FSNode(ConfMan.getPath("path"));
 	Common::FSList fslist;
 	folder.getChildren(fslist, Common::FSNode::kListFilesOnly);
 
@@ -192,7 +192,7 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) {
 
 	// Get the MD5
 	Common::File f;
-	if (!f.open(Common::FSNode(ConfMan.get("path")).getChild(gameDesc._filename)))
+	if (!f.open(Common::FSNode(ConfMan.getPath("path")).getChild(gameDesc._filename)))
 		return Common::kNoGameDataFoundError;
 
 	Common::String fileName = f.getName();
diff --git a/engines/glk/picture.cpp b/engines/glk/picture.cpp
index 13d3e2cbca9..dbc54b7c915 100644
--- a/engines/glk/picture.cpp
+++ b/engines/glk/picture.cpp
@@ -128,9 +128,9 @@ Picture *Pictures::load(const Common::String &name) {
 		return pic;
 
 	Common::File f;
-	if ((name.hasSuffixIgnoreCase(".png") && f.open(name))
-		|| f.open(Common::String::format("pic%s.png", name.c_str()))
-		|| f.open(Common::String::format("%s.png", name.c_str()))
+	if ((name.hasSuffixIgnoreCase(".png") && f.open(Common::Path(name)))
+		|| f.open(Common::Path(Common::String::format("pic%s.png", name.c_str())))
+		|| f.open(Common::Path(Common::String::format("%s.png", name.c_str())))
 	) {
 		png.setKeepTransparencyPaletted(true);
 		png.loadStream(f);
@@ -140,23 +140,23 @@ Picture *Pictures::load(const Common::String &name) {
 		hasTransColor = png.hasTransparentColor();
 		transColor = png.getTransparentColor();
 	} else if (
-		((name.hasSuffixIgnoreCase(".jpg") || name.hasSuffixIgnoreCase(".jpeg")) && f.open(name))
-		|| f.open(Common::String::format("pic%s.jpg", name.c_str()))
-		|| f.open(Common::String::format("pic%s.jpeg", name.c_str()))
-		|| f.open(Common::String::format("%s.jpg", name.c_str()))
+		((name.hasSuffixIgnoreCase(".jpg") || name.hasSuffixIgnoreCase(".jpeg")) && f.open(Common::Path(name)))
+		|| f.open(Common::Path(Common::String::format("pic%s.jpg", name.c_str())))
+		|| f.open(Common::Path(Common::String::format("pic%s.jpeg", name.c_str())))
+		|| f.open(Common::Path(Common::String::format("%s.jpg", name.c_str())))
 	) {
 		jpg.setOutputPixelFormat(g_system->getScreenFormat());
 		jpg.loadStream(f);
 		img = jpg.getSurface();
-	} else if ((name.hasSuffixIgnoreCase(".raw") && f.open(name)) ||
-			f.open(Common::String::format("pic%s.raw", name.c_str()))) {
+	} else if ((name.hasSuffixIgnoreCase(".raw") && f.open(Common::Path(name))) ||
+			f.open(Common::Path(Common::String::format("pic%s.raw", name.c_str())))) {
 		raw.loadStream(f);
 		img = raw.getSurface();
 		palette = raw.getPalette();
 		palCount = raw.getPaletteColorCount();
 		hasTransColor = raw.hasTransparentColor();
 		transColor = raw.getTransparentColor();
-	} else if (f.open(Common::String::format("pic%s.rect", name.c_str()))) {
+	} else if (f.open(Common::Path(Common::String::format("pic%s.rect", name.c_str())))) {
 		rectImg.w = f.readUint32BE();
 		rectImg.h = f.readUint32BE();
 		img = &rectImg;
diff --git a/engines/glk/quest/geas_glk.cpp b/engines/glk/quest/geas_glk.cpp
index 025c4554675..dfea4a9995d 100644
--- a/engines/glk/quest/geas_glk.cpp
+++ b/engines/glk/quest/geas_glk.cpp
@@ -111,7 +111,7 @@ void GeasGlkInterface::set_background(String s) {
  */
 String GeasGlkInterface::get_file(const String &fname) const {
 	Common::File f;
-	if (!f.open(fname)) {
+	if (!f.open(Common::Path(fname))) {
 		glk_put_cstring("Couldn't open ");
 		glk_put_cstring(fname.c_str());
 		g_vm->glk_put_char(0x0a);
diff --git a/engines/glk/sound.cpp b/engines/glk/sound.cpp
index a6bde487cf6..19dc474aff2 100644
--- a/engines/glk/sound.cpp
+++ b/engines/glk/sound.cpp
@@ -96,11 +96,11 @@ uint SoundChannel::play(uint soundNum, uint repeats, uint notify) {
 	// Find a sound of the given name
 	Audio::AudioStream *stream;
 	Common::File f;
-	Common::String nameSnd = Common::String::format("sound%u.snd", soundNum);
-	Common::String nameWav = Common::String::format("sound%u.wav", soundNum);
-	Common::String nameAiff = Common::String::format("sound%u.aiff", soundNum);
+	Common::Path nameSnd(Common::String::format("sound%u.snd", soundNum));
+	Common::Path nameWav(Common::String::format("sound%u.wav", soundNum));
+	Common::Path nameAiff(Common::String::format("sound%u.aiff", soundNum));
 #ifdef USE_MAD
-	Common::String nameMp3 = Common::String::format("sound%u.mp3", soundNum);
+	Common::Path nameMp3(Common::String::format("sound%u.mp3", soundNum));
 #endif
 
 	if (f.exists(nameSnd) && f.open(nameSnd)) {
diff --git a/engines/glk/streams.cpp b/engines/glk/streams.cpp
index ef39a97bce9..805bb9feaa6 100644
--- a/engines/glk/streams.cpp
+++ b/engines/glk/streams.cpp
@@ -1326,7 +1326,7 @@ FileStream::FileStream(Streams *streams, frefid_t fref, uint fmode, uint rock, b
 		setStream(_outSave);
 
 	} else if (fmode == filemode_Read) {
-		if (_file.open(fname)) {
+		if (_file.open(Common::Path(fname))) {
 			setStream(&_file);
 		} else {
 			_inSave = g_system->getSavefileManager()->openForLoading(fname);
@@ -1550,7 +1550,7 @@ bool FileReference::exists() const {
 	Common::String filename;
 
 	if (_slotNumber == -1) {
-		if (Common::File::exists(_filename))
+		if (Common::File::exists(Common::Path(_filename)))
 			return true;
 		filename = _filename;
 	} else {
diff --git a/engines/glk/zcode/glk_interface.cpp b/engines/glk/zcode/glk_interface.cpp
index 6e23f8dbcfb..b41a7f31ceb 100644
--- a/engines/glk/zcode/glk_interface.cpp
+++ b/engines/glk/zcode/glk_interface.cpp
@@ -229,7 +229,7 @@ void GlkInterface::initialize() {
 }
 
 void GlkInterface::addSound() {
-	Common::FSNode gameDir(ConfMan.get("path"));
+	Common::FSNode gameDir(ConfMan.getPath("path"));
 	SoundSubfolder::check(gameDir);
 	SoundZip::check(gameDir, _storyId);
 }
diff --git a/engines/glk/zcode/pics.cpp b/engines/glk/zcode/pics.cpp
index 438aa525e7c..66e0f5b24e6 100644
--- a/engines/glk/zcode/pics.cpp
+++ b/engines/glk/zcode/pics.cpp
@@ -37,7 +37,7 @@ enum {
 
 Pics::Pics() : Common::Archive(), _filename(getFilename()) {
 	Common::File f;
-	if (!f.open(_filename))
+	if (!f.open(Common::Path(_filename)))
 		error("Error reading Pics file");
 
 	_palette = new Common::Array<byte>();
@@ -109,7 +109,7 @@ Common::String Pics::getFilename() {
 }
 
 bool Pics::exists() {
-	return Common::File::exists(getFilename());
+	return Common::File::exists(Common::Path(getFilename()));
 }
 
 bool Pics::hasFile(const Common::Path &path) const {
@@ -131,11 +131,10 @@ int Pics::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr Pics::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::Path &path) const {
@@ -147,7 +146,7 @@ Common::SeekableReadStream *Pics::createReadStreamForMember(const Common::Path &
 		if (e._filename.equalsIgnoreCase(name)) {
 			Common::File f;
 			Common::SeekableReadStream *dest;
-			if (!f.open(_filename))
+			if (!f.open(path))
 				error("Reading failed");
 
 			if (e._dataSize) {
diff --git a/engines/glk/zcode/sound_folder.cpp b/engines/glk/zcode/sound_folder.cpp
index 151cd0607d9..bfb84a23d62 100644
--- a/engines/glk/zcode/sound_folder.cpp
+++ b/engines/glk/zcode/sound_folder.cpp
@@ -39,7 +39,7 @@ SoundSubfolder::SoundSubfolder(const Common::FSNode &folder) : _folder(folder) {
 			Common::String filename = files[idx].getName();
 			if (filename.hasSuffixIgnoreCase(".snd")) {
 				int fileNum = atoi(filename.c_str() + filename.size() - 6);
-				Common::String newName = Common::String::format("sound%d.snd", fileNum);
+				Common::Path newName(Common::String::format("sound%d.snd", fileNum));
 
 				_filenames[newName] = filename;
 			}
@@ -48,13 +48,12 @@ SoundSubfolder::SoundSubfolder(const Common::FSNode &folder) : _folder(folder) {
 }
 
 bool SoundSubfolder::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return _filenames.contains(name);
+	return _filenames.contains(path);
 }
 
 int SoundSubfolder::listMembers(Common::ArchiveMemberList &list) const {
 	int total = 0;
-	for (Common::StringMap::iterator i = _filenames.begin(); i != _filenames.end(); ++i) {
+	for (FileMap::iterator i = _filenames.begin(); i != _filenames.end(); ++i) {
 		list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember((*i)._key, *this)));
 		++total;
 	}
@@ -63,17 +62,15 @@ int SoundSubfolder::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr SoundSubfolder::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *SoundSubfolder::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	Common::File *f = new Common::File();
-	if (_filenames.contains(name) && f->open(_folder.getChild(_filenames[name])))
+	if (_filenames.contains(path) && f->open(_folder.getChild(_filenames[path])))
 		return f;
 
 	delete f;
@@ -100,10 +97,11 @@ SoundZip::SoundZip(Common::Archive *zip) : _zip(zip) {
 	zip->listMembers(files);
 
 	for (Common::ArchiveMemberList::iterator i = files.begin(); i != files.end(); ++i) {
-		Common::String filename = (*i)->getName();
-		if (filename.hasSuffixIgnoreCase(".snd")) {
-			int fileNum = atoi(filename.c_str() + filename.size() - 6);
-			Common::String newName = Common::String::format("sound%d.snd", fileNum);
+		Common::Path filename = (*i)->getPathInArchive();
+		Common::String basename(filename.baseName());
+		if (basename.hasSuffixIgnoreCase(".snd")) {
+			int fileNum = atoi(basename.c_str() + basename.size() - 6);
+			Common::Path newName(Common::String::format("sound%d.snd", fileNum));
 
 			_filenames[newName] = filename;
 		}
@@ -115,14 +113,13 @@ SoundZip::~SoundZip() {
 }
 
 bool SoundZip::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return _filenames.contains(name);
+	return _filenames.contains(path);
 }
 
 int SoundZip::listMembers(Common::ArchiveMemberList &list) const {
 	int total = 0;
 
-	for (Common::StringMap::iterator i = _filenames.begin(); i != _filenames.end(); ++i) {
+	for (FileMap::iterator i = _filenames.begin(); i != _filenames.end(); ++i) {
 		list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember((*i)._key, *this)));
 		++total;
 	}
@@ -131,20 +128,18 @@ int SoundZip::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr SoundZip::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 
 }
 
 Common::SeekableReadStream *SoundZip::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!_filenames.contains(name))
+	if (!_filenames.contains(path))
 		return nullptr;
 
-	return _zip->createReadStreamForMember(_filenames[name]);
+	return _zip->createReadStreamForMember(_filenames[path]);
 }
 
 } // End of namespace ZCode
diff --git a/engines/glk/zcode/sound_folder.h b/engines/glk/zcode/sound_folder.h
index 97c0cc6c873..6b35be33a56 100644
--- a/engines/glk/zcode/sound_folder.h
+++ b/engines/glk/zcode/sound_folder.h
@@ -25,7 +25,7 @@
 #include "glk/zcode/frotz_types.h"
 #include "common/archive.h"
 #include "common/fs.h"
-#include "common/hash-str.h"
+#include "common/hashmap.h"
 
 namespace Glk {
 namespace ZCode {
@@ -38,7 +38,8 @@ namespace ZCode {
 class SoundSubfolder : public Common::Archive {
 private:
 	Common::FSNode _folder;
-	Common::StringMap _filenames;
+	typedef Common::HashMap<Common::Path, Common::String, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
+	FileMap _filenames;
 private:
 	/**
 	 * Constructor
@@ -86,7 +87,8 @@ public:
 class SoundZip : public Common::Archive {
 private:
 	Common::Archive *_zip;
-	Common::StringMap _filenames;
+	typedef Common::HashMap<Common::Path, Common::Path, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
+	FileMap _filenames;
 private:
 	/**
 	 * Constructor


Commit: 49da9211ec03bfe94e2f4bd2eab553551c0f323d
    https://github.com/scummvm/scummvm/commit/49da9211ec03bfe94e2f4bd2eab553551c0f323d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GNAP: Migrate engine to Path

Changed paths:
    engines/gnap/music.cpp
    engines/gnap/music.h


diff --git a/engines/gnap/music.cpp b/engines/gnap/music.cpp
index bbe96d9e7f2..e1208c698ae 100644
--- a/engines/gnap/music.cpp
+++ b/engines/gnap/music.cpp
@@ -68,7 +68,7 @@ void MusicPlayer::playSMF(bool loop) {
 	Common::File musicFile;
 	musicFile.open(_filename);
 	if (!musicFile.isOpen()) {
-		debugC(2, kDebugMusic, "Cannot open music file %s", _filename.c_str());
+		debugC(2, kDebugMusic, "Cannot open music file %s", _filename.toString().c_str());
 		return;
 	}
 	int midiMusicSize = musicFile.size();
@@ -91,7 +91,7 @@ void MusicPlayer::playSMF(bool loop) {
 		_isLooping = loop;
 		_isPlaying = true;
 	} else {
-		debugC(2, kDebugMusic, "Cannot play music file %s", _filename.c_str());
+		debugC(2, kDebugMusic, "Cannot play music file %s", _filename.toString().c_str());
 		delete parser;
 	}
 }
diff --git a/engines/gnap/music.h b/engines/gnap/music.h
index 9e3b093d6d3..1f50715e8cb 100644
--- a/engines/gnap/music.h
+++ b/engines/gnap/music.h
@@ -41,7 +41,7 @@ public:
 	void sendToChannel(byte channel, uint32 b) override;
 
 protected:
-	Common::String _filename;
+	Common::Path _filename;
 };
 
 } // End of namespace Gnap


Commit: 8c49d1442e9c19c81fb2e1ffbe4de12078f345c8
    https://github.com/scummvm/scummvm/commit/8c49d1442e9c19c81fb2e1ffbe4de12078f345c8
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GOB: Migrate engine to Path

Changed paths:
    engines/gob/databases.cpp
    engines/gob/databases.h
    engines/gob/dataio.cpp
    engines/gob/dataio.h
    engines/gob/detection/detection.cpp
    engines/gob/iniconfig.cpp
    engines/gob/init_v7.cpp
    engines/gob/inter_v7.cpp
    engines/gob/resources.cpp
    engines/gob/resources.h


diff --git a/engines/gob/databases.cpp b/engines/gob/databases.cpp
index d29ca2ea806..1fa0e5f3f54 100644
--- a/engines/gob/databases.cpp
+++ b/engines/gob/databases.cpp
@@ -58,7 +58,7 @@ void Databases::setLanguage(Common::Language language) {
 	_language = lang;
 }
 
-bool Databases::open(const Common::String &id, const Common::String &file) {
+bool Databases::open(const Common::String &id, const Common::Path &file) {
 	if (_databases.contains(id)) {
 		warning("Databases::open(): A database with the ID \"%s\" already exists", id.c_str());
 		return false;
@@ -66,13 +66,13 @@ bool Databases::open(const Common::String &id, const Common::String &file) {
 
 	Common::File dbFile;
 	if (!dbFile.open(file)) {
-		warning("Databases::open(): No such file \"%s\"", file.c_str());
+		warning("Databases::open(): No such file \"%s\"", file.toString().c_str());
 		return false;
 	}
 
 	dBase db;
 	if (!db.load(dbFile)) {
-		warning("Databases::open(): Failed loading database file \"%s\"", file.c_str());
+		warning("Databases::open(): Failed loading database file \"%s\"", file.toString().c_str());
 		return false;
 	}
 
@@ -81,7 +81,7 @@ bool Databases::open(const Common::String &id, const Common::String &file) {
 	assert(map != _databases.end());
 
 	if (!buildMap(db, map->_value)) {
-		warning("Databases::open(): Failed building a map for database \"%s\"", file.c_str());
+		warning("Databases::open(): Failed building a map for database \"%s\"", file.toString().c_str());
 		_databases.erase(map);
 		return false;
 	}
diff --git a/engines/gob/databases.h b/engines/gob/databases.h
index a9b4e4fb0d5..7b9dbc5fb1f 100644
--- a/engines/gob/databases.h
+++ b/engines/gob/databases.h
@@ -38,7 +38,7 @@ public:
 
 	void setLanguage(Common::Language language);
 
-	bool open(const Common::String &id, const Common::String &file);
+	bool open(const Common::String &id, const Common::Path &file);
 	bool close(const Common::String &id);
 
 	bool getString(const Common::String &id, Common::String group,
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index 2309ca34fdd..dba7027ca91 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -231,7 +231,7 @@ bool DataIO::openArchive(Common::String name, bool base) {
 		name += ".stk";
 
 	// Try to open
-	*archive = openArchive(name);
+	*archive = openArchive(Common::Path(name));
 	if (!*archive)
 		return false;
 
@@ -245,14 +245,14 @@ static void replaceChar(char *str, char c1, char c2) {
 		*str = c2;
 }
 
-DataIO::Archive *DataIO::openArchive(const Common::String &name) {
+DataIO::Archive *DataIO::openArchive(const Common::Path &name) {
 	Archive *archive = new Archive;
 	if (!archive->file.open(name)) {
 		delete archive;
 		return nullptr;
 	}
 
-	archive->name = name;
+	archive->name = name.toString('/');
 
 	uint16 fileCount = archive->file.readUint16LE();
 	for (uint16 i = 0; i < fileCount; i++) {
@@ -316,7 +316,7 @@ bool DataIO::hasFile(const Common::String &name){
 		return true;
 
 	// Else, look if a plain file that matches exists
-	return Common::File::exists(name);
+	return Common::File::exists(Common::Path(name));
 }
 
 int32 DataIO::fileSize(const Common::String &name) {
@@ -342,7 +342,7 @@ int32 DataIO::fileSize(const Common::String &name) {
 
 	// Else, try to find a matching plain file
 	Common::File f;
-	if (!f.open(name))
+	if (!f.open(Common::Path(name)))
 		return -1;
 
 	return f.size();
@@ -359,7 +359,7 @@ Common::SeekableReadStream *DataIO::getFile(const Common::String &name) {
 
 	// Else, try to open a matching plain file
 	Common::File f;
-	if (!f.open(name))
+	if (!f.open(Common::Path(name)))
 		return nullptr;
 
 	return f.readStream(f.size());
@@ -376,7 +376,7 @@ byte *DataIO::getFile(const Common::String &name, int32 &size) {
 
 	// Else, try to open a matching plain file
 	Common::File f;
-	if (!f.open(name))
+	if (!f.open(Common::Path(name)))
 		return nullptr;
 
 	size = f.size();
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index afa43bef461..6a6c9462be3 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -90,7 +90,7 @@ private:
 
 	Common::Array<Archive *> _archives;
 
-	Archive *openArchive(const Common::String &name);
+	Archive *openArchive(const Common::Path &name);
 	bool closeArchive(Archive &archive);
 
 	File *findFile(const Common::String &name);
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp
index 644ba9fdc09..10cebfad6b1 100644
--- a/engines/gob/detection/detection.cpp
+++ b/engines/gob/detection/detection.cpp
@@ -100,7 +100,7 @@ ADDetectedGame GobMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 const Gob::GOBGameDescription *GobMetaEngineDetection::detectOnceUponATime(const Common::FSList &fslist) {
 	// Add the game path to the search manager
 	SearchMan.clear();
-	SearchMan.addDirectory(fslist.begin()->getParent().getPath(), fslist.begin()->getParent());
+	SearchMan.addDirectory(fslist.begin()->getParent());
 
 	// Open the archives
 	Gob::DataIO dataIO;
diff --git a/engines/gob/iniconfig.cpp b/engines/gob/iniconfig.cpp
index 1709aba19a4..7e21c72865c 100644
--- a/engines/gob/iniconfig.cpp
+++ b/engines/gob/iniconfig.cpp
@@ -75,7 +75,9 @@ bool INIConfig::openConfig(const Common::String &file, Config &config) {
 	config.config  = new Common::INIFile();
 	config.created = false;
 
-	if (!config.config->loadFromFile(file)) {
+	// GOB uses \ as a path separator but
+	// it almost always manipulates base names
+	if (!config.config->loadFromFile(Common::Path(file, '\\'))) {
 		delete config.config;
 		config.config = nullptr;
 		return false;
diff --git a/engines/gob/init_v7.cpp b/engines/gob/init_v7.cpp
index 9076ca09aab..d201ee420a2 100644
--- a/engines/gob/init_v7.cpp
+++ b/engines/gob/init_v7.cpp
@@ -33,7 +33,7 @@ Init_v7::~Init_v7() {
 }
 
 void Init_v7::initGame() {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	// Add the environment directory
 	SearchMan.addSubDirectoryMatching(gameDataDir, "envir");
diff --git a/engines/gob/inter_v7.cpp b/engines/gob/inter_v7.cpp
index aa67735095e..8e95d5ebc74 100644
--- a/engines/gob/inter_v7.cpp
+++ b/engines/gob/inter_v7.cpp
@@ -724,7 +724,7 @@ void Inter_v7::o7_setActiveCD() {
 	Common::String str1 = _vm->_game->_script->evalString();
 
 	Common::ArchiveMemberDetailsList files;
-	SearchMan.listMatchingMembers(files, str0);
+	SearchMan.listMatchingMembers(files, Common::Path(str0));
 	Common::String savedCDpath = _currentCDPath;
 
 	for (Common::ArchiveMemberDetails file : files) {
@@ -739,7 +739,7 @@ void Inter_v7::o7_setActiveCD() {
 }
 
 void Inter_v7::o7_findFile() {
-	Common::String file_pattern = getFile(_vm->_game->_script->evalString());
+	Common::Path file_pattern(getFile(_vm->_game->_script->evalString()));
 	Common::ArchiveMemberList files;
 
 	SearchMan.listMatchingMembers(files, file_pattern);
@@ -758,7 +758,7 @@ void Inter_v7::o7_findFile() {
 	}
 
 	debugC(5, kDebugFileIO, "o7_findFile(%s): %d matches (%d including duplicates)",
-		   file_pattern.c_str(),
+		   file_pattern.toString().c_str(),
 		   filesWithoutDuplicates.size(),
 		   files.size());
 
@@ -769,7 +769,7 @@ void Inter_v7::o7_findFile() {
 		Common::String file = files.front()->getName();
 		filesWithoutDuplicates.pop_front();
 		debugC(5, kDebugFileIO, "o7_findFile(%s): first match = %s",
-			   file_pattern.c_str(),
+			   file_pattern.toString().c_str(),
 			   file.c_str());
 
 		storeString(file.c_str());
@@ -961,7 +961,7 @@ void Inter_v7::o7_opendBase() {
 	dbFile += ".DBF";
 
 	_databases.setLanguage(_vm->_language);
-	if (!_databases.open(id, dbFile)) {
+	if (!_databases.open(id, Common::Path(dbFile))) {
 		WRITE_VAR(27, 0); // Failure
 		return;
 	}
@@ -1250,7 +1250,7 @@ void Inter_v7::o7_checkData(OpFuncParams &params) {
 		if (indexAppli == -1) {
 			// New appli, find the first directory containing an application still not installed, and set it as "current CD" path.
 			Common::ArchiveMemberDetailsList files;
-			SearchMan.listMatchingMembers(files, file); // Search for CD.INF files
+			SearchMan.listMatchingMembers(files, Common::Path(file)); // Search for CD.INF files
 			for (Common::ArchiveMemberDetails &cdInfFile : files) {
 				Common::SeekableReadStream *stream = cdInfFile.arcMember->createReadStream();
 				while (stream->pos() + 4 <= stream->size()) {
@@ -1266,7 +1266,7 @@ void Inter_v7::o7_checkData(OpFuncParams &params) {
 		} else if (indexAppli >= 0 && (size_t) indexAppli <= installedApplications.size()) {
 			// Already installed appli, find its directory and set it as "current CD" path
 			int32 applicationNumber = installedApplications[indexAppli - 1];
-			Common::String appliVmdName = Common::String::format("appli_%02d.vmd", applicationNumber);
+			Common::Path appliVmdName(Common::String::format("appli_%02d.vmd", applicationNumber));
 			Common::ArchiveMemberDetailsList matchingFiles;
 			SearchMan.listMatchingMembers(matchingFiles, appliVmdName);
 			for (Common::ArchiveMemberDetails &matchingFile : matchingFiles) {
diff --git a/engines/gob/resources.cpp b/engines/gob/resources.cpp
index b7ce2efa3cb..0489ecbf2f8 100644
--- a/engines/gob/resources.cpp
+++ b/engines/gob/resources.cpp
@@ -586,7 +586,7 @@ byte *Resources::getTexts() const {
 }
 
 bool Resources::dumpResource(const Resource &resource,
-		const Common::String &fileName) const {
+		const Common::Path &fileName) const {
 
 	Common::DumpFile dump;
 
@@ -614,7 +614,7 @@ bool Resources::dumpResource(const Resource &resource, uint16 id,
 	fileName += ".";
 	fileName += ext;
 
-	return dumpResource(resource, fileName);
+	return dumpResource(resource, Common::Path(fileName));
 }
 
 Resource *Resources::getTOTResource(uint16 id) const {
diff --git a/engines/gob/resources.h b/engines/gob/resources.h
index 433b56d09a2..57b30fb9cd6 100644
--- a/engines/gob/resources.h
+++ b/engines/gob/resources.h
@@ -25,6 +25,7 @@
 #include "common/str.h"
 
 namespace Common {
+class Path;
 class SeekableReadStream;
 }
 
@@ -88,7 +89,7 @@ public:
 	byte *getTexts() const;
 
 	bool dumpResource(const Resource &resource,
-			const Common::String &fileName) const;
+			const Common::Path &fileName) const;
 	bool dumpResource(const Resource &resource, uint16 id,
 			const Common::String &ext = "dmp") const;
 


Commit: 43cf69c238bb11ea5e8703647e2b74edb73335af
    https://github.com/scummvm/scummvm/commit/43cf69c238bb11ea5e8703647e2b74edb73335af
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GRIFFON: Migrate engine to Path

Changed paths:
    engines/griffon/griffon.cpp


diff --git a/engines/griffon/griffon.cpp b/engines/griffon/griffon.cpp
index 750300cb4c7..7e4d18b64cb 100644
--- a/engines/griffon/griffon.cpp
+++ b/engines/griffon/griffon.cpp
@@ -52,7 +52,7 @@
 namespace Griffon {
 
 GriffonEngine::GriffonEngine(OSystem *syst) : Engine(syst) {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
 
 	_rnd = new Common::RandomSource("griffon");


Commit: 7627ae3b979f625defd1f7b1ce2b0f7c2e2be5b3
    https://github.com/scummvm/scummvm/commit/7627ae3b979f625defd1f7b1ce2b0f7c2e2be5b3
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GRIM: Migrate engine to Path

Changed paths:
    engines/grim/bitmap.cpp
    engines/grim/grim.cpp
    engines/grim/lab.cpp
    engines/grim/lab.h
    engines/grim/movie/bink.cpp
    engines/grim/movie/movie.cpp
    engines/grim/movie/mpeg.cpp
    engines/grim/movie/quicktime.cpp
    engines/grim/movie/smush.cpp
    engines/grim/patchr.cpp
    engines/grim/patchr.h
    engines/grim/registry.cpp
    engines/grim/resource.cpp
    engines/grim/resource.h
    engines/grim/update/lang_filter.cpp
    engines/grim/update/mscab.cpp
    engines/grim/update/mscab.h


diff --git a/engines/grim/bitmap.cpp b/engines/grim/bitmap.cpp
index b0470785004..cf7784def3d 100644
--- a/engines/grim/bitmap.cpp
+++ b/engines/grim/bitmap.cpp
@@ -378,7 +378,7 @@ Bitmap::Bitmap() {
 }
 
 Bitmap *Bitmap::create(const Common::String &filename) {
-	if (!SearchMan.hasFile(filename)) {
+	if (!SearchMan.hasFile(Common::Path(filename))) {
 		warning("Could not find bitmap %s", filename.c_str());
 		return nullptr;
 	}
diff --git a/engines/grim/grim.cpp b/engines/grim/grim.cpp
index a5b78d082b5..5aa5b9f386f 100644
--- a/engines/grim/grim.cpp
+++ b/engines/grim/grim.cpp
@@ -177,7 +177,7 @@ GrimEngine::GrimEngine(OSystem *syst, uint32 gameFlags, GrimGameType gameType, C
 	_blastTextDefaults.setFont(nullptr);
 	_blastTextDefaults.setJustify(TextObject::LJUSTIFY);
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "movies"); // Add 'movies' subdirectory for the demo
 	SearchMan.addSubDirectoryMatching(gameDataDir, "credits");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "widescreen");
@@ -1667,7 +1667,7 @@ void GrimEngine::pauseEngineIntern(bool pause) {
 }
 
 
-Graphics::Surface *loadPNG(const Common::String &filename) {
+Graphics::Surface *loadPNG(const Common::Path &filename) {
 	Image::PNGDecoder d;
 	Common::SeekableReadStream *s = SearchMan.createReadStreamForMember(filename);
 	if (!s)
diff --git a/engines/grim/lab.cpp b/engines/grim/lab.cpp
index 872e2daf889..c7645940124 100644
--- a/engines/grim/lab.cpp
+++ b/engines/grim/lab.cpp
@@ -28,7 +28,7 @@
 
 namespace Grim {
 
-LabEntry::LabEntry(const Common::String &name, uint32 offset, uint32 len, Lab *parent) :
+LabEntry::LabEntry(const Common::Path &name, uint32 offset, uint32 len, Lab *parent) :
 		_offset(offset), _len(len), _parent(parent), _name(name) {
 	_name.toLowercase();
 }
@@ -45,7 +45,7 @@ Lab::~Lab() {
 	delete _stream;
 }
 
-bool Lab::open(const Common::String &filename, bool keepStream) {
+bool Lab::open(const Common::Path &filename, bool keepStream) {
 	_labFileName = filename;
 
 	bool result = true;
@@ -93,10 +93,12 @@ void Lab::parseGrimFileTable(Common::File *file) {
 		fname.toLowercase();
 
 		if (start + size > filesize)
-			error("File \"%s\" past the end of lab \"%s\". Your game files may be corrupt.", fname.c_str(), _labFileName.c_str());
+			error("File \"%s\" past the end of lab \"%s\". Your game files may be corrupt.",
+					fname.c_str(), _labFileName.toString(Common::Path::kNativeSeparator).c_str());
 
-		LabEntry *entry = new LabEntry(fname, start, size, this);
-		_entries[fname] = LabEntryPtr(entry);
+		Common::Path path(fname, Common::Path::kNoSeparator);
+		LabEntry *entry = new LabEntry(path, start, size, this);
+		_entries[path] = LabEntryPtr(entry);
 	}
 
 	delete[] stringTable;
@@ -125,30 +127,24 @@ void Lab::parseMonkey4FileTable(Common::File *file) {
 		int size = file->readUint32LE();
 		file->readUint32LE();
 
-		char *str = stringTable + fnameOffset;
-		int len = strlen(str);
-
-		for (int l = 0; l < len; ++l) {
-			if (str[l] == '\\')
-				str[l] = '/';
-		}
-		Common::String fname = str;
+		Common::String fname = stringTable + fnameOffset;
+		fname.replace('\\', '/');
 		fname.toLowercase();
 
 		if (start + size > filesize)
-			error("File \"%s\" past the end of lab \"%s\". Your game files may be corrupt.", fname.c_str(), _labFileName.c_str());
+			error("File \"%s\" past the end of lab \"%s\". Your game files may be corrupt.",
+					fname.c_str(), _labFileName.toString(Common::Path::kNativeSeparator).c_str());
 
-		LabEntry *entry = new LabEntry(fname, start, size, this);
-		_entries[fname] = LabEntryPtr(entry);
+		Common::Path path(fname, '/');
+		LabEntry *entry = new LabEntry(path, start, size, this);
+		_entries[path] = LabEntryPtr(entry);
 	}
 
 	delete[] stringTable;
 }
 
-bool Lab::hasFile(const Common::Path &filename) const {
-	Common::String fname(filename.toString());
-	fname.toLowercase();
-	return _entries.contains(fname);
+bool Lab::hasFile(const Common::Path &path) const {
+	return _entries.contains(path);
 }
 
 int Lab::listMembers(Common::ArchiveMemberList &list) const {
@@ -163,23 +159,17 @@ int Lab::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr Lab::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!_entries.contains(path))
 		return Common::ArchiveMemberPtr();
 
-	Common::String fname(name);
-	fname.toLowercase();
-	return _entries[fname];
+	return _entries[path];
 }
 
 Common::SeekableReadStream *Lab::createReadStreamForMember(const Common::Path &path) const {
-	Common::String filename = path.toString();
-	if (!hasFile(filename))
+	if (!hasFile(path))
 		return nullptr;
 
-	Common::String fname(filename);
-	fname.toLowercase();
-	LabEntryPtr i = _entries[fname];
+	LabEntryPtr i = _entries[path];
 
 	if (!_stream) {
 		Common::File *file = new Common::File();
diff --git a/engines/grim/lab.h b/engines/grim/lab.h
index 621bba394d0..8b1a2e62f93 100644
--- a/engines/grim/lab.h
+++ b/engines/grim/lab.h
@@ -34,12 +34,12 @@ class Lab;
 
 class LabEntry : public Common::ArchiveMember {
 	Lab *_parent;
-	Common::String _name;
+	Common::Path _name;
 	uint32 _offset, _len;
 public:
-	LabEntry(const Common::String &name, uint32 offset, uint32 len, Lab *parent);
-	Common::String getName() const override { return _name; }
-	Common::String getFileName() const override { return _name; }
+	LabEntry(const Common::Path &name, uint32 offset, uint32 len, Lab *parent);
+	Common::String getName() const override { return _name.baseName(); }
+	Common::String getFileName() const override { return _name.baseName(); }
 	Common::Path getPathInArchive() const override { return _name; }
 	Common::SeekableReadStream *createReadStream() const override;
 	Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override { return nullptr; }
@@ -48,7 +48,7 @@ public:
 
 class Lab : public Common::Archive {
 public:
-	bool open(const Common::String &filename, bool keepStream = false);
+	bool open(const Common::Path &filename, bool keepStream = false);
 	Lab();
 	~Lab();
 	// Common::Archive implementation
@@ -61,9 +61,9 @@ private:
 	void parseGrimFileTable(Common::File *_f);
 	void parseMonkey4FileTable(Common::File *_f);
 
-	Common::String _labFileName;
+	Common::Path _labFileName;
 	typedef Common::SharedPtr<LabEntry> LabEntryPtr;
-	typedef Common::HashMap<Common::String, LabEntryPtr, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LabMap;
+	typedef Common::HashMap<Common::Path, LabEntryPtr, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> LabMap;
 	LabMap _entries;
 	Common::SeekableReadStream *_stream;
 };
diff --git a/engines/grim/movie/bink.cpp b/engines/grim/movie/bink.cpp
index 9279d8a1dec..8baed9b3a6c 100644
--- a/engines/grim/movie/bink.cpp
+++ b/engines/grim/movie/bink.cpp
@@ -104,7 +104,7 @@ bool BinkPlayer::loadFile(const Common::String &filename) {
 		bool ret = MoviePlayer::loadFile(_fname);
 
 		// Load subtitles from adjacent .sub file, if present
-		Common::SeekableReadStream *substream = SearchMan.createReadStreamForMember(subname);
+		Common::SeekableReadStream *substream = SearchMan.createReadStreamForMember(Common::Path(subname));
 		if (substream) {
 			TextSplitter tsSub("", substream);
 			while (!tsSub.isEof()) {
@@ -126,7 +126,7 @@ bool BinkPlayer::loadFile(const Common::String &filename) {
 
 	_fname += ".m4b";
 
-	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(_fname);
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(Common::Path(_fname));
 	if (!stream) {
 		warning("BinkPlayer::loadFile(): Can't create stream for: %s", _fname.c_str());
 		return false;
diff --git a/engines/grim/movie/movie.cpp b/engines/grim/movie/movie.cpp
index 05940602e61..d805092f13c 100644
--- a/engines/grim/movie/movie.cpp
+++ b/engines/grim/movie/movie.cpp
@@ -182,7 +182,7 @@ bool MoviePlayer::play(const Common::String &filename, bool looping, int x, int
 }
 
 bool MoviePlayer::loadFile(const Common::String &filename) {
-	return _videoDecoder->loadFile(filename);
+	return _videoDecoder->loadFile(Common::Path(filename));
 }
 
 void MoviePlayer::saveState(SaveGame *state) {
diff --git a/engines/grim/movie/mpeg.cpp b/engines/grim/movie/mpeg.cpp
index e6e3c05b806..8175b1a1f68 100644
--- a/engines/grim/movie/mpeg.cpp
+++ b/engines/grim/movie/mpeg.cpp
@@ -41,7 +41,7 @@ MpegPlayer::MpegPlayer() : MoviePlayer() {
 bool MpegPlayer::loadFile(const Common::String &filename) {
 	_fname = Common::String("Video/") + filename + ".pss";
 
-	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(_fname);
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(Common::Path(_fname));
 	if (!stream)
 		return false;
 
diff --git a/engines/grim/movie/quicktime.cpp b/engines/grim/movie/quicktime.cpp
index 17cf61aa236..695e9e98fcc 100644
--- a/engines/grim/movie/quicktime.cpp
+++ b/engines/grim/movie/quicktime.cpp
@@ -39,7 +39,7 @@ QuickTimePlayer::QuickTimePlayer() : MoviePlayer() {
 bool QuickTimePlayer::loadFile(const Common::String &filename) {
 	_fname = filename;
 
-	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(_fname);
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(Common::Path(_fname));
 	if (!stream)
 		return false;
 
diff --git a/engines/grim/movie/smush.cpp b/engines/grim/movie/smush.cpp
index 7007b95b5cf..a525f6caaab 100644
--- a/engines/grim/movie/smush.cpp
+++ b/engines/grim/movie/smush.cpp
@@ -56,14 +56,21 @@ bool SmushPlayer::loadFile(const Common::String &filename) {
 	if (!_demo)
 		success = _videoDecoder->loadStream(g_resourceloader->openNewStreamFile(filename.c_str()));
 	else
-		success = _videoDecoder->loadFile(filename);
+		success = _videoDecoder->loadFile(Common::Path(filename));
 
 	if (!success) {
 #if defined (USE_THEORADEC)
-		Common::String theoraFilename = "MoviesHD/" + filename;
-		theoraFilename.erase(theoraFilename.size() - 4);
-		theoraFilename += ".ogv";
-		debug(2, "Trying to open %s", theoraFilename.c_str());
+		Common::Path theoraFilename(filename);
+
+		Common::String baseName(theoraFilename.baseName());
+		baseName.erase(baseName.size() - 4);
+		baseName += ".ogv";
+
+		theoraFilename = "MoviesHD";
+		theoraFilename.join(theoraFilename.getParent());
+		theoraFilename.appendComponent(baseName);
+
+		debug(2, "Trying to open %s", theoraFilename.toString().c_str());
 		success = _theoraDecoder->loadFile(theoraFilename);
 		_videoDecoder = _theoraDecoder;
 		_currentVideoIsTheora = true;
diff --git a/engines/grim/patchr.cpp b/engines/grim/patchr.cpp
index 6153a6dd759..bb49425eb0f 100644
--- a/engines/grim/patchr.cpp
+++ b/engines/grim/patchr.cpp
@@ -35,7 +35,7 @@ public:
 	PatchedFile();
 	virtual ~PatchedFile();
 
-	bool load(Common::SeekableReadStream *file, const Common::String &patchName);
+	bool load(Common::SeekableReadStream *file, const Common::Path &patchName);
 
 	// Common::ReadStream implementation
 	bool eos() const override;
@@ -72,7 +72,7 @@ private:
 
 	uint8 *_diffBuffer;
 
-	Common::String _patchName;
+	Common::Path _patchName;
 };
 
 const uint16 PatchedFile::_kVersionMajor = 2;
@@ -99,7 +99,7 @@ PatchedFile::~PatchedFile() {
 		delete _extra;
 }
 
-bool PatchedFile::load(Common::SeekableReadStream *file, const Common::String &patchName) {
+bool PatchedFile::load(Common::SeekableReadStream *file, const Common::Path &patchName) {
 	uint8 md5_p[16], md5_f[16];
 	uint32 zctrllen, zdatalen, zextralen;
 	Common::File patch;
@@ -108,19 +108,19 @@ bool PatchedFile::load(Common::SeekableReadStream *file, const Common::String &p
 
 	// Open the patch
 	if (!patch.open(_patchName)) {
-		error("Unable to open patchfile %s", _patchName.c_str());
+		error("Unable to open patchfile %s", _patchName.toString().c_str());
 		return false;
 	}
 
 	// Check for appropriate signature
 	if (patch.readUint32BE() != MKTAG('P','A','T','R')) {
-		error("%s patchfile is corrupted, wrong siganture", _patchName.c_str());
+		error("%s patchfile is corrupted, wrong siganture", _patchName.toString().c_str());
 		return false;
 	}
 
 	// Check the version number
 	if (patch.readUint16LE() != _kVersionMajor || patch.readUint16LE() > _kVersionMinor) {
-		error("%s has a wrong version number (must be major = %d, minor <= %d)", _patchName.c_str(), _kVersionMajor, _kVersionMinor);
+		error("%s has a wrong version number (must be major = %d, minor <= %d)", _patchName.toString().c_str(), _kVersionMajor, _kVersionMinor);
 		return false;
 	}
 
@@ -132,7 +132,7 @@ bool PatchedFile::load(Common::SeekableReadStream *file, const Common::String &p
 	patch.read(md5_p, 16);
 	uint32 fileSize = patch.readUint32LE();
 	if (memcmp(md5_p, md5_f, 16) != 0 || (uint32)file->size() != fileSize) {
-		Debug::debug(Debug::Patchr, "%s targets a different file", _patchName.c_str());
+		Debug::debug(Debug::Patchr, "%s targets a different file", _patchName.toString().c_str());
 		if (Debug::isChannelEnabled(Debug::Patchr)) {
 			Common::String md5_ps, md5_fs;
 			for (int i = 0; i < 16; i++) {
@@ -163,7 +163,7 @@ bool PatchedFile::load(Common::SeekableReadStream *file, const Common::String &p
 
 	//ctrl stream sanity checks
 	if (_ctrl->size() % (3 * sizeof(uint32)) != 0) {
-		error("%s patchfile is corrupted", _patchName.c_str());
+		error("%s patchfile is corrupted", _patchName.toString().c_str());
 		return false;
 	}
 
@@ -201,7 +201,7 @@ uint32 PatchedFile::read(void *dataPtr, uint32 dataSize) {
 			readSize = MIN(toRead, _diffCopy);
 			rd = _file->read(data, readSize);
 			if (_file->err() || rd != readSize)
-				error("%s: Corrupted patchfile", _patchName.c_str());
+				error("%s: Corrupted patchfile", _patchName.toString().c_str());
 
 			toRead -= readSize;
 			_diffCopy -= readSize;
@@ -212,7 +212,7 @@ uint32 PatchedFile::read(void *dataPtr, uint32 dataSize) {
 				diffRead = MIN(readSize, _kDiffBufferSize);
 				rd = _diff->read(_diffBuffer, diffRead);
 				if (_diff->err() || rd != diffRead)
-					error("%s: Corrupted patchfile", _patchName.c_str());
+					error("%s: Corrupted patchfile", _patchName.toString().c_str());
 
 				for (uint32 i = 0; i < diffRead / 4; ++i)
 					WRITE_UINT32((uint32 *)data + i, READ_UINT32((uint32 *)data + i) ^ READ_UINT32((uint32 *)_diffBuffer + i));
@@ -232,7 +232,7 @@ uint32 PatchedFile::read(void *dataPtr, uint32 dataSize) {
 			readSize = MIN(toRead, _extraCopy);
 			rd = _extra->read(data, readSize);
 			if (_extra->err() || rd != readSize)
-				error("%s: Corrupted patchfile", _patchName.c_str());
+				error("%s: Corrupted patchfile", _patchName.toString().c_str());
 
 			data += readSize;
 			toRead -= readSize;
@@ -272,7 +272,7 @@ bool PatchedFile::readNextInst() {
 	    (int32(_diffCopy) > _diff->size() - _diff->pos()) ||
 	    (int32(_extraCopy) > _extra->size() - _extra->pos()) ||
 	    (_jump > _file->size() - _file->pos())) {
-		error("%s: Corrupted patchfile. istrleft = %d", _patchName.c_str(), _instrLeft);
+		error("%s: Corrupted patchfile. istrleft = %d", _patchName.toString().c_str(), _instrLeft);
 	}
 
 	--_instrLeft;
@@ -313,14 +313,14 @@ bool PatchedFile::seek(int64 offset, int whence) {
 			relOffset = (size() + offset) - pos();
 			break;
 		default:
-			error("%s: Invalid seek instruction", _patchName.c_str());
+			error("%s: Invalid seek instruction", _patchName.toString().c_str());
 	}
 
 	if (relOffset == 0)
 		return true;
 
 	if (relOffset < 0) {
-		Debug::debug(Debug::Patchr, "Seeking back to start %s", _patchName.c_str());
+		Debug::debug(Debug::Patchr, "Seeking back to start %s", _patchName.toString().c_str());
 		_file->seek(0, SEEK_SET);
 		_ctrl->seek(0, SEEK_SET);
 		_extra->seek(0, SEEK_SET);
@@ -361,24 +361,24 @@ bool PatchedFile::seek(int64 offset, int whence) {
 	return true;
 }
 
-Common::SeekableReadStream *wrapPatchedFile(Common::SeekableReadStream *rs, const Common::String &filename) {
+Common::SeekableReadStream *wrapPatchedFile(Common::SeekableReadStream *rs, const Common::Path &filename) {
 	if (!rs)
 		return nullptr;
 
-	Common::String patchfile = filename + ".patchr";
+	Common::Path patchfile = filename.append(".patchr");
 	int i = 1;
 	while (SearchMan.hasFile(patchfile)) {
-		Debug::debug(Debug::Patchr, "Patch requested for %s (patch filename %s)", filename.c_str(), patchfile.c_str());
+		Debug::debug(Debug::Patchr, "Patch requested for %s (patch filename %s)", filename.toString().c_str(), patchfile.toString().c_str());
 
 		PatchedFile *pf = new PatchedFile;
 		if (pf->load(rs, patchfile)) {
 			rs = Common::wrapBufferedSeekableReadStream(pf, 1024, DisposeAfterUse::YES);
-			Debug::debug(Debug::Patchr, "Patch for %s successfully loaded", filename.c_str());
+			Debug::debug(Debug::Patchr, "Patch for %s successfully loaded", filename.toString().c_str());
 			break;
 		}
 
 		delete pf;
-		patchfile = Common::String::format("%s_%d.patchr", filename.c_str(), i++);
+		patchfile = filename.append(Common::String::format("_%d.patchr", i++));
 	}
 
 	return rs;
diff --git a/engines/grim/patchr.h b/engines/grim/patchr.h
index 94e6dbac165..ff5cbe86c45 100644
--- a/engines/grim/patchr.h
+++ b/engines/grim/patchr.h
@@ -35,7 +35,7 @@ namespace Grim {
  * It is safe to call this with a NULL parameter (in this case, NULL is
  * returned).
  */
-Common::SeekableReadStream *wrapPatchedFile(Common::SeekableReadStream *rs, const Common::String &filename);
+Common::SeekableReadStream *wrapPatchedFile(Common::SeekableReadStream *rs, const Common::Path &filename);
 
 } // end of namespace Grim
 
diff --git a/engines/grim/registry.cpp b/engines/grim/registry.cpp
index 171e5864ed9..69aecb83d56 100644
--- a/engines/grim/registry.cpp
+++ b/engines/grim/registry.cpp
@@ -105,8 +105,8 @@ Registry::Registry() :
 
 	// Read settings
 	_spewOnError.setString(ConfMan.get("spew_on_error"));
-	_dataPath.setString(ConfMan.get("path"));
-	_savePath.setString(ConfMan.get("savepath"));
+	_dataPath.setString(ConfMan.getPath("path").toString(Common::Path::kNativeSeparator));
+	_savePath.setString(ConfMan.getPath("savepath").toString(Common::Path::kNativeSeparator));
 	_develMode.setBool(ConfMan.getBool("game_devel_mode"));
 	_lastSet.setString(ConfMan.get("last_set"));
 	_musicVolume.setInt(convertVolumeFromMixer(ConfMan.getInt("music_volume")));
@@ -293,8 +293,8 @@ void Registry::save() {
 		return;
 
 	ConfMan.set("spew_on_error", _spewOnError.getString());
-	ConfMan.set("path", _dataPath.getString());
-	ConfMan.set("savepath", _savePath.getString());
+	ConfMan.setPath("path", Common::Path(_dataPath.getString(), Common::Path::kNativeSeparator));
+	ConfMan.setPath("savepath", Common::Path(_savePath.getString(), Common::Path::kNativeSeparator));
 	if (ConfMan.hasKey("last_set")) {
 		ConfMan.set("last_set", _lastSet.getString());
 	}
diff --git a/engines/grim/resource.cpp b/engines/grim/resource.cpp
index 29eb6e9937c..3fe51625f63 100644
--- a/engines/grim/resource.cpp
+++ b/engines/grim/resource.cpp
@@ -211,7 +211,7 @@ ResourceLoader::ResourceLoader() {
 		// we _COULD_ protect this with a platform check, but the file isn't
 		// really big anyhow...
 		bool useCache = (filename == "local.m4b");
-		if (l->open(filename, useCache))
+		if (l->open((*x)->getPathInArchive(), useCache))
 			SearchMan.add(filename, l, priority--, true);
 		else
 			delete l;
@@ -246,7 +246,7 @@ static int sortCallback(const void *entry1, const void *entry2) {
 	return scumm_stricmp(((const ResourceLoader::ResourceCache *)entry1)->fname, ((const ResourceLoader::ResourceCache *)entry2)->fname);
 }
 
-Common::SeekableReadStream *ResourceLoader::getFileFromCache(const Common::String &filename) const {
+Common::SeekableReadStream *ResourceLoader::getFileFromCache(const Common::Path &filename) const {
 	ResourceLoader::ResourceCache *entry = getEntryFromCache(filename);
 	if (!entry)
 		return nullptr;
@@ -254,7 +254,7 @@ Common::SeekableReadStream *ResourceLoader::getFileFromCache(const Common::Strin
 	return new Common::MemoryReadStream(entry->resPtr, entry->len);
 }
 
-ResourceLoader::ResourceCache *ResourceLoader::getEntryFromCache(const Common::String &filename) const {
+ResourceLoader::ResourceCache *ResourceLoader::getEntryFromCache(const Common::Path &filename) const {
 	if (_cache.empty())
 		return nullptr;
 
@@ -263,13 +263,15 @@ ResourceLoader::ResourceCache *ResourceLoader::getEntryFromCache(const Common::S
 		_cacheDirty = false;
 	}
 
+	Common::String sFilename(filename.toString('/'));
+
 	ResourceCache key;
-	key.fname = const_cast<char *>(filename.c_str());
+	key.fname = const_cast<char *>(sFilename.c_str());
 
 	return (ResourceLoader::ResourceCache *)bsearch(&key, _cache.begin(), _cache.size(), sizeof(ResourceCache), sortCallback);
 }
 
-Common::SeekableReadStream *ResourceLoader::loadFile(const Common::String &filename) const {
+Common::SeekableReadStream *ResourceLoader::loadFile(const Common::Path &filename) const {
 	Common::SeekableReadStream *rs = nullptr;
 	if (SearchMan.hasFile(filename))
 		rs = SearchMan.createReadStreamForMember(filename);
@@ -280,37 +282,40 @@ Common::SeekableReadStream *ResourceLoader::loadFile(const Common::String &filen
 	return rs;
 }
 
-Common::SeekableReadStream *ResourceLoader::openNewStreamFile(Common::String fname, bool cache) const {
+Common::SeekableReadStream *ResourceLoader::openNewStreamFile(const Common::String &fname, bool cache) const {
 	Common::SeekableReadStream *s;
-	fname.toLowercase();
+	Common::Path path(fname, '/');
+	path.toLowercase();
 
 	if (cache) {
-		s = getFileFromCache(fname);
+		s = getFileFromCache(path);
 		if (!s) {
-			s = loadFile(fname);
+			s = loadFile(path);
 			if (!s)
 				return nullptr;
 
 			uint32 size = s->size();
 			byte *buf = new byte[size];
 			s->read(buf, size);
-			putIntoCache(fname, buf, size);
+			putIntoCache(path, buf, size);
 			delete s;
 			s = new Common::MemoryReadStream(buf, size);
 		}
 	} else {
-		s = loadFile(fname);
+		s = loadFile(path);
 	}
 	// This will only have an effect if the stream is actually compressed.
 	return Common::wrapCompressedReadStream(s);
 }
 
-void ResourceLoader::putIntoCache(const Common::String &fname, byte *res, uint32 len) const {
+void ResourceLoader::putIntoCache(const Common::Path &fname, byte *res, uint32 len) const {
+	Common::String sFilename(fname.toString('/'));
+
 	ResourceCache entry;
 	entry.resPtr = res;
 	entry.len = len;
-	entry.fname = new char[fname.size() + 1];
-	Common::strcpy_s(entry.fname, fname.size() + 1, fname.c_str());
+	entry.fname = new char[sFilename.size() + 1];
+	Common::strcpy_s(entry.fname, sFilename.size() + 1, sFilename.c_str());
 	_cacheMemorySize += len;
 	_cache.push_back(entry);
 	_cacheDirty = true;
@@ -594,9 +599,10 @@ Overlay *ResourceLoader::loadOverlay(const Common::String &filename) {
 	return result;
 }
 
-void ResourceLoader::uncache(const char *filename) const {
-	Common::String fname = filename;
-	fname.toLowercase();
+void ResourceLoader::uncache(const Common::Path &filename) const {
+	Common::Path lower(filename);
+	lower.toLowercase();
+	Common::String fname(lower.toString('/'));
 
 	if (_cacheDirty) {
 		qsort(_cache.begin(), _cache.size(), sizeof(ResourceCache), sortCallback);
@@ -604,7 +610,7 @@ void ResourceLoader::uncache(const char *filename) const {
 	}
 
 	for (unsigned int i = 0; i < _cache.size(); i++) {
-		if (fname.compareTo(_cache[i].fname) == 0) {
+		if (fname.equals(_cache[i].fname)) {
 			delete[] _cache[i].fname;
 			_cacheMemorySize -= _cache[i].len;
 			delete[] _cache[i].resPtr;
diff --git a/engines/grim/resource.h b/engines/grim/resource.h
index 44a3c69b06c..857e024ad7e 100644
--- a/engines/grim/resource.h
+++ b/engines/grim/resource.h
@@ -72,7 +72,7 @@ public:
 	Sprite *loadSprite(const Common::String &fname, EMICostume *costume);
 	AnimationEmi *loadAnimationEmi(const Common::String &filename);
 	Overlay *loadOverlay(const Common::String &filename);
-	Common::SeekableReadStream *openNewStreamFile(Common::String fname, bool cache = false) const;
+	Common::SeekableReadStream *openNewStreamFile(const Common::String &fname, bool cache = false) const;
 
 	ModelPtr getModel(const Common::String &fname, CMap *c);
 	CMapPtr getColormap(const Common::String &fname);
@@ -94,11 +94,11 @@ public:
 	static Common::String fixFilename(const Common::String &filename, bool append = true);
 
 private:
-	Common::SeekableReadStream *loadFile(const Common::String &filename) const;
-	Common::SeekableReadStream *getFileFromCache(const Common::String &filename) const;
-	ResourceLoader::ResourceCache *getEntryFromCache(const Common::String &filename) const;
-	void putIntoCache(const Common::String &fname, byte *res, uint32 len) const;
-	void uncache(const char *fname) const;
+	Common::SeekableReadStream *loadFile(const Common::Path &filename) const;
+	Common::SeekableReadStream *getFileFromCache(const Common::Path &filename) const;
+	ResourceLoader::ResourceCache *getEntryFromCache(const Common::Path &filename) const;
+	void putIntoCache(const Common::Path &fname, byte *res, uint32 len) const;
+	void uncache(const Common::Path &fname) const;
 
 	mutable Common::Array<ResourceCache> _cache;
 	mutable bool _cacheDirty;
diff --git a/engines/grim/update/lang_filter.cpp b/engines/grim/update/lang_filter.cpp
index c02cc3973d3..a386178171c 100644
--- a/engines/grim/update/lang_filter.cpp
+++ b/engines/grim/update/lang_filter.cpp
@@ -66,14 +66,13 @@ LangFilter::~LangFilter() {
 }
 
 bool LangFilter::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	if (!_arc)
 		return false;
 
-	return (_arc->hasFile(kLanguages1[_lang] + name)) ||
-			(_arc->hasFile(kLanguages1[kCommon] + name)) ||
-			(_arc->hasFile(kLanguages2[_lang] + name)) ||
-			(_arc->hasFile(kLanguages2[kCommon] + name));
+	return (_arc->hasFile(Common::Path(kLanguages1[_lang]).appendInPlace(path))) ||
+			(_arc->hasFile(Common::Path(kLanguages1[kCommon]).appendInPlace(path))) ||
+			(_arc->hasFile(Common::Path(kLanguages2[_lang]).appendInPlace(path))) ||
+			(_arc->hasFile(Common::Path(kLanguages2[kCommon]).appendInPlace(path)));
 }
 
 int LangFilter::listMembers(Common::ArchiveMemberList &list) const {
@@ -102,7 +101,7 @@ int LangFilter::listMembers(Common::ArchiveMemberList &list) const {
 		} else
 			continue;
 		name.toLowercase();
-		list.push_back(getMember(name));
+		list.push_back(getMember(Common::Path(name)));
 		++num;
 	}
 
@@ -114,18 +113,17 @@ const Common::ArchiveMemberPtr LangFilter::getMember(const Common::Path &path) c
 }
 
 Common::SeekableReadStream *LangFilter::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	if (!_arc)
 		return nullptr;
 
 	// Search the right file
-	Common::String fullName;
-	Common::List<Common::String> namesToTry;
-	namesToTry.push_front(kLanguages1[_lang] + name);
-	namesToTry.push_front(kLanguages1[kCommon] + name);
-	namesToTry.push_front(kLanguages2[_lang] + name);
-	namesToTry.push_front(kLanguages2[kCommon] + name);
-	for (Common::List<Common::String>::const_iterator it = namesToTry.begin(); it != namesToTry.end(); ++it)
+	Common::Path fullName;
+	Common::List<Common::Path> pathsToTry;
+	pathsToTry.push_front(Common::Path(kLanguages1[_lang]).appendInPlace(path));
+	pathsToTry.push_front(Common::Path(kLanguages1[kCommon]).appendInPlace(path));
+	pathsToTry.push_front(Common::Path(kLanguages2[_lang]).appendInPlace(path));
+	pathsToTry.push_front(Common::Path(kLanguages2[kCommon]).appendInPlace(path));
+	for (Common::List<Common::Path>::const_iterator it = pathsToTry.begin(); it != pathsToTry.end(); ++it)
 		if (_arc->hasFile(*it)) {
 			fullName = *it;
 			break;
diff --git a/engines/grim/update/mscab.cpp b/engines/grim/update/mscab.cpp
index 0d6b521bd39..87aa26f395f 100644
--- a/engines/grim/update/mscab.cpp
+++ b/engines/grim/update/mscab.cpp
@@ -128,7 +128,7 @@ MsCabinet::MsCabinet(Common::SeekableReadStream *data) :
 			return;
 		}
 
-		_fileMap[name] = fEntry;
+		_fileMap[Common::Path(name, '/')] = fEntry;
 	}
 }
 
@@ -146,8 +146,7 @@ Common::String MsCabinet::readString(Common::ReadStream *stream) {
 }
 
 bool MsCabinet::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return _fileMap.contains(name);
+	return _fileMap.contains(path);
 }
 
 int MsCabinet::listMembers(Common::ArchiveMemberList &list) const {
@@ -158,23 +157,21 @@ int MsCabinet::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr MsCabinet::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *MsCabinet::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	byte *fileBuf;
 
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return nullptr;
 
-	const FileEntry &entry = _fileMap[name];
+	const FileEntry &entry = _fileMap[path];
 
 	// Check if the file has already been decompressed and it's in the cache,
 	// otherwise decompress it and put it in the cache
-	if (_cache.contains(name))
-		fileBuf = _cache[name];
+	if (_cache.contains(path))
+		fileBuf = _cache[path];
 	else {
 		// Check if the decompressor should be reinitialized
 		if (!_decompressor || entry.folder != _decompressor->getFolder()) {
@@ -186,7 +183,7 @@ Common::SeekableReadStream *MsCabinet::createReadStreamForMember(const Common::P
 		if (!_decompressor->decompressFile(fileBuf, entry))
 			return nullptr;
 
-		_cache[name] = fileBuf;
+		_cache[path] = fileBuf;
 	}
 
 	return new Common::MemoryReadStream(fileBuf, entry.length, DisposeAfterUse::NO);
diff --git a/engines/grim/update/mscab.h b/engines/grim/update/mscab.h
index e3ecfc8fe78..a4691a71740 100644
--- a/engines/grim/update/mscab.h
+++ b/engines/grim/update/mscab.h
@@ -57,7 +57,7 @@ private:
 		uint32 folderOffset;        // Uncompressed offset in the folder
 	};
 
-	typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, FileEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _fileMap;
 
 	typedef Common::HashMap<uint16, FolderEntry> FolderMap;
@@ -94,7 +94,7 @@ private:
 	mutable Decompressor *_decompressor;
 
 	// Cache
-	typedef Common::HashMap<Common::String, byte *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CacheMap;
+	typedef Common::HashMap<Common::Path, byte *, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> CacheMap;
 	mutable CacheMap _cache;
 };
 


Commit: cef464ac9329f72ce14a22da53f8709439604387
    https://github.com/scummvm/scummvm/commit/cef464ac9329f72ce14a22da53f8709439604387
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GROOVIE: Migrate engine to Path

Changed paths:
    engines/groovie/groovie.cpp
    engines/groovie/music.cpp
    engines/groovie/resource.cpp
    engines/groovie/resource.h
    engines/groovie/script.cpp
    engines/groovie/video/roq.cpp


diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index f9688ce2b9b..cec1907acbd 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -56,7 +56,7 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) :
 	_spookyMode(false) {
 
 	// Adding the default directories
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "groovie");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "media");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "system");
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index abb72bc3797..8f62ff892ed 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -439,11 +439,11 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
 	// 11th Hour uses SAMPLE.AD/SAMPLE.OPL/SAMPLE.MT
 	switch (musicType) {
 	case MT_ADLIB:
-		_driver = _multisourceDriver = Audio::MidiDriver_Miles_AdLib_create(gtlName + ".AD", gtlName + ".OPL");
+		_driver = _multisourceDriver = Audio::MidiDriver_Miles_AdLib_create(Common::Path(gtlName + ".AD"), Common::Path(gtlName + ".OPL"));
 		break;
 	case MT_MT32:
 		Audio::MidiDriver_Miles_Midi *milesDriver;
-		milesDriver = Audio::MidiDriver_Miles_MIDI_create(musicType, gtlName + ".MT");
+		milesDriver = Audio::MidiDriver_Miles_MIDI_create(musicType, Common::Path(gtlName + ".MT"));
 		_milesXmidiTimbres = milesDriver;
 		_driver = _multisourceDriver = milesDriver;
 		break;
@@ -668,7 +668,7 @@ bool MusicPlayerMac_v2::load(uint32 fileref, bool loop) {
 	info.filename.deleteLastChar();
 	info.filename += "mov";
 
-	Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(info.filename);
+	Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(Common::Path(info.filename));
 
 	if (!file) {
 		warning("Could not find file '%s'", info.filename.c_str());
@@ -753,7 +753,7 @@ bool MusicPlayerIOS::load(uint32 fileref, bool loop) {
 	}
 
 	// Create the audio stream
-	Audio::SeekableAudioStream *seekStream = Audio::SeekableAudioStream::openStreamFile(info.filename);
+	Audio::SeekableAudioStream *seekStream = Audio::SeekableAudioStream::openStreamFile(Common::Path(info.filename));
 
 	if (!seekStream) {
 		warning("Could not play audio file '%s'", info.filename.c_str());
@@ -820,7 +820,7 @@ bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
 		filename += ".mpg";
 
 	// Create the audio stream from fileref
-	_file->open(filename);
+	_file->open(Common::Path(filename));
 	Audio::SeekableAudioStream *seekStream = nullptr;
 	if (_file->isOpen()) {
 		if (filename.hasSuffix(".m4a"))
diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index 6c3f15b5937..11723582b16 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -52,19 +52,19 @@ Common::SeekableReadStream *ResMan::open(const ResInfo &resInfo) {
 		return nullptr;
 	}
 
-	debugC(1, kDebugResource, "Groovie::Resource: Opening resource (%s, %d, %d, %d)", _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size, resInfo.disks);
+	debugC(1, kDebugResource, "Groovie::Resource: Opening resource (%s, %d, %d, %d)", _gjds[resInfo.gjd].toString().c_str(), resInfo.offset, resInfo.size, resInfo.disks);
 
 	// Does it exist?
 	if (!Common::File::exists(_gjds[resInfo.gjd])) {
-		error("Groovie::Resource: %s not found (resInfo.disks: %d)", _gjds[resInfo.gjd].c_str(), resInfo.disks);
+		error("Groovie::Resource: %s not found (resInfo.disks: %d)", _gjds[resInfo.gjd].toString().c_str(), resInfo.disks);
 		return nullptr;
 	}
 
 	// Open the pack file
 	Common::File *gjdFile = new Common::File();
-	if (!gjdFile->open(_gjds[resInfo.gjd].c_str())) {
+	if (!gjdFile->open(_gjds[resInfo.gjd])) {
 		delete gjdFile;
-		error("Groovie::Resource: Couldn't open %s", _gjds[resInfo.gjd].c_str());
+		error("Groovie::Resource: Couldn't open %s", _gjds[resInfo.gjd].toString().c_str());
 		return nullptr;
 	}
 
@@ -76,7 +76,7 @@ Common::SeekableReadStream *ResMan::open(const ResInfo &resInfo) {
 	// Returning the resource substream
 	Common::SeekableSubReadStream *file = new Common::SeekableSubReadStream(gjdFile, resInfo.offset, resInfo.offset + resInfo.size, DisposeAfterUse::YES);
 	if (ConfMan.getBool("dump_resources")) {
-		dumpResource(file, resInfo.filename, false);
+		dumpResource(file, Common::Path(resInfo.filename), false);
 	}
 	return file;
 }
@@ -86,20 +86,20 @@ Common::String ResMan::getGjdName(const ResInfo &resInfo) {
 		error("Groovie::Resource: Unknown GJD %d", resInfo.gjd);
 	}
 
-	return _gjds[resInfo.gjd];
+	return _gjds[resInfo.gjd].baseName();
 }
 
 void ResMan::dumpResource(const Common::String &fileName) {
 	uint32 fileRef = getRef(fileName);
-	dumpResource(fileRef, fileName);
+	dumpResource(fileRef, Common::Path(fileName));
 }
 
-void ResMan::dumpResource(uint32 fileRef, const Common::String &fileName) {
+void ResMan::dumpResource(uint32 fileRef, const Common::Path &fileName) {
 	Common::SeekableReadStream *inFile = open(fileRef);
 	dumpResource(inFile, fileName);
 }
 
-void ResMan::dumpResource(Common::SeekableReadStream *inFile, const Common::String &fileName, bool dispose) {
+void ResMan::dumpResource(Common::SeekableReadStream *inFile, const Common::Path &fileName, bool dispose) {
 	Common::DumpFile outFile;
 	outFile.open(fileName);
 
@@ -135,7 +135,7 @@ ResMan_t7g::ResMan_t7g(Common::MacResManager *macResFork) : _macResFork(macResFo
 			filename = "T7GData";
 
 		// Append it to the list of GJD files
-		_gjds.push_back(filename);
+		_gjds.push_back(Common::Path(filename));
 	}
 }
 
@@ -151,7 +151,7 @@ uint32 ResMan_t7g::getRef(Common::String name) {
 		rlFile = _macResFork->getResource(rlFileName);
 	} else {
 		// Open the RL file
-		rlFile = SearchMan.createReadStreamForMember(rlFileName);
+		rlFile = SearchMan.createReadStreamForMember(Common::Path(rlFileName));
 	}
 
 	if (!rlFile)
@@ -203,7 +203,7 @@ bool ResMan_t7g::getResInfo(uint32 fileRef, ResInfo &resInfo) {
 		rlFile = _macResFork->getResource(rlFileName);
 	} else {
 		// Open the RL file
-		rlFile = SearchMan.createReadStreamForMember(rlFileName);
+		rlFile = SearchMan.createReadStreamForMember(Common::Path(rlFileName));
 	}
 
 	if (!rlFile)
@@ -255,7 +255,7 @@ ResMan_v2::ResMan_v2() {
 
 		// Append it to the list of GJD files
 		if (!filename.empty()) {
-			_gjds.push_back(filename);
+			_gjds.push_back(Common::Path(filename));
 		}
 
 		// Read the next line
diff --git a/engines/groovie/resource.h b/engines/groovie/resource.h
index 2977ed8488a..53d6fdc04ea 100644
--- a/engines/groovie/resource.h
+++ b/engines/groovie/resource.h
@@ -44,15 +44,15 @@ public:
 	Common::SeekableReadStream *open(const ResInfo &resInfo);
 
 	void dumpResource(const Common::String &fileName);
-	void dumpResource(uint32 fileRef, const Common::String &fileName);
-	void dumpResource(Common::SeekableReadStream *inFile, const Common::String &fileName, bool dispose = true);
+	void dumpResource(uint32 fileRef, const Common::Path &fileName);
+	void dumpResource(Common::SeekableReadStream *inFile, const Common::Path &fileName, bool dispose = true);
 
 	Common::String getGjdName(const ResInfo &resInfo);
 	virtual uint32 getRef(Common::String name) = 0;
 	virtual bool getResInfo(uint32 fileRef, ResInfo &resInfo) = 0;
 
 protected:
-	Common::Array<Common::String> _gjds;
+	Common::Array<Common::Path> _gjds;
 
 	uint16 _lastGjd;
 };
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 2b0d9fbd5cb..faab6f77544 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -166,7 +166,7 @@ bool Script::loadScript(Common::String filename) {
 		scriptfile = _vm->_macResFork->getResource(filename);
 	} else {
 		// Try to open the script file
-		scriptfile = SearchMan.createReadStreamForMember(filename);
+		scriptfile = SearchMan.createReadStreamForMember(Common::Path(filename));
 	}
 
 	if (!scriptfile)
diff --git a/engines/groovie/video/roq.cpp b/engines/groovie/video/roq.cpp
index 362b9cd8588..de4ff442aa2 100644
--- a/engines/groovie/video/roq.cpp
+++ b/engines/groovie/video/roq.cpp
@@ -294,7 +294,7 @@ void writeImage(const Common::String filename, Graphics::Surface &surface) {
 #endif
 
 	Common::DumpFile out;
-	if (!out.open(tname)) {
+	if (!out.open(Common::Path(tname))) {
 		warning("failed to write debug image to %s", tname.c_str());
 		return;
 	}


Commit: 09803f7a269b38132a293e8d84795cacf7670d86
    https://github.com/scummvm/scummvm/commit/09803f7a269b38132a293e8d84795cacf7670d86
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
HADESCH: Migrate engine to Path

Changed paths:
    engines/hadesch/hadesch.cpp
    engines/hadesch/pod_file.cpp
    engines/hadesch/pod_file.h
    engines/hadesch/video.cpp


diff --git a/engines/hadesch/hadesch.cpp b/engines/hadesch/hadesch.cpp
index d3133398be1..70df204b4f3 100644
--- a/engines/hadesch/hadesch.cpp
+++ b/engines/hadesch/hadesch.cpp
@@ -478,7 +478,7 @@ Common::Error HadeschEngine::run() {
 	_transMan->setLanguage(TransMan.getCurrentLanguage());
 #endif
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "WIN9x");
 
 	Common::ErrorCode err = loadCursors();
@@ -514,7 +514,7 @@ Common::Error HadeschEngine::run() {
 	// on cdScenePath
 	const char *const scenepaths[] = {"CDAssets/", "Scenes/"};
 	for (uint i = 0; i < ARRAYSIZE(scenepaths); ++i) {
-		Common::ScopedPtr<Common::SeekableReadStream> stream(Common::MacResManager::openFileOrDataFork(Common::String(scenepaths[i]) + "OLYMPUS/OL.POD"));
+		Common::ScopedPtr<Common::SeekableReadStream> stream(Common::MacResManager::openFileOrDataFork(Common::Path(scenepaths[i]).appendInPlace("OLYMPUS/OL.POD")));
 		if (stream) {
 			_cdScenesPath = scenepaths[i];
 			break;
diff --git a/engines/hadesch/pod_file.cpp b/engines/hadesch/pod_file.cpp
index c9f19302646..c1c67313190 100644
--- a/engines/hadesch/pod_file.cpp
+++ b/engines/hadesch/pod_file.cpp
@@ -75,7 +75,7 @@ bool PodFile::openStore(const Common::SharedPtr<Common::SeekableReadStream> &par
 	return true;
 }
 
-bool PodFile::openStore(const Common::String &name) {
+bool PodFile::openStore(const Common::Path &name) {
   	if (name.empty()) {
 		return false;
 	}
diff --git a/engines/hadesch/pod_file.h b/engines/hadesch/pod_file.h
index 14e4e89e526..7dae85fdc94 100644
--- a/engines/hadesch/pod_file.h
+++ b/engines/hadesch/pod_file.h
@@ -28,6 +28,7 @@
 
 namespace Common {
 	class File;
+	class Path;
 	class SeekableReadStream;
 }
 
@@ -40,7 +41,7 @@ Common::SeekableReadStream *memSubstream(Common::SharedPtr<Common::SeekableReadS
 class PodFile {
 public:
 	PodFile(const Common::String &debugName);
-	bool openStore(const Common::String &name);
+	bool openStore(const Common::Path &name);
 	bool openStore(const Common::SharedPtr<Common::SeekableReadStream> &parentstream);
 
 	Common::SeekableReadStream *getFileStream(const Common::String &name) const;
diff --git a/engines/hadesch/video.cpp b/engines/hadesch/video.cpp
index 0b04f781fea..2bbb5fa3aef 100644
--- a/engines/hadesch/video.cpp
+++ b/engines/hadesch/video.cpp
@@ -119,7 +119,7 @@ VideoRoom::VideoRoom(const Common::String &dir, const Common::String &pod,
 		     const Common::String &assetMapFile) : _layers(layerComparator) {
 	Common::String podPath = g_vm->getCDScenesPath() + dir + "/" + pod + ".pod";
 	_podFile = Common::SharedPtr<PodFile>(new PodFile(podPath));
-	_podFile->openStore(podPath);
+	_podFile->openStore(Common::Path(podPath));
 	_smkPath = g_vm->getCDScenesPath() + dir;
 	Common::SharedPtr<Common::SeekableReadStream> assetMapStream(assetMapFile != "" ? openFile(assetMapFile) : nullptr);
 	if (assetMapStream) {
@@ -762,7 +762,7 @@ void VideoRoom::playVideo(const Common::String &name, int zValue,
 	if (mappedName == "") {
 		mappedName = name;
 	}
-	Common::SeekableReadStream *stream = Common::MacResManager::openFileOrDataFork(_smkPath + "/" + mappedName + ".SMK");
+	Common::SeekableReadStream *stream = Common::MacResManager::openFileOrDataFork(Common::Path(_smkPath + "/" + mappedName + ".SMK"));
 
 	if (!stream || !decoder->loadStream(stream)) {
 		debug("Video file %s can't be opened", name.c_str());


Commit: d7c749864b0be6c605e7ae9a0863c33737acf5b7
    https://github.com/scummvm/scummvm/commit/d7c749864b0be6c605e7ae9a0863c33737acf5b7
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
HDB: Migrate engine to Path

Changed paths:
    engines/hdb/file-manager.cpp
    engines/hdb/file-manager.h
    engines/hdb/lua-script.cpp
    engines/hdb/sound.cpp
    engines/hdb/sound.h


diff --git a/engines/hdb/file-manager.cpp b/engines/hdb/file-manager.cpp
index 04f697f0c83..23278c5690f 100644
--- a/engines/hdb/file-manager.cpp
+++ b/engines/hdb/file-manager.cpp
@@ -40,9 +40,9 @@ FileMan::~FileMan() {
 		delete _dir[i];
 }
 
-void FileMan::openMPC(const Common::String &filename) {
+void FileMan::openMPC(const Common::Path &filename) {
 	if (!_mpcFile->open(filename))
-		error("FileMan::openMPC(): Error reading the MSD/MPC file %s", filename.c_str());
+		error("FileMan::openMPC(): Error reading the MSD/MPC file %s", filename.toString().c_str());
 
 	_dataHeader.id = _mpcFile->readUint32BE();
 
diff --git a/engines/hdb/file-manager.h b/engines/hdb/file-manager.h
index def477e8411..6dbf28ef5b1 100644
--- a/engines/hdb/file-manager.h
+++ b/engines/hdb/file-manager.h
@@ -67,7 +67,7 @@ public:
 		uint32 dirSize;
 	} _dataHeader;
 
-	void openMPC(const Common::String &filename);
+	void openMPC(const Common::Path &filename);
 	void closeMPC();
 	void seek(int32 offset, int flag);
 
diff --git a/engines/hdb/lua-script.cpp b/engines/hdb/lua-script.cpp
index 9cb5069eed1..326ace40c22 100644
--- a/engines/hdb/lua-script.cpp
+++ b/engines/hdb/lua-script.cpp
@@ -1998,7 +1998,7 @@ bool LuaScript::executeMPC(Common::SeekableReadStream *stream, const char *name,
 bool LuaScript::executeFile(const Common::String &filename) {
 	Common::File *file = new Common::File;
 
-	if (!file->open(filename)) {
+	if (!file->open(Common::Path(filename))) {
 		error("Cannot find \"%s\"", filename.c_str());
 	}
 
diff --git a/engines/hdb/sound.cpp b/engines/hdb/sound.cpp
index 80087a4b26f..0b9e46f1237 100644
--- a/engines/hdb/sound.cpp
+++ b/engines/hdb/sound.cpp
@@ -1765,7 +1765,7 @@ void Song::stop() {
 
 void Song::playSong(SoundType song, bool fadeIn, int ramp) {
 
-	Common::String fileName = getFileName(song);
+	Common::Path fileName = getFileName(song);
 	Audio::AudioStream* musicStream = createStream(fileName);
 
 	if (musicStream == nullptr) return;
@@ -1797,7 +1797,7 @@ void Song::playSong(SoundType song, bool fadeIn, int ramp) {
 	);
 }
 
-Common::String Song::getFileName(SoundType song) {
+Common::Path Song::getFileName(SoundType song) {
 	Common::String fileName(soundList[song].name);
 
 	if (g_hdb->getPlatform() == Common::kPlatformLinux) {
@@ -1820,10 +1820,10 @@ Common::String Song::getFileName(SoundType song) {
 		}
 	}
 
-	return fileName;
+	return Common::Path(fileName);
 }
 
-Audio::AudioStream* Song::createStream(Common::String fileName) {
+Audio::AudioStream* Song::createStream(const Common::Path &fileName) {
 	Common::SeekableReadStream* stream = SearchMan.createReadStreamForMember(fileName);
 	if (stream == nullptr)
 		return nullptr;
diff --git a/engines/hdb/sound.h b/engines/hdb/sound.h
index 7ba03e086aa..70d8ca1137d 100644
--- a/engines/hdb/sound.h
+++ b/engines/hdb/sound.h
@@ -1473,8 +1473,8 @@ public:
 //	void update();
 
 private:
-	static Common::String getFileName(SoundType song);
-	Audio::AudioStream* createStream(Common::String fileName);
+	static Common::Path getFileName(SoundType song);
+	Audio::AudioStream* createStream(const Common::Path &fileName);
 
 	Audio::SoundHandle handle;
 


Commit: 063e516fc8f4c346e7562c306dff9780c9c07460
    https://github.com/scummvm/scummvm/commit/063e516fc8f4c346e7562c306dff9780c9c07460
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
HOPKINS: Migrate engine to Path

Changed paths:
    engines/hopkins/anim.cpp
    engines/hopkins/anim.h
    engines/hopkins/computer.cpp
    engines/hopkins/dialogs.cpp
    engines/hopkins/files.cpp
    engines/hopkins/files.h
    engines/hopkins/font.cpp
    engines/hopkins/font.h
    engines/hopkins/globals.h
    engines/hopkins/graphics.cpp
    engines/hopkins/graphics.h
    engines/hopkins/hopkins.cpp
    engines/hopkins/hopkins.h
    engines/hopkins/lines.cpp
    engines/hopkins/lines.h
    engines/hopkins/objects.cpp
    engines/hopkins/objects.h
    engines/hopkins/script.cpp
    engines/hopkins/sound.cpp
    engines/hopkins/sound.h
    engines/hopkins/talk.cpp
    engines/hopkins/talk.h


diff --git a/engines/hopkins/anim.cpp b/engines/hopkins/anim.cpp
index 258046b9928..ff47d8325d8 100644
--- a/engines/hopkins/anim.cpp
+++ b/engines/hopkins/anim.cpp
@@ -54,7 +54,7 @@ void AnimationManager::clearAll() {
  * @param rate2			Delay amount between animation frames
  * @param rate3			Delay amount after animation finishes
  */
-void AnimationManager::playAnim(const Common::String &hiresName, const Common::String &lowresName, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) {
+void AnimationManager::playAnim(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) {
 	Common::File f;
 
 	if (_vm->shouldQuit())
@@ -66,7 +66,7 @@ void AnimationManager::playAnim(const Common::String &hiresName, const Common::S
 
 	if (!f.open(hiresName)) {
 		if (!f.open(lowresName))
-			error("Files not found: %s - %s", hiresName.c_str(), lowresName.c_str());
+			error("Files not found: %s - %s", hiresName.toString().c_str(), lowresName.toString().c_str());
 	}
 
 	f.skip(6);
@@ -195,7 +195,7 @@ void AnimationManager::playAnim(const Common::String &hiresName, const Common::S
 /**
  * Play Animation, type 2
  */
-void AnimationManager::playAnim2(const Common::String &hiresName, const Common::String &lowresName, uint32 rate1, uint32 rate2, uint32 rate3) {
+void AnimationManager::playAnim2(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3) {
 	int oldScrollPosX = 0;
 	byte *screenP = nullptr;
 	Common::File f;
@@ -216,7 +216,7 @@ void AnimationManager::playAnim2(const Common::String &hiresName, const Common::
 		screenP = _vm->_graphicsMan->_backBuffer;
 		if (!f.open(hiresName)) {
 			if (!f.open(lowresName))
-				error("Error opening files: %s - %s", hiresName.c_str(), lowresName.c_str());
+				error("Error opening files: %s - %s", hiresName.toString().c_str(), lowresName.toString().c_str());
 		}
 
 		f.skip(6);
@@ -351,13 +351,14 @@ void AnimationManager::playAnim2(const Common::String &hiresName, const Common::
 /**
  * Load Animation
  */
-void AnimationManager::loadAnim(const Common::String &animName) {
+void AnimationManager::loadAnim(const Common::Path &animName) {
 	clearAnim();
 
-	Common::String filename = animName + ".ANI";
+	Common::Path filename(animName);
+	filename.appendInPlace(".ANI");
 	Common::File f;
 	if (!f.open(filename))
-		error("Failed to open %s", filename.c_str());
+		error("Failed to open %s", filename.toString().c_str());
 
 	int filesize = f.size();
 	int nbytes = filesize - 115;
@@ -381,7 +382,7 @@ void AnimationManager::loadAnim(const Common::String &animName) {
 	f.read(filename6, 15);
 
 	if (READ_BE_UINT32(header) != MKTAG('A', 'N', 'I', 'S'))
-		error("Invalid animation File: %s", filename.c_str());
+		error("Invalid animation File: %s", filename.toString().c_str());
 
 	const char *files[6] = { &filename1[0], &filename2[0], &filename3[0], &filename4[0],
 			&filename5[0], &filename6[0] };
@@ -389,9 +390,9 @@ void AnimationManager::loadAnim(const Common::String &animName) {
 	for (int idx = 0; idx <= 5; ++idx) {
 		if (files[idx][0]) {
 			if (!f.exists(files[idx]))
-				error("Missing file %s in animation File: %s", files[idx], filename.c_str());
+				error("Missing file %s in animation File: %s", files[idx], filename.toString().c_str());
 			if (loadSpriteBank(idx + 1, files[idx]))
-				error("Invalid sprite bank in animation File: %s", filename.c_str());
+				error("Invalid sprite bank in animation File: %s", filename.toString().c_str());
 		}
 	}
 
@@ -425,7 +426,7 @@ void AnimationManager::clearAnim() {
 /**
  * Load Sprite Bank
  */
-int AnimationManager::loadSpriteBank(int idx, const Common::String &filename) {
+int AnimationManager::loadSpriteBank(int idx, const Common::Path &filename) {
 	int result = 0;
 	Bank[idx]._loadedFl = true;
 	Bank[idx]._filename = filename;
@@ -461,7 +462,7 @@ int AnimationManager::loadSpriteBank(int idx, const Common::String &filename) {
 	}
 	Bank[idx]._objDataIdx = objectDataIdx;
 
-	Common::String ofsFilename = Bank[idx]._filename;
+	Common::String ofsFilename = Bank[idx]._filename.baseName();
 	char ch;
 	do {
 		ch = ofsFilename.lastChar();
@@ -469,9 +470,10 @@ int AnimationManager::loadSpriteBank(int idx, const Common::String &filename) {
 	} while (ch != '.');
 	ofsFilename += ".OFS";
 
+	Common::Path ofsPathname(Bank[idx]._filename.getParent().appendComponent(ofsFilename));
 	Common::File f;
-	if (f.exists(ofsFilename)) {
-		byte *ofsData = _vm->_fileIO->loadFile(ofsFilename);
+	if (f.exists(ofsPathname)) {
+		byte *ofsData = _vm->_fileIO->loadFile(ofsPathname);
 		byte *curOfsData = ofsData;
 		for (int objIdx = 0; objIdx < Bank[idx]._objDataIdx; ++objIdx, curOfsData += 8) {
 			int x1 = READ_LE_INT16(curOfsData);
@@ -539,7 +541,7 @@ void AnimationManager::searchAnim(const byte *data, int animIndex, int bufSize)
 /**
  * Play sequence
  */
-void AnimationManager::playSequence(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipEscFl, bool skipSeqFl, bool noColFl) {
+void AnimationManager::playSequence(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipEscFl, bool skipSeqFl, bool noColFl) {
 	if (_vm->shouldQuit())
 		return;
 
@@ -555,7 +557,7 @@ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, ui
 	byte *screenP = _vm->_graphicsMan->_backBuffer;
 	Common::File f;
 	if (!f.open(file))
-		error("Error opening file - %s", file.c_str());
+		error("Error opening file - %s", file.toString().c_str());
 
 	f.skip(6);
 	f.read(_vm->_graphicsMan->_palette, 800);
@@ -665,7 +667,7 @@ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, ui
 /**
  * Play Sequence type 2
  */
-void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) {
+void AnimationManager::playSequence2(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) {
 	byte *screenP;
 	Common::File f;
 
@@ -676,7 +678,7 @@ void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, u
 	screenP = _vm->_graphicsMan->_backBuffer;
 
 	if (!f.open(file))
-		error("File not found - %s", file.c_str());
+		error("File not found - %s", file.toString().c_str());
 
 	f.skip(6);
 	f.read(_vm->_graphicsMan->_palette, 800);
diff --git a/engines/hopkins/anim.h b/engines/hopkins/anim.h
index 90479c8c017..54b7fb04b62 100644
--- a/engines/hopkins/anim.h
+++ b/engines/hopkins/anim.h
@@ -24,7 +24,7 @@
 
 #include "common/scummsys.h"
 #include "common/endian.h"
-#include "common/str.h"
+#include "common/path.h"
 #include "graphics/surface.h"
 
 namespace Hopkins {
@@ -32,7 +32,7 @@ namespace Hopkins {
 struct BankItem {
 	byte *_data;
 	bool _loadedFl;
-	Common::String _filename;
+	Common::Path _filename;
 	int _fileHeader;
 	int _objDataIdx;
 };
@@ -51,7 +51,7 @@ private:
 	HopkinsEngine *_vm;
 
 	void initAnimBqe();
-	int loadSpriteBank(int idx, const Common::String &filename);
+	int loadSpriteBank(int idx, const Common::Path &filename);
 	void searchAnim(const byte *data, int animIndex, int count);
 
 public:
@@ -61,12 +61,12 @@ public:
 	AnimationManager(HopkinsEngine *vm);
 	void clearAll();
 
-	void loadAnim(const Common::String &animName);
+	void loadAnim(const Common::Path &animName);
 	void clearAnim();
-	void playAnim(const Common::String &hiresName, const Common::String &lowresName, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl = false);
-	void playAnim2(const Common::String &hiresName, const Common::String &lowresName, uint32 rate1, uint32 rate2, uint32 rate3);
-	void playSequence(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipEscFl, bool skipSeqFl, bool noColFl = false);
-	void playSequence2(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl = false);
+	void playAnim(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl = false);
+	void playAnim2(const Common::Path &hiresName, const Common::Path &lowresName, uint32 rate1, uint32 rate2, uint32 rate3);
+	void playSequence(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipEscFl, bool skipSeqFl, bool noColFl = false);
+	void playSequence2(const Common::Path &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl = false);
 
 	void setClearAnimFlag()   { _clearAnimationFl = true; }
 	void unsetClearAnimFlag() { _clearAnimationFl = false; }
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index 6257198a1a8..005a1020631 100644
--- a/engines/hopkins/computer.cpp
+++ b/engines/hopkins/computer.cpp
@@ -76,7 +76,7 @@ void ComputerManager::setTextMode() {
 	_vm->_graphicsMan->_lineNbr = SCREEN_WIDTH;
 	_vm->_fontMan->_font = _vm->_globals->freeMemory(_vm->_fontMan->_font);
 
-	Common::String filename = "STFONT.SPR";
+	Common::Path filename("STFONT.SPR");
 	Common::File f;
 	if (!f.exists(filename))
 		filename = "FONTE.SPR"; // Used by the BeOS and OS/2 versions as an alternative
@@ -493,7 +493,7 @@ void ComputerManager::restoreFBIRoom() {
 void ComputerManager::readText(int idx) {
 	_vm->_events->_escKeyFl = false;
 
-	Common::String filename;
+	Common::Path filename;
 	switch (_vm->_globals->_language) {
 	case LANG_EN:
 		filename = "THOPKAN.TXT";
@@ -652,10 +652,10 @@ void ComputerManager::newLevel() {
 	_breakoutLevel = (int16 *)_vm->_globals->freeMemory((byte *)_breakoutLevel);
 
 	++_breakoutLevelNbr;
-	Common::String file;
+	Common::Path file;
 	Common::File f;
 	while (!_vm->shouldQuit()) {
-		file = Common::String::format("TAB%d.TAB", _breakoutLevelNbr);
+		file = Common::Path(Common::String::format("TAB%d.TAB", _breakoutLevelNbr));
 		if (f.open(file))
 			break;
 
diff --git a/engines/hopkins/dialogs.cpp b/engines/hopkins/dialogs.cpp
index 1d5bc454e02..b97b42148e2 100644
--- a/engines/hopkins/dialogs.cpp
+++ b/engines/hopkins/dialogs.cpp
@@ -79,7 +79,7 @@ void DialogsManager::drawInvent(Common::Point oldBorder, int oldBorderSpriteInde
 void DialogsManager::showOptionsDialog() {
 	_vm->_events->changeMouseCursor(0);
 	_vm->_events->refreshScreenAndEvents();
-	Common::String filename;
+	Common::Path filename;
 	if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
 		filename = "OPTION.SPR";
 	else {
@@ -360,7 +360,7 @@ void DialogsManager::showInventory() {
 		_vm->_globals->_disableInventFl = true;
 		_vm->_graphicsMan->setColorPercentage2(251, 100, 100, 100);
 
-		Common::String filename;
+		Common::Path filename;
 		if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
 			filename = "INVENT.SPR";
 		else {
@@ -381,7 +381,7 @@ void DialogsManager::showInventory() {
 
 		Common::File f;
 		if (!f.open(filename))
-			error("Error opening file - %s", filename.c_str());
+			error("Error opening file - %s", filename.toString().c_str());
 
 		size_t filesize = f.size();
 		_inventWin1 = _vm->_globals->allocMemory(filesize);
@@ -662,7 +662,7 @@ void DialogsManager::showSaveGame() {
  * Load/Save dialog
  */
 void DialogsManager::showSaveLoad(SaveLoadMode mode) {
-	Common::String filename;
+	Common::Path filename;
 
 	if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
 		filename = "SAVE.SPR";
diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp
index 1e383b9283e..7ad845f6844 100644
--- a/engines/hopkins/files.cpp
+++ b/engines/hopkins/files.cpp
@@ -43,16 +43,16 @@ FileManager::FileManager(HopkinsEngine *vm) {
 /**
  * Load a file
  */
-byte *FileManager::loadFile(const Common::String &file) {
+byte *FileManager::loadFile(const Common::Path &file) {
 	Common::File f;
 	if (!f.open(file))
-		error("Error opening %s", file.c_str());
+		error("Error opening %s", file.toString().c_str());
 
 	// Allocate space for the file contents
 	size_t filesize = f.size();
 	byte *data = _vm->_globals->allocMemory(filesize+1);
 	if (!data)
-		error("Error allocating space for file being loaded - %s", file.c_str());
+		error("Error allocating space for file being loaded - %s", file.toString().c_str());
 
 	readStream(f, data, filesize);
 	f.close();
@@ -79,7 +79,7 @@ void FileManager::initCensorship() {
 /**
  * Check if a file is present
  */
-bool FileManager::fileExists(const Common::String &file) {
+bool FileManager::fileExists(const Common::Path &file) {
 	Common::File f;
 
 	return f.exists(file);
@@ -88,13 +88,13 @@ bool FileManager::fileExists(const Common::String &file) {
 /**
  * Search file in Cat file
  */
-byte *FileManager::searchCat(const Common::String &file, CatMode mode, bool &fileFoundFl) {
+byte *FileManager::searchCat(const Common::Path &file, CatMode mode, bool &fileFoundFl) {
 	byte *ptr = nullptr;
 	fileFoundFl = true;
 	Common::File f;
 
-	Common::String filename = file;
-	Common::String secondaryFilename = "";
+	Common::String filename = file.toString('/');
+	Common::Path secondaryFilename;
 	filename.toUppercase();
 
 	switch (mode) {
@@ -166,7 +166,7 @@ byte *FileManager::searchCat(const Common::String &file, CatMode mode, bool &fil
 		break;
 
 	case RES_VOI: {
-		Common::String tmpFilename;
+		Common::Path tmpFilename;
 		if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS)
 			tmpFilename = "ENG_VOI.CAT";
 		// Win95 and Linux versions uses another set of names
@@ -226,7 +226,7 @@ byte *FileManager::searchCat(const Common::String &file, CatMode mode, bool &fil
 
 	_vm->_globals->freeMemory(ptr);
 
-	if (secondaryFilename != "") {
+	if (!secondaryFilename.empty()) {
 		if (!f.open(secondaryFilename))
 			error("CHARGE_FICHIER");
 
@@ -249,12 +249,12 @@ byte *FileManager::searchCat(const Common::String &file, CatMode mode, bool &fil
 /**
  * Returns the size of a file. Throws an error if the file can't be found
  */
-uint32 FileManager::fileSize(const Common::String &filename) {
+uint32 FileManager::fileSize(const Common::Path &filename) {
 	Common::File f;
 	uint32 size;
 
 	if (!f.open(filename))
-		error("Could not find file %s", filename.c_str());
+		error("Could not find file %s", filename.toString().c_str());
 
 	size = f.size();
 	f.close();
diff --git a/engines/hopkins/files.h b/engines/hopkins/files.h
index b2675a08dc8..42f778c8ce3 100644
--- a/engines/hopkins/files.h
+++ b/engines/hopkins/files.h
@@ -23,9 +23,11 @@
 #define HOPKINS_FILES_H
 
 #include "common/scummsys.h"
-#include "common/hash-str.h"
-#include "common/str.h"
-#include "common/stream.h"
+
+namespace Common {
+class ReadStream;
+class Path;
+}
 
 namespace Hopkins {
 
@@ -44,12 +46,12 @@ public:
 
 	FileManager(HopkinsEngine *vm);
 
-	bool fileExists(const Common::String &file);
-	byte *loadFile(const Common::String &file);
+	bool fileExists(const Common::Path &file);
+	byte *loadFile(const Common::Path &file);
 	int readStream(Common::ReadStream &stream, void *buf, size_t nbytes);
 	void initCensorship();
-	byte *searchCat(const Common::String &file, CatMode mode, bool &fileFoundFl);
-	uint32 fileSize(const Common::String &filename);
+	byte *searchCat(const Common::Path &file, CatMode mode, bool &fileFoundFl);
+	uint32 fileSize(const Common::Path &filename);
 };
 
 } // End of namespace Hopkins
diff --git a/engines/hopkins/font.cpp b/engines/hopkins/font.cpp
index 174aa7924f7..81003876da9 100644
--- a/engines/hopkins/font.cpp
+++ b/engines/hopkins/font.cpp
@@ -142,7 +142,7 @@ void FontManager::setOptimalColor(int idx1, int idx2, int idx3, int idx4) {
 /**
  * Init text structure
  */
-void FontManager::initTextBuffers(int idx, int messageId, const Common::String &filename, int xp, int yp, int textType, int length, int color) {
+void FontManager::initTextBuffers(int idx, int messageId, const Common::Path &filename, int xp, int yp, int textType, int length, int color) {
 	assert(idx - 5 >= 0 && (idx - 5) <= MAX_TEXT);
 
 	TxtItem &txt = _text[idx - 5];
@@ -157,7 +157,7 @@ void FontManager::initTextBuffers(int idx, int messageId, const Common::String &
 }
 
 // Box
-void FontManager::box(int idx, int messageId, const Common::String &filename, int xp, int yp) {
+void FontManager::box(int idx, int messageId, const Common::Path &filename, int xp, int yp) {
 	int textPosX = xp;
 	if (idx < 0)
 		error("Bad number for text");
@@ -190,26 +190,27 @@ void FontManager::box(int idx, int messageId, const Common::String &filename, in
 			_textSortArray[i] = 0;
 
 		_text[idx]._textLoadedFl = true;
-		Common::String file = filename;
-		if (strncmp(file.c_str(), _oldName.c_str(), strlen(file.c_str())) != 0) {
+		Common::String basename(filename.baseName());
+		if (filename != _oldName) {
 			// Starting to access a new file, so read in the index file for the file
-			_oldName = file;
-			_indexName = Common::String(file.c_str(), file.size() - 3);
-			_indexName += "IND";
+			_oldName = filename;
+			_indexName = filename.getParent();
+			_indexName.joinInPlace(Common::String(basename.c_str(), basename.size() - 3));
+			_indexName.appendInPlace("IND");
 
 			Common::File f;
 			if (!f.open(_indexName))
-				error("Error opening file - %s", _indexName.c_str());
+				error("Error opening file - %s", _indexName.toString().c_str());
 			int filesize = f.size();
 			for (int i = 0; i < (filesize / 4); ++i)
 				_index[i] = f.readUint32LE();
 			f.close();
 		}
 		int bufSize;
-		if (filename[0] != 'Z' || filename[1] != 'O') {
+		if (basename[0] != 'Z' || basename[1] != 'O') {
 			Common::File f;
-			if (!f.open(file))
-				error("Error opening file - %s", _indexName.c_str());
+			if (!f.open(filename))
+				error("Error opening file - %s", _indexName.toString().c_str());
 
 			bufSize = 2048;
 			f.seek(_index[messageId]);
diff --git a/engines/hopkins/font.h b/engines/hopkins/font.h
index e4f763fad9b..398e5003537 100644
--- a/engines/hopkins/font.h
+++ b/engines/hopkins/font.h
@@ -34,7 +34,7 @@ class HopkinsEngine;
 
 struct TxtItem {
 	bool _textOnFl;
-	Common::String _filename;
+	Common::Path _filename;
 	Common::Point _pos;
 	int _messageId;
 	int _lineCount;
@@ -62,8 +62,8 @@ private:
 	void setTextColor(int idx, byte colByte);
 
 	int _textSortArray[21];
-	Common::String _oldName;
-	Common::String _indexName;
+	Common::Path _oldName;
+	Common::Path _indexName;
 	int _index[4048];
 	byte *_tempText;
 	byte *_zoneText;
@@ -84,12 +84,12 @@ public:
 
 	void showText(int idx);
 	void hideText(int idx);
-	void initTextBuffers(int idx, int messageId, const Common::String &filename, int xp, int yp, int textType, int length, int color);
+	void initTextBuffers(int idx, int messageId, const Common::Path &filename, int xp, int yp, int textType, int length, int color);
 	void displayText(int xp, int yp, const Common::String &message, int col);
 	void displayTextVesa(int xp, int yp, const Common::String &message, int col);
 	void renderTextDisplay(int xp, int yp, const Common::String &msg, int col);
 	void setOptimalColor(int idx1, int idx2, int idx3, int idx4);
-	void box(int idx, int messageId, const Common::String &filename, int xp, int yp);
+	void box(int idx, int messageId, const Common::Path &filename, int xp, int yp);
 };
 
 } // End of namespace Hopkins
diff --git a/engines/hopkins/globals.h b/engines/hopkins/globals.h
index e6373949fff..01d6ffb6e68 100644
--- a/engines/hopkins/globals.h
+++ b/engines/hopkins/globals.h
@@ -229,8 +229,8 @@ public:
 	bool _freezeCharacterFl;
 	bool _checkDistanceFl;
 	byte *_characterSpriteBuf;
-	Common::String _zoneFilename;
-	Common::String _textFilename;
+	Common::Path _zoneFilename;
+	Common::Path _textFilename;
 	byte *_levelSpriteBuf;
 
 	EventMode _eventMode;
diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp
index ca7401799ec..442298d3757 100644
--- a/engines/hopkins/graphics.cpp
+++ b/engines/hopkins/graphics.cpp
@@ -169,8 +169,9 @@ void GraphicsManager::clearVesaScreen() {
 /**
  * Load Image
  */
-void GraphicsManager::loadImage(const Common::String &file) {
-	Common::String filename	= Common::String::format("%s.PCX", file.c_str());
+void GraphicsManager::loadImage(const Common::Path &file) {
+	Common::Path filename(file);
+	filename.appendInPlace(".PCX");
 	loadScreen(filename);
 	initColorTable(165, 170, _palette);
 }
@@ -178,7 +179,7 @@ void GraphicsManager::loadImage(const Common::String &file) {
 /**
  * Load VGA Image
  */
-void GraphicsManager::loadVgaImage(const Common::String &file) {
+void GraphicsManager::loadVgaImage(const Common::Path &file) {
 	setScreenWidth(SCREEN_WIDTH);
 	clearScreen();
 	loadPCX320(_backBuffer, file, _palette);
@@ -195,7 +196,7 @@ void GraphicsManager::loadVgaImage(const Common::String &file) {
 /**
  * Load Screen
  */
-void GraphicsManager::loadScreen(const Common::String &file) {
+void GraphicsManager::loadScreen(const Common::Path &file) {
 	Common::File f;
 	assert(!_videoPtr);
 
@@ -204,7 +205,7 @@ void GraphicsManager::loadScreen(const Common::String &file) {
 	_vm->_fileIO->searchCat(file, RES_PIC, fileFoundFl);
 	if (!fileFoundFl) {
 		if (!f.open(file))
-			error("loadScreen - %s", file.c_str());
+			error("loadScreen - %s", file.toString().c_str());
 
 		f.seek(0, SEEK_END);
 		f.close();
@@ -298,7 +299,7 @@ void GraphicsManager::fillSurface(byte *surface, byte *col, int size) {
 	}
 }
 
-void GraphicsManager::loadPCX640(byte *surface, const Common::String &file, byte *palette, bool typeFlag) {
+void GraphicsManager::loadPCX640(byte *surface, const Common::Path &file, byte *palette, bool typeFlag) {
 	Common::File f;
 	Image::PCXDecoder pcxDecoder;
 
@@ -313,12 +314,12 @@ void GraphicsManager::loadPCX640(byte *surface, const Common::String &file, byte
 	} else {
 		// Load stand alone PCX file
 		if (!f.open(file))
-		  error("Error opening PCX %s.", file.c_str());
+		  error("Error opening PCX %s.", file.toString().c_str());
 	}
 
 	// Decode the PCX
 	if (!pcxDecoder.loadStream(f))
-		error("Error decoding PCX %s", file.c_str());
+		error("Error decoding PCX %s", file.toString().c_str());
 
 	const Graphics::Surface *s = pcxDecoder.getSurface();
 
@@ -333,10 +334,10 @@ void GraphicsManager::loadPCX640(byte *surface, const Common::String &file, byte
 	f.close();
 }
 
-void GraphicsManager::loadPCX320(byte *surface, const Common::String &file, byte *palette) {
+void GraphicsManager::loadPCX320(byte *surface, const Common::Path &file, byte *palette) {
 	Common::File f;
 	if (!f.open(file))
-		error("File not found - %s", file.c_str());
+		error("File not found - %s", file.toString().c_str());
 
 	size_t filesize = f.size();
 
@@ -1752,8 +1753,9 @@ void GraphicsManager::displayFont(byte *surface, const byte *spriteData, int xp,
 	} while (yCtr != 1);
 }
 
-void GraphicsManager::initScreen(const Common::String &file, int mode, bool initializeScreen) {
-	Common::String filename = file + ".ini";
+void GraphicsManager::initScreen(const Common::Path &file, int mode, bool initializeScreen) {
+	Common::Path filename(file);
+	filename.appendInPlace(".ini");
 	bool fileFoundFl = false;
 
 	byte *ptr = _vm->_fileIO->searchCat(filename, RES_INI, fileFoundFl);
@@ -1763,7 +1765,8 @@ void GraphicsManager::initScreen(const Common::String &file, int mode, bool init
 	}
 
 	if (!mode) {
-		filename = file + ".spr";
+		filename = file;
+		filename.appendInPlace(".spr");
 		_vm->_globals->_levelSpriteBuf = _vm->_globals->freeMemory(_vm->_globals->_levelSpriteBuf);
 		if (initializeScreen) {
 			fileFoundFl = false;
@@ -1776,7 +1779,7 @@ void GraphicsManager::initScreen(const Common::String &file, int mode, bool init
 		}
 	}
 	if (READ_BE_UINT24(ptr) != MKTAG24('I', 'N', 'I')) {
-		error("Invalid INI File %s", file.c_str());
+		error("Invalid INI File %s", file.toString().c_str());
 	} else {
 		bool doneFlag = false;
 		int dataOffset = 1;
@@ -1801,7 +1804,8 @@ void GraphicsManager::initScreen(const Common::String &file, int mode, bool init
 	_vm->_globals->freeMemory(ptr);
 	_vm->_globals->_answerBuffer = _vm->_globals->freeMemory(_vm->_globals->_answerBuffer);
 
-	filename = file + ".rep";
+	filename = file;
+	filename.appendInPlace(".rep");
 	fileFoundFl = false;
 	byte *dataP = _vm->_fileIO->searchCat(filename, RES_REP, fileFoundFl);
 	if (!fileFoundFl)
diff --git a/engines/hopkins/graphics.h b/engines/hopkins/graphics.h
index 39b83819b52..aa08394b177 100644
--- a/engines/hopkins/graphics.h
+++ b/engines/hopkins/graphics.h
@@ -26,7 +26,6 @@
 #include "common/array.h"
 #include "common/endian.h"
 #include "common/rect.h"
-#include "common/str.h"
 #include "graphics/surface.h"
 
 namespace Hopkins {
@@ -70,9 +69,9 @@ private:
 
 	bool _manualScroll;
 
-	void loadScreen(const Common::String &file);
-	void loadPCX640(byte *surface, const Common::String &file, byte *palette, bool typeFlag);
-	void loadPCX320(byte *surface, const Common::String &file, byte *palette);
+	void loadScreen(const Common::Path &file);
+	void loadPCX640(byte *surface, const Common::Path &file, byte *palette, bool typeFlag);
+	void loadPCX320(byte *surface, const Common::Path &file, byte *palette);
 	void fadeIn(const byte *palette, int step, const byte *surface);
 	void fadeOut(const byte *palette, int step, const byte *surface);
 	void changePalette(const byte *palette);
@@ -140,8 +139,8 @@ public:
 	void displayLines();
 	void displayDebugRect(Graphics::Surface *surface, const Common::Rect &srcRect, uint32 color = 0xffffff);
 	void copySurface(const byte *surface, int x1, int y1, int width, int height, byte *destSurface, int destX, int destY);
-	void loadImage(const Common::String &file);
-	void loadVgaImage(const Common::String &file);
+	void loadImage(const Common::Path &file);
+	void loadVgaImage(const Common::Path &file);
 	void fadeInLong();
 	void fadeInBreakout();
 	void fadeInDefaultLength(const byte *surface);
@@ -166,7 +165,7 @@ public:
 	void scrollScreen(int amount);
 	int zoomIn(int v, int percentage);
 	int zoomOut(int v, int percentage);
-	void initScreen(const Common::String &file, int mode, bool initializeScreen);
+	void initScreen(const Common::Path &file, int mode, bool initializeScreen);
 	void displayAllBob();
 	void endDisplayBob();
 	void updateScreen();
diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp
index cc341e5f7a5..c125043cbb7 100644
--- a/engines/hopkins/hopkins.cpp
+++ b/engines/hopkins/hopkins.cpp
@@ -1191,7 +1191,7 @@ bool HopkinsEngine::runFull() {
 			_globals->_characterMaxPosY = 435;
 			_globals->_disableInventFl = false;
 			_objectsMan->_forestFl = true;
-			Common::String im = Common::String::format("IM%d", _globals->_exitId);
+			Common::Path im(Common::String::format("IM%d", _globals->_exitId));
 			_soundMan->playSound(13);
 			if (_objectsMan->_forestSprite == nullptr) {
 				_objectsMan->_forestSprite = _objectsMan->loadSprite("HOPDEG.SPR");
@@ -1589,7 +1589,7 @@ void HopkinsEngine::initializeSystem() {
 	// Synchronize the sound settings from ScummVM
 	_soundMan->syncSoundSettings();
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "SYSTEM");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "LINK");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "BUFFER");
@@ -2265,7 +2265,7 @@ void HopkinsEngine::playPlaneCutscene() {
 }
 
 void HopkinsEngine::loadBaseMap() {
-	Common::String filename	= Common::String::format("%s.PCX", "PBASE");
+	Common::Path filename(Common::String::format("%s.PCX", "PBASE"));
 	Common::File f;
 
 	if (f.exists(filename)) {
@@ -2398,7 +2398,7 @@ void HopkinsEngine::loadCredits() {
 	_globals->_creditsPosY = 440;
 	_globals->_creditsStep = 45;
 	byte *bufPtr;
-	Common::String filename;
+	Common::Path filename;
 	switch (_globals->_language) {
 	case LANG_EN:
 		filename = "CREAN.TXT";
@@ -2766,7 +2766,7 @@ void HopkinsEngine::setSubmarineSprites() {
 	}
 }
 
-void HopkinsEngine::handleOceanMaze(int16 curExitId, Common::String backgroundFilename, Directions defaultDirection, int16 exit1, int16 exit2, int16 exit3, int16 exit4, int16 soundId) {
+void HopkinsEngine::handleOceanMaze(int16 curExitId, const Common::Path &backgroundFilename, Directions defaultDirection, int16 exit1, int16 exit2, int16 exit3, int16 exit4, int16 soundId) {
 	_globals->_cityMapEnabledFl = false;
 	_graphicsMan->_noFadingFl = false;
 	_globals->_freezeCharacterFl = false;
@@ -2774,7 +2774,7 @@ void HopkinsEngine::handleOceanMaze(int16 curExitId, Common::String backgroundFi
 	_globals->_disableInventFl = true;
 	_soundMan->playSound(soundId);
 	_globals->_characterSpriteBuf = _fileIO->loadFile("VAISSEAU.SPR");
-	if (backgroundFilename.size())
+	if (!backgroundFilename.empty())
 		_graphicsMan->loadImage(backgroundFilename);
 
 	if (curExitId == 77)
diff --git a/engines/hopkins/hopkins.h b/engines/hopkins/hopkins.h
index ac098a64450..246618a3198 100644
--- a/engines/hopkins/hopkins.h
+++ b/engines/hopkins/hopkins.h
@@ -111,7 +111,7 @@ private:
 
 	void handleOceanMouseEvents();
 	void setSubmarineSprites();
-	void handleOceanMaze(int16 curExitId, Common::String backgroundFilename, Directions defaultDirection, int16 exit1, int16 exit2, int16 exit3, int16 exit4, int16 soundId);
+	void handleOceanMaze(int16 curExitId, const Common::Path &backgroundFilename, Directions defaultDirection, int16 exit1, int16 exit2, int16 exit3, int16 exit4, int16 soundId);
 	void loadCredits();
 	void displayCredits(int startPosY, byte *buffer, char color);
 	void displayCredits();
diff --git a/engines/hopkins/lines.cpp b/engines/hopkins/lines.cpp
index 2b15264289d..aaf97355204 100644
--- a/engines/hopkins/lines.cpp
+++ b/engines/hopkins/lines.cpp
@@ -120,8 +120,8 @@ int LigneItem::appendToRouteDec(int from, int to, RouteItem *route, int index) {
 /**
  * Load lines
  */
-void LinesManager::loadLines(const Common::String &file) {
-	debugC(5, kDebugPath, "loadLines(%s)", file.c_str());
+void LinesManager::loadLines(const Common::Path &file) {
+	debugC(5, kDebugPath, "loadLines(%s)", file.toString().c_str());
 	resetLines();
 	_linesNumb = 0;
 	_lastLine = 0;
diff --git a/engines/hopkins/lines.h b/engines/hopkins/lines.h
index 1b8d7e322d5..ad58d1242f7 100644
--- a/engines/hopkins/lines.h
+++ b/engines/hopkins/lines.h
@@ -175,7 +175,7 @@ public:
 	void setMaxLineIdx(int idx);
 	int checkInventoryHotspots(int posX, int posY);
 	void addZoneLine(int idx, int fromX, int fromY, int destX, int destY, int bobZoneIdx);
-	void loadLines(const Common::String &file);
+	void loadLines(const Common::Path &file);
 	void addLine(int lineIdx, Directions direction, int fromX, int fromY, int destX, int destY);
 	void initRoute();
 	RouteItem *findRoute(int fromX, int fromY, int destX, int destY);
diff --git a/engines/hopkins/objects.cpp b/engines/hopkins/objects.cpp
index 535e7dfaa7c..d9809565067 100644
--- a/engines/hopkins/objects.cpp
+++ b/engines/hopkins/objects.cpp
@@ -351,7 +351,7 @@ void ObjectsManager::removeObjectDataBuf() {
 /**
  * Load Sprite from file
  */
-byte *ObjectsManager::loadSprite(const Common::String &file) {
+byte *ObjectsManager::loadSprite(const Common::Path &file) {
 	return _vm->_fileIO->loadFile(file);
 }
 
@@ -1720,7 +1720,7 @@ void ObjectsManager::goHome2() {
 /**
  * Load Zone
  */
-void ObjectsManager::loadZone(const Common::String &file) {
+void ObjectsManager::loadZone(const Common::Path &file) {
 	for (int i = 1; i <= 100; i++) {
 		ZoneItem *curZone = &_vm->_linesMan->_zone[i];
 		curZone->_destX = 0;
@@ -1742,7 +1742,7 @@ void ObjectsManager::loadZone(const Common::String &file) {
 
 	Common::File f;
 	if (!f.exists(file))
-		error("File not found : %s", file.c_str());
+		error("File not found : %s", file.toString().c_str());
 
 	byte *ptr = _vm->_fileIO->loadFile(file);
 	int bufId = 0;
@@ -2613,7 +2613,7 @@ void ObjectsManager::takeInventoryObject(int idx) {
 
 void ObjectsManager::loadObjectIniFile() {
 	byte *data;
-	Common::String file;
+	Common::Path file;
 	int lastOpcodeResult = 1;
 
 	file = "OBJET1.ini";
@@ -2622,11 +2622,11 @@ void ObjectsManager::loadObjectIniFile() {
 	if (!fileFoundFl) {
 		data = _vm->_fileIO->loadFile(file);
 		if (data == nullptr)
-			error("INI file %s not found", file.c_str());
+			error("INI file %s not found", file.toString().c_str());
 	}
 
 	if (READ_BE_UINT24(data) != MKTAG24('I', 'N', 'I'))
-		error("File %s is not an INI file", file.c_str());
+		error("File %s is not an INI file", file.toString().c_str());
 
 	for (;;) {
 		int opcodeType = _vm->_script->handleOpcode(data + 20 * lastOpcodeResult);
@@ -3130,15 +3130,15 @@ int ObjectsManager::getBobPosX(int idx) {
 	return _bob[idx]._xp;
 }
 
-void ObjectsManager::loadLinkFile(const Common::String &file, bool skipDetails) {
+void ObjectsManager::loadLinkFile(const Common::Path &file, bool skipDetails) {
 	Common::File f;
-	Common::String filename = file + ".LNK";
+	Common::Path filename = file.append(".LNK");
 	bool fileFoundFl = false;
 	byte *ptr = _vm->_fileIO->searchCat(filename, RES_LIN, fileFoundFl);
 	size_t nbytes = _vm->_fileIO->_catalogSize;
 	if (!fileFoundFl) {
 		if (!f.open(filename))
-			error("Error opening file - %s", filename.c_str());
+			error("Error opening file - %s", filename.toString().c_str());
 
 		nbytes = f.size();
 		ptr = _vm->_globals->allocMemory(nbytes);
@@ -3153,7 +3153,7 @@ void ObjectsManager::loadLinkFile(const Common::String &file, bool skipDetails)
 
 		resetHidingItems();
 
-		Common::String filename2 = Common::String((const char *)ptr + 1000);
+		Common::Path filename2(Common::String((const char *)ptr + 1000));
 		if (!filename2.empty()) {
 			fileFoundFl = false;
 			_hidingItemData[1] = _vm->_fileIO->searchCat(filename2, RES_SLI, fileFoundFl);
@@ -3761,8 +3761,8 @@ void ObjectsManager::lockAnimX(int idx, int x) {
 /**
  * Game scene control method
  */
-void ObjectsManager::sceneControl(const Common::String &backgroundFile, const Common::String &linkFile,
-							   const Common::String &animFile, const Common::String &s4, int soundNum, bool initializeScreen) {
+void ObjectsManager::sceneControl(const Common::Path &backgroundFile, const Common::Path &linkFile,
+							   const Common::Path &animFile, const Common::Path &s4, int soundNum, bool initializeScreen) {
 	_vm->_dialog->_inventFl = false;
 	_vm->_events->_gameKey = KEY_NONE;
 	_vm->_dialog->enableInvent();
@@ -3849,8 +3849,8 @@ void ObjectsManager::sceneControl(const Common::String &backgroundFile, const Co
 /**
  * Game scene control method
  */
-void ObjectsManager::sceneControl2(const Common::String &backgroundFile, const Common::String &linkFile,
-								const Common::String &animFile, const Common::String &s4, int soundNum, bool initializeScreen) {
+void ObjectsManager::sceneControl2(const Common::Path &backgroundFile, const Common::Path &linkFile,
+								const Common::Path &animFile, const Common::Path &s4, int soundNum, bool initializeScreen) {
 	_vm->_dialog->_inventFl = false;
 	_vm->_events->_gameKey = KEY_NONE;
 	_verb = 4;
@@ -4008,10 +4008,10 @@ void ObjectsManager::setHidingUseCount(int idx) {
 }
 
 // Load Hiding Items
-void ObjectsManager::loadHidingItems(const Common::String &file) {
+void ObjectsManager::loadHidingItems(const Common::Path &file) {
 	resetHidingItems();
 	byte *ptr = _vm->_fileIO->loadFile(file);
-	Common::String filename = Common::String((const char *)ptr);
+	Common::Path filename((const char *)ptr);
 
 	Common::File f;
 	if (!f.exists(filename))
diff --git a/engines/hopkins/objects.h b/engines/hopkins/objects.h
index ef3bde27af6..0a82fb9325d 100644
--- a/engines/hopkins/objects.h
+++ b/engines/hopkins/objects.h
@@ -200,7 +200,7 @@ private:
 	void clearSprite();
 	void setSpriteZoom(int idx, int zoomFactor);
 
-	void loadZone(const Common::String &file);
+	void loadZone(const Common::Path &file);
 	void changeCharacterHead(PlayerCharacter oldCharacter, PlayerCharacter newCharacter);
 	void goHome2();
 
@@ -249,8 +249,8 @@ public:
 
 	int getWidth(const byte *objectData, int idx);
 	int getHeight(const byte *objectData, int idx);
-	byte *loadSprite(const Common::String &file);
-	void loadLinkFile(const Common::String &file, bool OBSSEUL = false);
+	byte *loadSprite(const Common::Path &file);
+	void loadLinkFile(const Common::Path &file, bool OBSSEUL = false);
 	void addStaticSprite(const byte *spriteData, Common::Point pos, int idx, int spriteIndex, int zoomFactor, bool flipFl, int deltaX, int deltaY);
 	void animateSprite(int idx);
 	void removeSprite(int idx);
@@ -303,7 +303,7 @@ public:
 	void resetHidingItems();
 	void resetHidingUseCount(int idx);
 	void setHidingUseCount(int idx);
-	void loadHidingItems(const Common::String &file);
+	void loadHidingItems(const Common::Path &file);
 	void enableHidingBehavior();
 	void disableHidingBehavior();
 	void disableHidingItem(int idx);
@@ -324,10 +324,10 @@ public:
 	void disableVbob(int idx);
 	void setAndPlayAnim(int idx, int animIdx, int destPosi, bool animAction);
 
-	void sceneControl(const Common::String &backgroundFile, const Common::String &linkFile,
-		const Common::String &animFile, const Common::String &s4, int soundNum, bool initializeScreen);
-	void sceneControl2(const Common::String &backgroundFile, const Common::String &linkFile,
-		const Common::String &animFile, const Common::String &s4, int soundNum, bool initializeScreen);
+	void sceneControl(const Common::Path &backgroundFile, const Common::Path &linkFile,
+		const Common::Path &animFile, const Common::Path &s4, int soundNum, bool initializeScreen);
+	void sceneControl2(const Common::Path &backgroundFile, const Common::Path &linkFile,
+		const Common::Path &animFile, const Common::Path &s4, int soundNum, bool initializeScreen);
 	void goHome();
 	void paradise();
 };
diff --git a/engines/hopkins/script.cpp b/engines/hopkins/script.cpp
index fc4b8ca056b..34fbf7788dc 100644
--- a/engines/hopkins/script.cpp
+++ b/engines/hopkins/script.cpp
@@ -2536,7 +2536,7 @@ int ScriptManager::handleOpcode(const byte *dataP) {
 	case MKTAG24('S', 'O', 'U'): {
 		int soundNum = READ_LE_INT16(dataP + 5);
 
-		Common::String file = Common::String::format("SOUND%d.WAV", soundNum);
+		Common::Path file(Common::String::format("SOUND%d.WAV", soundNum));
 		_vm->_soundMan->playSoundFile(file);
 		opcodeType = 1;
 		break;
diff --git a/engines/hopkins/sound.cpp b/engines/hopkins/sound.cpp
index c4d71ed5e03..e84b33befdd 100644
--- a/engines/hopkins/sound.cpp
+++ b/engines/hopkins/sound.cpp
@@ -73,7 +73,7 @@ Audio::RewindableAudioStream *makeAPCStream(Common::SeekableReadStream *stream,
 
 class TwaAudioStream : public Audio::AudioStream {
 public:
-	TwaAudioStream(Common::String name, Common::SeekableReadStream *stream) {
+	TwaAudioStream(const Common::Path &name, Common::SeekableReadStream *stream) {
 		_name = name;
 		_cueSheet.clear();
 		_cueStream = nullptr;
@@ -149,39 +149,41 @@ protected:
 		_cueStream = nullptr;
 		_loadedCue = _cueSheet[nr];
 
-		Common::String filename = Common::String::format("%s_%02d", _name.c_str(), _cueSheet[nr]);
+		Common::Path filename(_name);
+		filename.appendInPlace(Common::String::format("_%02d", _cueSheet[nr]));
+
 		Common::File *file = new Common::File();
 
-		if (file->open(filename + ".APC")) {
+		if (file->open(filename.append(".APC"))) {
 			_cueStream = makeAPCStream(file, DisposeAfterUse::YES);
 			return true;
 		}
 
-		if (file->open(filename + ".WAV")) {
+		if (file->open(filename.append(".WAV"))) {
 			_cueStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
 			return true;
 		}
 
-		if (file->open(filename + ".RAW")) {
+		if (file->open(filename.append(".RAW"))) {
 			_cueStream = Audio::makeRawStream(file, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
 			return true;
 		}
 
-		warning("TwaAudioStream::loadCue: Missing cue %d (%s)", nr, filename.c_str());
+		warning("TwaAudioStream::loadCue: Missing cue %d (%s)", nr, filename.toString().c_str());
 		_loadedCue = -1;
 		delete file;
 		return false;
 	}
 
 private:
-	Common::String _name;
+	Common::Path _name;
 	Common::Array<int> _cueSheet;
 	Audio::RewindableAudioStream *_cueStream;
 	uint _cue;
 	int _loadedCue;
 };
 
-Audio::AudioStream *makeTwaStream(Common::String name, Common::SeekableReadStream *stream) {
+Audio::AudioStream *makeTwaStream(const Common::Path &name, Common::SeekableReadStream *stream) {
 	return new TwaAudioStream(name, stream);
 }
 
@@ -377,10 +379,10 @@ void SoundManager::stopSound() {
 	}
 }
 
-void SoundManager::playMod(const Common::String &file) {
+void SoundManager::playMod(const Common::Path &file) {
 	if (_musicOffFl)
 		return;
-	Common::String modFile = file;
+	Common::String modFile = file.baseName();
 
 	// HACK
 	if (modFile == "URAVOLGA" && (_vm->getPlatform() == Common::kPlatformWindows || _vm->getPlatform() == Common::kPlatformLinux))
@@ -403,21 +405,22 @@ void SoundManager::playMod(const Common::String &file) {
 		_modPlayingFl = false;
 	}
 
-	loadMusic(modFile);
+	loadMusic(file.getParent().appendComponent(modFile));
 	playMusic();
 	_modPlayingFl = true;
 }
 
-void SoundManager::loadMusic(const Common::String &file) {
+void SoundManager::loadMusic(const Common::Path &file) {
 	if (_music._active)
 		delMusic();
 
 	Common::File f;
 	if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
-		Common::String filename = Common::String::format("%s.MOD", file.c_str());
+		Common::Path filename(file);
+		filename.append(".MOD");
 
 		if (!f.open(filename))
-			error("Error opening file %s", filename.c_str());
+			error("Error opening file %s", filename.toString().c_str());
 
 		Modules::Module *module;
 		Audio::AudioStream *modStream = Audio::makeProtrackerStream(&f, 0, 44100, true, &module);
@@ -434,12 +437,13 @@ void SoundManager::loadMusic(const Common::String &file) {
 		_vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, modStream);
 
 	} else {
-		Common::String filename = Common::String::format("%s.TWA", file.c_str());
+		Common::Path filename(file);
+		filename.append(".TWA");
 
 		if (!f.open(filename))
-			error("Error opening file %s", filename.c_str());
+			error("Error opening file %s", filename.toString().c_str());
 
-		Audio::AudioStream *twaStream = makeTwaStream(file.c_str(), &f);
+		Audio::AudioStream *twaStream = makeTwaStream(file, &f);
 		_vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, twaStream);
 		f.close();
 	}
@@ -481,7 +485,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
 	int fileNumber;
 	bool breakFlag;
 	Common::String prefix;
-	Common::String filename;
+	Common::Path filename;
 	Common::File f;
 	size_t catPos, catLen;
 
@@ -524,10 +528,10 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
 			mappedFileNumber = fileNumber - 1;
 	}
 
-	filename = Common::String::format("%s%d", prefix.c_str(), mappedFileNumber);
+	filename = Common::Path(Common::String::format("%s%d", prefix.c_str(), mappedFileNumber));
 
 	bool fileFoundFl = false;
-	_vm->_fileIO->searchCat(filename + ".WAV", RES_VOI, fileFoundFl);
+	_vm->_fileIO->searchCat(filename.append(".WAV"), RES_VOI, fileFoundFl);
 	if (fileFoundFl) {
 		if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
 			filename = "ENG_VOI.RES";
@@ -551,7 +555,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
 		catPos = _vm->_fileIO->_catalogPos;
 		catLen = _vm->_fileIO->_catalogSize;
 	} else {
-		_vm->_fileIO->searchCat(filename + ".APC", RES_VOI, fileFoundFl);
+		_vm->_fileIO->searchCat(filename.append(".APC"), RES_VOI, fileFoundFl);
 		if (fileFoundFl) {
 			if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
 				filename = "ENG_VOI.RES";
@@ -575,7 +579,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
 			catPos = _vm->_fileIO->_catalogPos;
 			catLen = _vm->_fileIO->_catalogSize;
 		} else {
-			_vm->_fileIO->searchCat(filename + ".RAW", RES_VOI, fileFoundFl);
+			_vm->_fileIO->searchCat(filename.append(".RAW"), RES_VOI, fileFoundFl);
 			if (fileFoundFl) {
 				if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) {
 					filename = "ENG_VOI.RES";
@@ -599,12 +603,12 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) {
 				catPos = _vm->_fileIO->_catalogPos;
 				catLen = _vm->_fileIO->_catalogSize;
 			} else {
-				if (!f.exists(filename + ".WAV")) {
-					if (!f.exists(filename + ".APC"))
+				if (!f.exists(filename.append(".WAV"))) {
+					if (!f.exists(filename.append(".APC")))
 						return false;
-					filename = filename + ".APC";
+					filename.appendInPlace(".APC");
 				} else
-					filename = filename + ".WAV";
+					filename.appendInPlace(".WAV");
 
 				catPos = 0;
 				catLen = 0;
@@ -674,7 +678,7 @@ void SoundManager::removeSample(int soundIndex) {
 	_sound[soundIndex]._active = false;
 }
 
-void SoundManager::playSoundFile(const Common::String &file) {
+void SoundManager::playSoundFile(const Common::Path &file) {
 	if (_soundOffFl)
 		return;
 
@@ -682,7 +686,7 @@ void SoundManager::playSoundFile(const Common::String &file) {
 	// The BeOS and OS/2 versions don't play sound at this point.
 	// sound20 sounds very close to bruit2 from the linux and Win95 versions.
 	Common::File f;
-	Common::String filename;
+	Common::Path filename;
 	if (file == "bruit2.wav" && !f.exists(file))
 		filename = "sound20.wav";
 	else
@@ -694,7 +698,7 @@ void SoundManager::playSoundFile(const Common::String &file) {
 	playWav(1);
 }
 
-void SoundManager::directPlayWav(const Common::String &file) {
+void SoundManager::directPlayWav(const Common::Path &file) {
 	if (_soundOffFl)
 		return;
 
@@ -723,7 +727,7 @@ void SoundManager::setMODMusicVolume(int volume) {
 		_vm->_mixer->setChannelVolume(_musicHandle, volume * 255 / 16);
 }
 
-void SoundManager::loadSample(int wavIndex, const Common::String &file) {
+void SoundManager::loadSample(int wavIndex, const Common::Path &file) {
 	loadWavSample(wavIndex, file, false);
 	_sound[wavIndex]._active = true;
 }
@@ -798,7 +802,7 @@ bool SoundManager::removeWavSample(int wavIndex) {
 	return true;
 }
 
-bool SoundManager::loadVoice(const Common::String &filename, size_t fileOffset, size_t entryLength, SwavItem &item) {
+bool SoundManager::loadVoice(const Common::Path &filename, size_t fileOffset, size_t entryLength, SwavItem &item) {
 	Common::File f;
 	if (!f.open(filename)) {
 		// Fallback to APC...
@@ -806,7 +810,7 @@ bool SoundManager::loadVoice(const Common::String &filename, size_t fileOffset,
 			// The English demo doesn't include the speech file.
 			// This avoids it to crash when discussing with other characters
 			if (!_vm->getIsDemo())
-				error("Could not open %s for reading", filename.c_str());
+				error("Could not open %s for reading", filename.toString().c_str());
 			return false;
 		}
 	}
@@ -818,7 +822,7 @@ bool SoundManager::loadVoice(const Common::String &filename, size_t fileOffset,
 	return true;
 }
 
-void SoundManager::loadWavSample(int wavIndex, const Common::String &filename, bool freeSample) {
+void SoundManager::loadWavSample(int wavIndex, const Common::Path &filename, bool freeSample) {
 	if (_sWav[wavIndex]._active)
 		removeWavSample(wavIndex);
 
@@ -830,7 +834,7 @@ void SoundManager::loadWavSample(int wavIndex, const Common::String &filename, b
 	}
 }
 
-void SoundManager::loadWav(const Common::String &file, int wavIndex) {
+void SoundManager::loadWav(const Common::Path &file, int wavIndex) {
 	loadWavSample(wavIndex, file, true);
 }
 
@@ -931,14 +935,15 @@ Audio::RewindableAudioStream *SoundManager::makeSoundStream(Common::SeekableRead
 }
 
 // Blatant rip from gob engine. Hi DrMcCoy!
-Common::String SoundManager::setExtension(const Common::String &str, const Common::String &ext) {
+Common::Path SoundManager::setExtension(const Common::Path &str, const Common::String &ext) {
 	if (str.empty())
 		return str;
 
-	const char *dot = strrchr(str.c_str(), '.');
+	Common::String basename(str.baseName());
+	const char *dot = strrchr(basename.c_str(), '.');
 	if (dot)
-		return Common::String(str.c_str(), dot - str.c_str()) + ext;
+		return str.getParent().appendComponent(Common::String(basename.c_str(), dot - basename.c_str()) + ext);
 
-	return str + ext;
+	return str.append(ext);
 }
 } // End of namespace Hopkins
diff --git a/engines/hopkins/sound.h b/engines/hopkins/sound.h
index 6d85e120c86..a62d16ea1a7 100644
--- a/engines/hopkins/sound.h
+++ b/engines/hopkins/sound.h
@@ -88,21 +88,21 @@ private:
 	SoundItem _sound[SOUND_COUNT];
 	MusicItem _music;
 
-	void playMod(const Common::String &file);
-	void loadMusic(const Common::String &file);
+	void playMod(const Common::Path &file);
+	void loadMusic(const Common::Path &file);
 	void playMusic();
 	void stopMusic();
 	void delMusic();
 	bool checkVoiceStatus(int voiceIndex);
-	bool loadVoice(const Common::String &filename, size_t fileOffset, size_t entryLength, SwavItem &item);
+	bool loadVoice(const Common::Path &filename, size_t fileOffset, size_t entryLength, SwavItem &item);
 	void stopVoice(int voiceIndex);
 	void playVoice();
 	void delWav(int wavIndex);
 	void checkVoiceActivity();
-	Common::String setExtension(const Common::String &str, const Common::String &ext);
+	Common::Path setExtension(const Common::Path &str, const Common::String &ext);
 	Audio::RewindableAudioStream *makeSoundStream(Common::SeekableReadStream *stream);
 	bool removeWavSample(int wavIndex);
-	void loadWavSample(int wavIndex, const Common::String &filename, bool freeSample);
+	void loadWavSample(int wavIndex, const Common::Path &filename, bool freeSample);
 	void playWavSample(int voiceIndex, int wavIndex);
 
 public:
@@ -123,13 +123,13 @@ public:
 	void loadAnimSound();
 	void playAnimSound(int animFrame);
 
-	void loadSample(int wavIndex, const Common::String &file);
+	void loadSample(int wavIndex, const Common::Path &file);
 	void playSample(int wavIndex, int voiceMode = 9);
 	void removeSample(int soundIndex);
 
 	void checkSoundEnd();
 	void checkSounds();
-	void playSoundFile(const Common::String &file);
+	void playSoundFile(const Common::Path &file);
 	void playSound(int soundNumber);
 	void stopSound();
 
@@ -141,9 +141,9 @@ public:
 	void setMODSampleVolume();
 	void setMODVoiceVolume();
 
-	void loadWav(const Common::String &file, int wavIndex);
+	void loadWav(const Common::Path &file, int wavIndex);
 	void playWav(int wavIndex);
-	void directPlayWav(const Common::String &file2);
+	void directPlayWav(const Common::Path &file2);
 };
 
 } // End of namespace Hopkins
diff --git a/engines/hopkins/talk.cpp b/engines/hopkins/talk.cpp
index deb3343ae24..5cd3c882cb4 100644
--- a/engines/hopkins/talk.cpp
+++ b/engines/hopkins/talk.cpp
@@ -45,8 +45,8 @@ TalkManager::TalkManager(HopkinsEngine *vm) {
 	_paletteBufferIdx = 0;
 }
 
-void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename) {
-	Common::String spriteFilename;
+void TalkManager::startAnimatedCharacterDialogue(const Common::Path &filename) {
+	Common::Path spriteFilename;
 
 	_vm->_fontMan->hideText(5);
 	_vm->_fontMan->hideText(9);
@@ -153,7 +153,7 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename)
 	_vm->_graphicsMan->_scrollStatus = 0;
 }
 
-void TalkManager::startStaticCharacterDialogue(const Common::String &filename) {
+void TalkManager::startStaticCharacterDialogue(const Common::Path &filename) {
 	// TODO: The original disables the mouse cursor here
 	bool oldDisableInventFl = _vm->_globals->_disableInventFl;
 	_vm->_globals->_disableInventFl = true;
@@ -226,7 +226,7 @@ void TalkManager::startStaticCharacterDialogue(const Common::String &filename) {
 	_vm->_globals->_disableInventFl = oldDisableInventFl;
 }
 
-void TalkManager::getStringFromBuffer(int srcStart, Common::String &dest, const char *srcData) {
+void TalkManager::getStringFromBuffer(int srcStart, Common::Path &dest, const char *srcData) {
 	dest = Common::String(srcData + srcStart);
 }
 
@@ -507,20 +507,22 @@ void TalkManager::dialogEndTalk() {
 	}
 }
 
-int TalkManager::countBoxLines(int idx, const Common::String &file) {
+int TalkManager::countBoxLines(int idx, const Common::Path &file) {
 	_vm->_fontMan->_fontFixedWidth = 11;
 
 	// Build up the filename
 	Common::String filename;
-	Common::String dest;
-	filename = dest = file;
+	filename = file.baseName();
 	while (filename.lastChar() != '.')
 		filename.deleteLastChar();
 	filename += "IND";
 
+	Common::Path indname(file.getParent());
+	indname.joinInPlace(filename);
+
 	Common::File f;
-	if (!f.open(filename))
-		error("Could not open file - %s", filename.c_str());
+	if (!f.open(indname))
+		error("Could not open file - %s", indname.toString().c_str());
 	int filesize = f.size();
 	assert(filesize < 16188);
 
@@ -529,8 +531,8 @@ int TalkManager::countBoxLines(int idx, const Common::String &file) {
 		indexData[i] = f.readUint32LE();
 	f.close();
 
-	if (!f.open(dest))
-		error("Error opening file - %s", dest.c_str());
+	if (!f.open(file))
+		error("Error opening file - %s", file.toString().c_str());
 
 	f.seek(indexData[idx]);
 	byte *decryptBuf = _vm->_globals->allocMemory(2058);
@@ -968,7 +970,7 @@ void TalkManager::handleForestAnswser(int zone, int verb) {
 	}
 }
 
-void TalkManager::animateObject(const Common::String &filename) {
+void TalkManager::animateObject(const Common::Path &filename) {
 	_vm->_fontMan->hideText(5);
 	_vm->_fontMan->hideText(9);
 	_vm->_events->refreshScreenAndEvents();
@@ -990,9 +992,9 @@ void TalkManager::animateObject(const Common::String &filename) {
 		_characterBuffer = _vm->_fileIO->loadFile(filename);
 		_characterSize = _vm->_fileIO->fileSize(filename);
 	}
-	Common::String screenFilename;
-	Common::String spriteFilename;
-	Common::String curScreenFilename;
+	Common::Path screenFilename;
+	Common::Path spriteFilename;
+	Common::Path curScreenFilename;
 	getStringFromBuffer(40, spriteFilename, (const char *)_characterBuffer);
 	getStringFromBuffer(0, screenFilename, (const char *)_characterBuffer);
 	getStringFromBuffer(20, curScreenFilename, (const char *)_characterBuffer);
diff --git a/engines/hopkins/talk.h b/engines/hopkins/talk.h
index 47df59bb1b7..64862ff1f53 100644
--- a/engines/hopkins/talk.h
+++ b/engines/hopkins/talk.h
@@ -23,7 +23,7 @@
 #define HOPKINS_TALK_H
 
 #include "common/scummsys.h"
-#include "common/str.h"
+#include "common/path.h"
 
 namespace Hopkins {
 
@@ -35,8 +35,8 @@ class TalkManager {
 private:
 	HopkinsEngine *_vm;
 
-	Common::String _questionsFilename;
-	Common::String _answersFilename;
+	Common::Path _questionsFilename;
+	Common::Path _answersFilename;
 	byte *_characterBuffer;
 	byte *_characterPalette;
 	size_t _characterSize;
@@ -44,7 +44,7 @@ private:
 	int _dialogueMesgId3, _dialogueMesgId4;
 	int _paletteBufferIdx;
 
-	void getStringFromBuffer(int srcStart, Common::String &dest, const char *srcData);
+	void getStringFromBuffer(int srcStart, Common::Path &dest, const char *srcData);
 	int dialogQuestion(bool animatedFl);
 	int dialogAnswer(int idx, bool animatedFl);
 	void searchCharacterPalette(int startIdx, bool dark);
@@ -55,7 +55,7 @@ private:
 	void initCharacterAnim();
 	void clearCharacterAnim();
 	bool searchCharacterAnim(int idx, const byte *bufPerso, int animId, int bufferSize);
-	int countBoxLines(int idx, const Common::String &file);
+	int countBoxLines(int idx, const Common::Path &file);
 	void dialogAnim();
 	void displayBobDialogAnim(int idx);
 
@@ -65,9 +65,9 @@ public:
 
 	TalkManager(HopkinsEngine *vm);
 
-	void startStaticCharacterDialogue(const Common::String &filename);
-	void startAnimatedCharacterDialogue(const Common::String &filename);
-	void animateObject(const Common::String &filename);
+	void startStaticCharacterDialogue(const Common::Path &filename);
+	void startAnimatedCharacterDialogue(const Common::Path &filename);
+	void animateObject(const Common::Path &filename);
 	void handleAnswer(int zone, int verb);
 	void handleForestAnswser(int zone, int verb);
 };


Commit: 69665f680322978d8bc8997f330c0e2e2ca88442
    https://github.com/scummvm/scummvm/commit/69665f680322978d8bc8997f330c0e2e2ca88442
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
HPL1: Migrate engine to Path

Changed paths:
    engines/hpl1/engine/graphics/bitmap2D.cpp
    engines/hpl1/engine/impl/OpenALSoundData.cpp
    engines/hpl1/engine/impl/SqScript.cpp
    engines/hpl1/engine/impl/tinyXML/tinyxml.cpp
    engines/hpl1/engine/resources/ConfigFile.cpp
    engines/hpl1/engine/resources/low_level_resources.cpp


diff --git a/engines/hpl1/engine/graphics/bitmap2D.cpp b/engines/hpl1/engine/graphics/bitmap2D.cpp
index da8c2ce8a0e..44324da224e 100644
--- a/engines/hpl1/engine/graphics/bitmap2D.cpp
+++ b/engines/hpl1/engine/graphics/bitmap2D.cpp
@@ -33,7 +33,7 @@ namespace hpl {
 
 static Image::ImageDecoder *loadImage(const tString &filepath, Image::ImageDecoder *decoder) {
 	Common::File imgFile;
-	if (!imgFile.open(filepath))
+	if (!imgFile.open(Common::Path(filepath)))
 		error("Could not open file: %s", filepath.c_str());
 	if (!decoder->loadStream(imgFile))
 		error("Could not load image at %s", filepath.c_str());
diff --git a/engines/hpl1/engine/impl/OpenALSoundData.cpp b/engines/hpl1/engine/impl/OpenALSoundData.cpp
index 828754bcacb..929d2328dbe 100644
--- a/engines/hpl1/engine/impl/OpenALSoundData.cpp
+++ b/engines/hpl1/engine/impl/OpenALSoundData.cpp
@@ -79,7 +79,7 @@ bool cOpenALSoundData::CreateFromFile(const tString &filename) {
 		Hpl1::logWarning(Hpl1::kDebugAudio, "overriding previous sound data with new audio at '%s'\n", filename.c_str());
 	}
 	Common::File file;
-	if (!file.open(filename)) {
+	if (!file.open(Common::Path(filename))) {
 		Hpl1::logWarning(Hpl1::kDebugFilePath | Hpl1::kDebugResourceLoading | Hpl1::kDebugAudio, "Audio file '%s' could not be opened\n", filename.c_str());
 		return false;
 	}
diff --git a/engines/hpl1/engine/impl/SqScript.cpp b/engines/hpl1/engine/impl/SqScript.cpp
index c42333a40b1..058f86ecd0b 100644
--- a/engines/hpl1/engine/impl/SqScript.cpp
+++ b/engines/hpl1/engine/impl/SqScript.cpp
@@ -126,7 +126,7 @@ bool cSqScript::Run(int alHandle) {
 
 char *cSqScript::LoadCharBuffer(const tString &asFileName, int &alLength) {
 	Common::File file;
-	file.open(asFileName);
+	file.open(Common::Path(asFileName));
 	if (!file.isOpen()) {
 		debugCN(Hpl1::kDebugLevelError, Hpl1::kDebugFilePath,
 				"script file at %s could not be opened", asFileName.c_str());
diff --git a/engines/hpl1/engine/impl/tinyXML/tinyxml.cpp b/engines/hpl1/engine/impl/tinyXML/tinyxml.cpp
index 1b773e19b48..b5e4223d500 100644
--- a/engines/hpl1/engine/impl/tinyXML/tinyxml.cpp
+++ b/engines/hpl1/engine/impl/tinyXML/tinyxml.cpp
@@ -732,7 +732,7 @@ bool TiXmlDocument::LoadFile(const char *filename, TiXmlEncoding encoding) {
 
 	// reading in binary mode so that tinyxml can normalize the EOL
 	Common::File file;
-	file.open(value);
+	file.open(Common::Path(value));
 
 	if (file.isOpen()) {
 		bool result = LoadFile(file, encoding);
diff --git a/engines/hpl1/engine/resources/ConfigFile.cpp b/engines/hpl1/engine/resources/ConfigFile.cpp
index b5d0bfc1291..8629b7cba65 100644
--- a/engines/hpl1/engine/resources/ConfigFile.cpp
+++ b/engines/hpl1/engine/resources/ConfigFile.cpp
@@ -61,7 +61,7 @@ cConfigFile::~cConfigFile() {
 
 bool cConfigFile::Load() {
 	Common::File cf;
-	if (!cf.open(Common::String(msFile))) {
+	if (!cf.open(Common::Path(Common::String(msFile)))) {
 		Hpl1::logWarning(Hpl1::kDebugFilePath, "file %S could not be opened", msFile.c_str());
 		return false;
 	}
diff --git a/engines/hpl1/engine/resources/low_level_resources.cpp b/engines/hpl1/engine/resources/low_level_resources.cpp
index d5a9ea5d925..0e07c7d0c74 100644
--- a/engines/hpl1/engine/resources/low_level_resources.cpp
+++ b/engines/hpl1/engine/resources/low_level_resources.cpp
@@ -64,10 +64,10 @@ void LowLevelResources::addVideoLoaders(cVideoManager *vm) {
 }
 
 void LowLevelResources::findFilesInDir(tStringList &alstStrings, tString asDir, tString asMask) {
-	Common::String pattern = asDir + '/' + asMask;
+	Common::Path pattern(asDir + '/' + asMask);
 	Common::ArchiveMemberList ls;
 	if (SearchMan.listMatchingMembers(ls, pattern) == 0)
-		Hpl1::logWarning(Hpl1::kDebugFilePath, "no files matching pattern %s were found", pattern.c_str());
+		Hpl1::logWarning(Hpl1::kDebugFilePath, "no files matching pattern %s were found", pattern.toString().c_str());
 
 	for (auto &f : ls)
 		alstStrings.push_back(f->getName());


Commit: a1a5407c64c6d2736ddf3e4718d08967db9f68e6
    https://github.com/scummvm/scummvm/commit/a1a5407c64c6d2736ddf3e4718d08967db9f68e6
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
HUGO: Migrate engine to Path

Changed paths:
    engines/hugo/file.cpp
    engines/hugo/file_v1d.cpp
    engines/hugo/hugo.h
    engines/hugo/schedule.cpp


diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp
index 9c9040584c2..86d1cfdd2ce 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -165,12 +165,12 @@ void FileManager::readImage(const int objNum, Object *objPtr) {
 
 		_objectsArchive.seek(objBlock.objOffset, SEEK_SET);
 	} else {
-		Common::String buf;
-		buf = _vm->_picDir + Common::String(_vm->_text->getNoun(objPtr->_nounIndex, 0)) + ".PIX";
+		Common::Path buf;
+		buf = _vm->_picDir.appendComponent(Common::String(_vm->_text->getNoun(objPtr->_nounIndex, 0)) + ".PIX");
 		if (!_objectsArchive.open(buf)) {
 			buf = Common::String(_vm->_text->getNoun(objPtr->_nounIndex, 0)) + ".PIX";
 			if (!_objectsArchive.open(buf))
-				error("File not found: %s", buf.c_str());
+				error("File not found: %s", buf.toString().c_str());
 		}
 	}
 
diff --git a/engines/hugo/file_v1d.cpp b/engines/hugo/file_v1d.cpp
index d63eb8553fe..3ba7874dfab 100644
--- a/engines/hugo/file_v1d.cpp
+++ b/engines/hugo/file_v1d.cpp
@@ -58,16 +58,17 @@ void FileManager_v1d::readOverlay(const int screenNum, ImagePtr image, const Ovl
 	debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum);
 
 	const char *ovlExt[] = {".b", ".o", ".ob"};
-	Common::String buf = Common::String(_vm->_text->getScreenNames(screenNum)) + Common::String(ovlExt[overlayType]);
+	Common::Path buf(_vm->_text->getScreenNames(screenNum));
+	buf.appendInPlace(ovlExt[overlayType]);
 
 	if (!Common::File::exists(buf)) {
 		memset(image, 0, kOvlSize);
-		warning("File not found: %s", buf.c_str());
+		warning("File not found: %s", buf.toString().c_str());
 		return;
 	}
 
 	if (!_sceneryArchive1.open(buf))
-		error("File not found: %s", buf.c_str());
+		error("File not found: %s", buf.toString().c_str());
 
 	ImagePtr tmpImage = image;                      // temp ptr to overlay file
 
@@ -81,10 +82,10 @@ void FileManager_v1d::readOverlay(const int screenNum, ImagePtr image, const Ovl
 void FileManager_v1d::readBackground(const int screenIndex) {
 	debugC(1, kDebugFile, "readBackground(%d)", screenIndex);
 
-	Common::String buf;
-	buf = Common::String(_vm->_text->getScreenNames(screenIndex)) + ".ART";
+	Common::Path buf(_vm->_text->getScreenNames(screenIndex));
+	buf.appendInPlace(".ART");
 	if (!_sceneryArchive1.open(buf))
-		error("File not found: %s", buf.c_str());
+		error("File not found: %s", buf.toString().c_str());
 	// Read the image into dummy seq and static dib_a
 	Seq *dummySeq;                                // Image sequence structure for Read_pcx
 	dummySeq = readPCX(_sceneryArchive1, nullptr, _vm->_screen->getFrontBuffer(), true, _vm->_text->getScreenNames(screenIndex));
diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h
index d9863086c4d..86cfcc5bd57 100644
--- a/engines/hugo/hugo.h
+++ b/engines/hugo/hugo.h
@@ -219,7 +219,7 @@ public:
 	Common::RandomSource *_rnd;
 
 	const char *_episode;
-	Common::String _picDir;
+	Common::Path _picDir;
 
 	Command _statusLine;
 	Command _scoreLine;
diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp
index 69257ef755d..0b5c5ec4fac 100644
--- a/engines/hugo/schedule.cpp
+++ b/engines/hugo/schedule.cpp
@@ -178,10 +178,10 @@ void Scheduler::newScreen(const int screenIndex) {
 
 	// Make sure the background file exists!
 	if (!_vm->isPacked()) {
-		Common::String filename = Common::String(_vm->_text->getScreenNames(screenIndex));
-		if (!Common::File::exists(_vm->_picDir + filename + ".PCX") &&
-			!Common::File::exists(filename + ".ART")) {
-				error("Unable to find background file for %s", filename.c_str());
+		Common::Path filename = _vm->_picDir.appendComponent(Common::String(_vm->_text->getScreenNames(screenIndex)));
+		if (!Common::File::exists(filename.append(".PCX")) &&
+			!Common::File::exists(filename.append(".ART"))) {
+				error("Unable to find background file for %s", filename.toString().c_str());
 			return;
 		}
 	}


Commit: 27396734e9ca7453eae5f220245b724a8adf257d
    https://github.com/scummvm/scummvm/commit/27396734e9ca7453eae5f220245b724a8adf257d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
HYPNO: Migrate engine to Path

Changed paths:
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/libfile.cpp
    engines/hypno/libfile.h
    engines/hypno/scene.cpp


diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 4746d60668b..23d652fd1d7 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -115,12 +115,12 @@ HypnoEngine::~HypnoEngine() {
 }
 
 void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
-	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
+	SearchMan.addDirectory(gamePath, 0, 10);
 }
 
-LibFile *HypnoEngine::loadLib(const Filename &prefix, const Filename &filename, bool encrypted) {
+LibFile *HypnoEngine::loadLib(const Common::Path &prefix, const Common::Path &filename, bool encrypted) {
 	LibFile *lib = new LibFile();
-	SearchMan.add(filename, (Common::Archive *)lib, 0, true);
+	SearchMan.add(filename.toString(), (Common::Archive *)lib, 0, true);
 	if (!lib->open(prefix, filename, encrypted)) {
 		return nullptr;
 	}
@@ -338,16 +338,16 @@ void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transpar
 
 Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, byte **palette) {
 	Common::File *file = new Common::File();
-	Common::String path = convertPath(name);
+	Common::Path path = convertPath(name);
 	if (!_prefixDir.empty())
-		path = _prefixDir + "/" + path;
+		path = _prefixDir.join(path);
 
 	if (!file->open(path))
-		error("unable to find video file %s", path.c_str());
+		error("unable to find video file %s", path.toString().c_str());
 
 	HypnoSmackerDecoder vd;
 	if (!vd.loadStream(file))
-		error("unable to load video %s", path.c_str());
+		error("unable to load video %s", path.toString().c_str());
 
 	for (int f = 0; f < n; f++)
 		vd.decodeNextFrame();
@@ -366,16 +366,16 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 Frames HypnoEngine::decodeFrames(const Common::String &name) {
 	Frames frames;
 	Common::File *file = new Common::File();
-	Common::String path = convertPath(name);
+	Common::Path path = convertPath(name);
 	if (!_prefixDir.empty())
-		path = _prefixDir + "/" + path;
+		path = _prefixDir.join(path);
 
 	if (!file->open(path))
-		error("unable to find video file %s", path.c_str());
+		error("unable to find video file %s", path.toString().c_str());
 
 	HypnoSmackerDecoder vd;
 	if (!vd.loadStream(file))
-		error("unable to load video %s", path.c_str());
+		error("unable to load video %s", path.toString().c_str());
 
 	const Graphics::Surface *frame = nullptr;
 	Graphics::Surface *rframe = nullptr;
@@ -424,14 +424,14 @@ void HypnoEngine::changeScreenMode(const Common::String &mode) {
 
 void HypnoEngine::loadPalette(const Common::String &fname) {
 	Common::File file;
-	Common::String path = convertPath(fname);
+	Common::Path path = convertPath(fname);
 	if (!_prefixDir.empty())
-		path = _prefixDir + "/" + path;
+		path = _prefixDir.join(path);
 
 	if (!file.open(path))
-		error("unable to find palette file %s", path.c_str());
+		error("unable to find palette file %s", path.toString().c_str());
 
-	debugC(1, kHypnoDebugMedia, "Loading palette from %s", path.c_str());
+	debugC(1, kHypnoDebugMedia, "Loading palette from %s", path.toString().c_str());
 	byte *videoPalette = (byte *)malloc(file.size());
 	file.read(videoPalette, file.size());
 	g_system->getPaletteManager()->setPalette(videoPalette + 8, 0, 256);
@@ -510,12 +510,12 @@ void HypnoEngine::drawScreen() {
 void HypnoEngine::playVideo(MVideo &video) {
 	debugC(1, kHypnoDebugMedia, "%s(%s)", __FUNCTION__, video.path.c_str());
 	Common::File *file = new Common::File();
-	Common::String path = convertPath(video.path);
+	Common::Path path = convertPath(video.path);
 	if (!_prefixDir.empty())
-		path = _prefixDir + "/" + path;
+		path = _prefixDir.join(path);
 
 	if (!file->open(path))
-		error("unable to find video file %s", path.c_str());
+		error("unable to find video file %s", path.toString().c_str());
 
 	if (video.decoder != nullptr) {
 		debugC(1, kHypnoDebugMedia, "Restarting %s!!!!", video.path.c_str());
@@ -526,7 +526,7 @@ void HypnoEngine::playVideo(MVideo &video) {
 	video.decoder = new HypnoSmackerDecoder();
 
 	if (!video.decoder->loadStream(file))
-		error("unable to load video %s", path.c_str());
+		error("unable to load video %s", path.toString().c_str());
 
 	debugC(1, kHypnoDebugMedia, "audio track count: %d", video.decoder->getAudioTrackCount());
 	video.decoder->start();
@@ -545,7 +545,7 @@ void HypnoEngine::skipVideo(MVideo &video) {
 
 void HypnoEngine::playSound(const Common::String &filename, uint32 loops, uint32 sampleRate, bool stereo) {
 	debugC(1, kHypnoDebugMedia, "%s(%s, %d, %d)", __FUNCTION__, filename.c_str(), loops, sampleRate);
-	Common::String name = convertPath(filename);
+	Common::Path name = convertPath(filename);
 
 	Audio::LoopingAudioStream *stream = nullptr;
 	Common::File *file = new Common::File();
@@ -564,12 +564,12 @@ void HypnoEngine::playSound(const Common::String &filename, uint32 loops, uint32
 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
 	} else {
 		if (!_prefixDir.empty())
-			name = _prefixDir + "/" + name;
+			name = _prefixDir.join(name);
 		if (file->open(name)) {
 			stream = new Audio::LoopingAudioStream(Audio::makeRawStream(file, sampleRate, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
 			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
 		} else
-			debugC(1, kHypnoDebugMedia, "%s not found!", name.c_str());
+			debugC(1, kHypnoDebugMedia, "%s not found!", name.toString().c_str());
 	}
 }
 
@@ -581,7 +581,7 @@ void HypnoEngine::stopSound() {
 
 // Path handling
 
-Common::String HypnoEngine::convertPath(const Common::String &name) {
+Common::Path HypnoEngine::convertPath(const Common::String &name) {
 	Common::String path(name);
 	Common::String s1("\\");
 	Common::String s2("/");
@@ -596,7 +596,7 @@ Common::String HypnoEngine::convertPath(const Common::String &name) {
 	Common::replace(path, s1, s2);
 
 	path.toLowercase();
-	return path;
+	return Common::Path(path);
 }
 
 // Timers
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 1b0c3548828..75219c10d57 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -132,7 +132,7 @@ public:
 	void loadSceneLevel(const Common::String &current, const Common::String &next, const Common::String &prefix);
 	void loadSceneLevel(const char *buf, const Common::String &name, const Common::String &next, const Common::String &prefix);
 
-	LibFile *loadLib(const Filename &prefix, const Filename &filename, bool encrypted);
+	LibFile *loadLib(const Common::Path &prefix, const Common::Path &filename, bool encrypted);
 
 	// User input
 	void clickedHotspot(Common::Point);
@@ -149,8 +149,8 @@ public:
 	bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return (isDemo() ? false : true); }
 	Common::String _checkpoint;
 
-	Common::String _prefixDir;
-	Common::String convertPath(const Common::String &);
+	Common::Path _prefixDir;
+	Common::Path convertPath(const Common::String &);
 	void playVideo(MVideo &video);
 	void skipVideo(MVideo &video);
 
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 5e1e7f104ed..931bed8cb39 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -33,7 +33,7 @@ LibFile::~LibFile() {
 	close();
 }
 
-bool LibFile::open(const Common::String &prefix, const Common::String &filename, bool encrypted) {
+bool LibFile::open(const Common::Path &prefix, const Common::Path &filename, bool encrypted) {
 	close();
 
 	_prefix = prefix;
@@ -41,7 +41,7 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename,
 
 	_libfile = new Common::File();
 	if (!_libfile->open(filename)) {
-		warning("Failed to open %s", filename.c_str());
+		warning("Failed to open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	uint32 offset = 0;
@@ -53,17 +53,18 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename,
 		_libfile->seek(offset);
 		debugC(1, kHypnoDebugParser, "parsing at offset %d with size %li", offset, long(_libfile->size()));
 		while (true) {
-			f.name = "";
+			Common::String fname;
 			for (uint32 i = 0; i < 12; i++) {
 				b = _libfile->readByte();
 				if (b != 0x96 && b != 0x0)
-					f.name += tolower(char(b));
+					fname += tolower(char(b));
 			}
 
-			if (!Common::isAlnum(*f.name.c_str()))
+			if (!Common::isAlnum(*fname.c_str()))
 				break;
 
-			debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
+			debugC(1, kHypnoDebugParser, "file: %s", fname.c_str());
+			f.name = Common::Path(fname);
 			f.start = start = _libfile->readUint32LE();
 			f.size = size = _libfile->readUint32LE();
 			if (size == 0)
@@ -81,9 +82,8 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename,
 }
 
 const FileEntry *LibFile::getEntry(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it) {
-		if (((_prefix + it->name).equalsIgnoreCase(name)) || it->name.equalsIgnoreCase(name))
+		if (((_prefix.join(it->name)).equalsIgnoreCase(path)) || it->name.equalsIgnoreCase(path))
 			return it;
 	}
 
@@ -96,8 +96,7 @@ void LibFile::close() {
 }
 
 bool LibFile::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return getEntry(name) != nullptr;
+	return getEntry(path) != nullptr;
 }
 
 int LibFile::listMembers(Common::ArchiveMemberList &list) const {
@@ -109,24 +108,23 @@ int LibFile::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr LibFile::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *LibFile::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	const FileEntry *entry = getEntry(name);
+	const FileEntry *entry = getEntry(path);
 	if (!entry)
 		return nullptr;
 
 	byte *data = (byte *)malloc(entry->size);
 	if (!data) {
-		warning("Not enough memory to load archive entry %s", name.c_str());
+		warning("Not enough memory to load archive entry %s", path.toString().c_str());
 		return nullptr;
 	}
 
 	_libfile->seek(entry->start);
 	_libfile->read(data, entry->size);
+	Common::String name = path.baseName();
 	name.toLowercase(); // just in case
 
 	if (name.hasSuffix(".raw")) {
diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
index 87ff82479d7..6db064db11c 100644
--- a/engines/hypno/libfile.h
+++ b/engines/hypno/libfile.h
@@ -31,7 +31,7 @@
 namespace Hypno {
 
 typedef struct FileEntry {
-	Common::String name;
+	Common::Path name;
 	uint32 start;
 	uint32 size;
 } FileEntry;
@@ -41,7 +41,7 @@ public:
 	LibFile();
 	~LibFile() override;
 
-	bool open(const Common::String &prefix, const Common::String &filename, bool encrypted);
+	bool open(const Common::Path &prefix, const Common::Path &filename, bool encrypted);
 	void close();
 
 	// Common::Archive API implementation
@@ -53,7 +53,7 @@ public:
 private:
 	bool _encrypted;
 	Common::File *_libfile;
-	Common::String _prefix;
+	Common::Path _prefix;
 	Common::Array<FileEntry> _fileEntries;
 	const FileEntry *getEntry(const Common::Path &path) const;
 };
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 2a45c8529a6..00740e37455 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -60,11 +60,11 @@ const char *sceneVariables[] = {
 
 void HypnoEngine::loadSceneLevel(const Common::String &current, const Common::String &next, const Common::String &prefix) {
 	debugC(1, kHypnoDebugParser, "Parsing %s", current.c_str());
-	Common::String name = convertPath(current);
+	Common::Path name = convertPath(current);
 
 	Common::File test;
-	if (!test.open(name.c_str()))
-		error("Failed to open %s", name.c_str());
+	if (!test.open(name))
+		error("Failed to open %s", name.toString().c_str());
 
 	const uint32 fileSize = test.size();
 	char *buf = (char *)malloc(fileSize + 1);
@@ -77,7 +77,7 @@ void HypnoEngine::loadSceneLevel(const Common::String &current, const Common::St
 	level->prefix = prefix;
 	level->levelIfWin = next;
 	level->hots = *g_parsedHots;
-	_levels[name] = level;
+	_levels[name.toString('/')] = level;
 	free(buf);
 }
 


Commit: d5736f602e08b93e8753dfa0fdab58d83a103eee
    https://github.com/scummvm/scummvm/commit/d5736f602e08b93e8753dfa0fdab58d83a103eee
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ICB: Migrate engine to Path

Changed paths:
    engines/icb/configfile.cpp
    engines/icb/configfile.h


diff --git a/engines/icb/configfile.cpp b/engines/icb/configfile.cpp
index 0f2540d8925..0a73306a40f 100644
--- a/engines/icb/configfile.cpp
+++ b/engines/icb/configfile.cpp
@@ -26,6 +26,7 @@
 
 #include "engines/icb/configfile.h"
 
+#include "common/path.h"
 #include "common/textconsole.h"
 #include "common/formats/ini-file.h"
 
@@ -33,10 +34,10 @@ namespace ICB {
 
 ConfigFile::ConfigFile() {}
 
-void ConfigFile::readFile(const Common::String &filename) {
+void ConfigFile::readFile(const char *filename) {
 	Common::INIFile file;
-	if (!file.loadFromFile(filename)) {
-		error("Opening file '%s' failed'", filename.c_str());
+	if (!file.loadFromFile(Common::Path(filename, '/'))) {
+		error("Opening file '%s' failed'", filename);
 		return;
 	}
 
diff --git a/engines/icb/configfile.h b/engines/icb/configfile.h
index 5507f5cbf90..dbb4862a964 100644
--- a/engines/icb/configfile.h
+++ b/engines/icb/configfile.h
@@ -41,7 +41,7 @@ public:
 	Common::String readSetting(const Common::String &section, const Common::String &key, const Common::String &defaultValue) const;
 	int32 readIntSetting(const Common::String &section, const Common::String &key, int32 defaultValue) const;
 
-	void readFile(const Common::String &filename);
+	void readFile(const char *filename);
 };
 
 } // End of namespace ICB


Commit: 0ab0721905c1c2b02abd8eb72ecb691a2072f233
    https://github.com/scummvm/scummvm/commit/0ab0721905c1c2b02abd8eb72ecb691a2072f233
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ILLUSIONS: Migrate engine to Path

Changed paths:
    engines/illusions/bbdou/bbdou_videoplayer.cpp
    engines/illusions/bbdou/illusions_bbdou.cpp
    engines/illusions/duckman/duckman_videoplayer.cpp
    engines/illusions/duckman/illusions_duckman.cpp
    engines/illusions/fileresourcereader.cpp
    engines/illusions/fileresourcereader.h
    engines/illusions/sound.cpp


diff --git a/engines/illusions/bbdou/bbdou_videoplayer.cpp b/engines/illusions/bbdou/bbdou_videoplayer.cpp
index b2ca3de2501..6e5790b382c 100644
--- a/engines/illusions/bbdou/bbdou_videoplayer.cpp
+++ b/engines/illusions/bbdou/bbdou_videoplayer.cpp
@@ -47,12 +47,12 @@ void BBDOUVideoPlayer::start(uint32 videoId, uint32 objectId, uint32 priority, u
 	Control *videoControl = _vm->_dict->getObjectControl(objectId);
 	videoControl->_flags |= 0x0008;
 	_vm->_input->discardAllEvents();
-	Common::String filename = Common::String::format("%08x.avi", videoId);
+	Common::Path filename(Common::String::format("%08x.avi", videoId));
 	_videoDecoder = new Video::AVIDecoder();
 	if (!_videoDecoder->loadFile(filename)) {
 		delete _videoDecoder;
 		_videoDecoder = nullptr;
-		warning("Unable to open video %s", filename.c_str());
+		warning("Unable to open video %s", filename.toString().c_str());
 		notifyCallingThread();
 		return;
 	}
diff --git a/engines/illusions/bbdou/illusions_bbdou.cpp b/engines/illusions/bbdou/illusions_bbdou.cpp
index 8ad9f48e569..772928bd500 100644
--- a/engines/illusions/bbdou/illusions_bbdou.cpp
+++ b/engines/illusions/bbdou/illusions_bbdou.cpp
@@ -132,7 +132,7 @@ IllusionsEngine_BBDOU::IllusionsEngine_BBDOU(OSystem *syst, const IllusionsGameD
 Common::Error IllusionsEngine_BBDOU::run() {
 
 	// Init search paths
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "music");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "resource");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "resrem");
diff --git a/engines/illusions/duckman/duckman_videoplayer.cpp b/engines/illusions/duckman/duckman_videoplayer.cpp
index 232855bfbcc..092447f50c0 100644
--- a/engines/illusions/duckman/duckman_videoplayer.cpp
+++ b/engines/illusions/duckman/duckman_videoplayer.cpp
@@ -41,12 +41,12 @@ void DuckmanVideoPlayer::start(uint32 videoId, uint32 callingThreadId) {
 	debug(0, "DuckmanVideoPlayer::play(%08X, %08X)", videoId, callingThreadId);
 	_callingThreadId = callingThreadId;
 	_vm->_input->discardAllEvents();
-	Common::String filename = Common::String::format("%08x.avi", videoId);
+	Common::Path filename(Common::String::format("%08x.avi", videoId));
 	_videoDecoder = new Video::AVIDecoder();
 	if (!_videoDecoder->loadFile(filename)) {
 		delete _videoDecoder;
 		_videoDecoder = nullptr;
-		warning("Unable to open video %s", filename.c_str());
+		warning("Unable to open video %s", filename.toString().c_str());
 		return;
 	}
 	_videoDecoder->start();
diff --git a/engines/illusions/duckman/illusions_duckman.cpp b/engines/illusions/duckman/illusions_duckman.cpp
index 41b2f9e5631..10f89a327d5 100644
--- a/engines/illusions/duckman/illusions_duckman.cpp
+++ b/engines/illusions/duckman/illusions_duckman.cpp
@@ -82,7 +82,7 @@ IllusionsEngine_Duckman::IllusionsEngine_Duckman(OSystem *syst, const IllusionsG
 Common::Error IllusionsEngine_Duckman::run() {
 
 	// Init search paths
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "music");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "sfx", 0, 2);
 	SearchMan.addSubDirectoryMatching(gameDataDir, "video");
diff --git a/engines/illusions/fileresourcereader.cpp b/engines/illusions/fileresourcereader.cpp
index f3d772fa1e5..15c6c446859 100644
--- a/engines/illusions/fileresourcereader.cpp
+++ b/engines/illusions/fileresourcereader.cpp
@@ -30,19 +30,19 @@ namespace Illusions {
 byte *ResourceReaderFileReader::readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) {
 	debug("ResourceReaderFileReader::readResource(%08X, %08X)", sceneId, resId);
 
-	Common::String filename = buildResourceFilename(resId);
+	Common::Path filename = buildResourceFilename(resId);
 	Common::File fd;
 	if (!fd.open(filename))
-		error("Resource::loadData() Could not open %s for reading", filename.c_str());
+		error("Resource::loadData() Could not open %s for reading", filename.toString().c_str());
 	dataSize = fd.size();
 	byte *data = (byte*)malloc(dataSize);
 	fd.read(data, dataSize);
 	return data;
 }
 
-Common::String ResourceReaderFileReader::buildResourceFilename(uint32 resId) {
+Common::Path ResourceReaderFileReader::buildResourceFilename(uint32 resId) {
 	const char *ext = getResourceExtension(resId);
-	return Common::String::format("%08X%s", resId, ext);
+	return Common::Path(Common::String::format("%08X%s", resId, ext));
 }
 
 const char *ResourceReaderFileReader::getResourceExtension(uint32 resId) {
diff --git a/engines/illusions/fileresourcereader.h b/engines/illusions/fileresourcereader.h
index b373880237b..17a49c82abd 100644
--- a/engines/illusions/fileresourcereader.h
+++ b/engines/illusions/fileresourcereader.h
@@ -31,7 +31,7 @@ class ResourceReaderFileReader : public BaseResourceReader {
 public:
 	byte *readResource(uint32 sceneId, uint32 resId, uint32 &dataSize) override;
 protected:
-	Common::String buildResourceFilename(uint32 resId);
+	Common::Path buildResourceFilename(uint32 resId);
 	const char *getResourceExtension(uint32 resId);
 };
 
diff --git a/engines/illusions/sound.cpp b/engines/illusions/sound.cpp
index 4fa1db60a90..fb3a1219bc9 100644
--- a/engines/illusions/sound.cpp
+++ b/engines/illusions/sound.cpp
@@ -51,15 +51,15 @@ void MusicPlayer::play(uint32 musicId, bool looping, int16 volume, int16 pan) {
 		} else {
 			_flags &= ~8;
 		}
-		Common::String filename = Common::String::format("%08x.wav", _musicId);
+		Common::Path filename(Common::String::format("%08x.wav", _musicId));
 		Common::File *fd = new Common::File();
 		if (!fd->open(filename)) {
 			delete fd;
-			error("MusicPlayer::play() Could not open %s", filename.c_str());
+			error("MusicPlayer::play() Could not open %s", filename.toString().c_str());
 		}
 		Audio::SeekableAudioStream *wavStream = Audio::makeWAVStream(fd, DisposeAfterUse::YES);
 		if (wavStream == nullptr) {
-			error("MusicPlayer::play() Could not load %s", filename.c_str());
+			error("MusicPlayer::play() Could not load %s", filename.toString().c_str());
 		}
 		Audio::AudioStream *audioStream = Audio::makeLoopingAudioStream(wavStream, looping ? 0 : 1);
 		g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, audioStream, -1, volume, pan);
@@ -158,12 +158,12 @@ void MidiPlayer::stop() {
 void MidiPlayer::sysMidiPlay(uint32 musicId) {
 	Common::StackLock lock(_mutex);
 
-	Common::String filename = Common::String::format("%08x.mid", musicId);
-	debug(0, "MidiPlayer::sysMidiPlay() %s", filename.c_str());
+	Common::Path filename(Common::String::format("%08x.mid", musicId));
+	debug(0, "MidiPlayer::sysMidiPlay() %s", filename.toString().c_str());
 
 	Common::File fd;
 	if (!fd.open(filename)) {
-		error("MidiPlayer::sysMidiPlay() Could not open %s", filename.c_str());
+		error("MidiPlayer::sysMidiPlay() Could not open %s", filename.toString().c_str());
 	}
 
 	_dataSize = fd.size();
@@ -259,15 +259,15 @@ void VoicePlayer::stopCueing() {
 }
 
 void VoicePlayer::start(int16 volume, int16 pan) {
-	Common::String filename = Common::String::format("%s.wav", _voiceName.c_str());
+	Common::Path filename(Common::String::format("%s.wav", _voiceName.c_str()));
 	Common::File *fd = new Common::File();
 	if (!fd->open(filename)) {
 		delete fd;
-		error("VoicePlayer::start() Could not open %s", filename.c_str());
+		error("VoicePlayer::start() Could not open %s", filename.toString().c_str());
 	}
 	Audio::AudioStream *audioStream = Audio::makeWAVStream(fd, DisposeAfterUse::YES);
 	if (audioStream == nullptr) {
-		error("VoicePlayer::start() Could not load %s", filename.c_str());
+		error("VoicePlayer::start() Could not load %s", filename.toString().c_str());
 	}
 	g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, audioStream, -1, volume, pan);
 	_voiceStatus = 4;
@@ -321,15 +321,15 @@ Sound::~Sound() {
 }
 
 void Sound::load() {
-	Common::String filename = Common::String::format("%08x/%08x.wav", _soundGroupId, _soundEffectId);
+	Common::Path filename(Common::String::format("%08x/%08x.wav", _soundGroupId, _soundEffectId));
 	Common::File *fd = new Common::File();
 	if (!fd->open(filename)) {
 		delete fd;
-		error("Sound::load() Could not open %s", filename.c_str());
+		error("Sound::load() Could not open %s", filename.toString().c_str());
 	}
 	_stream = Audio::makeWAVStream(fd, DisposeAfterUse::YES);
 	if (_stream == nullptr) {
-		warning("Sound::load() Could not load %s", filename.c_str());
+		warning("Sound::load() Could not load %s", filename.toString().c_str());
 	}
 }
 


Commit: fa613cc8e9ff00f0b73bead707a398bc8b739f2c
    https://github.com/scummvm/scummvm/commit/fa613cc8e9ff00f0b73bead707a398bc8b739f2c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
IMMORTAL: Migrate engine to Path

Changed paths:
    engines/immortal/immortal.cpp
    engines/immortal/kernal.cpp


diff --git a/engines/immortal/immortal.cpp b/engines/immortal/immortal.cpp
index d46bc86ff61..1a36a8b8d55 100644
--- a/engines/immortal/immortal.cpp
+++ b/engines/immortal/immortal.cpp
@@ -37,7 +37,7 @@ ImmortalEngine::ImmortalEngine(OSystem *syst, const ADGameDescription *gameDesc)
 	g_immortal = this;
 
 	// Add the game folder to the search manager path variable
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "game");
 
 	// Confirm that the engine was created
diff --git a/engines/immortal/kernal.cpp b/engines/immortal/kernal.cpp
index 521fb8411cd..3be41d7c001 100644
--- a/engines/immortal/kernal.cpp
+++ b/engines/immortal/kernal.cpp
@@ -713,7 +713,7 @@ Common::SeekableReadStream *ImmortalEngine::loadIFF(Common::String fileName) {
 	 */
 
 	Common::File f;
-	if (!f.open(fileName)) {
+	if (!f.open(Common::Path(fileName))) {
 		debug("*surprised pikachu face*");
 		return nullptr;
 	}


Commit: ca89a72b68fed729244141a9d6b41a12b75a3cb5
    https://github.com/scummvm/scummvm/commit/ca89a72b68fed729244141a9d6b41a12b75a3cb5
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
KINGDOM: Migrate engine to Path

Changed paths:
    engines/kingdom/kingdom.cpp


diff --git a/engines/kingdom/kingdom.cpp b/engines/kingdom/kingdom.cpp
index cae674cb127..aca893bb913 100644
--- a/engines/kingdom/kingdom.cpp
+++ b/engines/kingdom/kingdom.cpp
@@ -64,7 +64,7 @@ KingdomGame::KingdomGame(OSystem *syst, const ADGameDescription *gameDesc) : Eng
 
 	_showHotspots = false;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "MAPS");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "PICS");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "SOUNDS");
@@ -381,14 +381,14 @@ void KingdomGame::unloadKingArt() {
 }
 
 Common::SeekableReadStream *KingdomGame::loadAResource(int reznum) {
-	Common::String path = Common::String(_rezNames[reznum]);
+	Common::Path path(_rezNames[reznum]);
 	path.toUppercase();
 
-	debug("Loading resource: %i (%s)\n", reznum, path.c_str());
+	debug("Loading resource: %i (%s)\n", reznum, path.toString().c_str());
 
 	Common::File *file = new Common::File();
 	if(!file->open(path)) {
-		warning("Failed to open %s", path.c_str());
+		warning("Failed to open %s", path.toString().c_str());
 		delete file;
 		return nullptr;
 	} else {
@@ -485,7 +485,7 @@ void KingdomGame::playMovie(int movieNum) {
 	readMouse();
 	_mouseButton = 0;
 	_keyActive = false;
-	const Common::String path = Common::String::format("King%.3d.mve", movieNum);
+	const Common::Path path(Common::String::format("King%.3d.mve", movieNum));
 
 	// Check if the file is available. If not the original does the following: _ATimer = 55, display of error with a check of timer, exit
 	// That can be replaced by an error()


Commit: abfc95304678f7192ce691765490e9eef4af515d
    https://github.com/scummvm/scummvm/commit/abfc95304678f7192ce691765490e9eef4af515d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
KYRA: Migrate engine to Path

Changed paths:
    engines/kyra/engine/darkmoon.cpp
    engines/kyra/engine/eob.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/kyra_hof.cpp
    engines/kyra/engine/kyra_mr.cpp
    engines/kyra/engine/lol.cpp
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/engine/scene_lok.cpp
    engines/kyra/engine/scene_lol.cpp
    engines/kyra/engine/scene_mr.cpp
    engines/kyra/engine/sprites_eob.cpp
    engines/kyra/engine/util.cpp
    engines/kyra/engine/util.h
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/graphics/screen_eob.h
    engines/kyra/graphics/screen_eob_amiga.cpp
    engines/kyra/gui/debugger.cpp
    engines/kyra/gui/saveload_eob.cpp
    engines/kyra/resource/resource.cpp
    engines/kyra/resource/resource.h
    engines/kyra/resource/resource_intern.cpp
    engines/kyra/resource/resource_intern.h
    engines/kyra/resource/resource_segacd.cpp
    engines/kyra/resource/resource_segacd.h
    engines/kyra/resource/staticres.cpp
    engines/kyra/sequence/sequences_darkmoon.cpp
    engines/kyra/sequence/sequences_hof.cpp
    engines/kyra/sequence/sequences_lol.cpp
    engines/kyra/sound/sound.cpp
    engines/kyra/sound/sound.h
    engines/kyra/sound/sound_amiga_eob.cpp
    engines/kyra/sound/sound_digital_mr.cpp
    engines/kyra/sound/sound_intern.h
    engines/kyra/sound/sound_lol.cpp
    engines/kyra/sound/sound_mac_lok.cpp
    engines/kyra/sound/sound_mac_res.h
    engines/kyra/sound/sound_pc98_darkmoon.cpp
    engines/kyra/sound/sound_pc98_eob.cpp
    engines/kyra/sound/sound_pc98_lok.cpp
    engines/kyra/sound/sound_pc98_v2.cpp
    engines/kyra/sound/sound_pc_midi.cpp
    engines/kyra/sound/sound_pc_v1.cpp
    engines/kyra/sound/sound_pc_v1.h
    engines/kyra/sound/sound_towns_darkmoon.cpp
    engines/kyra/text/text_mr.cpp


diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
index 4bf9a7f6c00..86d66d316f9 100644
--- a/engines/kyra/engine/darkmoon.cpp
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -227,10 +227,10 @@ void DarkMoonEngine::loadMonsterShapes(const char *filename, int monsterIndex, b
 		return;
 	}
 
-	Common::String tmp = Common::String::format("%s.MNT", filename);
+	Common::Path tmp(Common::String::format("%s.MNT", filename));
 	Common::SeekableReadStream *s = _res->createReadStream(tmp);
 	if (!s)
-		error("Screen_EoB::loadMonsterShapes(): Failed to load file '%s'", tmp.c_str());
+		error("Screen_EoB::loadMonsterShapes(): Failed to load file '%s'", tmp.toString().c_str());
 
 	for (int i = 0; i < 6; i++)
 		_monsterShapes[monsterIndex + i] = loadFMTownsShape(s);
@@ -685,7 +685,7 @@ void DarkMoonEngine::snd_loadAmigaSounds(int level, int sub) {
 		if (valNew >= 0 && valNew != valCur) {
 			if (i < 2 && valCur >= 0 && _amigaCurSoundIndex)
 				_sound->unloadSoundFile(Common::String::format("%s.SAM", _amigaLevelSoundList1[_amigaSoundIndex1[_amigaCurSoundIndex]]));
-			_sound->loadSoundFile(Common::String::format("%s.CPS", _amigaLevelSoundList1[valNew]));
+			_sound->loadSoundFile(Common::Path(Common::String::format("%s.CPS", _amigaLevelSoundList1[valNew])));
 			assert(_amigaLevelSoundList2[valNew]);
 			_amigaSoundMap[36 + i] = _amigaLevelSoundList2[valNew][0] ? _amigaLevelSoundList2[valNew] : 0;
 		} else if (valNew == -2) {
@@ -695,7 +695,7 @@ void DarkMoonEngine::snd_loadAmigaSounds(int level, int sub) {
 		}
 	}
 
-	_sound->loadSoundFile(Common::String::format(sub ? "LEVEL%da.SAM" : "LEVEL%d.SAM", level));
+	_sound->loadSoundFile(Common::Path(Common::String::format(sub ? "LEVEL%da.SAM" : "LEVEL%d.SAM", level)));
 
 	_amigaCurSoundIndex = sndIndex;
 }
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
index c9d46c93ef7..bc35562c42c 100644
--- a/engines/kyra/engine/eob.cpp
+++ b/engines/kyra/engine/eob.cpp
@@ -603,7 +603,7 @@ void EoBEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool h
 		0x0e, 0x0c, 0x08, 0x0f, 0x14, 0x12, 0x09, 0x0b, 0x0a, 0x13, 0x11, 0x15, 0x0d
 	};
 
-	_sres->loadContainer(Common::String::format("L%d", _currentLevel));
+	_sres->loadContainer(Common::Path(Common::String::format("L%d", _currentLevel)));
 	uint8 *data = _sres->resData(monsterIndex >> 4, 0);
 	const uint8 *pos = data;
 
@@ -684,7 +684,7 @@ void EoBEngine::readLevelFileData(int level) {
 		EoBCoreEngine::readLevelFileData(level);
 		return;
 	}
-	_sres->loadContainer(Common::String::format("L%d", level));
+	_sres->loadContainer(Common::Path(Common::String::format("L%d", level)));
 	Common::SeekableReadStream *s = _sres->resStream(7);
 	_screen->loadFileDataToPage(s, 5, 15000);
 	delete s;
@@ -695,7 +695,7 @@ void EoBEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 		_lastBlockDataFile = file;
 	delete[] _vcnBlocks;
 
-	Common::String fn = Common::String::format(_vcnFilePattern.c_str(), _lastBlockDataFile.c_str());
+	Common::Path fn(Common::String::format(_vcnFilePattern.c_str(), _lastBlockDataFile.c_str()));
 	if (_flags.platform == Common::kPlatformAmiga) {
 		Common::SeekableReadStream *in = _res->createReadStream(fn);
 		uint32 vcnSize = in->readUint16LE() * (_vcnSrcBitsPerPixel << 3);
@@ -705,9 +705,9 @@ void EoBEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 		in->read(_vcnBlocks, vcnSize);
 		delete in;
 	} else if (_flags.platform == Common::kPlatformPC98) {
-		_vcnBlocks = _res->fileData(fn.c_str(), 0);
+		_vcnBlocks = _res->fileData(fn, 0);
 	} else if (_flags.platform == Common::kPlatformSegaCD) {
-		_sres->loadContainer(Common::String::format("L%d", _currentLevel));
+		_sres->loadContainer(Common::Path(Common::String::format("L%d", _currentLevel)));
 		_vcnBlocks = _sres->resData(5, 0);
 	} else {
 		EoBCoreEngine::loadVcnData(file, cgaMapping);
@@ -717,14 +717,14 @@ void EoBEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 Common::SeekableReadStreamEndian *EoBEngine::getVmpData(const char *file) {
 	if (_flags.platform != Common::kPlatformSegaCD)
 		return EoBCoreEngine::getVmpData(file);
-	_sres->loadContainer(Common::String::format("L%d", _currentLevel));
+	_sres->loadContainer(Common::Path(Common::String::format("L%d", _currentLevel)));
 	return _sres->resStreamEndian(3);
 }
 
 const uint8 *EoBEngine::getBlockFileData(int level) {
 	if (_flags.platform != Common::kPlatformSegaCD)
 		return EoBCoreEngine::getBlockFileData(level);
-	_sres->loadContainer(Common::String::format("L%d", level));
+	_sres->loadContainer(Common::Path(Common::String::format("L%d", level)));
 	Common::SeekableReadStream *s = _sres->resStream(6);
 	_screen->loadFileDataToPage(s, 15, s->size());
 	delete s;
@@ -735,7 +735,7 @@ const uint8 *EoBEngine::getBlockFileData(int level) {
 Common::SeekableReadStreamEndian *EoBEngine::getDecDefinitions(const char *decFile) {
 	if (_flags.platform != Common::kPlatformSegaCD)
 		return EoBCoreEngine::getDecDefinitions(decFile);
-	_sres->loadContainer(Common::String::format("L%d", _currentLevel));
+	_sres->loadContainer(Common::Path(Common::String::format("L%d", _currentLevel)));
 	return _sres->resStreamEndian(4);
 }
 
@@ -745,7 +745,7 @@ void EoBEngine::loadDecShapesToPage3(const char *shpFile) {
 		return;
 	}
 	if (_dcrResCur != _currentLevel) {
-		_sres->loadContainer(Common::String::format("L%d", _currentLevel));
+		_sres->loadContainer(Common::Path(Common::String::format("L%d", _currentLevel)));
 		Common::SeekableReadStream *s = _sres->resStream(2);
 		_screen->loadFileDataToPage(s, 3, s->size());
 		_dcrShpDataPos = _screen->getCPagePtr(3);
@@ -760,7 +760,7 @@ void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s
 	const int shapeId[2] = { shapeId1, shapeId2 };
 
 	if (_flags.platform == Common::kPlatformSegaCD) {
-		_sres->loadContainer(Common::String::format("L%d", _currentLevel));
+		_sres->loadContainer(Common::Path(Common::String::format("L%d", _currentLevel)));
 		Common::SeekableReadStreamEndian *in = _sres->resStreamEndian(8);
 		_screen->loadFileDataToPage(in, 2, in->size());
 		delete in;
@@ -983,12 +983,12 @@ void EoBEngine::snd_loadAmigaSounds(int level, int) {
 
 	for (int i = 0; i < 2; ++i) {
 		if (_amigaLevelSoundList1[level * 2 + i][0])
-			_sound->loadSoundFile(Common::String::format("%s.CPS", _amigaLevelSoundList1[level * 2 + i]));
+			_sound->loadSoundFile(Common::Path(Common::String::format("%s.CPS", _amigaLevelSoundList1[level * 2 + i])));
 		if (_amigaLevelSoundList2[level * 2 + i][0])
-			_sound->loadSoundFile(Common::String::format("%s.CPS", _amigaLevelSoundList2[level * 2 + i]));
+			_sound->loadSoundFile(Common::Path(Common::String::format("%s.CPS", _amigaLevelSoundList2[level * 2 + i])));
 	}
 
-	_sound->loadSoundFile(Common::String::format("LEVELSAM%d.CPS", level));
+	_sound->loadSoundFile(Common::Path(Common::String::format("LEVELSAM%d.CPS", level)));
 
 	_amigaCurSoundFile = level;
 }
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 5c3d70ba704..c8a3738a017 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -948,8 +948,8 @@ protected:
 	virtual void makeNameShapes(int charId = -1) {}
 	virtual void makeFaceShapes(int charId = -1);
 	// Default parameters will import all present original save files and push them to the top of the save dialog.
-	bool importOriginalSaveFile(int destSlot, const char *sourceFile = 0);
-	Common::String readOriginalSaveFile(Common::String &file);
+	bool importOriginalSaveFile(int destSlot, const Common::Path &sourceFile = Common::Path());
+	Common::String readOriginalSaveFile(const Common::Path &file);
 	bool saveAsOriginalSaveFile(int slot = -1);
 
 	void *generateMonsterTempData(LevelTempData *tmp) override;
diff --git a/engines/kyra/engine/kyra_hof.cpp b/engines/kyra/engine/kyra_hof.cpp
index 425074f6dd4..41223989937 100644
--- a/engines/kyra/engine/kyra_hof.cpp
+++ b/engines/kyra/engine/kyra_hof.cpp
@@ -1386,21 +1386,21 @@ void KyraEngine_HoF::restoreGfxRect32x32(int x, int y) {
 #pragma mark -
 
 void KyraEngine_HoF::openTalkFile(int newFile) {
-	Common::String talkFilename;
+	Common::Path talkFilename;
 
 	if (_oldTalkFile > 0) {
-		talkFilename = Common::String::format("CH%dVOC.TLK", _oldTalkFile);
+		talkFilename = Common::Path(Common::String::format("CH%dVOC.TLK", _oldTalkFile));
 		_res->unloadPakFile(talkFilename);
 		_oldTalkFile = -1;
 	}
 
-	talkFilename = newFile ? Common::String::format("CH%dVOC.TLK", newFile) : "ANYTALK.TLK";
+	talkFilename = newFile ? Common::Path(Common::String::format("CH%dVOC.TLK", newFile)) : Common::Path("ANYTALK.TLK");
 
 	_oldTalkFile = newFile;
 
 	if (!_res->loadPakFile(talkFilename)) {
 		if (speechEnabled()) {
-			warning("Couldn't load voice file '%s', falling back to text only mode", talkFilename.c_str());
+			warning("Couldn't load voice file '%s', falling back to text only mode", talkFilename.toString().c_str());
 			_configVoice = 0;
 
 			// Sync the config manager with the new settings
diff --git a/engines/kyra/engine/kyra_mr.cpp b/engines/kyra/engine/kyra_mr.cpp
index 02473070690..6d9e7fe652c 100644
--- a/engines/kyra/engine/kyra_mr.cpp
+++ b/engines/kyra/engine/kyra_mr.cpp
@@ -733,7 +733,7 @@ void KyraEngine_MR::openTalkFile(int file) {
 	}
 
 	_currentTalkFile = file;
-	if (!_res->loadPakFile(talkFilename)) {
+	if (!_res->loadPakFile(Common::Path(talkFilename))) {
 		if (speechEnabled()) {
 			warning("Couldn't load voice file '%s', falling back to text only mode", talkFilename.c_str());
 			_configVoice = 0;
diff --git a/engines/kyra/engine/lol.cpp b/engines/kyra/engine/lol.cpp
index 1506fa65339..8b6c65cb6e4 100644
--- a/engines/kyra/engine/lol.cpp
+++ b/engines/kyra/engine/lol.cpp
@@ -1861,7 +1861,7 @@ void LoLEngine::loadTalkFile(int index) {
 	if (index > 0)
 		_curTlkFile = index;
 
-	_res->loadPakFile(Common::String::format("%02d.TLK", index));
+	_res->loadPakFile(Common::Path(Common::String::format("%02d.TLK", index)));
 }
 
 int LoLEngine::characterSays(int track, int charId, bool redraw) {
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index 57374139453..a95ec486505 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -119,7 +119,7 @@ void EoBCoreEngine::readLevelFileData(int level) {
 
 	for (const char *const *sf = suffix; *sf && !s; sf++) {
 		file = Common::String::format("LEVEL%d.%s", level, *sf);
-		s = _res->createReadStream(file);
+		s = _res->createReadStream(Common::Path(file));
 	}
 
 	if (!s)
@@ -364,7 +364,7 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 }
 
 Common::SeekableReadStreamEndian *EoBCoreEngine::getVmpData(const char *file) {
-	return _res->createEndianAwareReadStream(Common::String::format(_vmpFilePattern.c_str(), file));
+	return _res->createEndianAwareReadStream(Common::Path(Common::String::format(_vmpFilePattern.c_str(), file)));
 }
 
 void EoBCoreEngine::loadBlockProperties(const char *mazFile) {
@@ -386,7 +386,7 @@ const uint8 *EoBCoreEngine::getBlockFileData(int) {
 	if (_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformPC98) {
 		_screen->loadBitmap(_curBlockFile.c_str(), 15, 15, 0);
 	} else {
-		Common::SeekableReadStream *s = _res->createReadStream(_curBlockFile);
+		Common::SeekableReadStream *s = _res->createReadStream(Common::Path(_curBlockFile));
 		_screen->loadFileDataToPage(s, 15, s->size());
 		delete s;
 	}
diff --git a/engines/kyra/engine/scene_lok.cpp b/engines/kyra/engine/scene_lok.cpp
index a31451c3470..0f0c822a117 100644
--- a/engines/kyra/engine/scene_lok.cpp
+++ b/engines/kyra/engine/scene_lok.cpp
@@ -1261,7 +1261,7 @@ void KyraEngine_LoK::setupSceneResource(int sceneId) {
 	if (!_flags.isTalkie)
 		return;
 
-	Common::String file;
+	Common::Path file;
 
 	if (_currentRoom != 0xFFFF) {
 		assert(_currentRoom < _roomTableSize);
@@ -1270,9 +1270,9 @@ void KyraEngine_LoK::setupSceneResource(int sceneId) {
 
 		// unload our old room
 		file = _roomFilenameTable[tableId];
-		_res->unloadPakFile(file + ".VRM");
-		_res->unloadPakFile(file + ".PAK");
-		_res->unloadPakFile(file + ".APK");
+		_res->unloadPakFile(file.append(".VRM"));
+		_res->unloadPakFile(file.append(".PAK"));
+		_res->unloadPakFile(file.append(".APK"));
 	}
 
 	assert(sceneId < _roomTableSize);
@@ -1280,16 +1280,16 @@ void KyraEngine_LoK::setupSceneResource(int sceneId) {
 	assert(tableId < _roomFilenameTableSize);
 
 	// load our new room
-	file = Common::String(_roomFilenameTable[tableId]) + ".VRM";
-	if (_res->exists(file.c_str()))
+	file = Common::Path(_roomFilenameTable[tableId]).appendInPlace(".VRM");
+	if (_res->exists(file))
 		_res->loadPakFile(file);
 
-	file = Common::String(_roomFilenameTable[tableId]) + ".PAK";
-	if (_res->exists(file.c_str()))
+	file = Common::Path(_roomFilenameTable[tableId]).appendInPlace(".PAK");
+	if (_res->exists(file))
 		_res->loadPakFile(file);
 
-	file = Common::String(_roomFilenameTable[tableId]) + ".APK";
-	if (_res->exists(file.c_str()))
+	file = Common::Path(_roomFilenameTable[tableId]).appendInPlace(".APK");
+	if (_res->exists(file))
 		_res->loadPakFile(file);
 }
 
diff --git a/engines/kyra/engine/scene_lol.cpp b/engines/kyra/engine/scene_lol.cpp
index c4c547cb5f9..532afdf426f 100644
--- a/engines/kyra/engine/scene_lol.cpp
+++ b/engines/kyra/engine/scene_lol.cpp
@@ -456,7 +456,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight
 	generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect);
 
 	if (_flags.isTalkie) {
-		Common::SeekableReadStream *s = _res->createReadStream(Common::String::format("LEVEL%.02d.TLC", _currentLevel));
+		Common::SeekableReadStream *s = _res->createReadStream(Common::Path(Common::String::format("LEVEL%.02d.TLC", _currentLevel)));
 		s->read(_transparencyTable1, 256);
 		s->read(_transparencyTable2, 5120);
 		delete s;
diff --git a/engines/kyra/engine/scene_mr.cpp b/engines/kyra/engine/scene_mr.cpp
index f99d785a968..a16610e5658 100644
--- a/engines/kyra/engine/scene_mr.cpp
+++ b/engines/kyra/engine/scene_mr.cpp
@@ -315,9 +315,10 @@ void KyraEngine_MR::loadScenePal() {
 }
 
 void KyraEngine_MR::loadSceneMsc() {
-	Common::String filename = Common::String(_sceneList[_mainCharacter.sceneId].filename1) + ".MSC";
+	Common::Path filename(_sceneList[_mainCharacter.sceneId].filename1);
+	filename.appendInPlace(".MSC");
 
-	_res->exists(filename.c_str(), true);
+	_res->exists(filename, true);
 	Common::SeekableReadStream *stream = _res->createReadStream(filename);
 	assert(stream);
 	int16 minY = 0, height = 0;
@@ -330,7 +331,7 @@ void KyraEngine_MR::loadSceneMsc() {
 
 	_screen->setShapePages(5, 3, _maskPageMinY, _maskPageMaxY);
 
-	_screen->loadBitmap(filename.c_str(), 5, 5, nullptr, true);
+	_screen->loadBitmap(filename.toString('/').c_str(), 5, 5, nullptr, true);
 
 	// HACK
 	uint8 *data = new uint8[320*200];
@@ -347,7 +348,7 @@ void KyraEngine_MR::initSceneScript(int unk1) {
 	Common::String filename = Common::String(scene.filename1) + ".DAT";
 
 	_res->exists(filename.c_str(), true);
-	Common::SeekableReadStream *stream = _res->createReadStream(filename);
+	Common::SeekableReadStream *stream = _res->createReadStream(Common::Path(filename));
 	assert(stream);
 	stream->seek(2, SEEK_CUR);
 
diff --git a/engines/kyra/engine/sprites_eob.cpp b/engines/kyra/engine/sprites_eob.cpp
index 23909c252ca..50538927b2a 100644
--- a/engines/kyra/engine/sprites_eob.cpp
+++ b/engines/kyra/engine/sprites_eob.cpp
@@ -41,7 +41,7 @@ void EoBCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bo
 	generateMonsterPalettes(filename, monsterIndex);
 
 	if (hasDecorations) {
-		Common::SeekableReadStream *s = _res->createReadStream(Common::String::format("%s.DCR", filename));
+		Common::SeekableReadStream *s = _res->createReadStream(Common::Path(Common::String::format("%s.DCR", filename)));
 		if (s)
 			loadMonsterDecoration(s, monsterIndex);
 		delete s;
diff --git a/engines/kyra/engine/util.cpp b/engines/kyra/engine/util.cpp
index 01931848f33..8500c7d1d5d 100644
--- a/engines/kyra/engine/util.cpp
+++ b/engines/kyra/engine/util.cpp
@@ -289,7 +289,7 @@ Common::String Util::decodeString2(const Common::String &src) {
 	return reslt;
 }
 
-Common::String Util::findMacResourceFile(const char *baseName, const char *suffix) {
+Common::Path Util::findMacResourceFile(const char *baseName, const char *suffix) {
 	// The original executable has a TM char as its last character (character
 	// 0xAA from Mac code page). Depending on the emulator or platform used to
 	// copy the file it might have been reencoded to something else. So I look
@@ -304,15 +304,15 @@ Common::String Util::findMacResourceFile(const char *baseName, const char *suffi
 
 	Common::MacResManager resource;
 	Common::String tryName(baseName);
-	Common::String fileName;
+	Common::Path fileName;
 
 	for (int i = 0; i < 2; ++i) {
 		for (int ii = 0; ii < ARRAYSIZE(tryCodePages); ++ii) {
 			Common::U32String fn(tryName + suffix, tryCodePages[ii]);
-			fileName = fn.encode(Common::kUtf8);
+			fileName = Common::Path(fn.encode(Common::kUtf8));
 			if (resource.exists(fileName))
 				return fileName;
-			fileName = Common::punycode_encodefilename(fn);
+			fileName = Common::Path(Common::punycode_encodefilename(fn));
 			if (resource.exists(fileName))
 				return fileName;
 		}
diff --git a/engines/kyra/engine/util.h b/engines/kyra/engine/util.h
index fb6fc2c6229..340eee2eae6 100644
--- a/engines/kyra/engine/util.h
+++ b/engines/kyra/engine/util.h
@@ -23,6 +23,7 @@
 #define KYRA_UTIL_H
 
 #include "common/language.h"
+#include "common/path.h"
 #include "common/scummsys.h"
 #include "common/str.h"
 
@@ -48,7 +49,7 @@ public:
 	// e. g. when typing a one-byte character, like a digit).
 	static void mergeUpdateJohabChars(uint16 &destJohabChar0, uint16 &destJohabChar1, char asciiInput, bool reset);
 
-	static Common::String findMacResourceFile(const char *baseName, const char *suffix = "");
+	static Common::Path findMacResourceFile(const char *baseName, const char *suffix = "");
 
 private:
 	struct DOS2JOHABEntry {
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index 9195018e325..6978ce8c339 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -448,7 +448,7 @@ void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Pal
 
 void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage) {
 	Common::String tmp = Common::String::format(_cpsFilePattern.c_str(), file);
-	Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp);
+	Common::SeekableReadStream *s = _vm->resource()->createReadStream(Common::Path(tmp));
 	bool loadAlternative = false;
 
 	if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
@@ -491,7 +491,7 @@ void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int te
 
 		} else {
 			tmp.setChar('X', 0);
-			s = _vm->resource()->createReadStream(tmp);
+			s = _vm->resource()->createReadStream(Common::Path(tmp));
 
 			if (!s)
 				error("Screen_EoB::loadEoBBitmap(): Failed to load file '%s'", file);
diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h
index 32ac4781405..d5f242b0d96 100644
--- a/engines/kyra/graphics/screen_eob.h
+++ b/engines/kyra/graphics/screen_eob.h
@@ -344,7 +344,7 @@ private:
 		const int16 *kerning;
 	};
 
-	TextFont *loadContentFile(const Common::String fileName);
+	TextFont *loadContentFile(const Common::Path &fileName);
 	void selectMode(int mode);
 
 	struct FontContent {
diff --git a/engines/kyra/graphics/screen_eob_amiga.cpp b/engines/kyra/graphics/screen_eob_amiga.cpp
index 35d338824f5..507e0d60261 100644
--- a/engines/kyra/graphics/screen_eob_amiga.cpp
+++ b/engines/kyra/graphics/screen_eob_amiga.cpp
@@ -298,25 +298,21 @@ void AmigaDOSFont::unload() {
 	delete[] _content;
 }
 
-AmigaDOSFont::TextFont *AmigaDOSFont::loadContentFile(const Common::String fileName) {
+AmigaDOSFont::TextFont *AmigaDOSFont::loadContentFile(const Common::Path &fileName) {
 	Common::SeekableReadStreamEndian *str = _res->createEndianAwareReadStream(fileName);
 
-	if (!str && fileName.contains('/')) {
+	if (!str && !fileName.getParent().empty()) {
 		// These content files are usually located in sub directories (i. e. the eobf8.font
 		// has a sub dir named 'eobf8' with a file '8' in it). In case someone put the content
 		// files directly in the game directory we still try to open it.
-		Common::String fileNameAlt = fileName;
-		while (fileNameAlt.firstChar() != '/')
-			fileNameAlt.deleteChar(0);
-		fileNameAlt.deleteChar(0);
-
+		Common::Path fileNameAlt(fileName.baseName(), Common::Path::kNoSeparator);
 		str = _res->createEndianAwareReadStream(fileNameAlt);
 
 		if (!str) {
 			// Someone might even have copied the floppy disks to the game directory with the
 			// full sub directory structure. So we also try that...
-			fileNameAlt = "fonts/";
-			fileNameAlt += fileName;
+			fileNameAlt = Common::Path("fonts");
+			fileNameAlt.joinInPlace(fileName);
 
 			str = _res->createEndianAwareReadStream(fileNameAlt);
 		}
diff --git a/engines/kyra/gui/debugger.cpp b/engines/kyra/gui/debugger.cpp
index 1e86329f951..d65a6e74aee 100644
--- a/engines/kyra/gui/debugger.cpp
+++ b/engines/kyra/gui/debugger.cpp
@@ -505,7 +505,7 @@ bool Debugger_EoB::cmdImportSaveFile(int argc, const char **argv) {
 			return true;
 		}
 
-		debugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n");
+		debugPrintf(_vm->importOriginalSaveFile(slot, Common::Path(argv[2], Common::Path::kNativeSeparator)) ? "Success.\n" : "Failure.\n");
 		_vm->loadItemDefs();
 	} else {
 		debugPrintf("Syntax:   import_savefile <dest slot> <source file>\n              (Imports source save game file to dest slot.)\n          import_savefile -1\n              (Imports all original save game files found and puts them into the first available slots.)\n\n");
@@ -525,9 +525,7 @@ bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::String dir = ConfMan.get("savepath");
-	if (dir == "None")
-		dir.clear();
+	Common::Path dir = ConfMan.getPath("savepath");
 
 	Common::FSNode nd(dir);
 	if (!nd.isDirectory())
@@ -538,7 +536,7 @@ bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
 			if (_vm->saveAsOriginalSaveFile()) {
 				Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA.SAV"));
 				if (nf.isReadable())
-					debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
+					debugPrintf("Saved to file: %s\n\n", nf.getPath().toString(Common::Path::kNativeSeparator).c_str());
 				else
 					debugPrintf("Failure.\n");
 			} else {
@@ -556,7 +554,7 @@ bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
 		} else if (_vm->saveAsOriginalSaveFile(slot)) {
 			Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA%d.SAV", slot));
 			if (nf.isReadable())
-				debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
+				debugPrintf("Saved to file: %s\n\n", nf.getPath().toString(Common::Path::kNativeSeparator).c_str());
 			else
 				debugPrintf("Failure.\n");
 		} else {
diff --git a/engines/kyra/gui/saveload_eob.cpp b/engines/kyra/gui/saveload_eob.cpp
index 2889edb084f..f8a6a4bff3a 100644
--- a/engines/kyra/gui/saveload_eob.cpp
+++ b/engines/kyra/gui/saveload_eob.cpp
@@ -568,11 +568,11 @@ void EoBCoreEngine::makeFaceShapes(int charId) {
 	_screen->_curPage = 0;
 }
 
-bool EoBCoreEngine::importOriginalSaveFile(int destSlot, const char *sourceFile) {
-	Common::Array<Common::String> origFiles;
+bool EoBCoreEngine::importOriginalSaveFile(int destSlot, const Common::Path &sourceFile) {
+	Common::Array<Common::Path> origFiles;
 	Common::Array<int> newSlots;
 
-	if (sourceFile) {
+	if (!sourceFile.empty()) {
 		// If a source file is specified via the console command we just check whether it exists.
 		if (Common::File::exists(sourceFile))
 			origFiles.push_back(sourceFile);
@@ -583,7 +583,7 @@ bool EoBCoreEngine::importOriginalSaveFile(int destSlot, const char *sourceFile)
 		int numMax = (_flags.gameID == GI_EOB1) ? 1 : 6;
 		const char *pattern = (_flags.gameID == GI_EOB1) ? "EOBDATA.SAV" : "EOBDATA%d.SAV";
 		for (int i = 0; i < numMax; ++i) {
-			Common::String temp = Common::String::format(pattern, i);
+			Common::Path temp(Common::String::format(pattern, i));
 			Common::SeekableReadStream *fs = _res->createReadStream(temp);
 			if (fs) {
 				Common::U32String dsc;
@@ -595,7 +595,7 @@ bool EoBCoreEngine::importOriginalSaveFile(int destSlot, const char *sourceFile)
 				}
 
 				delete fs;
-				::GUI::MessageDialog dialog(Common::U32String::format(_("The following original saved game file has been found in your game path:\n\n%s %S\n\nDo you wish to use this saved game file with ScummVM?\n\n"), temp.c_str(), dsc.c_str()), _("Yes"), _("No"));
+				::GUI::MessageDialog dialog(Common::U32String::format(_("The following original saved game file has been found in your game path:\n\n%s %S\n\nDo you wish to use this saved game file with ScummVM?\n\n"), temp.toString(Common::Path::kNativeSeparator).c_str(), dsc.c_str()), _("Yes"), _("No"));
 				if (dialog.runModal() == ::GUI::kMessageOK)
 					origFiles.push_back(temp);
 			}
@@ -638,14 +638,14 @@ bool EoBCoreEngine::importOriginalSaveFile(int destSlot, const char *sourceFile)
 	for (int i = 0; i < numFilesFound; i++) {
 		Common::String desc = readOriginalSaveFile(origFiles[i]);
 		if (desc.empty()) {
-			warning("Unable to import original save file '%s'", origFiles[i].c_str());
+			warning("Unable to import original save file '%s'", origFiles[i].toString().c_str());
 		} else {
 			// We can't make thumbnails here, since we do not want to load all the level data, monsters, etc. for each save we convert.
 			// Instead, we use an empty surface to avoid that createThumbnailFromScreen() makes a completely pointless thumbnail from
 			// whatever screen that is currently shown when this function is called.
 			Graphics::Surface dummy;
 			saveGameStateIntern(newSlots[i], desc.c_str(), &dummy);
-			warning("Imported original save file '%s' ('%s')", origFiles[i].c_str(), desc.c_str());
+			warning("Imported original save file '%s' ('%s')", origFiles[i].toString().c_str(), desc.c_str());
 			importedCount++;
 		}
 	}
@@ -668,7 +668,7 @@ bool EoBCoreEngine::importOriginalSaveFile(int destSlot, const char *sourceFile)
 	return true;
 }
 
-Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
+Common::String EoBCoreEngine::readOriginalSaveFile(const Common::Path &file) {
 	Common::String desc;
 
 	Common::SeekableReadStream *fs = _res->createReadStream(file);
@@ -789,7 +789,7 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 		if (c->effectFlags && _flags.gameID == GI_EOB1) {
 			// Spell effect flags are completely different in EOB I. We only use EOB II style flags in ScummVM.
 			// Doesn't matter much, since these are only temporary spell effects.
-			warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled character effect flags encountered in original EOB1 save file '%s' ('%s')", file.c_str(), desc.c_str());
+			warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled character effect flags encountered in original EOB1 save file '%s' ('%s')", file.toString().c_str(), desc.c_str());
 			c->effectFlags = 0;
 		}
 		c->damageTaken = in.readByte();
@@ -809,7 +809,7 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 	if (_partyEffectFlags && _flags.gameID == GI_EOB1) {
 		// Spell effect flags are completely different in EOB I. We only use EOB II style flags in ScummVM.
 		// Doesn't matter much, since these are only temporary spell effects.
-		warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled party effect flags encountered in original EOB1 save file '%s' ('%s')", file.c_str(), desc.c_str());
+		warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled party effect flags encountered in original EOB1 save file '%s' ('%s')", file.toString().c_str(), desc.c_str());
 		_partyEffectFlags = 0;
 	}
 	if (_flags.gameID == GI_EOB2)
@@ -1080,9 +1080,7 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 	if (_flags.gameID == GI_EOB2 && (slot < 0 || slot > 5))
 		return false;
 
-	Common::String dir = ConfMan.get("savepath");
-	if (dir == "None")
-		dir.clear();
+	Common::Path dir = ConfMan.getPath("savepath");
 
 	Common::FSNode nd(dir);
 	if (!nd.isDirectory())
diff --git a/engines/kyra/resource/resource.cpp b/engines/kyra/resource/resource.cpp
index 28fecbfcbbf..78bb1d4c7d9 100644
--- a/engines/kyra/resource/resource.cpp
+++ b/engines/kyra/resource/resource.cpp
@@ -33,7 +33,7 @@
 namespace Kyra {
 
 Common::Archive *Resource::loadKyra1MacInstaller() {
-	Common::String kyraInstaller = Util::findMacResourceFile("Install Legend of Kyrandia");
+	Common::Path kyraInstaller = Util::findMacResourceFile("Install Legend of Kyrandia");
 
 	if (!kyraInstaller.empty()) {
 		Common::Archive *archive = loadStuffItArchive(kyraInstaller, "Install Legend of Kyrandia");
@@ -47,12 +47,12 @@ Common::Archive *Resource::loadKyra1MacInstaller() {
 	if (!kyraInstaller.empty()) {
 		Common::Array<Common::SharedPtr<Common::SeekableReadStream>> parts;
 		for (int i = 1; i <= 5; i++) {
-			Common::String partName = i == 1 ? kyraInstaller : Common::String::format("%s.%d", kyraInstaller.c_str(), i);
+			Common::Path partName = i == 1 ? kyraInstaller : kyraInstaller.append(Common::String::format(".%d", i));
 			Common::SeekableReadStream *stream = Common::MacResManager::openFileOrDataFork(partName);
 			if (!stream)
-				error("Failed to load Legend of Kyrandia installer file part %s", partName.c_str());
+				error("Failed to load Legend of Kyrandia installer file part %s", partName.toString().c_str());
 			if (stream->size() <= 100)
-				error("Legend of Kyrandia installer file part %s is too short", partName.c_str());
+				error("Legend of Kyrandia installer file part %s is too short", partName.toString().c_str());
 			parts.push_back(Common::SharedPtr<Common::SeekableReadStream>(new Common::SeekableSubReadStream(stream, 100, stream->size(), DisposeAfterUse::YES)));
 		}
 		return loadStuffItArchive(new Common::ConcatReadStream(parts), "Install Legend of Kyrandia", "Legend of Kyrandia(TM) Installer.*");
@@ -65,15 +65,15 @@ Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles
 	initializeLoaders();
 
 	if (_vm->game() == GI_KYRA1 && _vm->gameFlags().platform == Common::Platform::kPlatformMacintosh)
-		SearchMan.addSubDirectoryMatching(Common::FSNode(ConfMan.get("path")), "runtime");
+		SearchMan.addSubDirectoryMatching(Common::FSNode(ConfMan.getPath("path")), "runtime");
 
 	// Initialize directories for playing from CD or with original
 	// directory structure
 	if (_vm->game() == GI_KYRA3)
-		SearchMan.addSubDirectoryMatching(Common::FSNode(ConfMan.get("path")), "malcolm");
+		SearchMan.addSubDirectoryMatching(Common::FSNode(ConfMan.getPath("path")), "malcolm");
 
 	if (_vm->game() == GI_LOL)
-		SearchMan.addSubDirectoryMatching(Common::FSNode(ConfMan.get("path")), "data", 0, 2);
+		SearchMan.addSubDirectoryMatching(Common::FSNode(ConfMan.getPath("path")), "data", 0, 2);
 
 	_files.add("global_search", &Common::SearchManager::instance(), 3, false);
 	// compressed installer archives are added at level '2',
@@ -93,10 +93,10 @@ Resource::~Resource() {
 bool Resource::reset() {
 	unloadAllPakFiles();
 
-	Common::FSNode dir(ConfMan.get("path"));
+	Common::FSNode dir(ConfMan.getPath("path"));
 
 	if (!dir.exists() || !dir.isDirectory())
-		error("invalid game path '%s'", dir.getPath().c_str());
+		error("invalid game path '%s'", dir.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	if (_vm->game() == GI_KYRA1 && _vm->gameFlags().platform == Common::kPlatformMacintosh && _vm->gameFlags().useInstallerPackage) {
 		Common::Archive *archive = loadKyra1MacInstaller();
@@ -155,7 +155,7 @@ bool Resource::reset() {
 				if (name == ((_vm->gameFlags().lang == Common::EN_ANY) ? "JMC.PAK" : "EMC.PAK"))
 					continue;
 
-				Common::Archive *archive = loadArchive(name, *i);
+				Common::Archive *archive = loadArchive((*i)->getName(), *i);
 
 				if (archive) {
 					// Hack for the Spanish version of EOB1. It has an invalid item.dat file in the
@@ -203,32 +203,34 @@ bool Resource::reset() {
 	return true;
 }
 
-bool Resource::loadPakFile(Common::String filename) {
-	filename.toUppercase();
+bool Resource::loadPakFile(const Common::Path &filename) {
+	Common::Path filenameFixed(filename);
+	filenameFixed.toUppercase();
 
-	Common::ArchiveMemberPtr file = _files.getMember(filename);
+	Common::ArchiveMemberPtr file = _files.getMember(filenameFixed);
 	if (!file)
 		return false;
 
-	return loadPakFile(filename, file);
+	return loadPakFile(filenameFixed.toString('/'), file);
 }
 
-bool Resource::loadPakFile(Common::String name, Common::ArchiveMemberPtr file) {
-	name.toUppercase();
+bool Resource::loadPakFile(const Common::String &name, Common::ArchiveMemberPtr file) {
+	Common::String nameFixed(name);
+	nameFixed.toUppercase();
 
-	if (_archiveFiles.hasArchive(name) || _protectedFiles.hasArchive(name))
+	if (_archiveFiles.hasArchive(nameFixed) || _protectedFiles.hasArchive(nameFixed))
 		return true;
 
-	Common::Archive *archive = loadArchive(name, file);
+	Common::Archive *archive = loadArchive(nameFixed, file);
 	if (!archive)
 		return false;
 
-	_archiveFiles.add(name, archive, 0, false);
+	_archiveFiles.add(nameFixed, archive, 0, false);
 
 	return true;
 }
 
-bool Resource::loadFileList(const Common::String &filedata) {
+bool Resource::loadFileList(const Common::Path &filedata) {
 	Common::SeekableReadStream *f = createReadStream(filedata);
 
 	if (!f)
@@ -248,12 +250,13 @@ bool Resource::loadFileList(const Common::String &filedata) {
 		filename.toUppercase();
 
 		if (filename.hasSuffix(".PAK")) {
-			if (!exists(filename.c_str()) && _vm->gameFlags().isDemo) {
+			Common::Path path(filename);
+			if (!exists(path) && _vm->gameFlags().isDemo) {
 				// the demo version supplied with Kyra3 does not
 				// contain all pak files listed in filedata.fdt
 				// so we don't do anything here if they are non
 				// existent.
-			} else if (!loadPakFile(filename)) {
+			} else if (!loadPakFile(path)) {
 				delete f;
 				error("couldn't load file '%s'", filename.c_str());
 				return false;   // for compilers that don't support NORETURN
@@ -295,31 +298,34 @@ bool Resource::loadProtectedFiles(const char *const *list) {
 	return true;
 }
 
-void Resource::unloadPakFile(Common::String filename, bool remFromCache) {
-	filename.toUppercase();
+void Resource::unloadPakFile(const Common::String &name, bool remFromCache) {
+	Common::String nameFixed(name);
+	nameFixed.toUppercase();
 
 	// We do not remove files from '_protectedFiles' here, since
 	// those are protected against unloading.
-	if (_archiveFiles.hasArchive(filename)) {
-		_archiveFiles.remove(filename);
+	if (_archiveFiles.hasArchive(nameFixed)) {
+		_archiveFiles.remove(nameFixed);
 		if (remFromCache) {
-			ArchiveMap::iterator iter = _archiveCache.find(filename);
+			ArchiveMap::iterator iter = _archiveCache.find(nameFixed);
 			if (iter != _archiveCache.end()) {
 				delete iter->_value;
-				_archiveCache.erase(filename);
+				_archiveCache.erase(nameFixed);
 			}
 		}
 	}
 }
 
-bool Resource::isInPakList(Common::String filename) {
-	filename.toUppercase();
-	return (_archiveFiles.hasArchive(filename) || _protectedFiles.hasArchive(filename));
+bool Resource::isInPakList(const Common::String &name) {
+	Common::String nameFixed(name);
+	nameFixed.toUppercase();
+	return (_archiveFiles.hasArchive(nameFixed) || _protectedFiles.hasArchive(nameFixed));
 }
 
-bool Resource::isInCacheList(Common::String name) {
-	name.toUppercase();
-	return (_archiveCache.find(name) != _archiveCache.end());
+bool Resource::isInCacheList(const Common::String &name) {
+	Common::String nameFixed(name);
+	nameFixed.toUppercase();
+	return (_archiveCache.find(nameFixed) != _archiveCache.end());
 }
 
 void Resource::unloadAllPakFiles() {
@@ -327,11 +333,11 @@ void Resource::unloadAllPakFiles() {
 	_protectedFiles.clear();
 }
 
-void Resource::listFiles(const Common::String &pattern, Common::ArchiveMemberList &list) {
+void Resource::listFiles(const Common::Path &pattern, Common::ArchiveMemberList &list) {
 	_files.listMatchingMembers(list, pattern);
 }
 
-uint8 *Resource::fileData(const char *file, uint32 *size) {
+uint8 *Resource::fileData(const Common::Path &file, uint32 *size) {
 	Common::SeekableReadStream *stream = createReadStream(file);
 	if (!stream)
 		return nullptr;
@@ -346,15 +352,15 @@ uint8 *Resource::fileData(const char *file, uint32 *size) {
 	return buffer;
 }
 
-bool Resource::exists(const char *file, bool errorOutOnFail) {
+bool Resource::exists(const Common::Path &file, bool errorOutOnFail) {
 	if (_files.hasFile(file))
 		return true;
 	else if (errorOutOnFail)
-		error("File '%s' can't be found", file);
+		error("File '%s' can't be found", file.toString().c_str());
 	return false;
 }
 
-uint32 Resource::getFileSize(const char *file) {
+uint32 Resource::getFileSize(const Common::Path &file) {
 	Common::SeekableReadStream *stream = createReadStream(file);
 	if (!stream)
 		return 0;
@@ -364,7 +370,7 @@ uint32 Resource::getFileSize(const char *file) {
 	return size;
 }
 
-bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) {
+bool Resource::loadFileToBuf(const Common::Path &file, void *buf, uint32 maxSize) {
 	Common::SeekableReadStream *stream = createReadStream(file);
 	if (!stream)
 		return false;
@@ -380,11 +386,11 @@ Common::Archive *Resource::getCachedArchive(const Common::String &file) const {
 	return a != _archiveCache.end() ? a->_value : 0;
 }
 
-Common::SeekableReadStream *Resource::createReadStream(const Common::String &file) {
+Common::SeekableReadStream *Resource::createReadStream(const Common::Path &file) {
 	return _files.createReadStreamForMember(file);
 }
 
-Common::SeekableReadStreamEndian *Resource::createEndianAwareReadStream(const Common::String &file, int endianness) {
+Common::SeekableReadStreamEndian *Resource::createEndianAwareReadStream(const Common::Path &file, int endianness) {
 	Common::SeekableReadStream *stream = _files.createReadStreamForMember(file);
 	return stream ? new Common::SeekableReadStreamEndianWrapper(stream, (endianness == kForceBE) ? true : (endianness == kForceLE ? false : _bigEndianPlatForm), DisposeAfterUse::YES) : nullptr;
 }
@@ -421,8 +427,9 @@ Common::Archive *Resource::loadArchive(const Common::String &name, Common::Archi
 	return archive;
 }
 
-Common::Archive *Resource::loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset) {
-	ArchiveMap::iterator cachedArchive = _archiveCache.find(file);
+Common::Archive *Resource::loadInstallerArchive(const Common::Path &file, const Common::String &ext, const uint8 offset) {
+	Common::String name(file.toString('/'));
+	ArchiveMap::iterator cachedArchive = _archiveCache.find(name);
 	if (cachedArchive != _archiveCache.end())
 		return cachedArchive->_value;
 
@@ -430,11 +437,11 @@ Common::Archive *Resource::loadInstallerArchive(const Common::String &file, cons
 	if (!archive)
 		return nullptr;
 
-	_archiveCache[file] = archive;
+	_archiveCache[name] = archive;
 	return archive;
 }
 
-Common::Archive *Resource::loadStuffItArchive(const Common::String &file, const Common::String& canonicalName) {
+Common::Archive *Resource::loadStuffItArchive(const Common::Path &file, const Common::String &canonicalName) {
 	ArchiveMap::iterator cachedArchive = _archiveCache.find(canonicalName);
 	if (cachedArchive != _archiveCache.end())
 		return cachedArchive->_value;
@@ -447,7 +454,7 @@ Common::Archive *Resource::loadStuffItArchive(const Common::String &file, const
 	return archive;
 }
 
-Common::Archive *Resource::loadStuffItArchive(Common::SeekableReadStream *stream, const Common::String& canonicalName, const Common::String& debugName) {
+Common::Archive *Resource::loadStuffItArchive(Common::SeekableReadStream *stream, const Common::String &canonicalName, const Common::String &debugName) {
 	ArchiveMap::iterator cachedArchive = _archiveCache.find(canonicalName);
 	if (cachedArchive != _archiveCache.end()) {
 		delete stream;
diff --git a/engines/kyra/resource/resource.h b/engines/kyra/resource/resource.h
index 48e6f38c89d..34751398ace 100644
--- a/engines/kyra/resource/resource.h
+++ b/engines/kyra/resource/resource.h
@@ -52,28 +52,30 @@ public:
 
 	bool reset();
 
-	bool loadPakFile(Common::String filename);
-	bool loadPakFile(Common::String name, Common::ArchiveMemberPtr file);
+	bool loadPakFile(const Common::Path &filename);
+	bool loadPakFile(const Common::String &name, Common::ArchiveMemberPtr file);
 
-	void unloadPakFile(Common::String filename, bool remFromCache = false);
+	void unloadPakFile(const Common::String &name, bool remFromCache = false);
+	void unloadPakFile(const char *name, bool remFromCache = false) { unloadPakFile(Common::String(name), remFromCache); }
+	void unloadPakFile(const Common::Path &name, bool remFromCache = false) { unloadPakFile(name.toString('/'), remFromCache); }
 
-	bool isInPakList(Common::String filename);
+	bool isInPakList(const Common::String &name);
 
-	bool isInCacheList(Common::String name);
+	bool isInCacheList(const Common::String &name);
 
-	bool loadFileList(const Common::String &filedata);
+	bool loadFileList(const Common::Path &filedata);
 	bool loadFileList(const char *const *filelist, uint32 numFiles);
 
 	// This unloads *all* pakfiles, even kyra.dat and protected ones.
 	// It does not remove files from cache though!
 	void unloadAllPakFiles();
 
-	void listFiles(const Common::String &pattern, Common::ArchiveMemberList &list);
+	void listFiles(const Common::Path &pattern, Common::ArchiveMemberList &list);
 
-	bool exists(const char *file, bool errorOutOnFail=false);
-	uint32 getFileSize(const char *file);
-	uint8 *fileData(const char *file, uint32 *size);
-	Common::SeekableReadStream *createReadStream(const Common::String &file);
+	bool exists(const Common::Path &file, bool errorOutOnFail=false);
+	uint32 getFileSize(const Common::Path &file);
+	uint8 *fileData(const Common::Path &file, uint32 *size);
+	Common::SeekableReadStream *createReadStream(const Common::Path &file);
 
 	enum Endianness {
 		kPlatformEndianness = 0,
@@ -81,9 +83,9 @@ public:
 		kForceBE
 	};
 
-	Common::SeekableReadStreamEndian *createEndianAwareReadStream(const Common::String &file, int endianness = kPlatformEndianness);
+	Common::SeekableReadStreamEndian *createEndianAwareReadStream(const Common::Path &file, int endianness = kPlatformEndianness);
 
-	bool loadFileToBuf(const char *file, void *buf, uint32 maxSize);
+	bool loadFileToBuf(const Common::Path &file, void *buf, uint32 maxSize);
 
 	Common::Archive *getCachedArchive(const Common::String &file) const;
 
@@ -96,9 +98,9 @@ protected:
 	Common::SearchSet _protectedFiles;
 
 	Common::Archive *loadArchive(const Common::String &name, Common::ArchiveMemberPtr member);
-	Common::Archive *loadInstallerArchive(const Common::String &file, const Common::String &ext, const uint8 offset);
-	Common::Archive *loadStuffItArchive(const Common::String &file, const Common::String& canonicalName);
-	Common::Archive *loadStuffItArchive(Common::SeekableReadStream *stream, const Common::String& canonicalName, const Common::String& debugName);
+	Common::Archive *loadInstallerArchive(const Common::Path &file, const Common::String &ext, const uint8 offset);
+	Common::Archive *loadStuffItArchive(const Common::Path &file, const Common::String &canonicalName);
+	Common::Archive *loadStuffItArchive(Common::SeekableReadStream *stream, const Common::String &canonicalName, const Common::String &debugName);
 	Common::Archive *loadKyra1MacInstaller();
 
 	bool loadProtectedFiles(const char *const * list);
diff --git a/engines/kyra/resource/resource_intern.cpp b/engines/kyra/resource/resource_intern.cpp
index e69722b2add..34c4145a66b 100644
--- a/engines/kyra/resource/resource_intern.cpp
+++ b/engines/kyra/resource/resource_intern.cpp
@@ -39,8 +39,7 @@ PlainArchive::PlainArchive(Common::ArchiveMemberPtr file)
 }
 
 bool PlainArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return (_files.find(name) != _files.end());
+	return (_files.find(path) != _files.end());
 }
 
 int PlainArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -55,16 +54,14 @@ int PlainArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr PlainArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *PlainArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	FileMap::const_iterator fDesc = _files.find(name);
+	FileMap::const_iterator fDesc = _files.find(path);
 	if (fDesc == _files.end())
 		return nullptr;
 
@@ -75,11 +72,11 @@ Common::SeekableReadStream *PlainArchive::createReadStreamForMember(const Common
 	return new Common::SeekableSubReadStream(parent, fDesc->_value.offset, fDesc->_value.offset + fDesc->_value.size, DisposeAfterUse::YES);
 }
 
-void PlainArchive::addFileEntry(const Common::String &name, const Entry entry) {
+void PlainArchive::addFileEntry(const Common::Path &name, const Entry entry) {
 	_files[name] = entry;
 }
 
-PlainArchive::Entry PlainArchive::getFileEntry(const Common::String &name) const {
+PlainArchive::Entry PlainArchive::getFileEntry(const Common::Path &name) const {
 	FileMap::const_iterator fDesc = _files.find(name);
 	if (fDesc == _files.end())
 		return Entry();
@@ -97,8 +94,7 @@ TlkArchive::~TlkArchive() {
 }
 
 bool TlkArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return (findFile(name) != nullptr);
+	return (findFile(path) != nullptr);
 }
 
 int TlkArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -113,16 +109,14 @@ int TlkArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr TlkArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *TlkArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	const uint32 *fileDesc = findFile(name);
+	const uint32 *fileDesc = findFile(path);
 	if (!fileDesc)
 		return nullptr;
 
@@ -137,8 +131,8 @@ Common::SeekableReadStream *TlkArchive::createReadStreamForMember(const Common::
 	return new Common::SeekableSubReadStream(parent, fileStart, fileStart + size, DisposeAfterUse::YES);
 }
 
-const uint32 *TlkArchive::findFile(const Common::String &name) const {
-	Common::String uppercaseName = name;
+const uint32 *TlkArchive::findFile(const Common::Path &path) const {
+	Common::String uppercaseName = path.baseName();
 	uppercaseName.toUppercase();
 
 	if (!uppercaseName.hasSuffix(".AUD"))
@@ -181,7 +175,7 @@ CachedArchive::CachedArchive(const FileInputList &files)
 		entry.data = i->data;
 		entry.size = i->size;
 
-		Common::String name = i->name;
+		Common::Path name = i->name;
 		name.toLowercase();
 		_files[name] = entry;
 	}
@@ -194,8 +188,7 @@ CachedArchive::~CachedArchive() {
 }
 
 bool CachedArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return (_files.find(name) != _files.end());
+	return (_files.find(path) != _files.end());
 }
 
 int CachedArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -210,16 +203,14 @@ int CachedArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr CachedArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *CachedArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	FileMap::const_iterator fDesc = _files.find(name);
+	FileMap::const_iterator fDesc = _files.find(path);
 	if (fDesc == _files.end())
 		return nullptr;
 
@@ -230,9 +221,12 @@ Common::SeekableReadStream *CachedArchive::createReadStreamForMember(const Commo
 
 // -> ResLoaderPak implementation
 
-bool ResLoaderPak::checkFilename(Common::String filename) const {
-	filename.toUppercase();
-	return (filename.hasSuffix(".PAK") || filename.hasSuffix(".APK") || filename.hasSuffix(".VRM") || filename.hasSuffix(".CMP") || filename.hasSuffix(".TLK") || filename.equalsIgnoreCase(StaticResource::staticDataFilename()));
+bool ResLoaderPak::checkFilename(const Common::String &filename) const {
+	Common::String filenameFixed(filename);
+	filenameFixed.toUppercase();
+	return (filenameFixed.hasSuffix(".PAK") || filenameFixed.hasSuffix(".APK") ||
+		filenameFixed.hasSuffix(".VRM") || filenameFixed.hasSuffix(".CMP") ||
+		filenameFixed.hasSuffix(".TLK") || filenameFixed.equalsIgnoreCase(StaticResource::staticDataFilename()));
 }
 
 namespace {
@@ -315,7 +309,7 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
 		startoffset = SWAP_BYTES_32(startoffset);
 	}
 
-	Common::String file;
+	Common::Path file;
 	while (!stream.eos()) {
 		// The start offset of a file should never be in the filelist
 		if (startoffset < stream.pos() || startoffset > filesize || startoffset < 0) {
@@ -323,7 +317,7 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
 			return nullptr;
 		}
 
-		file = readString(stream);
+		file = Common::Path(readString(stream));
 
 		if (stream.eos()) {
 			warning("PAK file '%s' is corrupted", memberFile->getName().c_str());
@@ -371,15 +365,15 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
 
 		const uint32 links = stream.readUint32BE();
 		for (uint32 i = 0; i < links; ++i) {
-			const Common::String linksTo = readString(stream);
+			const Common::Path linksTo(readString(stream));
 			const uint32 sources = stream.readUint32BE();
 
 			PlainArchive::Entry destination = result->getFileEntry(linksTo);
 			if (destination.size == 0)
-				error("PAK file link destination '%s' not found", linksTo.c_str());
+				error("PAK file link destination '%s' not found", linksTo.toString().c_str());
 
 			for (uint32 j = 0; j < sources; ++j) {
-				const Common::String dest = readString(stream);
+				const Common::Path dest(readString(stream));
 				result->addFileEntry(dest, destination);
 			}
 		}
@@ -390,9 +384,10 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common:
 
 // -> ResLoaderInsMalcolm implementation
 
-bool ResLoaderInsMalcolm::checkFilename(Common::String filename) const {
-	filename.toUppercase();
-	if (!filename.hasSuffix(".001"))
+bool ResLoaderInsMalcolm::checkFilename(const Common::String &filename) const {
+	Common::String filenameFixed(filename);
+	filenameFixed.toUppercase();
+	if (!filenameFixed.hasSuffix(".001"))
 		return false;
 	return true;
 }
@@ -448,16 +443,17 @@ Common::Archive *ResLoaderInsMalcolm::load(Common::ArchiveMemberPtr memberFile,
 		const uint32 fileSize = stream.readUint32LE();
 		const uint32 fileOffset = stream.pos();
 
-		result->addFileEntry(*file, PlainArchive::Entry(fileOffset, fileSize));
+		result->addFileEntry(Common::Path(*file, Common::Path::kNoSeparator), PlainArchive::Entry(fileOffset, fileSize));
 		stream.seek(fileSize, SEEK_CUR);
 	}
 
 	return result.release();
 }
 
-bool ResLoaderTlk::checkFilename(Common::String filename) const {
-	filename.toUppercase();
-	return (filename.hasSuffix(".TLK"));
+bool ResLoaderTlk::checkFilename(const Common::String &filename) const {
+	Common::String filenameFixed(filename);
+	filenameFixed.toUppercase();
+	return (filenameFixed.hasSuffix(".TLK"));
 }
 
 bool ResLoaderTlk::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const {
@@ -920,7 +916,7 @@ uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 &para) {
 namespace {
 
 struct InsArchive {
-	Common::String filename;
+	Common::Path filename;
 	uint32 firstFile;
 	uint32 startOffset;
 	uint32 lastFile;
@@ -944,17 +940,17 @@ private:
 	uint8 *_sndArray;
 };
 
-Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &filename, const Common::String &extension, const uint8 containerOffset) {
+Common::Archive *InstallerLoader::load(Resource *owner, const Common::Path &filename, const Common::String &extension, const uint8 containerOffset) {
 	uint32 pos = 0;
 	uint32 bytesleft = 0;
 	bool startFile = true;
 
-	Common::String filenameBase = filename;
-	Common::String filenameTemp;
+	Common::Path filenameBase = filename;
+	Common::Path filenameTemp;
 	char filenameExt[4];
 
-	if (filenameBase.lastChar() != '.')
-		filenameBase += '.';
+	if (filenameBase.baseName().lastChar() != '.')
+		filenameBase.appendInPlace(".");
 
 	InsArchive newArchive;
 	Common::List<InsArchive> archives;
@@ -963,10 +959,10 @@ Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &fi
 
 	for (int8 currentFile = 1; currentFile; currentFile++) {
 		Common::sprintf_s(filenameExt, extension.c_str(), currentFile);
-		filenameTemp = filenameBase + Common::String(filenameExt);
+		filenameTemp = filenameBase.append(filenameExt);
 
 		if (!(tmpFile = owner->createReadStream(filenameTemp))) {
-			debug(3, "couldn't open file '%s'\n", filenameTemp.c_str());
+			debug(3, "couldn't open file '%s'\n", filenameTemp.toString().c_str());
 			break;
 		}
 
@@ -1041,10 +1037,10 @@ Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &fi
 		startFile = true;
 		for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) {
 			Common::sprintf_s(filenameExt, extension.c_str(), i);
-			filenameTemp = a->filename + Common::String(filenameExt);
+			filenameTemp = a->filename.append(filenameExt);
 
 			if (!(tmpFile = owner->createReadStream(filenameTemp))) {
-				debug(3, "couldn't open file '%s'\n", filenameTemp.c_str());
+				debug(3, "couldn't open file '%s'\n", filenameTemp.toString().c_str());
 				break;
 			}
 
@@ -1116,7 +1112,7 @@ Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &fi
 					}
 
 					Common::sprintf_s(filenameExt, extension.c_str(), i + 1);
-					filenameTemp = a->filename + Common::String(filenameExt);
+					filenameTemp = a->filename.append(filenameExt);
 
 					Common::SeekableReadStream *tmpFile2 = owner->createReadStream(filenameTemp);
 					tmpFile->read(hdr, m);
@@ -1217,11 +1213,11 @@ Common::Archive *InstallerLoader::load(Resource *owner, const Common::String &fi
 	return new CachedArchive(fileList);
 }
 
-Common::Archive *StuffItLoader::load(Resource *owner, const Common::String &filename) {
-	return load(owner, Common::MacResManager::openFileOrDataFork(filename), filename);
+Common::Archive *StuffItLoader::load(Resource *owner, const Common::Path &filename) {
+	return load(owner, Common::MacResManager::openFileOrDataFork(filename), filename.toString('/'));
 }
 
-Common::Archive *StuffItLoader::load(Resource *owner, Common::SeekableReadStream *stream, const Common::String& debugName) {
+Common::Archive *StuffItLoader::load(Resource *owner, Common::SeekableReadStream *stream, const Common::String &debugName) {
 	if (stream) {
 		Common::Archive *archive = Common::createStuffItArchive(stream, true);
 		return archive;
diff --git a/engines/kyra/resource/resource_intern.h b/engines/kyra/resource/resource_intern.h
index be17623fac1..55863c9cff7 100644
--- a/engines/kyra/resource/resource_intern.h
+++ b/engines/kyra/resource/resource_intern.h
@@ -46,8 +46,8 @@ public:
 
 	PlainArchive(Common::ArchiveMemberPtr file);
 
-	void addFileEntry(const Common::String &name, const Entry entry);
-	Entry getFileEntry(const Common::String &name) const;
+	void addFileEntry(const Common::Path &name, const Entry entry);
+	Entry getFileEntry(const Common::Path &name) const;
 
 	// Common::Archive API implementation
 	bool hasFile(const Common::Path &path) const override;
@@ -55,7 +55,7 @@ public:
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
 	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
 private:
-	typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, Entry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 
 	Common::ArchiveMemberPtr _file;
 	FileMap _files;
@@ -73,7 +73,7 @@ public:
 private:
 	Common::ArchiveMemberPtr _file;
 
-	const uint32 *findFile(const Common::String &name) const;
+	const uint32 *findFile(const Common::Path &path) const;
 
 	const uint16 _entryCount;
 	const uint32 *const _fileEntries;
@@ -82,7 +82,7 @@ private:
 class CachedArchive : public Common::Archive {
 public:
 	struct InputEntry {
-		Common::String name;
+		Common::Path name;
 
 		byte *data;
 		uint32 size;
@@ -103,7 +103,7 @@ private:
 		uint32 size;
 	};
 
-	typedef Common::HashMap<Common::String, Entry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, Entry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _files;
 };
 
@@ -111,40 +111,40 @@ private:
 class ResArchiveLoader {
 public:
 	virtual ~ResArchiveLoader() {}
-	virtual bool checkFilename(Common::String filename) const = 0;
+	virtual bool checkFilename(const Common::String &filename) const = 0;
 	virtual bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const = 0;
 	virtual Common::Archive *load(Common::ArchiveMemberPtr file, Common::SeekableReadStream &stream) const = 0;
 };
 
 class ResLoaderPak : public ResArchiveLoader {
 public:
-	bool checkFilename(Common::String filename) const override;
+	bool checkFilename(const Common::String &filename) const override;
 	bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const override;
 	Common::Archive *load(Common::ArchiveMemberPtr file, Common::SeekableReadStream &stream) const override;
 };
 
 class ResLoaderInsMalcolm : public ResArchiveLoader {
 public:
-	bool checkFilename(Common::String filename) const override;
+	bool checkFilename(const Common::String &filename) const override;
 	bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const override;
 	Common::Archive *load(Common::ArchiveMemberPtr file, Common::SeekableReadStream &stream) const override;
 };
 
 class ResLoaderTlk : public ResArchiveLoader {
 public:
-	bool checkFilename(Common::String filename) const override;
+	bool checkFilename(const Common::String &filename) const override;
 	bool isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const override;
 	Common::Archive *load(Common::ArchiveMemberPtr file, Common::SeekableReadStream &stream) const override;
 };
 
 class InstallerLoader {
 public:
-	static Common::Archive *load(Resource *owner, const Common::String &filename, const Common::String &extension, const uint8 offset);
+	static Common::Archive *load(Resource *owner, const Common::Path &filename, const Common::String &extension, const uint8 offset);
 };
 
 class StuffItLoader {
 public:
-	static Common::Archive *load(Resource *owner, const Common::String &filename);
+	static Common::Archive *load(Resource *owner, const Common::Path &filename);
 	static Common::Archive *load(Resource *owner, Common::SeekableReadStream *stream, const Common::String &debugName);
 };
 
diff --git a/engines/kyra/resource/resource_segacd.cpp b/engines/kyra/resource/resource_segacd.cpp
index cf2712ffb33..c853a97af31 100644
--- a/engines/kyra/resource/resource_segacd.cpp
+++ b/engines/kyra/resource/resource_segacd.cpp
@@ -35,7 +35,7 @@ SegaCDResource::~SegaCDResource() {
 	unloadContainer();
 }
 
-bool SegaCDResource::loadContainer(const Common::String &filename, uint32 offset, uint32 size) {
+bool SegaCDResource::loadContainer(const Common::Path &filename, uint32 offset, uint32 size) {
 	if (_curFile.equals(filename) && _curOffset == offset && _curSize == size)
 		return true;
 
@@ -43,7 +43,7 @@ bool SegaCDResource::loadContainer(const Common::String &filename, uint32 offset
 
 	_str = _res->createEndianAwareReadStream(filename);
 	if (!_str) {
-		error("SegaCDResource: File '%s' not found.", filename.c_str());
+		error("SegaCDResource: File '%s' not found.", filename.toString().c_str());
 		return false;
 	}
 
diff --git a/engines/kyra/resource/resource_segacd.h b/engines/kyra/resource/resource_segacd.h
index 59cac767974..f26b71ac308 100644
--- a/engines/kyra/resource/resource_segacd.h
+++ b/engines/kyra/resource/resource_segacd.h
@@ -40,7 +40,7 @@ public:
 	SegaCDResource(Resource *res);
 	~SegaCDResource();
 
-	bool loadContainer(const Common::String &filename, uint32 offset = 0, uint32 size = 0);
+	bool loadContainer(const Common::Path &filename, uint32 offset = 0, uint32 size = 0);
 	void unloadContainer();
 
 	Common::SeekableReadStreamEndian *resStreamEndian(int resID);
@@ -60,7 +60,7 @@ private:
 	TableEntry *_resTable;
 	int _numResources;
 	Common::SeekableReadStreamEndian *_str;
-	Common::String _curFile;
+	Common::Path _curFile;
 	uint32 _curOffset;
 	uint32 _curSize;
 };
diff --git a/engines/kyra/resource/staticres.cpp b/engines/kyra/resource/staticres.cpp
index 4b796678311..8840da5358c 100644
--- a/engines/kyra/resource/staticres.cpp
+++ b/engines/kyra/resource/staticres.cpp
@@ -142,7 +142,7 @@ bool StaticResource::loadStaticResourceFile() {
 		return true;
 
 	Common::ArchiveMemberList kyraDatFiles;
-	res->listFiles(staticDataFilename(), kyraDatFiles);
+	res->listFiles(Common::Path(staticDataFilename()), kyraDatFiles);
 
 	bool foundWorkingKyraDat = false;
 	for (Common::ArchiveMemberList::iterator i = kyraDatFiles.begin(); i != kyraDatFiles.end(); ++i) {
@@ -218,7 +218,7 @@ Common::SeekableReadStream *StaticResource::loadIdMap(Common::Language lang) {
 
 
 	// load the ID map for our game
-	const Common::String filenamePattern = Common::String::format("0%01X%01X%01X000%01X", game, platform, special, lng);
+	const Common::Path filenamePattern(Common::String::format("0%01X%01X%01X000%01X", game, platform, special, lng));
 	return _vm->resource()->createReadStream(filenamePattern);
 }
 
@@ -368,7 +368,7 @@ bool StaticResource::prefetchId(int id) {
 	ResData data;
 	data.id = id;
 	data.type = dDesc->_value.type;
-	Common::SeekableReadStream *fileStream = _vm->resource()->createReadStream(Common::String::format("%08X", dDesc->_value.filename));
+	Common::SeekableReadStream *fileStream = _vm->resource()->createReadStream(Common::Path(Common::String::format("%08X", dDesc->_value.filename)));
 	if (!fileStream)
 		return false;
 
diff --git a/engines/kyra/sequence/sequences_darkmoon.cpp b/engines/kyra/sequence/sequences_darkmoon.cpp
index 8b38c104b55..46202aa834f 100644
--- a/engines/kyra/sequence/sequences_darkmoon.cpp
+++ b/engines/kyra/sequence/sequences_darkmoon.cpp
@@ -1219,7 +1219,7 @@ void DarkmoonSequenceHelper::loadScene(int index, int pageNum, bool ignorePalett
 
 	if (_config->cpsFiles) {
 		file = _config->cpsFiles[index];
-		s = _vm->resource()->createReadStream(file);
+		s = _vm->resource()->createReadStream(Common::Path(file));
 	}
 
 	if (s) {
@@ -1254,7 +1254,7 @@ void DarkmoonSequenceHelper::loadScene(int index, int pageNum, bool ignorePalett
 	} else {
 		if (!s) {
 			file.setChar('X', 0);
-			s = _vm->resource()->createReadStream(file);
+			s = _vm->resource()->createReadStream(Common::Path(file));
 		}
 
 		if (!s)
diff --git a/engines/kyra/sequence/sequences_hof.cpp b/engines/kyra/sequence/sequences_hof.cpp
index 251cc3d509c..495f29eeff4 100644
--- a/engines/kyra/sequence/sequences_hof.cpp
+++ b/engines/kyra/sequence/sequences_hof.cpp
@@ -395,7 +395,7 @@ SeqPlayer_HOF::SeqPlayer_HOF(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *syst
 
 	int tempSize = 0;
 	_vm->resource()->unloadAllPakFiles();
-	_vm->resource()->loadPakFile(StaticResource::staticDataFilename());
+	_vm->resource()->loadPakFile(Common::Path(StaticResource::staticDataFilename()));
 	const char *const *files = _vm->staticres()->loadStrings(k2SeqplayPakFiles, tempSize);
 	_vm->resource()->loadFileList(files, tempSize);
 
diff --git a/engines/kyra/sequence/sequences_lol.cpp b/engines/kyra/sequence/sequences_lol.cpp
index bbe793e1015..ad803e011c0 100644
--- a/engines/kyra/sequence/sequences_lol.cpp
+++ b/engines/kyra/sequence/sequences_lol.cpp
@@ -172,18 +172,18 @@ void LoLEngine::setupPrologueData(bool load) {
 
 	const char *const *fileList = _flags.isTalkie ? (_flags.isDemo ? fileListCDDemo : fileListCD) : (_flags.platform == Common::kPlatformFMTowns ? fileListTowns : fileListFloppy);
 
-	Common::String filename;
+	Common::Path filename;
 	for (uint i = 0; fileList[i]; ++i) {
 		filename.clear();
 
 		if (_flags.isTalkie && !_flags.isDemo)
-			filename = Common::String(_languageExt[_lang]) + "/";
+			filename = Common::Path(_languageExt[_lang]);
 
-		filename += fileList[i];
+		filename.joinInPlace(fileList[i]);
 
 		if (load) {
 			if (!_res->loadPakFile(filename))
-				error("Couldn't load file: '%s'", filename.c_str());
+				error("Couldn't load file: '%s'", filename.toString().c_str());
 		} else {
 			_res->unloadPakFile(filename);
 		}
@@ -1064,18 +1064,18 @@ void LoLEngine::setupEpilogueData(bool load) {
 	const char *const *fileList = _flags.isTalkie ? fileListCD : (_flags.platform == Common::kPlatformFMTowns ? fileListTowns : fileListFloppy);
 	assert(fileList);
 
-	Common::String filename;
+	Common::Path filename;
 	for (uint i = 0; fileList[i]; ++i) {
 		filename.clear();
 
 		if (_flags.isTalkie)
-			filename = Common::String(_languageExt[_lang]) + "/";
+			filename = Common::Path(_languageExt[_lang]);
 
-		filename += fileList[i];
+		filename.joinInPlace(fileList[i]);
 
 		if (load) {
 			if (!_res->loadPakFile(filename))
-				error("Couldn't load file: '%s'", filename.c_str());
+				error("Couldn't load file: '%s'", filename.toString().c_str());
 		} else {
 			_res->unloadPakFile(filename);
 		}
diff --git a/engines/kyra/sound/sound.cpp b/engines/kyra/sound/sound.cpp
index 21412256b54..90706ed88c8 100644
--- a/engines/kyra/sound/sound.cpp
+++ b/engines/kyra/sound/sound.cpp
@@ -77,12 +77,12 @@ int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volum
 }
 
 Audio::SeekableAudioStream *Sound::getVoiceStream(const char *file) const {
-	Common::String filename;
+	Common::Path filename;
 
 	Audio::SeekableAudioStream *audioStream = nullptr;
 	for (int i = 0; _supportedCodecs[i].fileext; ++i) {
 		filename = file;
-		filename += _supportedCodecs[i].fileext;
+		filename.appendInPlace(_supportedCodecs[i].fileext);
 
 		Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
 		if (!stream)
@@ -213,13 +213,13 @@ void MixedSoundDriver::loadSoundFile(uint file) {
 	_sfx->loadSoundFile(file);
 }
 
-void MixedSoundDriver::loadSoundFile(Common::String file) {
+void MixedSoundDriver::loadSoundFile(const Common::Path &file) {
 	_music->loadSoundFile(file);
-	_sfx->loadSoundFile(Common::move(file));
+	_sfx->loadSoundFile(file);
 }
 
-void MixedSoundDriver::loadSfxFile(Common::String file) {
-	_sfx->loadSoundFile(Common::move(file));
+void MixedSoundDriver::loadSfxFile(const Common::Path &file) {
+	_sfx->loadSoundFile(file);
 }
 
 void MixedSoundDriver::playTrack(uint8 track) {
diff --git a/engines/kyra/sound/sound.h b/engines/kyra/sound/sound.h
index d9f1c76b94c..27fe22d6e62 100644
--- a/engines/kyra/sound/sound.h
+++ b/engines/kyra/sound/sound.h
@@ -165,18 +165,18 @@ public:
 	 * Load a sound file for playing music
 	 * (and sometimes sound effects) from.
 	 */
-	virtual void loadSoundFile(Common::String file) = 0;
+	virtual void loadSoundFile(const Common::Path &file) = 0;
 
 	/**
 	* Unload a specifc sound file that has been loaded before.
 	*/
-	virtual void unloadSoundFile(Common::String file) {}
+	virtual void unloadSoundFile(const Common::String &file) {}
 
 	/**
 	 * Load a sound file for playing sound
 	 * effects from.
 	 */
-	virtual void loadSfxFile(Common::String file) {}
+	virtual void loadSfxFile(const Common::Path &file) {}
 
 	/**
 	 * Plays the specified track.
@@ -342,9 +342,9 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String file) override;
+	void loadSoundFile(const Common::Path &file) override;
 
-	void loadSfxFile(Common::String file) override;
+	void loadSfxFile(const Common::Path &file) override;
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
diff --git a/engines/kyra/sound/sound_amiga_eob.cpp b/engines/kyra/sound/sound_amiga_eob.cpp
index 42cd28e6153..ed84aeb35ce 100644
--- a/engines/kyra/sound/sound_amiga_eob.cpp
+++ b/engines/kyra/sound/sound_amiga_eob.cpp
@@ -76,12 +76,12 @@ void SoundAmiga_EoB::selectAudioResourceSet(int set) {
 	_currentResourceSet = set;
 }
 
-void SoundAmiga_EoB::loadSoundFile(Common::String file) {
+void SoundAmiga_EoB::loadSoundFile(const Common::Path &file) {
 	if (!_ready)
 		return;
 
 	Common::SeekableReadStream *in = _vm->resource()->createReadStream(file);
-	debugC(6, kDebugLevelSound, "SoundAmiga_EoB::loadSoundFile(): Attempting to load sound file '%s'...%s", file.c_str(), in ? "SUCCESS" : "FILE NOT FOUND");
+	debugC(6, kDebugLevelSound, "SoundAmiga_EoB::loadSoundFile(): Attempting to load sound file '%s'...%s", file.toString().c_str(), in ? "SUCCESS" : "FILE NOT FOUND");
 	if (!in)
 		return;
 
@@ -110,17 +110,17 @@ void SoundAmiga_EoB::loadSoundFile(Common::String file) {
 	} else if (cmp == 4) {
 		Screen::decodeFrame4(_fileBuffer, buf, outSize);
 	} else {
-		error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.c_str());
+		error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.toString().c_str());
 	}
 
 	Common::MemoryReadStream soundFile(buf, outSize);
 	if (!_driver->loadRessourceFile(&soundFile))
-		error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.c_str());
+		error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.toString().c_str());
 
 	delete[] buf;
 }
 
-void SoundAmiga_EoB::unloadSoundFile(Common::String file) {
+void SoundAmiga_EoB::unloadSoundFile(const Common::String &file) {
 	if (!_ready)
 		return;
 	debugC(5, kDebugLevelSound, "SoundAmiga_EoB::unloadSoundFile(): Attempting to free resource '%s'...%s", file.c_str(), _driver->stopSound(file) ? "SUCCESS" : "FAILURE");
diff --git a/engines/kyra/sound/sound_digital_mr.cpp b/engines/kyra/sound/sound_digital_mr.cpp
index e14447300b0..71e1a291e54 100644
--- a/engines/kyra/sound/sound_digital_mr.cpp
+++ b/engines/kyra/sound/sound_digital_mr.cpp
@@ -150,10 +150,10 @@ int SoundDigital_MR::playSound(const char *filename, uint8 priority, Audio::Mixe
 	Common::SeekableReadStream *stream = nullptr;
 	int usedCodec = -1;
 	for (int i = 0; _supportedCodecs[i].fileext; ++i) {
-		Common::String file = filename;
-		file += _supportedCodecs[i].fileext;
+		Common::Path file(filename);
+		file.appendInPlace(_supportedCodecs[i].fileext);
 
-		if (!_vm->resource()->exists(file.c_str()))
+		if (!_vm->resource()->exists(file))
 			continue;
 
 		stream = _vm->resource()->createReadStream(file);
diff --git a/engines/kyra/sound/sound_intern.h b/engines/kyra/sound/sound_intern.h
index f31cb36a69e..f25c88676ae 100644
--- a/engines/kyra/sound/sound_intern.h
+++ b/engines/kyra/sound/sound_intern.h
@@ -70,8 +70,8 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String file) override;
-	void loadSfxFile(Common::String file) override;
+	void loadSoundFile(const Common::Path &file) override;
+	void loadSfxFile(const Common::Path &file) override;
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -93,7 +93,7 @@ private:
 	bool _fadeMusicOut;
 
 	// Midi file related
-	Common::String _mFileName, _sFileName;
+	Common::Path _mFileName, _sFileName;
 	byte *_musicFile, *_sfxFile;
 
 	MidiParser *_music;
@@ -105,7 +105,7 @@ private:
 
 	// misc
 	kType _type;
-	Common::String getFileName(const Common::String &str);
+	Common::Path getFileName(const Common::Path &str);
 
 	bool _nativeMT32;
 	MidiDriver *_driver;
@@ -128,7 +128,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String) override {}
+	void loadSoundFile(const Common::Path &) override {}
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -182,7 +182,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String file) override;
+	void loadSoundFile(const Common::Path &file) override;
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -218,7 +218,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override {}
-	void loadSoundFile(Common::String file) override;
+	void loadSoundFile(const Common::Path &file) override;
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -333,7 +333,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String) override {}
+	void loadSoundFile(const Common::Path &) override {}
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -369,7 +369,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint) const override { return true; }
 	void loadSoundFile(uint) override {}
-	void loadSoundFile(Common::String) override {}
+	void loadSoundFile(const Common::Path &) override {}
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
 	void playSoundEffect(uint16 track, uint8) override;
@@ -423,7 +423,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String name) override;
+	void loadSoundFile(const Common::Path &name) override;
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -477,8 +477,8 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override { return false; }
 	void loadSoundFile(uint) override {}
-	void loadSoundFile(Common::String file) override;
-	void unloadSoundFile(Common::String file) override;
+	void loadSoundFile(const Common::Path &file) override;
+	void unloadSoundFile(const Common::String &file) override;
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
 	void playSoundEffect(uint16 track, uint8 volume = 0xFF) override;
@@ -513,8 +513,8 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override { return false; }
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String file) override {}
-	void loadSfxFile(Common::String file) override;
+	void loadSoundFile(const Common::Path &file) override {}
+	void loadSfxFile(const Common::Path &file) override;
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
 	void playSoundEffect(uint16 track, uint8) override;
@@ -548,7 +548,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override { return true; }
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String name) override;
+	void loadSoundFile(const Common::Path &name) override;
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -580,7 +580,7 @@ private:
 	SoundResourceInfo_PC *_resInfo[3];
 	int _currentResourceSet;
 
-	Common::String _soundFileLoaded;
+	Common::Path _soundFileLoaded;
 
 	MidiDriver::DeviceHandle _dev;
 	kType _drvType;
@@ -600,7 +600,7 @@ public:
 	void selectAudioResourceSet(int) override {}
 	bool hasSoundFile(uint file) const override { return false; }
 	void loadSoundFile(uint file) override {}
-	void loadSoundFile(Common::String file) override {}
+	void loadSoundFile(const Common::Path &file) override {}
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
 	void playSoundEffect(uint16 track, uint8 volume) override;
diff --git a/engines/kyra/sound/sound_lol.cpp b/engines/kyra/sound/sound_lol.cpp
index 134e660827d..cd9eee505cf 100644
--- a/engines/kyra/sound/sound_lol.cpp
+++ b/engines/kyra/sound/sound_lol.cpp
@@ -251,7 +251,7 @@ void LoLEngine::snd_loadSoundFile(int track) {
 	int t = (track - 250) * 3;
 	if (t < 0 || (_curMusicFileIndex == _musicTrackMap[t] && _curMusicFileExt == (char)_musicTrackMap[t + 1]))
 		return;
-	_sound->loadSoundFile(Common::String::format("LORE%02d%c", _musicTrackMap[t], (char)_musicTrackMap[t + 1]));
+	_sound->loadSoundFile(Common::Path(Common::String::format("LORE%02d%c", _musicTrackMap[t], (char)_musicTrackMap[t + 1])));
 	_curMusicFileIndex = _musicTrackMap[t];
 	_curMusicFileExt = (char)_musicTrackMap[t + 1];
 }
diff --git a/engines/kyra/sound/sound_mac_lok.cpp b/engines/kyra/sound/sound_mac_lok.cpp
index 52819e54b4e..5826f7381bc 100644
--- a/engines/kyra/sound/sound_mac_lok.cpp
+++ b/engines/kyra/sound/sound_mac_lok.cpp
@@ -54,7 +54,7 @@ bool SoundMacRes::init() {
 	if (!_resMan)
 		return false;
 
-	_kyraMacExe = _stuffItArchive ? "Legend of Kyrandia\xaa" : Util::findMacResourceFile("Legend of Kyrandia");
+	_kyraMacExe = _stuffItArchive ? Common::Path("Legend of Kyrandia\xaa") : Util::findMacResourceFile("Legend of Kyrandia");
 	if (_kyraMacExe.empty() && _isTalkie)
 		_kyraMacExe = Util::findMacResourceFile("LK");
 
@@ -99,23 +99,23 @@ Common::SeekableReadStream *SoundMacRes::getResource(uint16 id, uint32 type) {
 
 bool SoundMacRes::setQuality(bool hi) {
 	Common::StackLock lock(_mutex);
-	Common::String s[2];
+	Common::Path s[2];
 	s[0] = hi ? "HQ_Music.res" : "LQ_Music.res";
 	s[1] = _kyraMacExe;
 	int err = 0;
 
 	if (_stuffItArchive) {
 		for (int i = 0; i < 2; ++i)
-			err |= (_resMan[i].open(Common::Path(s[i]), *_stuffItArchive) ? 0 : (1 << i));
+			err |= (_resMan[i].open(s[i], *_stuffItArchive) ? 0 : (1 << i));
 	} else {
 		for (int i = 0; i < 2; ++i)
-			err |= (_resMan[i].open(Common::Path(s[i])) ? 0 : (1 << i));
+			err |= (_resMan[i].open(s[i]) ? 0 : (1 << i));
 	}
 
 	if (err) {
 		for (int i = 0; i < 2; ++i) {
 			if (err & (1 << i))
-				warning("SoundMacRes::setQuality(): Error opening resource container: '%s'", s[i].c_str());
+				warning("SoundMacRes::setQuality(): Error opening resource container: '%s'", s[i].toString().c_str());
 		}
 		return false;
 	}
diff --git a/engines/kyra/sound/sound_mac_res.h b/engines/kyra/sound/sound_mac_res.h
index bc2c40287a6..d502c60e1cd 100644
--- a/engines/kyra/sound/sound_mac_res.h
+++ b/engines/kyra/sound/sound_mac_res.h
@@ -45,7 +45,7 @@ public:
 	Common::SeekableReadStream *getResource(uint16 id, uint32 type);
 
 private:
-	Common::String _kyraMacExe;
+	Common::Path _kyraMacExe;
 	Common::MacResManager *_resMan;
 	Common::Archive *_stuffItArchive;
 	Common::Mutex _mutex;
diff --git a/engines/kyra/sound/sound_pc98_darkmoon.cpp b/engines/kyra/sound/sound_pc98_darkmoon.cpp
index 1b70b0395e8..e1111d6c131 100644
--- a/engines/kyra/sound/sound_pc98_darkmoon.cpp
+++ b/engines/kyra/sound/sound_pc98_darkmoon.cpp
@@ -89,27 +89,28 @@ void SoundPC98_Darkmoon::loadSoundFile(uint file) {
 		loadSoundFile(res()->fileList[file]);
 }
 
-void SoundPC98_Darkmoon::loadSoundFile(Common::String name) {
+void SoundPC98_Darkmoon::loadSoundFile(const Common::Path &name) {
 	if (!_ready)
 		return;
 
 	haltTrack();
 	stopAllSoundEffects();
 
-	name += (_drvType == kPC98 ? ".SDO" : ".SDM");
-	if (!_ready || _soundFileLoaded == name)
+	Common::Path path(name);
+	path.appendInPlace(_drvType == kPC98 ? ".SDO" : ".SDM");
+	if (!_ready || _soundFileLoaded == path)
 		return;
 
-	Common::SeekableReadStream *in = _vm->resource()->createReadStream(name.c_str());
+	Common::SeekableReadStream *in = _vm->resource()->createReadStream(path);
 	if (!in)
-		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
+		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
 
 	uint16 sz = in->readUint16LE();
 	uint8 cmp = in->readByte();
 	in->seek(1, SEEK_CUR);
 	uint32 outSize = in->readUint32LE();
 	if ((cmp == 0 && outSize > 10500) || (cmp != 0 && outSize > 20600))
-		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
+		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
 	sz -= in->pos();
 	in->seek(2, SEEK_CUR);
 
@@ -126,12 +127,12 @@ void SoundPC98_Darkmoon::loadSoundFile(Common::String name) {
 	} else if (cmp == 4) {
 		Screen::decodeFrame4(_fileBuffer, _soundData, outSize);
 	} else {
-		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
+		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
 	}
 
 	uint16 instrOffs = READ_LE_UINT16(_soundData);
 	if (instrOffs >= 20600)
-		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
+		error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
 	
 	_driver->loadFMInstruments(_soundData + instrOffs);
 	_driver->reset();
diff --git a/engines/kyra/sound/sound_pc98_eob.cpp b/engines/kyra/sound/sound_pc98_eob.cpp
index 1bade38bd66..e2134fb6ce7 100644
--- a/engines/kyra/sound/sound_pc98_eob.cpp
+++ b/engines/kyra/sound/sound_pc98_eob.cpp
@@ -78,7 +78,7 @@ void SoundPC98_EoB::loadSoundFile(uint file) {
 	delete s;
 }
 
-void SoundPC98_EoB::loadSfxFile(Common::String file) {
+void SoundPC98_EoB::loadSfxFile(const Common::Path &file) {
 	if (!_ready)
 		return;
 
diff --git a/engines/kyra/sound/sound_pc98_lok.cpp b/engines/kyra/sound/sound_pc98_lok.cpp
index 0e255dfe6c7..5d345337916 100644
--- a/engines/kyra/sound/sound_pc98_lok.cpp
+++ b/engines/kyra/sound/sound_pc98_lok.cpp
@@ -85,9 +85,9 @@ void SoundPC98_LoK::loadSoundFile(uint) {
 	}
 }
 
-void SoundPC98_LoK::loadSoundFile(Common::String file) {
+void SoundPC98_LoK::loadSoundFile(const Common::Path &file) {
 	delete[] _sfxTrackData;
-	_sfxTrackData = _vm->resource()->fileData(file.c_str(), nullptr);
+	_sfxTrackData = _vm->resource()->fileData(file, nullptr);
 }
 
 void SoundPC98_LoK::playTrack(uint8 track) {
diff --git a/engines/kyra/sound/sound_pc98_v2.cpp b/engines/kyra/sound/sound_pc98_v2.cpp
index 678b2742dae..9da52b43a57 100644
--- a/engines/kyra/sound/sound_pc98_v2.cpp
+++ b/engines/kyra/sound/sound_pc98_v2.cpp
@@ -107,9 +107,9 @@ bool SoundTownsPC98_v2::hasSoundFile(uint file) const {
 	return false;
 }
 
-void SoundTownsPC98_v2::loadSoundFile(Common::String file) {
+void SoundTownsPC98_v2::loadSoundFile(const Common::Path &file) {
 	delete[] _sfxTrackData;
-	_sfxTrackData = _vm->resource()->fileData(file.c_str(), nullptr);
+	_sfxTrackData = _vm->resource()->fileData(file, nullptr);
 }
 
 void SoundTownsPC98_v2::process() {
diff --git a/engines/kyra/sound/sound_pc_midi.cpp b/engines/kyra/sound/sound_pc_midi.cpp
index 1a655af8365..18b4088e5c6 100644
--- a/engines/kyra/sound/sound_pc_midi.cpp
+++ b/engines/kyra/sound/sound_pc_midi.cpp
@@ -232,14 +232,14 @@ void SoundMidiPC::loadSoundFile(uint file) {
 		loadSoundFile(res()->fileList[file]);
 }
 
-void SoundMidiPC::loadSoundFile(Common::String file) {
+void SoundMidiPC::loadSoundFile(const Common::Path &file) {
 	Common::StackLock lock(_mutex);
-	file = getFileName(file);
+	Common::Path path = getFileName(file);
 
-	if (_mFileName == file)
+	if (_mFileName == path)
 		return;
 
-	if (!_vm->resource()->exists(file.c_str()))
+	if (!_vm->resource()->exists(path))
 		return;
 
 	haltTrack();
@@ -249,8 +249,8 @@ void SoundMidiPC::loadSoundFile(Common::String file) {
 
 	delete[] _musicFile;
 	uint32 fileSize = 0;
-	_musicFile = _vm->resource()->fileData(file.c_str(), &fileSize);
-	_mFileName = file;
+	_musicFile = _vm->resource()->fileData(path, &fileSize);
+	_mFileName = path;
 
 	_music->loadMusic(_musicFile, fileSize);
 
@@ -269,7 +269,7 @@ void SoundMidiPC::loadSoundFile(Common::String file) {
 	// are sent in a different order, but that makes no practical difference.)
 	// The initial pitch bend neutral events are then sent again when the track
 	// loops.
-	if (file == "LOREINTR.XMI" && fileSize >= 0x6221 && _musicFile[0x6210] == 0xE1) {
+	if (path == "LOREINTR.XMI" && fileSize >= 0x6221 && _musicFile[0x6210] == 0xE1) {
 		// MT-32 floppy version.
 
 		// Overwrite first pitch bend event with for loop event.
@@ -281,7 +281,7 @@ void SoundMidiPC::loadSoundFile(Common::String file) {
 		_musicFile[0x621F] = 0xE1;
 		_musicFile[0x6220] = 0x00;
 		_musicFile[0x6221] = 0x40;
-	} else if (file == "LOREINTR.C55" && fileSize >= 0x216D && _musicFile[0x215C] == 0xE0) {
+	} else if (path == "LOREINTR.C55" && fileSize >= 0x216D && _musicFile[0x215C] == 0xE0) {
 		// GM floppy and CD version.
 
 		// Overwrite first pitch bend event with for loop event.
@@ -304,19 +304,19 @@ void SoundMidiPC::loadSoundFile(Common::String file) {
 	}
 }
 
-void SoundMidiPC::loadSfxFile(Common::String file) {
+void SoundMidiPC::loadSfxFile(const Common::Path &file) {
 	Common::StackLock lock(_mutex);
 
 	// Kyrandia 1 doesn't use a special sfx file
 	if (_vm->game() == GI_KYRA1)
 		return;
 
-	file = getFileName(file);
+	Common::Path path = getFileName(file);
 
-	if (_sFileName == file)
+	if (_sFileName == path)
 		return;
 
-	if (!_vm->resource()->exists(file.c_str()))
+	if (!_vm->resource()->exists(path))
 		return;
 
 	stopAllSoundEffects();
@@ -324,8 +324,8 @@ void SoundMidiPC::loadSfxFile(Common::String file) {
 	delete[] _sfxFile;
 
 	uint32 fileSize = 0;
-	_sfxFile = _vm->resource()->fileData(file.c_str(), &fileSize);
-	_sFileName = file;
+	_sfxFile = _vm->resource()->fileData(path, &fileSize);
+	_sFileName = path;
 
 	for (int i = 0; i < 3; ++i) {
 		_sfx[i]->loadMusic(_sfxFile, fileSize);
@@ -437,19 +437,19 @@ void SoundMidiPC::onTimer(void *data) {
 	}
 }
 
-Common::String SoundMidiPC::getFileName(const Common::String &str) {
-	Common::String file = str;
+Common::Path SoundMidiPC::getFileName(const Common::Path &str) {
+	Common::Path file(str);
 	if (_type == kMidiMT32)
-		file += ".XMI";
+		file.appendInPlace(".XMI");
 	else if (_type == kMidiGM)
-		file += ".C55";
+		file.appendInPlace(".C55");
 	else if (_type == kPCSpkr)
-		file += ".PCS";
+		file.appendInPlace(".PCS");
 
-	if (_vm->resource()->exists(file.c_str()))
+	if (_vm->resource()->exists(file))
 		return file;
 
-	return str + ".XMI";
+	return str.append(".XMI");
 }
 
 } // End of namespace Kyra
diff --git a/engines/kyra/sound/sound_pc_v1.cpp b/engines/kyra/sound/sound_pc_v1.cpp
index adc6a5e8e8e..4af86ebca52 100644
--- a/engines/kyra/sound/sound_pc_v1.cpp
+++ b/engines/kyra/sound/sound_pc_v1.cpp
@@ -211,13 +211,14 @@ void SoundPC_v1::loadSoundFile(uint file) {
 		internalLoadFile(res()->fileList[file]);
 }
 
-void SoundPC_v1::loadSoundFile(Common::String file) {
-	internalLoadFile(Common::move(file));
+void SoundPC_v1::loadSoundFile(const Common::Path &file) {
+	internalLoadFile(file);
 }
 
-void SoundPC_v1::internalLoadFile(Common::String file) {
-	file += ((_version == 1) ? ".DAT" : (_type == kPCSpkr ? ".SND" : ".ADL"));
-	if (_soundFileLoaded == file)
+void SoundPC_v1::internalLoadFile(const Common::Path &file) {
+	Common::Path path(file);
+	path.appendInPlace((_version == 1) ? ".DAT" : (_type == kPCSpkr ? ".SND" : ".ADL"));
+	if (_soundFileLoaded == path)
 		return;
 
 	if (_soundDataPtr)
@@ -225,9 +226,9 @@ void SoundPC_v1::internalLoadFile(Common::String file) {
 
 	uint8 *fileData = nullptr; uint32 fileSize = 0;
 
-	fileData = _vm->resource()->fileData(file.c_str(), &fileSize);
+	fileData = _vm->resource()->fileData(path, &fileSize);
 	if (!fileData) {
-		warning("Couldn't find music file: '%s'", file.c_str());
+		warning("Couldn't find music file: '%s'", path.toString().c_str());
 		return;
 	}
 
@@ -259,7 +260,7 @@ void SoundPC_v1::internalLoadFile(Common::String file) {
 	delete[] fileData;
 	delete[] oldData;
 
-	_soundFileLoaded = file;
+	_soundFileLoaded = path;
 }
 
 } // End of namespace Kyra
diff --git a/engines/kyra/sound/sound_pc_v1.h b/engines/kyra/sound/sound_pc_v1.h
index b497de8c2cf..8cf3e21516d 100644
--- a/engines/kyra/sound/sound_pc_v1.h
+++ b/engines/kyra/sound/sound_pc_v1.h
@@ -62,7 +62,7 @@ public:
 	void selectAudioResourceSet(int set) override;
 	bool hasSoundFile(uint file) const override;
 	void loadSoundFile(uint file) override;
-	void loadSoundFile(Common::String file) override;
+	void loadSoundFile(const Common::Path &file) override;
 
 	void playTrack(uint8 track) override;
 	void haltTrack() override;
@@ -75,7 +75,7 @@ public:
 	int checkTrigger() override;
 	void resetTrigger() override;
 private:
-	void internalLoadFile(Common::String file);
+	void internalLoadFile(const Common::Path &file);
 
 	void play(uint8 track, uint8 volume);
 
@@ -91,7 +91,7 @@ private:
 	uint8 *_soundDataPtr;
 	int _sfxPlayingSound;
 
-	Common::String _soundFileLoaded;
+	Common::Path _soundFileLoaded;
 
 	int _numSoundTriggers;
 	const int *_soundTriggers;
diff --git a/engines/kyra/sound/sound_towns_darkmoon.cpp b/engines/kyra/sound/sound_towns_darkmoon.cpp
index 3c81a15a849..35d0b76d07a 100644
--- a/engines/kyra/sound/sound_towns_darkmoon.cpp
+++ b/engines/kyra/sound/sound_towns_darkmoon.cpp
@@ -123,10 +123,10 @@ void SoundTowns_Darkmoon::loadSoundFile(uint file) {
 		loadSoundFile(_fileList[file]);
 }
 
-void SoundTowns_Darkmoon::loadSoundFile(Common::String name) {
-	Common::SeekableReadStream *s = _vm->resource()->createReadStream(Common::String::format("%s.SDT", name.c_str()));
+void SoundTowns_Darkmoon::loadSoundFile(const Common::Path &name) {
+	Common::SeekableReadStream *s = _vm->resource()->createReadStream(name.append(".SDT"));
 	if (!s)
-		error("Failed to load sound file '%s.SDT'", name.c_str());
+		error("Failed to load sound file '%s.SDT'", name.toString().c_str());
 
 	for (int i = 0; i < 120; i++) {
 		_soundTable[i].type = s->readSByte();
@@ -137,7 +137,7 @@ void SoundTowns_Darkmoon::loadSoundFile(Common::String name) {
 	delete s;
 
 	uint32 bytesLeft;
-	uint8 *pmb = _vm->resource()->fileData(Common::String::format("%s.PMB", name.c_str()).c_str(), &bytesLeft);
+	uint8 *pmb = _vm->resource()->fileData(name.append(".PMB"), &bytesLeft);
 
 	_vm->delay(300);
 
@@ -159,7 +159,7 @@ void SoundTowns_Darkmoon::loadSoundFile(Common::String name) {
 
 		delete[] pmb;
 	} else {
-		warning("Sound file '%s.PMB' not found.", name.c_str());
+		warning("Sound file '%s.PMB' not found.", name.toString().c_str());
 		// TODO
 	}
 }
diff --git a/engines/kyra/text/text_mr.cpp b/engines/kyra/text/text_mr.cpp
index 723a161e2f0..5bf452116fe 100644
--- a/engines/kyra/text/text_mr.cpp
+++ b/engines/kyra/text/text_mr.cpp
@@ -658,14 +658,14 @@ void KyraEngine_MR::updateDlgBuffer() {
 	if (_curDlgIndex == _mainCharacter.dlgIndex && _curDlgChapter == _currentChapter && _curDlgLang == _lang)
 		return;
 
-	Common::String dlgFile = Common::String::format("CH%.02d-S%.02d.%s", _currentChapter, _mainCharacter.dlgIndex, _languageExtension[_lang]);
-	Common::String cnvFile = Common::String::format("CH%.02d-S%.02d.CNV", _currentChapter, _mainCharacter.dlgIndex);
+	Common::Path dlgFile(Common::String::format("CH%.02d-S%.02d.%s", _currentChapter, _mainCharacter.dlgIndex, _languageExtension[_lang]));
+	Common::Path cnvFile(Common::String::format("CH%.02d-S%.02d.CNV", _currentChapter, _mainCharacter.dlgIndex));
 
 	delete _cnvFile;
 	delete _dlgBuffer;
 
-	_res->exists(cnvFile.c_str(), true);
-	_res->exists(dlgFile.c_str(), true);
+	_res->exists(cnvFile, true);
+	_res->exists(dlgFile, true);
 	_cnvFile = _res->createReadStream(cnvFile);
 	_dlgBuffer = _res->createReadStream(dlgFile);
 	assert(_cnvFile);


Commit: 244ee1b79e2d12f32c3e1c9931f2284b50a83216
    https://github.com/scummvm/scummvm/commit/244ee1b79e2d12f32c3e1c9931f2284b50a83216
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
LAB: Migrate engine to Path

Changed paths:
    engines/lab/lab.cpp
    engines/lab/resource.cpp
    engines/lab/resource.h


diff --git a/engines/lab/lab.cpp b/engines/lab/lab.cpp
index 0f2f2dd4766..053d94a8de8 100644
--- a/engines/lab/lab.cpp
+++ b/engines/lab/lab.cpp
@@ -130,7 +130,7 @@ LabEngine::LabEngine(OSystem *syst, const ADGameDescription *gameDesc)
 		_highPalette[i] = 0;
 	_introPlaying = false;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "game", 0, 4);
 }
 
diff --git a/engines/lab/resource.cpp b/engines/lab/resource.cpp
index 2ba6206ce61..261e0ca8e35 100644
--- a/engines/lab/resource.cpp
+++ b/engines/lab/resource.cpp
@@ -143,7 +143,7 @@ void Resource::readViews(uint16 roomNum) {
 	delete dataFile;
 }
 
-Common::String Resource::translateFileName(const Common::String filename) {
+Common::Path Resource::translateFileName(const Common::String &filename) {
 	Common::String upperFilename;
 
 	// The DOS and Windows version aren't looking for the right file,
@@ -213,7 +213,7 @@ Common::String Resource::translateFileName(const Common::String filename) {
 
 	fileNameStrFinal += upperFilename;
 
-	return fileNameStrFinal;
+	return Common::Path(fileNameStrFinal);
 }
 
 Common::File *Resource::openDataFile(const Common::String filename, uint32 fileHeader) {
@@ -227,13 +227,13 @@ Common::File *Resource::openDataFile(const Common::String filename, uint32 fileH
 			delete dataFile;
 			return nullptr;
 		} else
-			error("openDataFile: Couldn't open %s (%s)", translateFileName(filename).c_str(), filename.c_str());
+			error("openDataFile: Couldn't open %s (%s)", translateFileName(filename).toString().c_str(), filename.c_str());
 	}
 	if (fileHeader > 0) {
 		uint32 headerTag = dataFile->readUint32BE();
 		if (headerTag != fileHeader) {
 			dataFile->close();
-			error("openDataFile: Unexpected header in %s (%s) - expected: %d, got: %d", translateFileName(filename).c_str(), filename.c_str(), fileHeader, headerTag);
+			error("openDataFile: Unexpected header in %s (%s) - expected: %d, got: %d", translateFileName(filename).toString().c_str(), filename.c_str(), fileHeader, headerTag);
 		}
 	}
 
diff --git a/engines/lab/resource.h b/engines/lab/resource.h
index cd03bb1afdb..b5dfa0ad34d 100644
--- a/engines/lab/resource.h
+++ b/engines/lab/resource.h
@@ -113,7 +113,7 @@ private:
 	void readCloseUps(uint16 depth, Common::File *file, CloseDataList &close);
 	void readView(Common::File *file, ViewDataList &view);
 	void readStaticText();
-	Common::String translateFileName(const Common::String filename);
+	Common::Path translateFileName(const Common::String &filename);
 
 	Common::String _staticText[48];
 };


Commit: 1a31b42ca4e1d7cc75c5cf36201f15b7b7d178a9
    https://github.com/scummvm/scummvm/commit/1a31b42ca4e1d7cc75c5cf36201f15b7b7d178a9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
LASTEXPRESS: Migrate engine to Path

Changed paths:
    engines/lastexpress/data/archive.cpp
    engines/lastexpress/data/archive.h
    engines/lastexpress/debug.cpp
    engines/lastexpress/lastexpress.cpp
    engines/lastexpress/resource.cpp
    engines/lastexpress/resource.h
    engines/lastexpress/sound/entry.cpp
    engines/lastexpress/sound/entry.h


diff --git a/engines/lastexpress/data/archive.cpp b/engines/lastexpress/data/archive.cpp
index fd93ac7c178..901c790aca6 100644
--- a/engines/lastexpress/data/archive.cpp
+++ b/engines/lastexpress/data/archive.cpp
@@ -32,17 +32,17 @@
 
 namespace LastExpress {
 
-HPFArchive::HPFArchive(const Common::String &path) {
+HPFArchive::HPFArchive(const Common::Path &path) {
 	_filename = path;
 
 	// Open a stream to the archive
 	Common::SeekableReadStream *archive = SearchMan.createReadStreamForMember(_filename);
 	if (!archive) {
-		debugC(2, kLastExpressDebugResource, "Error opening file: %s", path.c_str());
+		debugC(2, kLastExpressDebugResource, "Error opening file: %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
-	debugC(2, kLastExpressDebugResource, "Opened archive: %s", path.c_str());
+	debugC(2, kLastExpressDebugResource, "Opened archive: %s", path.toString(Common::Path::kNativeSeparator).c_str());
 
 	// Read header to get the number of files
 	uint32 numFiles = archive->readUint32LE();
@@ -90,11 +90,10 @@ int HPFArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr HPFArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *HPFArchive::createReadStreamForMember(const Common::Path &path) const {
diff --git a/engines/lastexpress/data/archive.h b/engines/lastexpress/data/archive.h
index a2c46ccd9cd..a511323e679 100644
--- a/engines/lastexpress/data/archive.h
+++ b/engines/lastexpress/data/archive.h
@@ -43,7 +43,7 @@ namespace LastExpress {
 
 class HPFArchive : public Common::Archive {
 public:
-	HPFArchive(const Common::String &path);
+	HPFArchive(const Common::Path &path);
 
 	bool hasFile(const Common::Path &path) const override;
 	int listMembers(Common::ArchiveMemberList &list) const override;
@@ -66,7 +66,7 @@ private:
 	typedef Common::HashMap<Common::String, HPFEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
 
 	FileMap _files;             ///< List of files
-	Common::String _filename;   ///< Filename of the archive
+	Common::Path _filename;   ///< Filename of the archive
 };
 
 } // End of namespace LastExpress
diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp
index 399562dbdec..e43a625815b 100644
--- a/engines/lastexpress/debug.cpp
+++ b/engines/lastexpress/debug.cpp
@@ -239,7 +239,7 @@ bool Debugger::cmdHelp(int, const char **) {
  */
 bool Debugger::cmdListFiles(int argc, const char **argv) {
 	if (argc == 2 || argc == 3) {
-		Common::String filter(const_cast<char *>(argv[1]));
+		Common::Path filter(const_cast<char *>(argv[1]));
 
 		// Load the proper archive
 		if (argc == 3) {
@@ -333,7 +333,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) {
 				return true;
 		}
 
-		if (!_engine->getResourceManager()->hasFile(filename)) {
+		if (!_engine->getResourceManager()->hasFile(Common::Path(filename))) {
 			debugPrintf("Cannot find file: %s\n", filename.c_str());
 			return true;
 		}
@@ -395,7 +395,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) {
 				return true;
 		}
 
-		if (!_engine->getResourceManager()->hasFile(filename + ".BG")) {
+		if (!_engine->getResourceManager()->hasFile(Common::Path(filename + ".BG"))) {
 			debugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str());
 			return true;
 		}
@@ -450,7 +450,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) {
 				return true;
 		}
 
-		if (!_engine->getResourceManager()->hasFile(filename)) {
+		if (!_engine->getResourceManager()->hasFile(Common::Path(filename))) {
 			debugPrintf("Cannot find file: %s\n", filename.c_str());
 			return true;
 		}
@@ -531,7 +531,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) {
 		if (!name.contains('.'))
 			name += ".SND";
 
-		if (!_engine->getResourceManager()->hasFile(name)) {
+		if (!_engine->getResourceManager()->hasFile(Common::Path(name))) {
 			debugPrintf("Cannot find file: %s\n", name.c_str());
 			return true;
 		}
@@ -567,7 +567,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) {
 
 		filename += ".sbe";
 
-		if (!_engine->getResourceManager()->hasFile(filename)) {
+		if (!_engine->getResourceManager()->hasFile(Common::Path(filename))) {
 			debugPrintf("Cannot find file: %s\n", filename.c_str());
 			return true;
 		}
@@ -633,7 +633,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) {
 		}
 
 		// If we got a nis filename, check that the file exists
-		if (name.contains('.') && !_engine->getResourceManager()->hasFile(name)) {
+		if (name.contains('.') && !_engine->getResourceManager()->hasFile(Common::Path(name))) {
 			debugPrintf("Cannot find file: %s\n", name.c_str());
 			return true;
 		}
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index b86d7f75398..842d2acdf71 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -65,7 +65,7 @@ LastExpressEngine::LastExpressEngine(OSystem *syst, const ADGameDescription *gd)
 	Engine::syncSoundSettings();
 
 	// Adding the default directories
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "data");
 }
 
diff --git a/engines/lastexpress/resource.cpp b/engines/lastexpress/resource.cpp
index 31624ee590a..f805880954b 100644
--- a/engines/lastexpress/resource.cpp
+++ b/engines/lastexpress/resource.cpp
@@ -113,11 +113,11 @@ void ResourceManager::reset() {
 	_archives.clear();
 }
 
-bool ResourceManager::loadArchive(const Common::String &name) {
+bool ResourceManager::loadArchive(const Common::Path &name) {
 	HPFArchive *archive = new HPFArchive(name);
 
 	if (archive->count() == 0) {
-		debugC(2, kLastExpressDebugResource, "Error opening archive: %s", name.c_str());
+		debugC(2, kLastExpressDebugResource, "Error opening archive: %s", name.toString(Common::Path::kNativeSeparator).c_str());
 
 		delete archive;
 
@@ -132,25 +132,25 @@ bool ResourceManager::loadArchive(const Common::String &name) {
 // Get a stream to file in the archive
 //  - same as createReadStreamForMember except it checks if the file exists and will assert / output a debug message if not
 Common::SeekableReadStream *ResourceManager::getFileStream(const Common::String &name) const {
+	Common::Path path(name);
 
 	// Check if the file exits in the archive
-	if (!hasFile(name)) {
+	if (!hasFile(path)) {
 		debugC(2, kLastExpressDebugResource, "Error opening file: %s", name.c_str());
 		return nullptr;
 	}
 
 	debugC(2, kLastExpressDebugResource, "Opening file: %s", name.c_str());
 
-	return createReadStreamForMember(name);
+	return createReadStreamForMember(path);
 }
 
 //////////////////////////////////////////////////////////////////////////
 // Archive functions
 //////////////////////////////////////////////////////////////////////////
 bool ResourceManager::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (Common::Array<HPFArchive *>::const_iterator it = _archives.begin(); it != _archives.end(); ++it) {
-		if ((*it)->hasFile(name))
+		if ((*it)->hasFile(path))
 			return true;
 	}
 
@@ -172,18 +172,15 @@ int ResourceManager::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr ResourceManager::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *ResourceManager::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (Common::Array<HPFArchive *>::const_iterator it = _archives.begin(); it != _archives.end(); ++it) {
-
-		Common::SeekableReadStream *stream = (*it)->createReadStreamForMember(name);
+		Common::SeekableReadStream *stream = (*it)->createReadStreamForMember(path);
 
 		if (stream)
 			return stream;
@@ -196,8 +193,10 @@ Common::SeekableReadStream *ResourceManager::createReadStreamForMember(const Com
 // Resource loading
 
 Background *ResourceManager::loadBackground(const Common::String &name) const {
+	Common::Path path(name);
+	path.appendInPlace(".bg");
 	// Open the resource
-	Common::SeekableReadStream *stream = createReadStreamForMember(name + ".bg");
+	Common::SeekableReadStream *stream = createReadStreamForMember(path);
 	if (!stream)
 		return nullptr;
 
diff --git a/engines/lastexpress/resource.h b/engines/lastexpress/resource.h
index 1df32e9afdf..064ba8fcd3d 100644
--- a/engines/lastexpress/resource.h
+++ b/engines/lastexpress/resource.h
@@ -57,7 +57,7 @@ public:
 private:
 	bool _isDemo;
 
-	bool loadArchive(const Common::String &name);
+	bool loadArchive(const Common::Path &name);
 	void reset();
 
 	Common::Array<HPFArchive *> _archives;
diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp
index 22f50e04dd6..4a6dcbe36b5 100644
--- a/engines/lastexpress/sound/entry.cpp
+++ b/engines/lastexpress/sound/entry.cpp
@@ -331,7 +331,7 @@ void SoundEntry::initDelayedActivate(unsigned activateDelay) {
 	_status |= kSoundFlagDelayedActivate;
 }
 
-void SoundEntry::setSubtitles(Common::String filename) {
+void SoundEntry::setSubtitles(const Common::String &filename) {
 	_subtitle = new SubtitleEntry(_engine);
 	_subtitle->load(filename, this);
 
@@ -444,7 +444,7 @@ SubtitleEntry::~SubtitleEntry() {
 	_engine = nullptr;
 }
 
-void SubtitleEntry::load(Common::String filename, SoundEntry *soundEntry) {
+void SubtitleEntry::load(const Common::String &filename, SoundEntry *soundEntry) {
 	// Add ourselves to the list of active subtitles
 	getSoundQueue()->addSubtitle(this);
 
@@ -453,7 +453,7 @@ void SubtitleEntry::load(Common::String filename, SoundEntry *soundEntry) {
 	_sound = soundEntry;
 
 	// Load subtitle data
-	if (_engine->getResourceManager()->hasFile(_filename)) {
+	if (_engine->getResourceManager()->hasFile(Common::Path(_filename))) {
 		if (getSoundQueue()->getSubtitleFlag() & 2)
 			return;
 
diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h
index ffba153b1e0..7bb8f7a7d45 100644
--- a/engines/lastexpress/sound/entry.h
+++ b/engines/lastexpress/sound/entry.h
@@ -113,7 +113,7 @@ public:
 	void initDelayedActivate(unsigned activateDelay);
 
 	// Subtitles
-	void setSubtitles(Common::String filename);
+	void setSubtitles(const Common::String &filename);
 
 	// Serializable
 	void saveLoadWithSerializer(Common::Serializer &ser) override;
@@ -183,7 +183,7 @@ public:
 	SubtitleEntry(LastExpressEngine *engine);
 	~SubtitleEntry();
 
-	void load(Common::String filename, SoundEntry *soundEntry);
+	void load(const Common::String &filename, SoundEntry *soundEntry);
 	void loadData();
 	void close();
 	void setupAndDraw();


Commit: 0df39efb81a3366913aa852e1de7088387696fdc
    https://github.com/scummvm/scummvm/commit/0df39efb81a3366913aa852e1de7088387696fdc
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
LILLIPUT: Migrate engine to Path

Changed paths:
    engines/lilliput/lilliput.cpp
    engines/lilliput/lilliput.h
    engines/lilliput/script.cpp
    engines/lilliput/sound.cpp
    engines/lilliput/sound.h


diff --git a/engines/lilliput/lilliput.cpp b/engines/lilliput/lilliput.cpp
index 6f5e3ac0556..56843e7bcef 100644
--- a/engines/lilliput/lilliput.cpp
+++ b/engines/lilliput/lilliput.cpp
@@ -2342,13 +2342,13 @@ void LilliputEngine::pollEvent() {
 	}
 }
 
-byte *LilliputEngine::loadVGA(Common::String filename, int expectedSize, bool loadPal) {
-	debugC(1, kDebugEngine, "loadVGA(%s, %d, %d)", filename.c_str(), expectedSize, (loadPal) ? 1 : 0);
+byte *LilliputEngine::loadVGA(const Common::Path &filename, int expectedSize, bool loadPal) {
+	debugC(1, kDebugEngine, "loadVGA(%s, %d, %d)", filename.toString().c_str(), expectedSize, (loadPal) ? 1 : 0);
 
 	Common::File f;
 
 	if (!f.open(filename))
-		error("Missing game file %s", filename.c_str());
+		error("Missing game file %s", filename.toString().c_str());
 
 	int remainingSize = f.size();
 	if (loadPal) {
@@ -2402,13 +2402,13 @@ byte *LilliputEngine::loadVGA(Common::String filename, int expectedSize, bool lo
 	return decodeBuffer;
 }
 
-byte *LilliputEngine::loadRaw(Common::String filename, int filesize) {
-	debugC(1, kDebugEngine, "loadRaw(%s)", filename.c_str());
+byte *LilliputEngine::loadRaw(const Common::Path &filename, int filesize) {
+	debugC(1, kDebugEngine, "loadRaw(%s)", filename.toString().c_str());
 
 	Common::File f;
 
 	if (!f.open(filename))
-		error("Missing game file %s", filename.c_str());
+		error("Missing game file %s", filename.toString().c_str());
 
 	byte *res = (byte *)malloc(sizeof(byte) * filesize);
 	for (int i = 0; i < filesize; ++i)
@@ -2431,7 +2431,7 @@ void LilliputEngine::loadRules() {
 	Common::File f;
 	uint16 curWord;
 
-	Common::String filename = "ERULES.PRG";
+	Common::Path filename("ERULES.PRG");
 	Common::Language lang = Common::parseLanguage(ConfMan.get("language"));
 
 	switch (lang) {
@@ -2451,7 +2451,7 @@ void LilliputEngine::loadRules() {
 	}
 
 	if (!f.open(filename))
-		error("Missing game file %s", filename.c_str());
+		error("Missing game file %s", filename.toString().c_str());
 
 	_word10800_ERULES = f.readUint16LE();
 
@@ -2609,8 +2609,8 @@ void LilliputEngine::loadRules() {
 	f.close();
 }
 
-void LilliputEngine::displayVGAFile(Common::String fileName) {
-	debugC(1, kDebugEngine, "displayVGAFile(%s)", fileName.c_str());
+void LilliputEngine::displayVGAFile(const Common::Path &fileName) {
+	debugC(1, kDebugEngine, "displayVGAFile(%s)", fileName.toString().c_str());
 
 	byte *buffer = loadVGA(fileName, 64000, true);
 	memcpy(_mainSurface->getPixels(), buffer, 320*200);
diff --git a/engines/lilliput/lilliput.h b/engines/lilliput/lilliput.h
index b827fbee559..5ce465823d1 100644
--- a/engines/lilliput/lilliput.h
+++ b/engines/lilliput/lilliput.h
@@ -304,11 +304,11 @@ public:
 	void homeInChooseDirection(int index);
 
 	void initGame(const LilliputGameDescription *gd);
-	byte *loadVGA(Common::String filename, int fileSize, bool loadPal);
-	byte *loadRaw(Common::String filename, int filesize);
+	byte *loadVGA(const Common::Path &filename, int fileSize, bool loadPal);
+	byte *loadRaw(const Common::Path &filename, int filesize);
 	void loadRules();
 
-	void displayVGAFile(Common::String fileName);
+	void displayVGAFile(const Common::Path &fileName);
 	void initPalette();
 	void fixPaletteEntries(uint8 *palette, int num);
 
diff --git a/engines/lilliput/script.cpp b/engines/lilliput/script.cpp
index 5ec909296c9..10aa8b84b3b 100644
--- a/engines/lilliput/script.cpp
+++ b/engines/lilliput/script.cpp
@@ -2972,7 +2972,7 @@ void LilliputScript::OC_loadAndDisplayCubesGfx() {
 
 	int setNumb = (_currScript->readUint16LE() & 0xFF);
 	assert((setNumb >= 0) && (setNumb <= 9));
-	Common::String fileName = Common::String::format("CUBES%d.GFX", setNumb);
+	Common::Path fileName(Common::String::format("CUBES%d.GFX", setNumb));
 	_cubeSet = setNumb; // Useless in this variant, keep for the moment for Rome
 
 	_vm->_bufferCubegfx = _vm->loadVGA(fileName, 61440, false);
@@ -3147,7 +3147,7 @@ void LilliputScript::OC_displayVGAFile() {
 	_vm->paletteFadeOut();
 	int curWord = _currScript->readUint16LE();
 	int index = _vm->_packedStringIndex[curWord];
-	Common::String fileName = Common::String((const char *)&_vm->_packedStrings[index]);
+	Common::Path fileName((const char *)&_vm->_packedStrings[index]);
 	_talkingCharacter = -1;
 	_vm->displayVGAFile(fileName);
 	_vm->paletteFadeIn();
diff --git a/engines/lilliput/sound.cpp b/engines/lilliput/sound.cpp
index cf1ca124ac2..f4d7b41ff9b 100644
--- a/engines/lilliput/sound.cpp
+++ b/engines/lilliput/sound.cpp
@@ -91,13 +91,13 @@ uint32 LilliputSound::decode(const byte *src, byte *dst, uint32 len, uint32 star
 	return i;
 }
 
-void LilliputSound::loadMusic(Common::String filename) {
-	debugC(1, kDebugSound, "loadMusic(%s)", filename.c_str());
+void LilliputSound::loadMusic(const Common::Path &filename) {
+	debugC(1, kDebugSound, "loadMusic(%s)", filename.toString().c_str());
 
 	Common::File f;
 
 	if (!f.open(filename))
-		error("Missing music file %s", filename.c_str());
+		error("Missing music file %s", filename.toString().c_str());
 
 	_fileNumb = f.readUint16LE();
 
diff --git a/engines/lilliput/sound.h b/engines/lilliput/sound.h
index 3ce4c7e74d5..ad2b8865665 100644
--- a/engines/lilliput/sound.h
+++ b/engines/lilliput/sound.h
@@ -55,7 +55,7 @@ private:
 	uint32 decode(const byte *src, byte *dst, uint32 len, uint32 start);
 	byte readByte(const byte *data, uint32 offset);
 
-	void loadMusic(Common::String filename);
+	void loadMusic(const Common::Path &filename);
 	void playMusic(int var1);
 
 	void send(uint32 b) override;


Commit: 8e05d9c3490a78fe189df041180ace72993f7a6d
    https://github.com/scummvm/scummvm/commit/8e05d9c3490a78fe189df041180ace72993f7a6d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
M4: Migrate engine to Path

Changed paths:
    engines/m4/adv_db_r/db_catalog.cpp
    engines/m4/fileio/fileio.cpp
    engines/m4/fileio/fileio.h
    engines/m4/fileio/fstream.cpp
    engines/m4/fileio/fstream.h
    engines/m4/fileio/info.cpp
    engines/m4/fileio/info.h
    engines/m4/fileio/sys_file.cpp
    engines/m4/fileio/sys_file.h


diff --git a/engines/m4/adv_db_r/db_catalog.cpp b/engines/m4/adv_db_r/db_catalog.cpp
index 896da437abf..65eca6240e2 100644
--- a/engines/m4/adv_db_r/db_catalog.cpp
+++ b/engines/m4/adv_db_r/db_catalog.cpp
@@ -38,9 +38,7 @@ static int compare_catalog_entries_for_search(const void *n1, const void *n2);
 bool read_catalog() {
 	Common::File f;
 	size_t size = 0;
-	Common::String myFilename;
-
-	myFilename = "roomsdb.chk";
+	Common::Path myFilename("roomsdb.chk");
 
 	if (!f.open(myFilename))
 		return false;
diff --git a/engines/m4/fileio/fileio.cpp b/engines/m4/fileio/fileio.cpp
index 5f319bab757..f963844865a 100644
--- a/engines/m4/fileio/fileio.cpp
+++ b/engines/m4/fileio/fileio.cpp
@@ -26,7 +26,7 @@
 
 namespace M4 {
 
-Common::Stream *f_io_open(const Common::String &filename, const Common::String &mode) {
+Common::Stream *f_io_open(const Common::Path &filename, const Common::String &mode) {
 	if (mode.hasPrefix("r")) {
 		if (filename.empty())
 			return nullptr;
@@ -39,7 +39,7 @@ Common::Stream *f_io_open(const Common::String &filename, const Common::String &
 		return nullptr;
 
 	} else {
-		return g_system->getSavefileManager()->openForSaving(filename);
+		return g_system->getSavefileManager()->openForSaving(filename.baseName());
 	}
 }
 
diff --git a/engines/m4/fileio/fileio.h b/engines/m4/fileio/fileio.h
index 6534b2937dc..2602aaa5de8 100644
--- a/engines/m4/fileio/fileio.h
+++ b/engines/m4/fileio/fileio.h
@@ -54,7 +54,7 @@ struct Hag_Record {
 	Hag_Record *next;
 };
 
-Common::Stream *f_io_open(const Common::String &filename, const Common::String &mode);
+Common::Stream *f_io_open(const Common::Path &filename, const Common::String &mode);
 void f_io_close(Common::Stream *stream);
 
 } // namespace M4
diff --git a/engines/m4/fileio/fstream.cpp b/engines/m4/fileio/fstream.cpp
index 3a91e839f1b..8bec05858f9 100644
--- a/engines/m4/fileio/fstream.cpp
+++ b/engines/m4/fileio/fstream.cpp
@@ -28,9 +28,9 @@ namespace M4 {
 
 #define STR_STRMREQ "stream request"
 
-StreamFile::StreamFile(const Common::String &filename) {
+StreamFile::StreamFile(const Common::Path &filename) {
 	if (!_file.open(filename))
-		error("Could not open - %s", filename.c_str());
+		error("Could not open - %s", filename.toString().c_str());
 }
 
 int32 StreamFile::read(Handle bufferHandle, int32 n) {
diff --git a/engines/m4/fileio/fstream.h b/engines/m4/fileio/fstream.h
index b7829153d8d..94710601584 100644
--- a/engines/m4/fileio/fstream.h
+++ b/engines/m4/fileio/fstream.h
@@ -33,7 +33,7 @@ class StreamFile {
 private:
 	Common::File _file;
 public:
-	StreamFile(const Common::String &filename);
+	StreamFile(const Common::Path &filename);
 	~StreamFile() {}
 
 	int32 read(Handle bufferHandle, int32 n);
diff --git a/engines/m4/fileio/info.cpp b/engines/m4/fileio/info.cpp
index d0ed99acde1..b4e27315152 100644
--- a/engines/m4/fileio/info.cpp
+++ b/engines/m4/fileio/info.cpp
@@ -23,11 +23,11 @@
 
 namespace M4 {
 
-bool f_info_exists(const Common::String &filename) {
+bool f_info_exists(const Common::Path &filename) {
 	return Common::File::exists(filename);
 }
 
-size_t f_info_get_file_size(const Common::String &filename) {
+size_t f_info_get_file_size(const Common::Path &filename) {
 	Common::File f;
 	return f.open(filename) ? f.size() : 0;
 }
diff --git a/engines/m4/fileio/info.h b/engines/m4/fileio/info.h
index 6b39ac5e8b0..7c4fba43340 100644
--- a/engines/m4/fileio/info.h
+++ b/engines/m4/fileio/info.h
@@ -29,12 +29,12 @@ namespace M4 {
 /**
  * Returns true if a given file exists
  */
-extern bool f_info_exists(const Common::String &filename);
+extern bool f_info_exists(const Common::Path &filename);
 
 /**
  * Returns the size of a given file
  */
-extern size_t f_info_get_file_size(const Common::String &filename);
+extern size_t f_info_get_file_size(const Common::Path &filename);
 
 } // namespace M4
 
diff --git a/engines/m4/fileio/sys_file.cpp b/engines/m4/fileio/sys_file.cpp
index 276aef41062..114ffa9e8d2 100644
--- a/engines/m4/fileio/sys_file.cpp
+++ b/engines/m4/fileio/sys_file.cpp
@@ -97,7 +97,7 @@ void SysFile::open_read_low_level() {
 	Hag_Name_Record *temp_ptr;
 	char *temp_name;
 	Common::String last_string;
-	Common::String local_name, resource_hag;
+	Common::String resource_hag;
 	Common::File hagfile_fp;
 
 	if (filename.empty()) {
@@ -111,7 +111,7 @@ void SysFile::open_read_low_level() {
 			// Use hag file
 			// Get hagfile table list here
 			if (!temp_fp.open(_G(hag).hash_file))
-				error("Hash file not found: %s", _G(hag).hash_file.c_str());
+				error("Hash file not found: %s", _G(hag).hash_file.toString().c_str());
 
 			hash_table_size = temp_fp.readUint32LE();
 			if (!temp_fp.seek(hash_table_size * HASH_RECORD_LENGTH, SEEK_CUR))
@@ -127,10 +127,10 @@ void SysFile::open_read_low_level() {
 				assert(temp_ptr);
 
 				// Check hag file exists or not
-				local_name = f_extension_new(hag_name, "HAG");
+				Common::Path local_name(f_extension_new(hag_name, "HAG"));
 
 				if (!Common::File::exists(local_name))
-					error("couldn't find hag file: %s", local_name.c_str());
+					error("couldn't find hag file: %s", local_name.toString().c_str());
 
 				// put into hag_name_list //
 				Common::strcpy_s(temp_ptr->filename, hag_name);
@@ -156,7 +156,7 @@ void SysFile::open_read_low_level() {
 			if (!_G(hag).hag_flag) {
 				if (temp_name) {
 					filename = temp_name;
-					_fp = f_io_open(filename, "rb");
+					_fp = f_io_open(Common::Path(filename), "rb");
 
 					if (!_fp && show_error_flag)
 						error("Failed opening - %s", filename.c_str());
@@ -260,7 +260,7 @@ bool SysFile::open_hash_file() {
 
 	hashfp = dynamic_cast<Common::SeekableReadStream *>(f_io_open(_G(hag).hash_file, "rb"));
 	if (!hashfp) {
-		warning("open_hash_file: %s", _G(hag).hash_file.c_str());
+		warning("open_hash_file: %s", _G(hag).hash_file.toString().c_str());
 		hag_success = false;
 		return false;
 	}
@@ -310,10 +310,10 @@ bool SysFile::open_hash_file() {
 			}
 			if (!found) {
 				// hag file is not open, try the current directory first, then RESOURCE_PATH
-				temp_fp = f_io_open(hag_name, "rb");
+				temp_fp = f_io_open(Common::Path(hag_name), "rb");
 				if (!temp_fp) {
 					// hag_file is not in current directory, search for RESOURCE_PATH
-					temp_fp = f_io_open(temp_name, "rb");
+					temp_fp = f_io_open(Common::Path(temp_name), "rb");
 					if (!temp_fp) {
 						error("hag file not found: %s", hag_name.c_str());
 						hag_success = 0;
@@ -458,7 +458,7 @@ int SysFile::hash_search(const Common::String &fname, Hash_Record *current_hash_
 			local_name = local_hag_name;
 			//			sprintf(local_name, "%s%s", exec_path, local_hag_name);
 
-			if (Common::File::exists(local_name)) {
+			if (Common::File::exists(Common::Path(local_name))) {
 				finded = 1;
 				find_offset = offset;
 				break;
@@ -509,9 +509,9 @@ int SysFile::hash_search(const Common::String &fname, Hash_Record *current_hash_
 Common::Stream *SysFile::open_by_first_char() {
 	if (filename.hasPrefix("*")) {
 		// MADS folder file in original
-		_fp = f_io_open(filename.c_str() + 1, "rb");
+		_fp = f_io_open(Common::Path(filename.c_str() + 1, '/'), "rb");
 	} else {
-		_fp = f_io_open(filename, "rb");
+		_fp = f_io_open(Common::Path(filename, '/'), "rb");
 	}
 
 	if (!_fp) {
@@ -647,8 +647,8 @@ void sysfile_init(bool in_hag_mode) {
 	_G(hag).hag_flag = in_hag_mode;
 
 	if (in_hag_mode) {
-		_G(hag).hash_file = Common::String::format("%s.has",
-			g_engine->getGameType() == GType_Riddle ? "ripley" : "burger");
+		_G(hag).hash_file = Common::Path(Common::String::format("%s.has",
+			g_engine->getGameType() == GType_Riddle ? "ripley" : "burger"));
 		term_message("Initialized in hag mode");
 	} else {
 		term_message("Initialized in file mode");
diff --git a/engines/m4/fileio/sys_file.h b/engines/m4/fileio/sys_file.h
index 7549d66ae69..bb7b805cfd7 100644
--- a/engines/m4/fileio/sys_file.h
+++ b/engines/m4/fileio/sys_file.h
@@ -39,7 +39,7 @@ struct Hash_Record {
 struct Hag_Statics {
 	bool hag_flag = false;
 	bool first_read_flag = false;
-	Common::String hash_file;
+	Common::Path hash_file;
 	Hag_Name_Record *hag_name_list = nullptr;
 	Hag_Record *hag_file_list = nullptr;
 };


Commit: cd9c525b6d7588d1c652117f6325bf407d3f2586
    https://github.com/scummvm/scummvm/commit/cd9c525b6d7588d1c652117f6325bf407d3f2586
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MACVENTURE: Migrate engine to Path

Changed paths:
    engines/macventure/container.cpp
    engines/macventure/container.h
    engines/macventure/datafiles.cpp
    engines/macventure/macventure.cpp
    engines/macventure/macventure.h
    engines/macventure/sound.cpp
    engines/macventure/world.cpp
    engines/macventure/world.h


diff --git a/engines/macventure/container.cpp b/engines/macventure/container.cpp
index 962c59a8eb4..7d368d20d73 100644
--- a/engines/macventure/container.cpp
+++ b/engines/macventure/container.cpp
@@ -31,11 +31,11 @@
 
 namespace MacVenture {
 
-Container::Container(Common::String filename) {
+Container::Container(const Common::Path &filename) {
 	_filename = filename;
 
 	if (!_file.open(_filename)) {
-		error("CONTAINER: Could not open %s", _filename.c_str());
+		error("CONTAINER: Could not open %s", _filename.toString().c_str());
 	}
 
 	_res = _file.readStream(_file.size());
diff --git a/engines/macventure/container.h b/engines/macventure/container.h
index a7c5d29ea6f..8c56098de1a 100644
--- a/engines/macventure/container.h
+++ b/engines/macventure/container.h
@@ -48,7 +48,7 @@ typedef uint32 ContainerHeader;
 class Container {
 
 public:
-	Container(Common::String filename);
+	Container(const Common::Path &filename);
 	~Container();
 
 public:
@@ -75,7 +75,7 @@ protected:
 	Common::Array<uint8> _lens; // huffman lengths
 	Common::Array<ItemGroup> _groups;
 
-	Common::String _filename;
+	Common::Path _filename;
 	Common::File _file;
 	Common::SeekableReadStream *_res;
 
diff --git a/engines/macventure/datafiles.cpp b/engines/macventure/datafiles.cpp
index 87d5afe8d7c..f69dfa09c02 100644
--- a/engines/macventure/datafiles.cpp
+++ b/engines/macventure/datafiles.cpp
@@ -37,7 +37,7 @@
 
 namespace MacVenture {
 
-#define MACVENTURE_DATA_BUNDLE Common::String("macventure.dat")
+#define MACVENTURE_DATA_BUNDLE "macventure.dat"
 
 struct BorderName {
 	MVWindowType type;
@@ -75,15 +75,15 @@ Common::String windowTypeName(MVWindowType windowType) {
 void MacVentureEngine::loadDataBundle() {
 	_dataBundle = Common::makeZipArchive(MACVENTURE_DATA_BUNDLE);
 	if (!_dataBundle) {
-		error("ENGINE: Couldn't load data bundle '%s'.", MACVENTURE_DATA_BUNDLE.c_str());
+		error("ENGINE: Couldn't load data bundle '%s'.", MACVENTURE_DATA_BUNDLE);
 	}
 }
 
 Common::SeekableReadStream *MacVentureEngine::getBorderFile(MVWindowType windowType, bool isActive) {
-	Common::String filename = windowTypeName(windowType);
-	filename += (isActive ? "_act.bmp" : "_inac.bmp");
+	Common::Path filename(windowTypeName(windowType));
+	filename.appendInPlace(isActive ? "_act.bmp" : "_inac.bmp");
 	if (!_dataBundle->hasFile(filename)) {
-		warning("Missing border file '%s' in data bundle", filename.c_str());
+		warning("Missing border file '%s' in data bundle", filename.toString().c_str());
 		return nullptr;
 	}
 
diff --git a/engines/macventure/macventure.cpp b/engines/macventure/macventure.cpp
index 28dcaa1f26e..131fba10598 100644
--- a/engines/macventure/macventure.cpp
+++ b/engines/macventure/macventure.cpp
@@ -457,7 +457,7 @@ Common::String MacVentureEngine::getUserInput() {
 }
 
 
-Common::String MacVentureEngine::getStartGameFileName() {
+Common::Path MacVentureEngine::getStartGameFileName() {
 	Common::SeekableReadStream *res;
 	res = _resourceManager->getResource(MKTAG('S', 'T', 'R', ' '), kStartGameFilenameID);
 	if (!res)
@@ -474,7 +474,7 @@ Common::String MacVentureEngine::getStartGameFileName() {
 	delete[] fileName;
 	delete res;
 
-	return result;
+	return Common::Path(result);
 }
 
 const GlobalSettings& MacVentureEngine::getGlobalSettings() const {
@@ -956,11 +956,11 @@ Common::String MacVentureEngine::getCommandsPausedString() const {
 	return Common::String("Click to continue");
 }
 
-Common::String MacVentureEngine::getFilePath(FilePathID id) const {
+Common::Path MacVentureEngine::getFilePath(FilePathID id) const {
 	if (id <= 3) { // We don't want a file in the subdirectory
-		return _filenames->getString(id);
+		return Common::Path(_filenames->getString(id));
 	} else { // We want a game file
-		return _filenames->getString(3) + "/" + _filenames->getString(id);
+		return Common::Path(_filenames->getString(3) + "/" + _filenames->getString(id));
 	}
 }
 
diff --git a/engines/macventure/macventure.h b/engines/macventure/macventure.h
index 2417cf8828f..159c6dd21d5 100644
--- a/engines/macventure/macventure.h
+++ b/engines/macventure/macventure.h
@@ -242,12 +242,12 @@ public:
 	Common::String getUserInput();
 
 	// Data retrieval
-	Common::String getStartGameFileName();
+	Common::Path getStartGameFileName();
 	bool isPaused();
 	bool needsClickToContinue();
 	Common::String getCommandsPausedString() const;
 	const GlobalSettings &getGlobalSettings() const;
-	Common::String getFilePath(FilePathID id) const;
+	Common::Path getFilePath(FilePathID id) const;
 	bool isOldText() const;
 	const HuffmanLists *getDecodingHuffman() const;
 	uint32 randBetween(uint32 min, uint32 max);
diff --git a/engines/macventure/sound.cpp b/engines/macventure/sound.cpp
index 1c599a3081f..c7da695e3e5 100644
--- a/engines/macventure/sound.cpp
+++ b/engines/macventure/sound.cpp
@@ -38,10 +38,10 @@ namespace MacVenture {
 // SoundManager
 SoundManager::SoundManager(MacVentureEngine *engine, Audio::Mixer *mixer) {
 	_container = nullptr;
-	Common::String filename = engine->getFilePath(kSoundPathID);
+	Common::Path filename = engine->getFilePath(kSoundPathID);
 	_container = new Container(filename);
 	_mixer = mixer;
-	debugC(1, kMVDebugSound, "Created sound manager with file %s", filename.c_str());
+	debugC(1, kMVDebugSound, "Created sound manager with file %s", filename.toString().c_str());
 }
 
 SoundManager::~SoundManager() {
diff --git a/engines/macventure/world.cpp b/engines/macventure/world.cpp
index 36ed29cffc4..c4748955119 100644
--- a/engines/macventure/world.cpp
+++ b/engines/macventure/world.cpp
@@ -65,14 +65,14 @@ void World::startNewGame() {
 	if (_saveGame)
 		delete _saveGame;
 
-	if ((_startGameFileName = _engine->getStartGameFileName()) == "")
+	if ((_startGameFileName = _engine->getStartGameFileName()).empty())
 		error("WORLD: Could not load initial game configuration");
 
 	Common::File saveGameFile;
 	if (!saveGameFile.open(_startGameFileName))
 		error("WORLD: Could not load initial game configuration");
 
-	debugC(2, kMVDebugMain, "Loading save game state from %s", _startGameFileName.c_str());
+	debugC(2, kMVDebugMain, "Loading save game state from %s", _startGameFileName.toString().c_str());
 	Common::SeekableReadStream *saveGameRes = saveGameFile.readStream(saveGameFile.size());
 
 	_saveGame = new SaveGame(_engine, saveGameRes);
diff --git a/engines/macventure/world.h b/engines/macventure/world.h
index 42e8084e0b3..d4fab25ed96 100644
--- a/engines/macventure/world.h
+++ b/engines/macventure/world.h
@@ -131,7 +131,7 @@ private:
 	MacVentureEngine *_engine;
 	Common::MacResManager *_resourceManager;
 
-	Common::String _startGameFileName;
+	Common::Path _startGameFileName;
 
 	SaveGame *_saveGame;
 


Commit: f50a364ee8a63ffde4153288afb7b748999ebbb9
    https://github.com/scummvm/scummvm/commit/f50a364ee8a63ffde4153288afb7b748999ebbb9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MADS: Migrate engine to Path

Changed paths:
    engines/mads/animation.cpp
    engines/mads/animation.h
    engines/mads/assets.cpp
    engines/mads/assets.h
    engines/mads/audio.cpp
    engines/mads/audio.h
    engines/mads/compression.cpp
    engines/mads/compression.h
    engines/mads/conversations.cpp
    engines/mads/conversations.h
    engines/mads/debugger.cpp
    engines/mads/dragonsphere/dragonsphere_scenes.cpp
    engines/mads/dragonsphere/dragonsphere_scenes.h
    engines/mads/events.cpp
    engines/mads/events.h
    engines/mads/font.cpp
    engines/mads/font.h
    engines/mads/game.cpp
    engines/mads/game.h
    engines/mads/menu_views.cpp
    engines/mads/menu_views.h
    engines/mads/mps_installer.cpp
    engines/mads/mps_installer.h
    engines/mads/msurface.h
    engines/mads/nebular/dialogs_nebular.cpp
    engines/mads/nebular/menu_nebular.cpp
    engines/mads/nebular/nebular_scenes.cpp
    engines/mads/nebular/nebular_scenes.h
    engines/mads/nebular/sound_nebular.cpp
    engines/mads/nebular/sound_nebular.h
    engines/mads/phantom/phantom_scenes.cpp
    engines/mads/phantom/phantom_scenes.h
    engines/mads/player.cpp
    engines/mads/resources.cpp
    engines/mads/resources.h
    engines/mads/scene.cpp
    engines/mads/scene.h
    engines/mads/scene_data.cpp
    engines/mads/sprites.cpp
    engines/mads/sprites.h
    engines/mads/user_interface.cpp
    engines/mads/user_interface.h


diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp
index c7cd523e2a5..4b8dd574b01 100644
--- a/engines/mads/animation.cpp
+++ b/engines/mads/animation.cpp
@@ -193,11 +193,11 @@ Animation::~Animation() {
 }
 
 void Animation::load(MSurface &backSurface, DepthSurface &depthSurface,
-		const Common::String &resName, int flags, Common::Array<PaletteCycle> *palCycles,
+		const Common::Path &resName, int flags, Common::Array<PaletteCycle> *palCycles,
 		SceneInfo *sceneInfo) {
-	Common::String resourceName = resName;
-	if (!resourceName.contains("."))
-		resourceName += ".AA";
+	Common::Path resourceName = resName;
+	if (!resourceName.baseName().contains("."))
+		resourceName.appendInPlace(".AA");
 
 	File f(resourceName);
 	MadsPack madsPack(&f);
@@ -297,14 +297,14 @@ void Animation::load(MSurface &backSurface, DepthSurface &depthSurface,
 			// Skip over field, since it's manually loaded
 			_spriteSets[i] = nullptr;
 		} else {
-			_spriteSets[i] = new SpriteAsset(_vm, _header._spriteSetNames[i], flags);
+			_spriteSets[i] = new SpriteAsset(_vm, Common::Path(_header._spriteSetNames[i]), flags);
 			_spriteListIndexes[i] = _vm->_game->_scene._sprites.add(_spriteSets[i]);
 		}
 	}
 
 	if (_header._manualFlag) {
 		Common::String assetResName = "*" + _header._spriteSetNames[_header._spritesIndex];
-		SpriteAsset *sprites = new SpriteAsset(_vm, assetResName, flags);
+		SpriteAsset *sprites = new SpriteAsset(_vm, Common::Path(assetResName), flags);
 		_spriteSets[_header._spritesIndex] = sprites;
 
 		_spriteListIndexes[_header._spritesIndex] = _scene->_sprites.add(sprites);
@@ -328,7 +328,7 @@ void Animation::load(MSurface &backSurface, DepthSurface &depthSurface,
 	f.close();
 }
 
-void Animation::preLoad(const Common::String &resName, int level) {
+void Animation::preLoad(const Common::Path &resName, int level) {
 	// No implementation in ScummVM, since access is fast enough that data
 	// doesn't need to be preloaded
 }
@@ -401,7 +401,7 @@ void Animation::loadBackground(MSurface &backSurface, DepthSurface &depthSurface
 		}
 	} else if (header._bgType == ANIMBG_INTERFACE) {
 		// Load a scene interface
-		Common::String resourceName = "*" + header._backgroundFile;
+		Common::Path resourceName = Common::Path("*").appendInPlace(header._backgroundFile);
 		backSurface.load(resourceName);
 
 		if (palCycles)
diff --git a/engines/mads/animation.h b/engines/mads/animation.h
index 430b8952548..263f62036a4 100644
--- a/engines/mads/animation.h
+++ b/engines/mads/animation.h
@@ -201,13 +201,13 @@ public:
 	/**
 	 * Loads animation data
 	 */
-	void load(MSurface &backSurface, DepthSurface &depthSurface, const Common::String &resName,
+	void load(MSurface &backSurface, DepthSurface &depthSurface, const Common::Path &resName,
 		int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo);
 
 	/**
 	 * Preload animation data for the scene
 	 */
-	void preLoad(const Common::String &resName, int level);
+	void preLoad(const Common::Path &resName, int level);
 
 	/**
 	 * Setups up a loaded animation for playback
diff --git a/engines/mads/assets.cpp b/engines/mads/assets.cpp
index 0b2f36d40cb..9d667ddd954 100644
--- a/engines/mads/assets.cpp
+++ b/engines/mads/assets.cpp
@@ -26,10 +26,11 @@
 
 namespace MADS {
 
-SpriteAsset::SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags) : _vm(vm) {
-	Common::String resName = resourceName;
-	if (!resName.hasSuffix(".SS") && !resName.hasSuffix(".ss"))
-		resName += ".SS";
+SpriteAsset::SpriteAsset(MADSEngine *vm, const Common::Path &resourceName, int flags) : _vm(vm) {
+	Common::Path resName = resourceName;
+	Common::String baseName(resName.baseName());
+	if (!baseName.hasSuffix(".SS") && !baseName.hasSuffix(".ss"))
+		resName.appendInPlace(".SS");
 	_srcSize = 0;
 
 	File file(resName);
diff --git a/engines/mads/assets.h b/engines/mads/assets.h
index 612f1d508cb..936e17772f0 100644
--- a/engines/mads/assets.h
+++ b/engines/mads/assets.h
@@ -83,7 +83,7 @@ public:
 	/**
 	 * Constructor
 	 */
-	SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags);
+	SpriteAsset(MADSEngine *vm, const Common::Path &resourceName, int flags);
 
 	/**
 	 * Constructor
diff --git a/engines/mads/audio.cpp b/engines/mads/audio.cpp
index 42b95f23014..987fa77329e 100644
--- a/engines/mads/audio.cpp
+++ b/engines/mads/audio.cpp
@@ -65,7 +65,7 @@ void AudioPlayer::setDefaultSoundGroup() {
 	}
 }
 
-void AudioPlayer::setSoundGroup(const Common::String &filename) {
+void AudioPlayer::setSoundGroup(const Common::Path &filename) {
 	if (_filename != filename) {
 		_dsrEntries.clear();
 
diff --git a/engines/mads/audio.h b/engines/mads/audio.h
index d8839cc35b0..6442a242a8c 100644
--- a/engines/mads/audio.h
+++ b/engines/mads/audio.h
@@ -42,7 +42,7 @@ public:
 	AudioPlayer(Audio::Mixer *mixer, uint32 gameID);
 	~AudioPlayer();
 
-	void setSoundGroup(const Common::String &filename);
+	void setSoundGroup(const Common::Path &filename);
 	void setDefaultSoundGroup();
 	void playSound(int soundIndex, bool loop = false);
 	void stop();
@@ -55,7 +55,7 @@ public:
 	uint32 _gameID;
 
 	File _dsrFile;
-	Common::String _filename;
+	Common::Path _filename;
 	Common::Array<DSREntry> _dsrEntries;
 };
 
diff --git a/engines/mads/compression.cpp b/engines/mads/compression.cpp
index c78de8d7c5b..7d626d63dd1 100644
--- a/engines/mads/compression.cpp
+++ b/engines/mads/compression.cpp
@@ -44,7 +44,7 @@ MadsPack::MadsPack(Common::SeekableReadStream *stream) {
 	initialize(stream);
 }
 
-MadsPack::MadsPack(const Common::String &resourceName, MADSEngine *vm) {
+MadsPack::MadsPack(const Common::Path &resourceName, MADSEngine *vm) {
 	File file(resourceName);
 	initialize(&file);
 	file.close();
diff --git a/engines/mads/compression.h b/engines/mads/compression.h
index c623064b885..308b69012ab 100644
--- a/engines/mads/compression.h
+++ b/engines/mads/compression.h
@@ -50,7 +50,7 @@ private:
 public:
 	static bool isCompressed(Common::SeekableReadStream *stream);
 	MadsPack(Common::SeekableReadStream *stream);
-	MadsPack(const Common::String &resourceName, MADSEngine *_vm);
+	MadsPack(const Common::Path &resourceName, MADSEngine *_vm);
 	~MadsPack();
 
 	int getCount() const { return _count; }
diff --git a/engines/mads/conversations.cpp b/engines/mads/conversations.cpp
index 21b98f45e3d..b03a0dc1f10 100644
--- a/engines/mads/conversations.cpp
+++ b/engines/mads/conversations.cpp
@@ -71,11 +71,11 @@ void GameConversations::load(int id) {
 	_conversations[slotIndex]._convId = id;
 
 	// Load the conversation data
-	Common::String cnvFilename = Common::String::format("CONV%03d.CNV", id);
+	Common::Path cnvFilename(Common::String::format("CONV%03d.CNV", id));
 	_conversations[slotIndex]._data.load(cnvFilename);
 
 	// Load the conversation's CND data
-	Common::String cndFilename = Common::String::format("CONV%03d.CND", id);
+	Common::Path cndFilename(Common::String::format("CONV%03d.CND", id));
 	_conversations[slotIndex]._cnd.load(cndFilename);
 }
 
@@ -132,7 +132,7 @@ void GameConversations::run(int id) {
 
 	// Load sprite data for speaker portraits
 	for (uint idx = 0; idx < _runningConv->_data._speakerCount; ++idx) {
-		const Common::String &portraitName = _runningConv->_data._portraits[idx];
+		const Common::Path &portraitName = _runningConv->_data._portraits[idx];
 		_speakerSeries[idx] = _vm->_game->_scene._sprites.addSprites(portraitName, PALFLAG_RESERVED);
 
 		if (_speakerSeries[idx] > 0) {
@@ -607,7 +607,7 @@ bool GameConversations::scriptNode(ScriptEntry &scrEntry) {
 
 /*------------------------------------------------------------------------*/
 
-void ConversationData::load(const Common::String &filename) {
+void ConversationData::load(const Common::Path &filename) {
 	Common::File inFile;
 	char buffer[16];
 
@@ -740,7 +740,7 @@ ConversationConditionals::ConversationConditionals() : _numImports(0) {
 	_currentNode = -1;
 }
 
-void ConversationConditionals::load(const Common::String &filename) {
+void ConversationConditionals::load(const Common::Path &filename) {
 	Common::File inFile;
 	Common::SeekableReadStream *convFile;
 
diff --git a/engines/mads/conversations.h b/engines/mads/conversations.h
index 1adf75bd124..56e2c4ca0a1 100644
--- a/engines/mads/conversations.h
+++ b/engines/mads/conversations.h
@@ -252,9 +252,9 @@ struct ConversationData {
 	int _textSize;
 	int _commandsSize;
 
-	Common::String _portraits[MAX_SPEAKERS];
+	Common::Path _portraits[MAX_SPEAKERS];
 	int _speakerFrame[MAX_SPEAKERS];
-	Common::String _speechFile;
+	Common::Path _speechFile;
 	Common::Array<ConvMessage> _messages;
 	Common::StringArray _textLines;
 	Common::Array<ConvNode> _nodes;
@@ -263,7 +263,7 @@ struct ConversationData {
 	/**
 	 * Load the specified conversation resource file
 	 */
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 };
 
 /**
@@ -289,7 +289,7 @@ struct ConversationConditionals {
 	/**
 	 * Load the specified conversation conditionals resource file
 	 */
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 };
 
 /**
diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp
index 6aa7f0db1a5..a9c26a093af 100644
--- a/engines/mads/debugger.cpp
+++ b/engines/mads/debugger.cpp
@@ -356,12 +356,12 @@ bool Debugger::Cmd_PlayAnim(int argc, const char **argv) {
 		debugPrintf("Usage: %s <anim name>\n", argv[0]);
 		return true;
 	} else {
-		Common::String resName = argv[1];
-		if (resName.hasPrefix("@"))
-			resName.deleteChar(0);
+		Common::Path resName(argv[1]);
+		if (argv[1][0] == '@')
+			resName = Common::Path(argv[1] + 1);
 
 		Common::File f;
-		if (f.exists(resName) || f.exists(resName + ".res")) {
+		if (f.exists(resName) || f.exists(resName.append(".res"))) {
 			AnimationView::execute(_vm, resName);
 			return false;
 		} else {
@@ -376,12 +376,12 @@ bool Debugger::Cmd_PlayText(int argc, const char **argv) {
 		debugPrintf("Usage: %s <text name>\n", argv[0]);
 		return true;
 	} else {
-		Common::String resName = argv[1];
-		if (resName.hasPrefix("@"))
-			resName.deleteChar(0);
+		Common::Path resName(argv[1]);
+		if (argv[1][0] == '@')
+			resName = Common::Path(argv[1] + 1);
 
 		Common::File f;
-		if (f.exists(resName) || f.exists(resName + ".txr")) {
+		if (f.exists(resName) || f.exists(resName.append(".txr"))) {
 			TextView::execute(_vm, resName);
 			return false;
 		} else {
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.cpp b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
index a9d2022be9e..f2aa31f1b52 100644
--- a/engines/mads/dragonsphere/dragonsphere_scenes.cpp
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
@@ -194,7 +194,7 @@ DragonsphereScene::DragonsphereScene(MADSEngine *vm) : SceneLogic(vm),
 		_action(vm->_game->_scene._action) {
 }
 
-Common::String DragonsphereScene::formAnimName(char sepChar, int suffixNum) {
+Common::Path DragonsphereScene::formAnimName(char sepChar, int suffixNum) {
 	return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum,
 		EXT_NONE, "");
 }
@@ -203,7 +203,7 @@ Common::String DragonsphereScene::formAnimName(char sepChar, int suffixNum) {
 
 void SceneInfoDragonsphere::loadCodes(BaseSurface &depthSurface, int variant) {
 	Common::String ext = Common::String::format(".WW%d", variant);
-	Common::String fileName = Resources::formatName(RESPREFIX_RM, _sceneId, ext);
+	Common::Path fileName = Resources::formatName(RESPREFIX_RM, _sceneId, ext);
 	if (!Common::File::exists(fileName))
 		return;
 
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.h b/engines/mads/dragonsphere/dragonsphere_scenes.h
index cd54d363c11..20673b6de33 100644
--- a/engines/mads/dragonsphere/dragonsphere_scenes.h
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.h
@@ -628,7 +628,7 @@ protected:
 	/**
 	 * Forms an animation resource name
 	 */
-	Common::String formAnimName(char sepChar, int suffixNum);
+	Common::Path formAnimName(char sepChar, int suffixNum);
 
 	/**
 	 * Plays appropriate sound for entering varous rooms
diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp
index 1db3604287b..cd9e7044d86 100644
--- a/engines/mads/events.cpp
+++ b/engines/mads/events.cpp
@@ -51,7 +51,7 @@ EventsManager::~EventsManager() {
 	freeCursors();
 }
 
-void EventsManager::loadCursors(const Common::String &spritesName) {
+void EventsManager::loadCursors(const Common::Path &spritesName) {
 	delete _cursorSprites;
 	_cursorSprites = new SpriteAsset(_vm, spritesName, 0x4000);
 }
diff --git a/engines/mads/events.h b/engines/mads/events.h
index f4775b9884d..c4f906f8de4 100644
--- a/engines/mads/events.h
+++ b/engines/mads/events.h
@@ -84,7 +84,7 @@ public:
 	/**
 	 * Loads the sprite set containing the cursors
 	 */
-	void loadCursors(const Common::String &spritesName);
+	void loadCursors(const Common::Path &spritesName);
 
 	/**
 	 * Sets the cursor
diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp
index d1414838e5e..4af3e46f61e 100644
--- a/engines/mads/font.cpp
+++ b/engines/mads/font.cpp
@@ -55,7 +55,7 @@ Font *Font::getFont(const Common::String &fontName) {
 	if (_fonts->contains(fontName)) {
 		return _fonts->getVal(fontName);
 	} else {
-		Font *font = new Font(fontName);
+		Font *font = new Font(Common::Path(fontName));
 		_fonts->setVal(fontName, font);
 		return font;
 	}
@@ -68,7 +68,7 @@ Font::Font() {
 	setFont(FONT_INTERFACE);
 }
 
-Font::Font(const Common::String &filename) {
+Font::Font(const Common::Path &filename) {
 	_charWidths = nullptr;
 	_charOffs = nullptr;
 	_charData = nullptr;
@@ -81,16 +81,16 @@ Font::~Font() {
 	delete[] _charData;
 }
 
-void Font::setFont(const Common::String &filename) {
+void Font::setFont(const Common::Path &filename) {
 	if (!_filename.empty() && (filename == _filename))
 		// Already using specified font, so don't bother reloading
 		return;
 
 	_filename = filename;
 
-	Common::String resName = filename;
-	if (!resName.hasSuffix(".FF"))
-		resName += ".FF";
+	Common::Path resName = filename;
+	if (!resName.baseName().hasSuffix(".FF"))
+		resName.appendInPlace(".FF");
 
 	MadsPack fontData(resName, _vm);
 	Common::SeekableReadStream *fontFile = fontData.getItemStream(0);
diff --git a/engines/mads/font.h b/engines/mads/font.h
index 4ef1c69bded..2b0eec088d3 100644
--- a/engines/mads/font.h
+++ b/engines/mads/font.h
@@ -69,14 +69,14 @@ private:
 	uint8 *_charWidths;
 	uint16 *_charOffs;
 	uint8 *_charData;
-	Common::String _filename;
+	Common::Path _filename;
 
 	int getBpp(int charWidth);
 
-	void setFont(const Common::String &filename);
+	void setFont(const Common::Path &filename);
 public:
 	Font();
-	Font(const Common::String &filename);
+	Font(const Common::Path &filename);
 	virtual ~Font();
 
 	void setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4);
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index 54755722a4d..561fce012ca 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -463,7 +463,14 @@ void Game::synchronize(Common::Serializer &s, bool phase1) {
 		s.syncAsSint16LE(_trigger);
 		s.syncAsUint16LE(_triggerSetupMode);
 		s.syncAsUint16LE(_triggerMode);
-		s.syncString(_aaName);
+		if (s.isSaving()) {
+			Common::String name(_aaName.toString('/'));
+			s.syncString(name);
+		} else {
+			Common::String name;
+			s.syncString(name);
+			_aaName = Common::Path(name, '/');
+		}
 		s.syncAsSint16LE(_lastSave);
 
 		_scene.synchronize(s);
diff --git a/engines/mads/game.h b/engines/mads/game.h
index 152906a4a0a..0c49896d6c9 100644
--- a/engines/mads/game.h
+++ b/engines/mads/game.h
@@ -143,7 +143,7 @@ public:
 	TriggerMode _triggerMode;
 	TriggerMode _triggerSetupMode;
 	uint32 _priorFrameTimer;
-	Common::String _aaName;
+	Common::Path _aaName;
 	int _winStatus;
 	int _widepipeCtr;
 	int _loadGameSlot;
diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp
index d2d0034bd73..2cbec1d92a7 100644
--- a/engines/mads/menu_views.cpp
+++ b/engines/mads/menu_views.cpp
@@ -80,7 +80,7 @@ bool MenuView::onEvent(Common::Event &event) {
 }
 
 Common::String MenuView::getResourceName() {
-	Common::String s(_filename);
+	Common::String s(_filename.baseName());
 	s.toLowercase();
 	while (s.contains('.'))
 		s.deleteLastChar();
@@ -96,9 +96,9 @@ char TextView::_resourceName[100];
 #define TV_NUM_FADE_STEPS 40
 #define TV_FADE_DELAY_MILLI 50
 
-void TextView::execute(MADSEngine *vm, const Common::String &resName) {
-	assert(resName.size() < 100);
-	Common::strlcpy(_resourceName, resName.c_str(), sizeof(_resourceName));
+void TextView::execute(MADSEngine *vm, const Common::Path &resName) {
+	assert(resName.toString('/').size() < 100);
+	Common::strlcpy(_resourceName, resName.toString('/').c_str(), sizeof(_resourceName));
 	vm->_dialogs->_pendingDialog = DIALOG_TEXTVIEW;
 }
 
@@ -127,8 +127,8 @@ TextView::~TextView() {
 }
 
 void TextView::load() {
-	Common::String scriptName(_resourceName);
-	scriptName += ".txr";
+	Common::Path scriptName(_resourceName);
+	scriptName.appendInPlace(".txr");
 
 	_filename = scriptName;
 	if (!_script.open(scriptName))
@@ -454,9 +454,9 @@ void TextView::scriptDone() {
 
 char AnimationView::_resourceName[100];
 
-void AnimationView::execute(MADSEngine *vm, const Common::String &resName) {
-	assert(resName.size() < 100);
-	Common::strlcpy(_resourceName, resName.c_str(), sizeof(_resourceName));
+void AnimationView::execute(MADSEngine *vm, const Common::Path &resName) {
+	assert(resName.toString('/').size() < 100);
+	Common::strlcpy(_resourceName, resName.toString('/').c_str(), sizeof(_resourceName));
 	vm->_dialogs->_pendingDialog = DIALOG_ANIMVIEW;
 }
 
@@ -500,13 +500,13 @@ AnimationView::~AnimationView() {
 }
 
 void AnimationView::load() {
-	Common::String resName(_resourceName);
-	if (!resName.hasSuffix("."))
-		resName += ".res";
+	Common::Path resName(_resourceName);
+	if (!resName.baseName().hasSuffix("."))
+		resName.appendInPlace(".res");
 
 	_filename = resName;
 	if (!_script.open(resName))
-		error("Could not open resource %s", resName.c_str());
+		error("Could not open resource %s", resName.toString().c_str());
 
 	processLines();
 }
@@ -628,7 +628,7 @@ void AnimationView::loadNextResource() {
 	// Set the sound data for the animation
 	_vm->_sound->setEnabled(resEntry._soundFlag);
 
-	Common::String dsrName = _currentAnimation->_header._dsrName;
+	Common::Path dsrName(_currentAnimation->_header._dsrName);
 	if (!dsrName.empty())
 		_vm->_audio->setSoundGroup(dsrName);
 
@@ -704,7 +704,7 @@ void AnimationView::processLines() {
 				}
 
 				// Add resource into list along with any set state information
-				_resources.push_back(ResourceEntry(resName, _sfx, _soundFlag,
+				_resources.push_back(ResourceEntry(Common::Path(resName), _sfx, _soundFlag,
 					_bgLoadFlag, _showWhiteBars));
 
 				// Fx resets between resource entries
diff --git a/engines/mads/menu_views.h b/engines/mads/menu_views.h
index 471232ebbc3..63603ec0dfb 100644
--- a/engines/mads/menu_views.h
+++ b/engines/mads/menu_views.h
@@ -35,7 +35,7 @@ class MenuView: public FullScreenDialog {
 protected:
 	bool _breakFlag;
 	bool _redrawFlag;
-	Common::String _filename;
+	Common::Path _filename;
 
 	virtual void doFrame() = 0;
 
@@ -125,7 +125,7 @@ public:
 	/**
 	 * Queue the given text resource for display
 	 */
-	static void execute(MADSEngine *vm, const Common::String &resName);
+	static void execute(MADSEngine *vm, const Common::Path &resName);
 
 	TextView(MADSEngine *vm);
 
@@ -135,14 +135,14 @@ public:
 enum ResyncMode { NEVER, ALWAYS, BEGINNING };
 
 struct ResourceEntry {
-	Common::String _resourceName;
+	Common::Path _resourceName;
 	int _fx;
 	bool _soundFlag;
 	bool _bgFlag;
 	bool _showWhiteBars;
 
 	ResourceEntry() {}
-	ResourceEntry(const Common::String &resName, int fx, bool soundFlag,
+	ResourceEntry(const Common::Path &resName, int fx, bool soundFlag,
 			bool bgFlag, bool showWhiteBars) {
 		_resourceName = resName;
 		_fx = fx;
@@ -220,7 +220,7 @@ public:
 	/**
 	* Queue the given text resource for display
 	*/
-	static void execute(MADSEngine *vm, const Common::String &resName);
+	static void execute(MADSEngine *vm, const Common::Path &resName);
 
 	AnimationView(MADSEngine *vm);
 
diff --git a/engines/mads/mps_installer.cpp b/engines/mads/mps_installer.cpp
index c640c608faf..169948ddb1e 100644
--- a/engines/mads/mps_installer.cpp
+++ b/engines/mads/mps_installer.cpp
@@ -50,7 +50,7 @@ MpsInstaller* MpsInstaller::open(const Common::Path& baseName) {
 		filecnt = (indexSize - 12) / kEntryLength;
 
 	for (uint i = 0; i < filecnt; i++) {
-		Common::String name = indexFile.readString('\0', kNameFieldLength);
+		Common::Path name(indexFile.readString('\0', kNameFieldLength));
 		uint16 compression = indexFile.readUint16LE();
 		uint16 volumeNumber = indexFile.readUint16LE();
 		uint32 offsetInVolume = indexFile.readUint32LE();
@@ -89,7 +89,7 @@ Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::Pa
 	FileDescriptor desc = _files.getVal(translated);
 
 	if (desc._compressionAlgo != 0 && desc._compressionAlgo != 1) {
-		debug ("Unsupported compression algorithm %d for %s", desc._compressionAlgo, desc._fileName.c_str());
+		debug ("Unsupported compression algorithm %d for %s", desc._compressionAlgo, desc._fileName.toString().c_str());
 		return Common::SharedArchiveContents();
 	}
 
@@ -103,14 +103,14 @@ Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::Pa
 		Common::File fvol;
 		Common::Path volumePath = _baseName.append(Common::String::format(".%03d", vol));
 		if (!fvol.open(volumePath)) {
-			error("Failed to open volume %s.%03d", volumePath.toString().c_str(), vol);
+			error("Failed to open volume %s.%03d", volumePath.toString(Common::Path::kNativeSeparator).c_str(), vol);
 			delete[] compressedBuf;
 			return Common::SharedArchiveContents();
 		}
 		fvol.seek(off);
 		int32 actual = fvol.read(outptr, rem);
 		if (actual <= 0) {
-			warning("Read failure in volume %s.%03d", volumePath.toString().c_str(), vol);
+			warning("Read failure in volume %s.%03d", volumePath.toString(Common::Path::kNativeSeparator).c_str(), vol);
 			delete[] compressedBuf;
 			return Common::SharedArchiveContents();
 		}
@@ -137,7 +137,7 @@ Common::SharedArchiveContents MpsInstaller::readContentsForPath(const Common::Pa
 			if (!Common::decompressDCL(&compressedReadStream, uncompressedBuf, desc._compressedSize, uncompressedSize)) {
 				delete[] compressedBuf;
 				delete[] uncompressedBuf;
-				error("Unable to decompress %s", desc._fileName.c_str());
+				error("Unable to decompress %s", desc._fileName.toString().c_str());
 				return Common::SharedArchiveContents();
 			}
 			delete[] compressedBuf;
diff --git a/engines/mads/mps_installer.h b/engines/mads/mps_installer.h
index 46cef05d95e..b5d285709b9 100644
--- a/engines/mads/mps_installer.h
+++ b/engines/mads/mps_installer.h
@@ -50,7 +50,7 @@ private:
 				   _offsetInVolume(0),
 				   _volumeNumber(0) {}
 	protected:
-		FileDescriptor(const Common::String& name,
+		FileDescriptor(const Common::Path &name,
 			       uint16 compression,
 			       uint16 volumeNumber,
 			       uint32 offsetInVolume,
@@ -63,7 +63,7 @@ private:
 			_compressedSize(compressedSize),
 			_uncompressedSize(uncompressedSize) {}
 		
-		Common::String _fileName;
+		Common::Path _fileName;
 		uint _compressionAlgo;
 		uint _volumeNumber;
 		uint32 _offsetInVolume;
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index c546b816dac..86db234ba50 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -68,7 +68,7 @@ public:
 	/**
 	* Base method for descendents to load their contents
 	*/
-	virtual void load(const Common::String &resName) {}
+	virtual void load(const Common::Path &resName) {}
 public:
 	/**
 	 * Basic constructor
diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp
index 7f7ac80a994..02b2bd06f29 100644
--- a/engines/mads/nebular/dialogs_nebular.cpp
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -568,7 +568,7 @@ void PictureDialog::save() {
 	_vm->_screen->translate(map);
 
 	// Load the inventory picture
-	Common::String setName = Common::String::format("*OB%.3d.SS", _objectId);
+	Common::Path setName(Common::String::format("*OB%.3d.SS", _objectId));
 	SpriteAsset *asset = new SpriteAsset(_vm, setName, 0x8000);
 	palette.setFullPalette(palette._mainPalette);
 
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index 4963234eb46..3633eddfc11 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -75,7 +75,7 @@ void MainMenu::display() {
 
 	// Load each of the menu item assets and add to the scene sprites list
 	for (int i = 0; i < 7; ++i) {
-		Common::String spritesName = Resources::formatName(NEBULAR_MENUSCREEN,
+		Common::Path spritesName = Resources::formatName(NEBULAR_MENUSCREEN,
 			'A', i + 1, EXT_SS, "");
 		_menuItems[i] = new SpriteAsset(_vm, spritesName, 0);
 		_menuItemIndexes[i] = scene._sprites.add(_menuItems[i]);
diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp
index 92f5515d97b..1728f9e760e 100644
--- a/engines/mads/nebular/nebular_scenes.cpp
+++ b/engines/mads/nebular/nebular_scenes.cpp
@@ -303,7 +303,7 @@ NebularScene::NebularScene(MADSEngine *vm) : SceneLogic(vm),
 		_action(vm->_game->_scene._action) {
 }
 
-Common::String NebularScene::formAnimName(char sepChar, int suffixNum) {
+Common::Path NebularScene::formAnimName(char sepChar, int suffixNum) {
 	return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum,
 		EXT_NONE, "");
 }
diff --git a/engines/mads/nebular/nebular_scenes.h b/engines/mads/nebular/nebular_scenes.h
index 72e2e4cdb14..f1a95b272ef 100644
--- a/engines/mads/nebular/nebular_scenes.h
+++ b/engines/mads/nebular/nebular_scenes.h
@@ -1354,7 +1354,7 @@ protected:
 	/**
 	 * Forms an animation resource name
 	 */
-	Common::String formAnimName(char sepChar, int suffixNum);
+	Common::Path formAnimName(char sepChar, int suffixNum);
 
 	/**
 	 * Plays appropriate sound for entering various rooms
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index 414a8761e56..0de1c34e076 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -155,10 +155,10 @@ AdlibSample::AdlibSample(Common::SeekableReadStream &s) {
 
 /*-----------------------------------------------------------------------*/
 
-ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filename, int dataOffset) {
+ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::Path &filename, int dataOffset) {
 	// Open up the appropriate sound file
 	if (!_soundFile.open(filename))
-		error("Could not open file - %s", filename.c_str());
+		error("Could not open file - %s", filename.toString().c_str());
 
 	// Initialize fields
 	_commandParam = 0;
@@ -236,14 +236,14 @@ void ASound::validate() {
 	};
 
 	for (int i = 1; i <= 9; ++i) {
-		Common::String filename = Common::String::format("ASOUND.00%d", i);
+		Common::Path filename(Common::String::format("ASOUND.00%d", i));
 		if (!f.open(filename))
-			error("Could not process - %s", filename.c_str());
+			error("Could not process - %s", filename.toString().c_str());
 		Common::String md5str = Common::computeStreamMD5AsString(f, 8192);
 		f.close();
 
 		if (md5str != MD5[i - 1])
-			error("Invalid sound file - %s", filename.c_str());
+			error("Invalid sound file - %s", filename.toString().c_str());
 	}
 }
 
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
index d92899d314c..bfc2ca87fcc 100644
--- a/engines/mads/nebular/sound_nebular.h
+++ b/engines/mads/nebular/sound_nebular.h
@@ -324,7 +324,7 @@ public:
 	 * @param filename		Specifies the adlib sound player file to use
 	 * @param dataOffset	Offset in the file of the data segment
 	 */
-	ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filename, int dataOffset);
+	ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::Path &filename, int dataOffset);
 
 	/**
 	 * Destructor
diff --git a/engines/mads/phantom/phantom_scenes.cpp b/engines/mads/phantom/phantom_scenes.cpp
index 08dc18646b6..ef4c2145a07 100644
--- a/engines/mads/phantom/phantom_scenes.cpp
+++ b/engines/mads/phantom/phantom_scenes.cpp
@@ -167,7 +167,7 @@ PhantomScene::PhantomScene(MADSEngine *vm) : SceneLogic(vm),
 		_action(vm->_game->_scene._action) {
 }
 
-Common::String PhantomScene::formAnimName(char sepChar, int suffixNum) {
+Common::Path PhantomScene::formAnimName(char sepChar, int suffixNum) {
 	return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum,
 		EXT_NONE, "");
 }
@@ -176,7 +176,7 @@ Common::String PhantomScene::formAnimName(char sepChar, int suffixNum) {
 
 void SceneInfoPhantom::loadCodes(BaseSurface &depthSurface, int variant) {
 	Common::String ext = Common::String::format(".WW%d", variant);
-	Common::String fileName = Resources::formatName(RESPREFIX_RM, _sceneId, ext);
+	Common::Path fileName = Resources::formatName(RESPREFIX_RM, _sceneId, ext);
 	if (!Common::File::exists(fileName))
 		return;
 
diff --git a/engines/mads/phantom/phantom_scenes.h b/engines/mads/phantom/phantom_scenes.h
index 00aed5699b6..506ebd9003f 100644
--- a/engines/mads/phantom/phantom_scenes.h
+++ b/engines/mads/phantom/phantom_scenes.h
@@ -455,7 +455,7 @@ protected:
 	/**
 	 * Forms an animation resource name
 	 */
-	Common::String formAnimName(char sepChar, int suffixNum);
+	Common::Path formAnimName(char sepChar, int suffixNum);
 
 	/**
 	 * Plays appropriate sound for entering varous rooms
diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp
index eccc9fc37cd..a6b2d8e4915 100644
--- a/engines/mads/player.cpp
+++ b/engines/mads/player.cpp
@@ -147,8 +147,8 @@ bool Player::loadSprites(const Common::String &prefix) {
 	_numSprites = 0;
 	if (!_spritesPrefix.empty()) {
 		for (int fileIndex = 0; fileIndex < PLAYER_SPRITES_FILE_COUNT; ++fileIndex) {
-			Common::String setName = Common::String::format("*%s_%c.SS",
-				newPrefix.c_str(), suffixList[fileIndex]);
+			Common::Path setName(Common::String::format("*%s_%c.SS",
+				newPrefix.c_str(), suffixList[fileIndex]));
 			if (fileIndex >= 5)
 				_highSprites = true;
 
diff --git a/engines/mads/resources.cpp b/engines/mads/resources.cpp
index f5debd0a670..29d3240e13a 100644
--- a/engines/mads/resources.cpp
+++ b/engines/mads/resources.cpp
@@ -39,12 +39,12 @@ private:
 	 * Details of a single entry in a HAG file index
 	 */
 	struct HagEntry {
-		Common::String _resourceName;
+		Common::Path _resourceName;
 		uint32 _offset;
 		uint32 _size;
 
 		HagEntry() : _offset(0), _size(0) {}
-		HagEntry(Common::String resourceName, uint32 offset, uint32 size)
+		HagEntry(const Common::Path &resourceName, uint32 offset, uint32 size)
 			: _resourceName(resourceName), _offset(offset), _size(size) {
 		}
 	};
@@ -52,7 +52,7 @@ private:
 	class HagIndex {
 	public:
 		Common::List<HagEntry> _entries;
-		Common::String _filename;
+		Common::Path _filename;
 	};
 
 	Common::Array<HagIndex> _index;
@@ -66,12 +66,12 @@ private:
 	 * Given a resource name, opens up the correct HAG file and returns whether
 	 * an entry with the given name exists.
 	 */
-	bool getHeaderEntry(const Common::String &resourceName, HagIndex &hagIndex, HagEntry &hagEntry) const;
+	bool getHeaderEntry(const Common::Path &resourceName, HagIndex &hagIndex, HagEntry &hagEntry) const;
 
 	/**
 	 * Returns the HAG resource filename that will contain a given resource
 	 */
-	Common::String getResourceFilename(const Common::String &resourceName) const;
+	Common::Path getResourceFilename(const Common::Path &resourceName) const;
 
 	/**
 	 * Return a resource type given a resource name
@@ -99,10 +99,9 @@ HagArchive::~HagArchive() {
 
 // Archive implementation
 bool HagArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	HagIndex hagIndex;
 	HagEntry hagEntry;
-	return getHeaderEntry(name, hagIndex, hagEntry);
+	return getHeaderEntry(path, hagIndex, hagEntry);
 }
 
 int HagArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -123,19 +122,17 @@ int HagArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr HagArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *HagArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	HagIndex hagIndex;
 	HagEntry hagEntry;
 
-	if (getHeaderEntry(name, hagIndex, hagEntry)) {
+	if (getHeaderEntry(path, hagIndex, hagEntry)) {
 		// Entry found. If the correct file is not already open, open it
 		Common::File f;
 		if (!f.open(hagIndex._filename))
@@ -180,8 +177,8 @@ void HagArchive::loadIndex(MADSEngine *vm) {
 				continue;
 		}
 
-		Common::String filename = (sectionIndex == -1) ? "GLOBAL.HAG" :
-			Common::String::format("SECTION%d.HAG", sectionIndex);
+		Common::Path filename = (sectionIndex == -1) ? Common::Path("GLOBAL.HAG") :
+			Common::Path(Common::String::format("SECTION%d.HAG", sectionIndex));
 		if (sectionIndex == 10) {
 			// Speech
 			if (!Common::File::exists("SPEECH.HAG"))
@@ -190,7 +187,7 @@ void HagArchive::loadIndex(MADSEngine *vm) {
 				filename = "SPEECH.HAG";
 		}
 		if (!hagFile.open(filename))
-			error("Could not locate HAG file - %s", filename.c_str());
+			error("Could not locate HAG file - %s", filename.toString().c_str());
 
 		// Check for header
 		char headerBuffer[16];
@@ -219,14 +216,17 @@ void HagArchive::loadIndex(MADSEngine *vm) {
 	}
 }
 
-bool HagArchive::getHeaderEntry(const Common::String &resourceName,
+bool HagArchive::getHeaderEntry(const Common::Path &resourceName,
 		HagIndex &hagIndex, HagEntry &hagEntry) const {
-	Common::String resName = resourceName;
+	Common::Path resName = resourceName;
 	resName.toUppercase();
-	if (resName[0] == '*')
-		resName.deleteChar(0);
+	Common::String baseName(resName.baseName());
+	if (baseName[0] == '*') {
+		baseName.deleteChar(0);
+		resName = resName.getParent().appendComponent(baseName);
+	}
 
-	Common::String hagFilename = getResourceFilename(resName);
+	Common::Path hagFilename = getResourceFilename(resName);
 
 	// Find the index for the given file
 	for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) {
@@ -236,7 +236,7 @@ bool HagArchive::getHeaderEntry(const Common::String &resourceName,
 			Common::List<HagEntry>::iterator ei;
 			for (ei = hagIndex._entries.begin(); ei != hagIndex._entries.end(); ++ei) {
 				hagEntry = *ei;
-				if (hagEntry._resourceName.compareToIgnoreCase(resName) == 0)
+				if (hagEntry._resourceName.equalsIgnoreCase(resName))
 					return true;
 			}
 		}
@@ -245,16 +245,17 @@ bool HagArchive::getHeaderEntry(const Common::String &resourceName,
 	return false;
 }
 
-Common::String HagArchive::getResourceFilename(const Common::String &resourceName) const {
-	ResourceType resType = getResourceType(resourceName);
-	Common::String outputFilename = "GLOBAL.HAG";
+Common::Path HagArchive::getResourceFilename(const Common::Path &resourceName) const {
+	Common::String baseName(resourceName.baseName());
+	ResourceType resType = getResourceType(baseName);
+	Common::Path outputFilename = "GLOBAL.HAG";
 
 	if ((resType == RESTYPE_ROOM) || (resType == RESTYPE_SC)) {
-		int value = atoi(resourceName.c_str() + 2);
+		int value = atoi(baseName.c_str() + 2);
 		int hagFileNum = (resType == RESTYPE_ROOM) ? value / 100 : value;
 
 		if (hagFileNum >= 0)
-			outputFilename = Common::String::format("SECTION%d.HAG", hagFileNum);
+			outputFilename = Common::Path(Common::String::format("SECTION%d.HAG", hagFileNum));
 	}
 
 	if (resType == RESTYPE_SPEECH)
@@ -312,7 +313,7 @@ void Resources::init(MADSEngine *vm) {
 	SearchMan.add("HAG", new HagArchive(vm));
 }
 
-Common::String Resources::formatName(RESPREFIX resType, int id, const Common::String &ext) {
+Common::Path Resources::formatName(RESPREFIX resType, int id, const Common::String &ext) {
 	Common::String result = "*";
 
 	if (resType == 3 && !id) {
@@ -337,10 +338,10 @@ Common::String Resources::formatName(RESPREFIX resType, int id, const Common::St
 		result += ext;
 	}
 
-	return result;
+	return Common::Path(result);
 }
 
-Common::String Resources::formatName(int prefix, char asciiCh, int id, EXTTYPE extType,
+Common::Path Resources::formatName(int prefix, char asciiCh, int id, EXTTYPE extType,
 		const Common::String &suffix) {
 	Common::String result;
 	if (prefix <= 0) {
@@ -379,10 +380,10 @@ Common::String Resources::formatName(int prefix, char asciiCh, int id, EXTTYPE e
 		break;
 	}
 
-	return result;
+	return Common::Path(result);
 }
 
-Common::String Resources::formatResource(const Common::String &resName,
+Common::Path Resources::formatResource(const Common::String &resName,
 		const Common::String &hagFilename) {
 //	int v1 = 0, v2 = 0;
 
@@ -391,19 +392,19 @@ Common::String Resources::formatResource(const Common::String &resName,
 		error("TODO: formatResource");
 	} else {
 		// File outside of hag file
-		return resName;
+		return Common::Path(resName);
 	}
 }
 
-Common::String Resources::formatAAName(int idx) {
+Common::Path Resources::formatAAName(int idx) {
 	return formatName(0, 'I', idx, EXT_AA, "");
 }
 
 /*------------------------------------------------------------------------*/
 
-void File::openFile(const Common::String &filename) {
+void File::openFile(const Common::Path &filename) {
 	if (!Common::File::open(filename))
-		error("Could not open file - %s", filename.c_str());
+		error("Could not open file - %s", filename.toString().c_str());
 }
 
 /*------------------------------------------------------------------------*/
diff --git a/engines/mads/resources.h b/engines/mads/resources.h
index f5c070155a6..3fd867a8481 100644
--- a/engines/mads/resources.h
+++ b/engines/mads/resources.h
@@ -47,11 +47,11 @@ public:
 	 */
 	static void init(MADSEngine *vm);
 
-	static Common::String formatName(RESPREFIX resType, int id, const Common::String &ext);
-	static Common::String formatName(int prefix, char asciiCh, int id,
+	static Common::Path formatName(RESPREFIX resType, int id, const Common::String &ext);
+	static Common::Path formatName(int prefix, char asciiCh, int id,
 		EXTTYPE extType, const Common::String &suffix);
-	static Common::String formatResource(const Common::String &resName, const Common::String &hagFilename);
-	static Common::String formatAAName(int idx);
+	static Common::Path formatResource(const Common::String &resName, const Common::String &hagFilename);
+	static Common::Path formatAAName(int idx);
 };
 
 /**
@@ -67,12 +67,12 @@ public:
 	/**
 	 * Constructor
 	 */
-	File(const Common::String &filename) { openFile(filename); }
+	File(const Common::Path &filename) { openFile(filename); }
 
 	/**
 	 * Opens the given file, throwing an error if it can't be opened
 	 */
-	void openFile(const Common::String &filename);
+	void openFile(const Common::Path &filename);
 };
 
 class SynchronizedList : public Common::Array<int> {
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index 491a7916d31..8e417fc4bdc 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -141,7 +141,7 @@ void Scene::loadSceneLogic() {
 	}
 }
 
-void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) {
+void Scene::loadScene(int sceneId, const Common::Path &prefix, bool palFlag) {
 	// Store the previously active scene number and set the new one
 	_priorSceneId = _currentSceneId;
 	_currentSceneId = sceneId;
@@ -636,7 +636,7 @@ void Scene::checkKeyboard() {
 	}
 }
 
-int Scene::loadAnimation(const Common::String &resName, int trigger) {
+int Scene::loadAnimation(const Common::Path &resName, int trigger) {
 	// WORKAROUND: If there's already a previous active animation used by the
 	// scene, then free it before we create the new one
 	if ((_vm->getGameID() == GType_RexNebular) && _animation[0])
diff --git a/engines/mads/scene.h b/engines/mads/scene.h
index 18ab10739b0..ede33136dfb 100644
--- a/engines/mads/scene.h
+++ b/engines/mads/scene.h
@@ -175,7 +175,7 @@ public:
 	 * @param prefix		Prefix to use for retrieving animation data
 	 * @param palFlag		Flag for whether to reset the high/lo palette areas
 	 */
-	void loadScene(int sceneId, const Common::String &prefix, bool palFlag);
+	void loadScene(int sceneId, const Common::Path &prefix, bool palFlag);
 
 	/**
 	 * Loads the hotstpots for the scene
@@ -212,7 +212,7 @@ public:
 	/**
 	 * Load an animation
 	 */
-	int loadAnimation(const Common::String &resName, int trigger = 0);
+	int loadAnimation(const Common::Path &resName, int trigger = 0);
 
 	/**
 	 * Returns a vocab entry
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp
index 8d629c6d5b5..2ac264e651a 100644
--- a/engines/mads/scene_data.cpp
+++ b/engines/mads/scene_data.cpp
@@ -133,11 +133,11 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
 	bool sceneFlag = sceneId >= 0;
 
 	// Figure out the resource to use
-	Common::String resourceName;
+	Common::Path resourceName;
 	if (sceneFlag) {
 		resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".DAT");
 	} else {
-		resourceName = "*" + Resources::formatResource(resName, resName);
+		resourceName = Common::Path("*").appendInPlace(Resources::formatResource(resName, resName));
 	}
 
 	// Open the scene info resource for access
@@ -275,7 +275,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
 				setResName += "*";
 			setResName += setNames[i];
 
-			SpriteAsset *sprites = new SpriteAsset(_vm, setResName, flags);
+			SpriteAsset *sprites = new SpriteAsset(_vm, Common::Path(setResName), flags);
 			spriteSets.push_back(sprites);
 			usageList.push_back(sprites->_usageIndex);
 		}
@@ -302,7 +302,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
 
 void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, BaseSurface &bgSurface) {
 	bool sceneFlag = sceneId >= 0;
-	Common::String resourceName;
+	Common::Path resourceName;
 	bool isV2 = (_vm->getGameID() != GType_RexNebular);
 	Common::String extension = !isV2 ? ".ART" : ".TT";
 	int paletteStream = !isV2 ? 0 : 2;
@@ -311,7 +311,7 @@ void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &r
 	if (sceneFlag) {
 		resourceName = Resources::formatName(RESPREFIX_RM, artFileNum, extension);
 	} else {
-		resourceName = "*" + Resources::formatResource(resName, resName);
+		resourceName = Common::Path("*").appendInPlace(Resources::formatResource(resName, resName));
 	}
 
 	// Load in the ART header and palette
@@ -354,14 +354,14 @@ void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &r
 
 void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName, int flags, BaseSurface &bgSurface) {
 	bool sceneFlag = sceneId >= 0;
-	Common::String resourceName;
+	Common::Path resourceName;
 	Common::SeekableReadStream *stream;
 
 	// Get the ART resource
 	if (sceneFlag) {
 		resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".ART");
 	} else {
-		resourceName = "*" + Resources::formatResource(resName, resName);
+		resourceName = Common::Path("*").appendInPlace(Resources::formatResource(resName, resName));
 	}
 
 	// Load in the ART data
@@ -399,7 +399,7 @@ void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName,
 }
 
 void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, int flags, BaseSurface &bgSurface) {
-	Common::String tileMapResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".MM");
+	Common::Path tileMapResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".MM");
 	File tileMapFile(tileMapResourceName);
 	MadsPack tileMapPack(&tileMapFile);
 	Common::SeekableReadStream *mapStream = tileMapPack.getItemStream(0);
@@ -430,7 +430,7 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName,
 
 	// Tile data, which needs to be kept compressed, as the tile map offsets refer to
 	// the compressed data. Each tile is then uncompressed separately
-	Common::String tileDataResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".TT");
+	Common::Path tileDataResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".TT");
 	File tileDataFile(tileDataResourceName);
 	MadsPack tileDataPack(&tileDataFile);
 	Common::SeekableReadStream *tileDataUncomp = tileDataPack.getItemStream(0);
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
index a06cb189c9b..7e53133e2f2 100644
--- a/engines/mads/sprites.cpp
+++ b/engines/mads/sprites.cpp
@@ -386,7 +386,7 @@ int SpriteSets::add(SpriteAsset *asset, int idx) {
 	}
 }
 
-int SpriteSets::addSprites(const Common::String &resName, int flags) {
+int SpriteSets::addSprites(const Common::Path &resName, int flags) {
 	return add(new SpriteAsset(_vm, resName, flags));
 }
 
diff --git a/engines/mads/sprites.h b/engines/mads/sprites.h
index f3828ec2068..b38bf450435 100644
--- a/engines/mads/sprites.h
+++ b/engines/mads/sprites.h
@@ -226,7 +226,7 @@ public:
 	/**
 	 * Adds a sprite asset to the list by name
 	 */
-	int addSprites(const Common::String &resName, int flags = 0);
+	int addSprites(const Common::Path &resName, int flags = 0);
 
 	/**
 	 * Remove an asset from the list
diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp
index e77c949db84..1395421dcac 100644
--- a/engines/mads/user_interface.cpp
+++ b/engines/mads/user_interface.cpp
@@ -344,7 +344,7 @@ UserInterface::UserInterface(MADSEngine *vm) : _vm(vm), _dirtyAreas(vm),
 	_surface.create(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
 }
 
-void UserInterface::load(const Common::String &resName) {
+void UserInterface::load(const Common::Path &resName) {
 	File f(resName);
 	MadsPack madsPack(&f);
 
@@ -374,19 +374,21 @@ void UserInterface::setup(InputMode inputMode) {
 	Scene &scene = _vm->_game->_scene;
 
 	if (_vm->_game->_screenObjects._inputMode != inputMode) {
-		Common::String resName = _vm->_game->_aaName;
+		Common::Path resName = _vm->_game->_aaName;
 
 		// Strip off any extension
-		const char *p = strchr(resName.c_str(), '.');
+		Common::String baseName(resName.baseName());
+		const char *p = strchr(baseName.c_str(), '.');
 		if (p) {
-			resName = Common::String(resName.c_str(), p);
+			baseName = Common::String(baseName.c_str(), p);
+			resName = resName.getParent().appendComponent(baseName);
 		}
 
 		// Add on suffix if necessary
 		if (inputMode != kInputBuildingSentences)
-			resName += "A";
+			resName.appendInPlace("A");
 
-		resName += ".INT";
+		resName.appendInPlace(".INT");
 
 		load(resName);
 		blitFrom(_surface);
@@ -866,7 +868,7 @@ void UserInterface::loadInventoryAnim(int objectId) {
 
 	// WORKAROUND: Even in still mode, we now load the animation frames for the
 	// object, so we can show the first frame as a 'still'
-	Common::String resName = Common::String::format("*OB%.3dI", objectId);
+	Common::Path resName(Common::String::format("*OB%.3dI", objectId));
 	SpriteAsset *asset = new SpriteAsset(_vm, resName, ASSET_SPINNING_OBJECT);
 	_invSpritesIndex = scene._sprites.add(asset, 1);
 	if (_invSpritesIndex >= 0) {
diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h
index df8418d9c46..c5e2d900a22 100644
--- a/engines/mads/user_interface.h
+++ b/engines/mads/user_interface.h
@@ -220,7 +220,7 @@ public:
 	/**
 	* Loads an interface from a specified resource
 	*/
-	void load(const Common::String &resName) override;
+	void load(const Common::Path &resName) override;
 
 	/**
 	* Set up the interface


Commit: 0512d96b47a76a4d5003fea9825bab55db19e161
    https://github.com/scummvm/scummvm/commit/0512d96b47a76a4d5003fea9825bab55db19e161
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MM: Migrate engine to Path

Changed paths:
    engines/mm/mm1/console.cpp
    engines/mm/mm1/data/character.cpp
    engines/mm/mm1/gfx/dta.cpp
    engines/mm/mm1/gfx/dta.h
    engines/mm/mm1/gfx/screen_decoder.cpp
    engines/mm/mm1/gfx/screen_decoder.h
    engines/mm/mm1/maps/map.cpp
    engines/mm/mm1/views/title.cpp
    engines/mm/mm1/views_enh/create_characters.cpp
    engines/mm/mm1/views_enh/game_view.cpp
    engines/mm/mm1/views_enh/interactions/interaction.cpp
    engines/mm/mm1/views_enh/main_menu.cpp
    engines/mm/shared/utils/bitmap_font.cpp
    engines/mm/shared/utils/bitmap_font.h
    engines/mm/shared/utils/engine_data.cpp
    engines/mm/shared/utils/strings_data.cpp
    engines/mm/shared/utils/strings_data.h
    engines/mm/shared/xeen/cc_archive.cpp
    engines/mm/shared/xeen/cc_archive.h
    engines/mm/shared/xeen/file.cpp
    engines/mm/shared/xeen/file.h
    engines/mm/shared/xeen/sound.cpp
    engines/mm/shared/xeen/sound.h
    engines/mm/shared/xeen/sprites.cpp
    engines/mm/shared/xeen/sprites.h
    engines/mm/xeen/combat.cpp
    engines/mm/xeen/dialogs/dialogs.cpp
    engines/mm/xeen/dialogs/dialogs.h
    engines/mm/xeen/dialogs/dialogs_input.cpp
    engines/mm/xeen/dialogs/dialogs_items.cpp
    engines/mm/xeen/dialogs/dialogs_spells.cpp
    engines/mm/xeen/files.cpp
    engines/mm/xeen/files.h
    engines/mm/xeen/locations.cpp
    engines/mm/xeen/locations.h
    engines/mm/xeen/map.cpp
    engines/mm/xeen/map.h
    engines/mm/xeen/party.cpp
    engines/mm/xeen/resources.h
    engines/mm/xeen/screen.cpp
    engines/mm/xeen/screen.h
    engines/mm/xeen/scripts.cpp
    engines/mm/xeen/sprites.cpp
    engines/mm/xeen/sprites.h
    engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
    engines/mm/xeen/worldofxeen/clouds_cutscenes.h
    engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp


diff --git a/engines/mm/mm1/console.cpp b/engines/mm/mm1/console.cpp
index 8c2640aa869..78e36c45977 100644
--- a/engines/mm/mm1/console.cpp
+++ b/engines/mm/mm1/console.cpp
@@ -75,7 +75,7 @@ bool Console::cmdDumpMap(int argc, const char **argv) {
 			f.close();
 		}
 
-		if (f.open(Common::String::format("%s.ovr", map->getName().c_str()))) {
+		if (f.open(Common::Path(Common::String::format("%s.ovr", map->getName().c_str())))) {
 			int magicId = f.readUint16LE();
 			int codePtr = f.readUint16LE();
 			int codeSize = f.readUint16LE();
@@ -217,7 +217,7 @@ bool Console::cmdMapString(int argc, const char **argv) {
 		int offset = strToInt(Common::String::format(
 			"%sh", argv[2]).c_str());
 
-		if (!f.open(Common::String::format("%s.ovr", map->getName().c_str())))
+		if (!f.open(Common::Path(Common::String::format("%s.ovr", map->getName().c_str()))))
 			error("Failed to open map");
 
 		f.readUint16LE();
diff --git a/engines/mm/mm1/data/character.cpp b/engines/mm/mm1/data/character.cpp
index 1306e3ab593..f672ab2a25e 100644
--- a/engines/mm/mm1/data/character.cpp
+++ b/engines/mm/mm1/data/character.cpp
@@ -244,8 +244,8 @@ void Character::synchronize(Common::Serializer &s, int portraitNum) {
 
 void Character::loadFaceSprites() {
 	if (_portrait != 0xff && g_engine->isEnhanced()) {
-		Common::String cname = Common::String::format("char%02d.fac",
-			_portrait * 2 + (_sex == MALE ? 0 : 1) + 1);
+		Common::Path cname(Common::String::format("char%02d.fac",
+			_portrait * 2 + (_sex == MALE ? 0 : 1) + 1));
 		_faceSprites.load(cname);
 	}
 }
diff --git a/engines/mm/mm1/gfx/dta.cpp b/engines/mm/mm1/gfx/dta.cpp
index aa7c7c69a4c..45d1fd8fb0a 100644
--- a/engines/mm/mm1/gfx/dta.cpp
+++ b/engines/mm/mm1/gfx/dta.cpp
@@ -31,7 +31,7 @@ Common::SeekableReadStream *DTA::load(uint entryIndex) {
 	Common::File f;
 
 	if (!f.open(_fname))
-		error("Could not open - %s", _fname.c_str());
+		error("Could not open - %s", _fname.toString().c_str());
 
 	uint indexSize = f.readUint16LE();
 	assert(entryIndex < (indexSize / 4));
diff --git a/engines/mm/mm1/gfx/dta.h b/engines/mm/mm1/gfx/dta.h
index 32555f912a5..506326dceca 100644
--- a/engines/mm/mm1/gfx/dta.h
+++ b/engines/mm/mm1/gfx/dta.h
@@ -33,9 +33,9 @@ namespace Gfx {
 
 class DTA {
 public:
-	Common::String _fname;
+	Common::Path _fname;
 public:
-	DTA(const Common::String &fname) : _fname(fname) {
+	DTA(const Common::Path &fname) : _fname(fname) {
 	}
 
 	/**
diff --git a/engines/mm/mm1/gfx/screen_decoder.cpp b/engines/mm/mm1/gfx/screen_decoder.cpp
index 684ce60640c..22ea1592576 100644
--- a/engines/mm/mm1/gfx/screen_decoder.cpp
+++ b/engines/mm/mm1/gfx/screen_decoder.cpp
@@ -40,7 +40,7 @@ void ScreenDecoder::destroy() {
 	_surface.free();
 }
 
-bool ScreenDecoder::loadFile(const Common::String &fname,
+bool ScreenDecoder::loadFile(const Common::Path &fname,
 		int16 w, int16 h) {
 	Common::File f;
 	if (!f.open(fname))
diff --git a/engines/mm/mm1/gfx/screen_decoder.h b/engines/mm/mm1/gfx/screen_decoder.h
index 09b76099eec..723b8edfc21 100644
--- a/engines/mm/mm1/gfx/screen_decoder.h
+++ b/engines/mm/mm1/gfx/screen_decoder.h
@@ -39,7 +39,7 @@ public:
 	~ScreenDecoder() override;
 
 	void destroy() override;
-	bool loadFile(const Common::String &fname,
+	bool loadFile(const Common::Path &fname,
 		int16 w = 320, int16 h = 200);
 	bool loadStream(Common::SeekableReadStream &stream, int16 w, int16 h);
 	bool loadStream(Common::SeekableReadStream &stream) override {
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 5ada7d22ad4..56c5c7d90b6 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -64,7 +64,7 @@ void Map::loadMazeData() {
 
 void Map::loadOverlay() {
 	Common::File f;
-	if (!f.open(Common::String::format("%s.ovr", _name.c_str())))
+	if (!f.open(Common::Path(Common::String::format("%s.ovr", _name.c_str()))))
 		error("Could not open %s.ovr overlay", _name.c_str());
 
 	int magicId = f.readUint16LE();
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index f6dcc8f611a..d78fd7d63f6 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -48,9 +48,9 @@ bool Title::msgFocus(const FocusMessage &msg) {
 			decoder._indexes[2] = 5;
 		}
 
-		if (decoder.loadFile(
+		if (decoder.loadFile(Common::Path(
 			Common::String::format(g_engine->isEnhanced() ?
-				"gfx/screen%d" : "screen%d", i))) {
+				"gfx/screen%d" : "screen%d", i)))) {
 			_screens[i].copyFrom(decoder.getSurface());
 		} else {
 			error("Could not load title screen");
diff --git a/engines/mm/mm1/views_enh/create_characters.cpp b/engines/mm/mm1/views_enh/create_characters.cpp
index 82ac33d3ac6..a2d90efe8b9 100644
--- a/engines/mm/mm1/views_enh/create_characters.cpp
+++ b/engines/mm/mm1/views_enh/create_characters.cpp
@@ -60,8 +60,8 @@ void CreateCharacters::NewCharacter::reroll() {
 }
 
 void CreateCharacters::NewCharacter::loadPortrait() {
-	Common::String cname = Common::String::format("char%02d.fac",
-		_portrait * 2 + (_sex == MALE ? 0 : 1) + 1);
+	Common::Path cname(Common::String::format("char%02d.fac",
+		_portrait * 2 + (_sex == MALE ? 0 : 1) + 1));
 	_portraits.load(cname);
 }
 
diff --git a/engines/mm/mm1/views_enh/game_view.cpp b/engines/mm/mm1/views_enh/game_view.cpp
index f1df338ee6c..f5e909f1c5d 100644
--- a/engines/mm/mm1/views_enh/game_view.cpp
+++ b/engines/mm/mm1/views_enh/game_view.cpp
@@ -35,8 +35,8 @@ ViewAnimation::ViewAnimation(const char *prefix, uint count, uint frameCount) :
 	_backgrounds.resize(count);
 
 	for (uint i = 0; i < _backgrounds.size(); ++i) {
-		Common::String name = Common::String::format(
-			"%s%d.twn", prefix, i + 1);
+		Common::Path name(Common::String::format(
+			"%s%d.twn", prefix, i + 1));
 		_backgrounds[i].load(name);
 	}
 }
diff --git a/engines/mm/mm1/views_enh/interactions/interaction.cpp b/engines/mm/mm1/views_enh/interactions/interaction.cpp
index 5e7f7ca5725..8e1eeefd463 100644
--- a/engines/mm/mm1/views_enh/interactions/interaction.cpp
+++ b/engines/mm/mm1/views_enh/interactions/interaction.cpp
@@ -37,7 +37,7 @@ Interaction::Interaction(const Common::String &name, int portrait) : PartyView(n
 
 	if (portrait != -1) {
 		_frame.load("frame.fac");
-		_portrait.load(Common::String::format("face%02d.fac", portrait));
+		_portrait.load(Common::Path(Common::String::format("face%02d.fac", portrait)));
 	}
 }
 
diff --git a/engines/mm/mm1/views_enh/main_menu.cpp b/engines/mm/mm1/views_enh/main_menu.cpp
index d0fed2f5a6c..cb2481f1c1e 100644
--- a/engines/mm/mm1/views_enh/main_menu.cpp
+++ b/engines/mm/mm1/views_enh/main_menu.cpp
@@ -39,7 +39,7 @@ void MainMenu::drawCircles() {
 	decoder._indexes[3] = 15;
 
 	for (int i = 0; i < 2; ++i) {
-		if (decoder.loadFile(Common::String::format("screen%d", i))) {
+		if (decoder.loadFile(Common::Path(Common::String::format("screen%d", i)))) {
 			const Graphics::Surface *src = decoder.getSurface();
 
 			if (i == 0) {
diff --git a/engines/mm/shared/utils/bitmap_font.cpp b/engines/mm/shared/utils/bitmap_font.cpp
index 9eb530e9fd9..d600581bfee 100644
--- a/engines/mm/shared/utils/bitmap_font.cpp
+++ b/engines/mm/shared/utils/bitmap_font.cpp
@@ -25,7 +25,7 @@
 
 namespace MM {
 
-bool BitmapFont::load(const Common::String &filename) {
+bool BitmapFont::load(const Common::Path &filename) {
 	Image::BitmapDecoder decoder;
 	Common::File f;
 	_startingChar = ' ';
diff --git a/engines/mm/shared/utils/bitmap_font.h b/engines/mm/shared/utils/bitmap_font.h
index d92e4203884..f40d0818795 100644
--- a/engines/mm/shared/utils/bitmap_font.h
+++ b/engines/mm/shared/utils/bitmap_font.h
@@ -45,7 +45,7 @@ public:
 	/**
 	 * Loads the font
 	 */
-	bool load(const Common::String &filename);
+	bool load(const Common::Path &filename);
 
 	/**
 	 * Get the font height
diff --git a/engines/mm/shared/utils/engine_data.cpp b/engines/mm/shared/utils/engine_data.cpp
index 87a8e4155b1..5e1715841f9 100644
--- a/engines/mm/shared/utils/engine_data.cpp
+++ b/engines/mm/shared/utils/engine_data.cpp
@@ -33,11 +33,11 @@ namespace MM {
 class DataArchiveMember : public Common::ArchiveMember {
 private:
 	Common::SharedPtr<Common::ArchiveMember> _member;
-	Common::String _publicFolder;
-	Common::String _innerfolder;
+	Common::Path _publicFolder;
+	Common::Path _innerfolder;
 public:
 	DataArchiveMember(Common::SharedPtr<Common::ArchiveMember> member,
-		const Common::String &subfolder, const Common::String &publicFolder) :
+		const Common::Path &subfolder, const Common::Path &publicFolder) :
 			_member(member), _publicFolder(publicFolder), _innerfolder(subfolder) {
 	}
 	~DataArchiveMember() override {
@@ -48,16 +48,16 @@ public:
 	Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override {
 		return nullptr;
 	}
-	Common::String getName() const override {
-		Common::String name = _member->getName();
-		assert(name.hasPrefixIgnoreCase(_innerfolder));
-		return _publicFolder + Common::String(name.c_str() + _innerfolder.size());
+	Common::Path getPathInArchive() const override {
+		Common::Path name = _member->getPathInArchive();
+		assert(name.isRelativeTo(_innerfolder));
+		return _publicFolder.join(name.relativeTo(_innerfolder));
 	}
 	Common::U32String getDisplayName() const override {
 		return _member->getDisplayName();
 	}
-	Common::String getFileName() const override { return getName(); }
-	Common::Path getPathInArchive() const override { return getName(); }
+	Common::String getFileName() const override { return _member->getFileName(); }
+	Common::String getName() const override { return getPathInArchive().toString(); }
 };
 
 /**
@@ -67,16 +67,16 @@ public:
 class DataArchive : public Common::Archive {
 private:
 	Common::Archive *_zip;
-	Common::String _publicFolder;
-	Common::String _innerfolder;
+	Common::Path _publicFolder;
+	Common::Path _innerfolder;
 
-	Common::String innerToPublic(const Common::String &filename) const {
-		assert(filename.hasPrefixIgnoreCase(_publicFolder));
-		return _innerfolder + Common::String(filename.c_str() + _publicFolder.size());
+	Common::Path publicToInner(const Common::Path &filename) const {
+		assert(filename.isRelativeTo(_publicFolder));
+		return _innerfolder.join(filename.relativeTo(_publicFolder));
 	}
 public:
-	DataArchive(Common::Archive *zip, const Common::String &subfolder, bool useDataPrefix) :
-		_zip(zip), _publicFolder(useDataPrefix ? "data/" : ""), _innerfolder(subfolder + "/") {
+	DataArchive(Common::Archive *zip, const Common::Path &subfolder, bool useDataPrefix) :
+		_zip(zip), _publicFolder(useDataPrefix ? "data/" : ""), _innerfolder(subfolder) {
 	}
 	~DataArchive() override {
 		delete _zip;
@@ -125,12 +125,12 @@ class DataArchiveProxy : public Common::Archive {
 	friend class DataArchive;
 private:
 	Common::FSNode _folder;
-	const Common::String _publicFolder;
+	const Common::Path _publicFolder;
 
 	/**
 	 * Gets a file node from the passed filename
 	 */
-	Common::FSNode getNode(const Common::String &name) const;
+	Common::FSNode getNode(const Common::Path &name) const;
 public:
 	DataArchiveProxy(const Common::FSNode &folder, bool useDataPrefix) :
 		_folder(folder), _publicFolder(useDataPrefix ? "data/" : "") {}
@@ -142,8 +142,7 @@ public:
 	 * replacement.
 	 */
 	bool hasFile(const Common::Path &path) const override {
-		Common::String name = path.toString();
-		return name.hasPrefixIgnoreCase(_publicFolder) && getNode(name).exists();
+		return path.isRelativeTo(_publicFolder) && getNode(path).exists();
 	}
 
 	/**
@@ -174,11 +173,10 @@ public:
 #endif
 
 bool DataArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!name.hasPrefixIgnoreCase(_publicFolder))
+	if (!path.isRelativeTo(_publicFolder))
 		return false;
 
-	Common::String realFilename = innerToPublic(name);
+	Common::Path realFilename = publicToInner(path);
 	return _zip->hasFile(realFilename);
 }
 
@@ -198,17 +196,15 @@ int DataArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr DataArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *DataArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (hasFile(name)) {
-		Common::String filename = innerToPublic(name);
+	if (hasFile(path)) {
+		Common::Path filename = publicToInner(path);
 		return _zip->createReadStreamForMember(filename);
 	}
 
@@ -220,36 +216,36 @@ Common::SeekableReadStream *DataArchive::createReadStreamForMember(const Common:
 #ifndef RELEASE_BUILD
 
 const Common::ArchiveMemberPtr DataArchiveProxy::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *DataArchiveProxy::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (hasFile(name))
-		return getNode(name).createReadStream();
+	if (hasFile(path))
+		return getNode(path).createReadStream();
 
 	return nullptr;
 }
 
-Common::FSNode DataArchiveProxy::getNode(const Common::String &name) const {
-	Common::String remainingName = name.substr(_publicFolder.size());
+Common::FSNode DataArchiveProxy::getNode(const Common::Path &name) const {
+	Common::Path remainingName = name.relativeTo(_publicFolder);
 	Common::FSNode node = _folder;
-	size_t pos;
 
-	while ((pos = remainingName.findFirstOf('/')) != Common::String::npos) {
-		node = node.getChild(remainingName.substr(0, pos));
+	Common::StringArray components = remainingName.splitComponents();
+
+	if (components.empty()) {
+		return node;
+	}
+
+	for(Common::StringArray::const_iterator it = components.begin(); it != components.end() - 1; it++) {
+		node = node.getChild(*it);
 		if (!node.exists())
 			return node;
-
-		remainingName = remainingName.substr(pos + 1);
 	}
 
-	if (!remainingName.empty())
-		node = node.getChild(remainingName);
+	node = node.getChild(*(components.end() - 1));
 
 	return node;
 }
@@ -266,7 +262,7 @@ bool load_engine_data(const Common::String &subfolder, int reqMajorVersion,
 #ifndef RELEASE_BUILD
 	Common::FSNode folder;
 	if (ConfMan.hasKey("extrapath")) {
-		if ((folder = Common::FSNode(ConfMan.get("extrapath"))).exists()
+		if ((folder = Common::FSNode(ConfMan.getPath("extrapath"))).exists()
 			&& (folder = folder.getChild("files")).exists()
 			&& (folder = folder.getChild(subfolder)).exists()) {
 			f.open(folder.getChild("version.txt"));
@@ -277,7 +273,7 @@ bool load_engine_data(const Common::String &subfolder, int reqMajorVersion,
 	if (!f.isOpen()) {
 		if (!Common::File::exists(DATA_FILENAME) ||
 			(dataArchive = Common::makeZipArchive(DATA_FILENAME)) == 0 ||
-			!f.open(Common::String::format("%s/version.txt", subfolder.c_str()), *dataArchive)) {
+			!f.open(Common::Path(Common::String::format("%s/version.txt", subfolder.c_str())), *dataArchive)) {
 			delete dataArchive;
 			errorMsg = Common::U32String::format(_("Could not locate engine data %s"), DATA_FILENAME);
 			return false;
@@ -309,7 +305,7 @@ bool load_engine_data(const Common::String &subfolder, int reqMajorVersion,
 		archive = new DataArchiveProxy(folder, useDataPrefix);
 	else
 #endif
-		archive = new DataArchive(dataArchive, subfolder, useDataPrefix);
+		archive = new DataArchive(dataArchive, Common::Path(subfolder), useDataPrefix);
 
 	SearchMan.add("data", archive);
 	return true;
diff --git a/engines/mm/shared/utils/strings_data.cpp b/engines/mm/shared/utils/strings_data.cpp
index 35ef25c84c1..678edf0495a 100644
--- a/engines/mm/shared/utils/strings_data.cpp
+++ b/engines/mm/shared/utils/strings_data.cpp
@@ -26,7 +26,7 @@
 
 namespace MM {
 
-bool StringsData::load(const Common::String &filename) {
+bool StringsData::load(const Common::Path &filename) {
 	Common::File f;
 	Common::Array<Common::String> prefixKeys;
 	Common::String key, value, fullKey;
diff --git a/engines/mm/shared/utils/strings_data.h b/engines/mm/shared/utils/strings_data.h
index af0eb7592c9..4bd5a2c01b2 100644
--- a/engines/mm/shared/utils/strings_data.h
+++ b/engines/mm/shared/utils/strings_data.h
@@ -33,7 +33,7 @@ public:
 	/**
 	 * Loads the data
 	 */
-	bool load(const Common::String &filename);
+	bool load(const Common::Path &filename);
 };
 
 } // namespace MM
diff --git a/engines/mm/shared/xeen/cc_archive.cpp b/engines/mm/shared/xeen/cc_archive.cpp
index ac136c7b82e..36d5d416b8c 100644
--- a/engines/mm/shared/xeen/cc_archive.cpp
+++ b/engines/mm/shared/xeen/cc_archive.cpp
@@ -28,11 +28,11 @@ namespace MM {
 namespace Shared {
 namespace Xeen {
 
-uint16 BaseCCArchive::convertNameToId(const Common::String &resourceName) {
+uint16 BaseCCArchive::convertNameToId(const Common::Path &resourceName) {
 	if (resourceName.empty())
 		return 0xffff;
 
-	Common::String name = resourceName;
+	Common::String name = resourceName.baseName();
 	name.toUppercase();
 
 	// Check if a resource number is being directly specified
@@ -119,12 +119,11 @@ void BaseCCArchive::saveIndex(Common::WriteStream &stream) {
 }
 
 bool BaseCCArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	CCEntry ccEntry;
-	return getHeaderEntry(name, ccEntry);
+	return getHeaderEntry(path, ccEntry);
 }
 
-bool BaseCCArchive::getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const {
+bool BaseCCArchive::getHeaderEntry(const Common::Path &resourceName, CCEntry &ccEntry) const {
 	return getHeaderEntry(convertNameToId(resourceName), ccEntry);
 }
 
@@ -142,11 +141,10 @@ bool BaseCCArchive::getHeaderEntry(uint16 id, CCEntry &ccEntry) const {
 }
 
 const Common::ArchiveMemberPtr BaseCCArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(Common::String(name), *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -156,24 +154,24 @@ int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const {
 
 /*------------------------------------------------------------------------*/
 
-CCArchive::CCArchive(const Common::String &filename, bool encoded) :
+CCArchive::CCArchive(const Common::Path &filename, bool encoded) :
 	BaseCCArchive(), _filename(filename), _encoded(encoded) {
 
 	Common::File f;
 	if (!f.open(filename, SearchMan))
-		error("Could not open file - %s", filename.c_str());
+		error("Could not open file - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	loadIndex(f);
 }
 
-CCArchive::CCArchive(const Common::String &filename, const Common::String &prefix,
+CCArchive::CCArchive(const Common::Path &filename, const Common::String &prefix,
 	bool encoded) : BaseCCArchive(), _filename(filename),
 	_prefix(prefix), _encoded(encoded) {
 	_prefix.toLowercase();
 
 	Common::File f;
 	if (!f.open(filename, SearchMan))
-		error("Could not open file - %s", filename.c_str());
+		error("Could not open file - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	loadIndex(f);
 }
@@ -181,8 +179,8 @@ CCArchive::CCArchive(const Common::String &filename, const Common::String &prefi
 CCArchive::~CCArchive() {
 }
 
-bool CCArchive::getHeaderEntry(const Common::String &resourceName, Shared::Xeen::CCEntry &ccEntry) const {
-	Common::String resName = resourceName;
+bool CCArchive::getHeaderEntry(const Common::Path &resourceName, Shared::Xeen::CCEntry &ccEntry) const {
+	Common::String resName = resourceName.baseName();
 
 	if (!_prefix.empty() && resName.contains('|')) {
 		resName.toLowercase();
@@ -197,14 +195,13 @@ bool CCArchive::getHeaderEntry(const Common::String &resourceName, Shared::Xeen:
 			return false;
 	}
 
-	return BaseCCArchive::getHeaderEntry(resName, ccEntry);
+	return BaseCCArchive::getHeaderEntry(resourceName.getParent().appendComponent(resName), ccEntry);
 }
 
 Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	Shared::Xeen::CCEntry ccEntry;
 
-	if (getHeaderEntry(name, ccEntry)) {
+	if (getHeaderEntry(path, ccEntry)) {
 		// Open the correct CC file
 		Common::File f;
 		if (!f.open(_filename))
diff --git a/engines/mm/shared/xeen/cc_archive.h b/engines/mm/shared/xeen/cc_archive.h
index 21be50fd22a..959c04e7aee 100644
--- a/engines/mm/shared/xeen/cc_archive.h
+++ b/engines/mm/shared/xeen/cc_archive.h
@@ -66,7 +66,7 @@ protected:
 	 * Given a resource name, returns whether an entry exists, and returns
 	 * the header index data for that entry
 	 */
-	virtual bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const;
+	virtual bool getHeaderEntry(const Common::Path &resourceName, CCEntry &ccEntry) const;
 
 	/**
 	 * Given a resource Id, returns whether an entry exists, and returns
@@ -77,7 +77,7 @@ public:
 	/**
 	 * Hash a given filename to produce the Id that represents it
 	 */
-	static uint16 convertNameToId(const Common::String &resourceName);
+	static uint16 convertNameToId(const Common::Path &resourceName);
 public:
 	BaseCCArchive() {
 	}
@@ -93,14 +93,14 @@ public:
  */
 class CCArchive : public BaseCCArchive {
 private:
-	Common::String _filename;
+	Common::Path _filename;
 	Common::String _prefix;
 	bool _encoded;
 protected:
-	bool getHeaderEntry(const Common::String &resourceName, CCEntry &ccEntry) const override;
+	bool getHeaderEntry(const Common::Path &resourceName, CCEntry &ccEntry) const override;
 public:
-	CCArchive(const Common::String &filename, bool encoded);
-	CCArchive(const Common::String &filename, const Common::String &prefix, bool encoded);
+	CCArchive(const Common::Path &filename, bool encoded);
+	CCArchive(const Common::Path &filename, const Common::String &prefix, bool encoded);
 	~CCArchive() override;
 
 	// Archive implementation
diff --git a/engines/mm/shared/xeen/file.cpp b/engines/mm/shared/xeen/file.cpp
index f31fd216552..39459108b7d 100644
--- a/engines/mm/shared/xeen/file.cpp
+++ b/engines/mm/shared/xeen/file.cpp
@@ -29,16 +29,16 @@ namespace MM {
 namespace Shared {
 namespace Xeen {
 
-File::File(const Common::String &filename) {
+File::File(const Common::Path &filename) {
 	File::open(filename);
 }
 
-File::File(const Common::String &filename, Common::Archive &archive) {
+File::File(const Common::Path &filename, Common::Archive &archive) {
 	File::open(filename, archive);
 }
 
 #ifdef ENABLE_XEEN
-File::File(const Common::String &filename, int ccMode) {
+File::File(const Common::Path &filename, int ccMode) {
 	File::open(filename, ccMode);
 }
 #endif
@@ -54,16 +54,16 @@ bool File::open(const Common::Path &filename) {
 			if (!fm._currentArchive || !Common::File::open(filename, *fm._currentArchive)) {
 				// Could not find in current archive, so try intro.cc or in folder
 				if (!Common::File::open(filename))
-					error("Could not open file - %s", filename.toString().c_str());
+					error("Could not open file - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 			}
 		}
 	} else {
 		if (!Common::File::open(filename))
-			error("Could not open file - %s", filename.toString().c_str());
+			error("Could not open file - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 #else
 	if (!Common::File::open(filename))
-		error("Could not open file - %s", filename.toString().c_str());
+		error("Could not open file - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 #endif
 
 	return true;
@@ -71,12 +71,12 @@ bool File::open(const Common::Path &filename) {
 
 bool File::open(const Common::Path &filename, Common::Archive &archive) {
 	if (!Common::File::open(filename, archive))
-		error("Could not open file - %s", filename.toString().c_str());
+		error("Could not open file - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	return true;
 }
 
 #ifdef ENABLE_XEEN
-bool File::open(const Common::String &filename, int ccMode) {
+bool File::open(const Common::Path &filename, int ccMode) {
 	MM::Xeen::XeenEngine *engine = dynamic_cast<MM::Xeen::XeenEngine *>(g_engine);
 	assert(engine);
 
@@ -133,7 +133,7 @@ Common::String File::readString() {
 	return result;
 }
 
-bool File::exists(const Common::String &filename) {
+bool File::exists(const Common::Path &filename) {
 #ifdef ENABLE_XEEN
 	MM::Xeen::XeenEngine *engine = dynamic_cast<MM::Xeen::XeenEngine *>(g_engine);
 
@@ -157,7 +157,7 @@ bool File::exists(const Common::String &filename) {
 }
 
 #ifdef ENABLE_XEEN
-bool File::exists(const Common::String &filename, int ccMode) {
+bool File::exists(const Common::Path &filename, int ccMode) {
 	MM::Xeen::XeenEngine *engine = dynamic_cast<MM::Xeen::XeenEngine *>(g_engine);
 	assert(engine);
 	MM::Xeen::FileManager &fm = *engine->_files;
@@ -171,7 +171,7 @@ bool File::exists(const Common::String &filename, int ccMode) {
 }
 #endif
 
-bool File::exists(const Common::String &filename, Common::Archive &archive) {
+bool File::exists(const Common::Path &filename, Common::Archive &archive) {
 	return archive.hasFile(filename);
 }
 
diff --git a/engines/mm/shared/xeen/file.h b/engines/mm/shared/xeen/file.h
index 8da8cba0dca..486ec87afb7 100644
--- a/engines/mm/shared/xeen/file.h
+++ b/engines/mm/shared/xeen/file.h
@@ -50,10 +50,10 @@ public:
 public:
 	File() : Common::File() {
 	}
-	File(const Common::String &filename);
-	File(const Common::String &filename, Common::Archive &archive);
+	File(const Common::Path &filename);
+	File(const Common::Path &filename, Common::Archive &archive);
 #ifdef ENABLE_XEEN
-	File(const Common::String &filename, int ccMode);
+	File(const Common::Path &filename, int ccMode);
 #endif
 	~File() override {}
 
@@ -70,7 +70,7 @@ public:
 	/**
 	 * Opens the given file, throwing an error if it can't be opened
 	 */
-	virtual bool open(const Common::String &filename, int ccMode);
+	virtual bool open(const Common::Path &filename, int ccMode);
 #endif
 
 	/**
@@ -98,7 +98,7 @@ public:
 	 * @param	filename	the file to check for
 	 * @return	true if the file exists, false otherwise
 	 */
-	static bool exists(const Common::String &filename);
+	static bool exists(const Common::Path &filename);
 
 #ifdef ENABLE_XEEN
 	/**
@@ -108,7 +108,7 @@ public:
 	 * @param	ccMode		Archive to use
 	 * @return	true if the file exists, false otherwise
 	 */
-	static bool exists(const Common::String &filename, int ccMode);
+	static bool exists(const Common::Path &filename, int ccMode);
 #endif
 
 	/**
@@ -118,7 +118,7 @@ public:
 	 * @param	archive		Archive to use
 	 * @return	true if the file exists, false otherwise
 	 */
-	static bool exists(const Common::String &filename, Common::Archive &archive);
+	static bool exists(const Common::Path &filename, Common::Archive &archive);
 };
 
 } // namespace Xeen
diff --git a/engines/mm/shared/xeen/sound.cpp b/engines/mm/shared/xeen/sound.cpp
index 5ca36ee7aa3..42fda150313 100644
--- a/engines/mm/shared/xeen/sound.cpp
+++ b/engines/mm/shared/xeen/sound.cpp
@@ -62,28 +62,28 @@ void Sound::playSound(Common::SeekableReadStream &s, int unused) {
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream);
 }
 
-void Sound::playSound(const Common::String &name, int unused) {
+void Sound::playSound(const Common::Path &name, int unused) {
 	File f;
 	if (!f.open(name))
-		error("Could not open sound - %s", name.c_str());
+		error("Could not open sound - %s", name.toString().c_str());
 
 	playSound(f);
 }
 
 #ifdef ENABLE_XEEN
-void Sound::playSound(const Common::String &name, int ccNum, int unused) {
+void Sound::playSound(const Common::Path &name, int ccNum, int unused) {
 	File f;
 	if (!f.open(name, ccNum))
-		error("Could not open sound - %s", name.c_str());
+		error("Could not open sound - %s", name.toString().c_str());
 
 	playSound(f);
 }
 #endif
 
 #ifdef ENABLE_XEEN
-void Sound::playVoice(const Common::String &name, int ccMode) {
+void Sound::playVoice(const Common::Path &name, int ccMode) {
 #else
-void Sound::playVoice(const Common::String &name) {
+void Sound::playVoice(const Common::Path &name) {
 #endif
 	stopSound();
 	if (!_fxOn)
@@ -96,7 +96,7 @@ void Sound::playVoice(const Common::String &name) {
 #endif
 
 	if (!result)
-		error("Could not open sound - %s", name.c_str());
+		error("Could not open sound - %s", name.toString().c_str());
 	Common::SeekableReadStream *srcStream = f.readStream(f.size());
 	Audio::SeekableAudioStream *stream = Audio::makeVOCStream(srcStream,
 		Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
@@ -208,7 +208,7 @@ void Sound::playSong(Common::SeekableReadStream &stream) {
 	_SoundDriver->playSong(_songData);
 }
 
-void Sound::playSong(const Common::String &name, int param) {
+void Sound::playSong(const Common::Path &name, int param) {
 	if (isMusicPlaying() && name == _currentMusic)
 		return;
 	_currentMusic = name;
diff --git a/engines/mm/shared/xeen/sound.h b/engines/mm/shared/xeen/sound.h
index 7543fc12cab..bf169d5984a 100644
--- a/engines/mm/shared/xeen/sound.h
+++ b/engines/mm/shared/xeen/sound.h
@@ -59,7 +59,7 @@ private:
 public:
 	bool _fxOn;
 	bool _musicOn;
-	Common::String _currentMusic;
+	Common::Path _currentMusic;
 	int _musicSide;
 	bool _subtitles;
 public:
@@ -101,7 +101,7 @@ public:
 	/**
 	 * Plays a song
 	 */
-	void playSong(const Common::String &name, int param = 0);
+	void playSong(const Common::Path &name, int param = 0);
 
 	/**
 	 * Returns true if music is playing
@@ -136,12 +136,12 @@ public:
 	/**
 	 * Play a given sound
 	 */
-	void playSound(const Common::String &name, int unused = 0);
+	void playSound(const Common::Path &name, int unused = 0);
 #ifdef ENABLE_XEEN
 	/**
 	 * Play a given sound
 	 */
-	void playSound(const Common::String &name, int ccNum, int unused);
+	void playSound(const Common::Path &name, int ccNum, int unused);
 #endif
 	/**
 	 * Stop playing a sound loaded from a .m file
@@ -159,9 +159,9 @@ public:
 	 * Play a given voice file
 	 */
 #ifdef ENABLE_XEEN
-	void playVoice(const Common::String &name, int ccMode = -1);
+	void playVoice(const Common::Path &name, int ccMode = -1);
 #else
-	void playVoice(const Common::String &name);
+	void playVoice(const Common::Path &name);
 #endif
 };
 
diff --git a/engines/mm/shared/xeen/sprites.cpp b/engines/mm/shared/xeen/sprites.cpp
index 859818ddb66..ce719e522ab 100644
--- a/engines/mm/shared/xeen/sprites.cpp
+++ b/engines/mm/shared/xeen/sprites.cpp
@@ -45,7 +45,7 @@ SpriteResource::SpriteResource() {
 	_data = nullptr;
 }
 
-SpriteResource::SpriteResource(const Common::String &filename) {
+SpriteResource::SpriteResource(const Common::Path &filename) {
 	_data = nullptr;
 	load(filename);
 }
@@ -77,7 +77,7 @@ SpriteResource &SpriteResource::operator=(const SpriteResource &src) {
 	return *this;
 }
 
-void SpriteResource::load(const Common::String &filename) {
+void SpriteResource::load(const Common::Path &filename) {
 	_filename = filename;
 	Common::File f;
 	if (g_engine->getGameID() == GType_MightAndMagic1 && f.open(filename)) {
diff --git a/engines/mm/shared/xeen/sprites.h b/engines/mm/shared/xeen/sprites.h
index 5a5c6624f33..4697900e300 100644
--- a/engines/mm/shared/xeen/sprites.h
+++ b/engines/mm/shared/xeen/sprites.h
@@ -57,7 +57,7 @@ protected:
 	Common::Array<IndexEntry> _index;
 	size_t _filesize;
 	byte *_data;
-	Common::String _filename;
+	Common::Path _filename;
 	static int _clippedBottom;
 
 	/**
@@ -77,7 +77,7 @@ protected:
 	void copy(const SpriteResource &src);
 public:
 	SpriteResource();
-	SpriteResource(const Common::String &filename);
+	SpriteResource(const Common::Path &filename);
 	SpriteResource(const SpriteResource &src);
 
 	virtual ~SpriteResource();
@@ -90,7 +90,7 @@ public:
 	/**
 	 * Load a sprite resource from a given file
 	 */
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	/**
 	 * Clears the sprite resource
diff --git a/engines/mm/xeen/combat.cpp b/engines/mm/xeen/combat.cpp
index 13890b36363..96d0fa425d3 100644
--- a/engines/mm/xeen/combat.cpp
+++ b/engines/mm/xeen/combat.cpp
@@ -587,7 +587,7 @@ void Combat::monstersAttack() {
 		}
 	}
 
-	_powSprites.load(Common::String::format("pow%d.icn", (int)powNum));
+	_powSprites.load(Common::Path(Common::String::format("pow%d.icn", (int)powNum)));
 	sound.playFX(ATTACK_TYPE_FX[monsterData->_attackType]);
 
 	for (int charNum = 0; charNum < MAX_PARTY_COUNT; ++charNum) {
@@ -839,7 +839,7 @@ void Combat::doMonsterTurn(int monsterId) {
 		intf.draw3d(true);
 		intf.draw3d(true);
 
-		sound.playSound(Common::String::format("%s.voc", monsterData._attackVoc.c_str()));
+		sound.playSound(Common::Path(Common::String::format("%s.voc", monsterData._attackVoc.c_str())));
 		monsterId = monster._spriteId;
 	}
 
@@ -1483,7 +1483,7 @@ void Combat::attack2(int damage, RangeType rangeType) {
 
 			sound.stopSound();
 			int powNum = (_attackWeaponId > XEEN_SLAYER_SWORD) ? 0 : POW_WEAPON_VOCS[_attackWeaponId];
-			File powVoc(Common::String::format("pow%d.voc", powNum));
+			File powVoc(Common::Path(Common::String::format("pow%d.voc", powNum)));
 			sound.playFX(60 + powNum);
 			sound.playSound(powVoc, 1);
 
@@ -1870,7 +1870,7 @@ void Combat::rangedAttack(PowType powNum) {
 	}
 
 	intf._charsShooting = true;
-	_powSprites.load(Common::String::format("pow%d.icn", (int)powNum));
+	_powSprites.load(Common::Path(Common::String::format("pow%d.icn", (int)powNum)));
 	int attackDurationCtr = _attackDurationCtr;
 	int monster2Attack = _monster2Attack;
 	bool attackedFlag = false;
diff --git a/engines/mm/xeen/dialogs/dialogs.cpp b/engines/mm/xeen/dialogs/dialogs.cpp
index 9bb9a710667..b246ba8d256 100644
--- a/engines/mm/xeen/dialogs/dialogs.cpp
+++ b/engines/mm/xeen/dialogs/dialogs.cpp
@@ -169,7 +169,7 @@ bool ButtonContainer::doScroll(bool rollUp, bool fadeIn) {
 	}
 }
 
-void ButtonContainer::loadStrings(const Common::String &name) {
+void ButtonContainer::loadStrings(const Common::Path &name) {
 	File f(name);
 	_textStrings.clear();
 	while (f.pos() < f.size())
@@ -177,7 +177,7 @@ void ButtonContainer::loadStrings(const Common::String &name) {
 	f.close();
 }
 
-void ButtonContainer::loadStrings(const Common::String &name, int ccMode) {
+void ButtonContainer::loadStrings(const Common::Path &name, int ccMode) {
 	File f(name, ccMode);
 	_textStrings.clear();
 	while (f.pos() < f.size())
diff --git a/engines/mm/xeen/dialogs/dialogs.h b/engines/mm/xeen/dialogs/dialogs.h
index c9095827826..d9ab5aa2fe2 100644
--- a/engines/mm/xeen/dialogs/dialogs.h
+++ b/engines/mm/xeen/dialogs/dialogs.h
@@ -94,14 +94,14 @@ protected:
 	 * Load a set of text strings from the given resource
 	 * @param name		Name of resource containing strings
 	 */
-	void loadStrings(const Common::String &name);
+	void loadStrings(const Common::Path &name);
 
 	/**
 	 * Load a set of text strings from the given resource
 	 * @param name		Name of resource containing strings
 	 * @param ccMode	Optional cc file number to explicitly use
 	 */
-	void loadStrings(const Common::String &name, int ccMode);
+	void loadStrings(const Common::Path &name, int ccMode);
 
 	/**
 	 * Sets the wait bounds, the area where clicking with the mouse generates
diff --git a/engines/mm/xeen/dialogs/dialogs_input.cpp b/engines/mm/xeen/dialogs/dialogs_input.cpp
index fbdd4f62767..13e3c9956d9 100644
--- a/engines/mm/xeen/dialogs/dialogs_input.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_input.cpp
@@ -244,14 +244,14 @@ int StringInput::execute(bool type, const Common::String &expected,
 			MirrorEntry me;
 			scripts._mirror.clear();
 
-			File f(Common::String::format("%smirr.txt", files._ccNum ? "dark" : "xeen"), 1);
+			File f(Common::Path(Common::String::format("%smirr.txt", files._ccNum ? "dark" : "xeen")), 1);
 			while (me.synchronize(f))
 				scripts._mirror.push_back(me);
 			f.close();
 
 			// Load in any extended mirror entries
 			Common::File f2;
-			if (f2.open(Common::String::format("%smirr.ext", files._ccNum ? "dark" : "xeen"))) {
+			if (f2.open(Common::Path(Common::String::format("%smirr.ext", files._ccNum ? "dark" : "xeen")))) {
 				while (me.synchronize(f2))
 					scripts._mirror.push_back(me);
 				f2.close();
diff --git a/engines/mm/xeen/dialogs/dialogs_items.cpp b/engines/mm/xeen/dialogs/dialogs_items.cpp
index ca8238dd966..615903b4e4d 100644
--- a/engines/mm/xeen/dialogs/dialogs_items.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_items.cpp
@@ -470,7 +470,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
 
 void ItemsDialog::loadButtons(ItemsMode mode, Character *&c, ItemCategory category) {
 	if (_iconSprites.empty())
-		_iconSprites.load(Common::String::format("%s.icn", (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy"));
+		_iconSprites.load(Common::Path(Common::String::format("%s.icn", (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy")));
 	if (_equipSprites.empty())
 		_equipSprites.load("equip.icn");
 
diff --git a/engines/mm/xeen/dialogs/dialogs_spells.cpp b/engines/mm/xeen/dialogs/dialogs_spells.cpp
index 4e0e9efb244..d224b449805 100644
--- a/engines/mm/xeen/dialogs/dialogs_spells.cpp
+++ b/engines/mm/xeen/dialogs/dialogs_spells.cpp
@@ -913,7 +913,7 @@ int TownPortal::execute() {
 	if (_vm->getGameID() == GType_Swords) {
 		// Build up a lsit of the names of the towns on the current side of Xeen
 		for (int idx = 0; idx < 3; ++idx) {
-			Common::String txtName = Common::String::format("%s%04d.txt", "dark", Res.TOWN_MAP_NUMBERS[2][idx]);
+			Common::Path txtName(Common::String::format("%s%04d.txt", "dark", Res.TOWN_MAP_NUMBERS[2][idx]));
 			File f(txtName, 1);
 			townNames[idx] = f.readString();
 			f.close();
@@ -924,8 +924,8 @@ int TownPortal::execute() {
 	} else {
 		// Build up a lsit of the names of the towns on the current side of Xeen
 		for (int idx = 0; idx < 5; ++idx) {
-			Common::String txtName = Common::String::format("%s%04d.txt", map._sideTownPortal ? "dark" : "xeen",
-				Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]);
+			Common::Path txtName(Common::String::format("%s%04d.txt", map._sideTownPortal ? "dark" : "xeen",
+				Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]));
 			File f(txtName, 1);
 			townNames[idx] = f.readString();
 			f.close();
diff --git a/engines/mm/xeen/files.cpp b/engines/mm/xeen/files.cpp
index 607ad8c607e..3f753870965 100644
--- a/engines/mm/xeen/files.cpp
+++ b/engines/mm/xeen/files.cpp
@@ -108,11 +108,9 @@ SaveArchive::~SaveArchive() {
 }
 
 Common::SeekableReadStream *SaveArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-
 	// If the given resource has already been perviously "written" to the
 	// save manager, then return that new resource
-	uint16 id = BaseCCArchive::convertNameToId(name);
+	uint16 id = BaseCCArchive::convertNameToId(path);
 	return createReadStreamForMember(id);
 }
 
@@ -168,7 +166,7 @@ void SaveArchive::reset(CCArchive *src) {
 	g_vm->_files->setGameCc(g_vm->getGameID() == GType_DarkSide ? 1 : 0);
 	const int RESOURCES[6] = { 0x2A0C, 0x2A1C, 0x2A2C, 0x2A3C, 0x284C, 0x2A5C };
 	for (int i = 0; i < 6; ++i) {
-		Common::String filename = Common::String::format("%.4x", RESOURCES[i]);
+		Common::Path filename(Common::String::format("%.4x", RESOURCES[i]));
 		if (src->hasFile(filename)) {
 			// Read in the next resource
 			fIn.open(filename, *src);
@@ -178,7 +176,7 @@ void SaveArchive::reset(CCArchive *src) {
 
 			if (fIn.read(data, size) != size) {
 				delete[] data;
-				error("Failed to read %zu bytes from resource '%s' in save archive", size, filename.c_str());
+				error("Failed to read %zu bytes from resource '%s' in save archive", size, filename.toString().c_str());
 			}
 
 			// Copy it to the combined savefile resource
@@ -262,17 +260,17 @@ void SaveArchive::replaceEntry(uint16 id, const byte *data, size_t size) {
 
 /*------------------------------------------------------------------------*/
 
-OutFile::OutFile(const Common::String &filename) :
+OutFile::OutFile(const Common::Path &filename) :
 		_filename(filename), _backingStream(DisposeAfterUse::YES) {
 	FileManager &files = *g_vm->_files;
 	_archive = files._currentSave;
 }
 
-OutFile::OutFile(const Common::String &filename, SaveArchive *archive) :
+OutFile::OutFile(const Common::Path &filename, SaveArchive *archive) :
 	_filename(filename), _archive(archive), _backingStream(DisposeAfterUse::YES) {
 }
 
-OutFile::OutFile(const Common::String &filename, int ccMode) :
+OutFile::OutFile(const Common::Path &filename, int ccMode) :
 		_filename(filename), _backingStream(DisposeAfterUse::YES) {
 	FileManager &files = *g_vm->_files;
 	g_vm->_files->setGameCc(ccMode);
diff --git a/engines/mm/xeen/files.h b/engines/mm/xeen/files.h
index f8a8c872d55..909aa7b5256 100644
--- a/engines/mm/xeen/files.h
+++ b/engines/mm/xeen/files.h
@@ -200,12 +200,12 @@ public:
 class OutFile : public Common::WriteStream {
 private:
 	SaveArchive *_archive;
-	Common::String _filename;
+	Common::Path _filename;
 	Common::MemoryWriteStreamDynamic _backingStream;
 public:
-	OutFile(const Common::String &filename);
-	OutFile(const Common::String &filename, SaveArchive *archive);
-	OutFile(const Common::String &filename, int ccMode);
+	OutFile(const Common::Path &filename);
+	OutFile(const Common::Path &filename, SaveArchive *archive);
+	OutFile(const Common::Path &filename, int ccMode);
 
 	/**
 	 * Finishes any pending writes, pushing out the written data
diff --git a/engines/mm/xeen/locations.cpp b/engines/mm/xeen/locations.cpp
index 311ab706587..3e4d76dba13 100644
--- a/engines/mm/xeen/locations.cpp
+++ b/engines/mm/xeen/locations.cpp
@@ -71,8 +71,8 @@ int BaseLocation::show() {
 
 	// Load the needed sprite sets for the location
 	for (uint idx = 0; idx < _townSprites.size(); ++idx) {
-		Common::String shapesName = Common::String::format("%s%d.twn",
-			Res.TOWN_ACTION_SHAPES[_locationActionId], idx + 1);
+		Common::Path shapesName(Common::String::format("%s%d.twn",
+			Res.TOWN_ACTION_SHAPES[_locationActionId], idx + 1));
 		_townSprites[idx].load(shapesName);
 	}
 
@@ -1084,7 +1084,7 @@ Character *TrainingLocation::doOptions(Character *c) {
 			sound.stopSound();
 			_drawFrameIndex = 0;
 
-			Common::String name;
+			Common::Path name;
 			if (c->_level._permanent >= maxLevel()) {
 				name = _ccNum ? "gtlost.voc" : "trainin1.voc";
 			} else {
@@ -2373,7 +2373,7 @@ bool LocationMessage::execute(int portrait, const Common::String &name, const Co
 		loadButtons();
 
 	_townSprites.resize(2);
-	_townSprites[0].load(Common::String::format("face%02d.fac", portrait));
+	_townSprites[0].load(Common::Path(Common::String::format("face%02d.fac", portrait)));
 	_townSprites[1].load("frame.fac");
 
 	if (!w._enabled)
diff --git a/engines/mm/xeen/locations.h b/engines/mm/xeen/locations.h
index 8edfbae9702..5ab0cd290af 100644
--- a/engines/mm/xeen/locations.h
+++ b/engines/mm/xeen/locations.h
@@ -49,7 +49,7 @@ protected:
 	int _townMaxId;
 	const int &_ccNum;
 	int _animFrame;
-	Common::String _vocName, _songName;
+	Common::Path _vocName, _songName;
 	Common::Point _animPos;
 	int _drawFrameIndex;
 	uint _farewellTime;
diff --git a/engines/mm/xeen/map.cpp b/engines/mm/xeen/map.cpp
index b233ff565ee..f32185fe424 100644
--- a/engines/mm/xeen/map.cpp
+++ b/engines/mm/xeen/map.cpp
@@ -141,7 +141,7 @@ void MonsterStruct::synchronize(Common::SeekableReadStream &s) {
 MonsterData::MonsterData() {
 }
 
-void MonsterData::load(const Common::String &name) {
+void MonsterData::load(const Common::Path &name) {
 	File f(name);
 	synchronize(f);
 }
@@ -577,7 +577,7 @@ void MonsterObjectData::addMonsterSprites(MazeMonster &monster) {
 	}
 	if (idx == _monsterSprites.size()) {
 		_monsterSprites.push_back(SpriteResourceEntry(monster._spriteId));
-		_monsterSprites.back()._sprites.load(Common::String::format("%03u.mon", imgNumber));
+		_monsterSprites.back()._sprites.load(Common::Path(Common::String::format("%03u.mon", imgNumber)));
 		monster._sprites = &_monsterSprites.back()._sprites;
 	}
 
@@ -590,7 +590,7 @@ void MonsterObjectData::addMonsterSprites(MazeMonster &monster) {
 	}
 	if (idx == _monsterAttackSprites.size()) {
 		_monsterAttackSprites.push_back(SpriteResourceEntry(monster._spriteId));
-		_monsterAttackSprites.back()._sprites.load(Common::String::format("%03u.att", imgNumber));
+		_monsterAttackSprites.back()._sprites.load(Common::Path(Common::String::format("%03u.att", imgNumber)));
 		monster._attackSprites = &_monsterAttackSprites.back()._sprites;
 	}
 }
@@ -635,7 +635,7 @@ void AnimationInfo::synchronize(Common::SeekableReadStream &s) {
 	}
 }
 
-void AnimationInfo::load(const Common::String &name) {
+void AnimationInfo::load(const Common::Path &name) {
 	File f(name);
 	synchronize(f);
 	f.close();
@@ -768,8 +768,8 @@ void Map::load(int mapId) {
 			mazeDataP->clear();
 		} else {
 			// Load in the maze's data file
-			Common::String datName = Common::String::format("maze%c%03d.dat",
-				(mapId >= 100) ? 'x' : '0', mapId);
+			Common::Path datName(Common::String::format("maze%c%03d.dat",
+				(mapId >= 100) ? 'x' : '0', mapId));
 			File datFile(datName);
 			XeenSerializer datSer(&datFile, nullptr);
 			mazeDataP->synchronize(datSer);
@@ -784,7 +784,7 @@ void Map::load(int mapId) {
 
 			_isOutdoors = (mazeDataP->_mazeFlags2 & FLAG_IS_OUTDOORS) != 0;
 
-			Common::String mobName = Common::String::format("maze%c%03d.mob", (mapId >= 100) ? 'x' : '0', mapId);
+			Common::Path mobName(Common::String::format("maze%c%03d.mob", (mapId >= 100) ? 'x' : '0', mapId));
 
 			if (!mapDataLoaded) {
 				// Called once for the main map being loaded
@@ -797,8 +797,8 @@ void Map::load(int mapId) {
 				_mobData.synchronize(sMob, _monsterData);
 				mobFile.close();
 
-				Common::String headName = Common::String::format("aaze%c%03d.hed",
-					(mapId >= 100) ? 'x' : '0', mapId);
+				Common::Path headName(Common::String::format("aaze%c%03d.hed",
+					(mapId >= 100) ? 'x' : '0', mapId));
 				File headFile(headName);
 				_headData.synchronize(headFile);
 				headFile.close();
@@ -843,8 +843,8 @@ void Map::load(int mapId) {
 
 	// Reload the monster data for the main maze that we're loading
 	mapId = party._mazeId;
-	Common::String filename = Common::String::format("maze%c%03d.mob",
-		(mapId >= 100) ? 'x' : '0', mapId);
+	Common::Path filename(Common::String::format("maze%c%03d.mob",
+		(mapId >= 100) ? 'x' : '0', mapId));
 	File mobFile(filename);
 	XeenSerializer sMob(&mobFile, nullptr);
 	_mobData.synchronize(sMob, _monsterData);
@@ -864,9 +864,9 @@ void Map::load(int mapId) {
 			filename = "085.obj";
 			_mobData._objectSprites[0]._spriteId = 85;
 		} else {
-			filename = Common::String::format("%03d.%cbj",
+			filename = Common::Path(Common::String::format("%03d.%cbj",
 				_mobData._objectSprites[i]._spriteId,
-				_mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o');
+				_mobData._objectSprites[i]._spriteId >= 100 ? '0' : 'o'));
 		}
 
 		// Read in the object sprites
@@ -881,16 +881,16 @@ void Map::load(int mapId) {
 
 		files.setGameCc((spr._spriteId == 91 && _vm->getGameID() == GType_WorldOfXeen) ?
 			0 : _sideMonsters);
-		filename = Common::String::format("%03u.mon", imgNumber);
+		filename = Common::Path(Common::String::format("%03u.mon", imgNumber));
 		_mobData._monsterSprites[i]._sprites.load(filename);
 
-		filename = Common::String::format("%03u.att", imgNumber);
+		filename = Common::Path(Common::String::format("%03u.att", imgNumber));
 		_mobData._monsterSprites[i]._attackSprites.load(filename);
 	}
 
 	// Load wall picture sprite resources
 	for (uint i = 0; i < _mobData._wallItemSprites.size(); ++i) {
-		filename = Common::String::format("%03d.pic", _mobData._wallItemSprites[i]._spriteId);
+		filename = Common::Path(Common::String::format("%03d.pic", _mobData._wallItemSprites[i]._spriteId));
 		_mobData._wallItemSprites[i]._sprites.load(filename, _sidePictures);
 	}
 
@@ -900,7 +900,7 @@ void Map::load(int mapId) {
 	if (_isOutdoors) {
 		// Start playing relevant music
 		sound._musicSide = ccNum;
-		Common::String musName;
+		Common::Path musName;
 
 		if (_vm->_files->_ccNum) {
 			int randIndex = _vm->getRandomNumber(6);
@@ -921,8 +921,8 @@ void Map::load(int mapId) {
 			_wallSprites._surfaces[i].clear();
 
 			if (_mazeData[0]._wallTypes[i] != 0) {
-				_wallSprites._surfaces[i].load(Common::String::format("%s.wal",
-					Res.OUTDOORS_WALL_TYPES[_mazeData[0]._wallTypes[i]]));
+				_wallSprites._surfaces[i].load(Common::Path(Common::String::format("%s.wal",
+					Res.OUTDOORS_WALL_TYPES[_mazeData[0]._wallTypes[i]])));
 			}
 
 			_surfaceSprites[i].clear();
@@ -936,7 +936,7 @@ void Map::load(int mapId) {
 
 		// Start playing relevant music
 		const int MUS_INDEXES[] = { 1, 2, 3, 4, 3, 5 };
-		Common::String musName;
+		Common::Path musName;
 
 		if (files._ccNum) {
 			int randIndex = _vm->getRandomNumber(6);
@@ -947,12 +947,12 @@ void Map::load(int mapId) {
 		sound.playSong(musName, 207);
 
 		// Load sprite sets needed for scene rendering
-		_skySprites[1].load(Common::String::format("%s.sky",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]));
-		_groundSprites.load(Common::String::format("%s.gnd",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]));
-		_tileSprites.load(Common::String::format("%s.til",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]));
+		_skySprites[1].load(Common::Path(Common::String::format("%s.sky",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind])));
+		_groundSprites.load(Common::Path(Common::String::format("%s.gnd",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind])));
+		_tileSprites.load(Common::Path(Common::String::format("%s.til",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind])));
 
 		for (int i = 0; i < TOTAL_SURFACES; ++i) {
 			_surfaceSprites[i].clear();
@@ -964,16 +964,16 @@ void Map::load(int mapId) {
 		for (int i = 0; i < TOTAL_SURFACES; ++i)
 			_wallSprites._surfaces[i].clear();
 
-		_wallSprites._fwl1.load(Common::String::format("f%s1.fwl",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures);
-		_wallSprites._fwl2.load(Common::String::format("f%s2.fwl",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures);
-		_wallSprites._fwl3.load(Common::String::format("f%s3.fwl",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures);
-		_wallSprites._fwl4.load(Common::String::format("f%s4.fwl",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures);
-		_wallSprites._swl.load(Common::String::format("s%s.swl",
-			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures);
+		_wallSprites._fwl1.load(Common::Path(Common::String::format("f%s1.fwl",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures));
+		_wallSprites._fwl2.load(Common::Path(Common::String::format("f%s2.fwl",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures));
+		_wallSprites._fwl3.load(Common::Path(Common::String::format("f%s3.fwl",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures));
+		_wallSprites._fwl4.load(Common::Path(Common::String::format("f%s4.fwl",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures));
+		_wallSprites._swl.load(Common::Path(Common::String::format("s%s.swl",
+			Res.TERRAIN_TYPES[_mazeData[0]._wallKind]), _sidePictures));
 
 		// Set entries in the indoor draw list to the correct sprites
 		// for drawing various parts of the background
@@ -1128,16 +1128,16 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) {
 
 void Map::loadEvents(int mapId, int ccNum) {
 	// Load events
-	Common::String filename = Common::String::format("maze%c%03d.evt",
-		(mapId >= 100) ? 'x' : '0', mapId);
+	Common::Path filename(Common::String::format("maze%c%03d.evt",
+		(mapId >= 100) ? 'x' : '0', mapId));
 	File fEvents(filename, ccNum);
 	XeenSerializer sEvents(&fEvents, nullptr);
 	_events.synchronize(sEvents);
 	fEvents.close();
 
 	// Load text data
-	filename = Common::String::format("aaze%c%03d.txt",
-		(mapId >= 100) ? 'x' : '0', mapId);
+	filename = Common::Path(Common::String::format("aaze%c%03d.txt",
+		(mapId >= 100) ? 'x' : '0', mapId));
 	File fText(filename, ccNum);
 	_events._text.clear();
 	while (fText.pos() < fText.size())
@@ -1148,8 +1148,8 @@ void Map::loadEvents(int mapId, int ccNum) {
 void Map::saveEvents() {
 	// Save eents
 	int mapId = _mazeData[0]._mazeId;
-	Common::String filename = Common::String::format("maze%c%03d.evt",
-		(mapId >= 100) ? 'x' : '0', mapId);
+	Common::Path filename(Common::String::format("maze%c%03d.evt",
+		(mapId >= 100) ? 'x' : '0', mapId));
 	OutFile fEvents(filename);
 	XeenSerializer sEvents(nullptr, &fEvents);
 	_events.synchronize(sEvents);
@@ -1164,7 +1164,7 @@ void Map::saveMap() {
 		return;
 
 	// Save the primary maze
-	Common::String datName = Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId);
+	Common::Path datName(Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId));
 	OutFile datFile(datName);
 	XeenSerializer datSer(nullptr, &datFile);
 	_mazeData[0].synchronize(datSer);
@@ -1187,7 +1187,7 @@ void Map::saveMap() {
 			if (mapId == 0)
 				continue;
 
-			datName = Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId);
+			datName = Common::Path(Common::String::format("maze%c%03d.dat", (mapId >= 100) ? 'x' : '0', mapId));
 			OutFile datFile2(datName);
 			XeenSerializer datSer2(nullptr, &datFile2);
 			_mazeData[mazeIndex].synchronize(datSer2);
@@ -1198,8 +1198,8 @@ void Map::saveMap() {
 
 void Map::saveMonsters() {
 	int mapId = _mazeData[0]._mazeId;
-	Common::String filename = Common::String::format("maze%c%03d.mob",
-		(mapId >= 100) ? 'x' : '0', mapId);
+	Common::Path filename(Common::String::format("maze%c%03d.mob",
+		(mapId >= 100) ? 'x' : '0', mapId));
 	OutFile fMob(filename);
 	XeenSerializer sMob(nullptr, &fMob);
 	_mobData.synchronize(sMob, _monsterData);
@@ -1465,8 +1465,8 @@ Common::String Map::getMazeName(int mapId, int ccNum) {
 		} else
 			return Res._cloudsMapNames[mapId];
 	} else {
-		Common::String txtName = Common::String::format("%s%c%03d.txt",
-			ccNum ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId);
+		Common::Path txtName(Common::String::format("%s%c%03d.txt",
+			ccNum ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId));
 		File fText(txtName, 1);
 		char mazeName[33];
 		fText.read(mazeName, 33);
diff --git a/engines/mm/xeen/map.h b/engines/mm/xeen/map.h
index bd9c9768c2b..436529b288e 100644
--- a/engines/mm/xeen/map.h
+++ b/engines/mm/xeen/map.h
@@ -105,7 +105,7 @@ private:
 public:
 	MonsterData();
 
-	void load(const Common::String &name);
+	void load(const Common::Path &name);
 };
 
 class SurroundingMazes {
@@ -416,7 +416,7 @@ public:
 	/**
 	 * Load the animation info objects in the game
 	 */
-	void load(const Common::String &name);
+	void load(const Common::Path &name);
 };
 
 class Map {
diff --git a/engines/mm/xeen/party.cpp b/engines/mm/xeen/party.cpp
index f9f2aac9a7c..bcdda2305ea 100644
--- a/engines/mm/xeen/party.cpp
+++ b/engines/mm/xeen/party.cpp
@@ -44,7 +44,7 @@ Roster::Roster() {
 
 		if (idx < XEEN_TOTAL_CHARACTERS) {
 			// Load new character resource
-			Common::String name = Common::String::format("char%02d.fac", idx + 1);
+			Common::Path name(Common::String::format("char%02d.fac", idx + 1));
 			_charFaces[idx].load(name);
 			operator[](idx)._faceSprites = &_charFaces[idx];
 		} else {
diff --git a/engines/mm/xeen/resources.h b/engines/mm/xeen/resources.h
index 745cb096a59..980b055970d 100644
--- a/engines/mm/xeen/resources.h
+++ b/engines/mm/xeen/resources.h
@@ -49,7 +49,7 @@ class Resources {
 		char *_buffStart;
 	public:
 		ResFile(const char *type, char *buffer, int num) :
-			File(Common::String::format("%s%i", type, num)),
+			File(Common::Path(Common::String::format("%s%i", type, num))),
 			_buffer(buffer), _buffStart(buffer) {
 		}
 
diff --git a/engines/mm/xeen/screen.cpp b/engines/mm/xeen/screen.cpp
index 541905219f8..945b92991fd 100644
--- a/engines/mm/xeen/screen.cpp
+++ b/engines/mm/xeen/screen.cpp
@@ -37,13 +37,13 @@ Screen::Screen(XeenEngine *vm) : _vm(vm) {
 	Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0);
 }
 
-void Screen::loadPalette(const Common::String &name) {
+void Screen::loadPalette(const Common::Path &name) {
 	File f(name);
 	for (int i = 0; i < PALETTE_SIZE; ++i)
 		_tempPalette[i] = f.readByte() << 2;
 }
 
-void Screen::loadBackground(const Common::String &name) {
+void Screen::loadBackground(const Common::Path &name) {
 	File f(name);
 
 	assert(f.size() == (SCREEN_WIDTH * SCREEN_HEIGHT));
@@ -180,14 +180,14 @@ bool Screen::doScroll(bool rollUp, bool fadeInFlag) {
 	// Load hand sprites
 	SpriteResource *hand[16];
 	for (int i = 0; i < 16; ++i) {
-		Common::String name = Common::String::format("hand%02d.vga", i);
+		Common::Path name(Common::String::format("hand%02d.vga", i));
 		hand[i] = new SpriteResource(name);
 	}
 
 	// Load marb sprites
 	SpriteResource *marb[5];
 	for (int i = 0; i < 4; ++i) {
-		Common::String name = Common::String::format("marb%02d.vga", i + 1);
+		Common::Path name(Common::String::format("marb%02d.vga", i + 1));
 		marb[i] = new SpriteResource(name);
 	}
 
diff --git a/engines/mm/xeen/screen.h b/engines/mm/xeen/screen.h
index fb34e83c2ce..e3750340fcd 100644
--- a/engines/mm/xeen/screen.h
+++ b/engines/mm/xeen/screen.h
@@ -72,12 +72,12 @@ public:
 	/**
 	 * Load a palette resource into the temporary palette
 	 */
-	void loadPalette(const Common::String &name);
+	void loadPalette(const Common::Path &name);
 
 	/**
 	 * Load a background resource into memory
 	 */
-	void loadBackground(const Common::String &name);
+	void loadBackground(const Common::Path &name);
 
 	/**
 	 * Copy a loaded background into a display page
diff --git a/engines/mm/xeen/scripts.cpp b/engines/mm/xeen/scripts.cpp
index 37608456c32..a1054bd94a7 100644
--- a/engines/mm/xeen/scripts.cpp
+++ b/engines/mm/xeen/scripts.cpp
@@ -1381,7 +1381,7 @@ bool Scripts::cmdDisplayBottomTwoLines(ParamsIterator &params) {
 
 bool Scripts::cmdDisplayLarge(ParamsIterator &params) {
 	Party &party = *g_vm->_party;
-	Common::String filename = Common::String::format("aaze2%03u.txt", party._mazeId);
+	Common::Path filename(Common::String::format("aaze2%03u.txt", party._mazeId));
 	uint lineNumber = params.readByte();
 
 	// Get the text data for the current maze
diff --git a/engines/mm/xeen/sprites.cpp b/engines/mm/xeen/sprites.cpp
index 8d92648fc73..a1789b6a3c2 100644
--- a/engines/mm/xeen/sprites.cpp
+++ b/engines/mm/xeen/sprites.cpp
@@ -25,12 +25,12 @@
 namespace MM {
 namespace Xeen {
 
-SpriteResource::SpriteResource(const Common::String &filename, int ccMode) {
+SpriteResource::SpriteResource(const Common::Path &filename, int ccMode) {
 	_data = nullptr;
 	load(filename, ccMode);
 }
 
-void SpriteResource::load(const Common::String &filename, int ccMode) {
+void SpriteResource::load(const Common::Path &filename, int ccMode) {
 	_filename = filename;
 	File f(filename, ccMode);
 	Shared::Xeen::SpriteResource::load(f);
diff --git a/engines/mm/xeen/sprites.h b/engines/mm/xeen/sprites.h
index 40cf8c88433..4fc0aeb7034 100644
--- a/engines/mm/xeen/sprites.h
+++ b/engines/mm/xeen/sprites.h
@@ -40,21 +40,21 @@ private:
 
 public:
 	SpriteResource() : Shared::Xeen::SpriteResource() {}
-	SpriteResource(const Common::String &filename) :
+	SpriteResource(const Common::Path &filename) :
 		Shared::Xeen::SpriteResource(filename) {}
-	SpriteResource(const Common::String &filename, int ccMode);
+	SpriteResource(const Common::Path &filename, int ccMode);
 
 	/**
 	 * Load a sprite resource from a given file
 	 */
-	void load(const Common::String &filename) {
+	void load(const Common::Path &filename) {
 		Shared::Xeen::SpriteResource::load(filename);
 	}
 
 	/**
 	 * Load a sprite resource from a given file and archive
 	 */
-	void load(const Common::String &filename, int ccMode);
+	void load(const Common::Path &filename, int ccMode);
 
 	/**
 	 * Draw a sprite onto a surface
diff --git a/engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp b/engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
index d610ffb9c33..e93ad8e4e2b 100644
--- a/engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
+++ b/engines/mm/xeen/worldofxeen/clouds_cutscenes.cpp
@@ -29,7 +29,7 @@ namespace WorldOfXeen {
 #define WAIT(TIME) if (_subtitles.wait(TIME)) return false
 #define ROTATE_BG screen.horizMerge(_mergeX); \
 	_mergeX = (_mergeX + 1) % SCREEN_WIDTH
-#define LOAD_VORTEX loadScreen(Common::String::format("vort%02u.frm", cloudsCtr)); \
+#define LOAD_VORTEX loadScreen(Common::Path(Common::String::format("vort%02u.frm", cloudsCtr))); \
 	if (++cloudsCtr > 20) \
 		cloudsCtr = 1
 
@@ -420,7 +420,7 @@ bool CloudsCutscenes::showCloudsEnding1() {
 	screen.loadBackground("blank.raw");
 	screen.loadPalette("mm4e.pal");
 
-	loadScreen(Common::String::format("prec00%02u.frm", 1));
+	loadScreen(Common::Path(Common::String::format("prec00%02u.frm", 1)));
 	prec.draw(0, 0);
 	prec.draw(0, 1, Common::Point(160, 0));
 	screen.fadeIn();
@@ -432,7 +432,7 @@ bool CloudsCutscenes::showCloudsEnding1() {
 	// Initial animation of vortex & lightning in the sky
 	for (int idx = 1; idx < 42; ++idx) {
 		// Load up the background frame of swirling clouds
-		loadScreen(Common::String::format("prec00%02u.frm", idx));
+		loadScreen(Common::Path(Common::String::format("prec00%02u.frm", idx)));
 
 		// Render castle in front of it
 		prec.draw(0, 0, Common::Point(0, 0));
@@ -462,11 +462,11 @@ bool CloudsCutscenes::showCloudsEnding1() {
 
 	SpriteResource cast1[7], cast2[7], darkLord[3];
 	for (int idx = 1; idx < 7; ++idx)
-		cast1[idx - 1].load(Common::String::format("cast%02d.end", idx));
+		cast1[idx - 1].load(Common::Path(Common::String::format("cast%02d.end", idx)));
 	for (int idx = 1; idx < 7; ++idx)
-		cast2[idx - 1].load(Common::String::format("casb%02d.end", idx));
+		cast2[idx - 1].load(Common::Path(Common::String::format("casb%02d.end", idx)));
 	for (int idx = 1; idx < 4; ++idx)
-		darkLord[idx - 1].load(Common::String::format("darklrd%d.end", idx));
+		darkLord[idx - 1].load(Common::Path(Common::String::format("darklrd%d.end", idx)));
 
 	// Castle close-up
 	int cloudsCtr = 1;
@@ -803,8 +803,8 @@ bool CloudsCutscenes::showCloudsEnding3() {
 	// Loop through showing each monster
 	for (int monsterCtr = 0; monsterCtr < 73; ++monsterCtr) {
 		MonsterStruct &mon = map._monsterData[MONSTER_INDEXES[monsterCtr]];
-		monSprites.load(Common::String::format("%03d.mon", mon._imageNumber));
-		attackSprites.load(Common::String::format("%03d.att", mon._imageNumber));
+		monSprites.load(Common::Path(Common::String::format("%03d.mon", mon._imageNumber)));
+		attackSprites.load(Common::Path(Common::String::format("%03d.att", mon._imageNumber)));
 
 		for (int frameCtr = 0; frameCtr < 8; ++frameCtr) {
 			ROTATE_BG;
@@ -825,7 +825,7 @@ bool CloudsCutscenes::showCloudsEnding3() {
 
 		for (int frameCtr = 0; frameCtr < 3; ++frameCtr) {
 			if (frameCtr == 2)
-				sound.playVoice(Common::String::format("%s.voc", mon._attackVoc.c_str()));
+				sound.playVoice(Common::Path(Common::String::format("%s.voc", mon._attackVoc.c_str())));
 
 			ROTATE_BG;
 			counter1 = (counter1 + 1) % 8;
@@ -862,7 +862,7 @@ bool CloudsCutscenes::showCloudsEnding3() {
 
 		int powNum = getSpeakingFrame(0, 5);
 		sound.stopSound();
-		sound.playSound(Common::String::format("pow%d.voc", powNum));
+		sound.playSound(Common::Path(Common::String::format("pow%d.voc", powNum)));
 
 		for (int idx = 0; idx < 7; ++idx) {
 			ROTATE_BG;
@@ -1010,7 +1010,7 @@ bool CloudsCutscenes::showCloudsEnding5() {
 	return true;
 }
 
-void CloudsCutscenes::loadScreen(const Common::String &name) {
+void CloudsCutscenes::loadScreen(const Common::Path &name) {
 	Screen &screen = *_vm->_screen;
 	File fSrc(name);
 	byte *destP = (byte *)screen.getPixels();
diff --git a/engines/mm/xeen/worldofxeen/clouds_cutscenes.h b/engines/mm/xeen/worldofxeen/clouds_cutscenes.h
index 2c30f4091c6..a558ff5e91b 100644
--- a/engines/mm/xeen/worldofxeen/clouds_cutscenes.h
+++ b/engines/mm/xeen/worldofxeen/clouds_cutscenes.h
@@ -43,7 +43,7 @@ private:
 	SpriteResource _mirror, _mirrBack;
 	int _mergeX;
 private:
-	void loadScreen(const Common::String &name);
+	void loadScreen(const Common::Path &name);
 
 	/**
 	 * Shows the Clouds of Xeen title screen
diff --git a/engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp
index f97449915c8..1b6359e218b 100644
--- a/engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp
+++ b/engines/mm/xeen/worldofxeen/darkside_cutscenes.cpp
@@ -659,9 +659,9 @@ bool DarkSideCutscenes::showDarkSideIntro3() {
 	SpriteResource bird[11];
 	SpriteResource drop[4];
 	for (int idx = 0; idx < 11; ++idx)
-		bird[idx].load(Common::String::format("bird%02d.int", idx + 1));
+		bird[idx].load(Common::Path(Common::String::format("bird%02d.int", idx + 1)));
 	for (int idx = 0; idx < 4; ++idx)
-		drop[idx].load(Common::String::format("drop%d.int", idx + 1));
+		drop[idx].load(Common::Path(Common::String::format("drop%d.int", idx + 1)));
 
 	screen.loadPalette("fly.pal");
 	screen.loadBackground("fly.raw");
@@ -780,7 +780,7 @@ bool DarkSideCutscenes::showWorldOfXeenLogo() {
 	SpriteResource fizzle("fizzle.int");
 	SpriteResource wfire[7];
 	for (uint idx = 0; idx < 7; ++idx)
-		wfire[idx].load(Common::String::format("wfire%u.int", idx + 1));
+		wfire[idx].load(Common::Path(Common::String::format("wfire%u.int", idx + 1)));
 
 	screen.loadBackground("firemain.raw");
 	screen.loadPalette("firemain.pal");


Commit: 731798c4819d38d66ba007f289acc5fffc512811
    https://github.com/scummvm/scummvm/commit/731798c4819d38d66ba007f289acc5fffc512811
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MOHAWK: Migrate engine to Path

Changed paths:
    engines/mohawk/cstime.cpp
    engines/mohawk/cstime.h
    engines/mohawk/cstime_game.cpp
    engines/mohawk/cursors.cpp
    engines/mohawk/cursors.h
    engines/mohawk/installer_archive.cpp
    engines/mohawk/installer_archive.h
    engines/mohawk/livingbooks.cpp
    engines/mohawk/livingbooks.h
    engines/mohawk/livingbooks_lbx.cpp
    engines/mohawk/metaengine.cpp
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h
    engines/mohawk/myst_areas.cpp
    engines/mohawk/myst_areas.h
    engines/mohawk/resource.cpp
    engines/mohawk/resource.h
    engines/mohawk/riven.cpp
    engines/mohawk/video.cpp
    engines/mohawk/video.h


diff --git a/engines/mohawk/cstime.cpp b/engines/mohawk/cstime.cpp
index 4d311466e22..df327e0a137 100644
--- a/engines/mohawk/cstime.cpp
+++ b/engines/mohawk/cstime.cpp
@@ -41,7 +41,7 @@ MohawkEngine_CSTime::MohawkEngine_CSTime(OSystem *syst, const MohawkGameDescript
 	_rnd = new Common::RandomSource("cstime");
 
 	// If the user just copied the CD contents, the fonts are in a subdirectory.
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	// They're in setup/data32 for 'Where in Time is Carmen Sandiego?'.
 	SearchMan.addSubDirectoryMatching(gameDataDir, "setup/data32");
 	// They're in 95instal for 'Carmen Sandiego's Great Chase Through Time'.
@@ -238,10 +238,10 @@ void MohawkEngine_CSTime::nextScene() {
 	// TODO: maybe startMusic();
 }
 
-void MohawkEngine_CSTime::loadResourceFile(Common::String name) {
+void MohawkEngine_CSTime::loadResourceFile(const Common::Path &name) {
 	MohawkArchive *archive = new MohawkArchive();
-	if (!archive->openFile(name + ".mhk"))
-		error("failed to open %s.mhk", name.c_str());
+	if (!archive->openFile(name.append(".mhk")))
+		error("failed to open %s.mhk", name.toString().c_str());
 	_mhk.push_back(archive);
 }
 
diff --git a/engines/mohawk/cstime.h b/engines/mohawk/cstime.h
index 063c45596e5..d7e7d820e40 100644
--- a/engines/mohawk/cstime.h
+++ b/engines/mohawk/cstime.h
@@ -145,7 +145,7 @@ public:
 	CSTimeCase *getCase() { return _case; }
 	CSTimeInterface *getInterface() { return _interface; }
 
-	void loadResourceFile(Common::String name);
+	void loadResourceFile(const Common::Path &name);
 
 	void addEvent(const CSTimeEvent &event);
 	void addEventList(const Common::Array<CSTimeEvent> &list);
diff --git a/engines/mohawk/cstime_game.cpp b/engines/mohawk/cstime_game.cpp
index cb41bbcb608..10ba53ed668 100644
--- a/engines/mohawk/cstime_game.cpp
+++ b/engines/mohawk/cstime_game.cpp
@@ -650,11 +650,11 @@ void CSTimeConversation::unhighlightLine(uint line) {
 }
 
 CSTimeCase::CSTimeCase(MohawkEngine_CSTime *vm, uint id) : _vm(vm), _id(id) {
-	_vm->loadResourceFile(Common::String::format("Cases/C%dText", id));
+	_vm->loadResourceFile(Common::Path(Common::String::format("Cases/C%dText", id)));
 	// We load this early, so we can use the text for debugging.
 	loadRolloverText();
 
-	_vm->loadResourceFile(Common::String::format("Cases/C%dInfo", id));
+	_vm->loadResourceFile(Common::Path(Common::String::format("Cases/C%dInfo", id)));
 	Common::SeekableReadStream *caseInfoStream = _vm->getResource(ID_CINF, 1);
 	uint16 numScenes = caseInfoStream->readUint16BE();
 	uint16 numInvObjs = caseInfoStream->readUint16BE();
@@ -667,8 +667,8 @@ CSTimeCase::CSTimeCase(MohawkEngine_CSTime *vm, uint id) : _vm(vm), _id(id) {
 	for (uint i = 0; i < numInvObjs; i++)
 		_inventoryObjs.push_back(loadInventoryObject(i));
 
-	_vm->loadResourceFile(Common::String::format("Cases/C%dArt", id));
-	_vm->loadResourceFile(Common::String::format("Cases/C%dDlog", id));
+	_vm->loadResourceFile(Common::Path(Common::String::format("Cases/C%dArt", id)));
+	_vm->loadResourceFile(Common::Path(Common::String::format("Cases/C%dDlog", id)));
 
 	debug("Loading %d scenes...", numScenes);
 	for (uint i = 0; i < numScenes; i++)
diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp
index d37edc82ba2..16a55fb38ad 100644
--- a/engines/mohawk/cursors.cpp
+++ b/engines/mohawk/cursors.cpp
@@ -140,7 +140,7 @@ void MystCursorManager::setDefaultCursor() {
 
 #endif
 
-MacCursorManager::MacCursorManager(const Common::String &appName) {
+MacCursorManager::MacCursorManager(const Common::Path &appName) {
 	if (!appName.empty()) {
 		_resFork = new Common::MacResManager();
 
@@ -210,7 +210,7 @@ void LivingBooksCursorManager_v2::setCursor(const Common::String &name) {
 		setCursor(id);
 }
 
-NECursorManager::NECursorManager(const Common::String &appName) {
+NECursorManager::NECursorManager(const Common::Path &appName) {
 	Common::NEResources *exe = new Common::NEResources();
 	if (exe->loadFromEXE(appName)) {
 		// Not all have cursors anyway, so it's not a problem if this fails
@@ -219,7 +219,7 @@ NECursorManager::NECursorManager(const Common::String &appName) {
 	delete exe;
 }
 
-PECursorManager::PECursorManager(const Common::String &appName) {
+PECursorManager::PECursorManager(const Common::Path &appName) {
 	Common::PEResources *exe = new Common::PEResources();
 	if (exe->loadFromEXE(appName)) {
 		// Not all have cursors anyway, so it's not a problem if this fails
diff --git a/engines/mohawk/cursors.h b/engines/mohawk/cursors.h
index 929d866f61b..c3c4cfaabdb 100644
--- a/engines/mohawk/cursors.h
+++ b/engines/mohawk/cursors.h
@@ -127,7 +127,7 @@ private:
 // The cursor manager for Mac applications
 class MacCursorManager : public CursorManager {
 public:
-	explicit MacCursorManager(const Common::String &appName);
+	explicit MacCursorManager(const Common::Path &appName);
 	~MacCursorManager() override;
 
 	void setCursor(uint16 id) override;
@@ -175,13 +175,13 @@ private:
 // The cursor manager for NE EXE's
 class NECursorManager : public WinCursorManager {
 public:
-	explicit NECursorManager(const Common::String &appName);
+	explicit NECursorManager(const Common::Path &appName);
 };
 
 // The cursor manager for PE EXE's
 class PECursorManager : public WinCursorManager {
 public:
-	explicit PECursorManager(const Common::String &appName);
+	explicit PECursorManager(const Common::Path &appName);
 };
 
 } // End of namespace Mohawk
diff --git a/engines/mohawk/installer_archive.cpp b/engines/mohawk/installer_archive.cpp
index a25dac1a166..91124e2c90d 100644
--- a/engines/mohawk/installer_archive.cpp
+++ b/engines/mohawk/installer_archive.cpp
@@ -34,7 +34,7 @@ InstallerArchive::~InstallerArchive() {
 	close();
 }
 
-bool InstallerArchive::open(const Common::String &filename) {
+bool InstallerArchive::open(const Common::Path &filename) {
 	close();
 
 	_stream = SearchMan.createReadStreamForMember(filename);
@@ -92,7 +92,7 @@ bool InstallerArchive::open(const Common::String &filename) {
 
 		_stream->skip(13); // Unknown
 
-		_map[name] = entry;
+		_map[Common::Path(name, '\\')] = entry;
 
 		debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
 				entry.offset, entry.compressedSize, entry.uncompressedSize);
@@ -107,8 +107,7 @@ void InstallerArchive::close() {
 }
 
 bool InstallerArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return _map.contains(name);
+	return _map.contains(path);
 }
 
 int InstallerArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -119,16 +118,14 @@ int InstallerArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr InstallerArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *InstallerArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!_stream || !_map.contains(name))
+	if (!_stream || !_map.contains(path))
 		return nullptr;
 
-	const FileEntry &entry = _map[name];
+	const FileEntry &entry = _map[path];
 
 	// Seek to our offset and then send it off to the decompressor
 	_stream->seek(entry.offset);
diff --git a/engines/mohawk/installer_archive.h b/engines/mohawk/installer_archive.h
index d923a8c8594..b99d244a056 100644
--- a/engines/mohawk/installer_archive.h
+++ b/engines/mohawk/installer_archive.h
@@ -37,7 +37,7 @@ public:
 	InstallerArchive();
 	~InstallerArchive() override;
 
-	bool open(const Common::String &filename);
+	bool open(const Common::Path &filename);
 	void close();
 	bool isOpen() const { return _stream != nullptr; }
 
@@ -56,7 +56,7 @@ private:
 
 	Common::SeekableReadStream *_stream;
 
-	typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+	typedef Common::HashMap<Common::Path, FileEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 	FileMap _map;
 };
 
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp
index 908412045c8..cfb8dc9f77d 100644
--- a/engines/mohawk/livingbooks.cpp
+++ b/engines/mohawk/livingbooks.cpp
@@ -147,7 +147,7 @@ MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGa
 	_video = nullptr;
 	_page = nullptr;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	// Rugrats
 	SearchMan.addSubDirectoryMatching(gameDataDir, "program", 0, 2);
 	SearchMan.addSubDirectoryMatching(gameDataDir, "Rugrats Adventure Game", 0, 2);
@@ -303,10 +303,10 @@ void MohawkEngine_LivingBooks::pauseEngineIntern(bool pause) {
 	}
 }
 
-void MohawkEngine_LivingBooks::loadBookInfo(const Common::String &filename) {
+void MohawkEngine_LivingBooks::loadBookInfo(const Common::Path &filename) {
 	_bookInfoFile.allowNonEnglishCharacters();
 	if (!_bookInfoFile.loadFromFile(filename))
-		error("Could not open %s as a config file", filename.c_str());
+		error("Could not open %s as a config file", filename.toString().c_str());
 
 	_title = getStringFromConfig("BookInfo", "title");
 	_copyright = getStringFromConfig("BookInfo", "copyright");
@@ -400,7 +400,7 @@ static Common::String replaceColons(const Common::String &in, char replace) {
 // Helper function to assist in opening pages
 static bool tryOpenPage(Archive *archive, const Common::String &fileName) {
 	// Try the plain file name first
-	if (archive->openFile(fileName))
+	if (archive->openFile(Common::Path(fileName)))
 		return true;
 
 	// No colons, then bail out
@@ -409,12 +409,12 @@ static bool tryOpenPage(Archive *archive, const Common::String &fileName) {
 
 	// Try replacing colons with underscores (in case the original was
 	// a Mac version and had slashes not as a separator).
-	if (archive->openFile(replaceColons(fileName, '_')))
+	if (archive->openFile(Common::Path(replaceColons(fileName, '_'))))
 		return true;
 
 	// Try replacing colons with slashes (in case the original was a Mac
 	// version and had slashes as a separator).
-	if (archive->openFile(replaceColons(fileName, '/')))
+	if (archive->openFile(Common::Path(replaceColons(fileName, '/'))))
 		return true;
 
 	// Failed to open the archive
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 64d7d41dac0..77d4e8b9b13 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -761,8 +761,8 @@ public:
 private:
 	Common::INIFile _bookInfoFile;
 
-	Common::String getBookInfoFileName() const;
-	void loadBookInfo(const Common::String &filename);
+	Common::Path getBookInfoFileName() const;
+	void loadBookInfo(const Common::Path &filename);
 
 	Common::String stringForMode(LBMode mode);
 
diff --git a/engines/mohawk/livingbooks_lbx.cpp b/engines/mohawk/livingbooks_lbx.cpp
index a0822d5a909..d47b1c6e6a4 100644
--- a/engines/mohawk/livingbooks_lbx.cpp
+++ b/engines/mohawk/livingbooks_lbx.cpp
@@ -35,7 +35,7 @@ protected:
 	Common::INIFile _dataFile;
 	Common::String _curSection;
 
-	void open(const Common::String &filename);
+	void open(const Common::Path &filename);
 	bool sectionExists(const Common::String &section);
 };
 
@@ -62,7 +62,7 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> &params, LBValu
 		if (params.size() != 1)
 			error("incorrect number of parameters (%d) to LBXDataFile::open", params.size());
 
-		open(params[0].toString());
+		open(Common::Path(params[0].toString()));
 		return false;
 
 	case kLBXDataFileAddSection:
@@ -133,7 +133,7 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> &params, LBValu
 	}
 }
 
-void LBXDataFile::open(const Common::String &filename) {
+void LBXDataFile::open(const Common::Path &filename) {
 	_dataFile.clear();
 
 	if (_dataFile.loadFromFile(filename))
@@ -141,7 +141,7 @@ void LBXDataFile::open(const Common::String &filename) {
 
 	// FIXME: try savegames
 
-	error("LBXDataFile::open: couldn't open '%s'", filename.c_str());
+	error("LBXDataFile::open: couldn't open '%s'", filename.toString().c_str());
 }
 
 Common::SharedPtr<LBXObject> createLBXObject(MohawkEngine_LivingBooks *vm, uint16 type) {
diff --git a/engines/mohawk/metaengine.cpp b/engines/mohawk/metaengine.cpp
index c368f562fae..426151f69be 100644
--- a/engines/mohawk/metaengine.cpp
+++ b/engines/mohawk/metaengine.cpp
@@ -82,7 +82,7 @@ uint8 MohawkEngine::getGameType() const {
 	return _gameDescription->gameType;
 }
 
-Common::String MohawkEngine_LivingBooks::getBookInfoFileName() const {
+Common::Path MohawkEngine_LivingBooks::getBookInfoFileName() const {
 	return _gameDescription->desc.filesDescriptions[0].fileName;
 }
 
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 24b9424546b..c1db8e47459 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -199,7 +199,7 @@ static const char *mystFiles[] = {
 // qtw/myst/gar4wbf1.mov:	gar4wbf2.mov has two butterflies instead of one
 // qtw/myst/libelev.mov:	libup.mov is basically the same with sound
 
-Common::String MohawkEngine_Myst::wrapMovieFilename(const Common::String &movieName, uint16 stack) {
+Common::Path MohawkEngine_Myst::wrapMovieFilename(const Common::String &movieName, uint16 stack) {
 	Common::String prefix;
 
 	switch (stack) {
@@ -233,10 +233,10 @@ Common::String MohawkEngine_Myst::wrapMovieFilename(const Common::String &movieN
 		break;
 	}
 
-	return Common::String("qtw/") + prefix + movieName + ".mov";
+	return Common::Path("qtw/").joinInPlace(prefix).joinInPlace(movieName + ".mov");
 }
 
-Common::String MohawkEngine_Myst::selectLocalizedMovieFilename(const Common::String &movieName) {
+Common::Path MohawkEngine_Myst::selectLocalizedMovieFilename(const Common::Path &movieName) {
 	Common::Language language = getLanguage();
 	const MystLanguage *languageDesc = getLanguageDesc(language);
 
@@ -244,7 +244,7 @@ Common::String MohawkEngine_Myst::selectLocalizedMovieFilename(const Common::Str
 		return movieName;
 	}
 
-	Common::String localizedMovieName = Common::String::format("%s/%s", languageDesc->archiveSuffix, movieName.c_str());
+	Common::Path localizedMovieName = Common::Path(languageDesc->archiveSuffix).joinInPlace(movieName);
 	if (!SearchMan.hasFile(localizedMovieName)) {
 		return movieName;
 	}
@@ -253,12 +253,12 @@ Common::String MohawkEngine_Myst::selectLocalizedMovieFilename(const Common::Str
 }
 
 VideoEntryPtr MohawkEngine_Myst::playMovie(const Common::String &name, MystStack stack) {
-	Common::String filename = wrapMovieFilename(name, stack);
+	Common::Path filename = wrapMovieFilename(name, stack);
 	filename = selectLocalizedMovieFilename(filename);
 	VideoEntryPtr video = _video->playMovie(filename, Audio::Mixer::kSFXSoundType);
 
 	if (!video) {
-		error("Failed to open the '%s' movie", filename.c_str());
+		error("Failed to open the '%s' movie", filename.toString().c_str());
 	}
 
 	return video;
@@ -274,17 +274,17 @@ VideoEntryPtr MohawkEngine_Myst::playMovieFullscreen(const Common::String &name,
 
 
 VideoEntryPtr MohawkEngine_Myst::findVideo(const Common::String &name, MystStack stack) {
-	Common::String filename = wrapMovieFilename(name, stack);
+	Common::Path filename = wrapMovieFilename(name, stack);
 	filename = selectLocalizedMovieFilename(filename);
 	return _video->findVideo(filename);
 }
 
 void MohawkEngine_Myst::playMovieBlocking(const Common::String &name, MystStack stack, uint16 x, uint16 y) {
-	Common::String filename = wrapMovieFilename(name, stack);
+	Common::Path filename = wrapMovieFilename(name, stack);
 	filename = selectLocalizedMovieFilename(filename);
 	VideoEntryPtr video = _video->playMovie(filename, Audio::Mixer::kSFXSoundType);
 	if (!video) {
-		error("Failed to open the '%s' movie", filename.c_str());
+		error("Failed to open the '%s' movie", filename.toString().c_str());
 	}
 
 	video->moveTo(x, y);
@@ -330,10 +330,10 @@ void MohawkEngine_Myst::playFlybyMovie(MystStack stack) {
 
 	_gfx->clearScreen();
 
-	Common::String filename = wrapMovieFilename(flyby, kMasterpieceOnly);
+	Common::Path filename = wrapMovieFilename(flyby, kMasterpieceOnly);
 	VideoEntryPtr video = _video->playMovie(filename, Audio::Mixer::kSFXSoundType);
 	if (!video) {
-		error("Failed to open the '%s' movie", filename.c_str());
+		error("Failed to open the '%s' movie", filename.toString().c_str());
 	}
 
 	video->center();
@@ -505,18 +505,18 @@ void MohawkEngine_Myst::loadStackArchives(MystStack stackId) {
 }
 
 void MohawkEngine_Myst::loadArchive(const char *archiveName, const char *language, bool mandatory) {
-	Common::String filename;
+	Common::Path filename;
 	if (language) {
-		filename = Common::String::format("%s_%s.dat", archiveName, language);
+		filename = Common::Path(Common::String::format("%s_%s.dat", archiveName, language));
 	} else {
-		filename = Common::String::format("%s.dat", archiveName);
+		filename = Common::Path(Common::String::format("%s.dat", archiveName));
 	}
 
 	Archive *archive = new MohawkArchive();
 	if (!archive->openFile(filename)) {
 		delete archive;
 		if (mandatory) {
-			error("Could not open %s", filename.c_str());
+			error("Could not open %s", filename.toString().c_str());
 		} else {
 			return;
 		}
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index be0a30870ba..79a98bff55f 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -176,7 +176,7 @@ public:
 	void playFlybyMovie(MystStack stack);
 	void playSkippableMovie(const VideoEntryPtr &video, bool looping);
 	void waitUntilMovieEnds(const VideoEntryPtr &video);
-	Common::String selectLocalizedMovieFilename(const Common::String &movieName);
+	Common::Path selectLocalizedMovieFilename(const Common::Path &movieName);
 
 	void playSoundBlocking(uint16 id);
 
@@ -228,7 +228,7 @@ private:
 
 	void dropPage();
 
-	Common::String wrapMovieFilename(const Common::String &movieName, uint16 stack);
+	Common::Path wrapMovieFilename(const Common::String &movieName, uint16 stack);
 
 	void loadStackArchives(MystStack stackId);
 	void loadArchive(const char *archiveName, const char *language, bool mandatory);
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index 62f0e1ddbd2..2fdb43b7f7c 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -166,7 +166,7 @@ const Common::String MystAreaAction::describe() {
 }
 
 // In Myst/Making of Myst, the paths are hardcoded ala Windows style without extension. Convert them.
-Common::String MystAreaVideo::convertMystVideoName(const Common::String &name) {
+Common::Path MystAreaVideo::convertMystVideoName(const Common::String &name) {
 	Common::String temp;
 
 	for (uint32 i = 1; i < name.size(); i++) {
@@ -176,22 +176,23 @@ Common::String MystAreaVideo::convertMystVideoName(const Common::String &name) {
 			temp += name[i];
 	}
 
-	return temp + ".mov";
+	return Common::Path(temp + ".mov");
 }
 
 MystAreaVideo::MystAreaVideo(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
 		MystAreaAction(vm, type, rlstStream, parent) {
 	char c = 0;
 
+	Common::String videoFile;
 	while ((c = rlstStream->readByte()) != 0) {
-		_videoFile += c;
+		videoFile += c;
 	}
 
-	if ((_videoFile.size() & 1) == 0) {
+	if ((videoFile.size() & 1) == 0) {
 		rlstStream->skip(1);
 	}
 
-	_videoFile = convertMystVideoName(_videoFile);
+	_videoFile = convertMystVideoName(videoFile);
 	_videoFile = _vm->selectLocalizedMovieFilename(_videoFile);
 
 	// Position values require modulus 10000 to keep in sane range.
@@ -212,7 +213,7 @@ MystAreaVideo::MystAreaVideo(MohawkEngine_Myst *vm, ResourceType type, Common::S
 		_playOnCardChange = false;
 	}
 
-	debugC(kDebugResource, "\tvideoFile: \"%s\"", _videoFile.c_str());
+	debugC(kDebugResource, "\tvideoFile: \"%s\"", _videoFile.toString().c_str());
 	debugC(kDebugResource, "\tleft: %d", _left);
 	debugC(kDebugResource, "\ttop: %d", _top);
 	debugC(kDebugResource, "\tloop: %d", _loop);
@@ -230,7 +231,7 @@ VideoEntryPtr MystAreaVideo::playMovie() {
 	if (!handle) {
 		handle = _vm->_video->playMovie(_videoFile, Audio::Mixer::kSFXSoundType);
 		if (!handle)
-			error("Failed to open '%s'", _videoFile.c_str());
+			error("Failed to open '%s'", _videoFile.toString().c_str());
 
 		handle->moveTo(_left, _top);
 		handle->setLooping(_loop != 0);
@@ -269,7 +270,7 @@ VideoEntryPtr MystAreaVideo::getVideo() {
 		// If the video has not been loaded yet, do it but don't start playing it
 		handle = _vm->_video->playMovie(_videoFile, Audio::Mixer::kSFXSoundType);
 		if (!handle)
-			error("Failed to open '%s'", _videoFile.c_str());
+			error("Failed to open '%s'", _videoFile.toString().c_str());
 		handle->stop();
 	}
 
diff --git a/engines/mohawk/myst_areas.h b/engines/mohawk/myst_areas.h
index 6813244cf6e..6c204947fb6 100644
--- a/engines/mohawk/myst_areas.h
+++ b/engines/mohawk/myst_areas.h
@@ -118,9 +118,9 @@ public:
 	void pauseMovie(bool pause);
 
 protected:
-	static Common::String convertMystVideoName(const Common::String &name);
+	static Common::Path convertMystVideoName(const Common::String &name);
 
-	Common::String _videoFile;
+	Common::Path _videoFile;
 	int16 _left;
 	int16 _top;
 	uint16 _loop;
diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp
index 6cabae47144..bdcfcc8607f 100644
--- a/engines/mohawk/resource.cpp
+++ b/engines/mohawk/resource.cpp
@@ -38,7 +38,7 @@ Archive::~Archive() {
 	close();
 }
 
-bool Archive::openFile(const Common::String &fileName) {
+bool Archive::openFile(const Common::Path &fileName) {
 	Common::File *file = new Common::File();
 
 	if (!file->open(fileName)) {
diff --git a/engines/mohawk/resource.h b/engines/mohawk/resource.h
index b4b7204a02a..a60f682fe6e 100644
--- a/engines/mohawk/resource.h
+++ b/engines/mohawk/resource.h
@@ -136,7 +136,7 @@ public:
 	Archive();
 	virtual ~Archive();
 
-	bool openFile(const Common::String &fileName);
+	bool openFile(const Common::Path &fileName);
 	virtual bool openStream(Common::SeekableReadStream *stream) = 0;
 	void close();
 
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index e732ee169a1..481d5831725 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -91,7 +91,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
 	// file. The following directories allow Riven to be played directly
 	// from the DVD.
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "all");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "data");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "exe");
@@ -536,7 +536,7 @@ void MohawkEngine_Riven::loadLanguageDatafile(char prefix, uint16 stackId) {
 		return;
 	}
 
-	Common::String languageDatafile = Common::String::format("%c_data_%s.mhk", prefix, languageDesc->archiveSuffix);
+	Common::Path languageDatafile(Common::String::format("%c_data_%s.mhk", prefix, languageDesc->archiveSuffix));
 
 	MohawkArchive *mhk = new MohawkArchive();
 	if (mhk->openFile(languageDatafile)) {
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 704e6897e1e..15d4073a37f 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -40,7 +40,7 @@ namespace Mohawk {
 VideoEntry::VideoEntry() : _video(nullptr), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) {
 }
 
-VideoEntry::VideoEntry(Video::VideoDecoder *video, const Common::String &fileName) : _video(video), _fileName(fileName), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) {
+VideoEntry::VideoEntry(Video::VideoDecoder *video, const Common::Path &fileName) : _video(video), _fileName(fileName), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) {
 }
 
 VideoEntry::VideoEntry(Video::VideoDecoder *video, int id) : _video(video), _id(id), _x(0), _y(0), _loop(false), _enabled(true) {
@@ -192,14 +192,15 @@ void VideoManager::stopVideos() {
 	_videos.clear();
 }
 
-VideoEntryPtr VideoManager::playMovie(const Common::String &fileName, Audio::Mixer::SoundType soundType) {
+VideoEntryPtr VideoManager::playMovie(const Common::Path &fileName, Audio::Mixer::SoundType soundType) {
 	VideoEntryPtr ptr = open(fileName, soundType);
 	if (!ptr)
 		return VideoEntryPtr();
 
+	Common::String baseName(fileName.baseName());
 
-	Common::String subtitlesName = Common::String::format("%s.srt", fileName.substr(0, fileName.size() - 4).c_str());
-	ptr->loadSubtitles(subtitlesName.c_str());
+	Common::String subtitlesName = Common::String::format("%s.srt", baseName.substr(0, baseName.size() - 4).c_str());
+	ptr->loadSubtitles(fileName.getParent().appendComponent(subtitlesName));
 
 	ptr->start();
 	return ptr;
@@ -347,7 +348,7 @@ VideoEntryPtr VideoManager::open(uint16 id) {
 	return entry;
 }
 
-VideoEntryPtr VideoManager::open(const Common::String &fileName, Audio::Mixer::SoundType soundType) {
+VideoEntryPtr VideoManager::open(const Common::Path &fileName, Audio::Mixer::SoundType soundType) {
 	// If this video is already playing, return that entry
 	VideoEntryPtr oldVideo = findVideo(fileName);
 	if (oldVideo)
@@ -389,7 +390,7 @@ VideoEntryPtr VideoManager::findVideo(uint16 id) {
 	return VideoEntryPtr();
 }
 
-VideoEntryPtr VideoManager::findVideo(const Common::String &fileName) {
+VideoEntryPtr VideoManager::findVideo(const Common::Path &fileName) {
 	if (fileName.empty())
 		return VideoEntryPtr();
 
@@ -439,7 +440,7 @@ void VideoManager::checkEnableDither(VideoEntryPtr &entry) {
 		if (entry->getFileName().empty())
 			error("Failed to set dither for video tMOV %d", entry->getID());
 		else
-			error("Failed to set dither for video %s", entry->getFileName().c_str());
+			error("Failed to set dither for video %s", entry->getFileName().toString().c_str());
 	}
 }
 
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 6dd6ced4a3d..3980de90691 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -51,7 +51,7 @@ private:
 	// Hide the destructor/constructor
 	// Only VideoManager should be allowed
 	VideoEntry();
-	VideoEntry(Video::VideoDecoder *video, const Common::String &fileName);
+	VideoEntry(Video::VideoDecoder *video, const Common::Path &fileName);
 	VideoEntry(Video::VideoDecoder *video, int id);
 
 public:
@@ -105,7 +105,7 @@ public:
 	/**
 	 * Get the file name of the video, or empty if by ID
 	 */
-	const Common::String &getFileName() const { return _fileName; }
+	const Common::Path &getFileName() const { return _fileName; }
 
 	/**
 	 * Get the ID of the video, or -1 if by file name
@@ -222,11 +222,11 @@ public:
 	/**
 	 * Load the subtitles
 	 */
-	void loadSubtitles(const char *fname) { _subtitles.loadSRTFile(fname); }
+	void loadSubtitles(const Common::Path &fname) { _subtitles.loadSRTFile(fname); }
 private:
 	// Non-changing variables
 	Video::VideoDecoder *_video;
-	Common::String _fileName; // External video files
+	Common::Path _fileName;   // External video files
 	int _id;                  // Internal Mohawk files
 
 	// Playback variables
@@ -247,7 +247,7 @@ public:
 	virtual ~VideoManager();
 
 	// Generic movie functions
-	VideoEntryPtr playMovie(const Common::String &filename, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+	VideoEntryPtr playMovie(const Common::Path &filename, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
 	VideoEntryPtr playMovie(uint16 id);
 	bool updateMovies();
 	void pauseVideos();
@@ -257,7 +257,7 @@ public:
 
 	// Handle functions
 	VideoEntryPtr findVideo(uint16 id);
-	VideoEntryPtr findVideo(const Common::String &fileName);
+	VideoEntryPtr findVideo(const Common::Path &fileName);
 	void drawVideoFrame(const VideoEntryPtr &video, const Audio::Timestamp &time);
 	void removeEntry(const VideoEntryPtr &video);
 
@@ -270,7 +270,7 @@ protected:
 
 	// Utility functions for managing entries
 	VideoEntryPtr open(uint16 id);
-	VideoEntryPtr open(const Common::String &fileName, Audio::Mixer::SoundType soundType);
+	VideoEntryPtr open(const Common::Path &fileName, Audio::Mixer::SoundType soundType);
 
 	VideoList::iterator findEntry(VideoEntryPtr ptr);
 


Commit: 1b1f9fc209b29c6d2af365708ca8e995b6d01b67
    https://github.com/scummvm/scummvm/commit/1b1f9fc209b29c6d2af365708ca8e995b6d01b67
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MORTEVIELLE: Migrate engine to Path

Changed paths:
    engines/mortevielle/outtext.cpp
    engines/mortevielle/outtext.h
    engines/mortevielle/saveload.cpp


diff --git a/engines/mortevielle/outtext.cpp b/engines/mortevielle/outtext.cpp
index fd8e94f9fff..b3b3fef426b 100644
--- a/engines/mortevielle/outtext.cpp
+++ b/engines/mortevielle/outtext.cpp
@@ -127,11 +127,11 @@ void TextHandler::displayStr(Common::String inputStr, int x, int y, int dx, int
  * Load DES (picture container) file
  * @remarks	Originally called 'chardes'
  */
-void TextHandler::loadPictureFile(Common::String filename, Common::String altFilename, int32 skipSize, int length) {
+void TextHandler::loadPictureFile(const Common::Path &filename, const Common::Path &altFilename, int32 skipSize, int length) {
 	Common::File f;
 	if (!f.open(filename)) {
 		if (!f.open(altFilename))
-			error("Missing file: Either %s or %s", filename.c_str(), altFilename.c_str());
+			error("Missing file: Either %s or %s", filename.toString().c_str(), altFilename.toString().c_str());
 	}
 	// HACK: The original game contains a bug in the 2nd intro screen, in German DOS version.
 	// The size specified in the fxx array is wrong (too short). In order to fix it, we are using
@@ -152,10 +152,10 @@ void TextHandler::loadPictureFile(Common::String filename, Common::String altFil
  * Load ANI file
  * @remarks	Originally called 'charani'
  */
-void TextHandler::loadAniFile(Common::String filename, int32 skipSize, int length) {
+void TextHandler::loadAniFile(const Common::Path &filename, int32 skipSize, int length) {
 	Common::File f;
 	if (!f.open(filename))
-		error("Missing file - %s", filename.c_str());
+		error("Missing file - %s", filename.toString().c_str());
 
 	assert(skipSize + length <= f.size());
 
@@ -223,7 +223,7 @@ void TextHandler::taffich() {
 	_vm->_destinationOk = true;
 	_vm->_mouse->hideMouse();
 	drawingStartPos = 0;
-	Common::String filename, altFilename;
+	Common::Path filename, altFilename;
 
 	if ((a != 50) && (a != 51)) {
 		int m = a + 2000;
diff --git a/engines/mortevielle/outtext.h b/engines/mortevielle/outtext.h
index 224616e3d07..38ff9797edd 100644
--- a/engines/mortevielle/outtext.h
+++ b/engines/mortevielle/outtext.h
@@ -40,8 +40,8 @@ public:
 	TextHandler (MortevielleEngine *vm);
 
 	void displayStr(Common::String inputStr, int x, int y, int dx, int dy, int typ);
-	void loadPictureFile(Common::String filename, Common::String altFilename, int32 skipSize, int length);
-	void loadAniFile(Common::String filename, int32 skipSize, int length);
+	void loadPictureFile(const Common::Path &filename, const Common::Path &altFilename, int32 skipSize, int length);
+	void loadAniFile(const Common::Path &filename, int32 skipSize, int length);
 	void taffich();
 };
 
diff --git a/engines/mortevielle/saveload.cpp b/engines/mortevielle/saveload.cpp
index 77c2aa65cd7..cd55df3e92d 100644
--- a/engines/mortevielle/saveload.cpp
+++ b/engines/mortevielle/saveload.cpp
@@ -77,7 +77,7 @@ bool SavegameManager::loadSavegame(const Common::String &filename) {
 
 	Common::File f;
 	if (stream == nullptr) {
-		if (!f.open(filename)) {
+		if (!f.open(Common::Path(filename))) {
 			warning("Unable to open save file '%s'", filename.c_str());
 			return false;
 		}


Commit: c78ace6701a229db160532c172be1b3e8f00fa18
    https://github.com/scummvm/scummvm/commit/c78ace6701a229db160532c172be1b3e8f00fa18
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MTROPOLIS: Migrate engine to Path

Changed paths:
    engines/mtropolis/mtropolis.cpp
    engines/mtropolis/vfs.cpp
    engines/mtropolis/vfs.h


diff --git a/engines/mtropolis/mtropolis.cpp b/engines/mtropolis/mtropolis.cpp
index 6c34285f0c2..4450744e741 100644
--- a/engines/mtropolis/mtropolis.cpp
+++ b/engines/mtropolis/mtropolis.cpp
@@ -55,7 +55,7 @@
 namespace MTropolis {
 
 MTropolisEngine::MTropolisEngine(OSystem *syst, const MTropolisGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _saveWriter(nullptr), _isTriggeredAutosave(false) {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "Resource");
 
 	bootAddSearchPaths(gameDataDir, *gameDesc);
diff --git a/engines/mtropolis/vfs.cpp b/engines/mtropolis/vfs.cpp
index f33e1005bc2..42e7b6449f6 100644
--- a/engines/mtropolis/vfs.cpp
+++ b/engines/mtropolis/vfs.cpp
@@ -93,7 +93,7 @@ VirtualFileSystem::VirtualFileSystem(const VirtualFileSystemLayout &layout) : _p
 
 		VirtualFile vf;
 		vf._archiveMember = tempLayoutFiles[ctofNode._value]._archiveMember;
-		vf._virtualPath = ctovIt->_value;
+		vf._virtualPath = Common::Path(ctovIt->_value, _pathSeparator);
 
 		_virtualFiles.push_back(vf);
 	}
@@ -212,11 +212,11 @@ Common::SeekableReadStream *VirtualFileSystem::VFSArchiveMember::createReadStrea
 }
 
 Common::String VirtualFileSystem::VFSArchiveMember::getName() const {
-	return _virtualFile->_virtualPath;
+	return _virtualFile->_virtualPath.toString(_pathSeparator);
 }
 
 Common::Path VirtualFileSystem::VFSArchiveMember::getPathInArchive() const {
-	return Common::Path(_virtualFile->_virtualPath, _pathSeparator);
+	return _virtualFile->_virtualPath;
 }
 
 Common::String VirtualFileSystem::VFSArchiveMember::getFileName() const {
diff --git a/engines/mtropolis/vfs.h b/engines/mtropolis/vfs.h
index 43d4f27e756..099a0d7f96b 100644
--- a/engines/mtropolis/vfs.h
+++ b/engines/mtropolis/vfs.h
@@ -66,7 +66,7 @@ public:
 
 private:
 	struct VirtualFile {
-		Common::String _virtualPath;
+		Common::Path _virtualPath;
 		Common::ArchiveMemberPtr _archiveMember;
 
 		Common::ArchiveMemberPtr _vfsArchiveMember;


Commit: c8d211090ece13d642d5f70c6731d2130030ab14
    https://github.com/scummvm/scummvm/commit/c8d211090ece13d642d5f70c6731d2130030ab14
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MUTATIONOFJB: Migrate engine to Path

Changed paths:
    engines/mutationofjb/animationdecoder.cpp
    engines/mutationofjb/animationdecoder.h
    engines/mutationofjb/conversationlinelist.cpp
    engines/mutationofjb/conversationlinelist.h
    engines/mutationofjb/font.cpp
    engines/mutationofjb/font.h
    engines/mutationofjb/game.cpp
    engines/mutationofjb/mutationofjb.cpp
    engines/mutationofjb/room.cpp


diff --git a/engines/mutationofjb/animationdecoder.cpp b/engines/mutationofjb/animationdecoder.cpp
index b52f089d1de..de7972ccced 100644
--- a/engines/mutationofjb/animationdecoder.cpp
+++ b/engines/mutationofjb/animationdecoder.cpp
@@ -26,19 +26,19 @@
 
 namespace MutationOfJB {
 
-AnimationDecoder::AnimationDecoder(const Common::String &fileName) : _fileName(fileName), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {
+AnimationDecoder::AnimationDecoder(const Common::Path &fileName) : _fileName(fileName), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {
 	_surface.create(IMAGE_WIDTH, IMAGE_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
 	_owningSurface = true;
 }
 
-AnimationDecoder::AnimationDecoder(const Common::String &fileName, const Graphics::Surface &outSurface) : _fileName(fileName), _surface(outSurface), _owningSurface(false), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {}
+AnimationDecoder::AnimationDecoder(const Common::Path &fileName, const Graphics::Surface &outSurface) : _fileName(fileName), _surface(outSurface), _owningSurface(false), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {}
 
 bool AnimationDecoder::decode(AnimationDecoderCallback *callback) {
 	EncryptedFile file;
 	file.open(_fileName);
 
 	if (!file.isOpen()) {
-		reportFileMissingError(_fileName.c_str());
+		reportFileMissingError(_fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 		return false;
 	}
diff --git a/engines/mutationofjb/animationdecoder.h b/engines/mutationofjb/animationdecoder.h
index 48fcdd8cca8..4050cab00a4 100644
--- a/engines/mutationofjb/animationdecoder.h
+++ b/engines/mutationofjb/animationdecoder.h
@@ -23,8 +23,8 @@
 #define MUTATIONOFJB_ANIMATIONDECODER_H
 
 #include "common/rect.h"
+#include "common/path.h"
 #include "common/scummsys.h"
-#include "common/str.h"
 
 #include "graphics/surface.h"
 #include "mutationofjb/encryptedfile.h"
@@ -51,8 +51,8 @@ public:
 
 class AnimationDecoder {
 public:
-	AnimationDecoder(const Common::String &fileName);
-	AnimationDecoder(const Common::String &fileName, const Graphics::Surface &outSurface);
+	AnimationDecoder(const Common::Path &fileName);
+	AnimationDecoder(const Common::Path &fileName, const Graphics::Surface &outSurface);
 	~AnimationDecoder();
 	bool decode(AnimationDecoderCallback *callback);
 
@@ -71,7 +71,7 @@ private:
 	void loadFullFrame(EncryptedFile &file, uint32 size);
 	void loadDiffFrame(EncryptedFile &file, uint32 size);
 
-	Common::String _fileName;
+	Common::Path _fileName;
 	Graphics::Surface _surface;
 	bool _owningSurface;
 	byte _palette[PALETTE_SIZE];
diff --git a/engines/mutationofjb/conversationlinelist.cpp b/engines/mutationofjb/conversationlinelist.cpp
index 9ca79337e74..1b2a0fa65cf 100644
--- a/engines/mutationofjb/conversationlinelist.cpp
+++ b/engines/mutationofjb/conversationlinelist.cpp
@@ -25,7 +25,7 @@
 
 namespace MutationOfJB {
 
-ConversationLineList::ConversationLineList(const Common::String &fileName) {
+ConversationLineList::ConversationLineList(const Common::Path &fileName) {
 	parseFile(fileName);
 }
 
@@ -37,11 +37,11 @@ const ConversationLineList::Line *ConversationLineList::getLine(uint index) cons
 	return &_lines[index - 1];
 }
 
-bool ConversationLineList::parseFile(const Common::String &fileName) {
+bool ConversationLineList::parseFile(const Common::Path &fileName) {
 	EncryptedFile file;
 	file.open(fileName);
 	if (!file.isOpen()) {
-		reportFileMissingError(fileName.c_str());
+		reportFileMissingError(fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/engines/mutationofjb/conversationlinelist.h b/engines/mutationofjb/conversationlinelist.h
index a43576fe890..7e1e9ba7e37 100644
--- a/engines/mutationofjb/conversationlinelist.h
+++ b/engines/mutationofjb/conversationlinelist.h
@@ -22,8 +22,9 @@
 #ifndef MUTATIONOFJB_CONVERSATIONLINELIST_H
 #define MUTATIONOFJB_CONVERSATIONLINELIST_H
 
-#include "common/str.h"
 #include "common/array.h"
+#include "common/path.h"
+#include "common/str.h"
 
 namespace MutationOfJB {
 
@@ -50,11 +51,11 @@ public:
 		Common::String _extra;
 	};
 
-	ConversationLineList(const Common::String &fileName);
+	ConversationLineList(const Common::Path &fileName);
 	const Line *getLine(uint index) const;
 
 private:
-	bool parseFile(const Common::String &fileName);
+	bool parseFile(const Common::Path &fileName);
 
 	Common::Array<Line> _lines;
 };
diff --git a/engines/mutationofjb/font.cpp b/engines/mutationofjb/font.cpp
index 0aa315218c2..fd321d36a9c 100644
--- a/engines/mutationofjb/font.cpp
+++ b/engines/mutationofjb/font.cpp
@@ -26,7 +26,7 @@
 
 namespace MutationOfJB {
 
-Font::Font(const Common::String &fileName, int horizSpacing, int lineHeight) :
+Font::Font(const Common::Path &fileName, int horizSpacing, int lineHeight) :
 	_horizSpacing(horizSpacing),
 	_lineHeight(lineHeight),
 	_maxCharWidth(0) {
@@ -34,11 +34,11 @@ Font::Font(const Common::String &fileName, int horizSpacing, int lineHeight) :
 	load(fileName);
 }
 
-bool Font::load(const Common::String &fileName) {
+bool Font::load(const Common::Path &fileName) {
 	EncryptedFile file;
 	file.open(fileName);
 	if (!file.isOpen()) {
-		reportFileMissingError(fileName.c_str());
+		reportFileMissingError(fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/engines/mutationofjb/font.h b/engines/mutationofjb/font.h
index 3af44d625ee..74355610c39 100644
--- a/engines/mutationofjb/font.h
+++ b/engines/mutationofjb/font.h
@@ -37,7 +37,7 @@ namespace MutationOfJB {
 class Font : public Graphics::Font {
 	friend class FontBlitOperation;
 public:
-	Font(const Common::String &fileName, int horizSpacing, int lineHeight);
+	Font(const Common::Path &fileName, int horizSpacing, int lineHeight);
 
 	int getFontHeight() const override;
 	int getMaxCharWidth() const override;
@@ -49,7 +49,7 @@ protected:
 	virtual uint8 transformColor(uint8 baseColor, uint8 glyphColor) const;
 
 private:
-	bool load(const Common::String &fileName);
+	bool load(const Common::Path &fileName);
 
 	int _horizSpacing;
 	int _lineHeight;
diff --git a/engines/mutationofjb/game.cpp b/engines/mutationofjb/game.cpp
index 527485fbd54..d1f9e06f379 100644
--- a/engines/mutationofjb/game.cpp
+++ b/engines/mutationofjb/game.cpp
@@ -117,10 +117,10 @@ Script *Game::changeSceneLoadScript(uint8 sceneId, bool partB) {
 	_gui.refreshAfterSceneChanged();
 
 	EncryptedFile scriptFile;
-	Common::String fileName = Common::String::format("scrn%d%s.atn", sceneId, partB ? "b" : "");
+	Common::Path fileName(Common::String::format("scrn%d%s.atn", sceneId, partB ? "b" : ""));
 	scriptFile.open(fileName);
 	if (!scriptFile.isOpen()) {
-		reportFileMissingError(fileName.c_str());
+		reportFileMissingError(fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return nullptr;
 	}
 
diff --git a/engines/mutationofjb/mutationofjb.cpp b/engines/mutationofjb/mutationofjb.cpp
index ae4667e7719..7f458c5cd33 100644
--- a/engines/mutationofjb/mutationofjb.cpp
+++ b/engines/mutationofjb/mutationofjb.cpp
@@ -51,7 +51,7 @@ MutationOfJBEngine::MutationOfJBEngine(OSystem *syst, const ADGameDescription *g
 	  _cursorState(CURSOR_IDLE),
 	  _currentScreen(nullptr) {
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "data");
 }
 
diff --git a/engines/mutationofjb/room.cpp b/engines/mutationofjb/room.cpp
index 6e091b3d4c0..cce63f34c79 100644
--- a/engines/mutationofjb/room.cpp
+++ b/engines/mutationofjb/room.cpp
@@ -110,7 +110,7 @@ bool Room::load(uint8 roomNumber, bool roomB) {
 		}
 	}
 
-	const Common::String fileName = Common::String::format("room%d%s.dat", roomNumber, roomB ? "b" : "");
+	const Common::Path fileName(Common::String::format("room%d%s.dat", roomNumber, roomB ? "b" : ""));
 	AnimationDecoder decoder(fileName);
 	RoomAnimationDecoderCallback callback(*this);
 	return decoder.decode(&callback);
@@ -188,7 +188,7 @@ void Room::drawFrames(int fromFrame, int toFrame, const Common::Rect &area, uint
 		return;
 	}
 
-	const Common::String fileName = Common::String::format("room%d%s.dat", gameData._currentScene, gameData._partB ? "b" : "");
+	const Common::Path fileName(Common::String::format("room%d%s.dat", gameData._currentScene, gameData._partB ? "b" : ""));
 
 	{
 		AnimationDecoder decoder(fileName, *_screen);


Commit: aa5ad1f500cecf3594f272a69f8c739ac90393d0
    https://github.com/scummvm/scummvm/commit/aa5ad1f500cecf3594f272a69f8c739ac90393d0
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
MYST3: Migrate engine to Path

Changed paths:
    engines/myst3/console.cpp
    engines/myst3/myst3.cpp
    engines/myst3/sound.cpp
    engines/myst3/subtitles.cpp


diff --git a/engines/myst3/console.cpp b/engines/myst3/console.cpp
index 2d812b43174..3cfee876d60 100644
--- a/engines/myst3/console.cpp
+++ b/engines/myst3/console.cpp
@@ -301,7 +301,7 @@ bool Console::Cmd_Extract(int argc, const char **argv) {
 	}
 
 	Common::SeekableReadStream *s = desc.getData();
-	Common::String filename = Common::String::format("node%s_%d_face%d.%d", room.c_str(), id, face, type);
+	Common::Path filename(Common::String::format("node%s_%d_face%d.%d", room.c_str(), id, face, type));
 	Common::DumpFile f;
 	f.open(filename);
 
@@ -316,7 +316,7 @@ bool Console::Cmd_Extract(int argc, const char **argv) {
 
 	delete s;
 
-	debugPrintf("File '%s' successfully written\n", filename.c_str());
+	debugPrintf("File '%s' successfully written\n", filename.toString(Common::Path::kNativeSeparator).c_str());
 
 	return true;
 }
@@ -344,7 +344,7 @@ public:
 	void visitDirectorySubEntry(Archive::DirectorySubEntry &directorySubEntry) override {
 		assert(_currentDirectoryEntry);
 
-		Common::String fileName;
+		Common::Path fileName;
 		switch (directorySubEntry.type) {
 		case Archive::kNumMetadata:
 		case Archive::kTextMetadata:
@@ -353,27 +353,27 @@ public:
 		case Archive::kSpotItem:
 		case Archive::kLocalizedSpotItem:
 		case Archive::kFrame:
-			fileName = Common::String::format("dump/%s-%d-%d.jpg", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index, directorySubEntry.face);
+			fileName = Common::Path(Common::String::format("dump/%s-%d-%d.jpg", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index, directorySubEntry.face));
 			break;
 		case Archive::kWaterEffectMask:
-			fileName = Common::String::format("dump/%s-%d-%d.mask", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index, directorySubEntry.face);
+			fileName = Common::Path(Common::String::format("dump/%s-%d-%d.mask", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index, directorySubEntry.face));
 			break;
 		case Archive::kMovie:
 		case Archive::kStillMovie:
 		case Archive::kDialogMovie:
 		case Archive::kMultitrackMovie:
-			fileName = Common::String::format("dump/%s-%d.bik", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index);
+			fileName = Common::Path(Common::String::format("dump/%s-%d.bik", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index));
 			break;
 		default:
-			fileName = Common::String::format("dump/%s-%d-%d.%d", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index, directorySubEntry.face, directorySubEntry.type);
+			fileName = Common::Path(Common::String::format("dump/%s-%d-%d.%d", _currentDirectoryEntry->roomName.c_str(), _currentDirectoryEntry->index, directorySubEntry.face, directorySubEntry.type));
 			break;
 		}
 
-		debug("Extracted %s", fileName.c_str());
+		debug("Extracted %s", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 		Common::DumpFile outFile;
 		if (!outFile.open(fileName, true))
-			error("Unable to open file '%s' for writing", fileName.c_str());
+			error("Unable to open file '%s' for writing", fileName.toString(Common::Path::kNativeSeparator).c_str());
 
 		_archive->copyTo(directorySubEntry.offset, directorySubEntry.size, outFile);
 		outFile.close();
@@ -467,7 +467,8 @@ bool Console::dumpFaceMask(uint16 index, int face, Archive::ResourceType type) {
 	delete maskStream;
 
 	Common::DumpFile outFile;
-	outFile.open(Common::String::format("dump/%d-%d.masku_%d", index, face, type));
+	Common::Path fileName(Common::String::format("dump/%d-%d.masku_%d", index, face, type));
+	outFile.open(fileName);
 	outFile.write(mask->surface->getPixels(), mask->surface->pitch * mask->surface->h);
 	outFile.close();
 
diff --git a/engines/myst3/myst3.cpp b/engines/myst3/myst3.cpp
index 895dcb3a7b6..533c6b68852 100644
--- a/engines/myst3/myst3.cpp
+++ b/engines/myst3/myst3.cpp
@@ -78,7 +78,7 @@ Myst3Engine::Myst3Engine(OSystem *syst, const Myst3GameDescription *version) :
 		_transition(nullptr), _frameLimiter(nullptr), _inventoryManualHide(false) {
 
 	// Add subdirectories to the search path to allow running from a full HDD install
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "bin");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "M3Data");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "M3Data/TEXT");
diff --git a/engines/myst3/sound.cpp b/engines/myst3/sound.cpp
index 6f89c21b96f..e41fb3a200b 100644
--- a/engines/myst3/sound.cpp
+++ b/engines/myst3/sound.cpp
@@ -479,7 +479,7 @@ uint32 SoundChannel::adjustVolume(uint32 volume) {
 
 Audio::RewindableAudioStream *SoundChannel::makeAudioStream(const Common::String &name) const {
 	Common::String folder = Common::String(name.c_str(), 4);
-	Common::String filename = Common::String::format("M3Data/%s/%s", folder.c_str(), name.c_str());
+	Common::Path filename(Common::String::format("M3Data/%s/%s", folder.c_str(), name.c_str()));
 
 	Common::SeekableReadStream *s = SearchMan.createReadStreamForMember(filename);
 
@@ -487,26 +487,26 @@ Audio::RewindableAudioStream *SoundChannel::makeAudioStream(const Common::String
 	bool isWMA = false;
 
 	if (!s)
-		s = SearchMan.createReadStreamForMember(filename + ".wav");
+		s = SearchMan.createReadStreamForMember(filename.append(".wav"));
 
 	if (!s) {
-		s = SearchMan.createReadStreamForMember(filename + ".mp3");
+		s = SearchMan.createReadStreamForMember(filename.append(".mp3"));
 		if (s) isMP3 = true;
 	}
 
 	if (!s) {
-		s = SearchMan.createReadStreamForMember(filename + ".wma");
+		s = SearchMan.createReadStreamForMember(filename.append(".wma"));
 		if (s) isWMA = true;
 	}
 
 	if (!s)
-		error("Unable to open sound file '%s'", filename.c_str());
+		error("Unable to open sound file '%s'", filename.toString().c_str());
 
 	if (isMP3) {
 #ifdef USE_MAD
 		return Audio::makeMP3Stream(s, DisposeAfterUse::YES);
 #else
-		warning("Unable to play sound '%s', MP3 support is not compiled in.", filename.c_str());
+		warning("Unable to play sound '%s', MP3 support is not compiled in.", filename.toString().c_str());
 		delete s;
 		return NULL;
 #endif
diff --git a/engines/myst3/subtitles.cpp b/engines/myst3/subtitles.cpp
index 75b210b81e8..4bbefd86d99 100644
--- a/engines/myst3/subtitles.cpp
+++ b/engines/myst3/subtitles.cpp
@@ -81,7 +81,7 @@ void FontSubtitles::loadResources() {
 	_scale = getPosition().width() / (float) getOriginalPosition().width();
 
 #ifdef USE_FREETYPE2
-	Common::String ttfFile;
+	const char *ttfFile;
 	if (_fontFace == "Arial Narrow") {
 		// Use the TTF font provided by the game if TTF support is available
 		ttfFile = "arir67w.ttf";
@@ -100,7 +100,7 @@ void FontSubtitles::loadResources() {
 		_font = Graphics::loadTTFFont(*s, _fontSize * _scale);
 		delete s;
 	} else {
-		warning("Unable to load the subtitles font '%s'", ttfFile.c_str());
+		warning("Unable to load the subtitles font '%s'", ttfFile);
 	}
 #endif
 }


Commit: 1c2d757dbda92141e76634a0ee779f8038f7d489
    https://github.com/scummvm/scummvm/commit/1c2d757dbda92141e76634a0ee779f8038f7d489
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
NANCY: Migrate engine to Path

Changed paths:
    engines/nancy/action/autotext.h
    engines/nancy/action/conversation.cpp
    engines/nancy/action/conversation.h
    engines/nancy/action/inventoryrecords.h
    engines/nancy/action/overlay.cpp
    engines/nancy/action/overlay.h
    engines/nancy/action/puzzle/assemblypuzzle.h
    engines/nancy/action/puzzle/bballpuzzle.h
    engines/nancy/action/puzzle/bombpuzzle.h
    engines/nancy/action/puzzle/bulpuzzle.h
    engines/nancy/action/puzzle/collisionpuzzle.h
    engines/nancy/action/puzzle/cubepuzzle.h
    engines/nancy/action/puzzle/leverpuzzle.h
    engines/nancy/action/puzzle/mazechasepuzzle.h
    engines/nancy/action/puzzle/mouselightpuzzle.h
    engines/nancy/action/puzzle/orderingpuzzle.h
    engines/nancy/action/puzzle/overridelockpuzzle.h
    engines/nancy/action/puzzle/peepholepuzzle.cpp
    engines/nancy/action/puzzle/peepholepuzzle.h
    engines/nancy/action/puzzle/raycastpuzzle.cpp
    engines/nancy/action/puzzle/raycastpuzzle.h
    engines/nancy/action/puzzle/rippedletterpuzzle.h
    engines/nancy/action/puzzle/rotatinglockpuzzle.h
    engines/nancy/action/puzzle/safedialpuzzle.cpp
    engines/nancy/action/puzzle/safedialpuzzle.h
    engines/nancy/action/puzzle/setplayerclock.h
    engines/nancy/action/puzzle/sliderpuzzle.h
    engines/nancy/action/puzzle/soundequalizerpuzzle.h
    engines/nancy/action/puzzle/tangrampuzzle.h
    engines/nancy/action/puzzle/telephone.h
    engines/nancy/action/puzzle/towerpuzzle.h
    engines/nancy/action/puzzle/turningpuzzle.h
    engines/nancy/action/puzzle/twodialpuzzle.h
    engines/nancy/action/secondarymovie.cpp
    engines/nancy/action/secondarymovie.h
    engines/nancy/action/secondaryvideo.cpp
    engines/nancy/action/secondaryvideo.h
    engines/nancy/cif.cpp
    engines/nancy/cif.h
    engines/nancy/commontypes.cpp
    engines/nancy/console.cpp
    engines/nancy/console.h
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h
    engines/nancy/font.cpp
    engines/nancy/graphics.cpp
    engines/nancy/graphics.h
    engines/nancy/nancy.cpp
    engines/nancy/renderobject.cpp
    engines/nancy/renderobject.h
    engines/nancy/resource.cpp
    engines/nancy/resource.h
    engines/nancy/sound.cpp
    engines/nancy/state/loadsave.cpp
    engines/nancy/state/map.cpp
    engines/nancy/state/map.h
    engines/nancy/state/scene.cpp
    engines/nancy/state/scene.h
    engines/nancy/state/setupmenu.cpp
    engines/nancy/ui/fullscreenimage.cpp
    engines/nancy/ui/fullscreenimage.h
    engines/nancy/ui/viewport.cpp
    engines/nancy/ui/viewport.h
    engines/nancy/util.cpp
    engines/nancy/util.h


diff --git a/engines/nancy/action/autotext.h b/engines/nancy/action/autotext.h
index 4d3bd90e63f..6ae633b12d4 100644
--- a/engines/nancy/action/autotext.h
+++ b/engines/nancy/action/autotext.h
@@ -53,7 +53,7 @@ protected:
 	uint16 _surfHeight = 0;
 
 	// Data for displaying images inside text; not supported yet
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	Common::Array<uint16> _imageLineIDs;
 	Common::Array<Common::Rect> _imageSrcs;
diff --git a/engines/nancy/action/conversation.cpp b/engines/nancy/action/conversation.cpp
index 0ac72c4162d..58b581dfb05 100644
--- a/engines/nancy/action/conversation.cpp
+++ b/engines/nancy/action/conversation.cpp
@@ -512,7 +512,7 @@ bool ConversationSound::ConversationFlags::isSatisfied() const {
 }
 
 void ConversationVideo::init() {
-	if (!_decoder.loadFile(_videoName + ".avf")) {
+	if (!_decoder.loadFile(Common::Path(_videoName + ".avf"))) {
 		error("Couldn't load video file %s", _videoName.c_str());
 	}
 
@@ -672,7 +672,7 @@ void ConversationCel::readData(Common::SeekableReadStream &stream) {
 	
 	readFilenameArray(stream, _treeNames, 4);
 
-	Common::SeekableReadStream *xsheet = SearchMan.createReadStreamForMember(xsheetName);
+	Common::SeekableReadStream *xsheet = SearchMan.createReadStreamForMember(Common::Path(xsheetName));
 
 	// Read the xsheet and load all images into the arrays
 	// Completely unoptimized, the original engine uses a buffer
@@ -689,7 +689,7 @@ void ConversationCel::readData(Common::SeekableReadStream &stream) {
 	_frameTime = xsheet->readUint16LE();
 	xsheet->skip(2);
 
-	_celNames.resize(4, Common::Array<Common::String>(numFrames));
+	_celNames.resize(4, Common::Array<Common::Path>(numFrames));
 	for (uint i = 0; i < numFrames; ++i) {
 		for (uint j = 0; j < _celNames.size(); ++j) {
 			readFilename(*xsheet, _celNames[j][i]);
@@ -729,7 +729,7 @@ bool ConversationCel::isVideoDonePlaying() {
 	return _curFrame >= MIN<uint>(_lastFrame, _celNames[0].size()) && _nextFrameTime <= g_nancy->getTotalPlayTime();
 }
 
-ConversationCel::Cel &ConversationCel::loadCel(const Common::String &name, const Common::String &treeName) {
+ConversationCel::Cel &ConversationCel::loadCel(const Common::Path &name, const Common::String &treeName) {
 	// Assumes head and body cels will be named differently
 	if (_celCache.contains(name)) {
 		return _celCache[name];
diff --git a/engines/nancy/action/conversation.h b/engines/nancy/action/conversation.h
index 535242fe8fb..44fb8e0dbe6 100644
--- a/engines/nancy/action/conversation.h
+++ b/engines/nancy/action/conversation.h
@@ -141,7 +141,7 @@ protected:
 	Common::String getRecordTypeName() const override;
 
 	Common::String _videoName;
-	Common::String _paletteName;
+	Common::Path _paletteName;
 	uint _videoFormat = kLargeVideoFormat;
 	uint16 _firstFrame = 0;
 	int16 _lastFrame = 0;
@@ -184,9 +184,9 @@ protected:
 	static const byte kCelOverrideTreeRectsOn	= 2;
 
 	bool isVideoDonePlaying() override;
-	Cel &loadCel(const Common::String &name, const Common::String &treeName);
+	Cel &loadCel(const Common::Path &name, const Common::String &treeName);
 
-	Common::Array<Common::Array<Common::String>> _celNames;
+	Common::Array<Common::Array<Common::Path>> _celNames;
 	Common::Array<Common::String> _treeNames;
 
 	uint16 _frameTime = 0;
@@ -205,7 +205,7 @@ protected:
 
 	Common::Array<RenderedCel> _celRObjects;
 
-	Common::HashMap<Common::String, Cel> _celCache;
+	Common::HashMap<Common::Path, Cel, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _celCache;
 	Common::SharedPtr<ConversationCelLoader> _loaderPtr;
 };
 
diff --git a/engines/nancy/action/inventoryrecords.h b/engines/nancy/action/inventoryrecords.h
index 015fc65b9c1..e9bbb4d52e9 100644
--- a/engines/nancy/action/inventoryrecords.h
+++ b/engines/nancy/action/inventoryrecords.h
@@ -67,7 +67,7 @@ public:
 	void init() override;
 
 	uint16 _objectID = 0;
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<FrameBlitDescription> _blitDescriptions;
 
 	int16 _drawnFrameID = -1;
diff --git a/engines/nancy/action/overlay.cpp b/engines/nancy/action/overlay.cpp
index ba1ceed9b1f..5e01edd9bae 100644
--- a/engines/nancy/action/overlay.cpp
+++ b/engines/nancy/action/overlay.cpp
@@ -38,7 +38,7 @@ namespace Action {
 
 void Overlay::init() {
 	// Autotext overlays need special handling when blitting
-	if (_imageName.hasPrefix("USE_")) {
+	if (_imageName.baseName().hasPrefix("USE_")) {
 		_usesAutotext = true;
 	}
 	
diff --git a/engines/nancy/action/overlay.h b/engines/nancy/action/overlay.h
index 3c228e54dc1..b5c6c090d2f 100644
--- a/engines/nancy/action/overlay.h
+++ b/engines/nancy/action/overlay.h
@@ -52,7 +52,7 @@ public:
 	void readData(Common::SeekableReadStream &stream) override;
 	void execute() override;
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	uint16 _transparency = kPlayOverlayPlain;
 	uint16 _hasSceneChange = kPlayOverlaySceneChange;
diff --git a/engines/nancy/action/puzzle/assemblypuzzle.h b/engines/nancy/action/puzzle/assemblypuzzle.h
index c03d27c3771..90d27639f78 100644
--- a/engines/nancy/action/puzzle/assemblypuzzle.h
+++ b/engines/nancy/action/puzzle/assemblypuzzle.h
@@ -60,7 +60,7 @@ protected:
 		int curRotation = 0;
 	};
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	uint16 _height = 0;
 
diff --git a/engines/nancy/action/puzzle/bballpuzzle.h b/engines/nancy/action/puzzle/bballpuzzle.h
index fa901a6ff88..6adbf6dce2b 100644
--- a/engines/nancy/action/puzzle/bballpuzzle.h
+++ b/engines/nancy/action/puzzle/bballpuzzle.h
@@ -43,7 +43,7 @@ protected:
 	Common::String getRecordTypeName() const override { return "BBallPuzzle"; };
 	bool isViewportRelative() const override { return true; }
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	uint16 _positions = 0;
 	uint16 _powers = 0;
diff --git a/engines/nancy/action/puzzle/bombpuzzle.h b/engines/nancy/action/puzzle/bombpuzzle.h
index 3d40ffd2ebe..cb4fd8a1ee7 100644
--- a/engines/nancy/action/puzzle/bombpuzzle.h
+++ b/engines/nancy/action/puzzle/bombpuzzle.h
@@ -43,7 +43,7 @@ protected:
 	Common::String getRecordTypeName() const override { return "BombPuzzle"; }
 	bool isViewportRelative() const override { return true; }
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<Common::Rect> _wireSrcs;
 	Common::Array<Common::Rect> _wireDests;
 	Common::Array<Common::Rect> _digitSrcs;
diff --git a/engines/nancy/action/puzzle/bulpuzzle.h b/engines/nancy/action/puzzle/bulpuzzle.h
index b19b2016b80..b121da285f0 100644
--- a/engines/nancy/action/puzzle/bulpuzzle.h
+++ b/engines/nancy/action/puzzle/bulpuzzle.h
@@ -49,7 +49,7 @@ protected:
 	Common::String getRecordTypeName() const override { return "BulPuzzle"; }
 	bool isViewportRelative() const override { return true; }
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	uint16 _numCells = 0;
 	uint16 _numPieces = 0;
diff --git a/engines/nancy/action/puzzle/collisionpuzzle.h b/engines/nancy/action/puzzle/collisionpuzzle.h
index f6b24265405..72075ba34d0 100644
--- a/engines/nancy/action/puzzle/collisionpuzzle.h
+++ b/engines/nancy/action/puzzle/collisionpuzzle.h
@@ -73,7 +73,7 @@ protected:
 	Common::Rect getScreenPosition(Common::Point gridPos);
 	void drawGrid();
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	Common::Array<Common::Array<uint16>> _grid;
 	Common::Array<Common::Point> _startLocations;
diff --git a/engines/nancy/action/puzzle/cubepuzzle.h b/engines/nancy/action/puzzle/cubepuzzle.h
index 1a00d0ea872..c92a4008a44 100644
--- a/engines/nancy/action/puzzle/cubepuzzle.h
+++ b/engines/nancy/action/puzzle/cubepuzzle.h
@@ -49,7 +49,7 @@ protected:
 
 	void rotateBase(int dir);
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	Common::Rect _cwCursorDest;
 	Common::Rect _ccwCursorDest;
diff --git a/engines/nancy/action/puzzle/leverpuzzle.h b/engines/nancy/action/puzzle/leverpuzzle.h
index 5fd4c20f510..d5d6a48c1d0 100644
--- a/engines/nancy/action/puzzle/leverpuzzle.h
+++ b/engines/nancy/action/puzzle/leverpuzzle.h
@@ -39,7 +39,7 @@ public:
 	void execute() override;
 	void handleInput(NancyInput &input) override;
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<Common::Array<Common::Rect>> _srcRects;
 	Common::Array<Common::Rect> _destRects;
 	Common::Array<byte> _correctSequence;
diff --git a/engines/nancy/action/puzzle/mazechasepuzzle.h b/engines/nancy/action/puzzle/mazechasepuzzle.h
index c2af6577b12..6d39536d658 100644
--- a/engines/nancy/action/puzzle/mazechasepuzzle.h
+++ b/engines/nancy/action/puzzle/mazechasepuzzle.h
@@ -69,7 +69,7 @@ protected:
 	bool canMove(uint pieceID, WallType direction);
 	void reset();
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	
 	Common::Point _exitPos = Common::Point(-1, -1);
 
diff --git a/engines/nancy/action/puzzle/mouselightpuzzle.h b/engines/nancy/action/puzzle/mouselightpuzzle.h
index 195c68d1ebd..99f1475bdda 100644
--- a/engines/nancy/action/puzzle/mouselightpuzzle.h
+++ b/engines/nancy/action/puzzle/mouselightpuzzle.h
@@ -45,7 +45,7 @@ protected:
 	Common::String getRecordTypeName() const override { return "MouseLightPuzzle"; };
 	bool isViewportRelative() const override { return true; }
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	byte _radius = 0;
 	bool _smoothEdges = false;
 
diff --git a/engines/nancy/action/puzzle/orderingpuzzle.h b/engines/nancy/action/puzzle/orderingpuzzle.h
index 41eb58b1d2a..8dcd6dfe222 100644
--- a/engines/nancy/action/puzzle/orderingpuzzle.h
+++ b/engines/nancy/action/puzzle/orderingpuzzle.h
@@ -58,7 +58,7 @@ protected:
 	void popUp(uint id);
 	void clearAllElements();
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	bool _hasSecondState = false;
 	bool _itemsStayDown = true;
 	bool _needButtonToCheckSuccess = false;
diff --git a/engines/nancy/action/puzzle/overridelockpuzzle.h b/engines/nancy/action/puzzle/overridelockpuzzle.h
index c06db0f9674..fe8bb6b0837 100644
--- a/engines/nancy/action/puzzle/overridelockpuzzle.h
+++ b/engines/nancy/action/puzzle/overridelockpuzzle.h
@@ -52,7 +52,7 @@ protected:
 
 	enum SolveState { kNotSolved, kSolved };
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	byte _popButtons = kButtonsStayDown;
 	byte _randomizeLights = kLightsCircular;
diff --git a/engines/nancy/action/puzzle/peepholepuzzle.cpp b/engines/nancy/action/puzzle/peepholepuzzle.cpp
index b4541a67ab7..746de7bc7a4 100644
--- a/engines/nancy/action/puzzle/peepholepuzzle.cpp
+++ b/engines/nancy/action/puzzle/peepholepuzzle.cpp
@@ -40,7 +40,7 @@ void PeepholePuzzle::init() {
 
 	g_nancy->_resource->loadImage(_innerImageName, _innerImage);
 
-	if (!_buttonsImageName.size()) {
+	if (_buttonsImageName.empty()) {
 		// Empty image name for buttons, use other image as source
 		_buttonsImage.create(_innerImage, _innerImage.getBounds());
 	} else {
diff --git a/engines/nancy/action/puzzle/peepholepuzzle.h b/engines/nancy/action/puzzle/peepholepuzzle.h
index c15702abb1c..f4ef770a51f 100644
--- a/engines/nancy/action/puzzle/peepholepuzzle.h
+++ b/engines/nancy/action/puzzle/peepholepuzzle.h
@@ -47,8 +47,8 @@ protected:
 	void drawInner();
 	void checkButtons();
 
-	Common::String _innerImageName;
-	Common::String _buttonsImageName;
+	Common::Path _innerImageName;
+	Common::Path _buttonsImageName;
 
 	uint16 _transparency = 0;
 
diff --git a/engines/nancy/action/puzzle/raycastpuzzle.cpp b/engines/nancy/action/puzzle/raycastpuzzle.cpp
index e7f637e6782..98f797fe648 100644
--- a/engines/nancy/action/puzzle/raycastpuzzle.cpp
+++ b/engines/nancy/action/puzzle/raycastpuzzle.cpp
@@ -1434,7 +1434,7 @@ void RaycastPuzzle::updateMap() {
 	}
 }
 
-void RaycastPuzzle::createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, const Common::String &textureName) {
+void RaycastPuzzle::createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, const Common::Path &textureName) {
 	Graphics::PixelFormat format = g_nancy->_graphicsManager->getInputPixelFormat();
 	array->resize(8);
 
diff --git a/engines/nancy/action/puzzle/raycastpuzzle.h b/engines/nancy/action/puzzle/raycastpuzzle.h
index 9ab2bc67830..bb9be7d6254 100644
--- a/engines/nancy/action/puzzle/raycastpuzzle.h
+++ b/engines/nancy/action/puzzle/raycastpuzzle.h
@@ -55,7 +55,7 @@ protected:
 
 	void validateMap();
 
-	void createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, const Common::String &textureName);
+	void createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, const Common::Path &textureName);
 
 	void drawMap();
 	void updateMap();
diff --git a/engines/nancy/action/puzzle/rippedletterpuzzle.h b/engines/nancy/action/puzzle/rippedletterpuzzle.h
index 49380dca5e1..ddbe35483dd 100644
--- a/engines/nancy/action/puzzle/rippedletterpuzzle.h
+++ b/engines/nancy/action/puzzle/rippedletterpuzzle.h
@@ -43,7 +43,7 @@ public:
 	void execute() override;
 	void handleInput(NancyInput &input) override;
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<Common::Rect> _srcRects;
 	Common::Array<Common::Rect> _destRects;
 	Common::Rect _rotateHotspot;
diff --git a/engines/nancy/action/puzzle/rotatinglockpuzzle.h b/engines/nancy/action/puzzle/rotatinglockpuzzle.h
index f5210d23c5e..27561c02924 100644
--- a/engines/nancy/action/puzzle/rotatinglockpuzzle.h
+++ b/engines/nancy/action/puzzle/rotatinglockpuzzle.h
@@ -39,7 +39,7 @@ public:
 	void execute() override;
 	void handleInput(NancyInput &input) override;
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<Common::Rect> _srcRects;
 	Common::Array<Common::Rect> _destRects;
 	Common::Array<Common::Rect> _upHotspots;
diff --git a/engines/nancy/action/puzzle/safedialpuzzle.cpp b/engines/nancy/action/puzzle/safedialpuzzle.cpp
index f3d08c86f01..f0f30e3d31b 100644
--- a/engines/nancy/action/puzzle/safedialpuzzle.cpp
+++ b/engines/nancy/action/puzzle/safedialpuzzle.cpp
@@ -63,7 +63,7 @@ void SafeDialPuzzle::updateGraphics() {
 	}
 
 	if (_animState == kReset && _nextAnim < g_nancy->getTotalPlayTime()) {
-		if (_resetImageName.size()) {
+		if (!_resetImageName.empty()) {
 			_animState = kResetAnim;
 		} else {
 			_animState = kNone;
@@ -92,7 +92,7 @@ void SafeDialPuzzle::readData(Common::SeekableReadStream &stream) {
 	readFilename(stream, _imageName2);
 	readFilename(stream, _resetImageName);
 
-	_numInbetweens = (_imageName2.size() ? 1 : 0);
+	_numInbetweens = (!_imageName2.empty() ? 1 : 0);
 
 	uint16 num = 10;
 	if (g_nancy->getGameType() >= kGameTypeNancy4) {
@@ -297,7 +297,7 @@ void SafeDialPuzzle::handleInput(NancyInput &input) {
 
 void SafeDialPuzzle::drawDialFrame(uint frame) {
 	debug("%u", frame);
-	if (frame >= _dialSrcs.size() / 2 && _imageName2.size()) {
+	if (frame >= _dialSrcs.size() / 2 && !_imageName2.empty()) {
 		_drawSurface.blitFrom(_image2, _dialSrcs[frame], _dialDest);
 	} else {
 		_drawSurface.blitFrom(_image1, _dialSrcs[frame], _dialDest);
diff --git a/engines/nancy/action/puzzle/safedialpuzzle.h b/engines/nancy/action/puzzle/safedialpuzzle.h
index 825c274097c..de16056c6f3 100644
--- a/engines/nancy/action/puzzle/safedialpuzzle.h
+++ b/engines/nancy/action/puzzle/safedialpuzzle.h
@@ -49,9 +49,9 @@ protected:
 	void drawDialFrame(uint frame);
 	void pushSequence(uint id);
 
-	Common::String _imageName1;
-	Common::String _imageName2;
-	Common::String _resetImageName;
+	Common::Path _imageName1;
+	Common::Path _imageName2;
+	Common::Path _resetImageName;
 
 	bool _enableWraparound = true;
 
diff --git a/engines/nancy/action/puzzle/setplayerclock.h b/engines/nancy/action/puzzle/setplayerclock.h
index d9273b77d5f..711adfd8587 100644
--- a/engines/nancy/action/puzzle/setplayerclock.h
+++ b/engines/nancy/action/puzzle/setplayerclock.h
@@ -46,7 +46,7 @@ protected:
 
 	void drawTime(uint16 hours, uint16 minutes);
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	Common::Rect _minutesDest;
 	Common::Rect _hoursDest;
diff --git a/engines/nancy/action/puzzle/sliderpuzzle.h b/engines/nancy/action/puzzle/sliderpuzzle.h
index b062f22701f..3c7cffb69d7 100644
--- a/engines/nancy/action/puzzle/sliderpuzzle.h
+++ b/engines/nancy/action/puzzle/sliderpuzzle.h
@@ -46,7 +46,7 @@ public:
 	const SPUZ *_spuzData = nullptr;
 	SliderPuzzleData *_puzzleState = nullptr;
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	uint16 _width = 0;
 	uint16 _height = 0;
 	Common::Array<Common::Array<Common::Rect>> _srcRects;
diff --git a/engines/nancy/action/puzzle/soundequalizerpuzzle.h b/engines/nancy/action/puzzle/soundequalizerpuzzle.h
index 2f28eb9e4de..901d63cfc28 100644
--- a/engines/nancy/action/puzzle/soundequalizerpuzzle.h
+++ b/engines/nancy/action/puzzle/soundequalizerpuzzle.h
@@ -48,7 +48,7 @@ public:
 	void execute() override;
 	void handleInput(NancyInput &input) override;
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	Common::Rect _buttonSrc;
 	Common::Rect _buttonDest;
diff --git a/engines/nancy/action/puzzle/tangrampuzzle.h b/engines/nancy/action/puzzle/tangrampuzzle.h
index 84884add713..cd7d4149d3b 100644
--- a/engines/nancy/action/puzzle/tangrampuzzle.h
+++ b/engines/nancy/action/puzzle/tangrampuzzle.h
@@ -78,8 +78,8 @@ protected:
 
 	bool checkBuffer(const Tile &tile) const;
 
-	Common::String _tileImageName;
-	Common::String _maskImageName;
+	Common::Path _tileImageName;
+	Common::Path _maskImageName;
 
 	Common::Array<Common::Rect> _tileSrcs;
 	Common::Array<Common::Rect> _tileDests;
diff --git a/engines/nancy/action/puzzle/telephone.h b/engines/nancy/action/puzzle/telephone.h
index d6c17c47c4b..e36f007536a 100644
--- a/engines/nancy/action/puzzle/telephone.h
+++ b/engines/nancy/action/puzzle/telephone.h
@@ -52,7 +52,7 @@ public:
 	void execute() override;
 	void handleInput(NancyInput &input) override;
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<Common::Rect> _srcRects;
 	Common::Array<Common::Rect> _destRects;
 	SoundDescription _genericDialogueSound;
diff --git a/engines/nancy/action/puzzle/towerpuzzle.h b/engines/nancy/action/puzzle/towerpuzzle.h
index 6f6a4c06e6f..84ec1cbe31f 100644
--- a/engines/nancy/action/puzzle/towerpuzzle.h
+++ b/engines/nancy/action/puzzle/towerpuzzle.h
@@ -49,7 +49,7 @@ protected:
 
 	void drawRing(uint poleID, uint position, uint ringID, bool clear = false);
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<uint16> _numRingsByDifficulty;
 
 	Common::Array<Common::Rect> _droppedRingSrcs;
diff --git a/engines/nancy/action/puzzle/turningpuzzle.h b/engines/nancy/action/puzzle/turningpuzzle.h
index 0665b2f2125..cb8a9884f98 100644
--- a/engines/nancy/action/puzzle/turningpuzzle.h
+++ b/engines/nancy/action/puzzle/turningpuzzle.h
@@ -51,7 +51,7 @@ protected:
 	void drawObject(uint objectID, uint faceID, uint frameID);
 	void turnLogic(uint objectID);
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	uint16 _numFaces = 0;
 	uint16 _numFramesPerTurn = 0;
diff --git a/engines/nancy/action/puzzle/twodialpuzzle.h b/engines/nancy/action/puzzle/twodialpuzzle.h
index 42accaa8711..6685ad9a73b 100644
--- a/engines/nancy/action/puzzle/twodialpuzzle.h
+++ b/engines/nancy/action/puzzle/twodialpuzzle.h
@@ -44,7 +44,7 @@ protected:
 	Common::String getRecordTypeName() const override { return "TwoDialPuzzle"; }
 	bool isViewportRelative() const override { return true; }
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	bool _isClockwise[2] = { false, false };
 	uint16 _startPositions[2] = { 0, 0 };
diff --git a/engines/nancy/action/secondarymovie.cpp b/engines/nancy/action/secondarymovie.cpp
index b2223db989e..9700d710d51 100644
--- a/engines/nancy/action/secondarymovie.cpp
+++ b/engines/nancy/action/secondarymovie.cpp
@@ -100,11 +100,11 @@ void PlaySecondaryMovie::init() {
 	}
 
 	if (!_decoder->isVideoLoaded()) {
-		if (!_decoder->loadFile(_videoName + (_videoType == kVideoPlaytypeAVF ? ".avf" : ".bik"))) {
-			error("Couldn't load video file %s", _videoName.c_str());
+		if (!_decoder->loadFile(_videoName.append(_videoType == kVideoPlaytypeAVF ? ".avf" : ".bik"))) {
+			error("Couldn't load video file %s", _videoName.toString().c_str());
 		}
 
-		if (_paletteName.size()) {
+		if (!_paletteName.empty()) {
 			GraphicsManager::loadSurfacePalette(_fullFrame, _paletteName);
 			GraphicsManager::loadSurfacePalette(_drawSurface, _paletteName);
 		}
diff --git a/engines/nancy/action/secondarymovie.h b/engines/nancy/action/secondarymovie.h
index b33c0bbbe1a..05e2acb917e 100644
--- a/engines/nancy/action/secondarymovie.h
+++ b/engines/nancy/action/secondarymovie.h
@@ -64,9 +64,9 @@ public:
 	void readData(Common::SeekableReadStream &stream) override;
 	void execute() override;
 
-	Common::String _videoName;
-	Common::String _paletteName;
-	Common::String _bitmapOverlayName;
+	Common::Path _videoName;
+	Common::Path _paletteName;
+	Common::Path _bitmapOverlayName;
 
 	uint16 _videoType = kVideoPlaytypeAVF;
 	uint16 _videoFormat = kLargeVideoFormat;
diff --git a/engines/nancy/action/secondaryvideo.cpp b/engines/nancy/action/secondaryvideo.cpp
index dcb3b98969d..0e9aaf5cc10 100644
--- a/engines/nancy/action/secondaryvideo.cpp
+++ b/engines/nancy/action/secondaryvideo.cpp
@@ -38,8 +38,8 @@ void PlaySecondaryVideo::init() {
 		_decoder.close();
 	}
 
-	if (!_decoder.loadFile(_filename + ".avf")) {
-		error("Couldn't load video file %s", _filename.c_str());
+	if (!_decoder.loadFile(_filename.append(".avf"))) {
+		error("Couldn't load video file %s", _filename.toString().c_str());
 	}
 
 	// Every secondary video frame (in nancy1) plays exactly 12ms slower than what its metadata says.
@@ -47,7 +47,7 @@ void PlaySecondaryVideo::init() {
 	_decoder.addFrameTime(12);
 	_drawSurface.create(_decoder.getWidth(), _decoder.getHeight(), g_nancy->_graphicsManager->getInputPixelFormat());
 
-	if (_paletteFilename.size()) {
+	if (!_paletteFilename.empty()) {
 		GraphicsManager::loadSurfacePalette(_fullFrame, _paletteFilename);
 	}
 
@@ -103,7 +103,7 @@ void PlaySecondaryVideo::updateGraphics() {
 
 		if (_decoder.isPlaying()) {
 			if (_decoder.needsUpdate()) {
-				GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _fullFrame, _paletteFilename.size(), _videoFormat == kSmallVideoFormat);
+				GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _fullFrame, !_paletteFilename.empty(), _videoFormat == kSmallVideoFormat);
 				_needsRedraw = true;
 			}
 
diff --git a/engines/nancy/action/secondaryvideo.h b/engines/nancy/action/secondaryvideo.h
index 92edd6f320e..f460293606d 100644
--- a/engines/nancy/action/secondaryvideo.h
+++ b/engines/nancy/action/secondaryvideo.h
@@ -50,9 +50,9 @@ public:
 	void readData(Common::SeekableReadStream &stream) override;
 	void execute() override;
 
-	Common::String _filename;
-	Common::String _paletteFilename;
-	// Common::String _bitmapOverlayFilename
+	Common::Path _filename;
+	Common::Path _paletteFilename;
+	// Common::Path _bitmapOverlayFilename
 
 	// TVD only
 	uint16 _videoFormat = kLargeVideoFormat;
diff --git a/engines/nancy/cif.cpp b/engines/nancy/cif.cpp
index 3a6dc13fb26..7c46bb511cc 100644
--- a/engines/nancy/cif.cpp
+++ b/engines/nancy/cif.cpp
@@ -67,7 +67,7 @@ static void syncCiftreeInfo(Common::Serializer &ser, CifInfo &info) {
 	uint nameSize = g_nancy->getGameType() <= kGameTypeNancy2 ? 9 : 33;
 	byte name[34];
 	if (ser.isSaving()) {
-		memcpy(name, info.name.c_str(), nameSize);
+		memcpy(name, info.name.toString('/').c_str(), nameSize);
 		name[nameSize] = 0;
 	}
 	
@@ -89,7 +89,7 @@ enum {
 	kHashMapSize = 1024
 };
 
-CifFile::CifFile(Common::SeekableReadStream *stream, const Common::String &name) {
+CifFile::CifFile(Common::SeekableReadStream *stream, const Common::Path &name) {
 	assert(stream);
 	_stream = stream;
 
@@ -126,7 +126,7 @@ Common::SeekableReadStream *CifFile::createReadStream() const {
 	}
 	
 	if (!success) {
-		warning("Failed to read data for CifFile '%s'", _info.name.c_str());
+		warning("Failed to read data for CifFile '%s'", _info.name.toString().c_str());
 		delete[] buf;
 		_stream->clearErr();
 		return nullptr;
@@ -140,7 +140,7 @@ Common::SeekableReadStream *CifFile::createReadStreamRaw() const {
 	byte *buf = new byte[size];
 
 	if (!_stream->seek(_info.dataOffset) || _stream->read(buf, size) < size) {
-		warning("Failed to read data for CifFile '%s'", _info.name.c_str());
+		warning("Failed to read data for CifFile '%s'", _info.name.toString().c_str());
 	}
 	
 	return new Common::MemoryReadStream(buf, size, DisposeAfterUse::YES);
@@ -148,7 +148,7 @@ Common::SeekableReadStream *CifFile::createReadStreamRaw() const {
 
 bool CifFile::sync(Common::Serializer &ser) {
 	if (!ser.matchBytes("CIF FILE WayneSikes", 20)) {
-		warning("Invalid id string found in CifFile '%s'", _info.name.c_str());
+		warning("Invalid id string found in CifFile '%s'", _info.name.toString().c_str());
 		return false;
 	}
 
@@ -163,7 +163,7 @@ bool CifFile::sync(Common::Serializer &ser) {
 	ser.syncAsUint16LE(ver);
 
 	if (ver != 0 && ver != 1) {
-		warning("Unsupported version %d found in CifFile '%s'", ver, _info.name.c_str());
+		warning("Unsupported version %d found in CifFile '%s'", ver, _info.name.toString().c_str());
 		return false;
 	}
 
@@ -177,7 +177,7 @@ bool CifFile::sync(Common::Serializer &ser) {
 	return true;
 }
 
-CifTree::CifTree(Common::SeekableReadStream *stream, const Common::String &name) :
+CifTree::CifTree(Common::SeekableReadStream *stream, const Common::Path &name) :
 		_stream(stream),
 		_name(name) {}
 
@@ -185,12 +185,12 @@ CifTree::~CifTree() {
 	delete _stream;
 }
 
-const CifInfo &CifTree::getCifInfo(const Common::String &name) const {
+const CifInfo &CifTree::getCifInfo(const Common::Path &name) const {
 	return _fileMap[name];
 }
 
 bool CifTree::hasFile(const Common::Path &path) const {
-	return _fileMap.contains(path.toString());
+	return _fileMap.contains(path);
 }
 
 int CifTree::listMembers(Common::ArchiveMemberList &list) const {
@@ -214,7 +214,7 @@ Common::SeekableReadStream *CifTree::createReadStreamForMember(const Common::Pat
 		return nullptr;
 	}
 
-	const CifInfo &info = _fileMap[path.toString()];
+	const CifInfo &info = _fileMap[path];
 	byte *buf = new byte[info.size];
 
 	bool success = true;
@@ -236,7 +236,7 @@ Common::SeekableReadStream *CifTree::createReadStreamForMember(const Common::Pat
 	}
 	
 	if (!success) {
-		warning("Failed to read data for '%s' from CifTree '%s'", info.name.c_str(), _name.c_str());
+		warning("Failed to read data for '%s' from CifTree '%s'", info.name.toString().c_str(), _name.toString().c_str());
 		delete[] buf;
 		_stream->clearErr();
 		return nullptr;
@@ -250,25 +250,28 @@ Common::SeekableReadStream *CifTree::createReadStreamRaw(const Common::Path &pat
 		return nullptr;
 	}
 
-	const CifInfo &info = _fileMap[path.toString()];
+	const CifInfo &info = _fileMap[path];
 	uint32 size = (info.comp == CifInfo::kResCompression ? info.compressedSize : info.size);
 	byte *buf = new byte[size];
 
 	if (!_stream->seek(info.dataOffset) || _stream->read(buf, size) < size) {
-		warning("Failed to read data for '%s' from CifTree '%s'", info.name.c_str(), _name.c_str());
+		warning("Failed to read data for '%s' from CifTree '%s'", info.name.toString().c_str(), _name.toString().c_str());
 	}
 	
 	return new Common::MemoryReadStream(buf, size, DisposeAfterUse::YES);
 }
 
 CifTree *CifTree::makeCifTreeArchive(const Common::String &name, const Common::String &ext) {
-	auto *stream = SearchMan.createReadStreamForMember(name + '.' + ext);
+	Common::Path path(name);
+	path.appendInPlace('.' + ext);
+
+	auto *stream = SearchMan.createReadStreamForMember(path);
 
 	if (!stream) {
 		return nullptr;
 	}
 
-	CifTree *ret = new CifTree(stream, name + '.' + ext);
+	CifTree *ret = new CifTree(stream, path);
 	Common::Serializer ser(stream, nullptr);
 
 	if (!ret->sync(ser)) {
@@ -281,7 +284,7 @@ CifTree *CifTree::makeCifTreeArchive(const Common::String &name, const Common::S
 
 bool CifTree::sync(Common::Serializer &ser) {
 	if (!ser.matchBytes("CIF TREE WayneSikes", 20)) {
-		warning("Invalid id string found in CifTree '%s'", _name.c_str());
+		warning("Invalid id string found in CifTree '%s'", _name.toString().c_str());
 		return false;
 	}
 
@@ -296,7 +299,7 @@ bool CifTree::sync(Common::Serializer &ser) {
 	ser.syncAsUint16LE(ver);
 
 	if (ver != 0 && ver != 1) {
-		warning("Unsupported version %d found in CifTree '%s'", ver, _name.c_str());
+		warning("Unsupported version %d found in CifTree '%s'", ver, _name.toString().c_str());
 		return false;
 	}
 
@@ -336,8 +339,8 @@ bool PatchTree::hasFile(const Common::Path &path) const {
 		for (auto &assoc : _associations) {
 			auto &confManProps = assoc.first;
 			auto &filenames = assoc.second;
-			for (const Common::String &s : filenames) {
-				if (s == path.toString()) {
+			for (const Common::Path &s : filenames) {
+				if (s == path) {
 					bool satisfied = true;
 
 					for (uint i = 0; i < confManProps.size(); ++i) {
diff --git a/engines/nancy/cif.h b/engines/nancy/cif.h
index 7a6751154a1..672d1998100 100644
--- a/engines/nancy/cif.h
+++ b/engines/nancy/cif.h
@@ -47,7 +47,7 @@ struct CifInfo {
 		kResCompression = 2
 	};
 
-	Common::String name;
+	Common::Path name;
 	ResType type = kResTypeEmpty; // ResType
 	ResCompression comp = kResCompressionNone; // ResCompression
 	uint16 width = 0, pitch = 0, height = 0;
@@ -64,7 +64,7 @@ private:
 friend class ResourceManager;
 	CifFile() : _stream(nullptr) {}
 public:
-	CifFile(Common::SeekableReadStream *stream, const Common::String &name);
+	CifFile(Common::SeekableReadStream *stream, const Common::Path &name);
 	~CifFile();
 
 	Common::SeekableReadStream *createReadStream() const;
@@ -82,12 +82,12 @@ class CifTree : public Common::Archive {
 protected:
 friend class ResourceManager;
 	CifTree() : _stream(nullptr) {}
-	CifTree(Common::SeekableReadStream *stream, const Common::String &name);
+	CifTree(Common::SeekableReadStream *stream, const Common::Path &name);
 	virtual ~CifTree();
 
 public:
 	// Used for extracting additional image data for conversation cels (nancy2 and up)
-	const CifInfo &getCifInfo(const Common::String &name) const;
+	const CifInfo &getCifInfo(const Common::Path &name) const;
 
 	// Archive interface
 	bool hasFile(const Common::Path &path) const override;
@@ -96,7 +96,7 @@ public:
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
 	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
 
-	Common::String getName() const { return _name; }
+	Common::Path getName() const { return _name; }
 
 	static CifTree *makeCifTreeArchive(const Common::String &name, const Common::String &ext);
 
@@ -104,21 +104,21 @@ private:
 	bool sync(Common::Serializer &ser);
 	Common::SeekableReadStream *createReadStreamRaw(const Common::Path &path) const;
 
-	Common::String _name;
+	Common::Path _name;
 	Common::SeekableReadStream *_stream;
-	Common::HashMap<Common::String, CifInfo, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _fileMap;
+	Common::HashMap<Common::Path, CifInfo, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _fileMap;
 	Common::Array<CifInfo> _writeFileMap;
 };
 
 // Ciftree that only provides a file if a certain ConfMan flag is true. Used for handling game patches
 class PatchTree : public CifTree {
 public:
-	PatchTree(Common::SeekableReadStream *stream, const Common::String &name) : CifTree(stream, name) {}
+	PatchTree(Common::SeekableReadStream *stream, const Common::Path &name) : CifTree(stream, name) {}
 	virtual ~PatchTree() {}
 
 	bool hasFile(const Common::Path &path) const override;
 
-	Common::Array<Common::Pair<Common::Array<Common::Pair<Common::String, Common::String>>, Common::StringArray>> _associations;
+	Common::Array<Common::Pair<Common::Array<Common::Pair<Common::String, Common::String>>, Common::Array<Common::Path>>> _associations;
 };
 
 } // End of namespace Nancy
diff --git a/engines/nancy/commontypes.cpp b/engines/nancy/commontypes.cpp
index 329630393fc..fed2915ec7c 100644
--- a/engines/nancy/commontypes.cpp
+++ b/engines/nancy/commontypes.cpp
@@ -357,7 +357,7 @@ void StaticData::readData(Common::SeekableReadStream &stream, Common::Language l
 	byte *patchBuf = nullptr;
 	uint32 patchBufSize = 0;
 	Common::Array<Common::Array<Common::String>> confManProps;
-	Common::Array<Common::Array<Common::String>> fileIDs;
+	Common::Array<Common::Array<Common::Path>> fileIDs;
 
 	while (stream.pos() < endPos) {
 		uint32 nextSectionOffset = stream.readUint32LE();
@@ -564,7 +564,7 @@ void StaticData::readData(Common::SeekableReadStream &stream, Common::Language l
 				num2 = stream.readUint16LE();
 				fileIDs[i].resize(num2);
 				for (uint j = 0; j < num2; ++j) {
-					fileIDs[i][j] = stream.readString();
+					fileIDs[i][j] = Common::Path(stream.readString());
 				}
 			}
 
diff --git a/engines/nancy/console.cpp b/engines/nancy/console.cpp
index 5b7ee6e5a11..7b8e5e8f4de 100644
--- a/engines/nancy/console.cpp
+++ b/engines/nancy/console.cpp
@@ -81,7 +81,7 @@ void NancyConsole::postEnter() {
 		if (dec->loadFile(_videoFile)) {
 			Graphics::ManagedSurface surf;
 
-			if (_paletteFile.size()) {
+			if (!_paletteFile.empty()) {
 				GraphicsManager::loadSurfacePalette(surf, _paletteFile);
 			}
 
@@ -98,7 +98,7 @@ void NancyConsole::postEnter() {
 				if (dec->needsUpdate()) {
 					const Graphics::Surface *frame = dec->decodeNextFrame();
 					if (frame) {
-						GraphicsManager::copyToManaged(*frame, surf, _paletteFile.size());
+						GraphicsManager::copyToManaged(*frame, surf, !_paletteFile.empty());
 						g_nancy->_graphicsManager->debugDrawToScreen(surf);
 					}
 				}
@@ -108,7 +108,7 @@ void NancyConsole::postEnter() {
 
 			g_nancy->_graphicsManager->redrawAll();
 		} else {
-			debugPrintf("Failed to load '%s'\n", _videoFile.c_str());
+			debugPrintf("Failed to load '%s'\n", _videoFile.toString(Common::Path::kNativeSeparator).c_str());
 		}
 
 		_videoFile.clear();
@@ -119,7 +119,7 @@ void NancyConsole::postEnter() {
 	if (!_imageFile.empty()) {
 		Graphics::ManagedSurface surf;
 		if (g_nancy->_resource->loadImage(_imageFile, surf)) {
-			if (_paletteFile.size()) {
+			if (!_paletteFile.empty()) {
 				GraphicsManager::loadSurfacePalette(surf, _paletteFile);
 			}
 
@@ -141,7 +141,7 @@ void NancyConsole::postEnter() {
 
 			g_nancy->_graphicsManager->redrawAll();
 		} else {
-			debugPrintf("Failed to load image '%s'\n", _imageFile.c_str());
+			debugPrintf("Failed to load image '%s'\n", _imageFile.toString().c_str());
 		}
 
 		_imageFile.clear();
@@ -173,7 +173,7 @@ bool NancyConsole::Cmd_ciftreeExport(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::StringArray files;
+	Common::Array<Common::Path> files;
 
 	for (int i = 2; i < argc; ++i) {
 		files.push_back(argv[i]);
@@ -193,10 +193,15 @@ bool NancyConsole::Cmd_cifList(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::Array<Common::String> list;
+	Common::Array<Common::Path> list;
 	g_nancy->_resource->list((argc == 2 ? "" : argv[2]), list, (CifInfo::ResType)atoi(argv[1]));
 
-	debugPrintColumns(list);
+	Common::StringArray listStr;
+	listStr.resize(list.size());
+	for (unsigned int i = 0; i < list.size(); i++) {
+		listStr[i] = list[i].toString();
+	}
+	debugPrintColumns(listStr);
 
 	return true;
 }
@@ -251,7 +256,7 @@ bool NancyConsole::Cmd_chunkExport(int argc, const char **argv) {
 	filename += '_';
 	filename += argv[2];
 	filename += ".dat";
-	dumpfile.open(filename);
+	dumpfile.open(Common::Path(filename));
 	dumpfile.write(buf, size);
 	dumpfile.close();
 	delete iff;
@@ -354,7 +359,7 @@ bool NancyConsole::Cmd_exportImage(int argc, const char **argv) {
 	Graphics::ManagedSurface surf;
 	if (g_nancy->_resource->loadImage(argv[1], surf)) {
 		Common::DumpFile f;
-		if (!f.open(Common::String(argv[1]) + ".bmp")) {
+		if (!f.open(Common::Path(argv[1]).appendInPlace(".bmp"))) {
 			debugPrintf("Couldn't open file for writing!");
 
 			return true;
@@ -376,7 +381,7 @@ bool NancyConsole::Cmd_playVideo(int argc, const char **argv) {
 		}
 
 		_videoFile = argv[1];
-		_videoFile += ".avf";
+		_videoFile.appendInPlace(".avf");
 		_paletteFile = argv[2];
 		return cmdExit(0, nullptr);
 	} else {
@@ -387,7 +392,7 @@ bool NancyConsole::Cmd_playVideo(int argc, const char **argv) {
 		}
 
 		_videoFile = argv[1];
-		_videoFile += ".avf";
+		_videoFile.appendInPlace(".avf");
 		return cmdExit(0, nullptr);
 	}
 }
@@ -412,7 +417,7 @@ bool NancyConsole::Cmd_playSound(int argc, const char **argv) {
 	}
 
 	Common::File *f = new Common::File;
-	if (!f->open(Common::String(argv[1]) + ".his")) {
+	if (!f->open(Common::Path(argv[1]).appendInPlace(".his"))) {
 		debugPrintf("Failed to open '%s.his'\n", argv[1]);
 		delete f;
 		return true;
@@ -442,7 +447,7 @@ bool NancyConsole::Cmd_loadScene(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::String sceneName = Common::String::format("S%s", argv[1]);
+	Common::Path sceneName(Common::String::format("S%s", argv[1]));
 	IFF *iff = g_nancy->_resource->loadIFF(sceneName);
 	if (!iff) {
 		debugPrintf("Invalid scene S%s\n", argv[1]);
@@ -610,7 +615,7 @@ bool NancyConsole::Cmd_listActionRecords(int argc, const char **argv) {
 		Common::Queue<uint> unknownTypes;
 		Common::Queue<Common::String> unknownDescs;
 		Common::SeekableReadStream *chunk;
-		IFF *sceneIFF = g_nancy->_resource->loadIFF("S" + s);
+		IFF *sceneIFF = g_nancy->_resource->loadIFF(Common::Path("S" + s));
 		if (!sceneIFF) {
 			debugPrintf("Invalid scene S%s\n", argv[1]);
 			return true;
@@ -692,15 +697,15 @@ bool NancyConsole::Cmd_scanForActionRecordType(int argc, const char **argv) {
 		}
 	}
 
-	Common::Array<Common::String> list;
+	Common::Array<Common::Path> list;
 	// Action records only appear in the ciftree and promotree
 	g_nancy->_resource->list("ciftree", list, CifInfo::kResTypeScript);
 	g_nancy->_resource->list("promotree", list, CifInfo::kResTypeScript);
 
 	char descBuf[0x30];
 
-	for (Common::String &cifName : list) {
-		Common::String name = cifName;
+	for (Common::Path &cifName : list) {
+		Common::String name = cifName.baseName();
 		if (name.hasSuffixIgnoreCase(".iff")) {
 			name = name.substr(0, name.size() - 4);
 		}
@@ -734,7 +739,7 @@ bool NancyConsole::Cmd_scanForActionRecordType(int argc, const char **argv) {
 						chunk->seek(0);
 						chunk->read(descBuf, 0x30);
 						descBuf[0x2F] = '\0';
-						debugPrintf("%s: ACT chunk %u, %s\n", cifName.c_str(), num, descBuf);
+						debugPrintf("%s: ACT chunk %u, %s\n", cifName.toString().c_str(), num, descBuf);
 					}
 
 					++num;
diff --git a/engines/nancy/console.h b/engines/nancy/console.h
index 0d8830d9653..8a283f7d6ec 100644
--- a/engines/nancy/console.h
+++ b/engines/nancy/console.h
@@ -71,9 +71,9 @@ private:
 	void printActionRecord(const Nancy::Action::ActionRecord *record, bool noDependencies = false);
 	void recursePrintDependencies(const Nancy::Action::DependencyRecord &record);
 
-	Common::String _videoFile;
-	Common::String _imageFile;
-	Common::String _paletteFile;
+	Common::Path _videoFile;
+	Common::Path _imageFile;
+	Common::Path _paletteFile;
 };
 
 } // End of namespace Nancy
diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index eea5ee62bfb..e46823127fa 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -355,7 +355,7 @@ CRED::CRED(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readFilename(*chunkStream, imageName);
 
 	textNames.resize(isVampire ? 7 : 1);
-	for (Common::String &str : textNames) {
+	for (Common::Path &str : textNames) {
 		readFilename(*chunkStream, str);
 	}
 
@@ -698,16 +698,17 @@ RCPR::RCPR(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	uColor10[1] = chunkStream->readByte();
 	uColor10[2] = chunkStream->readByte();
 
-	Common::String tmp;
+	Common::Path tmp;
 	while (chunkStream->pos() < chunkStream->size()) {
 		readFilename(*chunkStream, tmp);
-		if (tmp.hasPrefixIgnoreCase("Wall")) {
+		Common::String baseName(tmp.baseName());
+		if (baseName.hasPrefixIgnoreCase("Wall")) {
 			wallNames.push_back(tmp);
-		} else if (tmp.hasPrefixIgnoreCase("SpW")) {
+		} else if (baseName.hasPrefixIgnoreCase("SpW")) {
 			specialWallNames.push_back(tmp);
-		} else if (tmp.hasPrefixIgnoreCase("Ceil")) {
+		} else if (baseName.hasPrefixIgnoreCase("Ceil")) {
 			ceilingNames.push_back(tmp);
-		} else if (tmp.hasPrefixIgnoreCase("Floor")) {
+		} else if (baseName.hasPrefixIgnoreCase("Floor")) {
 			floorNames.push_back(tmp);
 		}
 	}
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index c623a5c4e5b..29d6c02e762 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -39,8 +39,8 @@ struct BSUM : public EngineData {
 
 	byte header[90];
 
-	Common::String conversationTextsFilename;
-	Common::String autotextFilename;
+	Common::Path conversationTextsFilename;
+	Common::Path autotextFilename;
 
 	// Game start section
 	SceneChangeDescription firstScene;
@@ -132,8 +132,8 @@ struct INV : public EngineData {
 
 	uint16 captionAutoClearTime = 3000;
 
-	Common::String inventoryBoxIconsImageName;
-	Common::String inventoryCursorsImageName;
+	Common::Path inventoryBoxIconsImageName;
+	Common::Path inventoryCursorsImageName;
 
 	SoundDescription cantSound;
 	Common::String cantText;
@@ -181,8 +181,8 @@ struct MAP : public EngineData {
 
 	MAP(Common::SeekableReadStream *chunkStream);
 
-	Common::Array<Common::String> mapNames;
-	Common::Array<Common::String> mapPaletteNames;
+	Common::Array<Common::Path> mapNames;
+	Common::Array<Common::Path> mapPaletteNames;
 	Common::Array<SoundDescription> sounds;
 
 	// Globe section, TVD only
@@ -207,7 +207,7 @@ struct MAP : public EngineData {
 struct HELP : public EngineData {
 	HELP(Common::SeekableReadStream *chunkStream);
 
-	Common::String imageName;
+	Common::Path imageName;
 	Common::Rect buttonDest;
 	Common::Rect buttonSrc;
 	Common::Rect buttonHoverSrc;
@@ -217,8 +217,8 @@ struct HELP : public EngineData {
 struct CRED : public EngineData {
 	CRED(Common::SeekableReadStream *chunkStream);
 
-	Common::String imageName;
-	Common::Array<Common::String> textNames;
+	Common::Path imageName;
+	Common::Array<Common::Path> textNames;
 	Common::Rect textScreenPosition;
 	uint16 updateTime;
 	uint16 pixelsToScroll;
@@ -229,7 +229,7 @@ struct CRED : public EngineData {
 struct MENU : public EngineData {
 	MENU(Common::SeekableReadStream *chunkStream);
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	Common::Array<Common::Rect> _buttonDests;
 	Common::Array<Common::Rect> _buttonDownSrcs;
 	Common::Array<Common::Rect> _buttonHighlightSrcs;
@@ -240,7 +240,7 @@ struct MENU : public EngineData {
 struct SET : public EngineData {
 	SET(Common::SeekableReadStream *chunkStream);
 
-	Common::String _imageName;
+	Common::Path _imageName;
 	// Common::Rect _scrollbarsBounds
 	Common::Array<Common::Rect> _scrollbarBounds;
 	Common::Array<Common::Rect> _buttonDests;
@@ -259,7 +259,7 @@ struct SET : public EngineData {
 struct LOAD : public EngineData {
 	LOAD(Common::SeekableReadStream *chunkStream);
 
-	Common::String _imageName;
+	Common::Path _imageName;
 
 	int16 _mainFontID;
 	int16 _highlightFontID;
@@ -291,7 +291,7 @@ struct LOAD : public EngineData {
 	Common::Rect _cancelButtonHighlightSrc;
 	Common::Rect _cancelButtonDisabledSrc;
 
-	Common::String _gameSavedPopup;
+	Common::Path _gameSavedPopup;
 	// Common::Rect _gameSavedBounds
 };
 
@@ -301,7 +301,7 @@ struct SDLG : public EngineData {
 	struct Dialog {
 		Dialog(Common::SeekableReadStream *chunkStream);
 		
-		Common::String imageName;
+		Common::Path imageName;
 
 		Common::Rect yesDest;
 		Common::Rect noDest;
@@ -421,17 +421,17 @@ struct RCPR : public EngineData {
 	byte transparentWallColor[3];
 	byte uColor10[3];
 
-	Common::Array<Common::String> wallNames;
-	Common::Array<Common::String> specialWallNames;
-	Common::Array<Common::String> ceilingNames;
-	Common::Array<Common::String> floorNames;
+	Common::Array<Common::Path> wallNames;
+	Common::Array<Common::Path> specialWallNames;
+	Common::Array<Common::Path> ceilingNames;
+	Common::Array<Common::Path> floorNames;
 };
 
 // Contains the name and dimensions of an image.
 struct ImageChunk : public EngineData {
 	ImageChunk(Common::SeekableReadStream *chunkStream);
 
-	Common::String imageName;
+	Common::Path imageName;
 	uint16 width;
 	uint16 height;
 };
diff --git a/engines/nancy/font.cpp b/engines/nancy/font.cpp
index a4f458053e8..f6116580006 100644
--- a/engines/nancy/font.cpp
+++ b/engines/nancy/font.cpp
@@ -34,7 +34,7 @@ void Font::read(Common::SeekableReadStream &stream) {
 	_fontHeight = 0;
 	uint16 numCharacters = 78;
 
-	Common::String imageName;
+	Common::Path imageName;
 	readFilename(stream, imageName);
 
 	g_nancy->_resource->loadImage(imageName, _image);
diff --git a/engines/nancy/graphics.cpp b/engines/nancy/graphics.cpp
index 19583d9aa66..a9a4f4753c5 100644
--- a/engines/nancy/graphics.cpp
+++ b/engines/nancy/graphics.cpp
@@ -213,9 +213,9 @@ void GraphicsManager::suppressNextDraw() {
 	_isSuppressed = true;
 }
 
-void GraphicsManager::loadSurfacePalette(Graphics::ManagedSurface &inSurf, const Common::String paletteFilename, uint paletteStart, uint paletteSize) {
+void GraphicsManager::loadSurfacePalette(Graphics::ManagedSurface &inSurf, const Common::Path &paletteFilename, uint paletteStart, uint paletteSize) {
 	Common::File f;
-	if (f.open(paletteFilename + ".bmp")) {
+	if (f.open(paletteFilename.append(".bmp"))) {
 		Image::BitmapDecoder dec;
 		if (dec.loadStream(f)) {
 			inSurf.setPalette(dec.getPalette(), paletteStart, paletteSize);
diff --git a/engines/nancy/graphics.h b/engines/nancy/graphics.h
index 55fc27beb8e..3b80a8de9af 100644
--- a/engines/nancy/graphics.h
+++ b/engines/nancy/graphics.h
@@ -61,7 +61,7 @@ public:
 	void grabViewportObjects(Common::Array<RenderObject *> &inArray);
 	void screenshotScreen(Graphics::ManagedSurface &inSurf);
 
-	static void loadSurfacePalette(Graphics::ManagedSurface &inSurf, const Common::String paletteFilename, uint paletteStart = 0, uint paletteSize = 256);
+	static void loadSurfacePalette(Graphics::ManagedSurface &inSurf, const Common::Path &paletteFilename, uint paletteStart = 0, uint paletteSize = 256);
 	static void copyToManaged(const Graphics::Surface &src, Graphics::ManagedSurface &dst, bool verticalFlip = false, bool doubleSize = false);
 	static void copyToManaged(void *src, Graphics::ManagedSurface &dst, uint srcW, uint srcH, const Graphics::PixelFormat &format, bool verticalFlip = false, bool doubleSize = false);
 
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 2a162252fb6..8b97ead58d3 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -375,7 +375,7 @@ void NancyEngine::pauseEngineIntern(bool pause) {
 
 void NancyEngine::bootGameEngine() {
 	// Load paths
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "game");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "datafiles");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "ciftree");
@@ -464,7 +464,7 @@ void NancyEngine::bootGameEngine() {
 
 	// Load convo texts and autotext
 	auto *bsum = GetEngineData(BSUM);
-	if (bsum && bsum->conversationTextsFilename.size() && bsum->autotextFilename.size())  {
+	if (bsum && !bsum->conversationTextsFilename.empty() && !bsum->autotextFilename.empty()) {
 		iff = _resource->loadIFF(bsum->conversationTextsFilename);
 		if (!iff) {
 			error("Could not load CONVO IFF");
diff --git a/engines/nancy/renderobject.cpp b/engines/nancy/renderobject.cpp
index d960c6a6787..0ec90398d59 100644
--- a/engines/nancy/renderobject.cpp
+++ b/engines/nancy/renderobject.cpp
@@ -95,7 +95,7 @@ void RenderObject::grabPalette(byte *colors, uint paletteStart, uint paletteSize
 	}
 }
 
-void RenderObject::setPalette(const Common::String &paletteName, uint paletteStart, uint paletteSize) {
+void RenderObject::setPalette(const Common::Path &paletteName, uint paletteStart, uint paletteSize) {
 	GraphicsManager::loadSurfacePalette(_drawSurface, paletteName, paletteStart, paletteSize);
 	_needsRedraw = true;
 }
diff --git a/engines/nancy/renderobject.h b/engines/nancy/renderobject.h
index 4ae27fe9fbc..6cf5d2886cf 100644
--- a/engines/nancy/renderobject.h
+++ b/engines/nancy/renderobject.h
@@ -52,7 +52,7 @@ public:
 
 	// Only used by The Vampire Diaries
 	void grabPalette(byte *colors, uint paletteStart = 0, uint paletteSize = 256);
-	void setPalette(const Common::String &paletteName, uint paletteStart = 0, uint paletteSize = 256);
+	void setPalette(const Common::Path &paletteName, uint paletteStart = 0, uint paletteSize = 256);
 	void setPalette(const byte *colors, uint paletteStart = 0, uint paletteSize = 256);
 
 	bool hasMoved() const { return _previousScreenPosition != _screenPosition; }
diff --git a/engines/nancy/resource.cpp b/engines/nancy/resource.cpp
index 85a90597240..e9dd82fc072 100644
--- a/engines/nancy/resource.cpp
+++ b/engines/nancy/resource.cpp
@@ -35,17 +35,18 @@ static char treePrefix[] = "_tree_";
 
 namespace Nancy {
 
-bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSurface &surf, const Common::String treeName, Common::Rect *outSrc, Common::Rect *outDest) {
+bool ResourceManager::loadImage(const Common::Path &name, Graphics::ManagedSurface &surf, const Common::String &treeName, Common::Rect *outSrc, Common::Rect *outDest) {
 	// Detect and load autotext surfaces
-	if (name.hasPrefixIgnoreCase("USE_")) {
+	Common::String baseName(name.baseName());
+	if (baseName.hasPrefixIgnoreCase("USE_")) {
 		int surfID = -1;
 
-		if (name.hasPrefixIgnoreCase("USE_AUTOTEXT")) {
-			surfID = name[12] - '1';
-		} else if (name.hasPrefixIgnoreCase("USE_AUTOJOURNAL")) { // nancy6/7
-			surfID = name.substr(15).asUint64() + 2;
-		} else if (name.hasPrefixIgnoreCase("USE_AUTOLIST")) { // nancy8
-			surfID = name.substr(12).asUint64() + 2;
+		if (baseName.hasPrefixIgnoreCase("USE_AUTOTEXT")) {
+			surfID = baseName[12] - '1';
+		} else if (baseName.hasPrefixIgnoreCase("USE_AUTOJOURNAL")) { // nancy6/7
+			surfID = baseName.substr(15).asUint64() + 2;
+		} else if (baseName.hasPrefixIgnoreCase("USE_AUTOLIST")) { // nancy8
+			surfID = baseName.substr(12).asUint64() + 2;
 		}
 
 		if (surfID >= 0) {
@@ -59,7 +60,7 @@ bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSur
 
 	// First, check for external .bmp (TVD only; can also be enabled via a hidden ConfMan option)
 	if (g_nancy->getGameType() == kGameTypeVampire || ConfMan.getBool("external_bmp", ConfMan.getActiveDomainName())) {
-		stream = SearchMan.createReadStreamForMember(name + ".bmp");
+		stream = SearchMan.createReadStreamForMember(name.append(".bmp"));
 		if (stream) {
 			// Found external image
 			Image::BitmapDecoder bmpDec;
@@ -76,7 +77,7 @@ bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSur
 	
 	// Check for loose .cif images. This bypasses tree search even with a provided treeName
 	if (!stream) {
-		stream = SearchMan.createReadStreamForMember(name + ".cif");
+		stream = SearchMan.createReadStreamForMember(name.append(".cif"));
 		if (stream) {
 			// .cifs are compressed, so we need to extract
 			CifFile cifFile(stream, name); // cifFile takes ownership of the current stream
@@ -93,16 +94,16 @@ bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSur
 			upper.toUppercase();
 			const CifTree *tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 
-			stream = tree->createReadStreamForMember(name);
+			stream = tree->createReadStreamForMember(Common::Path(name));
 			info = tree->getCifInfo(name);
 		}
 
 		if (!stream) {
 			// Tree name was not provided, or lookup failed. Use SearchMan
-			stream = SearchMan.createReadStreamForMember(name);
+			stream = SearchMan.createReadStreamForMember(Common::Path(name));
 
 			if (!stream) {
-				warning("Couldn't open image file %s", name.c_str());
+				warning("Couldn't open image file %s", name.toString().c_str());
 				return false;
 			}
 
@@ -112,7 +113,7 @@ bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSur
 				// No provided tree name, check inside every loaded tree
 				Common::String upper = _cifTreeNames[i];
 				upper.toUppercase();
-				if (SearchMan.getArchive(treePrefix + upper)->hasFile(name)) {
+				if (SearchMan.getArchive(treePrefix + upper)->hasFile(Common::Path(name))) {
 					tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 					break;
 				}
@@ -129,13 +130,13 @@ bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSur
 
 	// Sanity checks
 	if (info.type != CifInfo::kResTypeImage) {
-		warning("Resource '%s' is not an image", name.c_str());
+		warning("Resource '%s' is not an image", name.toString().c_str());
 		delete stream;
 		return false;
 	}
 
 	if (info.depth != 16) {
-		warning("Image '%s' has unsupported depth %i", name.c_str(), info.depth);
+		warning("Image '%s' has unsupported depth %i", name.toString().c_str(), info.depth);
 		delete stream;
 		return false;
 	}
@@ -166,9 +167,9 @@ bool ResourceManager::loadImage(const Common::String &name, Graphics::ManagedSur
 	return true;
 }
 
-IFF *ResourceManager::loadIFF(const Common::String &name) {
+IFF *ResourceManager::loadIFF(const Common::Path &name) {
 	// First, try to load external .cif
-	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name + ".cif");
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name.append(".cif"));
 	if (stream) {
 		// .cifs are compressed, so we need to extract
 		CifFile cifFile(stream, name); // cifFile takes ownership of the current stream
@@ -177,11 +178,11 @@ IFF *ResourceManager::loadIFF(const Common::String &name) {
 
 	if (!stream) {
 		// Then, look for external .iff. These are uncompressed
-		stream = SearchMan.createReadStreamForMember(name + ".iff");
+		stream = SearchMan.createReadStreamForMember(name.append(".iff"));
 
 		// Finally, look inside ciftrees
 		if (!stream) {
-			stream = SearchMan.createReadStreamForMember(name);
+			stream = SearchMan.createReadStreamForMember(Common::Path(name));
 		}
 	}
 
@@ -213,7 +214,7 @@ PatchTree *ResourceManager::readPatchTree(Common::SeekableReadStream *stream, co
 		return nullptr;
 	}
 
-	PatchTree *tree = new PatchTree(stream, name);
+	PatchTree *tree = new PatchTree(stream, Common::Path(name));
 	Common::Serializer ser(stream, nullptr);
 
 	if (!tree->sync(ser)) {
@@ -228,7 +229,7 @@ PatchTree *ResourceManager::readPatchTree(Common::SeekableReadStream *stream, co
 	return tree;
 }
 
-Common::String ResourceManager::getCifDescription(const Common::String &treeName, const Common::String &name) const {
+Common::String ResourceManager::getCifDescription(const Common::String &treeName, const Common::Path &name) const {
 	const CifTree *tree = nullptr;
 	if (treeName.size()) {
 		Common::String upper = treeName;
@@ -253,7 +254,7 @@ Common::String ResourceManager::getCifDescription(const Common::String &treeName
 	const CifInfo &info = tree->getCifInfo(name);
 
 	Common::String desc;
-	desc = Common::String::format("Name: %s\n", info.name.c_str());
+	desc = Common::String::format("Name: %s\n", info.name.toString().c_str());
 	desc += Common::String::format("Type: %i\n", info.type);
 	desc += Common::String::format("Compression: %i\n", info.comp);
 	desc += Common::String::format("Size: %i\n", info.size);
@@ -266,7 +267,7 @@ Common::String ResourceManager::getCifDescription(const Common::String &treeName
 	return desc;
 }
 
-void ResourceManager::list(const Common::String &treeName, Common::StringArray &outList, CifInfo::ResType type) const {
+void ResourceManager::list(const Common::String &treeName, Common::Array<Common::Path> &outList, CifInfo::ResType type) const {
 	if (treeName.size()) {
 		Common::String upper = treeName;
 		upper.toUppercase();
@@ -294,14 +295,14 @@ void ResourceManager::list(const Common::String &treeName, Common::StringArray &
 	}
 }
 
-bool ResourceManager::exportCif(const Common::String &treeName, const Common::String &name) {
+bool ResourceManager::exportCif(const Common::String &treeName, const Common::Path &name) {
 	if (!SearchMan.hasFile(name)) {
 		return false;
 	}
 
 	// First, look for a loose .cif file
 	CifInfo info;
-	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name + ".cif");
+	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name.append(".cif"));
 	if (stream) {
 		// .cifs are compressed, so we need to extract
 		CifFile cifFile(stream, name); // cifFile takes ownership of the current stream
@@ -311,7 +312,7 @@ bool ResourceManager::exportCif(const Common::String &treeName, const Common::St
 
 	if (!stream) {
 		// Then, look for an external .iff. These are uncompressed
-		stream = SearchMan.createReadStreamForMember(name + ".iff");
+		stream = SearchMan.createReadStreamForMember(name.append(".iff"));
 		if (stream) {
 			info.comp = CifInfo::kResCompressionNone;
 			info.type = CifInfo::kResTypeScript;
@@ -337,7 +338,7 @@ bool ResourceManager::exportCif(const Common::String &treeName, const Common::St
 				// would regularly not be in a ciftree (e.g. sounds)
 				stream = SearchMan.createReadStreamForMember(name);
 				if (!stream) {
-					warning("Couldn't open resource %s", name.c_str());
+					warning("Couldn't open resource %s", name.toString().c_str());
 					return false;
 				}
 
@@ -353,7 +354,7 @@ bool ResourceManager::exportCif(const Common::String &treeName, const Common::St
 	file._info = info;
 
 	Common::DumpFile dump;
-	dump.open(name + ".cif");
+	dump.open(name.append(".cif"));
 
 	Common::Serializer ser(nullptr, &dump);
 	file.sync(ser);
@@ -365,7 +366,7 @@ bool ResourceManager::exportCif(const Common::String &treeName, const Common::St
 	return true;
 }
 
-bool ResourceManager::exportCifTree(const Common::String &treeName, const Common::StringArray &names) {
+bool ResourceManager::exportCifTree(const Common::String &treeName, const Common::Array<Common::Path> &names) {
 	Common::Array<Common::SeekableReadStream *> resStreams;
 	CifTree file;
 
@@ -386,23 +387,24 @@ bool ResourceManager::exportCifTree(const Common::String &treeName, const Common
 	}
 
 	for (uint i = 0; i < names.size(); ++i) {
+		const Common::Path &path = names[i];
 		// First, look for loose .cif files
 		CifInfo info;
-		Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(names[i] + ".cif");
+		Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(path.append(".cif"));
 		if (stream) {
 			// .cifs are compressed, so we need to extract
-			CifFile cifFile(stream, names[i]); // cifFile takes ownership of the current stream
+			CifFile cifFile(stream, path); // cifFile takes ownership of the current stream
 			stream = cifFile.createReadStreamRaw();
 			info = cifFile._info;
 		}
 
 		if (!stream) {
 			// Then, look for external .iff. These are uncompressed
-			stream = SearchMan.createReadStreamForMember(names[i] + ".iff");
+			stream = SearchMan.createReadStreamForMember(path.append(".iff"));
 			if (stream) {
 				info.comp = CifInfo::kResCompressionNone;
 				info.type = CifInfo::kResTypeScript;
-				info.name = names[i];
+				info.name = path;
 				info.compressedSize = info.size = stream->size();
 			} else {
 				// Look inside ciftrees
@@ -410,27 +412,27 @@ bool ResourceManager::exportCifTree(const Common::String &treeName, const Common
 				for (uint j = 0; j < _cifTreeNames.size(); ++j) {
 					Common::String upper = _cifTreeNames[j];
 					upper.toUppercase();
-					if (SearchMan.getArchive(treePrefix + upper)->hasFile(names[i])) {
+					if (SearchMan.getArchive(treePrefix + upper)->hasFile(path)) {
 						tree = (const CifTree *)SearchMan.getArchive(treePrefix + upper);
 						break;
 					}
 				}
 
 				if (tree) {
-					stream = tree->createReadStreamRaw(names[i]);
-					info = tree->getCifInfo(names[i]);
+					stream = tree->createReadStreamRaw(path);
+					info = tree->getCifInfo(path);
 				} else {
 					// Finally, use SearchMan to get a loose file. This is useful if we want to add files that
 					// would regularly not be in a ciftree (e.g. sounds)
-					stream = SearchMan.createReadStreamForMember(names[i]);
+					stream = SearchMan.createReadStreamForMember(path);
 					if (!stream) {
-						warning("Couldn't open resource %s", names[i].c_str());
+						warning("Couldn't open resource %s", path.toString().c_str());
 						continue;
 					}
 
 					info.comp = CifInfo::kResCompressionNone;
 					info.type = CifInfo::kResTypeScript;
-					info.name = names[i];
+					info.name = path;
 					info.compressedSize = info.size = stream->size();
 				}
 			}
@@ -449,7 +451,7 @@ bool ResourceManager::exportCifTree(const Common::String &treeName, const Common
 	}
 
 	Common::DumpFile dump;
-	dump.open(treeName + ".dat");
+	dump.open(Common::Path(treeName + ".dat"));
 
 	Common::Serializer ser(nullptr, &dump);
 	file.sync(ser);
diff --git a/engines/nancy/resource.h b/engines/nancy/resource.h
index 459dd981677..515f92dd593 100644
--- a/engines/nancy/resource.h
+++ b/engines/nancy/resource.h
@@ -43,10 +43,10 @@ public:
 	// Load an image resource. Can be either external .bmp file, or raw image data embedded inside a ciftree
 	// Ciftree images may have additional data dictating how they need to be blitted on screen (see ConversationCel).
 	// This is accessed via the outSrc/outDest parameters.
-	bool loadImage(const Common::String &name, Graphics::ManagedSurface &surf, const Common::String treeName = "", Common::Rect *outSrc = nullptr, Common::Rect *outDest = nullptr);
+	bool loadImage(const Common::Path &name, Graphics::ManagedSurface &surf, const Common::String &treeName = Common::String(), Common::Rect *outSrc = nullptr, Common::Rect *outDest = nullptr);
 	
 	// Loads a single IFF file. These can either be inside standalone .cif files, or embedded inside a ciftree
-	IFF *loadIFF(const Common::String &name);
+	IFF *loadIFF(const Common::Path &name);
 
 	// Load a new ciftree
 	bool readCifTree(const Common::String &name, const Common::String &ext, int priority);
@@ -56,16 +56,16 @@ private:
 	// Debug functions
 
 	// Return a human-readable description of a single CIF file.
-	Common::String getCifDescription(const Common::String &treeName, const Common::String &name) const;
+	Common::String getCifDescription(const Common::String &treeName, const Common::Path &name) const;
 
 	// Return a list of all resources of a certain type (does not list external files)
-	void list(const Common::String &treeName, Common::StringArray &outList, CifInfo::ResType type) const;
+	void list(const Common::String &treeName, Common::Array<Common::Path> &outList, CifInfo::ResType type) const;
 
 	// Exports a single resource as a standalone .cif file
-	bool exportCif(const Common::String &treeName, const Common::String &name);
+	bool exportCif(const Common::String &treeName, const Common::Path &name);
 
 	// Exports a collection of resources as a ciftree
-	bool exportCifTree(const Common::String &treeName, const Common::StringArray &names);
+	bool exportCifTree(const Common::String &treeName, const Common::Array<Common::Path> &names);
 
 private:
 	Common::Array<Common::String> _cifTreeNames;
diff --git a/engines/nancy/sound.cpp b/engines/nancy/sound.cpp
index fba51b778ea..596da39a6a2 100644
--- a/engines/nancy/sound.cpp
+++ b/engines/nancy/sound.cpp
@@ -303,7 +303,8 @@ void SoundManager::loadSound(const SoundDescription &description, SoundEffectDes
 		*effectData = nullptr;
 	}
 
-	Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(description.name + (g_nancy->getGameType() == kGameTypeVampire ? ".dwd" : ".his"));
+	Common::Path path(description.name + (g_nancy->getGameType() == kGameTypeVampire ? ".dwd" : ".his"));
+	Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(path);
 	if (file) {
 		_channels[description.channelID].stream = makeHISStream(file, DisposeAfterUse::YES, description.samplesPerSec);
 	}
diff --git a/engines/nancy/state/loadsave.cpp b/engines/nancy/state/loadsave.cpp
index 7346bbf269c..06bbff6eeda 100644
--- a/engines/nancy/state/loadsave.cpp
+++ b/engines/nancy/state/loadsave.cpp
@@ -231,7 +231,7 @@ void LoadSaveMenu::init() {
 		Common::Point(), g_nancy->_graphicsManager->getTransColor());
 
 	// Load the "Your game has been saved" popup graphic
-	if (_loadSaveData->_gameSavedPopup.size()) {
+	if (!_loadSaveData->_gameSavedPopup.empty()) {
 		g_nancy->_resource->loadImage(_loadSaveData->_gameSavedPopup, _successOverlay._drawSurface);
 		Common::Rect destBounds = Common::Rect(0,0, _successOverlay._drawSurface.w, _successOverlay._drawSurface.h);
 		destBounds.moveTo(640 / 2 - destBounds.width() / 2,
diff --git a/engines/nancy/state/map.cpp b/engines/nancy/state/map.cpp
index ac38295dbff..aa8888189e1 100644
--- a/engines/nancy/state/map.cpp
+++ b/engines/nancy/state/map.cpp
@@ -168,20 +168,20 @@ void Map::MapViewport::updateGraphics() {
 	}
 }
 
-void Map::MapViewport::loadVideo(const Common::String &filename, const Common::String &palette) {
+void Map::MapViewport::loadVideo(const Common::Path &filename, const Common::Path &palette) {
 	if (_decoder.isVideoLoaded()) {
 		_decoder.close();
 	}
 
-	if (!_decoder.loadFile(filename + ".avf")) {
-		error("Couldn't load video file %s", filename.c_str());
+	if (!_decoder.loadFile(filename.append(".avf"))) {
+		error("Couldn't load video file %s", filename.toString().c_str());
 	}
 
-	if (palette.size()) {
+	if (!palette.empty()) {
 		setPalette(palette);
 	}
 
-	GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _drawSurface, palette.size());
+	GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _drawSurface, !palette.empty());
 	_needsRedraw = true;
 }
 
diff --git a/engines/nancy/state/map.h b/engines/nancy/state/map.h
index 6fb784b1087..62a433eeabd 100644
--- a/engines/nancy/state/map.h
+++ b/engines/nancy/state/map.h
@@ -63,7 +63,7 @@ protected:
 		void init() override;
 		void updateGraphics() override;
 
-		void loadVideo(const Common::String &filename, const Common::String &palette = Common::String());
+		void loadVideo(const Common::Path &filename, const Common::Path &palette = Common::Path());
 		void playVideo() { _decoder.start(); }
 		void unloadVideo() { _decoder.close(); }
 
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 9ae4d156da2..dc399037586 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -852,11 +852,11 @@ void Scene::load(bool fromSaveFile) {
 	g_nancy->_graphicsManager->suppressNextDraw();
 
 	// Scene IDs are prefixed with S inside the cif tree; e.g 100 -> S100
-	Common::String sceneName = Common::String::format("S%u", _sceneState.nextScene.sceneID);
+	Common::Path sceneName(Common::String::format("S%u", _sceneState.nextScene.sceneID));
 	IFF *sceneIFF = g_nancy->_resource->loadIFF(sceneName);
 
 	if (!sceneIFF) {
-		error("Faled to load IFF %s", sceneName.c_str());
+		error("Faled to load IFF %s", sceneName.toString().c_str());
 	}
 
 	Common::SeekableReadStream *sceneSummaryChunk = sceneIFF->getChunkStream("SSUM");
@@ -909,7 +909,7 @@ void Scene::load(bool fromSaveFile) {
 						_sceneState.currentScene.verticalOffset,
 						_sceneState.summary.panningType,
 						_sceneState.summary.videoFormat,
-						_sceneState.summary.palettes.size() ? _sceneState.summary.palettes[(byte)_sceneState.currentScene.paletteID] : Common::String());
+						_sceneState.summary.palettes.size() ? _sceneState.summary.palettes[(byte)_sceneState.currentScene.paletteID] : Common::Path());
 
 	if (_viewport.getFrameCount() <= 1) {
 		_viewport.disableEdges(kLeft | kRight);
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 15abcbe550a..4e63e28d678 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -79,10 +79,10 @@ public:
 		// SSUM and TSUM
 		// Default values set to match those applied when loading from a TSUM chunk
 		Common::String description;
-		Common::String videoFile;
+		Common::Path videoFile;
 		
 		uint16 videoFormat = kLargeVideoFormat;
-		Common::Array<Common::String> palettes;
+		Common::Array<Common::Path> palettes;
 		SoundDescription sound;
 		
 		byte panningType = kPan360;
diff --git a/engines/nancy/state/setupmenu.cpp b/engines/nancy/state/setupmenu.cpp
index 1d8ca45ee63..c5adcfe0360 100644
--- a/engines/nancy/state/setupmenu.cpp
+++ b/engines/nancy/state/setupmenu.cpp
@@ -134,7 +134,7 @@ void SetupMenu::init() {
 	if (g_nancy->getGameType() == kGameTypeVampire) {
 		// There is a setup.bmp an the top directory of the first disk,
 		// which we need to avoid
-		_background.init("ART/" + _setupData->_imageName);
+		_background.init(Common::Path("ART/").joinInPlace(_setupData->_imageName));
 	} else {
 		_background.init(_setupData->_imageName);
 	}
diff --git a/engines/nancy/ui/fullscreenimage.cpp b/engines/nancy/ui/fullscreenimage.cpp
index b3400190d0b..c6ab4bffdb7 100644
--- a/engines/nancy/ui/fullscreenimage.cpp
+++ b/engines/nancy/ui/fullscreenimage.cpp
@@ -27,7 +27,7 @@
 namespace Nancy {
 namespace UI {
 
-void FullScreenImage::init(const Common::String &imageName) {
+void FullScreenImage::init(const Common::Path &imageName) {
 	g_nancy->_resource->loadImage(imageName, _drawSurface);
 
 	Common::Rect srcBounds = Common::Rect(0,0, _drawSurface.w, _drawSurface.h);
diff --git a/engines/nancy/ui/fullscreenimage.h b/engines/nancy/ui/fullscreenimage.h
index eb11ea70912..f6d55d4ae56 100644
--- a/engines/nancy/ui/fullscreenimage.h
+++ b/engines/nancy/ui/fullscreenimage.h
@@ -32,7 +32,7 @@ public:
 	FullScreenImage() : RenderObject(0) {}
 	virtual ~FullScreenImage() = default;
 
-	void init(const Common::String &imageName);
+	void init(const Common::Path &imageName);
 
 protected:
 	void init() override {}
diff --git a/engines/nancy/ui/viewport.cpp b/engines/nancy/ui/viewport.cpp
index 3842b0bf58c..c1c1e2655eb 100644
--- a/engines/nancy/ui/viewport.cpp
+++ b/engines/nancy/ui/viewport.cpp
@@ -207,13 +207,13 @@ void Viewport::handleInput(NancyInput &input) {
 	_movementLastFrame = direction;
 }
 
-void Viewport::loadVideo(const Common::String &filename, uint frameNr, uint verticalScroll, byte panningType, uint16 format, const Common::String &palette) {
+void Viewport::loadVideo(const Common::Path &filename, uint frameNr, uint verticalScroll, byte panningType, uint16 format, const Common::Path &palette) {
 	if (_decoder.isVideoLoaded()) {
 		_decoder.close();
 	}
 
-	if (!_decoder.loadFile(filename + ".avf")) {
-		error("Couldn't load video file %s", filename.c_str());
+	if (!_decoder.loadFile(filename.append(".avf"))) {
+		error("Couldn't load video file %s", filename.toString().c_str());
 	}
 
 	_videoFormat = format;
@@ -225,7 +225,7 @@ void Viewport::loadVideo(const Common::String &filename, uint frameNr, uint vert
 	setFrame(frameNr);
 	setVerticalScroll(verticalScroll);
 
-	if (palette.size()) {
+	if (!palette.empty()) {
 		GraphicsManager::loadSurfacePalette(_fullFrame, palette);
 		setPalette(palette);
 	}
diff --git a/engines/nancy/ui/viewport.h b/engines/nancy/ui/viewport.h
index a8373630f18..547d92d5f0d 100644
--- a/engines/nancy/ui/viewport.h
+++ b/engines/nancy/ui/viewport.h
@@ -56,7 +56,7 @@ public:
 	void init() override;
 	void handleInput(NancyInput &input);
 
-	void loadVideo(const Common::String &filename, uint frameNr = 0, uint verticalScroll = 0, byte panningType = kPanNone, uint16 format = 2, const Common::String &palette = Common::String());
+	void loadVideo(const Common::Path &filename, uint frameNr = 0, uint verticalScroll = 0, byte panningType = kPanNone, uint16 format = 2, const Common::Path &palette = Common::Path());
 
 	void setFrame(uint frameNr);
 	void setNextFrame();
diff --git a/engines/nancy/util.cpp b/engines/nancy/util.cpp
index 83149b92d2c..819f41d3ab4 100644
--- a/engines/nancy/util.cpp
+++ b/engines/nancy/util.cpp
@@ -230,6 +230,23 @@ void readFilenameArray(Common::Serializer &stream, Common::Array<Common::String>
 	}
 }
 
+void readFilenameArray(Common::SeekableReadStream &stream, Common::Array<Common::Path> &inArray, uint num) {
+	inArray.resize(num);
+	for (Common::Path &str : inArray) {
+		readFilename(stream, str);
+	}
+}
+
+void readFilenameArray(Common::Serializer &stream, Common::Array<Common::Path> &inArray, uint num, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
+	Common::Serializer::Version version = stream.getVersion();
+	if (version >= minVersion && version <= maxVersion) {
+		inArray.resize(num);
+		for (Common::Path &str : inArray) {
+			readFilename(stream, str, minVersion, maxVersion);
+		}
+	}
+}
+
 // A text line will often be broken up into chunks separated by nulls, use
 // this function to put it back together as a Common::String
 void assembleTextLine(char *rawCaption, Common::String &output, uint size) {
diff --git a/engines/nancy/util.h b/engines/nancy/util.h
index 47974a16f3b..665cde67b2b 100644
--- a/engines/nancy/util.h
+++ b/engines/nancy/util.h
@@ -38,8 +38,20 @@ void readRectArray16(Common::Serializer &stream, Common::Array<Common::Rect> &in
 
 void readFilename(Common::SeekableReadStream &stream, Common::String &inString);
 void readFilename(Common::Serializer &stream, Common::String &inString, Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion);
+inline void readFilename(Common::SeekableReadStream &stream, Common::Path &inPath) {
+	Common::String inString;
+	readFilename(stream, inString);
+	inPath = Common::Path(inString);
+}
+inline void readFilename(Common::Serializer &stream, Common::Path &inPath, Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion) {
+	Common::String inString;
+	readFilename(stream, inString, minVersion, maxVersion);
+	inPath = Common::Path(inString);
+}
 void readFilenameArray(Common::SeekableReadStream &stream, Common::Array<Common::String> &inArray, uint num);
 void readFilenameArray(Common::Serializer &stream, Common::Array<Common::String> &inArray, uint num, Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion);
+void readFilenameArray(Common::SeekableReadStream &stream, Common::Array<Common::Path> &inArray, uint num);
+void readFilenameArray(Common::Serializer &stream, Common::Array<Common::Path> &inArray, uint num, Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion);
 
 void assembleTextLine(char *rawCaption, Common::String &output, uint size);
 


Commit: 31d3a266bdf76fb249dd5f394198e589806510bc
    https://github.com/scummvm/scummvm/commit/31d3a266bdf76fb249dd5f394198e589806510bc
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
NEVERHOOD: Migrate engine to Path

Changed paths:
    engines/neverhood/blbarchive.cpp
    engines/neverhood/blbarchive.h
    engines/neverhood/dialogs.cpp
    engines/neverhood/neverhood.cpp
    engines/neverhood/nhcarchive.cpp
    engines/neverhood/nhcarchive.h
    engines/neverhood/resourceman.cpp
    engines/neverhood/resourceman.h


diff --git a/engines/neverhood/blbarchive.cpp b/engines/neverhood/blbarchive.cpp
index 53799bcb012..b7f867980cd 100644
--- a/engines/neverhood/blbarchive.cpp
+++ b/engines/neverhood/blbarchive.cpp
@@ -31,7 +31,7 @@ BlbArchive::~BlbArchive() {
 	delete[] _extData;
 }
 
-bool BlbArchive::open(const Common::String &filename, bool isOptional) {
+bool BlbArchive::open(const Common::Path &filename, bool isOptional) {
 	BlbHeader header;
 	uint16 *extDataOffsets;
 
@@ -39,7 +39,7 @@ bool BlbArchive::open(const Common::String &filename, bool isOptional) {
 
 	if (!_fd.open(filename)) {
 		if (!isOptional)
-			error("BlbArchive::open() Could not open %s", filename.c_str());
+			error("BlbArchive::open() Could not open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -50,11 +50,11 @@ bool BlbArchive::open(const Common::String &filename, bool isOptional) {
 	header.fileCount = _fd.readUint32LE();
 
 	if (header.id1 != 0x2004940 || header.id2 != 7 || header.fileSize != _fd.size()) {
-		error("BlbArchive::open() %s seems to be corrupt", filename.c_str());
+		error("BlbArchive::open() %s seems to be corrupt", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
-	debug(4, "%s: fileCount = %d", filename.c_str(), header.fileCount);
+	debug(4, "%s: fileCount = %d", filename.toString(Common::Path::kNativeSeparator).c_str(), header.fileCount);
 
 	_entries.reserve(header.fileCount);
 
diff --git a/engines/neverhood/blbarchive.h b/engines/neverhood/blbarchive.h
index 575d9d1fba1..4b830e8c9bc 100644
--- a/engines/neverhood/blbarchive.h
+++ b/engines/neverhood/blbarchive.h
@@ -54,7 +54,7 @@ class BlbArchive {
 public:
 	BlbArchive();
 	~BlbArchive();
-	bool open(const Common::String &filename, bool isOptional);
+	bool open(const Common::Path &filename, bool isOptional);
 	void load(uint index, byte *buffer, uint32 size);
 	void load(BlbArchiveEntry *entry, byte *buffer, uint32 size);
 	byte *getEntryExtData(uint index);
diff --git a/engines/neverhood/dialogs.cpp b/engines/neverhood/dialogs.cpp
index 17f37bbd10f..263a90e2d7b 100644
--- a/engines/neverhood/dialogs.cpp
+++ b/engines/neverhood/dialogs.cpp
@@ -62,8 +62,8 @@ NeverhoodOptionsWidget::NeverhoodOptionsWidget(GuiObject *boss, const Common::St
 		"NeverhoodGameOptionsDialog.RepeatWillieHint", _("Repeat useful Willie's hint"),
 		_("Repeat actual useful hint by Willie"));
 
-	Common::FSDirectory dir(ConfMan.get("path", _domain));
-	Common::String extraPath(ConfMan.get("extrapath", _domain));
+	Common::FSDirectory dir(ConfMan.getPath("path", _domain));
+	Common::Path extraPath(ConfMan.getPath("extrapath", _domain));
 	Common::FSDirectory extraDir(extraPath);
 	Common::Array<Common::FSDirectory *> langdirs = { &dir, dir.getSubDirectory("language") };
 	if (!extraPath.empty()) {
diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp
index aaaf72a7ce6..2e407df35bf 100644
--- a/engines/neverhood/neverhood.cpp
+++ b/engines/neverhood/neverhood.cpp
@@ -67,8 +67,8 @@ NeverhoodEngine::~NeverhoodEngine() {
 Common::Error NeverhoodEngine::run() {
 	initGraphics(640, 480);
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
-	const Common::String extraPath(ConfMan.get("extrapath"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
+	const Common::Path extraPath(ConfMan.getPath("extrapath"));
 
 	SearchMan.addSubDirectoryMatching(gameDataDir, "data");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "language");
@@ -109,7 +109,7 @@ Common::Error NeverhoodEngine::run() {
 	}
 
 	Common::String nhcFile = ConfMan.get("nhc_file");
-	if (!nhcFile.empty() && _res->addNhcArchive(nhcFile + ".nhc")) {
+	if (!nhcFile.empty() && _res->addNhcArchive(Common::Path(nhcFile + ".nhc"))) {
 		uint32 fontSpecHash = calcHash("asRecFont");
 		if (_res->nhcExists(fontSpecHash, kResTypeData)) {
 			DataResource fontData(this);
diff --git a/engines/neverhood/nhcarchive.cpp b/engines/neverhood/nhcarchive.cpp
index 213763b3ed6..a36bbb3e416 100644
--- a/engines/neverhood/nhcarchive.cpp
+++ b/engines/neverhood/nhcarchive.cpp
@@ -24,12 +24,12 @@
 
 namespace Neverhood {
 
-bool NhcArchive::open(const Common::String &filename, bool isOptional) {
+bool NhcArchive::open(const Common::Path &filename, bool isOptional) {
 	_entries.clear();
 
 	if (!_fd.open(filename)) {
 		if (!isOptional)
-			error("NhcArchive::open() Could not open %s", filename.c_str());
+			error("NhcArchive::open() Could not open %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -40,7 +40,7 @@ bool NhcArchive::open(const Common::String &filename, bool isOptional) {
 	/* totalSize = */ _fd.readUint32LE();
 	uint32 fileCount = _fd.readUint32LE();
 
-	debug(4, "%s: fileCount = %d", filename.c_str(), fileCount);
+	debug(4, "%s: fileCount = %d", filename.toString(Common::Path::kNativeSeparator).c_str(), fileCount);
 
 	_entries.reserve(fileCount);
 
diff --git a/engines/neverhood/nhcarchive.h b/engines/neverhood/nhcarchive.h
index a574bb3cb82..999d5585487 100644
--- a/engines/neverhood/nhcarchive.h
+++ b/engines/neverhood/nhcarchive.h
@@ -49,7 +49,7 @@ class NhcArchive {
 public:
 	NhcArchive() {}
 	~NhcArchive() {}
-	bool open(const Common::String &filename, bool isOptional);
+	bool open(const Common::Path &filename, bool isOptional);
 	void load(uint index, byte *buffer, uint32 size);
 	void load(NhcArchiveEntry *entry, byte *buffer, uint32 size);
 	uint32 getSize(uint index) { return _entries[index].size; }
diff --git a/engines/neverhood/resourceman.cpp b/engines/neverhood/resourceman.cpp
index e4c727d1a0c..e1d4a174603 100644
--- a/engines/neverhood/resourceman.cpp
+++ b/engines/neverhood/resourceman.cpp
@@ -36,14 +36,14 @@ ResourceMan::ResourceMan() {
 ResourceMan::~ResourceMan() {
 }
 
-void ResourceMan::addArchive(const Common::String &filename, bool isOptional) {
+void ResourceMan::addArchive(const Common::Path &filename, bool isOptional) {
 	BlbArchive *archive = new BlbArchive();
 	if (!archive->open(filename, isOptional)) {
 		delete archive;
 		return;
 	}
 	_archives.push_back(archive);
-	debug(3, "ResourceMan::addArchive(%s) %d files", filename.c_str(), archive->getCount());
+	debug(3, "ResourceMan::addArchive(%s) %d files", filename.toString(Common::Path::kNativeSeparator).c_str(), archive->getCount());
 	for (uint archiveEntryIndex = 0; archiveEntryIndex < archive->getCount(); archiveEntryIndex++) {
 		BlbArchiveEntry *archiveEntry = archive->getEntry(archiveEntryIndex);
 		ResourceFileEntry *entry = findEntrySimple(archiveEntry->fileHash);
@@ -64,14 +64,14 @@ void ResourceMan::addArchive(const Common::String &filename, bool isOptional) {
 	}
 }
 
-bool ResourceMan::addNhcArchive(const Common::String &filename) {
+bool ResourceMan::addNhcArchive(const Common::Path &filename) {
 	NhcArchive *archive = new NhcArchive();
 	if (!archive->open(filename, true)) {
 		delete archive;
 		return false;
 	}
 	_nhcArchives.push_back(archive);
-	debug(3, "ResourceMan::addArchive(%s) %d files", filename.c_str(), archive->getCount());
+	debug(3, "ResourceMan::addArchive(%s) %d files", filename.toString(Common::Path::kNativeSeparator).c_str(), archive->getCount());
 	for (uint archiveEntryIndex = 0; archiveEntryIndex < archive->getCount(); archiveEntryIndex++) {
 		NhcArchiveEntry *archiveEntry = archive->getEntry(archiveEntryIndex);
 		ResourceFileEntry *entry = findEntrySimple(archiveEntry->fileHash);
diff --git a/engines/neverhood/resourceman.h b/engines/neverhood/resourceman.h
index 21f935d3bea..2decc59663c 100644
--- a/engines/neverhood/resourceman.h
+++ b/engines/neverhood/resourceman.h
@@ -108,8 +108,8 @@ class ResourceMan {
 public:
 	ResourceMan();
 	~ResourceMan();
-	void addArchive(const Common::String &filename, bool isOptional = false);
-	bool addNhcArchive(const Common::String &filename);
+	void addArchive(const Common::Path &filename, bool isOptional = false);
+	bool addNhcArchive(const Common::Path &filename);
 	ResourceFileEntry *findEntrySimple(uint32 fileHash);
 	ResourceFileEntry *findEntry(uint32 fileHash, ResourceFileEntry **firstEntry = NULL);
 	Common::SeekableReadStream *createStream(uint32 fileHash);


Commit: 7961472a0966c67bd7ffc7e98f680b5457549bcf
    https://github.com/scummvm/scummvm/commit/7961472a0966c67bd7ffc7e98f680b5457549bcf
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
NGI: Migrate engine to Path

Changed paths:
    engines/ngi/gfx.cpp
    engines/ngi/ngi.h
    engines/ngi/ngiarchive.cpp
    engines/ngi/ngiarchive.h
    engines/ngi/scene.cpp
    engines/ngi/sound.cpp
    engines/ngi/sound.h
    engines/ngi/statics.cpp
    engines/ngi/utils.cpp
    engines/ngi/utils.h


diff --git a/engines/ngi/gfx.cpp b/engines/ngi/gfx.cpp
index 680b50526db..fbd5498fd2f 100644
--- a/engines/ngi/gfx.cpp
+++ b/engines/ngi/gfx.cpp
@@ -417,7 +417,7 @@ Picture::~Picture() {
 }
 
 void Picture::freePicture() {
-	debugC(5, kDebugMemory, "Picture::freePicture(): file: %s", _memfilename.c_str());
+	debugC(5, kDebugMemory, "Picture::freePicture(): file: %s", _memfilename.toString().c_str());
 
 	if (_bitmap) {
 		if (testFlags() && !_field_54) {
@@ -474,8 +474,8 @@ bool Picture::load(MfcArchive &file) {
 
 	getData();
 
-	debugC(5, kDebugLoading, "Picture::load: loaded memobject=\"%s\" x=%d y=%d f44=%d width=%d height=%d alpha=%d memobject2=\"%s\"", _memfilename.c_str(),
-				_x, _y, _field_44, _width, _height, _alpha, _memoryObject2->_memfilename.c_str());
+	debugC(5, kDebugLoading, "Picture::load: loaded memobject=\"%s\" x=%d y=%d f44=%d width=%d height=%d alpha=%d memobject2=\"%s\"", _memfilename.toString().c_str(),
+				_x, _y, _field_44, _width, _height, _alpha, _memoryObject2->_memfilename.toString().c_str());
 
 	return true;
 }
@@ -495,7 +495,7 @@ void Picture::setAOIDs() {
 }
 
 void Picture::init() {
-	debugC(5, kDebugLoading, "Picture::init(), %s", _memfilename.c_str());
+	debugC(5, kDebugLoading, "Picture::init(), %s", _memfilename.toString().c_str());
 
 	MemoryObject::getData();
 
@@ -521,7 +521,7 @@ void Picture::getDibInfo() {
 	}
 
 	if (!_data) {
-		warning("Picture::getDibInfo: data is empty <%s>", _memfilename.c_str());
+		warning("Picture::getDibInfo: data is empty <%s>", _memfilename.toString().c_str());
 
 		MemoryObject::load();
 
@@ -547,7 +547,7 @@ void Picture::draw(int x, int y, int style, int angle) {
 	int x1 = x;
 	int y1 = y;
 
-	debugC(7, kDebugDrawing, "Picture::draw(%d, %d, %d, %d) (%s)", x, y, style, angle, _memfilename.c_str());
+	debugC(7, kDebugDrawing, "Picture::draw(%d, %d, %d, %d) (%s)", x, y, style, angle, _memfilename.toString().c_str());
 
 	if (x != -1)
 		x1 = x;
diff --git a/engines/ngi/ngi.h b/engines/ngi/ngi.h
index 544ced37d04..76edce6f5bd 100644
--- a/engines/ngi/ngi.h
+++ b/engines/ngi/ngi.h
@@ -188,7 +188,7 @@ public:
 	int _currSoundListCount;
 	bool _soundEnabled;
 	bool _flgSoundList;
-	Common::String _sceneTracks[10];
+	Common::Path _sceneTracks[10];
 	int _numSceneTracks;
 	bool _sceneTrackHasSequence;
 	int _musicMinDelay;
@@ -196,7 +196,7 @@ public:
 	int _musicLocal;
 	Common::String _trackName;
 	int _trackStartDelay;
-	Common::String _sceneTracksCurrentTrack;
+	Common::Path _sceneTracksCurrentTrack;
 	bool _sceneTrackIsPlaying;
 
 	void stopAllSounds();
@@ -206,8 +206,8 @@ public:
 	int getSceneTrack();
 	void updateTrackDelay();
 	void startSceneTrack();
-	void startSoundStream1(const Common::String &trackName);
-	void playOggSound(const Common::String &trackName, Audio::SoundHandle &stream);
+	void startSoundStream1(const Common::Path &trackName);
+	void playOggSound(const Common::Path &trackName, Audio::SoundHandle &stream);
 	void stopSoundStream2();
 	void stopAllSoundStreams();
 	void stopAllSoundInstances(int id);
diff --git a/engines/ngi/ngiarchive.cpp b/engines/ngi/ngiarchive.cpp
index 1d40b125a28..a534d60ae1a 100644
--- a/engines/ngi/ngiarchive.cpp
+++ b/engines/ngi/ngiarchive.cpp
@@ -32,7 +32,7 @@
 
 namespace NGI {
 
-NGIArchive::NGIArchive(const Common::String &filename) : _ngiFilename(filename) {
+NGIArchive::NGIArchive(const Common::Path &filename) : _ngiFilename(filename) {
 	Common::File ngiFile;
 
 	if (!ngiFile.open(_ngiFilename)) {
@@ -91,7 +91,7 @@ NGIArchive::NGIArchive(const Common::String &filename) : _ngiFilename(filename)
 
 	g_nmi->_currArchive = this;
 
-	debug(4, "NGIArchive::NGIArchive(%s): Located %d files", filename.c_str(), _headers.size());
+	debug(4, "NGIArchive::NGIArchive(%s): Located %d files", filename.toString().c_str(), _headers.size());
 }
 
 NGIArchive::~NGIArchive() {
@@ -100,8 +100,7 @@ NGIArchive::~NGIArchive() {
 }
 
 bool NGIArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	return _headers.contains(name);
+	return _headers.contains(path);
 }
 
 int NGIArchive::listMembers(Common::ArchiveMemberList &list) const {
@@ -117,20 +116,18 @@ int NGIArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr NGIArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *NGIArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!_headers.contains(name)) {
+	if (!_headers.contains(path)) {
 		return nullptr;
 	}
 
-	NgiHeader *hdr = _headers[name].get();
+	NgiHeader *hdr = _headers[path].get();
 
 	Common::File archiveFile;
 	archiveFile.open(_ngiFilename);
@@ -145,7 +142,7 @@ Common::SeekableReadStream *NGIArchive::createReadStreamForMember(const Common::
 	return new Common::MemoryReadStream(data, hdr->size, DisposeAfterUse::YES);
 }
 
-NGIArchive *makeNGIArchive(const Common::String &name) {
+NGIArchive *makeNGIArchive(const Common::Path &name) {
 	return new NGIArchive(name);
 }
 
diff --git a/engines/ngi/ngiarchive.h b/engines/ngi/ngiarchive.h
index 22244d0c2f9..50281fd3aa7 100644
--- a/engines/ngi/ngiarchive.h
+++ b/engines/ngi/ngiarchive.h
@@ -22,8 +22,8 @@
 #ifndef NGI_NGIARCHIVE_H
 #define NGI_NGIARCHIVE_H
 
+#include "common/path.h"
 #include "common/ptr.h"
-#include "common/str.h"
 
 namespace NGI {
 
@@ -39,14 +39,14 @@ struct NgiHeader {
 	char  filename[NGI_FILENAME_MAX];
 };
 
-typedef Common::HashMap<Common::String, Common::ScopedPtr<NgiHeader>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> NgiHeadersMap;
+typedef Common::HashMap<Common::Path, Common::ScopedPtr<NgiHeader>, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> NgiHeadersMap;
 
 class NGIArchive : public Common::Archive {
 	NgiHeadersMap _headers;
-	Common::String _ngiFilename;
+	Common::Path _ngiFilename;
 
 public:
-	NGIArchive(const Common::String &name);
+	NGIArchive(const Common::Path &name);
 	~NGIArchive() override;
 
 	// Archive implementation
@@ -62,7 +62,7 @@ public:
  *
  * May return 0 in case of a failure.
  */
-NGIArchive *makeNGIArchive(const Common::String &name);
+NGIArchive *makeNGIArchive(const Common::Path &name);
 
 } // End of namespace NGI
 
diff --git a/engines/ngi/scene.cpp b/engines/ngi/scene.cpp
index 51b6ec35863..6bdcecd6c45 100644
--- a/engines/ngi/scene.cpp
+++ b/engines/ngi/scene.cpp
@@ -88,11 +88,11 @@ bool SceneTag::load(MfcArchive &file) {
 }
 
 void SceneTag::loadScene() {
-	Common::String archname = genFileName(0, _sceneId, "nl");
+	Common::Path archname = genFileName(0, _sceneId, "nl");
 
 	Common::Archive *arch = makeNGIArchive(archname);
 
-	Common::String fname = genFileName(0, _sceneId, "sc");
+	Common::Path fname = genFileName(0, _sceneId, "sc");
 
 	Common::ScopedPtr<Common::SeekableReadStream> file(arch->createReadStreamForMember(fname));
 
@@ -144,7 +144,7 @@ bool Scene::load(MfcArchive &file) {
 
 	for (int i = 0; i < count; i++) {
 		int aniNum = file.readUint16LE();
-		Common::String aniname = genFileName(0, aniNum, "ani");
+		Common::Path aniname = genFileName(0, aniNum, "ani");
 
 		Common::SeekableReadStream *f = g_nmi->_currArchive->createReadStreamForMember(aniname);
 
@@ -165,7 +165,7 @@ bool Scene::load(MfcArchive &file) {
 
 	for (int i = 0; i < count; i++) {
 		int qNum = file.readUint16LE();
-		Common::String qname = genFileName(0, qNum, "qu");
+		Common::Path qname = genFileName(0, qNum, "qu");
 
 		Common::SeekableReadStream *f = g_nmi->_currArchive->createReadStreamForMember(qname);
 		MfcArchive archive(f);
@@ -210,7 +210,7 @@ bool Scene::load(MfcArchive &file) {
 		}
 	}
 
-	Common::String shdname = genFileName(0, _sceneId, "shd");
+	Common::Path shdname = genFileName(0, _sceneId, "shd");
 
 	Shadows *shd = new Shadows();
 
@@ -219,13 +219,13 @@ bool Scene::load(MfcArchive &file) {
 	else
 		delete shd;
 
-	Common::String slsname = genFileName(0, _sceneId, "sls");
+	Common::Path slsname = genFileName(0, _sceneId, "sls");
 
 	if (g_nmi->_soundEnabled) {
 		_soundList.reset(new SoundList());
 
 		if (g_nmi->_flgSoundList) {
-			Common::String nlname = genFileName(17, _sceneId, "nl");
+			Common::Path nlname = genFileName(17, _sceneId, "nl");
 
 			_soundList->loadFile(slsname, nlname);
 		} else {
diff --git a/engines/ngi/sound.cpp b/engines/ngi/sound.cpp
index f2fb8daa736..c77ac1c6909 100644
--- a/engines/ngi/sound.cpp
+++ b/engines/ngi/sound.cpp
@@ -37,7 +37,7 @@
 
 namespace NGI {
 
-bool SoundList::load(MfcArchive &file, const Common::String &fname) {
+bool SoundList::load(MfcArchive &file, const Common::Path &fname) {
 	debugC(5, kDebugLoading, "SoundList::load()");
 
 	uint32 count = file.readUint32LE();
@@ -56,7 +56,7 @@ bool SoundList::load(MfcArchive &file, const Common::String &fname) {
 	return true;
 }
 
-bool SoundList::loadFile(const Common::String &fname, const Common::String &libname) {
+bool SoundList::loadFile(const Common::Path &fname, const Common::Path &libname) {
 	Common::File file;
 
 	if (!file.open(fname))
@@ -339,20 +339,20 @@ int NGIEngine::getSceneTrack() {
 	return res;
 }
 
-void NGIEngine::startSoundStream1(const Common::String &trackName) {
+void NGIEngine::startSoundStream1(const Common::Path &trackName) {
 	stopAllSoundStreams();
 
 	playOggSound(trackName, _soundStream1);
 }
 
-void NGIEngine::playOggSound(const Common::String &trackName, Audio::SoundHandle &stream) {
+void NGIEngine::playOggSound(const Common::Path &trackName, Audio::SoundHandle &stream) {
 #ifdef USE_VORBIS
 	if (_mixer->isSoundHandleActive(stream))
 		return;
 
 	Common::File *track = new Common::File();
 	if (!track->open(trackName)) {
-		warning("Could not open %s", trackName.c_str());
+		warning("Could not open %s", trackName.toString().c_str());
 		delete track;
 		return;
 	}
diff --git a/engines/ngi/sound.h b/engines/ngi/sound.h
index 5693efbf38f..cfb903187ed 100644
--- a/engines/ngi/sound.h
+++ b/engines/ngi/sound.h
@@ -63,9 +63,9 @@ class SoundList : public CObject {
 	Common::ScopedPtr<NGIArchive> _libHandle;
 
  public:
-	virtual bool load(MfcArchive &file, const Common::String &fname);
+	virtual bool load(MfcArchive &file, const Common::Path &fname);
 	bool load(MfcArchive &file) override { assert(0); return false; } // Disable base class
-	bool loadFile(const Common::String &fname, const Common::String &libname);
+	bool loadFile(const Common::Path &fname, const Common::Path &libname);
 
 	int getCount() { return _soundItems.size(); }
 	Sound &getSoundByIndex(int idx) { return _soundItems[idx]; }
diff --git a/engines/ngi/statics.cpp b/engines/ngi/statics.cpp
index f5be08befac..f0c93fd76f0 100644
--- a/engines/ngi/statics.cpp
+++ b/engines/ngi/statics.cpp
@@ -179,7 +179,7 @@ bool StaticANIObject::load(MfcArchive &file) {
 	for (int i = 0; i < count; i++) {
 		int movNum = file.readUint16LE();
 
-		Common::String movname = genFileName(_id, movNum, "mov");
+		Common::Path movname = genFileName(_id, movNum, "mov");
 
 		Common::ScopedPtr<Common::SeekableReadStream> f(g_nmi->_currArchive->createReadStreamForMember(movname));
 
diff --git a/engines/ngi/utils.cpp b/engines/ngi/utils.cpp
index 7827585c31c..3652b70fa1d 100644
--- a/engines/ngi/utils.cpp
+++ b/engines/ngi/utils.cpp
@@ -33,7 +33,7 @@
 
 namespace NGI {
 
-bool CObject::loadFile(const Common::String &fname) {
+bool CObject::loadFile(const Common::Path &fname) {
 	Common::File file;
 
 	if (!file.open(fname))
@@ -124,12 +124,14 @@ MemoryObject::~MemoryObject() {
 
 bool MemoryObject::load(MfcArchive &file) {
 	debugC(5, kDebugLoading, "MemoryObject::load()");
-	_memfilename = file.readPascalString();
+	Common::String filename = file.readPascalString();
 
-	while (_memfilename.contains('\\')) {
-		_memfilename.deleteChar(0);
+	while (filename.contains('\\')) {
+		filename.deleteChar(0);
 	}
 
+	_memfilename = Common::Path(filename);
+
 	if (g_nmi->_currArchive) {
 		_mfield_14 = 0;
 		_libHandle = g_nmi->_currArchive;
@@ -138,8 +140,8 @@ bool MemoryObject::load(MfcArchive &file) {
 	return true;
 }
 
-void MemoryObject::loadFile(const Common::String &filename) {
-	debugC(5, kDebugLoading, "MemoryObject::loadFile(<%s>)", filename.c_str());
+void MemoryObject::loadFile(const Common::Path &filename) {
+	debugC(5, kDebugLoading, "MemoryObject::loadFile(<%s>)", filename.toString().c_str());
 
 	if (filename.empty())
 		return;
@@ -157,7 +159,7 @@ void MemoryObject::loadFile(const Common::String &filename) {
 
 			_dataSize = s->size();
 
-			debugC(5, kDebugLoading, "Loading %s (%d bytes)", filename.c_str(), _dataSize);
+			debugC(5, kDebugLoading, "Loading %s (%d bytes)", filename.toString().c_str(), _dataSize);
 			_data = (byte *)calloc(_dataSize, 1);
 			s->read(_data, _dataSize);
 			delete s;
@@ -185,7 +187,7 @@ byte *MemoryObject::loadData() {
 }
 
 void MemoryObject::freeData() {
-	debugC(8, kDebugMemory, "MemoryObject::freeData(): file: %s", _memfilename.c_str());
+	debugC(8, kDebugMemory, "MemoryObject::freeData(): file: %s", _memfilename.toString().c_str());
 
 	if (_data)
 		free(_data);
@@ -218,7 +220,7 @@ bool MemoryObject2::load(MfcArchive &file) {
 
 	_mflags |= 1;
 
-	debugC(5, kDebugLoading, "MemoryObject2::load: <%s>", _memfilename.c_str());
+	debugC(5, kDebugLoading, "MemoryObject2::load: <%s>", _memfilename.toString().c_str());
 
 	if (!_memfilename.empty()) {
 		MemoryObject::loadFile(_memfilename);
@@ -453,7 +455,7 @@ void MfcArchive::writeObject(CObject *obj) {
 	}
 }
 
-Common::String genFileName(int superId, int sceneId, const char *ext) {
+Common::Path genFileName(int superId, int sceneId, const char *ext) {
 	Common::String s;
 
 	if (superId) {
@@ -464,7 +466,7 @@ Common::String genFileName(int superId, int sceneId, const char *ext) {
 
 	debugC(7, kDebugLoading, "genFileName: %s", s.c_str());
 
-	return s;
+	return Common::Path(s);
 }
 
 // Translates cp-1251..utf-8
diff --git a/engines/ngi/utils.h b/engines/ngi/utils.h
index 88a7a0a3d64..dab46a1dbe9 100644
--- a/engines/ngi/utils.h
+++ b/engines/ngi/utils.h
@@ -113,7 +113,7 @@ public:
 	virtual void save(MfcArchive &out) { error("Not implemented for obj type: %d", _objtype); }
 	virtual ~CObject() {}
 
-	bool loadFile(const Common::String &fname);
+	bool loadFile(const Common::Path &fname);
 };
 
 template <class T>
@@ -141,7 +141,7 @@ class MemoryObject : CObject {
 	friend class Scene;
 
  protected:
-	Common::String _memfilename;
+	Common::Path _memfilename;
 	int _mfield_8;
 	int _mfield_C;
 	int _mfield_10;
@@ -156,7 +156,7 @@ class MemoryObject : CObject {
 	~MemoryObject() override;
 
 	bool load(MfcArchive &file) override;
-	void loadFile(const Common::String &filename);
+	void loadFile(const Common::Path &filename);
 	void load() { loadFile(_memfilename); }
 	byte *getData();
 	byte *loadData();
@@ -191,7 +191,7 @@ class DWordArray : public Common::Array<int32>, public CObject {
 	bool load(MfcArchive &file) override;
 };
 
-Common::String genFileName(int superId, int sceneId, const char *ext);
+Common::Path genFileName(int superId, int sceneId, const char *ext);
 byte *transCyrillic(const Common::String &str);
 
 } // End of namespace NGI


Commit: bb879ae56eb47c359d0c2e262cb20f4fbc07cfed
    https://github.com/scummvm/scummvm/commit/bb879ae56eb47c359d0c2e262cb20f4fbc07cfed
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
PARALLACTION: Migrate engine to Path

Changed paths:
    engines/parallaction/disk_br.cpp
    engines/parallaction/disk_ns.cpp


diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 87151b2dd21..72d8f3b27a3 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -92,12 +92,12 @@ Common::SeekableReadStream *Disk_br::openFile_internal(bool errorOnNotFound, con
 	assert(!name.empty());
 	debugC(5, kDebugDisk, "Disk_br::openFile(%s, %s)", name.c_str(), ext.c_str());
 
-	Common::String lookup(name);
+	Common::Path lookup(name);
 
 	if (!ext.empty() && !name.hasSuffix(ext.c_str())) {
 		// make sure we are using the specified extension
 		debugC(9, kDebugDisk, "Disk_br::openFile: appending explicit extension (%s) to (%s)", ext.c_str(), name.c_str());
-		lookup = name + ext;
+		lookup.appendInPlace(ext);
 	}
 
 	Common::SeekableReadStream *stream = _sset.createReadStreamForMember(lookup);
@@ -106,16 +106,16 @@ Common::SeekableReadStream *Disk_br::openFile_internal(bool errorOnNotFound, con
 	}
 
 	// as a very last resort, try trimming the file name to 8 chars
-	if (!ext.empty() && lookup.hasSuffix(ext.c_str())) {
-		Common::String filename = Common::lastPathComponent(lookup, '/');
+	Common::String filename = lookup.baseName();
+	if (!ext.empty() && filename.hasSuffix(ext.c_str())) {
 		int len = filename.size();
 		if (len > 8) {
 			debugC(9, kDebugDisk, "Disk_br::openFile: trimming filename (%s) to 8 characters", name.c_str());
 			while (len-- > 8) {
-				lookup.deleteLastChar();
+				filename.deleteLastChar();
 			}
-			lookup += ext;
-			stream = _sset.createReadStreamForMember(lookup);
+			filename += ext;
+			stream = _sset.createReadStreamForMember(lookup.getParent().appendComponent(filename));
 		}
 	}
 
@@ -146,7 +146,7 @@ Common::String DosDisk_br::selectArchive(const Common::String& name) {
 
 	debugC(5, kDebugDisk, "DosDisk_br::selectArchive: adding part directory to search set");
 	_sset.remove("part");
-	_sset.add("part", _baseDir->getSubDirectory(name, 3), 10);
+	_sset.add("part", _baseDir->getSubDirectory(Common::Path(name), 3), 10);
 
 	return oldPath;
 }
@@ -163,7 +163,7 @@ DosDisk_br::DosDisk_br(Parallaction* vm) : Disk_br(vm) {
 void DosDisk_br::init() {
 	// TODO: clarify whether the engine or OSystem should add the base game directory to the search manager.
 	// Right now, I am keeping an internal search set to do the job.
-	_baseDir = new Common::FSDirectory(ConfMan.get("path"));
+	_baseDir = new Common::FSDirectory(ConfMan.getPath("path"));
 	_sset.add("base", _baseDir, 5, true);
 }
 
@@ -414,7 +414,7 @@ DosDemoDisk_br::DosDemoDisk_br(Parallaction *vm) : DosDisk_br(vm) {
 void DosDemoDisk_br::init() {
 	// TODO: clarify whether the engine or OSystem should add the base game directory to the search manager.
 	// Right now, I am keeping an internal search set to do the job.
-	_baseDir = new Common::FSDirectory(ConfMan.get("path"), 2);
+	_baseDir = new Common::FSDirectory(ConfMan.getPath("path"), 2);
 	_sset.add("base", _baseDir, 5, false);
 }
 
@@ -431,11 +431,11 @@ AmigaDisk_br::AmigaDisk_br(Parallaction *vm) : DosDisk_br(vm) {
 }
 
 void AmigaDisk_br::init() {
-	_baseDir = new Common::FSDirectory(ConfMan.get("path"));
+	_baseDir = new Common::FSDirectory(ConfMan.getPath("path"));
 	_sset.add("base", _baseDir, 5, false);
 
-	const Common::String subDirNames[3] = { "fonts", "backs", "common" };
-	const Common::String subDirPrefixes[3] = { "fonts", "backs", "" };
+	const char *subDirNames[3] = { "fonts", "backs", "common" };
+	const char *subDirPrefixes[3] = { "fonts", "backs", "" };
 	// The common sub directory, doesn't exist in the Amiga demo
 	uint numDir = (_vm->getFeatures() & GF_DEMO) ? 2 : 3;
 	for (uint i = 0; i < numDir; i++)
@@ -751,7 +751,7 @@ Common::String AmigaDisk_br::selectArchive(const Common::String& name) {
 
 	debugC(5, kDebugDisk, "AmigaDisk_br::selectArchive: adding part directory to search set");
 	_sset.remove("part");
-	_sset.add("part", _baseDir->getSubDirectory(name, 3), 10);
+	_sset.add("part", _baseDir->getSubDirectory(Common::Path(name), 3), 10);
 
 	return oldPath;
 }
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 57919e1ebc5..5a6ff419a72 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -158,11 +158,12 @@ const Common::ArchiveMemberPtr NSArchive::getMember(const Common::Path &path) co
 	Common::String name = path.toString();
 	uint32 index = lookup(name.c_str());
 
-	const char *item = nullptr;
-	if (index < _numFiles) {
-		item = _archiveDir[index];
+	if (index >= _numFiles) {
+		return Common::ArchiveMemberPtr();
 	}
 
+	const char *item = _archiveDir[index];
+
 	return Common::SharedPtr<Common::GenericArchiveMember>(new Common::GenericArchiveMember(Common::String(item), *this));
 }
 
@@ -173,7 +174,7 @@ const Common::ArchiveMemberPtr NSArchive::getMember(const Common::Path &path) co
 #define LOWEST_ARCHIVE_PRIORITY		1
 
 Disk_ns::Disk_ns(Parallaction *vm) : _vm(vm) {
-	Common::FSDirectory *baseDir = new Common::FSDirectory(ConfMan.get("path"));
+	Common::FSDirectory *baseDir = new Common::FSDirectory(ConfMan.getPath("path"));
 	_sset.add("basedir", baseDir, HIGHEST_PRIORITY);
 }
 
@@ -194,7 +195,7 @@ Common::SeekableReadStream *Disk_ns::openFile(const char *filename) {
 
 
 void Disk_ns::addArchive(const Common::String& name, int priority) {
-	Common::SeekableReadStream *stream = _sset.createReadStreamForMember(name);
+	Common::SeekableReadStream *stream = _sset.createReadStreamForMember(Common::Path(name));
 	if (!stream)
 		error("Disk_ns::addArchive() couldn't find archive '%s'", name.c_str());
 


Commit: ffe2ad54462c11832500c554f0ecd02b7935a180
    https://github.com/scummvm/scummvm/commit/ffe2ad54462c11832500c554f0ecd02b7935a180
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
PEGASUS: Migrate engine to Path

Changed paths:
    engines/pegasus/ai/ai_action.cpp
    engines/pegasus/ai/ai_action.h
    engines/pegasus/ai/ai_area.cpp
    engines/pegasus/ai/ai_area.h
    engines/pegasus/elements.cpp
    engines/pegasus/elements.h
    engines/pegasus/interaction.h
    engines/pegasus/items/biochips/aichip.cpp
    engines/pegasus/items/biochips/arthurchip.cpp
    engines/pegasus/items/biochips/arthurchip.h
    engines/pegasus/items/biochips/opticalchip.cpp
    engines/pegasus/items/inventorypicture.h
    engines/pegasus/menu.cpp
    engines/pegasus/movie.cpp
    engines/pegasus/movie.h
    engines/pegasus/neighborhood/caldoria/caldoria.cpp
    engines/pegasus/neighborhood/caldoria/caldoria.h
    engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
    engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
    engines/pegasus/neighborhood/caldoria/caldoriabomb.h
    engines/pegasus/neighborhood/mars/mars.cpp
    engines/pegasus/neighborhood/mars/mars.h
    engines/pegasus/neighborhood/neighborhood.cpp
    engines/pegasus/neighborhood/neighborhood.h
    engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
    engines/pegasus/neighborhood/norad/alpha/noradalpha.h
    engines/pegasus/neighborhood/norad/alpha/panorama.cpp
    engines/pegasus/neighborhood/norad/alpha/panorama.h
    engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
    engines/pegasus/neighborhood/norad/alpha/panoramascroll.h
    engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
    engines/pegasus/neighborhood/norad/delta/noraddelta.h
    engines/pegasus/neighborhood/norad/norad.cpp
    engines/pegasus/neighborhood/norad/norad.h
    engines/pegasus/neighborhood/prehistoric/prehistoric.cpp
    engines/pegasus/neighborhood/prehistoric/prehistoric.h
    engines/pegasus/neighborhood/tsa/fulltsa.cpp
    engines/pegasus/neighborhood/tsa/fulltsa.h
    engines/pegasus/neighborhood/tsa/tinytsa.cpp
    engines/pegasus/neighborhood/tsa/tinytsa.h
    engines/pegasus/neighborhood/wsc/wsc.cpp
    engines/pegasus/neighborhood/wsc/wsc.h
    engines/pegasus/pegasus.cpp
    engines/pegasus/pegasus.h
    engines/pegasus/sound.cpp
    engines/pegasus/sound.h
    engines/pegasus/surface.cpp
    engines/pegasus/surface.h


diff --git a/engines/pegasus/ai/ai_action.cpp b/engines/pegasus/ai/ai_action.cpp
index 25f471402c9..85f0f2acfb4 100644
--- a/engines/pegasus/ai/ai_action.cpp
+++ b/engines/pegasus/ai/ai_action.cpp
@@ -38,7 +38,7 @@ void AICompoundAction::performAIAction(AIRule *rule) {
 		(*it)->performAIAction(rule);
 }
 
-AIPlayMessageAction::AIPlayMessageAction(const Common::String &movieName, bool keepLastFrame, const InputBits interruptionFilter) {
+AIPlayMessageAction::AIPlayMessageAction(const Common::Path &movieName, bool keepLastFrame, const InputBits interruptionFilter) {
 	_movieName = movieName;
 	_keepLastFrame = keepLastFrame;
 	_interruptionFilter = interruptionFilter;
diff --git a/engines/pegasus/ai/ai_action.h b/engines/pegasus/ai/ai_action.h
index 38adafd2c6c..5214292a785 100644
--- a/engines/pegasus/ai/ai_action.h
+++ b/engines/pegasus/ai/ai_action.h
@@ -78,12 +78,12 @@ protected:
 
 class AIPlayMessageAction : public AIAction {
 public:
-	AIPlayMessageAction(const Common::String &movieName, bool keepLastFrame, const InputBits = kWarningInterruption);
+	AIPlayMessageAction(const Common::Path &movieName, bool keepLastFrame, const InputBits = kWarningInterruption);
 
 	void performAIAction(AIRule *) override;
 
 protected:
-	Common::String _movieName;
+	Common::Path _movieName;
 	InputBits _interruptionFilter;
 	bool _keepLastFrame;
 };
diff --git a/engines/pegasus/ai/ai_area.cpp b/engines/pegasus/ai/ai_area.cpp
index ba08b472d5c..0293244ef93 100644
--- a/engines/pegasus/ai/ai_area.cpp
+++ b/engines/pegasus/ai/ai_area.cpp
@@ -273,7 +273,7 @@ void AIArea::playAIAreaSequence(const LowerClientSignature, const LowerAreaSigna
 	unlockAI();
 }
 
-bool AIArea::playAIMovie(const LowerAreaSignature area, const Common::String &movieName, bool keepLastFrame, const InputBits interruptFilter) {
+bool AIArea::playAIMovie(const LowerAreaSignature area, const Common::Path &movieName, bool keepLastFrame, const InputBits interruptFilter) {
 	lockAIOut();
 
 	InputDevice.waitInput(interruptFilter);
diff --git a/engines/pegasus/ai/ai_area.h b/engines/pegasus/ai/ai_area.h
index e48b85da85b..cf6be5c7248 100644
--- a/engines/pegasus/ai/ai_area.h
+++ b/engines/pegasus/ai/ai_area.h
@@ -115,7 +115,7 @@ public:
 	// For PlayAIMovie, it is assumed that the client is the AI itself.
 	// This is used to play AI messages as well as Optical Memory video.
 	// Returns true if the movie played all the way through, false if it was interrupted.
-	bool playAIMovie(const LowerAreaSignature, const Common::String &movieName, bool keepLastFrame, const InputBits);
+	bool playAIMovie(const LowerAreaSignature, const Common::Path &movieName, bool keepLastFrame, const InputBits);
 
 	// Loop the requested sequence indefinitely.
 	void loopAIAreaSequence(const LowerClientSignature, const LowerAreaSignature, const TimeValue, const TimeValue);
diff --git a/engines/pegasus/elements.cpp b/engines/pegasus/elements.cpp
index 98f7f7ad672..0f47aeeda38 100644
--- a/engines/pegasus/elements.cpp
+++ b/engines/pegasus/elements.cpp
@@ -234,7 +234,7 @@ FrameSequence::~FrameSequence() {
 	delete _resFork;
 }
 
-void FrameSequence::useFileName(const Common::String &fileName) {
+void FrameSequence::useFileName(const Common::Path &fileName) {
 	_resFork->open(fileName);
 }
 
diff --git a/engines/pegasus/elements.h b/engines/pegasus/elements.h
index 564ed902926..afee5037d80 100644
--- a/engines/pegasus/elements.h
+++ b/engines/pegasus/elements.h
@@ -140,7 +140,7 @@ public:
 	FrameSequence(const DisplayElementID);
 	~FrameSequence() override;
 
-	void useFileName(const Common::String &fileName);
+	void useFileName(const Common::Path &fileName);
 
 	virtual void openFrameSequence();
 	virtual void closeFrameSequence();
diff --git a/engines/pegasus/interaction.h b/engines/pegasus/interaction.h
index 32b0f31bd2f..a8a1cdf3196 100644
--- a/engines/pegasus/interaction.h
+++ b/engines/pegasus/interaction.h
@@ -69,10 +69,10 @@ public:
 	bool isInteracting() const { return _isInteracting; }
 	Neighborhood *getOwner() const { return _owner; }
 
-	virtual Common::String getBriefingMovie() { return ""; }
-	virtual Common::String getEnvScanMovie() { return ""; }
+	virtual Common::Path getBriefingMovie() { return Common::Path(); }
+	virtual Common::Path getEnvScanMovie() { return Common::Path(); }
 	virtual long getNumHints() { return 0; }
-	virtual Common::String getHintMovie(uint) { return ""; }
+	virtual Common::Path getHintMovie(uint) { return Common::Path(); }
 	virtual bool canSolve() { return false; }
 
 	virtual void setSoundFXLevel(const uint16) {}
diff --git a/engines/pegasus/items/biochips/aichip.cpp b/engines/pegasus/items/biochips/aichip.cpp
index d932d2f71d9..fed317d2023 100644
--- a/engines/pegasus/items/biochips/aichip.cpp
+++ b/engines/pegasus/items/biochips/aichip.cpp
@@ -210,7 +210,7 @@ void AIChip::clearClicked() {
 }
 
 void AIChip::clickInAIHotspot(HotSpotID id) {
-	Common::String movieName;
+	Common::Path movieName;
 
 	switch (id) {
 	case kAIBriefingSpotID:
diff --git a/engines/pegasus/items/biochips/arthurchip.cpp b/engines/pegasus/items/biochips/arthurchip.cpp
index 9dc3ab5ac98..4e4a4ccf73b 100644
--- a/engines/pegasus/items/biochips/arthurchip.cpp
+++ b/engines/pegasus/items/biochips/arthurchip.cpp
@@ -238,7 +238,7 @@ void ArthurChip::clickInArthurHotspot(HotSpotID id) {
 	setItemState(state);
 }
 
-void ArthurChip::playArthurMovie(const Common::String &movieName) {
+void ArthurChip::playArthurMovie(const Common::Path &movieName) {
 	if (g_AIArea) {
 		g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kHintInterruption);
 		if (movieName != "Images/AI/Globals/XGLOB00" &&
@@ -250,7 +250,7 @@ void ArthurChip::playArthurMovie(const Common::String &movieName) {
 	}
 }
 
-bool ArthurChip::playArthurMovieForEvent(const Common::String &movieName, ArthurEvent event) {
+bool ArthurChip::playArthurMovieForEvent(const Common::Path &movieName, ArthurEvent event) {
 	if (g_vm->isDVD() && g_vm->playerHasItemID(kArthurBiochip) &&
 		g_vm->isChattyArthur() && !Arthur._arthurFlags.getFlag(event)) {
 		Arthur._arthurFlags.setFlag(event, true);
diff --git a/engines/pegasus/items/biochips/arthurchip.h b/engines/pegasus/items/biochips/arthurchip.h
index 83ce4fe84b6..ce5a51a99d2 100644
--- a/engines/pegasus/items/biochips/arthurchip.h
+++ b/engines/pegasus/items/biochips/arthurchip.h
@@ -187,15 +187,15 @@ public:
 	void setUpArthurChip();
 	void activateArthurHotspots();
 	void clickInArthurHotspot(HotSpotID);
-	void playArthurMovie(const Common::String &);
-	bool playArthurMovieForEvent(const Common::String &, ArthurEvent event);
+	void playArthurMovie(const Common::Path &);
+	bool playArthurMovieForEvent(const Common::Path &, ArthurEvent event);
 
 protected:
 	Hotspot _arthurWisdomHotspot;
 	Hotspot _chattyArthurHotspot;
 	Hotspot _chattyAIHotspot;
 	Hotspot _arthurHeadHotspot;
-	Common::String _lastArthurMovie;
+	Common::Path _lastArthurMovie;
 };
 
 class ArthurManager : public Common::Singleton<ArthurManager> {
diff --git a/engines/pegasus/items/biochips/opticalchip.cpp b/engines/pegasus/items/biochips/opticalchip.cpp
index dd9bd0552a7..09809ba9be0 100644
--- a/engines/pegasus/items/biochips/opticalchip.cpp
+++ b/engines/pegasus/items/biochips/opticalchip.cpp
@@ -123,7 +123,7 @@ void OpticalChip::clickInOpticalHotspot(HotSpotID id) {
 }
 
 void OpticalChip::playOpMemMovie(HotSpotID id) {
-	Common::String movieName;
+	Common::Path movieName;
 	switch (id) {
 	case kAriesSpotID:
 		// WORKAROUND: The original CD release played the ares video even
diff --git a/engines/pegasus/items/inventorypicture.h b/engines/pegasus/items/inventorypicture.h
index 2146f127f2e..fad32be27c5 100644
--- a/engines/pegasus/items/inventorypicture.h
+++ b/engines/pegasus/items/inventorypicture.h
@@ -77,9 +77,9 @@ protected:
 	Common::Rect _highlightBounds;
 	bool _active, _shouldDrawHighlight;
 
-	Common::String _pictName;
-	Common::String _movieName;
-	Common::String _highlightName;
+	Common::Path _pictName;
+	Common::Path _movieName;
+	Common::Path _highlightName;
 	uint16 _itemsPerRow;
 	uint16 _numberOfRows;
 	uint16 _itemWidth;
diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp
index 02c9a5264b3..1806da6a5b5 100644
--- a/engines/pegasus/menu.cpp
+++ b/engines/pegasus/menu.cpp
@@ -733,7 +733,7 @@ DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _d
 		imageName += ".pict";
 	}
 
-	_deathBackground.initFromPICTFile(imageName);
+	_deathBackground.initFromPICTFile(Common::Path(imageName));
 	_deathReason = deathReason;
 
 	if (!isDemo) {
@@ -748,16 +748,16 @@ DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _d
 
 	if (isDemo) {
 		if (_playerWon) // Make credits button...
-			_continueButton.initFromPICTFile(prefix + "Credits.pict");
+			_continueButton.initFromPICTFile(Common::Path(prefix + "Credits.pict"));
 		else            // Make continue button...
-			_continueButton.initFromPICTFile(prefix + "Continue.pict");
+			_continueButton.initFromPICTFile(Common::Path(prefix + "Continue.pict"));
 
-		_mainMenuButton.initFromPICTFile(prefix + "MainMenu.pict");
+		_mainMenuButton.initFromPICTFile(Common::Path(prefix + "MainMenu.pict"));
 		_mainMenuButton.setDisplayOrder(1);
 		_mainMenuButton.moveElementTo(kMainMenuLeftDemo, kMainMenuTopDemo);
 		_mainMenuButton.startDisplaying();
 
-		_quitButton.initFromPICTFile(prefix + "Quit.pict");
+		_quitButton.initFromPICTFile(Common::Path(prefix + "Quit.pict"));
 		_quitButton.setDisplayOrder(1);
 		_quitButton.moveElementTo(kQuitLeftDemo, kQuitTopDemo);
 		_quitButton.startDisplaying();
@@ -765,23 +765,23 @@ DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _d
 		_menuSelection = kDeathScreenContinueDemo;
 	} else {
 		if (!_playerWon) {
-			_mainMenuButton.initFromPICTFile(prefix + "MainMenu.pict");
+			_mainMenuButton.initFromPICTFile(Common::Path(prefix + "MainMenu.pict"));
 			_mainMenuButton.setDisplayOrder(1);
 			_mainMenuButton.moveElementTo(kMainMenuLeft, kMainMenuTop);
 			_mainMenuButton.startDisplaying();
 
-			_restoreButton.initFromPICTFile(prefix + "Restore.pict");
+			_restoreButton.initFromPICTFile(Common::Path(prefix + "Restore.pict"));
 			_restoreButton.setDisplayOrder(1);
 			_restoreButton.moveElementTo(kRestoreLeftDeath, kRestoreTopDeath);
 			_restoreButton.startDisplaying();
 		}
 
-		_continueButton.initFromPICTFile(prefix + "Continue.pict");
+		_continueButton.initFromPICTFile(Common::Path(prefix + "Continue.pict"));
 
 		_menuSelection = kDeathScreenContinue;
 	}
 
-	_smallSelect.initFromPICTFile(prefix + "SelectS.pict", true);
+	_smallSelect.initFromPICTFile(Common::Path(prefix + "SelectS.pict"), true);
 	_smallSelect.setDisplayOrder(2);
 	_smallSelect.startDisplaying();
 
@@ -790,7 +790,7 @@ DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _d
 	_continueButton.startDisplaying();
 
 	if (isDemo || !_playerWon) {
-		_largeSelect.initFromPICTFile(prefix + "SelectL.pict", true);
+		_largeSelect.initFromPICTFile(Common::Path(prefix + "SelectL.pict"), true);
 		_largeSelect.setDisplayOrder(2);
 		_largeSelect.startDisplaying();
 	} else {
diff --git a/engines/pegasus/movie.cpp b/engines/pegasus/movie.cpp
index 4ed21e6e6f5..a2f799b8a65 100644
--- a/engines/pegasus/movie.cpp
+++ b/engines/pegasus/movie.cpp
@@ -53,7 +53,7 @@ void Movie::releaseMovie() {
 	setBounds(Common::Rect(0, 0, 0, 0));
 }
 
-void Movie::initFromMovieFile(const Common::String &fileName, bool transparent) {
+void Movie::initFromMovieFile(const Common::Path &fileName, bool transparent) {
 	_transparent = transparent;
 
 	releaseMovie();
@@ -62,14 +62,14 @@ void Movie::initFromMovieFile(const Common::String &fileName, bool transparent)
 		// Replace any colon with an underscore, since only macOS
 		// supports that. See PegasusEngine::detectOpeningClosingDirectory()
 		// for more info.
-		Common::String newName(fileName);
+		Common::String newName(fileName.toString('/'));
 		if (newName.contains(':'))
 			for (uint i = 0; i < newName.size(); i++)
 				if (newName[i] == ':')
 					newName.setChar('_', i);
 
-		if (!_video->loadFile(newName))
-			error("Could not load video '%s'", fileName.c_str());
+		if (!_video->loadFile(Common::Path(newName)))
+			error("Could not load video '%s'", fileName.toString().c_str());
 	}
 
 	Common::Rect bounds(0, 0, _video->getWidth(), _video->getHeight());
diff --git a/engines/pegasus/movie.h b/engines/pegasus/movie.h
index 84bb0f593da..20427769389 100644
--- a/engines/pegasus/movie.h
+++ b/engines/pegasus/movie.h
@@ -41,7 +41,7 @@ public:
 	Movie(const DisplayElementID);
 	~Movie() override;
 
-	virtual void initFromMovieFile(const Common::String &fileName, bool transparent = false);
+	virtual void initFromMovieFile(const Common::Path &fileName, bool transparent = false);
 
 	bool isMovieValid() { return _video != 0; }
 
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
index 1e8899936bb..f5b7cb48065 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
@@ -238,7 +238,7 @@ void Caldoria::start() {
 
 	if (!GameState.getCaldoriaSeenPullback()) {
 		Input input;
-		Common::String wakeModeMoviePath;
+		Common::Path wakeModeMoviePath;
 		InputDevice.getInput(input, kPullbackInterruptFilter);
 		if (_vm->isDVD() && JMPPPInput::isEasterEggModifierInput(input)) {
 			wakeModeMoviePath = "Images/Caldoria/A00WM";
@@ -334,14 +334,14 @@ void Caldoria::start() {
 				Video::VideoDecoder* wakeModeMovie = nullptr;
 #ifdef USE_THEORADEC
 				wakeModeMovie = new Video::TheoraDecoder();
-				if (!wakeModeMovie->loadFile(wakeModeMoviePath + ".ogg")) {
+				if (!wakeModeMovie->loadFile(wakeModeMoviePath.append(".ogg"))) {
 					delete wakeModeMovie;
 					wakeModeMovie = nullptr;
 				}
 #endif
 				if (!wakeModeMovie) {
 					wakeModeMovie = new Video::QuickTimeDecoder();
-					if (!wakeModeMovie->loadFile(wakeModeMoviePath + ".movie"))
+					if (!wakeModeMovie->loadFile(wakeModeMoviePath.append(".movie")))
 						error("Could not load Jonny Ego movie");
 				}
 
@@ -2465,8 +2465,8 @@ void Caldoria::checkInterruptSinclair() {
 	}
 }
 
-Common::String Caldoria::getBriefingMovie() {
-	Common::String movieName = Neighborhood::getBriefingMovie();
+Common::Path Caldoria::getBriefingMovie() {
+	Common::Path movieName = Neighborhood::getBriefingMovie();
 
 	if (movieName.empty()) {
 		if (GameState.allTimeZonesFinished())
@@ -2478,8 +2478,8 @@ Common::String Caldoria::getBriefingMovie() {
 	return movieName;
 }
 
-Common::String Caldoria::getEnvScanMovie() {
-	Common::String movieName = Neighborhood::getEnvScanMovie();
+Common::Path Caldoria::getEnvScanMovie() {
+	Common::Path movieName = Neighborhood::getEnvScanMovie();
 
 	if (movieName.empty()) {
 		RoomID room = GameState.getCurrentRoom();
@@ -2537,8 +2537,8 @@ uint Caldoria::getNumHints() {
 	return numHints;
 }
 
-Common::String Caldoria::getHintMovie(uint hintNum) {
-	Common::String movieName = Neighborhood::getHintMovie(hintNum);
+Common::Path Caldoria::getHintMovie(uint hintNum) {
+	Common::Path movieName = Neighborhood::getHintMovie(hintNum);
 
 	if (movieName.empty()) {
 		switch (GameState.getCurrentRoomAndView()) {
@@ -2591,11 +2591,11 @@ void Caldoria::updateCursor(const Common::Point where, const Hotspot *cursorSpot
 	Neighborhood::updateCursor(where, cursorSpot);
 }
 
-Common::String Caldoria::getNavMovieName() {
+Common::Path Caldoria::getNavMovieName() {
 	return "Images/Caldoria/Caldoria.movie";
 }
 
-Common::String Caldoria::getSoundSpotsName() {
+Common::Path Caldoria::getSoundSpotsName() {
 	return "Sounds/Caldoria/Caldoria Spots";
 }
 
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.h b/engines/pegasus/neighborhood/caldoria/caldoria.h
index 25a1632e135..b556f5bdf91 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoria.h
+++ b/engines/pegasus/neighborhood/caldoria/caldoria.h
@@ -415,10 +415,10 @@ public:
 
 	GameInteraction *makeInteraction(const InteractionID) override;
 
-	Common::String getBriefingMovie() override;
-	Common::String getEnvScanMovie() override;
+	Common::Path getBriefingMovie() override;
+	Common::Path getEnvScanMovie() override;
 	uint getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 	void loadAmbientLoops() override;
 	bool wantsCursor() override;
 	void flushGameState() override;
@@ -535,8 +535,8 @@ protected:
 
 	SinclairCallBack _sinclairInterrupt;
 
-	Common::String getSoundSpotsName() override;
-	Common::String getNavMovieName() override;
+	Common::Path getSoundSpotsName() override;
+	Common::Path getNavMovieName() override;
 };
 
 } // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
index 83948881827..9b06f14dda0 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
@@ -385,7 +385,7 @@ void Caldoria4DSystem::playSound(const Common::String &baseFileName) {
 	if (g_vm->isDVD())
 		fileName += ".44K";
 
-	_owner->loadLoopSound1(fileName + ".aiff");
+	_owner->loadLoopSound1(Common::Path(fileName + ".aiff"));
 }
 
 } // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
index 7cb902db6ed..5bfdbfc2fd4 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
@@ -1234,7 +1234,7 @@ void CaldoriaBomb::closeInteraction() {
 	_neighborhoodNotification->cancelNotification(this);
 }
 
-void CaldoriaBomb::startBombAmbient(Common::String ambient) {
+void CaldoriaBomb::startBombAmbient(const Common::Path &ambient) {
 	_owner->loadLoopSound1(ambient);
 }
 
@@ -1266,7 +1266,7 @@ void CaldoriaBomb::receiveNotification(Notification *notification, const Notific
 			_currentLevel++;
 			_grid.drawEdges(_bombLevel[_currentLevel]);
 			_lastVertex = -1;
-			startBombAmbient(Common::String::format("Sounds/Caldoria/BmbLoop%d.22K.AIFF", _owner->getLastExtra() - kCaldoria56BombStage1 + 1));
+			startBombAmbient(Common::Path(Common::String::format("Sounds/Caldoria/BmbLoop%d.22K.AIFF", _owner->getLastExtra() - kCaldoria56BombStage1 + 1)));
 			break;
 		case kCaldoria56BombStage7:
 			_owner->requestDeleteCurrentInteraction();
@@ -1454,7 +1454,7 @@ long CaldoriaBomb::getNumHints() {
 	return 2;
 }
 
-Common::String CaldoriaBomb::getHintMovie(uint hintNum) {
+Common::Path CaldoriaBomb::getHintMovie(uint hintNum) {
 	return (hintNum == 1) ? "Images/AI/Caldoria/X56EH2" : "Images/AI/Caldoria/X56EH3";
 }
 
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
index 835f5175080..be31043f951 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
+++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
@@ -125,7 +125,7 @@ public:
 	void setAmbienceLevel(const uint16) override;
 
 	long getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 	void doSolve() override;
 	bool canSolve() override;
 
@@ -138,7 +138,7 @@ protected:
 	void clickInHotspot(const Input &, const Hotspot *) override;
 	void handleInput(const Input &, const Hotspot *) override;
 	InputBits getInputFilter() override;
-	void startBombAmbient(Common::String);
+	void startBombAmbient(const Common::Path &);
 
 	Notification *_neighborhoodNotification;
 	BombGrid _grid;
diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp
index 88330eefb41..1f4f60a8994 100644
--- a/engines/pegasus/neighborhood/mars/mars.cpp
+++ b/engines/pegasus/neighborhood/mars/mars.cpp
@@ -4433,8 +4433,8 @@ void Mars::didntFindBomb() {
 	die(kDeathDidntFindMarsBomb);
 }
 
-Common::String Mars::getBriefingMovie() {
-	Common::String movieName = Neighborhood::getBriefingMovie();
+Common::Path Mars::getBriefingMovie() {
+	Common::Path movieName = Neighborhood::getBriefingMovie();
 
 	if (!movieName.empty())
 		return movieName;
@@ -4442,8 +4442,8 @@ Common::String Mars::getBriefingMovie() {
 	return "Images/AI/Mars/XM01";
 }
 
-Common::String Mars::getEnvScanMovie() {
-	Common::String movieName = Neighborhood::getEnvScanMovie();
+Common::Path Mars::getEnvScanMovie() {
+	Common::Path movieName = Neighborhood::getEnvScanMovie();
 
 	if (movieName.empty()) {
 		RoomID room = GameState.getCurrentRoom();
@@ -4536,8 +4536,8 @@ uint Mars::getNumHints() {
 	return numHints;
 }
 
-Common::String Mars::getHintMovie(uint hintNum) {
-	Common::String movieName = Neighborhood::getHintMovie(hintNum);
+Common::Path Mars::getHintMovie(uint hintNum) {
+	Common::Path movieName = Neighborhood::getHintMovie(hintNum);
 
 	if (movieName.empty()) {
 		switch (GameState.getCurrentRoomAndView()) {
@@ -4592,7 +4592,7 @@ Common::String Mars::getHintMovie(uint hintNum) {
 			return "Images/AI/Globals/XGLOB3F";
 		case MakeRoomView(kMars56, kEast):
 			if (getCurrentActivation() == kActivateReactorReadyForNitrogen)
-				return Common::String::format("Images/AI/Mars/XM57SD%d", hintNum);
+				return Common::Path(Common::String::format("Images/AI/Mars/XM57SD%d", hintNum));
 
 			if (hintNum == 1) {
 				if (GameState.isTakenItemID(kShieldBiochip))
@@ -4635,11 +4635,11 @@ void Mars::doSolve() {
 	}
 }
 
-Common::String Mars::getSoundSpotsName() {
+Common::Path Mars::getSoundSpotsName() {
 	return "Sounds/Mars/Mars Spots";
 }
 
-Common::String Mars::getNavMovieName() {
+Common::Path Mars::getNavMovieName() {
 	return "Images/Mars/Mars.movie";
 }
 
diff --git a/engines/pegasus/neighborhood/mars/mars.h b/engines/pegasus/neighborhood/mars/mars.h
index d4d9af05eae..8f42d4c1932 100644
--- a/engines/pegasus/neighborhood/mars/mars.h
+++ b/engines/pegasus/neighborhood/mars/mars.h
@@ -91,10 +91,10 @@ public:
 	void decreaseRobotShuttleEnergy(const int, Common::Point impactPoint);
 	void setUpNextDropTime();
 
-	Common::String getBriefingMovie() override;
-	Common::String getEnvScanMovie() override;
+	Common::Path getBriefingMovie() override;
+	Common::Path getEnvScanMovie() override;
 	uint getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 
 	void shieldOn() override;
 	void shieldOff() override;
@@ -197,8 +197,8 @@ protected:
 	void updateCursor(const Common::Point, const Hotspot *) override;
 	void playSpaceAmbient();
 
-	Common::String getSoundSpotsName() override;
-	Common::String getNavMovieName() override;
+	Common::Path getSoundSpotsName() override;
+	Common::Path getNavMovieName() override;
 
 	Movie _extraMovie;
 	NotificationCallBack _extraMovieCallBack;
diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp
index c99ad5dcab9..b95a2dd4ecb 100644
--- a/engines/pegasus/neighborhood/neighborhood.cpp
+++ b/engines/pegasus/neighborhood/neighborhood.cpp
@@ -148,7 +148,7 @@ void Neighborhood::init() {
 	_navMovie.initFromMovieFile(getNavMovieName());
 	_navMovie.setVolume(_vm->getSoundFXLevel());
 
-	Common::String soundSpotsName = getSoundSpotsName();
+	Common::Path soundSpotsName = getSoundSpotsName();
 	if (soundSpotsName.empty()) {
 		_spotSounds.disposeSound();
 	} else {
@@ -505,18 +505,18 @@ bool operator!=(const QueueRequest &arg1, const QueueRequest &arg2) {
 	return !operator==(arg1, arg2);
 }
 
-Common::String Neighborhood::getBriefingMovie() {
+Common::Path Neighborhood::getBriefingMovie() {
 	if (_currentInteraction)
 		return _currentInteraction->getBriefingMovie();
 
-	return Common::String();
+	return Common::Path();
 }
 
-Common::String Neighborhood::getEnvScanMovie() {
+Common::Path Neighborhood::getEnvScanMovie() {
 	if (_currentInteraction)
 		return _currentInteraction->getEnvScanMovie();
 
-	return Common::String();
+	return Common::Path();
 }
 
 uint Neighborhood::getNumHints() {
@@ -526,11 +526,11 @@ uint Neighborhood::getNumHints() {
 	return 0;
 }
 
-Common::String Neighborhood::getHintMovie(uint hintNum) {
+Common::Path Neighborhood::getHintMovie(uint hintNum) {
 	if (_currentInteraction)
 		return _currentInteraction->getHintMovie(hintNum);
 
-	return Common::String();
+	return Common::Path();
 }
 
 bool Neighborhood::canSolve() {
@@ -1468,7 +1468,7 @@ void Neighborhood::zoomUpOrBump() {
 		bumpIntoWall();
 }
 
-void Neighborhood::loadLoopSound1(const Common::String &soundName, uint16 volume, TimeValue fadeOut, TimeValue fadeIn, TimeScale fadeScale) {
+void Neighborhood::loadLoopSound1(const Common::Path &soundName, uint16 volume, TimeValue fadeOut, TimeValue fadeIn, TimeScale fadeScale) {
 	FaderMoveSpec faderMove;
 
 	if (!loop1Loaded(soundName)) {
@@ -1495,7 +1495,7 @@ void Neighborhood::loadLoopSound1(const Common::String &soundName, uint16 volume
 	}
 }
 
-void Neighborhood::loadLoopSound2(const Common::String &soundName, uint16 volume, TimeValue fadeOut, TimeValue fadeIn, TimeScale fadeScale) {
+void Neighborhood::loadLoopSound2(const Common::Path &soundName, uint16 volume, TimeValue fadeOut, TimeValue fadeIn, TimeScale fadeScale) {
 	FaderMoveSpec faderMove;
 
 	if (!loop2Loaded(soundName)) {
@@ -1579,7 +1579,7 @@ void Neighborhood::startExtraLongSequence(const uint32 firstExtra, const uint32
 	}
 }
 
-void Neighborhood::openCroppedMovie(const Common::String &movieName, CoordType left, CoordType top) {
+void Neighborhood::openCroppedMovie(const Common::Path &movieName, CoordType left, CoordType top) {
 	if (_croppedMovie.isMovieValid())
 		closeCroppedMovie();
 
@@ -1589,7 +1589,7 @@ void Neighborhood::openCroppedMovie(const Common::String &movieName, CoordType l
 	_croppedMovie.show();
 }
 
-void Neighborhood::loopCroppedMovie(const Common::String &movieName, CoordType left, CoordType top) {
+void Neighborhood::loopCroppedMovie(const Common::Path &movieName, CoordType left, CoordType top) {
 	openCroppedMovie(movieName, left, top);
 	_croppedMovie.setVolume(_vm->getSoundFXLevel());
 	_croppedMovie.redrawMovieWorld();
@@ -1601,7 +1601,7 @@ void Neighborhood::closeCroppedMovie() {
 	_croppedMovie.releaseMovie();
 }
 
-void Neighborhood::playCroppedMovieOnce(const Common::String &movieName, CoordType left, CoordType top, const InputBits interruptionFilter) {
+void Neighborhood::playCroppedMovieOnce(const Common::Path &movieName, CoordType left, CoordType top, const InputBits interruptionFilter) {
 	openCroppedMovie(movieName, left, top);
 	_croppedMovie.setVolume(_vm->getSoundFXLevel());
 	_croppedMovie.redrawMovieWorld();
@@ -1724,7 +1724,7 @@ void Neighborhood::downButton(const Input &) {
 	}
 }
 
-void Neighborhood::initOnePicture(Picture *picture, const Common::String &pictureName, DisplayOrder order, CoordType left, CoordType top, bool show) {
+void Neighborhood::initOnePicture(Picture *picture, const Common::Path &pictureName, DisplayOrder order, CoordType left, CoordType top, bool show) {
 	picture->initFromPICTFile(pictureName);
 	picture->setDisplayOrder(order);
 	picture->moveElementTo(left, top);
@@ -1733,7 +1733,7 @@ void Neighborhood::initOnePicture(Picture *picture, const Common::String &pictur
 		picture->show();
 }
 
-void Neighborhood::initOneMovie(Movie *movie, const Common::String &movieName, DisplayOrder order, CoordType left, CoordType top, bool show) {
+void Neighborhood::initOneMovie(Movie *movie, const Common::Path &movieName, DisplayOrder order, CoordType left, CoordType top, bool show) {
 	movie->initFromMovieFile(movieName);
 	movie->setDisplayOrder(order);
 	movie->moveElementTo(left, top);
diff --git a/engines/pegasus/neighborhood/neighborhood.h b/engines/pegasus/neighborhood/neighborhood.h
index 15673f3db27..4d80d03c98b 100644
--- a/engines/pegasus/neighborhood/neighborhood.h
+++ b/engines/pegasus/neighborhood/neighborhood.h
@@ -197,13 +197,13 @@ public:
 
 	virtual void flushGameState() {}
 
-	virtual Common::String getBriefingMovie();
-	virtual Common::String getEnvScanMovie();
+	virtual Common::Path getBriefingMovie();
+	virtual Common::Path getEnvScanMovie();
 	virtual uint getNumHints();
-	virtual Common::String getHintMovie(uint);
+	virtual Common::Path getHintMovie(uint);
 	virtual bool canSolve();
-	virtual void prepareForAIHint(const Common::String &) {}
-	virtual void cleanUpAfterAIHint(const Common::String &) {}
+	virtual void prepareForAIHint(const Common::Path &) {}
+	virtual void cleanUpAfterAIHint(const Common::Path &) {}
 	virtual void doSolve();
 
 	virtual bool okayToJump();
@@ -214,14 +214,14 @@ public:
 	virtual void shieldOn() {}
 	virtual void shieldOff() {}
 
-	virtual void loadLoopSound1(const Common::String &, const uint16 volume = 0x100,
+	virtual void loadLoopSound1(const Common::Path &, const uint16 volume = 0x100,
 			const TimeValue fadeOut = kDefaultLoopFadeOut, const TimeValue fadeIn = kDefaultLoopFadeIn,
 			const TimeScale fadeScale = kDefaultLoopFadeScale);
-	virtual void loadLoopSound2(const Common::String &, const uint16 volume = 0x100,
+	virtual void loadLoopSound2(const Common::Path &, const uint16 volume = 0x100,
 			const TimeValue fadeOut = kDefaultLoopFadeOut, const TimeValue fadeIn = kDefaultLoopFadeIn,
 			const TimeScale fadeScale = kDefaultLoopFadeScale);
-	bool loop1Loaded(const Common::String &soundName) { return _loop1SoundString == soundName; }
-	bool loop2Loaded(const Common::String &soundName) { return _loop2SoundString == soundName; }
+	bool loop1Loaded(const Common::Path &soundName) { return _loop1SoundString == soundName; }
+	bool loop2Loaded(const Common::Path &soundName) { return _loop2SoundString == soundName; }
 	void startLoop1Fader(const FaderMoveSpec &);
 	void startLoop2Fader(const FaderMoveSpec &);
 
@@ -237,10 +237,10 @@ public:
 	virtual void showExtraView(uint32);
 	virtual void startExtraLongSequence(const uint32, const uint32, NotificationFlags, const InputBits interruptionFilter);
 
-	void openCroppedMovie(const Common::String &, CoordType, CoordType);
-	void loopCroppedMovie(const Common::String &, CoordType, CoordType);
+	void openCroppedMovie(const Common::Path &, CoordType, CoordType);
+	void loopCroppedMovie(const Common::Path &, CoordType, CoordType);
 	void closeCroppedMovie();
-	void playCroppedMovieOnce(const Common::String &, CoordType, CoordType, const InputBits interruptionFilter = kFilterNoInput);
+	void playCroppedMovieOnce(const Common::Path &, CoordType, CoordType, const InputBits interruptionFilter = kFilterNoInput);
 
 	void playMovieSegment(Movie *, TimeValue = 0, TimeValue = 0xffffffff);
 
@@ -254,8 +254,8 @@ protected:
 	PegasusEngine *_vm;
 	Common::String _resName;
 
-	virtual Common::String getSoundSpotsName() = 0;
-	virtual Common::String getNavMovieName() = 0;
+	virtual Common::Path getSoundSpotsName() = 0;
+	virtual Common::Path getNavMovieName() = 0;
 
 	// Notification function.
 	void receiveNotification(Notification *, const NotificationFlags) override;
@@ -320,8 +320,8 @@ protected:
 	virtual void rightButton(const Input &);
 	virtual void downButton(const Input &);
 
-	void initOnePicture(Picture *, const Common::String &, DisplayOrder, CoordType, CoordType, bool);
-	void initOneMovie(Movie *, const Common::String &, DisplayOrder, CoordType, CoordType, bool);
+	void initOnePicture(Picture *, const Common::Path &, DisplayOrder, CoordType, CoordType, bool);
+	void initOneMovie(Movie *, const Common::Path &, DisplayOrder, CoordType, CoordType, bool);
 
 	void reinstateMonocleInterface();
 
@@ -390,11 +390,11 @@ protected:
 	Movie _croppedMovie;
 
 	Sound _soundLoop1;
-	Common::String _loop1SoundString;
+	Common::Path _loop1SoundString;
 	SoundFader _loop1Fader;
 
 	Sound _soundLoop2;
-	Common::String _loop2SoundString;
+	Common::Path _loop2SoundString;
 	SoundFader _loop2Fader;
 
 	// The event timer...
diff --git a/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp b/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
index f131d04cd64..7ca7b6854d4 100644
--- a/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
+++ b/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
@@ -828,8 +828,8 @@ Hotspot *NoradAlpha::getItemScreenSpot(Item *item, DisplayElement *element) {
 	return Norad::getItemScreenSpot(item, element);
 }
 
-Common::String NoradAlpha::getEnvScanMovie() {
-	Common::String movieName = Neighborhood::getEnvScanMovie();
+Common::Path NoradAlpha::getEnvScanMovie() {
+	Common::Path movieName = Neighborhood::getEnvScanMovie();
 
 	if (movieName.empty()) {
 		RoomID room = GameState.getCurrentRoom();
@@ -879,8 +879,8 @@ uint NoradAlpha::getNumHints() {
 	return numHints;
 }
 
-Common::String NoradAlpha::getHintMovie(uint hintNum) {
-	Common::String movieName = Neighborhood::getHintMovie(hintNum);
+Common::Path NoradAlpha::getHintMovie(uint hintNum) {
+	Common::Path movieName = Neighborhood::getHintMovie(hintNum);
 
 	if (movieName.empty()) {
 		switch (GameState.getCurrentRoomAndView()) {
@@ -958,11 +958,11 @@ void NoradAlpha::doSolve() {
 	}
 }
 
-Common::String NoradAlpha::getNavMovieName() {
+Common::Path NoradAlpha::getNavMovieName() {
 	return "Images/Norad Alpha/Norad Alpha.movie";
 }
 
-Common::String NoradAlpha::getSoundSpotsName() {
+Common::Path NoradAlpha::getSoundSpotsName() {
 	return "Sounds/Norad/Norad Alpha Spots";
 }
 
diff --git a/engines/pegasus/neighborhood/norad/alpha/noradalpha.h b/engines/pegasus/neighborhood/norad/alpha/noradalpha.h
index 0f95ac4fc4a..a9a2faf453c 100644
--- a/engines/pegasus/neighborhood/norad/alpha/noradalpha.h
+++ b/engines/pegasus/neighborhood/norad/alpha/noradalpha.h
@@ -64,9 +64,9 @@ public:
 
 	void loadAmbientLoops() override;
 
-	Common::String getEnvScanMovie() override;
+	Common::Path getEnvScanMovie() override;
 	uint getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 	void setUpAIRules() override;
 
 	void setSubPrepFailed(bool value) { _subPrepFailed = value; }
@@ -117,8 +117,8 @@ protected:
 
 	bool _subPrepFailed;
 
-	Common::String getSoundSpotsName() override;
-	Common::String getNavMovieName() override;
+	Common::Path getSoundSpotsName() override;
+	Common::Path getNavMovieName() override;
 };
 
 } // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/alpha/panorama.cpp b/engines/pegasus/neighborhood/norad/alpha/panorama.cpp
index 506ece3fa3f..00ec3e752cb 100644
--- a/engines/pegasus/neighborhood/norad/alpha/panorama.cpp
+++ b/engines/pegasus/neighborhood/norad/alpha/panorama.cpp
@@ -58,15 +58,15 @@ void Panorama::releasePanorama() {
 static const uint32 kPanoramaResType = MKTAG('P', 'a', 'n', 'I'); // Panorama Information.
 static const uint16 kPanoramaResID = 128;
 
-void Panorama::initFromMovieFile(const Common::String &fileName) {
+void Panorama::initFromMovieFile(const Common::Path &fileName) {
 	// First, we need the resource fork for other reasons -- PanI resource
 	Common::MacResManager *resFork = new Common::MacResManager();
 	if (!resFork->open(fileName) || !resFork->hasResFork())
-		error("Could not open the resource fork of '%s'", fileName.c_str());
+		error("Could not open the resource fork of '%s'", fileName.toString().c_str());
 
 	Common::SeekableReadStream *resource = resFork->getResource(kPanoramaResType, kPanoramaResID);
 	if (!resource)
-		error("No panorama information in the resource fork of '%s'", fileName.c_str());
+		error("No panorama information in the resource fork of '%s'", fileName.toString().c_str());
 
 	_panoramaWidth = resource->readUint16BE();
 	_panoramaHeight = resource->readUint16BE();
diff --git a/engines/pegasus/neighborhood/norad/alpha/panorama.h b/engines/pegasus/neighborhood/norad/alpha/panorama.h
index e49b8114d5c..0baf8bed90e 100644
--- a/engines/pegasus/neighborhood/norad/alpha/panorama.h
+++ b/engines/pegasus/neighborhood/norad/alpha/panorama.h
@@ -62,7 +62,7 @@ public:
 	Panorama();
 	virtual ~Panorama();
 
-	void initFromMovieFile(const Common::String &);
+	void initFromMovieFile(const Common::Path &);
 	void releasePanorama();
 	bool isPanoramaOpen() { return _panoramaMovie.isMovieValid(); }
 
diff --git a/engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
index 15425afaf6d..76226e94fed 100644
--- a/engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
+++ b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
@@ -31,7 +31,7 @@ PanoramaScroll::PanoramaScroll(const DisplayElementID id) : IdlerAnimation(id) {
 	_totalWidth = 0;
 }
 
-void PanoramaScroll::initFromMovieFile(const Common::String &fileName) {
+void PanoramaScroll::initFromMovieFile(const Common::Path &fileName) {
 	_panorama.initFromMovieFile(fileName);
 
 	Common::Rect r;
@@ -39,7 +39,7 @@ void PanoramaScroll::initFromMovieFile(const Common::String &fileName) {
 	_totalWidth = r.width();
 }
 
-void PanoramaScroll::initMaskFromPICTFile(const Common::String &fileName) {
+void PanoramaScroll::initMaskFromPICTFile(const Common::Path &fileName) {
 	if (!_panorama.isPanoramaOpen())
 		return;
 
diff --git a/engines/pegasus/neighborhood/norad/alpha/panoramascroll.h b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.h
index f569376a2c6..1794e09e41f 100644
--- a/engines/pegasus/neighborhood/norad/alpha/panoramascroll.h
+++ b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.h
@@ -34,8 +34,8 @@ public:
 	PanoramaScroll(const DisplayElementID);
 	~PanoramaScroll() override {}
 
-	void initFromMovieFile(const Common::String &);
-	void initMaskFromPICTFile(const Common::String &);
+	void initFromMovieFile(const Common::Path &);
+	void initMaskFromPICTFile(const Common::Path &);
 
 	void releasePanorama();
 
diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
index 8660e9c1bfc..3349d5b3a9e 100644
--- a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
+++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
@@ -835,7 +835,7 @@ Hotspot *NoradDelta::getItemScreenSpot(Item *item, DisplayElement *element) {
 	return Norad::getItemScreenSpot(item, element);
 }
 
-Common::String NoradDelta::getEnvScanMovie() {
+Common::Path NoradDelta::getEnvScanMovie() {
 	return "Images/AI/Norad/XNE2";
 }
 
@@ -877,8 +877,8 @@ uint NoradDelta::getNumHints() {
 	return numHints;
 }
 
-Common::String NoradDelta::getHintMovie(uint hintNum) {
-	Common::String movieName = Neighborhood::getHintMovie(hintNum);
+Common::Path NoradDelta::getHintMovie(uint hintNum) {
+	Common::Path movieName = Neighborhood::getHintMovie(hintNum);
 
 	if (movieName.empty()) {
 		switch (GameState.getCurrentRoomAndView()) {
@@ -973,11 +973,11 @@ void NoradDelta::setSoundFXLevel(const uint16 level) {
 		_loop2Fader.setMasterVolume(level);
 }
 
-Common::String NoradDelta::getSoundSpotsName() {
+Common::Path NoradDelta::getSoundSpotsName() {
 	return "Sounds/Norad/Norad Delta Spots";
 }
 
-Common::String NoradDelta::getNavMovieName() {
+Common::Path NoradDelta::getNavMovieName() {
 	return "Images/Norad Delta/Norad Delta.movie";
 }
 
diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.h b/engines/pegasus/neighborhood/norad/delta/noraddelta.h
index 3fb9cfd4441..6b22ae12b3e 100644
--- a/engines/pegasus/neighborhood/norad/delta/noraddelta.h
+++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.h
@@ -57,9 +57,9 @@ public:
 	void loadAmbientLoops() override;
 
 	void setUpAIRules() override;
-	Common::String getEnvScanMovie() override;
+	Common::Path getEnvScanMovie() override;
 	uint getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 	void closeDoorOffScreen(const RoomID, const DirectionConstant) override;
 
 	void checkContinuePoint(const RoomID, const DirectionConstant) override;
@@ -111,8 +111,8 @@ protected:
 
 	FlagsArray<byte, kNumNoradPrivateFlags> _privateFlags;
 
-	Common::String getSoundSpotsName() override;
-	Common::String getNavMovieName() override;
+	Common::Path getSoundSpotsName() override;
+	Common::Path getNavMovieName() override;
 };
 
 } // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/norad.cpp b/engines/pegasus/neighborhood/norad/norad.cpp
index c042eb76ba4..643b7bc3226 100644
--- a/engines/pegasus/neighborhood/norad/norad.cpp
+++ b/engines/pegasus/neighborhood/norad/norad.cpp
@@ -283,7 +283,7 @@ uint16 Norad::getDateResID() const {
 	return kDate2112ID;
 }
 
-Common::String Norad::getBriefingMovie() {
+Common::Path Norad::getBriefingMovie() {
 	return "Images/AI/Norad/XNO";
 }
 
diff --git a/engines/pegasus/neighborhood/norad/norad.h b/engines/pegasus/neighborhood/norad/norad.h
index a834e987556..796d4ada502 100644
--- a/engines/pegasus/neighborhood/norad/norad.h
+++ b/engines/pegasus/neighborhood/norad/norad.h
@@ -51,7 +51,7 @@ public:
 
 	GameInteraction *makeInteraction(const InteractionID) override;
 
-	Common::String getBriefingMovie() override;
+	Common::Path getBriefingMovie() override;
 
 	void pickedUpItem(Item *) override;
 
diff --git a/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp b/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp
index dc0e9f37e68..3b8a1adac3b 100644
--- a/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp
+++ b/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp
@@ -681,8 +681,8 @@ void Prehistoric::spotCompleted() {
 		g_arthurChip->playArthurMovieForEvent("Images/AI/Globals/XGLOBA15", kArthurPrehistoricAtCliffEdge);
 }
 
-Common::String Prehistoric::getBriefingMovie() {
-	Common::String movieName = Neighborhood::getBriefingMovie();
+Common::Path Prehistoric::getBriefingMovie() {
+	Common::Path movieName = Neighborhood::getBriefingMovie();
 
 	if (movieName.empty())
 		movieName = "Images/AI/Prehistoric/XPE";
@@ -690,8 +690,8 @@ Common::String Prehistoric::getBriefingMovie() {
 	return movieName;
 }
 
-Common::String Prehistoric::getEnvScanMovie() {
-	Common::String movieName = Neighborhood::getEnvScanMovie();
+Common::Path Prehistoric::getEnvScanMovie() {
+	Common::Path movieName = Neighborhood::getEnvScanMovie();
 
 	if (movieName.empty()) {
 		if (!_vm->isOldDemo()) {
@@ -733,8 +733,8 @@ uint Prehistoric::getNumHints() {
 	return numHints;
 }
 
-Common::String Prehistoric::getHintMovie(uint hintNum) {
-	Common::String movieName = Neighborhood::getHintMovie(hintNum);
+Common::Path Prehistoric::getHintMovie(uint hintNum) {
+	Common::Path movieName = Neighborhood::getHintMovie(hintNum);
 
 	if (movieName.empty()) {
 		switch (GameState.getCurrentRoomAndView()) {
@@ -805,11 +805,11 @@ void Prehistoric::bumpIntoWall() {
 	Neighborhood::bumpIntoWall();
 }
 
-Common::String Prehistoric::getNavMovieName() {
+Common::Path Prehistoric::getNavMovieName() {
 	return "Images/Prehistoric/Prehistoric.movie";
 }
 
-Common::String Prehistoric::getSoundSpotsName() {
+Common::Path Prehistoric::getSoundSpotsName() {
 	return "Sounds/Prehistoric/Prehistoric Spots";
 }
 
diff --git a/engines/pegasus/neighborhood/prehistoric/prehistoric.h b/engines/pegasus/neighborhood/prehistoric/prehistoric.h
index b906e3f8fcf..fc02c213425 100644
--- a/engines/pegasus/neighborhood/prehistoric/prehistoric.h
+++ b/engines/pegasus/neighborhood/prehistoric/prehistoric.h
@@ -110,10 +110,10 @@ public:
 	void arriveAt(const RoomID, const DirectionConstant) override;
 	void activateHotspots() override;
 	void clickInHotspot(const Input &, const Hotspot *) override;
-	Common::String getBriefingMovie() override;
-	Common::String getEnvScanMovie() override;
+	Common::Path getBriefingMovie() override;
+	Common::Path getEnvScanMovie() override;
 	uint getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 
 	Hotspot *getItemScreenSpot(Item *, DisplayElement *) override;
 	void dropItemIntoRoom(Item *, Hotspot *) override;
@@ -149,8 +149,8 @@ protected:
 
 	FlagsArray<byte, kNumPrehistoricPrivateFlags> _privateFlags;
 
-	Common::String getNavMovieName() override;
-	Common::String getSoundSpotsName() override;
+	Common::Path getNavMovieName() override;
+	Common::Path getSoundSpotsName() override;
 };
 
 } // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
index 2ebd9f2ff7f..ca7c3185864 100644
--- a/engines/pegasus/neighborhood/tsa/fulltsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
@@ -733,8 +733,8 @@ void FullTSA::flushGameState() {
 	GameState.setTSAFuseTimeLimit(_utilityFuse.getTimeRemaining());
 }
 
-Common::String FullTSA::getBriefingMovie() {
-	Common::String movieName = Neighborhood::getBriefingMovie();
+Common::Path FullTSA::getBriefingMovie() {
+	Common::Path movieName = Neighborhood::getBriefingMovie();
 
 	if (movieName.empty()) {
 		RoomID room = GameState.getCurrentRoom();
@@ -791,8 +791,8 @@ Common::String FullTSA::getBriefingMovie() {
 	return movieName;
 }
 
-Common::String FullTSA::getEnvScanMovie() {
-	Common::String movieName = Neighborhood::getEnvScanMovie();
+Common::Path FullTSA::getEnvScanMovie() {
+	Common::Path movieName = Neighborhood::getEnvScanMovie();
 
 	if (movieName.empty()) {
 		switch (GameState.getTSAState()) {
@@ -859,11 +859,11 @@ uint FullTSA::getNumHints() {
 	return numHints;
 }
 
-Common::String FullTSA::getHintMovie(uint hintNum) {
-	Common::String movieName = Neighborhood::getHintMovie(hintNum);
+Common::Path FullTSA::getHintMovie(uint hintNum) {
+	Common::Path movieName = Neighborhood::getHintMovie(hintNum);
 
 	if (movieName.empty())
-		movieName = Common::String::format("Images/AI/TSA/XT20NH%d", hintNum);
+		movieName = Common::Path(Common::String::format("Images/AI/TSA/XT20NH%d", hintNum));
 
 	return movieName;
 }
@@ -3548,11 +3548,11 @@ void FullTSA::updateCursor(const Common::Point where, const Hotspot *cursorSpot)
 	Neighborhood::updateCursor(where, cursorSpot);
 }
 
-Common::String FullTSA::getNavMovieName() {
+Common::Path FullTSA::getNavMovieName() {
 	return "Images/TSA/Full TSA.movie";
 }
 
-Common::String FullTSA::getSoundSpotsName() {
+Common::Path FullTSA::getSoundSpotsName() {
 	return "Sounds/TSA/TSA Spots";
 }
 
diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.h b/engines/pegasus/neighborhood/tsa/fulltsa.h
index 38a1032cf8a..6f7cacd09f5 100644
--- a/engines/pegasus/neighborhood/tsa/fulltsa.h
+++ b/engines/pegasus/neighborhood/tsa/fulltsa.h
@@ -86,10 +86,10 @@ protected:
 		kNumTSAPrivateFlags
 	};
 
-	Common::String getBriefingMovie() override;
-	Common::String getEnvScanMovie() override;
+	Common::Path getBriefingMovie() override;
+	Common::Path getEnvScanMovie() override;
 	uint getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 	void loadAmbientLoops() override;
 	void clickInHotspot(const Input &, const Hotspot *) override;
 
@@ -164,8 +164,8 @@ protected:
 
 	FlagsArray<byte, kNumTSAPrivateFlags> _privateFlags;
 
-	Common::String getNavMovieName() override;
-	Common::String getSoundSpotsName() override;
+	Common::Path getNavMovieName() override;
+	Common::Path getSoundSpotsName() override;
 
 	void dieUncreatedInTSA();
 };
diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
index abd9167ad41..9380a59b911 100644
--- a/engines/pegasus/neighborhood/tsa/tinytsa.cpp
+++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
@@ -122,8 +122,8 @@ void TinyTSA::start() {
 	Neighborhood::start();
 }
 
-Common::String TinyTSA::getBriefingMovie() {
-	Common::String movieName = Neighborhood::getBriefingMovie();
+Common::Path TinyTSA::getBriefingMovie() {
+	Common::Path movieName = Neighborhood::getBriefingMovie();
 
 	if (movieName.empty()) {
 		switch (getCurrentActivation()) {
@@ -157,8 +157,8 @@ Common::String TinyTSA::getBriefingMovie() {
 	return movieName;
 }
 
-Common::String TinyTSA::getEnvScanMovie() {
-	Common::String movieName = Neighborhood::getEnvScanMovie();
+Common::Path TinyTSA::getEnvScanMovie() {
+	Common::Path movieName = Neighborhood::getEnvScanMovie();
 
 	if (movieName.empty()) {
 		g_AIChip->showEnvScanClicked();
@@ -478,7 +478,7 @@ void TinyTSA::arriveFromWSC() {
 	}
 }
 
-Common::String TinyTSA::getNavMovieName() {
+Common::Path TinyTSA::getNavMovieName() {
 	return "Images/TSA/Tiny TSA.movie";
 }
 
diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.h b/engines/pegasus/neighborhood/tsa/tinytsa.h
index bc1e924d4e4..6cad4cec050 100644
--- a/engines/pegasus/neighborhood/tsa/tinytsa.h
+++ b/engines/pegasus/neighborhood/tsa/tinytsa.h
@@ -45,8 +45,8 @@ public:
 	void checkContinuePoint(const RoomID, const DirectionConstant) override;
 
 protected:
-	Common::String getBriefingMovie() override;
-	Common::String getEnvScanMovie() override;
+	Common::Path getBriefingMovie() override;
+	Common::Path getEnvScanMovie() override;
 	void loadAmbientLoops() override;
 	void clickInHotspot(const Input &, const Hotspot *) override;
 
@@ -61,8 +61,8 @@ protected:
 	void showMainJumpMenu();
 	void receiveNotification(Notification *, const NotificationFlags) override;
 
-	Common::String getNavMovieName() override;
-	Common::String getSoundSpotsName() override { return ""; }
+	Common::Path getNavMovieName() override;
+	Common::Path getSoundSpotsName() override { return Common::Path(); }
 };
 
 } // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/wsc/wsc.cpp b/engines/pegasus/neighborhood/wsc/wsc.cpp
index ebe239806e0..a5366d02bd4 100644
--- a/engines/pegasus/neighborhood/wsc/wsc.cpp
+++ b/engines/pegasus/neighborhood/wsc/wsc.cpp
@@ -649,11 +649,11 @@ void WSC::setUpAIRules() {
 	}
 }
 
-Common::String WSC::getBriefingMovie() {
+Common::Path WSC::getBriefingMovie() {
 	return "Images/AI/WSC/XWO";
 }
 
-Common::String WSC::getEnvScanMovie() {
+Common::Path WSC::getEnvScanMovie() {
 	RoomID room = GameState.getCurrentRoom();
 
 	if (room >= kWSC01 && room <= kWSC04)
@@ -770,7 +770,7 @@ uint WSC::getNumHints() {
 	return 0;
 }
 
-Common::String WSC::getHintMovie(uint hintNum) {
+Common::Path WSC::getHintMovie(uint hintNum) {
 	switch (GameState.getCurrentRoomAndView()) {
 	case MakeRoomView(kWSC10, kWest):
 	case MakeRoomView(kWSC28, kWest):
@@ -786,7 +786,7 @@ Common::String WSC::getHintMovie(uint hintNum) {
 		if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
 				!_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
 				!GameState.getWSCDesignedAntidote())
-			return Common::String::format("Images/AI/WSC/XWPH%d", hintNum);
+			return Common::Path(Common::String::format("Images/AI/WSC/XWPH%d", hintNum));
 
 		return "Images/AI/Globals/XGLOB1C";
 	case MakeRoomView(kWSC61, kEast):
@@ -853,14 +853,14 @@ Common::String WSC::getHintMovie(uint hintNum) {
 	case MakeRoomView(kWSC04, kEast):
 	case MakeRoomView(kWSC04, kWest):
 		// analyzer hint
-		return Common::String::format("Images/AI/WSC/XWPH%d", hintNum);
+		return Common::Path(Common::String::format("Images/AI/WSC/XWPH%d", hintNum));
 	case MakeRoomView(kWSC02Messages, kSouth):
 	case MakeRoomView(kWSC02Morph, kSouth):
 		if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
 				!_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
 				!GameState.getWSCDesignedAntidote())
 			// analyzer hint
-			return Common::String::format("Images/AI/WSC/XWPH%d", hintNum);
+			return Common::Path(Common::String::format("Images/AI/WSC/XWPH%d", hintNum));
 
 		return "Images/AI/Globals/XGLOB1C";
 	case MakeRoomView(kWSC98, kWest):
@@ -872,12 +872,12 @@ Common::String WSC::getHintMovie(uint hintNum) {
 	return "";
 }
 
-void WSC::prepareForAIHint(const Common::String &movieName) {
+void WSC::prepareForAIHint(const Common::Path &movieName) {
 	if (movieName == "Images/AI/WSC/XW98WH2" && isEventTimerRunning())
 		pauseTimer();
 }
 
-void WSC::cleanUpAfterAIHint(const Common::String &movieName) {
+void WSC::cleanUpAfterAIHint(const Common::Path &movieName) {
 	if (movieName == "Images/AI/WSC/XW98WH2" && isEventTimerRunning())
 		resumeTimer();
 }
@@ -2958,11 +2958,11 @@ void WSC::setSoundFXLevel(const uint16 level) {
 		_welcomeSound.setVolume(level);
 }
 
-Common::String WSC::getNavMovieName() {
+Common::Path WSC::getNavMovieName() {
 	return "Images/World Science Center/WSC.movie";
 }
 
-Common::String WSC::getSoundSpotsName() {
+Common::Path WSC::getSoundSpotsName() {
 	return "Sounds/World Science Center/WSC Spots";
 }
 
diff --git a/engines/pegasus/neighborhood/wsc/wsc.h b/engines/pegasus/neighborhood/wsc/wsc.h
index 1a1e4ee89aa..64444724717 100644
--- a/engines/pegasus/neighborhood/wsc/wsc.h
+++ b/engines/pegasus/neighborhood/wsc/wsc.h
@@ -58,8 +58,8 @@ public:
 
 	void setSoundFXLevel(const uint16) override;
 
-	void prepareForAIHint(const Common::String &) override;
-	void cleanUpAfterAIHint(const Common::String &) override;
+	void prepareForAIHint(const Common::Path &) override;
+	void cleanUpAfterAIHint(const Common::Path &) override;
 
 	void init() override;
 	void start() override;
@@ -142,17 +142,17 @@ protected:
 	void spotCompleted() override;
 	void activateHotspots() override;
 	void setUpAIRules() override;
-	Common::String getBriefingMovie() override;
-	Common::String getEnvScanMovie() override;
+	Common::Path getBriefingMovie() override;
+	Common::Path getEnvScanMovie() override;
 	uint getNumHints() override;
-	Common::String getHintMovie(uint) override;
+	Common::Path getHintMovie(uint) override;
 	void closeDoorOffScreen(const RoomID, const DirectionConstant) override;
 	void setUpPoison();
 	void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &) override;
 	void timerExpired(const uint32) override;
 
-	Common::String getSoundSpotsName() override;
-	Common::String getNavMovieName() override;
+	Common::Path getSoundSpotsName() override;
+	Common::Path getNavMovieName() override;
 
 	FlagsArray<byte, kNumWSCPrivateFlags> _privateFlags;
 	const Hotspot *_cachedZoomSpot;
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index b5b05338a81..92676e30ead 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -225,7 +225,7 @@ bool PegasusEngine::detectOpeningClosingDirectory() {
 	// macOS will display this as 'Opening:Closing' and we can use that directly
 	// On other systems, users will need to rename to "Opening_Closing"
 
-	Common::FSNode gameDataDir(ConfMan.get("path"));
+	Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	gameDataDir = gameDataDir.getChild("Images");
 
 	if (!gameDataDir.exists())
@@ -235,20 +235,21 @@ bool PegasusEngine::detectOpeningClosingDirectory() {
 	if (!gameDataDir.getChildren(fsList, Common::FSNode::kListDirectoriesOnly, true))
 		return false;
 
-	for (uint i = 0; i < fsList.size() && _introDirectory.empty(); i++) {
+	Common::String introDirectory;
+	for (uint i = 0; i < fsList.size() && introDirectory.empty(); i++) {
 		Common::String name = fsList[i].getName();
 
 		if (name.equalsIgnoreCase("Opening:Closing"))
-			_introDirectory = name;
+			introDirectory = name;
 		else if (name.equalsIgnoreCase("Opening_Closing"))
-			_introDirectory = name;
+			introDirectory = name;
 	}
 
-	if (_introDirectory.empty())
+	if (introDirectory.empty())
 		return false;
 
-	debug(0, "Detected intro location as '%s'", _introDirectory.c_str());
-	_introDirectory = Common::String("Images/") + _introDirectory;
+	debug(0, "Detected intro location as '%s'", introDirectory.c_str());
+	_introDirectory = Common::Path("Images/").append(introDirectory);
 	return true;
 }
 
@@ -324,7 +325,7 @@ void PegasusEngine::runIntro() {
 	bool skipped = false;
 
 	Video::VideoDecoder *video = new Video::QuickTimeDecoder();
-	if (video->loadFile(_introDirectory + "/BandaiLogo.movie")) {
+	if (video->loadFile(_introDirectory.appendComponent("BandaiLogo.movie"))) {
 		video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF));
 		video->start();
 
@@ -353,11 +354,11 @@ void PegasusEngine::runIntro() {
 		return;
 
 #ifdef USE_THEORADEC
-	if (isDVD() && Common::File::exists(_introDirectory + "/BigMovie_hq.ogg")) {
+	if (isDVD() && Common::File::exists(_introDirectory.appendComponent("BigMovie_hq.ogg"))) {
 		Video::TheoraDecoder hqVideo;
 		hqVideo.setSoundType(Audio::Mixer::kPlainSoundType);
 
-		if (hqVideo.loadFile(_introDirectory + "/BigMovie_hq.ogg")) {
+		if (hqVideo.loadFile(_introDirectory.appendComponent("BigMovie_hq.ogg"))) {
 			hqVideo.start();
 			playMovieScaled(&hqVideo, 0, 0);
 			return;
@@ -367,8 +368,8 @@ void PegasusEngine::runIntro() {
 
 	video = new Video::QuickTimeDecoder();
 
-	if (!video->loadFile(_introDirectory + "/Big Movie.movie"))
-		if (!video->loadFile(_introDirectory + "/BigMovie.movie"))
+	if (!video->loadFile(_introDirectory.appendComponent("Big Movie.movie")))
+		if (!video->loadFile(_introDirectory.appendComponent("BigMovie.movie")))
 			error("Could not load intro movie");
 
 	video->setVolume(MIN<uint>(getAmbienceLevel(), 0xFF));
@@ -833,7 +834,7 @@ void PegasusEngine::introTimerExpired() {
 		if (isDVD()) {
 			video = new Video::TheoraDecoder();
 
-			if (!video->loadFile(_introDirectory + "/LilMovie_hq.ogg")) {
+			if (!video->loadFile(_introDirectory.appendComponent("LilMovie_hq.ogg"))) {
 				delete video;
 				video = nullptr;
 			}
@@ -842,7 +843,7 @@ void PegasusEngine::introTimerExpired() {
 
 		if (!video) {
 			video = new Video::QuickTimeDecoder();
-			if (!video->loadFile(_introDirectory + "/LilMovie.movie"))
+			if (!video->loadFile(_introDirectory.appendComponent("LilMovie.movie")))
 				error("Failed to load little movie");
 		}
 
@@ -1006,27 +1007,27 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) {
 				if (GameState.getEasterEgg()) {
 #ifdef USE_THEORADEC
 					video = new Video::TheoraDecoder();
-					if (!video->loadFile(_introDirectory + "/Closing_hq2.ogg")) {
+					if (!video->loadFile(_introDirectory.appendComponent("Closing_hq2.ogg"))) {
 						delete video;
 						video = nullptr;
 					}
 #endif
 					if (!video) {
 						video = new Video::QuickTimeDecoder();
-						if (!video->loadFile(_introDirectory + "/Closing2.movie"))
+						if (!video->loadFile(_introDirectory.appendComponent("Closing2.movie")))
 							error("Could not load alternate closing movie");
 					}
 				} else {
 #ifdef USE_THEORADEC
 					video = new Video::TheoraDecoder();
-					if (!video->loadFile(_introDirectory + "/Closing_hq1.ogg")) {
+					if (!video->loadFile(_introDirectory.appendComponent("Closing_hq1.ogg"))) {
 						delete video;
 						video = nullptr;
 					}
 #endif
 					if (!video) {
 						video = new Video::QuickTimeDecoder();
-						if (!video->loadFile(_introDirectory + "/Closing.movie"))
+						if (!video->loadFile(_introDirectory.appendComponent("Closing.movie")))
 							error("Could not load closing movie");
 					}
 				}
@@ -1046,14 +1047,14 @@ void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) {
 					// Display new post credits movie
 #ifdef USE_THEORADEC
 					video = new Video::TheoraDecoder();
-					if (!video->loadFile(_introDirectory + "/Closing_hq3.ogg")) {
+					if (!video->loadFile(_introDirectory.appendComponent("Closing_hq3.ogg"))) {
 						delete video;
 						video = nullptr;
 					}
 #endif
 					if (!video) {
 						video = new Video::QuickTimeDecoder();
-						if (!video->loadFile(_introDirectory + "/Closing3.movie"))
+						if (!video->loadFile(_introDirectory.appendComponent("Closing3.movie")))
 							error("Could not load closing 3 movie");
 					}
 
@@ -1420,7 +1421,7 @@ void PegasusEngine::doInterfaceOverview() {
 	_loadRequested = false;
 }
 
-void PegasusEngine::showTempScreen(const Common::String &fileName) {
+void PegasusEngine::showTempScreen(const Common::Path &fileName) {
 	_gfx->doFadeOutSync();
 
 	Picture picture(0);
@@ -1519,18 +1520,18 @@ bool PegasusEngine::playerAlive() {
 	return (_shellNotification.getNotificationFlags() & kPlayerDiedFlag) == 0;
 }
 
-Common::String PegasusEngine::getBriefingMovie() {
+Common::Path PegasusEngine::getBriefingMovie() {
 	if (_neighborhood)
 		return _neighborhood->getBriefingMovie();
 
-	return Common::String();
+	return Common::Path();
 }
 
-Common::String PegasusEngine::getEnvScanMovie() {
+Common::Path PegasusEngine::getEnvScanMovie() {
 	if (_neighborhood)
 		return _neighborhood->getEnvScanMovie();
 
-	return Common::String();
+	return Common::Path();
 }
 
 uint PegasusEngine::getNumHints() {
@@ -1540,11 +1541,11 @@ uint PegasusEngine::getNumHints() {
 	return 0;
 }
 
-Common::String PegasusEngine::getHintMovie(uint hintNum) {
+Common::Path PegasusEngine::getHintMovie(uint hintNum) {
 	if (_neighborhood)
 		return _neighborhood->getHintMovie(hintNum);
 
-	return Common::String();
+	return Common::Path();
 }
 
 bool PegasusEngine::canSolve() {
@@ -1554,12 +1555,12 @@ bool PegasusEngine::canSolve() {
 	return false;
 }
 
-void PegasusEngine::prepareForAIHint(const Common::String &movieName) {
+void PegasusEngine::prepareForAIHint(const Common::Path &movieName) {
 	if (g_neighborhood)
 		g_neighborhood->prepareForAIHint(movieName);
 }
 
-void PegasusEngine::cleanUpAfterAIHint(const Common::String &movieName) {
+void PegasusEngine::cleanUpAfterAIHint(const Common::Path &movieName) {
 	if (g_neighborhood)
 		g_neighborhood->cleanUpAfterAIHint(movieName);
 }
diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h
index f994fb0c34f..60a7b24d2d5 100644
--- a/engines/pegasus/pegasus.h
+++ b/engines/pegasus/pegasus.h
@@ -165,13 +165,13 @@ public:
 	InventoryResult addItemToBiochips(BiochipItem *);
 
 	// AI
-	Common::String getBriefingMovie();
-	Common::String getEnvScanMovie();
+	Common::Path getBriefingMovie();
+	Common::Path getEnvScanMovie();
 	uint getNumHints();
-	Common::String getHintMovie(uint);
+	Common::Path getHintMovie(uint);
 	bool canSolve();
-	void prepareForAIHint(const Common::String &);
-	void cleanUpAfterAIHint(const Common::String &);
+	void prepareForAIHint(const Common::Path &);
+	void cleanUpAfterAIHint(const Common::Path &);
 	void requestToggle(bool request = true) { _toggleRequested = request; }
 	bool toggleRequested() const { return _toggleRequested; }
 	bool isChattyAI() { return _chattyAI; }
@@ -233,7 +233,7 @@ private:
 	void runIntro();
 	void stopIntroTimer();
 	bool detectOpeningClosingDirectory();
-	Common::String _introDirectory;
+	Common::Path _introDirectory;
 	FuseFunction *_introTimer;
 
 	// Idlers
@@ -270,7 +270,7 @@ private:
 	Hotspot _returnHotspot;
 	HotspotList _allHotspots;
 	InputHandler *_savedHandler;
-	void showTempScreen(const Common::String &fileName);
+	void showTempScreen(const Common::Path &fileName);
 	bool playMovieScaled(Video::VideoDecoder *video, uint16 x, uint16 y);
 	void throwAwayEverything();
 	void shellGameInput(const Input &input, const Hotspot *cursorSpot);
diff --git a/engines/pegasus/sound.cpp b/engines/pegasus/sound.cpp
index 9bc8dab9729..2e0031cb57e 100644
--- a/engines/pegasus/sound.cpp
+++ b/engines/pegasus/sound.cpp
@@ -48,12 +48,12 @@ void Sound::disposeSound() {
 	delete _stream; _stream = nullptr;
 }
 
-void Sound::initFromAIFFFile(const Common::String &fileName) {
+void Sound::initFromAIFFFile(const Common::Path &fileName) {
 	disposeSound();
 
 	Common::File *file = new Common::File();
 	if (!file->open(fileName)) {
-		warning("Failed to open AIFF file '%s'", fileName.c_str());
+		warning("Failed to open AIFF file '%s'", fileName.toString().c_str());
 		delete file;
 		return;
 	}
@@ -64,18 +64,18 @@ void Sound::initFromAIFFFile(const Common::String &fileName) {
 
 	if (!_stream) {
 		delete stream;
-		warning("AIFF stream '%s' is not seekable", fileName.c_str());
+		warning("AIFF stream '%s' is not seekable", fileName.toString().c_str());
 		return;
 	}
 }
 
-void Sound::initFromQuickTime(const Common::String &fileName) {
+void Sound::initFromQuickTime(const Common::Path &fileName) {
 	disposeSound();
 
 	_stream = Audio::makeQuickTimeStream(fileName);
 
 	if (!_stream)
-		warning("Failed to open QuickTime file '%s'", fileName.c_str());
+		warning("Failed to open QuickTime file '%s'", fileName.toString().c_str());
 }
 
 void Sound::attachFader(SoundFader *fader) {
diff --git a/engines/pegasus/sound.h b/engines/pegasus/sound.h
index 98f1decfd1f..361751af7fa 100644
--- a/engines/pegasus/sound.h
+++ b/engines/pegasus/sound.h
@@ -55,12 +55,12 @@ public:
 	// We only have one access point here because we should
 	// only be opening an AIFF file from a file name. We're
 	// not using the resource fork string resources.
-	void initFromAIFFFile(const Common::String &fileName);
+	void initFromAIFFFile(const Common::Path &fileName);
 
 	// Unlike the original game, we're going to use a regular
 	// audio stream for sound spots. The original treated them
 	// as movies.
-	void initFromQuickTime(const Common::String &fileName);
+	void initFromQuickTime(const Common::Path &fileName);
 
 	void disposeSound();
 	bool isSoundLoaded() const;
diff --git a/engines/pegasus/surface.cpp b/engines/pegasus/surface.cpp
index f11f6072085..1dd85e991e6 100644
--- a/engines/pegasus/surface.cpp
+++ b/engines/pegasus/surface.cpp
@@ -79,22 +79,22 @@ void Surface::allocateSurface(const Common::Rect &bounds) {
 	_ownsSurface = true;
 }
 
-void Surface::getImageFromPICTFile(const Common::String &fileName) {
+void Surface::getImageFromPICTFile(const Common::Path &fileName) {
 	Common::File pict;
 	if (!pict.open(fileName))
-		error("Could not open picture '%s'", fileName.c_str());
+		error("Could not open picture '%s'", fileName.toString().c_str());
 
 	if (!getImageFromPICTStream(&pict))
-		error("Failed to load PICT '%s'", fileName.c_str());
+		error("Failed to load PICT '%s'", fileName.toString().c_str());
 }
 
 void Surface::getImageFromPICTResource(Common::MacResManager *resFork, uint16 id) {
 	Common::SeekableReadStream *res = resFork->getResource(MKTAG('P', 'I', 'C', 'T'), id);
 	if (!res)
-		error("Could not open PICT resource %d from '%s'", id, resFork->getBaseFileName().toString().c_str());
+		error("Could not open PICT resource %d from '%s'", id, resFork->getBaseFileName().toString(Common::Path::kNativeSeparator).c_str());
 
 	if (!getImageFromPICTStream(res))
-		error("Failed to load PICT resource %d from '%s'", id, resFork->getBaseFileName().toString().c_str());
+		error("Failed to load PICT resource %d from '%s'", id, resFork->getBaseFileName().toString(Common::Path::kNativeSeparator).c_str());
 
 	delete res;
 }
@@ -337,7 +337,7 @@ void PixelImage::drawImage(const Common::Rect &sourceBounds, const Common::Rect
 		copyToCurrentPort(sourceBounds, destBounds);
 }
 
-void Frame::initFromPICTFile(const Common::String &fileName, bool transparent) {
+void Frame::initFromPICTFile(const Common::Path &fileName, bool transparent) {
 	getImageFromPICTFile(fileName);
 	_transparent = transparent;
 }
@@ -368,7 +368,7 @@ void Picture::draw(const Common::Rect &r) {
 	drawImage(r2, r1);
 }
 
-void Picture::initFromPICTFile(const Common::String &fileName, bool transparent) {
+void Picture::initFromPICTFile(const Common::Path &fileName, bool transparent) {
 	Frame::initFromPICTFile(fileName, transparent);
 
 	Common::Rect surfaceBounds;
diff --git a/engines/pegasus/surface.h b/engines/pegasus/surface.h
index 7c4e2064971..4e7d9931438 100644
--- a/engines/pegasus/surface.h
+++ b/engines/pegasus/surface.h
@@ -73,7 +73,7 @@ public:
 	void scaleTransparentCopy(const Common::Rect &, const Common::Rect &) const;
 	void scaleTransparentCopyGlow(const Common::Rect &, const Common::Rect &) const;
 
-	virtual void getImageFromPICTFile(const Common::String &fileName);
+	virtual void getImageFromPICTFile(const Common::Path &fileName);
 	virtual void getImageFromPICTResource(Common::MacResManager *resFork, uint16 id);
 	virtual void getImageFromMovieFrame(Video::VideoDecoder *, TimeValue);
 
@@ -107,7 +107,7 @@ public:
 	Frame() {}
 	~Frame() override {}
 
-	virtual void initFromPICTFile(const Common::String &fileName, bool transparent = false);
+	virtual void initFromPICTFile(const Common::Path &fileName, bool transparent = false);
 	virtual void initFromPICTResource(Common::MacResManager *resFork, uint16 id, bool transparent = false);
 	virtual void initFromMovieFrame(Video::VideoDecoder *, TimeValue, bool transparent = false);
 };
@@ -127,7 +127,7 @@ public:
 	Picture(const DisplayElementID id) : DisplayElement(id) {}
 	~Picture() override {}
 
-	void initFromPICTFile(const Common::String &fileName, bool transparent = false) override;
+	void initFromPICTFile(const Common::Path &fileName, bool transparent = false) override;
 	void initFromPICTResource(Common::MacResManager *resFork, uint16 id, bool transparent = false) override;
 	void initFromMovieFrame(Video::VideoDecoder *, TimeValue, bool transparent = false) override;
 


Commit: cfdd63abf86a3c6ad140059cdc99acbe2d7a8bd2
    https://github.com/scummvm/scummvm/commit/cfdd63abf86a3c6ad140059cdc99acbe2d7a8bd2
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
PETKA: Migrate engine to Path

Changed paths:
    engines/petka/file_mgr.cpp


diff --git a/engines/petka/file_mgr.cpp b/engines/petka/file_mgr.cpp
index a9a59803223..7a6f6141135 100644
--- a/engines/petka/file_mgr.cpp
+++ b/engines/petka/file_mgr.cpp
@@ -30,7 +30,7 @@ namespace Petka {
 
 bool FileMgr::openStore(const Common::String &name) {
 	Common::SharedPtr<Common::File> file(new Common::File());
-	if (name.empty() || !file->open(name) || file->readUint32BE() != MKTAG('S', 't', 'O', 'R')) {
+	if (name.empty() || !file->open(Common::Path(name)) || file->readUint32BE() != MKTAG('S', 't', 'O', 'R')) {
 		return false;
 	}
 
@@ -81,13 +81,13 @@ void FileMgr::closeAll() {
 	_stores.clear();
 }
 
-static Common::String formPath(Common::String name) {
+static Common::Path formPath(Common::String name) {
 	for (uint i = 0; i < name.size(); ++i) {
 		if (name[i] == '\\') {
 			name.setChar('/', i);
 		}
 	}
-	return name;
+	return Common::Path(name, '/');
 }
 
 Common::SeekableReadStream *FileMgr::getFileStream(const Common::String &name) {


Commit: e62dcdfed4e1c68efd50b14f964da7e14773c913
    https://github.com/scummvm/scummvm/commit/e62dcdfed4e1c68efd50b14f964da7e14773c913
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
PINK: Migrate engine to Path

Changed paths:
    engines/pink/gui.cpp
    engines/pink/pink.cpp


diff --git a/engines/pink/gui.cpp b/engines/pink/gui.cpp
index 1f88f1998b1..ba34a83204e 100644
--- a/engines/pink/gui.cpp
+++ b/engines/pink/gui.cpp
@@ -311,10 +311,10 @@ bool PinkEngine::executePageChangeCommand(uint id) {
 }
 
 void PinkEngine::openLocalWebPage(const Common::String &pageName) const {
-	Common::FSNode gameFolder = Common::FSNode(ConfMan.get("path"));
+	Common::FSNode gameFolder = Common::FSNode(ConfMan.getPath("path"));
 	Common::FSNode filePath = gameFolder.getChild("INSTALL").getChild(pageName);
 	if (filePath.exists()) {
-		Common::String fullUrl = Common::String::format("file:///%s", filePath.getPath().c_str());
+		Common::String fullUrl = Common::String::format("file:///%s", filePath.getPath().toString('/').c_str());
 		_system->openUrl(fullUrl);
 	}
 }
diff --git a/engines/pink/pink.cpp b/engines/pink/pink.cpp
index 3289c12c019..bfaa74446f0 100644
--- a/engines/pink/pink.cpp
+++ b/engines/pink/pink.cpp
@@ -47,7 +47,7 @@ PinkEngine::PinkEngine(OSystem *system, const ADGameDescription *desc)
 	_desc(desc), _bro(nullptr), _menu(nullptr), _actor(nullptr),
 	_module(nullptr), _screen(nullptr), _pdaMgr(this) {
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "install");
 
 	g_paletteLookup = new Graphics::PaletteLookup;
@@ -76,7 +76,7 @@ Common::Error PinkEngine::init() {
 	initGraphics(640, 480);
 
 	_exeResources = new Common::PEResources();
-	Common::String fileName = isPeril() ? "pptp.exe" : "hpp.exe";
+	Common::Path fileName = isPeril() ? "pptp.exe" : "hpp.exe";
 
 	if ((_desc->flags & GF_COMPRESSED) && isPeril()) {
 		fileName = "pptp.ex_";
@@ -97,8 +97,8 @@ Common::Error PinkEngine::init() {
 
 	initMenu();
 
-	Common::String orbName;
-	Common::String broName;
+	Common::Path orbName;
+	Common::Path broName;
 	if (isPeril()) {
 		orbName = "PPTP.ORB";
 		broName = "PPTP.BRO";


Commit: e8a4a8af805270c0fa1005a2aaf21e764f28319f
    https://github.com/scummvm/scummvm/commit/e8a4a8af805270c0fa1005a2aaf21e764f28319f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
PLUMBERS: Migrate engine to Path

Changed paths:
    engines/plumbers/3do.cpp
    engines/plumbers/plumbers.cpp


diff --git a/engines/plumbers/3do.cpp b/engines/plumbers/3do.cpp
index f83a406c5ff..4f62a452454 100644
--- a/engines/plumbers/3do.cpp
+++ b/engines/plumbers/3do.cpp
@@ -405,18 +405,18 @@ void PlumbersGame3DO::loadMikeDecision(const Common::String &dirname, const Comm
 		Common::Point p = getMikeStart(i, num);
 		Common::Point sz = getMikeSize(num);
 		Common::File fileP;
-		Common::String nameP = Common::String::format("%s%dP.CEL", baseName.c_str(), i + 1);
+		Common::Path nameP(Common::String::format("%s%dP.CEL", baseName.c_str(), i + 1));
 		if (!fileP.open(nameP))
-			error("unable to load image %s", nameP.c_str());
+			error("unable to load image %s", nameP.toString().c_str());
 
 		_image->loadStream(fileP);
 		surf->copyRectToSurface(*_image->getSurface(), p.x, p.y,
 					Common::Rect(0, 0, sz.x, sz.y));
 
 		Common::File fileW;
-		Common::String nameW = Common::String::format("%s%dW.CEL", baseName.c_str(), i + 1);
+		Common::Path nameW(Common::String::format("%s%dW.CEL", baseName.c_str(), i + 1));
 		if (!fileW.open(nameW))
-			error("unable to load image %s", nameW.c_str());
+			error("unable to load image %s", nameW.toString().c_str());
 
 		_image->loadStream(fileW);
 		surf->copyRectToSurface(*_image->getSurface(), p.x + sz.x, p.y,
@@ -426,7 +426,7 @@ void PlumbersGame3DO::loadMikeDecision(const Common::String &dirname, const Comm
 	_compositeSurface = surf;
 
 	Common::File fileCtrl;
-	if (fileCtrl.open(dirname + "/CONTROLHELP.CEL"))
+	if (fileCtrl.open(Common::Path(dirname + "/CONTROLHELP.CEL")))
 		_ctrlHelpImage->loadStream(fileCtrl);
 }
 
@@ -434,7 +434,7 @@ void PlumbersGame3DO::postSceneBitmaps() {
 	if (_scenes[_curSceneIdx]._style == Scene::STYLE_VIDEO) {
 		_videoDecoder = new Video::ThreeDOMovieDecoder();
 		_curChoice = 0;
-		if (!_videoDecoder->loadFile(_scenes[_curSceneIdx]._sceneName)) {
+		if (!_videoDecoder->loadFile(Common::Path(_scenes[_curSceneIdx]._sceneName))) {
 			_actions.push(ChangeScene);
 			return;
 		}
diff --git a/engines/plumbers/plumbers.cpp b/engines/plumbers/plumbers.cpp
index 2753844a9b5..c541c6feef1 100644
--- a/engines/plumbers/plumbers.cpp
+++ b/engines/plumbers/plumbers.cpp
@@ -213,7 +213,7 @@ Common::Error PlumbersGame::run() {
 void PlumbersGame::loadImage(const Common::String &name) {
 	debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, name.c_str());
 	Common::File file;
-	if (!file.open(name))
+	if (!file.open(Common::Path(name)))
 		error("unable to load image %s", name.c_str());
 
 	_image->loadStream(file);
@@ -275,7 +275,7 @@ void PlumbersGame::drawScreen() {
 void PlumbersGame::playSound(const Common::String &name) {
 	debugC(3, kDebugGeneral, "%s : %s", __FUNCTION__, name.c_str());
 	Common::File *file = new Common::File();
-	if (!file->open(name))
+	if (!file->open(Common::Path(name)))
 		error("unable to load sound %s", name.c_str());
 
 	Audio::AudioStream *stream;


Commit: d7526ad28098a26b61a91779f1754273de83026a
    https://github.com/scummvm/scummvm/commit/d7526ad28098a26b61a91779f1754273de83026a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
PRINCE: Migrate engine to Path

Changed paths:
    engines/prince/archive.cpp
    engines/prince/archive.h
    engines/prince/object.cpp
    engines/prince/prince.cpp
    engines/prince/prince.h
    engines/prince/pscr.cpp
    engines/prince/resource.cpp
    engines/prince/script.cpp
    engines/prince/sound.cpp
    engines/prince/videoplayer.cpp


diff --git a/engines/prince/archive.cpp b/engines/prince/archive.cpp
index 91a48b891fc..45a8e8c660f 100644
--- a/engines/prince/archive.cpp
+++ b/engines/prince/archive.cpp
@@ -45,7 +45,7 @@ static void decrypt(byte *buffer, uint32 size) {
 	}
 }
 
-bool PtcArchive::open(const Common::String &filename) {
+bool PtcArchive::open(const Common::Path &filename) {
 	_stream = SearchMan.createReadStreamForMember(filename);
 	if (!_stream)
 		return false;
@@ -78,7 +78,7 @@ bool PtcArchive::open(const Common::String &filename) {
 	return true;
 }
 
-bool PtcArchive::openTranslation(const Common::String &filename) {
+bool PtcArchive::openTranslation(const Common::Path &filename) {
 	_stream = SearchMan.createReadStreamForMember(filename);
 	if (!_stream)
 		return false;
@@ -147,11 +147,10 @@ int PtcArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr PtcArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!_items.contains(name)) {
+	if (!hasFile(path)) {
 		Common::ArchiveMemberPtr();
 	}
-	return Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *PtcArchive::createReadStreamForMember(const Common::Path &path) const {
diff --git a/engines/prince/archive.h b/engines/prince/archive.h
index 0550196c42c..238a31cda93 100644
--- a/engines/prince/archive.h
+++ b/engines/prince/archive.h
@@ -33,8 +33,8 @@ public:
 	PtcArchive();
 	~PtcArchive() override;
 
-	bool open(const Common::String &filename);
-	bool openTranslation(const Common::String &filename);
+	bool open(const Common::Path &filename);
+	bool openTranslation(const Common::Path &filename);
 	void close();
 	bool isOpen() const { return _stream != 0; }
 
diff --git a/engines/prince/object.cpp b/engines/prince/object.cpp
index fc04ac2adc4..edfa680bae1 100644
--- a/engines/prince/object.cpp
+++ b/engines/prince/object.cpp
@@ -70,7 +70,7 @@ bool Object::loadFromStream(Common::SeekableReadStream &stream) {
 	_x = x;
 	_y = stream.readSint16LE(); // skull mini-game has some signed y coords
 
-	const Common::String obStreamName = Common::String::format("OB%02d", stream.readUint16LE());
+	const Common::Path obStreamName(Common::String::format("OB%02d", stream.readUint16LE()));
 	Common::SeekableReadStream *obStream = SearchMan.createReadStreamForMember(obStreamName);
 	if (obStream) {
 		obStream = Resource::getDecompressedStream(obStream);
diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp
index 724ec75a2e5..a573a054906 100644
--- a/engines/prince/prince.cpp
+++ b/engines/prince/prince.cpp
@@ -193,9 +193,9 @@ PrinceEngine::~PrinceEngine() {
 
 void PrinceEngine::init() {
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
-	debugEngine("Adding all path: %s", gameDataDir.getPath().c_str());
+	debugEngine("Adding all path: %s", gameDataDir.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	if (!(getFeatures() & GF_EXTRACTED)) {
 		PtcArchive *all = new PtcArchive();
diff --git a/engines/prince/prince.h b/engines/prince/prince.h
index c55e2f00bac..6d4aa3551e9 100644
--- a/engines/prince/prince.h
+++ b/engines/prince/prince.h
@@ -284,7 +284,7 @@ public:
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	Common::Error loadGameState(int slot) override;
 
-	void playVideo(Common::String videoFilename);
+	void playVideo(const Common::Path &videoFilename);
 
 	WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail = true);
 	void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header);
diff --git a/engines/prince/pscr.cpp b/engines/prince/pscr.cpp
index 63aaf7aa0f8..3e1369a4986 100644
--- a/engines/prince/pscr.cpp
+++ b/engines/prince/pscr.cpp
@@ -61,7 +61,7 @@ bool PScr::loadFromStream(Common::SeekableReadStream &stream) {
 	_y = stream.readUint16LE();
 	_step = stream.readUint16LE();
 
-	const Common::String pscrStreamName = Common::String::format("PS%02d", file);
+	const Common::Path pscrStreamName(Common::String::format("PS%02d", file));
 	Common::SeekableReadStream *pscrStream = SearchMan.createReadStreamForMember(pscrStreamName);
 	if (pscrStream != nullptr) {
 		pscrStream = Resource::getDecompressedStream(pscrStream);
diff --git a/engines/prince/resource.cpp b/engines/prince/resource.cpp
index c7574e4a9f1..a71dc2c3a2b 100644
--- a/engines/prince/resource.cpp
+++ b/engines/prince/resource.cpp
@@ -99,7 +99,7 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
 	freeAllSamples();
 
 	debugEngine("PrinceEngine::loadLocation %d", locationNr);
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.remove(Common::String::format("%02d", _locationNr));
 
 	_locationNr = locationNr;
@@ -115,7 +115,7 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
 
 	if (!(getFeatures() & GF_EXTRACTED)) {
 		PtcArchive *locationArchive = new PtcArchive();
-		if (!locationArchive->open(locationNrStr + "/databank.ptc"))
+		if (!locationArchive->open(Common::Path(locationNrStr).appendComponent("databank.ptc")))
 			error("Can't open location %s", locationNrStr.c_str());
 
 		SearchMan.add(locationNrStr, locationArchive);
@@ -203,21 +203,21 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
 }
 
 bool PrinceEngine::loadAnim(uint16 animNr, bool loop) {
-	Common::String streamName = Common::String::format("AN%02d", animNr);
+	Common::Path streamName(Common::String::format("AN%02d", animNr));
 	Common::SeekableReadStream *flicStream = SearchMan.createReadStreamForMember(streamName);
 
 	if (!flicStream) {
-		error("Can't open %s", streamName.c_str());
+		error("Can't open %s", streamName.toString().c_str());
 		return false;
 	}
 
 	flicStream = Resource::getDecompressedStream(flicStream);
 
 	if (!_flicPlayer.loadStream(flicStream)) {
-		error("Can't load flic stream %s", streamName.c_str());
+		error("Can't load flic stream %s", streamName.toString().c_str());
 	}
 
-	debugEngine("%s loaded", streamName.c_str());
+	debugEngine("%s loaded", streamName.toString().c_str());
 	_flicLooped = loop;
 	_flicPlayer.start();
 	playNextFLCFrame();
@@ -321,7 +321,7 @@ bool PrinceEngine::loadAllInv() {
 	for (int i = 0; i < kMaxInv; i++) {
 		InvItem tempInvItem;
 
-		const Common::String invStreamName = Common::String::format("INV%02d", i);
+		const Common::Path invStreamName(Common::String::format("INV%02d", i));
 		Common::SeekableReadStream *invStream = SearchMan.createReadStreamForMember(invStreamName);
 		if (!invStream) {
 			delete invStream;
diff --git a/engines/prince/script.cpp b/engines/prince/script.cpp
index a54b419addb..cadaf74557a 100644
--- a/engines/prince/script.cpp
+++ b/engines/prince/script.cpp
@@ -381,13 +381,13 @@ bool Script::loadAllMasks(Common::Array<Mask> &maskList, int offset) {
 		tempMask._z = maskStream.readUint16LE();
 		tempMask._number = maskStream.readUint16LE();
 
-		const Common::String msStreamName = Common::String::format("MS%02d", tempMask._number);
+		const Common::Path msStreamName(Common::String::format("MS%02d", tempMask._number));
 		Common::SeekableReadStream *msStream = SearchMan.createReadStreamForMember(msStreamName);
 		if (!msStream) {
 			tempMask._width = 0;
 			tempMask._height = 0;
 			tempMask._data = nullptr;
-			warning("loadAllMasks: Can't load %s", msStreamName.c_str());
+			warning("loadAllMasks: Can't load %s", msStreamName.toString().c_str());
 			delete msStream;
 		} else {
 			msStream = Resource::getDecompressedStream(msStream);
diff --git a/engines/prince/sound.cpp b/engines/prince/sound.cpp
index e79b770f1e2..c47d178469c 100644
--- a/engines/prince/sound.cpp
+++ b/engines/prince/sound.cpp
@@ -79,7 +79,7 @@ bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamNam
 	debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());
 
 	freeSample(sampleSlot);
-	Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(normalizedPath);
+	Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(Common::Path(normalizedPath));
 	if (sampleStream == nullptr) {
 		delete sampleStream;
 		error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
@@ -103,7 +103,7 @@ bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::Strin
 	}
 
 	freeSample(sampleSlot);
-	Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(streamName);
+	Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(Common::Path(streamName));
 	if (sampleStream == nullptr) {
 		warning("loadVoice: Can't open %s", streamName.c_str());
 		_missingVoice = true;	// Insert END tag if needed
diff --git a/engines/prince/videoplayer.cpp b/engines/prince/videoplayer.cpp
index 32d3b6c6546..0228f2061c8 100644
--- a/engines/prince/videoplayer.cpp
+++ b/engines/prince/videoplayer.cpp
@@ -27,7 +27,7 @@
 
 namespace Prince {
 
-void PrinceEngine::playVideo(Common::String videoFilename) {
+void PrinceEngine::playVideo(const Common::Path &videoFilename) {
 		// Set the correct video mode
 		initGraphics(640, 480, nullptr);
 		if (_system->getScreenFormat().bytesPerPixel == 1) {
@@ -40,7 +40,7 @@ void PrinceEngine::playVideo(Common::String videoFilename) {
 	Video::VideoDecoder *videoDecoder = new Video::AVIDecoder();
 	if (!videoDecoder->loadFile(videoFilename)) {
 		delete videoDecoder;
-		warning("Unable to open video %s", videoFilename.c_str());
+		warning("Unable to open video %s", videoFilename.toString().c_str());
 		initGraphics(640, 480);
 		return;
 	}


Commit: 50e408526357b6750991d3937993f321400a2d85
    https://github.com/scummvm/scummvm/commit/50e408526357b6750991d3937993f321400a2d85
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
PRIVATE: Migrate engine to Path

Changed paths:
    engines/private/private.cpp
    engines/private/private.h


diff --git a/engines/private/private.cpp b/engines/private/private.cpp
index 45c6cba37d1..1cd579c48d7 100644
--- a/engines/private/private.cpp
+++ b/engines/private/private.cpp
@@ -127,7 +127,7 @@ PrivateEngine::~PrivateEngine() {
 }
 
 void PrivateEngine::initializePath(const Common::FSNode &gamePath) {
-	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
+	SearchMan.addDirectory(gamePath, 0, 10);
 }
 
 Common::SeekableReadStream *PrivateEngine::loadAssets() {
@@ -1172,7 +1172,7 @@ Common::Error PrivateEngine::saveGameStream(Common::WriteStream *stream, bool is
 	return Common::kNoError;
 }
 
-Common::String PrivateEngine::convertPath(const Common::String &name) {
+Common::Path PrivateEngine::convertPath(const Common::String &name) {
 	Common::String path(name);
 	Common::String s1("\\");
 	Common::String s2("/");
@@ -1187,17 +1187,17 @@ Common::String PrivateEngine::convertPath(const Common::String &name) {
 	Common::replace(path, s1, s2);
 
 	path.toLowercase();
-	return path;
+	return Common::Path(path);
 }
 
 void PrivateEngine::playSound(const Common::String &name, uint loops, bool stopOthers, bool background) {
 	debugC(1, kPrivateDebugFunction, "%s(%s,%d,%d,%d)", __FUNCTION__, name.c_str(), loops, stopOthers, background);
 
-	Common::String path = convertPath(name);
+	Common::Path path = convertPath(name);
 	Common::SeekableReadStream *file = Common::MacResManager::openFileOrDataFork(path);
 
 	if (!file)
-		error("unable to find sound file %s", path.c_str());
+		error("unable to find sound file %s", path.toString().c_str());
 
 	Audio::LoopingAudioStream *stream;
 	stream = new Audio::LoopingAudioStream(Audio::makeWAVStream(file, DisposeAfterUse::YES), loops);
@@ -1224,14 +1224,14 @@ bool PrivateEngine::isSoundActive() {
 void PrivateEngine::playVideo(const Common::String &name) {
 	debugC(1, kPrivateDebugFunction, "%s(%s)", __FUNCTION__, name.c_str());
 	//stopSound(true);
-	Common::String path = convertPath(name);
+	Common::Path path = convertPath(name);
 	Common::SeekableReadStream *file = Common::MacResManager::openFileOrDataFork(path);
 
 	if (!file)
-		error("unable to find video file %s", path.c_str());
+		error("unable to find video file %s", path.toString().c_str());
 
 	if (!_videoDecoder->loadStream(file))
-		error("unable to load video %s", path.c_str());
+		error("unable to load video %s", path.toString().c_str());
 	_videoDecoder->start();
 }
 
@@ -1255,7 +1255,7 @@ void PrivateEngine::stopSound(bool all) {
 
 Graphics::Surface *PrivateEngine::decodeImage(const Common::String &name, byte **palette) {
 	debugC(1, kPrivateDebugFunction, "%s(%s)", __FUNCTION__, name.c_str());
-	Common::String path = convertPath(name);
+	Common::Path path = convertPath(name);
 	Common::ScopedPtr<Common::SeekableReadStream> file(Common::MacResManager::openFileOrDataFork(path));
 	if (!file)
 		error("unable to load image %s", name.c_str());
@@ -1268,7 +1268,7 @@ Graphics::Surface *PrivateEngine::decodeImage(const Common::String &name, byte *
 	byte *currentPalette;
 
 	uint16 ncolors = _image->getPaletteColorCount();
-	if (ncolors < 256 || path.hasPrefix("intro")) { // For some reason, requires color remapping
+	if (ncolors < 256 || path.toString('/').hasPrefix("intro")) { // For some reason, requires color remapping
 		currentPalette = (byte *) malloc(3*256);
 		drawScreen();
 		g_system->getPaletteManager()->grabPalette(currentPalette, 0, 256);
diff --git a/engines/private/private.h b/engines/private/private.h
index 3fa64ada715..e02587dc2bb 100644
--- a/engines/private/private.h
+++ b/engines/private/private.h
@@ -195,7 +195,7 @@ public:
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
 	void syncGameStream(Common::Serializer &s);
 
-	Common::String convertPath(const Common::String &);
+	Common::Path convertPath(const Common::String &);
 	void playVideo(const Common::String &);
 	void skipVideo();
 


Commit: f58b045ec8395dbf3312812ca8fc20909f4f9d3a
    https://github.com/scummvm/scummvm/commit/f58b045ec8395dbf3312812ca8fc20909f4f9d3a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SAGA: Migrate engine to Path

Changed paths:
    engines/saga/font.cpp
    engines/saga/font.h
    engines/saga/music.cpp
    engines/saga/resource.cpp
    engines/saga/saga.cpp


diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp
index 0306a84bb8a..66cbfdba3bd 100644
--- a/engines/saga/font.cpp
+++ b/engines/saga/font.cpp
@@ -227,7 +227,7 @@ DefaultFont::~DefaultFont() {
 	}
 }
 
-void DefaultFont::loadChineseFontITE(const Common::String& fileName) {
+void DefaultFont::loadChineseFontITE(const Common::Path &fileName) {
 	Common::File f;
 	if (!f.open(fileName))
 		return;
@@ -246,7 +246,7 @@ void DefaultFont::loadChineseFontITE(const Common::String& fileName) {
 	}
 }
 
-void DefaultFont::loadKoreanFontIHNM(const Common::String& fileName) {
+void DefaultFont::loadKoreanFontIHNM(const Common::Path &fileName) {
 	Common::File f;
 	if (!f.open(fileName))
 		return;
diff --git a/engines/saga/font.h b/engines/saga/font.h
index 4ca407aac60..c48b0e5304d 100644
--- a/engines/saga/font.h
+++ b/engines/saga/font.h
@@ -239,8 +239,8 @@ class DefaultFont : public Font {
 	 void loadFont(FontData *font, uint32 fontResourceId);
 	 void loadFont(FontData *font, const ByteArray& fontResourceData, bool isBigEndian);
 	 void loadChineseFontIHNM(FontData *font, uint32 fontResourceId);
-	 void loadChineseFontITE(const Common::String& fileName);
-	 void loadKoreanFontIHNM(const Common::String& fileName);
+	 void loadChineseFontITE(const Common::Path &fileName);
+	 void loadKoreanFontIHNM(const Common::Path &fileName);
 	 void saveBig5Index(byte head, byte tail, uint curIdx);
 	 void createOutline(FontData *font);
 	 void blitGlyph(const Common::Point &textPoint, const byte* bitmap, int charWidth, int charHeight, int rowLength, byte color);
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index d5d1a046245..1f2ca1e386e 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -470,9 +470,9 @@ void Music::playQuickTime(uint32 resourceId, MusicFlags flags) {
 	// Handle music looping
 	_parser->property(MidiParser::mpAutoLoop, flags & MUSIC_LOOP);
 
-	const Common::String &musicName = Common::String::format("Music/Music%02x", resourceId);
+	Common::Path musicName(Common::String::format("Music/Music%02x", resourceId));
 	if (!((MidiParser_QT *)_parser)->loadFromContainerFile(musicName))
-		error("Music::playQuickTime(): Failed to load file '%s'", musicName.c_str());
+		error("Music::playQuickTime(): Failed to load file '%s'", musicName.toString().c_str());
 	_parser->setTrack(0);
 }
 
diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp
index f37adb2ab01..5f41ad7e071 100644
--- a/engines/saga/resource.cpp
+++ b/engines/saga/resource.cpp
@@ -501,12 +501,13 @@ void Resource::loadResource(ResourceContext *context, uint32 resourceId, ByteArr
 			sz--;
 		if (sz > 0)
 			sz--;
+		Common::Path filePath;
 		if (_vm->getFeatures() & GF_ITE_FLOPPY)
-			fileName = Common::String::format("%s%02d.adf", fileName.substr(0, sz).c_str(), resourceData->diskNum + 1);
+			filePath = Common::Path(Common::String::format("%s%02d.adf", fileName.substr(0, sz).c_str(), resourceData->diskNum + 1));
 		else
-			fileName = Common::String::format("%s.%03d", fileName.substr(0, sz).c_str(), resourceData->diskNum);
-		if (!actualFile.open(fileName))
-			error("Resource::loadResource() failed to open %s", fileName.c_str());
+			filePath = Common::Path(Common::String::format("%s.%03d", fileName.substr(0, sz).c_str(), resourceData->diskNum));
+		if (!actualFile.open(filePath))
+			error("Resource::loadResource() failed to open %s", filePath.toString().c_str());
 		file = &actualFile;
 	}
 
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 561f2caa225..d050d946eb3 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -253,7 +253,7 @@ SagaEngine::SagaEngine(OSystem *syst, const SAGAGameDescription *gameDesc)
 
 	_frameCount = 0;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	// The Linux version of Inherit the Earth puts all data files in an
 	// 'itedata' sub-directory, except for voices.rsc


Commit: 0c3ddc2a87697ae83b4fd0028283614148e5a146
    https://github.com/scummvm/scummvm/commit/0c3ddc2a87697ae83b4fd0028283614148e5a146
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SAGA2: Migrate engine to Path

Changed paths:
    engines/saga2/console.cpp
    engines/saga2/hresmgr.cpp
    engines/saga2/hresmgr.h
    engines/saga2/main.cpp
    engines/saga2/saga2.cpp
    engines/saga2/video.cpp


diff --git a/engines/saga2/console.cpp b/engines/saga2/console.cpp
index cf59364ae1c..d5a9ec82dcb 100644
--- a/engines/saga2/console.cpp
+++ b/engines/saga2/console.cpp
@@ -427,7 +427,7 @@ bool Console::cmdDumpMap(int argc, const char **argv) {
 		sur.create(drawMap._size.x, drawMap._size.y, Graphics::PixelFormat::createFormatCLUT8());
 		sur.setPixels(drawMap._data);
 
-		Common::String pngFile = Common::String::format("%s-mapdump.png", _vm->getMetaEngine()->getName());
+		Common::Path pngFile(Common::String::format("%s-mapdump.png", _vm->getMetaEngine()->getName()));
 		Common::DumpFile dump;
 		dump.open(pngFile);
 
diff --git a/engines/saga2/hresmgr.cpp b/engines/saga2/hresmgr.cpp
index 28920451538..385ed32d52d 100644
--- a/engines/saga2/hresmgr.cpp
+++ b/engines/saga2/hresmgr.cpp
@@ -238,7 +238,7 @@ uint32 hResContext::getSize(hResID id, const char desc[]) {
 	return entry->size;
 }
 
-byte *hResContext::loadResource(hResID id, const char desc[], Common::String filename) {
+byte *hResContext::loadResource(hResID id, const char desc[], const Common::Path &filename) {
 	hResEntry *entry;
 
 	debugC(3, kDebugResources, "Loading resource %x (%s)", id, desc);
@@ -249,11 +249,10 @@ byte *hResContext::loadResource(hResID id, const char desc[], Common::String fil
 
 	byte *res = (byte*)malloc(entry->size);
 
-	if (filename.equalsIgnoreCase(""))
-		filename = _filename;
+	const Common::Path &path = filename.empty() ? _filename : filename;
 
 	if (!_file.isOpen())
-		_file.open(filename);
+		_file.open(path);
 
 	_file.seek(entry->offset, SEEK_SET);
 	_file.read(res, entry->size);
@@ -261,7 +260,7 @@ byte *hResContext::loadResource(hResID id, const char desc[], Common::String fil
 	return res;
 }
 
-byte *hResContext::loadIndexResource(int16 index, const char desc[], Common::String filename) {
+byte *hResContext::loadIndexResource(int16 index, const char desc[], const Common::Path &filename) {
 	hResEntry *entry;
 	entry = &_base[index];
 
@@ -283,11 +282,10 @@ byte *hResContext::loadIndexResource(int16 index, const char desc[], Common::Str
 	debugC(5, kDebugResources, "_indexData: pushing (%d, %p)", index, (void*)res);
 	_indexData.setVal(index, res);
 
-	if (filename.equalsIgnoreCase(""))
-		filename = _filename;
+	const Common::Path &path = filename.empty() ? _filename : filename;
 
 	if (!_file.isOpen())
-		_file.open(filename);
+		_file.open(path);
 
 	_file.seek(entry->offset, SEEK_SET);
 	_file.read(res, entry->size);
diff --git a/engines/saga2/hresmgr.h b/engines/saga2/hresmgr.h
index 3c645824907..2f191cbde21 100644
--- a/engines/saga2/hresmgr.h
+++ b/engines/saga2/hresmgr.h
@@ -112,7 +112,7 @@ protected:
 
 public:
 	bool            _valid;
-	Common::String  _filename;
+	Common::Path    _filename;
 
 	hResContext();
 	hResContext(hResContext *sire, hResID id, const char []);
@@ -137,8 +137,8 @@ public:
 	bool        skip(uint32 amount);
 	bool        get(hResID id, void *buffer, uint32 size);
 	uint32       getSize(hResID id, const char desc[]);
-	byte       *loadResource(hResID id, const char desc[], Common::String filename = "");
-	byte       *loadIndexResource(int16 index, const char desc[], Common::String filename = "");
+	byte       *loadResource(hResID id, const char desc[], const Common::Path &filename = Common::Path());
+	byte       *loadIndexResource(int16 index, const char desc[], const Common::Path &filename = Common::Path());
 	void        releaseIndexData();
 	Common::File     *resFileHandle() {
 		return _handle;
diff --git a/engines/saga2/main.cpp b/engines/saga2/main.cpp
index d5cd19b4376..1e184e79c2a 100644
--- a/engines/saga2/main.cpp
+++ b/engines/saga2/main.cpp
@@ -528,7 +528,7 @@ void dumpResource(hResContext *con, uint32 id) {
 
 	Common::DumpFile out;
 
-	Common::String path = Common::String::format("./dumps/mus%s.dat", tag2strP(id));
+	Common::Path path(Common::String::format("./dumps/mus%s.dat", tag2strP(id)));
 
 	if (out.open(path, true)) {
 		out.write(buffer, size);
diff --git a/engines/saga2/saga2.cpp b/engines/saga2/saga2.cpp
index f77c92117e4..7540b28dfb2 100644
--- a/engines/saga2/saga2.cpp
+++ b/engines/saga2/saga2.cpp
@@ -61,7 +61,7 @@ Saga2Engine *g_vm;
 
 Saga2Engine::Saga2Engine(OSystem *syst, const SAGA2GameDescription *desc)
 	: Engine(syst), _gameDescription(desc) {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	// Don't forget to register your random source
 	_rnd = new Common::RandomSource("saga2");
diff --git a/engines/saga2/video.cpp b/engines/saga2/video.cpp
index c49a3bcee98..b11dd78a2fe 100644
--- a/engines/saga2/video.cpp
+++ b/engines/saga2/video.cpp
@@ -41,7 +41,7 @@ void Saga2Engine::startVideo(const char *fileName, int x, int y) {
 	if (!_smkDecoder)
 		_smkDecoder = new Video::SmackerDecoder();
 
-	if (!_smkDecoder->loadFile(fname)) {
+	if (!_smkDecoder->loadFile(Common::Path(fname))) {
 		warning("startVideo: Cannot open file %s", fname.c_str());
 
 		return;


Commit: 45286ad131cb538afea2694f159ee6b730114d7b
    https://github.com/scummvm/scummvm/commit/45286ad131cb538afea2694f159ee6b730114d7b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SCI: Migrate engine to Path

Changed paths:
    engines/sci/console.cpp
    engines/sci/console.h
    engines/sci/detection.cpp
    engines/sci/engine/file.cpp
    engines/sci/engine/kfile.cpp
    engines/sci/engine/kscripts.cpp
    engines/sci/engine/ksound.cpp
    engines/sci/engine/kvideo.cpp
    engines/sci/graphics/macfont.cpp
    engines/sci/graphics/portrait.cpp
    engines/sci/graphics/video32.cpp
    engines/sci/graphics/video32.h
    engines/sci/resource/resource.cpp
    engines/sci/resource/resource.h
    engines/sci/resource/resource_audio.cpp
    engines/sci/resource/resource_intern.h
    engines/sci/sci.cpp
    engines/sci/sound/audio.cpp
    engines/sci/video/robot_decoder.cpp


diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 44216f04849..f70bb2da9e4 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -291,9 +291,9 @@ void Console::postEnter() {
 	if (!_videoFile.empty()) {
 		Common::ScopedPtr<Video::VideoDecoder> videoDecoder;
 
-		if (_videoFile.hasSuffix(".seq")) {
+		if (_videoFile.baseName().hasSuffix(".seq")) {
 			videoDecoder.reset(new SEQDecoder(_videoFrameDelay));
-		} else if (_videoFile.hasSuffix(".avi")) {
+		} else if (_videoFile.baseName().hasSuffix(".avi")) {
 			videoDecoder.reset(new Video::AVIDecoder());
 		} else {
 			warning("Unrecognized video type");
@@ -304,7 +304,7 @@ void Console::postEnter() {
 			playVideo(*videoDecoder);
 			_engine->_gfxCursor->kernelShow();
 		} else
-			warning("Could not play video %s\n", _videoFile.c_str());
+			warning("Could not play video %s\n", _videoFile.toString(Common::Path::kNativeSeparator).c_str());
 
 		_videoFile.clear();
 		_videoFrameDelay = 0;
@@ -881,7 +881,7 @@ void Console::cmdDiskDumpWorker(ResourceType resourceType, int resourceNumber, u
 		outFile->finalize();
 		outFile->close();
 		delete outFile;
-		debugPrintf("Resource %s (located in %s) has been dumped to disk\n", outFileName, resource->getResourceLocation().c_str());
+		debugPrintf("Resource %s (located in %s) has been dumped to disk\n", outFileName, resource->getResourceLocation().toString(Common::Path::kNativeSeparator).c_str());
 	} else {
 		debugPrintf("Resource %s not found\n", outFileName);
 	}
@@ -1032,7 +1032,7 @@ bool Console::cmdResourceIntegrityDump(int argc, const char **argv) {
 				extension = getResourceTypeExtension(resType);
 				assert(*extension != '\0');
 
-				const Common::String filesGlob = Common::String::format("*.%s", extension).c_str();
+				const Common::Path filesGlob(Common::String::format("*.%s", extension));
 				Common::ArchiveMemberList files;
 				const int numMatches = SearchMan.listMatchingMembers(files, filesGlob);
 				if (numMatches > 0) {
@@ -1069,7 +1069,7 @@ bool Console::cmdResourceIntegrityDump(int argc, const char **argv) {
 					Common::MemoryReadStream stream = resource->toStream();
 					writeIntegrityDumpLine(statusName, resourceName, outFile, &stream, resource->size(), true);
 				} else if (videoFiles && *extension != '\0') {
-					const Common::String fileName = Common::String::format("%u.%s", it->getNumber(), extension);
+					const Common::Path fileName(Common::String::format("%u.%s", it->getNumber(), extension));
 					Common::File file;
 					Common::ReadStream *stream = nullptr;
 					if (file.open(fileName)) {
@@ -1179,7 +1179,7 @@ bool Console::cmdResourceInfo(int argc, const char **argv) {
 		Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0);
 		if (resource) {
 			debugPrintf("Resource size: %u\n", resource->size());
-			debugPrintf("Resource location: %s\n", resource->getResourceLocation().c_str());
+			debugPrintf("Resource location: %s\n", resource->getResourceLocation().toString().c_str());
 			Common::MemoryReadStream stream = resource->toStream();
 			const Common::String hash = Common::computeStreamMD5AsString(stream);
 			debugPrintf("Resource hash (decompressed): %s\n", hash.c_str());
@@ -1552,9 +1552,9 @@ bool Console::cmdAudioDump(int argc, const char **argv) {
 	Common::MemoryReadStream stream = resource->toStream();
 
 	Common::DumpFile outFile;
-	const Common::String fileName = Common::String::format("%s.wav", id.toString().c_str());
+	const Common::Path fileName(Common::String::format("%s.wav", id.toString().c_str()));
 	if (!outFile.open(fileName)) {
-		debugPrintf("Could not open dump file %s.\n", fileName.c_str());
+		debugPrintf("Could not open dump file %s.\n", fileName.toString(Common::Path::kNativeSeparator).c_str());
 		return true;
 	}
 
@@ -1660,7 +1660,7 @@ bool Console::cmdAudioDump(int argc, const char **argv) {
 		error("Impossible situation");
 	}
 
-	debugPrintf("Written to %s successfully.\n", fileName.c_str());
+	debugPrintf("Written to %s successfully.\n", fileName.toString(Common::Path::kNativeSeparator).c_str());
 #else
 	debugPrintf("SCI32 isn't included in this compiled executable\n");
 #endif
@@ -3286,13 +3286,13 @@ bool Console::cmdDumpReference(int argc, const char **argv) {
 	}
 
 	Common::DumpFile out;
-	Common::String outFileName;
+	Common::Path outFileName;
 	uint32 bytesWritten;
 
 	switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) {
 #ifdef ENABLE_SCI32
 	case SEG_TYPE_BITMAP: {
-		outFileName = Common::String::format("%04x_%04x.tga", PRINT_REG(reg));
+		outFileName = Common::Path(Common::String::format("%04x_%04x.tga", PRINT_REG(reg)));
 		out.open(outFileName);
 		SciBitmap &bitmap = *_engine->_gamestate->_segMan->lookupBitmap(reg);
 		const Color *color = g_sci->_gfxPalette32->getCurrentPalette().colors;
@@ -3348,7 +3348,7 @@ bool Console::cmdDumpReference(int argc, const char **argv) {
 			debugPrintf("Block size less than or equal to %d\n", size);
 		}
 
-		outFileName = Common::String::format("%04x_%04x.dmp", PRINT_REG(reg));
+		outFileName = Common::Path(Common::String::format("%04x_%04x.dmp", PRINT_REG(reg)));
 		out.open(outFileName);
 		bytesWritten = out.write(block.raw, size);
 		break;
@@ -3358,7 +3358,7 @@ bool Console::cmdDumpReference(int argc, const char **argv) {
 	out.finalize();
 	out.close();
 
-	debugPrintf("Wrote %u bytes to %s\n", bytesWritten, outFileName.c_str());
+	debugPrintf("Wrote %u bytes to %s\n", bytesWritten, outFileName.toString(Common::Path::kNativeSeparator).c_str());
 	return true;
 }
 
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 615d9dfe8e3..5d1f5db4b79 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -215,7 +215,7 @@ private:
 
 	SciEngine *_engine;
 	DebugState &_debugState;
-	Common::String _videoFile;
+	Common::Path _videoFile;
 	int _videoFrameDelay;
 	uint16 _gameFlagsGlobal;
 };
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 2936c8424c0..3e48c5f4da8 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -215,7 +215,7 @@ public:
 	ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist, ADDetectedGameExtraInfo **extra) const override;
 
 private:
-	void addFileToDetectedGame(const Common::String &name, const FileMap &allFiles, MD5Properties md5Prop, ADDetectedGame &game) const;
+	void addFileToDetectedGame(const Common::Path &name, const FileMap &allFiles, MD5Properties md5Prop, ADDetectedGame &game) const;
 };
 
 ADDetectedGame SciMetaEngineDetection::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist, ADDetectedGameExtraInfo **extra) const {
@@ -264,7 +264,7 @@ ADDetectedGame SciMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 		addFileToDetectedGame("resource.map", allFiles, md5Prop, game);
 		for (int i = 0; i <= 11; i++) {
 			Common::String volume = Common::String::format("resource.%03d", i);
-			addFileToDetectedGame(volume, allFiles, md5Prop, game);
+			addFileToDetectedGame(Common::Path(volume, '/'), allFiles, md5Prop, game);
 		}
 
 		// add message and audio volumes.
@@ -276,22 +276,22 @@ ADDetectedGame SciMetaEngineDetection::fallbackDetect(const FileMap &allFiles, c
 		for (int i = 0; i <= 7; i++) {
 			Common::String map = Common::String::format("resmap.%03d", i);
 			Common::String volume = Common::String::format("ressci.%03d", i);
-			addFileToDetectedGame(map, allFiles, md5Prop, game);
-			addFileToDetectedGame(volume, allFiles, md5Prop, game);
+			addFileToDetectedGame(Common::Path(map), allFiles, md5Prop, game);
+			addFileToDetectedGame(Common::Path(volume), allFiles, md5Prop, game);
 		}
 	} else if (allFiles.contains("Data1")) {
 		// add Mac volumes
 		md5Prop = (MD5Properties)(md5Prop | kMD5MacResOrDataFork);
 		for (int i = 1; i <= 13; i++) {
 			Common::String volume = Common::String::format("Data%d", i);
-			addFileToDetectedGame(volume, allFiles, md5Prop, game);
+			addFileToDetectedGame(Common::Path(volume), allFiles, md5Prop, game);
 		}
 	}
 
 	return game;
 }
 
-void SciMetaEngineDetection::addFileToDetectedGame(const Common::String &name, const FileMap &allFiles, MD5Properties md5Prop, ADDetectedGame &game) const {
+void SciMetaEngineDetection::addFileToDetectedGame(const Common::Path &name, const FileMap &allFiles, MD5Properties md5Prop, ADDetectedGame &game) const {
 	FileProperties fileProperties;
 	if (getFileProperties(allFiles, md5Prop, name, fileProperties)) {
 		game.hasUnknownFiles = true;
diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp
index 6a854676513..fa392640f4d 100644
--- a/engines/sci/engine/file.cpp
+++ b/engines/sci/engine/file.cpp
@@ -191,7 +191,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, kFileOpenMode mo
 		// If no matching savestate exists: fall back to reading from a regular
 		// file
 		if (!inFile)
-			inFile = SearchMan.createReadStreamForMember(englishName);
+			inFile = SearchMan.createReadStreamForMember(Common::Path(englishName));
 
 		if (mode == kFileOpenModeOpenOrFail && !inFile) {
 			debugC(kDebugLevelFile, "  -> file_open(kFileOpenModeOpenOrFail): failed to open file '%s'", englishName.c_str());
@@ -213,7 +213,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, kFileOpenMode mo
 		// If no matching savestate exists: fall back to reading from a regular
 		// file
 		if (!inFile)
-			inFile = SearchMan.createReadStreamForMember(englishName);
+			inFile = SearchMan.createReadStreamForMember(Common::Path(englishName));
 
 		if (!inFile)
 			debugC(kDebugLevelFile, "  -> file_open(kFileOpenModeOpenOrFail): failed to open file '%s'", englishName.c_str());
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 6814c7e17f9..268ffbf8669 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -343,7 +343,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
 		unwrapFilename = false;
 
 		// LSL6hires version is in a file with an empty extension
-		if (Common::File::exists(name + ".")) {
+		if (Common::File::exists(Common::Path(name + "."))) {
 			name += ".";
 		}
 	}
@@ -849,7 +849,7 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
 	// phantsg.dir, and possibly even keeping it open persistently
 
 	// Check for regular file
-	exists = Common::File::exists(name);
+	exists = Common::File::exists(Common::Path(name));
 
 	// Check for a savegame with the name
 	Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager();
@@ -909,7 +909,7 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
 	// case someone has a "HalfDome.bin" file, etc.
 	if (!exists && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
 			(name == "HalfDome" || name == "Kq6Movie"))
-		exists = Common::MacResManager::exists(name);
+		exists = Common::MacResManager::exists(Common::Path(name));
 
 	debugC(kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists);
 	return make_reg(0, exists);
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index d6189a56fa6..1da0424e486 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -183,7 +183,7 @@ reg_t kResCheck(EngineState *s, int argc, reg_t *argv) {
 		}
 
 		if (format) {
-			const Common::String fileName = Common::String::format(format, argv[1].toUint16());
+			const Common::Path fileName(Common::String::format(format, argv[1].toUint16()));
 			return make_reg(0, Common::File::exists(fileName));
 		}
 	}
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 8480b11e55a..f44e218ea6a 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -501,7 +501,7 @@ reg_t kSetLanguage(EngineState *s, int argc, reg_t *argv) {
 	// Used by script 90 of MUMG Deluxe from the main menu to toggle between
 	// English and Spanish in some versions and English and Spanish and
 	// French and German in others.
-	const Common::String audioDirectory = s->_segMan->getString(argv[0]);
+	const Common::Path audioDirectory(s->_segMan->getString(argv[0]));
 	if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
 		g_sci->getResMan()->changeMacAudioDirectory(audioDirectory);
 	} else {
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 1a67406c4f7..a37d77d16a6 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -129,7 +129,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
 	bool switchedGraphicsMode = false;
 
 	if (argv[0].isPointer()) {
-		Common::String filename = s->_segMan->getString(argv[0]);
+		Common::Path filename(s->_segMan->getString(argv[0]));
 
 		if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
 			// Mac QuickTime
@@ -156,7 +156,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
 
 			videoDecoder.reset(new Video::QuickTimeDecoder());
 			if (!videoDecoder->loadFile(filename))
-				error("Could not open '%s'", filename.c_str());
+				error("Could not open '%s'", filename.toString().c_str());
 		} else {
 			// DOS SEQ
 			// SEQ's are called with no subops, just the string and delay
@@ -164,7 +164,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
 			videoDecoder.reset(new SEQDecoder(argv[1].toUint16()));
 
 			if (!videoDecoder->loadFile(filename)) {
-				warning("Failed to open movie file %s", filename.c_str());
+				warning("Failed to open movie file %s", filename.toString().c_str());
 				videoDecoder.reset();
 			}
 		}
@@ -211,7 +211,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
 
 #ifdef ENABLE_SCI32
 reg_t kShowMovie32(EngineState *s, int argc, reg_t *argv) {
-	Common::String fileName = s->_segMan->getString(argv[0]);
+	Common::Path fileName(s->_segMan->getString(argv[0]));
 	const int16 numTicks = argv[1].toSint16();
 	const int16 x = argc > 3 ? argv[2].toSint16() : 0;
 	const int16 y = argc > 3 ? argv[3].toSint16() : 0;
@@ -315,7 +315,7 @@ reg_t kShowMovieWinOpen(EngineState *s, int argc, reg_t *argv) {
 		//--argc;
 	}
 
-	const Common::String fileName = s->_segMan->getString(argv[0]);
+	const Common::Path fileName(s->_segMan->getString(argv[0]));
 	return make_reg(0, g_sci->_video32->getAVIPlayer().open(fileName));
 }
 
@@ -394,7 +394,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kPlayVMDOpen(EngineState *s, int argc, reg_t *argv) {
-	const Common::String fileName = s->_segMan->getString(argv[0]);
+	const Common::Path fileName(s->_segMan->getString(argv[0]));
 	// argv[1] is an optional cache size argument which we do not use
 	// const uint16 cacheSize = argc > 1 ? CLIP<int16>(argv[1].toSint16(), 16, 1024) : 0;
 	const VMDPlayer::OpenFlags flags = argc > 2 ? (VMDPlayer::OpenFlags)argv[2].toUint16() : VMDPlayer::kOpenFlagNone;
diff --git a/engines/sci/graphics/macfont.cpp b/engines/sci/graphics/macfont.cpp
index 12feefa4730..0685b5f28b3 100644
--- a/engines/sci/graphics/macfont.cpp
+++ b/engines/sci/graphics/macfont.cpp
@@ -81,7 +81,7 @@ GfxMacFontManager::~GfxMacFontManager() {
 bool GfxMacFontManager::initFromFontTable(Common::MacResManager *macExecutable) {
 	Common::SeekableReadStream *table = macExecutable->getResource(MKTAG('f', 't', 'b', 'l'), 128);
 	if (table == nullptr) {
-		warning("Mac font table not found in \"%s\"", macExecutable->getBaseFileName().toString().c_str());
+		warning("Mac font table not found in \"%s\"", macExecutable->getBaseFileName().toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -89,14 +89,14 @@ bool GfxMacFontManager::initFromFontTable(Common::MacResManager *macExecutable)
 	uint16 defaultFontIndex = table->readUint16BE();
 	uint16 numberOfFonts = table->readUint16BE();
 	if (table->eos() || table->size() < 4 + numberOfFonts * 10) {
-		warning("Invalid mac font table in \"%s\"", macExecutable->getBaseFileName().toString().c_str());
+		warning("Invalid mac font table in \"%s\"", macExecutable->getBaseFileName().toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	for (uint16 i = 0; i < numberOfFonts; ++i) {
 		uint16 sciFontId = table->readUint16BE();
 		if (_macFonts.contains(sciFontId)) {
-			warning("Duplicate Mac font table entry for %d in \"%s\"", sciFontId, macExecutable->getBaseFileName().toString().c_str());
+			warning("Duplicate Mac font table entry for %d in \"%s\"", sciFontId, macExecutable->getBaseFileName().toString(Common::Path::kNativeSeparator).c_str());
 			return false;
 		}
 		uint16 macFontId = table->readUint16BE();
@@ -107,7 +107,7 @@ bool GfxMacFontManager::initFromFontTable(Common::MacResManager *macExecutable)
 		const Graphics::Font *smallFont = getMacFont(macFontId, smallFontSize);
 		const Graphics::Font *largeFont = getMacFont(macFontId, MAX(mediumFontSize, largeFontSize));
 		if (smallFont == nullptr || largeFont == nullptr) {
-			warning("Mac font %d not found in \"%s\"", macFontId, macExecutable->getBaseFileName().toString().c_str());
+			warning("Mac font %d not found in \"%s\"", macFontId, macExecutable->getBaseFileName().toString(Common::Path::kNativeSeparator).c_str());
 			return false;
 		}
 
diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp
index 22243b16120..06a19cc81b0 100644
--- a/engines/sci/graphics/portrait.cpp
+++ b/engines/sci/graphics/portrait.cpp
@@ -83,7 +83,7 @@ void Portrait::init() {
 	// 4 bytes appended, seem to be random
 	//   9E11120E for alex
 	//   9E9E9E9E for vizier
-	Common::String fileName = "actors/" + _resourceName + ".bin";
+	Common::Path fileName("actors/" + _resourceName + ".bin", '/');
 	Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(fileName);
 
 	if (!file) {
@@ -92,7 +92,7 @@ void Portrait::init() {
 		if (!file)
 			error("portrait %s.bin not found", _resourceName.c_str());
 	}
-	_fileData->allocateFromStream(*file, Common::kSpanMaxSize, fileName);
+	_fileData->allocateFromStream(*file, Common::kSpanMaxSize, fileName.toString('/'));
 	delete file;
 
 	if (strncmp((const char *)_fileData->getUnsafeDataAt(0, 3), "WIN", 3)) {
diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp
index 786a9a95458..347b8a00c08 100644
--- a/engines/sci/graphics/video32.cpp
+++ b/engines/sci/graphics/video32.cpp
@@ -54,9 +54,9 @@ namespace Graphics { struct Surface; }
 
 namespace Sci {
 
-bool VideoPlayer::open(const Common::String &fileName) {
+bool VideoPlayer::open(const Common::Path &fileName) {
 	if (!_decoder->loadFile(fileName)) {
-		warning("Failed to load %s", fileName.c_str());
+		warning("Failed to load %s", fileName.toString().c_str());
 		return false;
 	}
 
@@ -346,7 +346,7 @@ void VideoPlayer::setDrawRect(const int16 x, const int16 y, const int16 width, c
 SEQPlayer::SEQPlayer(EventManager *eventMan) :
 	VideoPlayer(eventMan) {}
 
-void SEQPlayer::play(const Common::String &fileName, const int16 numTicks, const int16, const int16) {
+void SEQPlayer::play(const Common::Path &fileName, const int16 numTicks, const int16, const int16) {
 
 	_decoder.reset(new SEQDecoder(numTicks));
 
@@ -389,7 +389,7 @@ AVIPlayer::AVIPlayer(EventManager *eventMan) :
 	_decoder->setSoundType(Audio::Mixer::kSFXSoundType);
 }
 
-AVIPlayer::IOStatus AVIPlayer::open(const Common::String &fileName) {
+AVIPlayer::IOStatus AVIPlayer::open(const Common::Path &fileName) {
 	if (_status != kAVINotOpen) {
 		close();
 	}
@@ -545,7 +545,7 @@ uint16 AVIPlayer::getDuration() const {
 QuickTimePlayer::QuickTimePlayer(EventManager *eventMan) :
 	VideoPlayer(eventMan) {}
 
-void QuickTimePlayer::play(const Common::String& fileName) {
+void QuickTimePlayer::play(const Common::Path &fileName) {
 	_decoder.reset(new Video::QuickTimeDecoder());
 
 	if (!VideoPlayer::open(fileName)) {
@@ -619,16 +619,16 @@ VMDPlayer::~VMDPlayer() {
 #pragma mark -
 #pragma mark VMDPlayer - Playback
 
-VMDPlayer::IOStatus VMDPlayer::open(const Common::String &fileName, const OpenFlags flags) {
+VMDPlayer::IOStatus VMDPlayer::open(const Common::Path &fileName, const OpenFlags flags) {
 	if (_isOpen) {
-		error("Attempted to play %s, but another VMD was loaded", fileName.c_str());
+		error("Attempted to play %s, but another VMD was loaded", fileName.toString().c_str());
 	}
 
 	if (g_sci->_features->VMDOpenStopsAudio()) {
 		g_sci->_audio32->stop(kAllChannels);
 	}
 
-	Resource *bundledVmd = g_sci->getResMan()->findResource(ResourceId(kResourceTypeVMD, fileName.asUint64()), true);
+	Resource *bundledVmd = g_sci->getResMan()->findResource(ResourceId(kResourceTypeVMD, fileName.baseName().asUint64()), true);
 
 	if (bundledVmd != nullptr) {
 		Common::SeekableReadStream *stream = bundledVmd->makeStream();
@@ -649,8 +649,8 @@ VMDPlayer::IOStatus VMDPlayer::open(const Common::String &fileName, const OpenFl
 		}
 
 		// Try load fan-made SRT subtitles for current video
-		Common::String subtitlesName = Common::String::format("%s.srt", fileName.c_str());
-		_subtitles.loadSRTFile(subtitlesName.c_str());
+		Common::Path subtitlesName(fileName.append(".srt"));
+		_subtitles.loadSRTFile(subtitlesName);
 
 		return kIOSuccess;
 	}
@@ -1188,7 +1188,7 @@ void DuckPlayer::open(const GuiResourceId resourceId, const int displayMode, con
 		error("Attempted to play %u.duk, but another video was loaded", resourceId);
 	}
 
-	const Common::String fileName = Common::String::format("%u.duk", resourceId);
+	const Common::Path fileName(Common::String::format("%u.duk", resourceId));
 
 	if (!VideoPlayer::open(fileName)) {
 		return;
@@ -1219,8 +1219,8 @@ void DuckPlayer::open(const GuiResourceId resourceId, const int displayMode, con
 	}
 
 	// Try load fan-made SRT subtitles for current video
-	Common::String subtitlesName = Common::String::format("%s.srt", fileName.c_str());
-	_subtitles.loadSRTFile(subtitlesName.c_str());
+	Common::Path subtitlesName(fileName.append(".srt"));
+	_subtitles.loadSRTFile(subtitlesName);
 
 	_status = kDuckOpen;
 }
diff --git a/engines/sci/graphics/video32.h b/engines/sci/graphics/video32.h
index 1707ef0cb95..92405666f3b 100644
--- a/engines/sci/graphics/video32.h
+++ b/engines/sci/graphics/video32.h
@@ -25,10 +25,10 @@
 #ifdef USE_RGB_COLOR
 #include "common/config-manager.h" // for ConfMan
 #endif
+#include "common/path.h"          // for Path
 #include "common/ptr.h"
 #include "common/rect.h"          // for Rect
 #include "common/scummsys.h"      // for int16, uint8, uint16, int32
-#include "common/str.h"           // for String
 #include "sci/engine/vm_types.h"  // for reg_t
 #include "sci/video/robot_decoder.h" // for RobotDecoder
 #include "sci/sound/audio32.h"    // for Audio32::kMaxVolume
@@ -93,7 +93,7 @@ protected:
 	 * ensure that the current system is actually capable of playing back the
 	 * video.
 	 */
-	bool open(const Common::String &fileName);
+	bool open(const Common::Path &fileName);
 
 	/**
 	 * Reinitializes the system hardware surface for playback of high-quality
@@ -219,7 +219,7 @@ public:
 	 * Plays a SEQ animation with the given file name, with each frame being
 	 * displayed for `numTicks` ticks.
 	 */
-	void play(const Common::String &fileName, const int16 numTicks, const int16 x, const int16 y);
+	void play(const Common::Path &fileName, const int16 numTicks, const int16 x, const int16 y);
 };
 
 #pragma mark -
@@ -249,7 +249,7 @@ public:
 	/**
 	 * Opens a stream to an AVI resource.
 	 */
-	IOStatus open(const Common::String &fileName);
+	IOStatus open(const Common::Path &fileName);
 
 	/**
 	 * Initializes the AVI rendering parameters for the current AVI. This must
@@ -300,7 +300,7 @@ public:
 	/**
 	 * Plays a QuickTime animation with the given file name
 	 */
-	void play(const Common::String& fileName);
+	void play(const Common::Path &fileName);
 };
 
 #pragma mark -
@@ -355,7 +355,7 @@ public:
 	/**
 	 * Opens a stream to a VMD resource.
 	 */
-	IOStatus open(const Common::String &fileName, const OpenFlags flags);
+	IOStatus open(const Common::Path &fileName, const OpenFlags flags);
 
 	/**
 	 * Initializes the VMD rendering parameters for the current VMD. This must
diff --git a/engines/sci/resource/resource.cpp b/engines/sci/resource/resource.cpp
index c328004ffdb..7f280b7718f 100644
--- a/engines/sci/resource/resource.cpp
+++ b/engines/sci/resource/resource.cpp
@@ -251,7 +251,7 @@ uint32 AudioVolumeResourceSource::getAudioCompressionType() const {
 	return _audioCompressionType;
 }
 
-ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum, const Common::FSNode *resFile)
+ResourceSource::ResourceSource(ResSourceType type, const Common::Path &name, int volNum, const Common::FSNode *resFile)
  : _sourceType(type), _name(name), _volumeNumber(volNum), _resourceFile(resFile) {
 	_scanned = false;
 }
@@ -259,7 +259,7 @@ ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, i
 ResourceSource::~ResourceSource() {
 }
 
-MacResourceForkResourceSource::MacResourceForkResourceSource(const Common::String &name, int volNum)
+MacResourceForkResourceSource::MacResourceForkResourceSource(const Common::Path &name, int volNum)
  : ResourceSource(kSourceMacResourceFork, name, volNum) {
 	_macResMan = new Common::MacResManager();
 }
@@ -272,7 +272,7 @@ MacResourceForkResourceSource::~MacResourceForkResourceSource() {
 
 // Resource source list management
 
-ResourceSource *ResourceManager::addExternalMap(const Common::String &filename, int volume_nr) {
+ResourceSource *ResourceManager::addExternalMap(const Common::Path &filename, int volume_nr) {
 	ResourceSource *newsrc = new ExtMapResourceSource(filename, volume_nr);
 
 	_sources.push_back(newsrc);
@@ -280,7 +280,7 @@ ResourceSource *ResourceManager::addExternalMap(const Common::String &filename,
 }
 
 ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) {
-	ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName(), volume_nr, mapFile);
+	ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getPathInArchive(), volume_nr, mapFile);
 
 	_sources.push_back(newsrc);
 	return newsrc;
@@ -293,7 +293,7 @@ ResourceSource *ResourceManager::addSource(ResourceSource *newsrc) {
 	return newsrc;
 }
 
-ResourceSource *ResourceManager::addPatchDir(const Common::String &dirname) {
+ResourceSource *ResourceManager::addPatchDir(const Common::Path &dirname) {
 	ResourceSource *newsrc = new DirectoryResourceSource(dirname);
 
 	_sources.push_back(newsrc);
@@ -343,9 +343,9 @@ bool Resource::loadPatch(Common::SeekableReadStream *file) {
 
 bool Resource::loadFromPatchFile() {
 	Common::File file;
-	const Common::String &filename = _source->getLocationName();
+	const Common::Path &filename = _source->getLocationName();
 	if (!file.open(filename)) {
-		warning("Failed to open patch file %s", filename.c_str());
+		warning("Failed to open patch file %s", filename.toString().c_str());
 		unalloc();
 		return false;
 	}
@@ -368,12 +368,13 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc
 	if (source->_resourceFile)
 		return source->_resourceFile->createReadStream();
 
-	const char *filename = source->getLocationName().c_str();
+	// TODO: check if it still works
+	const Common::String filename = source->getLocationName().toString('/');
 
 	// check if file is already opened
 	while (it != _volumeFiles.end()) {
 		file = *it;
-		if (scumm_stricmp(file->getName(), filename) == 0) {
+		if (scumm_stricmp(file->getName(), filename.c_str()) == 0) {
 			// move file to top
 			if (it != _volumeFiles.begin()) {
 				_volumeFiles.erase(it);
@@ -385,7 +386,7 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc
 	}
 	// adding a new file
 	file = new Common::File;
-	if (file->open(filename)) {
+	if (file->open(source->getLocationName())) {
 		if (_volumeFiles.size() == MAX_OPENED_VOLUMES) {
 			it = --_volumeFiles.end();
 			delete *it;
@@ -586,7 +587,7 @@ Common::SeekableReadStream *ResourceSource::getVolumeFile(ResourceManager *resMa
 	Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this);
 
 	if (!fileStream) {
-		warning("Failed to open %s", getLocationName().c_str());
+		warning("Failed to open %s", getLocationName().toString().c_str());
 		resMan->_hasBadResources = true;
 		if (res)
 			res->unalloc();
@@ -617,7 +618,7 @@ void ResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
 	int error = res->decompress(volVersion, fileStream);
 	if (error) {
 		warning("Error %d occurred while reading %s from resource file %s: %s",
-				error, res->_id.toString().c_str(), res->getResourceLocation().c_str(),
+				error, res->_id.toString().c_str(), res->getResourceLocation().toString().c_str(),
 				s_errorDescriptions[error]);
 		res->unalloc();
 	}
@@ -642,11 +643,11 @@ int ResourceManager::addAppropriateSources() {
 
 		Common::sort(files.begin(), files.end(), Common::ArchiveMemberListComparator());
 		for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
-			const Common::String name = (*x)->getName();
+			const Common::String name = (*x)->getFileName();
 			const char *dot = strrchr(name.c_str(), '.');
 			int number = atoi(dot + 1);
 
-			addSource(new VolumeResourceSource(name, map, number));
+			addSource(new VolumeResourceSource((*x)->getPathInArchive(), map, number));
 		}
 #ifdef ENABLE_SCI32
 		// GK1CD hires content
@@ -660,8 +661,8 @@ int ResourceManager::addAppropriateSources() {
 		Common::MacResManager::listFiles(files, "Data##");
 
 		for (Common::Array<Common::Path>::const_iterator x = files.begin(); x != files.end(); ++x) {
-			Common::String path(x->toString());
-			addSource(new MacResourceForkResourceSource(path, atoi(path.c_str() + 4)));
+			Common::String baseName(x->baseName());
+			addSource(new MacResourceForkResourceSource(*x, atoi(baseName.c_str() + 4)));
 		}
 
 #ifdef ENABLE_SCI32
@@ -683,17 +684,17 @@ int ResourceManager::addAppropriateSources() {
 
 		Common::sort(mapFiles.begin(), mapFiles.end(), Common::ArchiveMemberListComparator());
 		for (Common::ArchiveMemberList::const_iterator mapIterator = mapFiles.begin(); mapIterator != mapFiles.end(); ++mapIterator) {
-			Common::String mapName = (*mapIterator)->getName();
+			Common::String mapName = (*mapIterator)->getFileName();
 			int mapNumber = atoi(strrchr(mapName.c_str(), '.') + 1);
 			bool foundVolume = false;
 
 			for (Common::ArchiveMemberList::const_iterator fileIterator = files.begin(); fileIterator != files.end(); ++fileIterator) {
-				Common::String resName = (*fileIterator)->getName();
+				Common::String resName = (*fileIterator)->getFileName();
 				int resNumber = atoi(strrchr(resName.c_str(), '.') + 1);
 
 				if (mapNumber == resNumber) {
 					foundVolume = true;
-					addSource(new VolumeResourceSource(resName, addExternalMap(mapName, mapNumber), mapNumber));
+					addSource(new VolumeResourceSource((*fileIterator)->getPathInArchive(), addExternalMap((*mapIterator)->getPathInArchive(), mapNumber), mapNumber));
 					break;
 				}
 			}
@@ -758,7 +759,7 @@ int ResourceManager::addAppropriateSourcesForDetection(const Common::FSList &fsl
 		if (file->isDirectory())
 			continue;
 
-		Common::String filename = file->getName();
+		Common::String filename = file->getFileName();
 		filename.toLowercase();
 
 		if (filename.contains("resource.map"))
@@ -790,7 +791,7 @@ int ResourceManager::addAppropriateSourcesForDetection(const Common::FSList &fsl
 
 #ifdef ENABLE_SCI32
 	if (sci21PatchMap && sci21PatchRes)
-		addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap, kResPatVolumeNumber, sci21PatchRes));
+		addSource(new VolumeResourceSource(sci21PatchRes->getPathInArchive(), sci21PatchMap, kResPatVolumeNumber, sci21PatchRes));
 #endif
 
 	// Now find all the resource.0?? files
@@ -798,20 +799,20 @@ int ResourceManager::addAppropriateSourcesForDetection(const Common::FSList &fsl
 		if (file->isDirectory())
 			continue;
 
-		Common::String filename = file->getName();
+		Common::String filename = file->getFileName();
 		filename.toLowercase();
 
 		if (filename.contains("resource.0")) {
 			const char *dot = strrchr(filename.c_str(), '.');
 			int number = atoi(dot + 1);
 
-			addSource(new VolumeResourceSource(file->getName(), map, number, file));
+			addSource(new VolumeResourceSource(file->getPathInArchive(), map, number, file));
 		} else if (filename.contains("ressci.0")) {
 			const char *dot = strrchr(filename.c_str(), '.');
 			int number = atoi(dot + 1);
 
 			// Match this volume to its own map
-			addSource(new VolumeResourceSource(file->getName(), sci21Maps[number], number, file));
+			addSource(new VolumeResourceSource(file->getPathInArchive(), sci21Maps[number], number, file));
 		}
 	}
 
@@ -914,7 +915,7 @@ void IntMapResourceSource::scanSource(ResourceManager *resMan) {
 // dw offset
 // dw length
 
-ChunkResourceSource::ChunkResourceSource(const Common::String &name, uint16 number)
+ChunkResourceSource::ChunkResourceSource(const Common::Path &name, uint16 number)
 	: ResourceSource(kSourceChunk, name) {
 
 	_number = number;
@@ -981,7 +982,7 @@ void ChunkResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
 }
 
 void ResourceManager::addResourcesFromChunk(uint16 id) {
-	addSource(new ChunkResourceSource(Common::String::format("Chunk %d", id), id));
+	addSource(new ChunkResourceSource(Common::Path(Common::String::format("Chunk %d", id)), id));
 	scanNewSources();
 }
 
@@ -1500,7 +1501,7 @@ bool ResourceManager::detectSci2Mac() {
 	for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
 		ResourceSource *rsrc = *it;
 		if (rsrc->getSourceType() == kSourceMacResourceFork) {
-			if (macResManager.open(rsrc->getLocationName().c_str())) {
+			if (macResManager.open(rsrc->getLocationName())) {
 				const uint32 scriptTypeID = MKTAG('S', 'C', 'R', ' ');
 				const uint32 objectScriptID = 64999;
 				Common::SeekableReadStream *resource = macResManager.getResource(scriptTypeID, objectScriptID);
@@ -1577,7 +1578,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource
 	ResourceType checkForType = resourceType;
 
 	if (isBlacklistedPatch(resId)) {
-		debug("Skipping blacklisted patch file %s", source->getLocationName().c_str());
+		debug("Skipping blacklisted patch file %s", source->getLocationName().toString().c_str());
 		delete source;
 		return;
 	}
@@ -1593,7 +1594,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource
 	} else {
 		Common::File *file = new Common::File();
 		if (!file->open(source->getLocationName())) {
-			warning("ResourceManager::processPatch(): failed to open %s", source->getLocationName().c_str());
+			warning("ResourceManager::processPatch(): failed to open %s", source->getLocationName().toString().c_str());
 			delete source;
 			delete file;
 			return;
@@ -1603,7 +1604,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource
 
 	int fsize = fileStream->size();
 	if (fsize < 3) {
-		debug("Patching %s failed - file too small", source->getLocationName().c_str());
+		debug("Patching %s failed - file too small", source->getLocationName().toString().c_str());
 		delete source;
 		delete fileStream;
 		return;
@@ -1667,14 +1668,14 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource
 	delete fileStream;
 
 	if (patchType != checkForType) {
-		debug("Patching %s failed - resource type mismatch", source->getLocationName().c_str());
+		debug("Patching %s failed - resource type mismatch", source->getLocationName().toString().c_str());
 		delete source;
 		return;
 	}
 
 	if (patchDataOffset >= fsize) {
 		debug("Patching %s failed - patch starting at offset %d can't be in file of size %d",
-		      source->getLocationName().c_str(), patchDataOffset, fsize);
+		      source->getLocationName().toString().c_str(), patchDataOffset, fsize);
 		delete source;
 		return;
 	}
@@ -1683,7 +1684,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource
 	newrsc = updateResource(resId, source, 0, fsize - patchDataOffset, source->getLocationName());
 	newrsc->_headerSize = patchDataOffset;
 
-	debugC(1, kDebugLevelResMan, "Patching %s - OK", source->getLocationName().c_str());
+	debugC(1, kDebugLevelResMan, "Patching %s - OK", source->getLocationName().toString().c_str());
 }
 
 ResourceId convertPatchNameBase36(ResourceType type, const Common::String &filename) {
@@ -1733,7 +1734,8 @@ void ResourceManager::readResourcePatchesBase36() {
 		}
 
 		for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
-			Common::String name = (*x)->getName();
+			Common::Path path = (*x)->getPathInArchive();
+			Common::String name(path.baseName());
 			name.toUppercase();
 
 			// The S/T prefixes often conflict with non-patch files and generate
@@ -1754,12 +1756,12 @@ void ResourceManager::readResourcePatchesBase36() {
 
 			// Make sure that the audio patch is a valid resource
 			if (i == kResourceTypeAudio36) {
-				Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
+				Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(path);
 				uint32 tag = stream->readUint32BE();
 
 				if (tag == MKTAG('R','I','F','F') || tag == MKTAG('F','O','R','M')) {
 					delete stream;
-					processWavePatch(resource36, name);
+					processWavePatch(resource36, path);
 					continue;
 				}
 
@@ -1774,7 +1776,7 @@ void ResourceManager::readResourcePatchesBase36() {
 				delete stream;
 			}
 
-			ResourceSource *psrcPatch = new PatchResourceSource(name);
+			ResourceSource *psrcPatch = new PatchResourceSource(path);
 			processPatch(psrcPatch, (ResourceType)i, resource36.getNumber(), resource36.getTuple());
 		}
 	}
@@ -1785,7 +1787,7 @@ void ResourceManager::readResourcePatches() {
 	// this function tries to read patch file with any supported naming scheme,
 	// regardless of s_sciVersion value
 
-	Common::String mask, name;
+	Common::Path mask, name;
 	Common::ArchiveMemberList files;
 	uint16 resourceNr = 0;
 	const char *szResType;
@@ -1800,11 +1802,11 @@ void ResourceManager::readResourcePatches() {
 		szResType = getResourceTypeName((ResourceType)i);
 		// SCI0 naming - type.nnn
 		mask = szResType;
-		mask += ".###";
+		mask.appendInPlace(".###");
 		SearchMan.listMatchingMembers(files, mask);
 		// SCI1 and later naming - nnn.typ
 		mask = "*.";
-		mask += s_resourceTypeSuffixes[i];
+		mask.appendInPlace(s_resourceTypeSuffixes[i]);
 		SearchMan.listMatchingMembers(files, mask);
 
 		if (i == kResourceTypeView) {
@@ -1822,19 +1824,20 @@ void ResourceManager::readResourcePatches() {
 
 		for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
 			bool bAdd = false;
-			name = (*x)->getName();
+			name = (*x)->getPathInArchive();
+			Common::String baseName(name.baseName());
 
 			// SCI1 scheme
-			if (Common::isDigit(name[0])) {
+			if (Common::isDigit(baseName[0])) {
 				char *end = nullptr;
-				resourceNr = strtol(name.c_str(), &end, 10);
+				resourceNr = strtol(baseName.c_str(), &end, 10);
 				bAdd = (*end == '.'); // Ensure the next character is the period
 			} else {
 				// SCI0 scheme
 				int resname_len = strlen(szResType);
-				if (scumm_strnicmp(name.c_str(), szResType, resname_len) == 0
-					&& !Common::isAlpha(name[resname_len + 1])) {
-					resourceNr = atoi(name.c_str() + resname_len + 1);
+				if (scumm_strnicmp(baseName.c_str(), szResType, resname_len) == 0
+					&& !Common::isAlpha(baseName[resname_len + 1])) {
+					resourceNr = atoi(baseName.c_str() + resname_len + 1);
 					bAdd = true;
 				}
 			}
@@ -1880,7 +1883,7 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
 
 		if (fileStream->eos() || fileStream->err()) {
 			delete fileStream;
-			warning("Error while reading %s", map->getLocationName().c_str());
+			warning("Error while reading %s", map->getLocationName().toString().c_str());
 			return SCI_ERROR_RESMAP_NOT_FOUND;
 		}
 
@@ -1958,7 +1961,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
 		resMap[type].wOffset = fileStream->readUint16LE();
 		if (fileStream->eos()) {
 			delete fileStream;
-			warning("Premature end of file %s", map->getLocationName().c_str());
+			warning("Premature end of file %s", map->getLocationName().toString().c_str());
 			return SCI_ERROR_RESMAP_NOT_FOUND;
 		}
 
@@ -1993,7 +1996,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
 			}
 			if (fileStream->eos() || fileStream->err()) {
 				delete fileStream;
-				warning("Error while reading %s", map->getLocationName().c_str());
+				warning("Error while reading %s", map->getLocationName().toString().c_str());
 				return SCI_ERROR_RESMAP_NOT_FOUND;
 			}
 			resId = ResourceId(convertResType(type), number);
@@ -2038,7 +2041,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
 				IntMapResourceSource *audioMap = new IntMapResourceSource(source->getLocationName(), mapVolumeNr, resId.getNumber());
 				addSource(audioMap);
 
-				Common::String volumeName;
+				Common::Path volumeName;
 				if (mapVolumeNr == kResPatVolumeNumber) {
 					if (resId.getNumber() == 65535) {
 						volumeName = "RESSCI.PAT";
@@ -2046,7 +2049,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
 						volumeName = "RESAUD.001";
 					}
 				} else if (resId.getNumber() == 65535) {
-					volumeName = Common::String::format("RESSFX.%03d", mapVolumeNr);
+					volumeName = Common::Path(Common::String::format("RESSFX.%03d", mapVolumeNr));
 
 					if (g_sci && g_sci->getGameId() == GID_RAMA && !Common::File::exists(volumeName)) {
 						if (Common::File::exists("RESOURCE.SFX")) {
@@ -2056,7 +2059,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
 						}
 					}
 				} else {
-					volumeName = Common::String::format("RESAUD.%03d", mapVolumeNr);
+					volumeName = Common::Path(Common::String::format("RESAUD.%03d", mapVolumeNr));
 				}
 
 				ResourceSource *audioVolume = addSource(new AudioVolumeResourceSource(this, volumeName, audioMap, mapVolumeNr));
@@ -2112,8 +2115,8 @@ static Common::Array<uint32> resTypeToMacTags(ResourceType type) {
 }
 
 void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) {
-	if (!_macResMan->open(getLocationName().c_str()))
-		error("%s is not a valid Mac resource fork", getLocationName().c_str());
+	if (!_macResMan->open(getLocationName()))
+		error("%s is not a valid Mac resource fork", getLocationName().toString().c_str());
 
 	Common::MacResTagArray tagArray = _macResMan->getResTagArray();
 
@@ -2168,15 +2171,15 @@ void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) {
 	}
 }
 
-bool ResourceManager::validateResource(const ResourceId &resourceId, const Common::String &sourceMapLocation, const Common::String &sourceName, const uint32 offset, const uint32 size, const uint32 sourceSize) const {
+bool ResourceManager::validateResource(const ResourceId &resourceId, const Common::Path &sourceMapLocation, const Common::Path &sourceName, const uint32 offset, const uint32 size, const uint32 sourceSize) const {
 	if (size != 0) {
 		if (offset + size > sourceSize) {
-			warning("Resource %s from %s points beyond end of %s (%u + %u > %u)", resourceId.toString().c_str(), sourceMapLocation.c_str(), sourceName.c_str(), offset, size, sourceSize);
+			warning("Resource %s from %s points beyond end of %s (%u + %u > %u)", resourceId.toString().c_str(), sourceMapLocation.toString().c_str(), sourceName.toString().c_str(), offset, size, sourceSize);
 			return false;
 		}
 	} else {
 		if (offset >= sourceSize) {
-			warning("Resource %s from %s points beyond end of %s (%u >= %u)", resourceId.toString().c_str(), sourceMapLocation.c_str(), sourceName.c_str(), offset, sourceSize);
+			warning("Resource %s from %s points beyond end of %s (%u >= %u)", resourceId.toString().c_str(), sourceMapLocation.toString().c_str(), sourceName.toString().c_str(), offset, sourceSize);
 			return false;
 		}
 	}
@@ -2184,7 +2187,7 @@ bool ResourceManager::validateResource(const ResourceId &resourceId, const Commo
 	return true;
 }
 
-Resource *ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size, const Common::String &sourceMapLocation) {
+Resource *ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size, const Common::Path &sourceMapLocation) {
 	// Adding new resource only if it does not exist
 	// Hoyle 4 contains each audio resource twice. The first file is in an unknown
 	// format and only static sounds are heard when it's played. The second file
@@ -2197,7 +2200,7 @@ Resource *ResourceManager::addResource(ResourceId resId, ResourceSource *src, ui
 	}
 }
 
-Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 size, const Common::String &sourceMapLocation) {
+Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 size, const Common::Path &sourceMapLocation) {
 	uint32 offset = 0;
 	if (_resMap.contains(resId)) {
 		const Resource *res = _resMap.getVal(resId);
@@ -2206,7 +2209,7 @@ Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src,
 	return updateResource(resId, src, offset, size, sourceMapLocation);
 }
 
-Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size, const Common::String &sourceMapLocation) {
+Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size, const Common::Path &sourceMapLocation) {
 	// Update a patched resource, whether it exists or not
 	Resource *res = _resMap.getValOrDefault(resId, nullptr);
 
@@ -2216,13 +2219,13 @@ Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src,
 	if (src->getSourceType() != kSourceMacResourceFork) {
 		volumeFile = getVolumeFile(src);
 		if (volumeFile == nullptr) {
-			error("Could not open %s for reading", src->getLocationName().c_str());
+			error("Could not open %s for reading", src->getLocationName().toString().c_str());
 		}
 	}
 
 	AudioVolumeResourceSource *avSrc = dynamic_cast<AudioVolumeResourceSource *>(src);
 	if (avSrc != nullptr && !avSrc->relocateMapOffset(offset, size)) {
-		warning("Compressed volume %s does not contain a valid entry for %s (map offset %u)", src->getLocationName().c_str(), resId.toString().c_str(), offset);
+		warning("Compressed volume %s does not contain a valid entry for %s (map offset %u)", src->getLocationName().toString().c_str(), resId.toString().c_str(), offset);
 		_hasBadResources = true;
 		if (volumeFile != nullptr)
 			disposeVolumeFileStream(volumeFile, src);
@@ -2410,7 +2413,7 @@ int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file
 			const uint32 audioSize = READ_LE_UINT32(ptr + 9);
 			const uint32 calculatedTotalSize = audioSize + headerSize + kResourceHeaderSize;
 			if (calculatedTotalSize != _size) {
-				warning("Unexpected audio file size: the size of %s in %s is %d, but the volume says it should be %d", _id.toString().c_str(), _source->getLocationName().c_str(), calculatedTotalSize, _size);
+				warning("Unexpected audio file size: the size of %s in %s is %d, but the volume says it should be %d", _id.toString().c_str(), _source->getLocationName().toString().c_str(), calculatedTotalSize, _size);
 			}
 			_size = MIN(_size - kResourceHeaderSize, headerSize + audioSize);
 		}
@@ -3099,7 +3102,7 @@ Common::String ResourceManager::findSierraGameId(const bool isBE) {
 // Eventually they should be used for native menus and possibly even splash screens.
 // For example, LSL6 can't function without native menus. (bug #11356)
 // Executables that we currently don't use are commented out.
-Common::String ResourceManager::getMacExecutableName() const {
+Common::Path ResourceManager::getMacExecutableName() const {
 	switch (g_sci->getGameId()) {
 	case GID_CASTLEBRAIN: return "Castle of Dr. Brain"; // fonts, splash screen
 	case GID_FREDDYPHARKAS: return "Freddy Pharkas"; // fonts, icon bar, menu, splash screen
@@ -3121,7 +3124,7 @@ bool ResourceManager::isKoreanMessageMap(ResourceSource *source) {
 	return source->getLocationName() == "message.map" && g_sci && g_sci->getLanguage() == Common::KO_KOR;
 }
 
-const Common::String &Resource::getResourceLocation() const {
+const Common::Path &Resource::getResourceLocation() const {
 	return _source->getLocationName();
 }
 
diff --git a/engines/sci/resource/resource.h b/engines/sci/resource/resource.h
index 4798d704c2f..cb956a161c2 100644
--- a/engines/sci/resource/resource.h
+++ b/engines/sci/resource/resource.h
@@ -295,7 +295,7 @@ public:
 	Common::SeekableReadStream *makeStream() const;
 #endif
 
-	const Common::String &getResourceLocation() const;
+	const Common::Path &getResourceLocation() const;
 
 	// FIXME: This audio specific method is a hack. After all, why should a
 	// Resource have audio specific methods? But for now we keep this, as it
@@ -409,8 +409,8 @@ public:
 
 	void setAudioLanguage(int language);
 	int getAudioLanguage() const;
-	void changeAudioDirectory(Common::String path);
-	void changeMacAudioDirectory(Common::String path);
+	void changeAudioDirectory(const Common::Path &path);
+	void changeMacAudioDirectory(const Common::Path &path);
 	bool isGMTrackIncluded();
 	bool isSci11Mac() const { return _volVersion == kResVersionSci11Mac; }
 	ViewType getViewType() const { return _viewType; }
@@ -512,7 +512,7 @@ protected:
 	 * Add a path to the resource manager's list of sources.
 	 * @return a pointer to the added source structure, or NULL if an error occurred.
 	 */
-	ResourceSource *addPatchDir(const Common::String &path);
+	ResourceSource *addPatchDir(const Common::Path &path);
 
 	ResourceSource *findVolume(ResourceSource *map, int volume_nr);
 
@@ -530,7 +530,7 @@ protected:
 	 * @param volume_nr  The volume number the map starts at, 0 for <SCI2.1
 	 * @return		A pointer to the added source structure, or NULL if an error occurred.
 	 */
-	ResourceSource *addExternalMap(const Common::String &filename, int volume_nr = 0);
+	ResourceSource *addExternalMap(const Common::Path &filename, int volume_nr = 0);
 
 	ResourceSource *addExternalMap(const Common::FSNode *mapFile, int volume_nr = 0);
 
@@ -562,10 +562,10 @@ protected:
 	void disposeVolumeFileStream(Common::SeekableReadStream *fileStream, ResourceSource *source);
 	void loadResource(Resource *res);
 	void freeOldResources();
-	bool validateResource(const ResourceId &resourceId, const Common::String &sourceMapLocation, const Common::String &sourceName, const uint32 offset, const uint32 size, const uint32 sourceSize) const;
-	Resource *addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0, const Common::String &sourceMapLocation = Common::String("(no map location)"));
-	Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 size, const Common::String &sourceMapLocation = Common::String("(no map location)"));
-	Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size, const Common::String &sourceMapLocation = Common::String("(no map location)"));
+	bool validateResource(const ResourceId &resourceId, const Common::Path &sourceMapLocation, const Common::Path &sourceName, const uint32 offset, const uint32 size, const uint32 sourceSize) const;
+	Resource *addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0, const Common::Path &sourceMapLocation = Common::Path("(no map location)"));
+	Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 size, const Common::Path &sourceMapLocation = Common::Path("(no map location)"));
+	Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size, const Common::Path &sourceMapLocation = Common::Path("(no map location)"));
 	void removeAudioResource(ResourceId resId);
 
 	/**--- Resource map decoding functions ---*/
@@ -624,7 +624,7 @@ protected:
 	 * Process wave files as patches for Audio resources.
 	 */
 	void readWaveAudioPatches();
-	void processWavePatch(ResourceId resourceId, const Common::String &name);
+	void processWavePatch(ResourceId resourceId, const Common::Path &name);
 
 	/**
 	 * Process AIFF files as patches for Audio resources.
@@ -656,7 +656,7 @@ protected:
 
 public:
 	/** Returns the file name of the game's Mac executable. */
-	Common::String getMacExecutableName() const;
+	Common::Path getMacExecutableName() const;
 	bool isKoreanMessageMap(ResourceSource *source);
 
 private:
diff --git a/engines/sci/resource/resource_audio.cpp b/engines/sci/resource/resource_audio.cpp
index 4dde944645f..fd2b8cbf2d2 100644
--- a/engines/sci/resource/resource_audio.cpp
+++ b/engines/sci/resource/resource_audio.cpp
@@ -31,7 +31,7 @@
 
 namespace Sci {
 
-AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum)
+AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, const Common::Path &name, ResourceSource *map, int volNum)
 	: VolumeResourceSource(name, map, volNum, kSourceAudioVolume) {
 
 	_audioCompressionType = 0;
@@ -55,7 +55,7 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, co
 		_audioCompressionType = compressionType;
 		const uint32 numEntries = fileStream->readUint32LE();
 		if (!numEntries) {
-			error("Compressed audio volume %s has no relocation table entries", name.c_str());
+			error("Compressed audio volume %s has no relocation table entries", name.toString().c_str());
 		}
 
 		CompressedTableEntry *lastEntry = nullptr;
@@ -161,7 +161,7 @@ bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) {
 }
 
 void ResourceManager::addNewGMPatch(SciGameId gameId) {
-	Common::String gmPatchFile;
+	const char *gmPatchFile = nullptr;
 
 	switch (gameId) {
 	case GID_ECOQUEST:
@@ -189,17 +189,17 @@ void ResourceManager::addNewGMPatch(SciGameId gameId) {
 		gmPatchFile = "TALEGM.PAT";
 		break;
 	default:
-		break;
+		return;
 	}
 
-	if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) {
+	if (Common::File::exists(gmPatchFile)) {
 		ResourceSource *psrcPatch = new PatchResourceSource(gmPatchFile);
 		processPatch(psrcPatch, kResourceTypePatch, 4);
 	}
 }
 
 void ResourceManager::addNewD110Patch(SciGameId gameId) {
-	Common::String patchFile;
+	const char *patchFile = nullptr;
 
 	switch (gameId) {
 	case GID_CAMELOT:
@@ -231,16 +231,16 @@ void ResourceManager::addNewD110Patch(SciGameId gameId) {
 		break;
 	default:
 		// There's also a CB.000, but unfortunately that file contains an MT-32 patch
-		break;
+		return;
 	}
 
-	if (!patchFile.empty() && Common::File::exists(patchFile)) {
+	if (Common::File::exists(patchFile)) {
 		ResourceSource *psrcPatch = new PatchResourceSource(patchFile);
 		processPatch(psrcPatch, kResourceTypePatch, 0);
 	}
 }
 
-void ResourceManager::processWavePatch(ResourceId resourceId, const Common::String &name) {
+void ResourceManager::processWavePatch(ResourceId resourceId, const Common::Path &name) {
 	ResourceSource *resSrc = new WaveResourceSource(name);
 	Common::File file;
 	file.open(name);
@@ -248,7 +248,7 @@ void ResourceManager::processWavePatch(ResourceId resourceId, const Common::Stri
 	updateResource(resourceId, resSrc, 0, file.size(), name);
 	_sources.push_back(resSrc);
 
-	debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str());
+	debugC(1, kDebugLevelResMan, "Patching %s - OK", name.toString().c_str());
 }
 
 void ResourceManager::readWaveAudioPatches() {
@@ -257,10 +257,10 @@ void ResourceManager::readWaveAudioPatches() {
 	SearchMan.listMatchingMembers(files, "*.wav");
 
 	for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
-		Common::String name = (*x)->getName();
+		Common::String name = (*x)->getFileName();
 
 		if (Common::isDigit(name[0]))
-			processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name);
+			processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), (*x)->getPathInArchive());
 	}
 }
 
@@ -277,9 +277,9 @@ void ResourceManager::readAIFFAudioPatches() {
 	SearchMan.listMatchingMembers(files, "####");
 
 	for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
-		Common::String name = (*x)->getName();
+		Common::String name = (*x)->getFileName();
 
-		processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name);
+		processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), (*x)->getPathInArchive());
 	}
 }
 #endif
@@ -395,7 +395,7 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
 	Common::SeekableReadStream *fileStream = getVolumeFile(src);
 
 	if (!fileStream) {
-		warning("Failed to open file stream for %s", src->getLocationName().c_str());
+		warning("Failed to open file stream for %s", src->getLocationName().toString().c_str());
 		return SCI_ERROR_NO_RESOURCE_FILES_FOUND;
 	}
 
@@ -664,7 +664,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
 		uint32 size = file.readUint32LE();
 
 		if (file.eos() || file.err()) {
-			warning("Error while reading %s", map->getLocationName().c_str());
+			warning("Error while reading %s", map->getLocationName().toString().c_str());
 			return SCI_ERROR_RESMAP_NOT_FOUND;
 		}
 
@@ -731,8 +731,8 @@ void ResourceManager::setAudioLanguage(int language) {
 		_audioMapSCI1 = nullptr;
 	}
 
-	Common::String filename = Common::String::format("AUDIO%03d", language);
-	Common::String fullname = filename + ".MAP";
+	Common::Path filename(Common::String::format("AUDIO%03d", language));
+	Common::Path fullname = filename.append(".MAP");
 	if (!Common::File::exists(fullname)) {
 		warning("No audio map found for language %i", language);
 		return;
@@ -742,13 +742,13 @@ void ResourceManager::setAudioLanguage(int language) {
 
 	// Search for audio volumes for this language and add them to the source list
 	Common::ArchiveMemberList files;
-	SearchMan.listMatchingMembers(files, filename + ".0##");
+	SearchMan.listMatchingMembers(files, filename.append(".0##"));
 	for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
-		const Common::String name = (*x)->getName();
+		const Common::String name = (*x)->getFileName();
 		const char *dot = strrchr(name.c_str(), '.');
 		int number = atoi(dot + 1);
 
-		addSource(new AudioVolumeResourceSource(this, name, _audioMapSCI1, number));
+		addSource(new AudioVolumeResourceSource(this, (*x)->getPathInArchive(), _audioMapSCI1, number));
 	}
 
 	scanNewSources();
@@ -1154,15 +1154,11 @@ bool ResourceManager::addAudioSources() {
 	return true;
 }
 
-void ResourceManager::changeAudioDirectory(Common::String path) {
-	if (!path.empty()) {
-		path += "/";
-	}
-
-	const Common::String resAudPath = path + "RESOURCE.AUD";
+void ResourceManager::changeAudioDirectory(const Common::Path &path) {
+	const Common::Path resAudPath = path.join("RESOURCE.AUD");
 
 	if (!SearchMan.hasFile(resAudPath)) {
-		error("Could not find %s", resAudPath.c_str());
+		error("Could not find %s", resAudPath.toString().c_str());
 	}
 
 	// When a IntMapResourceSource is scanned, it will not update existing
@@ -1207,7 +1203,7 @@ void ResourceManager::changeAudioDirectory(Common::String path) {
 		}
 
 		AudioVolumeResourceSource *volSource = dynamic_cast<AudioVolumeResourceSource *>(*it);
-		if (volSource && volSource->getLocationName().contains("RESOURCE.AUD")) {
+		if (volSource && volSource->getLocationName().baseName() == "RESOURCE.AUD") {
 			delete volSource;
 			it = _sources.erase(it);
 			continue;
@@ -1219,13 +1215,13 @@ void ResourceManager::changeAudioDirectory(Common::String path) {
 	// # is used as the first pattern character to avoid matching non-audio maps
 	// like RESOURCE.MAP
 	Common::ArchiveMemberList mapFiles;
-	SearchMan.listMatchingMembers(mapFiles, path + "#*.MAP");
+	SearchMan.listMatchingMembers(mapFiles, path.join("#*.MAP"));
 
 	for (Common::ArchiveMemberList::const_iterator it = mapFiles.begin(); it != mapFiles.end(); ++it) {
 		const Common::ArchiveMemberPtr &file = *it;
 		assert(file);
 
-		const Common::String fileName = file->getName();
+		const Common::String fileName = file->getFileName();
 		const int mapNo = atoi(fileName.c_str());
 
 		// Sound effects are the same across all audio directories, so ignore
@@ -1234,7 +1230,7 @@ void ResourceManager::changeAudioDirectory(Common::String path) {
 			continue;
 		}
 
-		ResourceSource *newSource = new PatchResourceSource(path + fileName);
+		ResourceSource *newSource = new PatchResourceSource(path.appendComponent(fileName));
 		processPatch(newSource, kResourceTypeMap, mapNo);
 		Resource *mapResource = _resMap.getVal(ResourceId(kResourceTypeMap, mapNo));
 		assert(mapResource);
@@ -1246,7 +1242,7 @@ void ResourceManager::changeAudioDirectory(Common::String path) {
 	scanNewSources();
 }
 
-void ResourceManager::changeMacAudioDirectory(Common::String path) {
+void ResourceManager::changeMacAudioDirectory(const Common::Path &path_) {
 	// delete all Audio36 resources so that they can be replaced with
 	//  different patch files from the new directory.
 	for (ResourceMap::iterator it = _resMap.begin(); it != _resMap.end(); ++it) {
@@ -1271,21 +1267,22 @@ void ResourceManager::changeMacAudioDirectory(Common::String path) {
 		}
 	}
 
+	Common::Path path(path_);
 	if (path.empty()) {
 		path = "english";
 	}
-	path = "voices/" + path + "/";
+	path = Common::Path("voices").join(path);
 
 	// add all Audio36 wave patch files from language directory
 	Common::ArchiveMemberList audio36Files;
-	SearchMan.listMatchingMembers(audio36Files, path + "A???????.???");
+	SearchMan.listMatchingMembers(audio36Files, path.join("A???????.???"));
 	for (Common::ArchiveMemberList::const_iterator it = audio36Files.begin(); it != audio36Files.end(); ++it) {
 		const Common::ArchiveMemberPtr &file = *it;
 		assert(file);
 
-		const Common::String fileName = file->getName();
-		ResourceId resource36 = convertPatchNameBase36(kResourceTypeAudio36, fileName);
-		processWavePatch(resource36, path + fileName);
+		const Common::Path fileName = file->getPathInArchive();
+		ResourceId resource36 = convertPatchNameBase36(kResourceTypeAudio36, file->getFileName());
+		processWavePatch(resource36, path.join(fileName));
 	}
 }
 
diff --git a/engines/sci/resource/resource_intern.h b/engines/sci/resource/resource_intern.h
index ff5ec9ba980..0b9f3d2da78 100644
--- a/engines/sci/resource/resource_intern.h
+++ b/engines/sci/resource/resource_intern.h
@@ -48,7 +48,7 @@ enum ResSourceType {
 class ResourceSource {
 protected:
 	const ResSourceType _sourceType;
-	const Common::String _name;
+	const Common::Path _name;
 
 public:
 	bool _scanned;
@@ -56,12 +56,12 @@ public:
 	const int _volumeNumber;
 
 protected:
-	ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0, const Common::FSNode *resFile = 0);
+	ResourceSource(ResSourceType type, const Common::Path &name, int volNum = 0, const Common::FSNode *resFile = 0);
 public:
 	virtual ~ResourceSource();
 
 	ResSourceType getSourceType() const { return _sourceType; }
-	const Common::String &getLocationName() const { return _name; }
+	const Common::Path &getLocationName() const { return _name; }
 
 	// Auxiliary method, used by loadResource implementations.
 	Common::SeekableReadStream *getVolumeFile(ResourceManager *resMan, Resource *res);
@@ -91,14 +91,14 @@ public:
 
 class DirectoryResourceSource : public ResourceSource {
 public:
-	DirectoryResourceSource(const Common::String &name) : ResourceSource(kSourceDirectory, name) {}
+	DirectoryResourceSource(const Common::Path &name) : ResourceSource(kSourceDirectory, name) {}
 
 	void scanSource(ResourceManager *resMan) override;
 };
 
 class PatchResourceSource : public ResourceSource {
 public:
-	PatchResourceSource(const Common::String &name) : ResourceSource(kSourcePatch, name) {}
+	PatchResourceSource(const Common::Path &name) : ResourceSource(kSourcePatch, name) {}
 
 	void loadResource(ResourceManager *resMan, Resource *res) override;
 };
@@ -108,11 +108,11 @@ protected:
 	ResourceSource * const _associatedMap;
 
 public:
-	VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, ResSourceType type = kSourceVolume)
+	VolumeResourceSource(const Common::Path &name, ResourceSource *map, int volNum, ResSourceType type = kSourceVolume)
 		: ResourceSource(type, name, volNum), _associatedMap(map) {
 	}
 
-	VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, const Common::FSNode *resFile)
+	VolumeResourceSource(const Common::Path &name, ResourceSource *map, int volNum, const Common::FSNode *resFile)
 		: ResourceSource(kSourceVolume, name, volNum, resFile), _associatedMap(map) {
 	}
 
@@ -125,7 +125,7 @@ public:
 
 class ExtMapResourceSource : public ResourceSource {
 public:
-	ExtMapResourceSource(const Common::String &name, int volNum, const Common::FSNode *resFile = 0)
+	ExtMapResourceSource(const Common::Path &name, int volNum, const Common::FSNode *resFile = 0)
 		: ResourceSource(kSourceExtMap, name, volNum, resFile) {
 	}
 
@@ -135,7 +135,7 @@ public:
 class IntMapResourceSource : public ResourceSource {
 public:
 	uint16 _mapNumber;
-	IntMapResourceSource(const Common::String &name, int volNum, int mapNum)
+	IntMapResourceSource(const Common::Path &name, int volNum, int mapNum)
 		: ResourceSource(kSourceIntMap, name, volNum), _mapNumber(mapNum) {
 	}
 
@@ -153,7 +153,7 @@ protected:
 	Common::HashMap<uint32, CompressedTableEntry> _compressedOffsets;
 
 public:
-	AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum);
+	AudioVolumeResourceSource(ResourceManager *resMan, const Common::Path &name, ResourceSource *map, int volNum);
 
 	void loadResource(ResourceManager *resMan, Resource *res) override;
 
@@ -177,7 +177,7 @@ public:
 
 class ExtAudioMapResourceSource : public ResourceSource {
 public:
-	ExtAudioMapResourceSource(const Common::String &name, int volNum)
+	ExtAudioMapResourceSource(const Common::Path &name, int volNum)
 		: ResourceSource(kSourceExtAudioMap, name, volNum) {
 	}
 
@@ -186,7 +186,7 @@ public:
 
 class WaveResourceSource : public ResourceSource {
 public:
-	WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {}
+	WaveResourceSource(const Common::Path &name) : ResourceSource(kSourceWave, name) {}
 
 	void loadResource(ResourceManager *resMan, Resource *res) override;
 };
@@ -196,7 +196,7 @@ public:
  */
 class MacResourceForkResourceSource : public ResourceSource {
 public:
-	MacResourceForkResourceSource(const Common::String &name, int volNum);
+	MacResourceForkResourceSource(const Common::Path &name, int volNum);
 	~MacResourceForkResourceSource() override;
 
 	void scanSource(ResourceManager *resMan) override;
@@ -217,7 +217,7 @@ protected:
  */
 class ChunkResourceSource : public ResourceSource {
 public:
-	ChunkResourceSource(const Common::String &name, uint16 number);
+	ChunkResourceSource(const Common::Path &name, uint16 number);
 
 	void scanSource(ResourceManager *resMan) override;
 	void loadResource(ResourceManager *resMan, Resource *res) override;
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 88dc5ba27e4..855dfdaf6f8 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -141,7 +141,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam
 	assert(g_sci == nullptr);
 	g_sci = this;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	SearchMan.addSubDirectoryMatching(gameDataDir, "actors");	// KQ6 hi-res portraits
 	SearchMan.addSubDirectoryMatching(gameDataDir, "aud");	// resource.aud and audio files
@@ -1053,14 +1053,14 @@ void SciEngine::updateSoundMixerVolumes() {
 }
 
 void SciEngine::loadMacExecutable() {
-	Common::String filename = _resMan->getMacExecutableName();
+	Common::Path filename = _resMan->getMacExecutableName();
 	if (filename.empty())
 		return;
 
 	if (!_macExecutable.open(filename) || !_macExecutable.hasResFork()) {
 		// KQ6/Freddy require the executable to load their icon bar palettes
 		if (hasMacIconBar())
-			error("Could not load Mac resource fork '%s'", filename.c_str());
+			error("Could not load Mac resource fork '%s'", filename.toString().c_str());
 	}
 }
 
@@ -1086,8 +1086,8 @@ void SciEngine::loadMacFonts() {
 				_gfxMacFontManager = nullptr;
 			}
 		} else {
-			Common::String filename = _resMan->getMacExecutableName();
-			warning("Macintosh executable \"%s\" not found, using SCI fonts", filename.c_str());
+			Common::Path filename = _resMan->getMacExecutableName();
+			warning("Macintosh executable \"%s\" not found, using SCI fonts", filename.toString().c_str());
 		}
 		break;
 	case GID_LSL6:
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index cf202a0eb97..5f969660ced 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -150,7 +150,7 @@ void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan
 			if (fileName[i] == '\\')
 				fileName.setChar('/', i);
 		}
-		sciAudioFile->open("sciAudio/" + fileName);
+		sciAudioFile->open(Common::Path("sciAudio/" + fileName, '/'));
 
 		Audio::RewindableAudioStream *audioStream = nullptr;
 
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index f0256e1c379..c82efb483e1 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -361,12 +361,12 @@ RobotDecoder::~RobotDecoder() {
 #pragma mark RobotDecoder - Initialization
 
 void RobotDecoder::initStream(const GuiResourceId robotId) {
-	const Common::String fileName = Common::String::format("%d.rbt", robotId);
+	const Common::Path fileName(Common::String::format("%d.rbt", robotId));
 	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName);
 	_fileOffset = 0;
 
 	if (stream == nullptr) {
-		error("Unable to open robot file %s", fileName.c_str());
+		error("Unable to open robot file %s", fileName.toString().c_str());
 	}
 
 	_robotId = robotId;
@@ -374,7 +374,7 @@ void RobotDecoder::initStream(const GuiResourceId robotId) {
 	const uint16 id = stream->readUint16LE();
 	// TODO: id 0x3d for PQ:SWAT demo?
 	if (id != 0x16) {
-		error("Invalid robot file %s", fileName.c_str());
+		error("Invalid robot file %s", fileName.toString().c_str());
 	}
 
 	// Determine the robot file's endianness by examining the version field.
@@ -388,7 +388,7 @@ void RobotDecoder::initStream(const GuiResourceId robotId) {
 	_stream = new Common::SeekableReadStreamEndianWrapper(stream, bigEndian, DisposeAfterUse::YES);
 	_stream->seek(2, SEEK_SET);
 	if (_stream->readUint32BE() != MKTAG('S', 'O', 'L', 0)) {
-		error("Resource %s is not Robot type!", fileName.c_str());
+		error("Resource %s is not Robot type!", fileName.toString().c_str());
 	}
 }
 


Commit: 17f09bb48c786fedbc117639129f9ab388a50318
    https://github.com/scummvm/scummvm/commit/17f09bb48c786fedbc117639129f9ab388a50318
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SCUMM: Migrate engine to Path

Changed paths:
    engines/scumm/charset.cpp
    engines/scumm/charset.h
    engines/scumm/detection_internal.h
    engines/scumm/file.cpp
    engines/scumm/file.h
    engines/scumm/file_nes.cpp
    engines/scumm/file_nes.h
    engines/scumm/he/animation_he.cpp
    engines/scumm/he/animation_he.h
    engines/scumm/he/intern_he.h
    engines/scumm/he/logic/basketball.cpp
    engines/scumm/he/moonbase/moonbase.h
    engines/scumm/he/moonbase/moonbase_fow.cpp
    engines/scumm/he/resource_he.cpp
    engines/scumm/he/resource_he.h
    engines/scumm/he/script_v60he.cpp
    engines/scumm/he/script_v72he.cpp
    engines/scumm/he/sound_he.cpp
    engines/scumm/imuse/drivers/amiga.cpp
    engines/scumm/macgui/macgui.cpp
    engines/scumm/macgui/macgui.h
    engines/scumm/macgui/macgui_impl.cpp
    engines/scumm/macgui/macgui_impl.h
    engines/scumm/macgui/macgui_indy3.cpp
    engines/scumm/macgui/macgui_indy3.h
    engines/scumm/macgui/macgui_loom.cpp
    engines/scumm/macgui/macgui_loom.h
    engines/scumm/metaengine.cpp
    engines/scumm/players/player_he.cpp
    engines/scumm/players/player_mac.cpp
    engines/scumm/players/player_mac.h
    engines/scumm/resource.cpp
    engines/scumm/scumm.cpp
    engines/scumm/scumm.h
    engines/scumm/scumm_v7.h
    engines/scumm/smush/smush_player.cpp
    engines/scumm/sound.cpp


diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 9f90e2bee05..7f426f01dfc 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -1603,7 +1603,7 @@ void CharsetRendererPCE::setDrawCharIntern(uint16 chr) {
 }
 #endif
 
-CharsetRendererMac::CharsetRendererMac(ScummEngine *vm, const Common::String &fontFile)
+CharsetRendererMac::CharsetRendererMac(ScummEngine *vm, const Common::Path &fontFile)
 	 : CharsetRendererCommon(vm) {
 
 	// The original Macintosh interpreter didn't use the correct spacing
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index 20aa278b4b2..165e6f55239 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -299,7 +299,7 @@ protected:
 	Graphics::Surface *_glyphSurface;
 
 public:
-	CharsetRendererMac(ScummEngine *vm, const Common::String &fontFile);
+	CharsetRendererMac(ScummEngine *vm, const Common::Path &fontFile);
 	~CharsetRendererMac() override;
 
 	void setCurID(int32 id) override;
diff --git a/engines/scumm/detection_internal.h b/engines/scumm/detection_internal.h
index 4b5e10c0dfe..576e07de96c 100644
--- a/engines/scumm/detection_internal.h
+++ b/engines/scumm/detection_internal.h
@@ -652,7 +652,7 @@ static bool testGame(const GameSettings *g, const DescMap &fileMD5Map, const Com
 
 	Common::File tmp;
 	if (!tmp.open(d.node)) {
-		warning("SCUMM testGame: failed to open '%s' for read access", d.node.getPath().c_str());
+		warning("SCUMM testGame: failed to open '%s' for read access", d.node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp
index 7a0de987ed9..41c2f88f8bd 100644
--- a/engines/scumm/file.cpp
+++ b/engines/scumm/file.cpp
@@ -69,7 +69,7 @@ bool ScummFile::open(const Common::Path &filename) {
 	}
 }
 
-bool ScummFile::openSubFile(const Common::String &filename) {
+bool ScummFile::openSubFile(const Common::Path &filename) {
 	assert(_baseStream);
 
 	// Disable the XOR encryption and reset any current subfile range
@@ -99,6 +99,7 @@ bool ScummFile::openSubFile(const Common::String &filename) {
 		return false;
 	}
 
+	Common::String matchname = filename.toString('/');
 	// Scan through the files
 	for (i = 0; i < file_record_len; i += 0x28) {
 		// read a file record
@@ -116,7 +117,7 @@ bool ScummFile::openSubFile(const Common::String &filename) {
 			return false;
 		}
 
-		if (scumm_stricmp(file_name, filename.c_str()) == 0) {
+		if (scumm_stricmp(file_name, matchname.c_str()) == 0) {
 			// We got a match!
 			setSubfileRange(file_off, file_len);
 			return true;
@@ -198,7 +199,7 @@ uint32 ScummFile::read(void *dataPtr, uint32 dataSize) {
 #pragma mark -
 
 bool ScummSteamFile::open(const Common::Path &filename) {
-	if (filename.toString().equalsIgnoreCase(_indexFile.indexFileName)) {
+	if (filename.equalsIgnoreCase(_indexFile.indexFileName)) {
 		return openWithSubRange(_indexFile.executableName, _indexFile.start, _indexFile.len);
 	} else {
 		// Regular non-bundled file
@@ -206,7 +207,7 @@ bool ScummSteamFile::open(const Common::Path &filename) {
 	}
 }
 
-bool ScummSteamFile::openWithSubRange(const Common::String &filename, int32 subFileStart, int32 subFileLen) {
+bool ScummSteamFile::openWithSubRange(const Common::Path &filename, int32 subFileStart, int32 subFileLen) {
 	if (ScummFile::open(filename)) {
 		_subFileStart = subFileStart;
 		_subFileLen = subFileLen;
@@ -312,10 +313,10 @@ bool ScummDiskImage::openDisk(char num) {
 
 	if (_openedDisk != num || !_baseStream) {
 		if (num == 1) {
-			_baseStream.reset(SearchMan.createReadStreamForMember(_disk1));
+			_baseStream.reset(SearchMan.createReadStreamForMember(Common::Path(_disk1)));
 			_debugName = _disk1;
 		} else if (num == 2) {
-			_baseStream.reset(SearchMan.createReadStreamForMember(_disk2));
+			_baseStream.reset(SearchMan.createReadStreamForMember(Common::Path(_disk2)));
 			_debugName = _disk2;
 		} else {
 			error("ScummDiskImage::open(): wrong disk (%c)", num);
@@ -519,10 +520,11 @@ void ScummDiskImage::close() {
 	_debugName.clear();
 }
 
-bool ScummDiskImage::openSubFile(const Common::String &filename) {
+bool ScummDiskImage::openSubFile(const Common::Path &filename) {
 	assert(_baseStream);
 
-	const char *ext = strrchr(filename.c_str(), '.');
+	Common::String basename = filename.baseName();
+	const char *ext = strrchr(basename.c_str(), '.');
 	char resNum[3];
 	int res;
 
diff --git a/engines/scumm/file.h b/engines/scumm/file.h
index 9ae46a54819..1bbcca97f9a 100644
--- a/engines/scumm/file.h
+++ b/engines/scumm/file.h
@@ -42,7 +42,7 @@ public:
 	void setEnc(byte value) { _encbyte = value; }
 
 	virtual bool open(const Common::Path &filename) = 0;
-	virtual bool openSubFile(const Common::String &filename) = 0;
+	virtual bool openSubFile(const Common::Path &filename) = 0;
 	virtual void close();
 
 	int64 pos() const override = 0;
@@ -74,7 +74,7 @@ public:
 	explicit ScummFile(const ScummEngine *vm);
 
 	bool open(const Common::Path &filename) override;
-	bool openSubFile(const Common::String &filename) override;
+	bool openSubFile(const Common::Path &filename) override;
 
 	void clearErr() override { _myEos = false; BaseScummFile::clearErr(); }
 
@@ -119,7 +119,7 @@ public:
 	ScummDiskImage(const char *disk1, const char *disk2, GameSettings game);
 
 	bool open(const Common::Path &filename) override;
-	bool openSubFile(const Common::String &filename) override;
+	bool openSubFile(const Common::Path &filename) override;
 
 	void close() override;
 	bool eos() const override { return _stream->eos(); }
@@ -143,7 +143,7 @@ class ScummSteamFile : public ScummFile {
 private:
 	const SteamIndexFile &_indexFile;
 
-	bool openWithSubRange(const Common::String &filename, int32 subFileStart, int32 subFileLen);
+	bool openWithSubRange(const Common::Path &filename, int32 subFileStart, int32 subFileLen);
 public:
 	ScummSteamFile(const ScummEngine *vm, const SteamIndexFile &indexFile) : ScummFile(vm), _indexFile(indexFile) {}
 
diff --git a/engines/scumm/file_nes.cpp b/engines/scumm/file_nes.cpp
index c21333ebe12..8f3d212be27 100644
--- a/engines/scumm/file_nes.cpp
+++ b/engines/scumm/file_nes.cpp
@@ -1426,10 +1426,11 @@ void ScummNESFile::close() {
 	_debugName.clear();
 }
 
-bool ScummNESFile::openSubFile(const Common::String &filename) {
+bool ScummNESFile::openSubFile(const Common::Path &filename) {
 	assert(_baseStream);
 
-	const char *ext = strrchr(filename.c_str(), '.');
+	Common::String basename = filename.baseName();
+	const char *ext = strrchr(basename.c_str(), '.');
 	char resNum[3];
 	int res;
 
diff --git a/engines/scumm/file_nes.h b/engines/scumm/file_nes.h
index 10d5aa67123..e4ca9a5109d 100644
--- a/engines/scumm/file_nes.h
+++ b/engines/scumm/file_nes.h
@@ -79,7 +79,7 @@ public:
 	ScummNESFile();
 
 	bool open(const Common::Path &filename) override;
-	bool openSubFile(const Common::String &filename) override;
+	bool openSubFile(const Common::Path &filename) override;
 
 	void close() override;
 	bool eos() const override { return _stream->eos(); }
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index a60796544cc..99108baf066 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -61,12 +61,12 @@ int MoviePlayer::getImageNum() {
 	return _wizResNum;
 }
 
-int MoviePlayer::load(const Common::String &filename, int flags, int image) {
+int MoviePlayer::load(const Common::Path &filename, int flags, int image) {
 	if (_video->isVideoLoaded())
 		_video->close();
 
 	if (!_video->loadFile(filename)) {
-		warning("Failed to load video file %s", filename.c_str());
+		warning("Failed to load video file %s", filename.toString().c_str());
 		return -1;
 	}
 
@@ -75,7 +75,7 @@ int MoviePlayer::load(const Common::String &filename, int flags, int image) {
 
 	_video->start();
 
-	debug(1, "Playing video %s", filename.c_str());
+	debug(1, "Playing video %s", filename.toString().c_str());
 
 	if (flags & 2)
 		_vm->_wiz->createWizEmptyImage(image, 0, 0, _video->getWidth(), _video->getHeight());
diff --git a/engines/scumm/he/animation_he.h b/engines/scumm/he/animation_he.h
index 0167c6eb078..36229744321 100644
--- a/engines/scumm/he/animation_he.h
+++ b/engines/scumm/he/animation_he.h
@@ -27,7 +27,7 @@ class Mixer;
 }
 
 namespace Common {
-class String;
+class Path;
 }
 
 namespace Video {
@@ -44,7 +44,7 @@ public:
 	~MoviePlayer();
 
 	int getImageNum();
-	int load(const Common::String &filename, int flags, int image = 0);
+	int load(const Common::Path &filename, int flags, int image = 0);
 
 	void copyFrameToBuffer(byte *dst, int dstType, uint x, uint y, uint pitch);
 	void handleNextFrame();
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 4f2e382924c..255b58a8ac3 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -79,7 +79,7 @@ public:
 	ScummEngine_v60he(OSystem *syst, const DetectorResult &dr);
 	~ScummEngine_v60he() override;
 
-	Common::String generateFilename(const int room) const override;
+	Common::Path generateFilename(const int room) const override;
 
 	void resetScumm() override;
 
@@ -99,7 +99,7 @@ protected:
 	void decodeParseString(int a, int b) override;
 	void swapObjects(int object1, int object2);
 
-	Common::String convertFilePath(const byte *src);
+	Common::Path convertFilePath(const byte *src);
 	Common::String convertSavePath(const byte *src);
 	Common::String convertSavePathOld(const byte *src);
 
@@ -208,7 +208,7 @@ public:
 	ScummEngine_v70he(OSystem *syst, const DetectorResult &dr);
 	~ScummEngine_v70he() override;
 
-	Common::String generateFilename(const int room) const override;
+	Common::Path generateFilename(const int room) const override;
 
 	void restoreBackgroundHE(Common::Rect rect, int dirtybit = 0);
 
diff --git a/engines/scumm/he/logic/basketball.cpp b/engines/scumm/he/logic/basketball.cpp
index 6a9f18082a3..2a82281ef77 100644
--- a/engines/scumm/he/logic/basketball.cpp
+++ b/engines/scumm/he/logic/basketball.cpp
@@ -163,13 +163,13 @@ int LogicHEbasketball::op_1050(int32 *args) {
 		"Moon", "Barn"
 	};
 
-	Common::String courtFileName = Common::String::format("data/courts/%s.cof", courtNames[args[0] - 1]);
+	Common::Path courtFileName = Common::Path(Common::String::format("data/courts/%s.cof", courtNames[args[0] - 1]));
 
 	Common::File file;
 	if (!file.open(courtFileName))
-		error("Could not open file '%s'", courtFileName.c_str());
+		error("Could not open file '%s'", courtFileName.toString(Common::Path::kNativeSeparator).c_str());
 
-	debug(0, "Loading court data from '%s'", courtFileName.c_str());
+	debug(0, "Loading court data from '%s'", courtFileName.toString(Common::Path::kNativeSeparator).c_str());
 
 	// First, read in the header
 	file.readUint32LE(); // Header size (?)
diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h
index 1ddce72114d..c5748edc721 100644
--- a/engines/scumm/he/moonbase/moonbase.h
+++ b/engines/scumm/he/moonbase/moonbase.h
@@ -108,7 +108,7 @@ private:
 	int32 _fowRenderTable[32768];
 
 	Common::PEResources *_exe;
-	Common::String _fileName;
+	Common::Path _fileName;
 };
 
 } // End of namespace Scumm
diff --git a/engines/scumm/he/moonbase/moonbase_fow.cpp b/engines/scumm/he/moonbase/moonbase_fow.cpp
index 96eab50e4d8..05fcae0de37 100644
--- a/engines/scumm/he/moonbase/moonbase_fow.cpp
+++ b/engines/scumm/he/moonbase/moonbase_fow.cpp
@@ -100,7 +100,7 @@ bool Moonbase::setFOWImage(int image) {
 				_fileName = _vm->generateFilename(-3);
 
 				if (!_exe->loadFromEXE(_fileName))
-					error("Cannot open file %s", _fileName.c_str());
+					error("Cannot open file %s", _fileName.toString(Common::Path::kNativeSeparator).c_str());
 			}
 
 			Common::SeekableReadStream *stream = _exe->getResource(Common::kWinRCData, resId);
diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp
index 67367f1f8ae..123c7423dae 100644
--- a/engines/scumm/he/resource_he.cpp
+++ b/engines/scumm/he/resource_he.cpp
@@ -126,7 +126,7 @@ bool Win32ResExtractor::extractResource(int id, CachedCursor *cc) {
 		_fileName = _vm->generateFilename(-3);
 
 		if (!_exe->loadFromEXE(_fileName))
-			error("Cannot open file %s", _fileName.c_str());
+			error("Cannot open file %s", _fileName.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	Graphics::WinCursorGroup *group = Graphics::WinCursorGroup::createCursorGroup(_exe, id);
@@ -169,8 +169,9 @@ bool MacResExtractor::extractResource(int id, CachedCursor *cc) {
 	// Create the MacResManager if not created already
 	if (_resMgr == nullptr) {
 		_resMgr = new Common::MacResManager();
-		if (!_resMgr->open(_vm->generateFilename(-3)))
-			error("Cannot open file %s", _fileName.c_str());
+		_fileName = _vm->generateFilename(-3);
+		if (!_resMgr->open(_fileName))
+			error("Cannot open file %s", _fileName.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	Common::SeekableReadStream *dataStream = _resMgr->getResource('crsr', id + 1000);
diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h
index ba57468ed7e..dbc80479c52 100644
--- a/engines/scumm/he/resource_he.h
+++ b/engines/scumm/he/resource_he.h
@@ -51,7 +51,7 @@ protected:
 		int palSize;
 	};
 
-	Common::String _fileName;
+	Common::Path _fileName;
 	ScummEngine_v70he *_vm;
 
 	virtual bool extractResource(int id, CachedCursor *cc) = 0;
diff --git a/engines/scumm/he/script_v60he.cpp b/engines/scumm/he/script_v60he.cpp
index 2bd6d992bfc..41e1a696a7a 100644
--- a/engines/scumm/he/script_v60he.cpp
+++ b/engines/scumm/he/script_v60he.cpp
@@ -90,7 +90,7 @@ void ScummEngine_v60he::setupOpcodes() {
 	_opcodes[0xed].setProc(nullptr, nullptr);
 }
 
-Common::String ScummEngine_v60he::convertFilePath(const byte *src) {
+Common::Path ScummEngine_v60he::convertFilePath(const byte *src) {
 	debug(2, "convertFilePath in: '%s'", (const char *)src);
 
 	int srcSize = resStrLen(src);
@@ -136,21 +136,14 @@ Common::String ScummEngine_v60he::convertFilePath(const byte *src) {
 
 	debug(2, "convertFilePath out: '%s'", dst.c_str());
 
-	return dst;
+	return Common::Path(dst, '/');
 }
 
 Common::String ScummEngine_v60he::convertSavePath(const byte *src) {
 	debug(2, "convertSavePath in: '%s'", (const char *)src);
 
-	Common::String filePath = convertFilePath(src);
-
 	// Strip us down to only the file
-	for (int32 i = filePath.size() - 1; i >= 0; i--) {
-		if (filePath[i] == '/') {
-			filePath = Common::String(filePath.c_str() + i + 1);
-			break;
-		}
-	}
+	Common::String filePath = convertFilePath(src).baseName();
 
 	// Prepend the target name
 	filePath = _targetName + '-' + filePath;
diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp
index 5a12c423c34..f9af89c3860 100644
--- a/engines/scumm/he/script_v72he.cpp
+++ b/engines/scumm/he/script_v72he.cpp
@@ -1985,7 +1985,7 @@ void ScummEngine_v72he::o72_readINI() {
 	case SO_STRING: // string
 		writeVar(0, 0);
 		if (!strcmp((char *)option, "HE3File")) {
-			Common::String fileName = generateFilename(-3);
+			Common::String fileName = generateFilename(-3).toString('/');
 			int len = resStrLen((const byte *)fileName.c_str());
 			data = defineArray(0, kStringArray, 0, 0, 0, len);
 			memcpy(data, fileName.c_str(), len);
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 6b8dd299824..6f88c83e6d7 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -461,7 +461,7 @@ void SoundHE::setOverrideFreq(int freq) {
 
 void SoundHE::setupHEMusicFile() {
 	uint32 id, len;
-	Common::String musicFilename(_vm->generateFilename(-4));
+	Common::Path musicFilename(_vm->generateFilename(-4));
 
 	// For engine restarts
 	if (_heSpoolingMusicFile.isOpen())
@@ -487,7 +487,7 @@ void SoundHE::setupHEMusicFile() {
 					_heSpoolingMusicFile.seek(len - 8 - 4, SEEK_CUR);
 				} else {
 					_heSpoolingMusicFile.close();
-					debug(5, "setupHEMusicFile(): Invalid spooling file '%s', couldn't find SGHD tag, found %s", musicFilename.c_str(), tag2str(id));
+					debug(5, "setupHEMusicFile(): Invalid spooling file '%s', couldn't find SGHD tag, found %s", musicFilename.toString().c_str(), tag2str(id));
 					return;
 				}
 			}
@@ -504,7 +504,7 @@ void SoundHE::setupHEMusicFile() {
 						len = _heSpoolingMusicFile.readUint32BE();
 						if (id != MKTAG('S', 'G', 'E', 'N')) {
 							_heSpoolingMusicFile.close();
-							debug(5, "setupHEMusicFile(): Invalid spooling file '%s', couldn't find SGEN tag, found %s", musicFilename.c_str(), tag2str(id));
+							debug(5, "setupHEMusicFile(): Invalid spooling file '%s', couldn't find SGEN tag, found %s", musicFilename.toString().c_str(), tag2str(id));
 							return;
 						}
 					}
@@ -536,13 +536,13 @@ void SoundHE::setupHEMusicFile() {
 
 				_heMixer->setSpoolingSongsTable(_heSpoolingMusicTable, _heSpoolingMusicCount);
 			} else {
-				debug(5, "setupHEMusicFile(): Can't allocate table for spooling music file '%s'", musicFilename.c_str());
+				debug(5, "setupHEMusicFile(): Can't allocate table for spooling music file '%s'", musicFilename.toString().c_str());
 			}
 		} else {
-			debug(5, "setupHEMusicFile(): Invalid file '%s', couldn't find SONG tag, found %s", musicFilename.c_str(), tag2str(id));
+			debug(5, "setupHEMusicFile(): Invalid file '%s', couldn't find SONG tag, found %s", musicFilename.toString().c_str(), tag2str(id));
 		}
 	} else {
-		debug(5, "setupHEMusicFile(): Can't open spooling music file '%s'", musicFilename.c_str());
+		debug(5, "setupHEMusicFile(): Can't open spooling music file '%s'", musicFilename.toString().c_str());
 	}
 }
 
@@ -895,7 +895,7 @@ void SoundHE::triggerSpoolingSound(int song, int offset, int channel, int flags,
 				debug(5, "SoundHE::triggerSpoolingSound(): Starting spooling sound %d with offset %d, on channel %d with flags %d",
 					song, offset, channel, flags);
 
-				Common::String filename(_vm->generateFilename(-4));
+				Common::Path filename(_vm->generateFilename(-4));
 				int fileOffset = 0;
 				int songsize = 0;
 				uint32 id, len;
@@ -919,7 +919,7 @@ void SoundHE::triggerSpoolingSound(int song, int offset, int channel, int flags,
 					filename = _heSpoolingMusicTable[i].filename;
 
 					if (!_heSpoolingMusicFile.open(filename)) {
-						debug("SoundHE::triggerSpoolingSound(): Can't open music file '%s'", filename.c_str());
+						debug("SoundHE::triggerSpoolingSound(): Can't open music file '%s'", filename.toString().c_str());
 						if (_vm->_game.heversion < 95) {
 							_vm->VAR(_vm->VAR_ERROR_FLAG) = -1;
 						} else {
@@ -1056,7 +1056,7 @@ void SoundHE::triggerSpoolingSound(int song, int offset, int channel, int flags,
 					if (offset)
 						debug("SoundHE::triggerSpoolingSound(): Starting offsets into music files not supported with Miles currently");
 
-					_heMixer->milesStartSpoolingChannel(channel, filename.c_str(), fileOffset, flags, modifiers);
+					_heMixer->milesStartSpoolingChannel(channel, filename.toString('/').c_str(), fileOffset, flags, modifiers);
 				} else {
 					// Start the music track at a specified offset
 					if (offset) {
@@ -1510,7 +1510,7 @@ void SoundHE::playVoice(uint32 offset, uint32 length) {
 	}
 
 	ScummFile file(_vm);
-	if (!_vm->openFile(file, _sfxFilename)) {
+	if (!_vm->openFile(file, Common::Path(_sfxFilename))) {
 		warning("SoundHE::playVoice(): Could not open speech file %s", _sfxFilename.c_str());
 		return;
 	}
diff --git a/engines/scumm/imuse/drivers/amiga.cpp b/engines/scumm/imuse/drivers/amiga.cpp
index 08c3f2b8758..f335ecfb71e 100644
--- a/engines/scumm/imuse/drivers/amiga.cpp
+++ b/engines/scumm/imuse/drivers/amiga.cpp
@@ -802,7 +802,7 @@ void IMuseDriver_Amiga::loadInstrument(int program) {
 	}
 
 	for (int fileNo = 1; fileNo != -1 && !ims.isOpen(); ) {
-		if (!ims.open(Common::String::format("amiga%d.ims", fileNo))) {
+		if (!ims.open(Common::Path(Common::String::format("amiga%d.ims", fileNo)))) {
 			_missingFiles |= (1 << (fileNo - 1));
 			return;
 		}
diff --git a/engines/scumm/macgui/macgui.cpp b/engines/scumm/macgui/macgui.cpp
index ecd73be885a..1efd1342b06 100644
--- a/engines/scumm/macgui/macgui.cpp
+++ b/engines/scumm/macgui/macgui.cpp
@@ -29,7 +29,7 @@
 
 namespace Scumm {
 
-MacGui::MacGui(ScummEngine *vm, Common::String resourceFile) {
+MacGui::MacGui(ScummEngine *vm, const Common::Path &resourceFile) {
 	switch (vm->_game.id) {
 	case GID_INDY3:
 		_impl = new MacIndy3Gui(vm, resourceFile);
diff --git a/engines/scumm/macgui/macgui.h b/engines/scumm/macgui/macgui.h
index 8934bf65dc9..d64bbdad912 100644
--- a/engines/scumm/macgui/macgui.h
+++ b/engines/scumm/macgui/macgui.h
@@ -41,7 +41,7 @@ private:
 	MacGuiImpl *_impl = nullptr;
 
 public:
-	MacGui(ScummEngine *vm, Common::String resourceFile);
+	MacGui(ScummEngine *vm, const Common::Path &resourceFile);
 	~MacGui();
 
 	void initialize();
diff --git a/engines/scumm/macgui/macgui_impl.cpp b/engines/scumm/macgui/macgui_impl.cpp
index 048623b4c59..0ecc514fcd9 100644
--- a/engines/scumm/macgui/macgui_impl.cpp
+++ b/engines/scumm/macgui/macgui_impl.cpp
@@ -40,7 +40,7 @@ namespace Scumm {
 // loading, etc.
 // ===========================================================================
 
-MacGuiImpl::MacGuiImpl(ScummEngine *vm, Common::String resourceFile) : _vm(vm), _system(_vm->_system), _surface(_vm->_macScreen), _resourceFile(resourceFile) {
+MacGuiImpl::MacGuiImpl(ScummEngine *vm, const Common::Path &resourceFile) : _vm(vm), _system(_vm->_system), _surface(_vm->_macScreen), _resourceFile(resourceFile) {
 	_fonts.clear();
 
 	// kMacRomanConversionTable is a conversion table from Mac Roman
diff --git a/engines/scumm/macgui/macgui_impl.h b/engines/scumm/macgui/macgui_impl.h
index a6252a1364d..8b2a1f739a1 100644
--- a/engines/scumm/macgui/macgui_impl.h
+++ b/engines/scumm/macgui/macgui_impl.h
@@ -55,7 +55,7 @@ protected:
 	Graphics::Surface *_surface = nullptr;
 	MacGuiImpl::MacDialogWindow *_bannerWindow = nullptr;
 
-	Common::String _resourceFile;
+	Common::Path _resourceFile;
 
 	bool _menuIsActive = false;
 	bool _cursorWasVisible = false;
@@ -589,7 +589,7 @@ public:
 		void drawTextBox(Common::Rect r, const TextLine *lines, int arc = 9);
 	};
 
-	MacGuiImpl(ScummEngine *vm, Common::String resourceFile);
+	MacGuiImpl(ScummEngine *vm, const Common::Path &resourceFile);
 	virtual ~MacGuiImpl();
 
 	Graphics::MacWindowManager *_windowManager = nullptr;
diff --git a/engines/scumm/macgui/macgui_indy3.cpp b/engines/scumm/macgui/macgui_indy3.cpp
index c577ecc1b43..e67a6abfe00 100644
--- a/engines/scumm/macgui/macgui_indy3.cpp
+++ b/engines/scumm/macgui/macgui_indy3.cpp
@@ -874,7 +874,7 @@ void MacIndy3Gui::Inventory::ScrollButton::draw() {
 // the work to the individual widgets.
 // ---------------------------------------------------------------------------
 
-MacIndy3Gui::MacIndy3Gui(ScummEngine *vm, Common::String resourceFile) :
+MacIndy3Gui::MacIndy3Gui(ScummEngine *vm, const Common::Path &resourceFile) :
 	MacGuiImpl(vm, resourceFile), _visible(false) {
 
 	Common::Rect verbGuiArea(640, 112);
diff --git a/engines/scumm/macgui/macgui_indy3.h b/engines/scumm/macgui/macgui_indy3.h
index b0637cb01b2..aad097ad657 100644
--- a/engines/scumm/macgui/macgui_indy3.h
+++ b/engines/scumm/macgui/macgui_indy3.h
@@ -39,7 +39,7 @@ public:
 		kScrollDown
 	};
 
-	MacIndy3Gui(ScummEngine *vm, Common::String resourceFile);
+	MacIndy3Gui(ScummEngine *vm, const Common::Path &resourceFile);
 	~MacIndy3Gui();
 
 	const Common::String name() const { return "Indy"; }
diff --git a/engines/scumm/macgui/macgui_loom.cpp b/engines/scumm/macgui/macgui_loom.cpp
index 382f6b9b8ac..1c92ce0e793 100644
--- a/engines/scumm/macgui/macgui_loom.cpp
+++ b/engines/scumm/macgui/macgui_loom.cpp
@@ -44,7 +44,7 @@ namespace Scumm {
 // The Mac Loom GUI. This one is pretty simple.
 // ===========================================================================
 
-MacLoomGui::MacLoomGui(ScummEngine *vm, Common::String resourceFile) : MacGuiImpl(vm, resourceFile) {
+MacLoomGui::MacLoomGui(ScummEngine *vm, const Common::Path &resourceFile) : MacGuiImpl(vm, resourceFile) {
 	// The practice box can be moved, but this is its default position on
 	// a large screen, and it's not saved.
 
diff --git a/engines/scumm/macgui/macgui_loom.h b/engines/scumm/macgui/macgui_loom.h
index 683a58f2e18..e68394239f8 100644
--- a/engines/scumm/macgui/macgui_loom.h
+++ b/engines/scumm/macgui/macgui_loom.h
@@ -32,7 +32,7 @@ class MacGuiImpl;
 
 class MacLoomGui : public MacGuiImpl {
 public:
-	MacLoomGui(ScummEngine *vm, Common::String resourceFile);
+	MacLoomGui(ScummEngine *vm, const Common::Path &resourceFile);
 	~MacLoomGui();
 
 	const Common::String name() const { return "Loom"; }
diff --git a/engines/scumm/metaengine.cpp b/engines/scumm/metaengine.cpp
index 4581a635654..e0a89446ff2 100644
--- a/engines/scumm/metaengine.cpp
+++ b/engines/scumm/metaengine.cpp
@@ -47,7 +47,7 @@
 
 namespace Scumm {
 
-Common::String ScummEngine::generateFilename(const int room) const {
+Common::Path ScummEngine::generateFilename(const int room) const {
 	const int diskNumber = (room > 0) ? _res->_types[rtRoom][room]._roomno : 0;
 	Common::String result;
 
@@ -78,10 +78,10 @@ Common::String ScummEngine::generateFilename(const int room) const {
 		}
 	}
 
-	return result;
+	return Common::Path(result, Common::Path::kNoSeparator);
 }
 
-Common::String ScummEngine_v60he::generateFilename(const int room) const {
+Common::Path ScummEngine_v60he::generateFilename(const int room) const {
 	Common::String result;
 	char id = 0;
 
@@ -117,10 +117,10 @@ Common::String ScummEngine_v60he::generateFilename(const int room) const {
 		return ScummEngine::generateFilename(room);
 	}
 
-	return result;
+	return Common::Path(result, Common::Path::kNoSeparator);
 }
 
-Common::String ScummEngine_v70he::generateFilename(const int room) const {
+Common::Path ScummEngine_v70he::generateFilename(const int room) const {
 	Common::String result;
 	char id = 0;
 
@@ -194,7 +194,7 @@ Common::String ScummEngine_v70he::generateFilename(const int room) const {
 		return ScummEngine_v60he::generateFilename(room);
 	}
 
-	return result;
+	return Common::Path(result, Common::Path::kNoSeparator);
 }
 
 bool ScummEngine::isMacM68kIMuse() const {
@@ -271,7 +271,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) {
 
 	// Fetch the list of files in the current directory.
 	Common::FSList fslist;
-	Common::FSNode dir(ConfMan.get("path"));
+	Common::FSNode dir(ConfMan.getPath("path"));
 	if (!dir.isDirectory())
 		return Common::kPathNotDirectory;
 	if (!dir.getChildren(fslist, Common::FSNode::kListAll))
diff --git a/engines/scumm/players/player_he.cpp b/engines/scumm/players/player_he.cpp
index 3f7d723753c..9acf7eef4c6 100644
--- a/engines/scumm/players/player_he.cpp
+++ b/engines/scumm/players/player_he.cpp
@@ -158,7 +158,7 @@ void Player_HE::loadAdLibBank() {
 
 	drvName += "drv";
 
-	if (!file.open(drvName))
+	if (!file.open(Common::Path(drvName)))
 		error("Player_HE::loadAdLibBank(): could not open %s", drvName.c_str());
 
 	uint32 size = (uint32)file.size();
diff --git a/engines/scumm/players/player_mac.cpp b/engines/scumm/players/player_mac.cpp
index c1d6cf48620..50f6288df25 100644
--- a/engines/scumm/players/player_mac.cpp
+++ b/engines/scumm/players/player_mac.cpp
@@ -40,7 +40,7 @@ Player_Mac::Player_Mac(ScummEngine *scumm, Audio::Mixer *mixer, int numberOfChan
 	assert(mixer);
 }
 
-void Player_Mac::init(const Common::String &instrumentFile) {
+void Player_Mac::init(const Common::Path &instrumentFile) {
 	_instrumentFile = instrumentFile;
 	_channel = new Player_Mac::Channel[_numberOfChannels];
 
diff --git a/engines/scumm/players/player_mac.h b/engines/scumm/players/player_mac.h
index 0e34ef850fc..da7e2ae0eff 100644
--- a/engines/scumm/players/player_mac.h
+++ b/engines/scumm/players/player_mac.h
@@ -45,7 +45,7 @@ public:
 	Player_Mac(ScummEngine *scumm, Audio::Mixer *mixer, int numberOfChannels, int channelMask, bool fadeNoteEnds);
 	~Player_Mac() override;
 
-	void init(const Common::String &instrumentFile);
+	void init(const Common::Path &instrumentFile);
 
 	// MusicEngine API
 	void setMusicVolume(int vol) override;
@@ -121,7 +121,7 @@ protected:
 	friend void syncWithSerializer(Common::Serializer &, Channel &);
 
 	ScummEngine *const _vm;
-	Common::String _instrumentFile;
+	Common::Path _instrumentFile;
 	Channel *_channel;
 
 	uint32 durationToSamples(uint16 duration);
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index fbe08d74d1a..bfabde42494 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -100,7 +100,7 @@ void ScummEngine::openRoom(const int room) {
 			return;
 		}
 
-		Common::String filename(generateFilename(room));
+		Common::Path filename(generateFilename(room));
 
 		// Determine the encryption, if any.
 		if (_game.features & GF_USE_KEY) {
@@ -129,10 +129,10 @@ void ScummEngine::openRoom(const int room) {
 			if (_fileOffset != 8)
 				return;
 
-			error("Room %d not in %s", room, filename.c_str());
+			error("Room %d not in %s", room, filename.toString().c_str());
 			return;
 		}
-		askForDisk(filename.c_str(), diskNumber);
+		askForDisk(filename, diskNumber);
 	}
 
 	do {
@@ -182,7 +182,7 @@ void ScummEngine::readRoomsOffsets() {
 	}
 }
 
-bool ScummEngine::openFile(BaseScummFile &file, const Common::String &filename, bool resourceFile) {
+bool ScummEngine::openFile(BaseScummFile &file, const Common::Path &filename, bool resourceFile) {
 	bool result = false;
 
 	if (!_containerFile.empty()) {
@@ -201,8 +201,8 @@ bool ScummEngine::openFile(BaseScummFile &file, const Common::String &filename,
 	return result;
 }
 
-bool ScummEngine::openResourceFile(const Common::String &filename, byte encByte) {
-	debugC(DEBUG_GENERAL, "openResourceFile(%s)", filename.c_str());
+bool ScummEngine::openResourceFile(const Common::Path &filename, byte encByte) {
+	debugC(DEBUG_GENERAL, "openResourceFile(%s)", filename.toString().c_str());
 
 	if (openFile(*_fileHandle, filename, true)) {
 		_fileHandle->setEnc(encByte);
@@ -211,7 +211,7 @@ bool ScummEngine::openResourceFile(const Common::String &filename, byte encByte)
 	return false;
 }
 
-void ScummEngine::askForDisk(const char *filename, int disknum) {
+void ScummEngine::askForDisk(const Common::Path &filename, int disknum) {
 	char buf[128];
 
 	if (_game.version == 8) {
@@ -221,21 +221,22 @@ void ScummEngine::askForDisk(const char *filename, int disknum) {
 		_imuseDigital->stopAllSounds();
 
 #ifdef MACOSX
-		Common::sprintf_s(buf, "Cannot find file: '%s'\nPlease insert disc %d.\nPress OK to retry, Quit to exit", filename, disknum);
+		Common::sprintf_s(buf, "Cannot find file: '%s'\nPlease insert disc %d.\nPress OK to retry, Quit to exit", filename.toString(Common::Path::kNativeSeparator).c_str(), disknum);
 #else
-		Common::sprintf_s(buf, "Cannot find file: '%s'\nInsert disc %d into drive %s\nPress OK to retry, Quit to exit", filename, disknum, ConfMan.get("path").c_str());
+		Common::sprintf_s(buf, "Cannot find file: '%s'\nInsert disc %d into drive %s\nPress OK to retry, Quit to exit", filename.toString(Common::Path::kNativeSeparator).c_str(), disknum,
+				ConfMan.getPath("path").toString(Common::Path::kNativeSeparator).c_str());
 #endif
 
 		result = displayMessage("Quit", "%s", buf);
 		if (!result) {
-			error("Cannot find file: '%s'", filename);
+			error("Cannot find file: '%s'", filename.toString(Common::Path::kNativeSeparator).c_str());
 		}
 #endif
 	} else {
-		Common::sprintf_s(buf, "Cannot find file: '%s'", filename);
+		Common::sprintf_s(buf, "Cannot find file: '%s'", filename.toString(Common::Path::kNativeSeparator).c_str());
 		InfoDialog dialog(this, Common::U32String(buf));
 		runDialog(dialog);
-		error("Cannot find file: '%s'", filename);
+		error("Cannot find file: '%s'", filename.toString(Common::Path::kNativeSeparator).c_str());
 	}
 }
 
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 92175b9bded..35246f0d02a 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -911,7 +911,7 @@ ScummEngine_v8::~ScummEngine_v8() {
 
 Common::Error ScummEngine::init() {
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	for (uint i = 0; ruScummPatcherTable[i].patcherName; i++) {
 		if (ruScummPatcherTable[i].gameid == _game.id && (_game.variant == nullptr || strcmp(_game.variant, ruScummPatcherTable[i].variant) == 0)) {
@@ -960,7 +960,7 @@ Common::Error ScummEngine::init() {
 
 #ifdef ENABLE_SCUMM_7_8
 #ifdef MACOSX
-	if (_game.version == 8 && !memcmp(gameDataDir.getPath().c_str(), "/Volumes/MONKEY3_", 17)) {
+	if (_game.version == 8 && !memcmp(gameDataDir.getPath().toString('/').c_str(), "/Volumes/MONKEY3_", 17)) {
 		// Special case for COMI on macOS. The mount points on macOS depend
 		// on the volume name. Hence if playing from CD, we'd get a problem.
 		// So if loading of a resource file fails, we fall back to the (fixed)
@@ -1107,7 +1107,7 @@ Common::Error ScummEngine::init() {
 			// Test which file name to use
 			_filenamePattern.genMethod = kGenDiskNum;
 			if (!_fileHandle->open(_containerFile))
-				error("Couldn't open container file '%s'", _containerFile.c_str());
+				error("Couldn't open container file '%s'", _containerFile.toString(Common::Path::kNativeSeparator).c_str());
 
 			if ((_filenamePattern.pattern = p1) && _fileHandle->openSubFile(generateFilename(0))) {
 				// Found regular version
@@ -1115,7 +1115,7 @@ Common::Error ScummEngine::init() {
 				// Found demo
 				_game.features |= GF_DEMO;
 			} else
-				error("Couldn't find known subfile inside container file '%s'", _containerFile.c_str());
+				error("Couldn't find known subfile inside container file '%s'", _containerFile.toString(Common::Path::kNativeSeparator).c_str());
 
 			_fileHandle->close();
 		} else {
@@ -1146,7 +1146,7 @@ Common::Error ScummEngine::init() {
 	// Load it earlier so _useCJKMode variable could be set
 	loadCJKFont();
 
-	Common::String macResourceFile;
+	Common::Path macResourceFile;
 
 	if (_game.platform == Common::kPlatformMacintosh) {
 		Common::MacResManager resource;
@@ -1232,10 +1232,10 @@ Common::Error ScummEngine::init() {
 
 		if (!macResourceFile.empty()) {
 			if (!resource.open(macResourceFile))
-				return Common::Error(Common::kReadingFailed, Common::U32String::format(_("Could not open Macintosh resource file %s"), macResourceFile.c_str()));
+				return Common::Error(Common::kReadingFailed, Common::U32String::format(_("Could not open Macintosh resource file %s"), macResourceFile.toString().c_str()));
 
 			if (!resource.hasResFork())
-				return Common::Error(Common::kReadingFailed, Common::U32String::format(_("Could not find resource fork in Macintosh resource file %s"), macResourceFile.c_str()));
+				return Common::Error(Common::kReadingFailed, Common::U32String::format(_("Could not find resource fork in Macintosh resource file %s"), macResourceFile.toString().c_str()));
 
 			resource.close();
 		}
@@ -1353,7 +1353,7 @@ Common::Error ScummEngine::init() {
 	return Common::kNoError;
 }
 
-void ScummEngine::setupScumm(const Common::String &macResourceFile) {
+void ScummEngine::setupScumm(const Common::Path &macResourceFile) {
 	// TODO: This may be the wrong place for it
 	// Enhancements used to be all or nothing, but now there are different
 	// types of them.
@@ -1365,8 +1365,8 @@ void ScummEngine::setupScumm(const Common::String &macResourceFile) {
 		ConfMan.flushToDisk();
 	}
 
-	Common::String macInstrumentFile;
-	Common::String macFontFile;
+	Common::Path macInstrumentFile;
+	Common::Path macFontFile;
 
 	if (_game.platform == Common::kPlatformMacintosh) {
 		if (_game.id == GID_INDY3) {
@@ -1544,7 +1544,7 @@ void ScummEngine::setupScumm(const Common::String &macResourceFile) {
 }
 
 #ifdef ENABLE_SCUMM_7_8
-void ScummEngine_v7::setupScumm(const Common::String &macResourceFile) {
+void ScummEngine_v7::setupScumm(const Common::Path &macResourceFile) {
 
 	// The object line toggle is always synchronized from the main game to
 	// our internal Game Options; at startup we do the opposite, since an user
@@ -1620,7 +1620,7 @@ void ScummEngine_v7::setupScumm(const Common::String &macResourceFile) {
 }
 #endif
 
-void ScummEngine::setupCharsetRenderer(const Common::String &macFontFile) {
+void ScummEngine::setupCharsetRenderer(const Common::Path &macFontFile) {
 	if (_game.version <= 2) {
 		if (_game.platform == Common::kPlatformNES)
 			_charset = new CharsetRendererNES(this);
@@ -2014,7 +2014,7 @@ void ScummEngine_v100he::resetScumm() {
 }
 #endif
 
-void ScummEngine::setupMusic(int midi, const Common::String &macInstrumentFile) {
+void ScummEngine::setupMusic(int midi, const Common::Path &macInstrumentFile) {
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(midi);
 	_native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
 
@@ -2053,21 +2053,23 @@ void ScummEngine::setupMusic(int midi, const Common::String &macInstrumentFile)
 
 	if ((_game.id == GID_MONKEY_EGA || (_game.id == GID_LOOM && _game.version == 3))
 	   &&  (_game.platform == Common::kPlatformDOS) && _sound->_musicType == MDT_MIDI) {
-		Common::String fileName;
+		Common::Path fileName;
 		bool missingFile = false;
 		if (_game.id == GID_LOOM && !(_game.features & GF_DEMO)) {
 			Common::File f;
+			char buf[2] = { 0 };
 			for (char c = '2'; c <= '5'; c++) {
 				fileName = "8";
-				fileName += c;
-				fileName += ".LFL";
+				buf[0] = c;
+				fileName.appendInPlace(buf);
+				fileName.appendInPlace(".LFL");
 				if (!Common::File::exists(fileName)) {
 					missingFile = true;
 					break;
 				}
 			}
 		} else if (_game.id == GID_MONKEY_EGA) {
-			fileName = "DISK09.LEC";
+			fileName.set("DISK09.LEC");
 			if (!Common::File::exists(fileName)) {
 				missingFile = true;
 			}
@@ -2077,7 +2079,7 @@ void ScummEngine::setupMusic(int midi, const Common::String &macInstrumentFile)
 			GUI::MessageDialog dialog(
 				Common::U32String::format(
 					_("Native MIDI support requires the Roland Upgrade from LucasArts,\n"
-					"but %s is missing. Using AdLib instead."), fileName.c_str()),
+					"but %s is missing. Using AdLib instead."), fileName.toString(Common::Path::kNativeSeparator).c_str()),
 				_("OK"));
 			dialog.runModal();
 			_sound->_musicType = MDT_ADLIB;
@@ -3753,7 +3755,7 @@ void ScummEngine_v90he::runBootscript() {
 #endif
 
 bool ScummEngine::startManiac() {
-	Common::String currentPath = ConfMan.get("path");
+	Common::Path currentPath = ConfMan.getPath("path");
 	Common::String maniacTarget;
 
 	if (!ConfMan.hasKey("easter_egg")) {
@@ -3762,15 +3764,15 @@ bool ScummEngine::startManiac() {
 		Common::ConfigManager::DomainMap::iterator iter = ConfMan.beginGameDomains();
 		for (; iter != ConfMan.endGameDomains(); ++iter) {
 			Common::ConfigManager::Domain &dom = iter->_value;
-			Common::String path = dom.getVal("path");
+			Common::Path path = Common::Path::fromConfig(dom.getVal("path"));
 
-			if (path.hasPrefix(currentPath)) {
-				path.erase(0, currentPath.size());
+			if (path.isRelativeTo(currentPath)) {
+				path = path.relativeTo(currentPath);
 				// Do a case-insensitive non-path-mode match of the remainder.
 				// While strictly speaking it's too broad, this matchString
 				// ignores the presence or absence of trailing path separators
 				// in either currentPath or path.
-				if (path.matchString("*maniac*", true, nullptr)) {
+				if (path.toString('/').matchString("*maniac*", true, nullptr)) {
 					maniacTarget = iter->_key;
 					break;
 				}
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 051c98accbf..826ebec9047 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -596,20 +596,20 @@ public:
 	void pauseEngineIntern(bool pause) override;
 
 protected:
-	virtual void setupScumm(const Common::String &macResourceFile);
+	virtual void setupScumm(const Common::Path &macResourceFile);
 	virtual void resetScumm();
 
 	virtual void setupScummVars();
 	virtual void resetScummVars();
 	void setVideoModeVarToCurrentConfig();
 
-	void setupCharsetRenderer(const Common::String &macFontFile);
+	void setupCharsetRenderer(const Common::Path &macFontFile);
 	void setupCostumeRenderer();
 
 	virtual void loadLanguageBundle();
 	void loadCJKFont();
 	void loadKorFont();
-	void setupMusic(int midi, const Common::String &macInstrumentFile);
+	void setupMusic(int midi, const Common::Path &macInstrumentFile);
 	void setTalkSpeed(int talkspeed);
 	int getTalkSpeed();
 
@@ -884,7 +884,7 @@ public:
 
 	FilenamePattern _filenamePattern;
 
-	virtual Common::String generateFilename(const int room) const;
+	virtual Common::Path generateFilename(const int room) const;
 
 protected:
 	Common::KeyState _keyPressed;
@@ -1058,10 +1058,10 @@ protected:
 	uint32 _fileOffset = 0;
 public:
 	/** The name of the (macintosh/rescumm style) container file, if any. */
-	Common::String _containerFile;
-	Common::String _macCursorFile;
+	Common::Path _containerFile;
+	Common::Path _macCursorFile;
 
-	bool openFile(BaseScummFile &file, const Common::String &filename, bool resourceFile = false);
+	bool openFile(BaseScummFile &file, const Common::Path &filename, bool resourceFile = false);
 
 	/** Is this game a Mac m68k v5 game with iMuse? */
 	bool isMacM68kIMuse() const;
@@ -1077,8 +1077,8 @@ protected:
 	void closeRoom();
 	void deleteRoomOffsets();
 	virtual void readRoomsOffsets();
-	void askForDisk(const char *filename, int disknum);	// TODO: Use Common::String
-	bool openResourceFile(const Common::String &filename, byte encByte);	// TODO: Use Common::String
+	void askForDisk(const Common::Path &filename, int disknum);
+	bool openResourceFile(const Common::Path &filename, byte encByte);
 
 	void loadPtrToResource(ResType type, ResId idx, const byte *ptr);
 	virtual int readResTypeList(ResType type);
diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h
index 58f13c0e7fa..403f24b79d6 100644
--- a/engines/scumm/scumm_v7.h
+++ b/engines/scumm/scumm_v7.h
@@ -112,7 +112,7 @@ protected:
 	void processInput() override;
 	void processKeyboard(Common::KeyState lastKeyHit) override;
 
-	void setupScumm(const Common::String &macResourceFile) override;
+	void setupScumm(const Common::Path &macResourceFile) override;
 	void resetScumm() override;
 
 	void setupScummVars() override;
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index 15b1279f576..211c6801f23 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -1020,7 +1020,7 @@ void SmushPlayer::parseNextFrame() {
 			delete _base;
 
 			ScummFile *tmp = new ScummFile(_vm);
-			if (!g_scumm->openFile(*tmp, _seekFile))
+			if (!g_scumm->openFile(*tmp, Common::Path(_seekFile)))
 				error("SmushPlayer: Unable to open file %s", _seekFile.c_str());
 			_base = tmp;
 			_base->readUint32BE();
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index d1b153c25f7..8953cf93865 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -798,7 +798,7 @@ void Sound::startTalkSound(uint32 offset, uint32 length, int mode, Audio::SoundH
 			if (!file)
 				error("startTalkSound: Out of memory");
 
-			if (!_vm->openFile(*file, _sfxFilename)) {
+			if (!_vm->openFile(*file, Common::Path(_sfxFilename))) {
 				warning("startTalkSound: could not open sfx file %s", _sfxFilename.c_str());
 				return;
 			}
@@ -915,7 +915,7 @@ void Sound::startTalkSound(uint32 offset, uint32 length, int mode, Audio::SoundH
 		if (!file)
 			error("startTalkSound: Out of memory");
 
-		if (!_vm->openFile(*file, _sfxFilename)) {
+		if (!_vm->openFile(*file, Common::Path(_sfxFilename))) {
 			warning("startTalkSound: could not open sfx file %s", _sfxFilename.c_str());
 			return;
 		}
@@ -1316,7 +1316,7 @@ void Sound::setupSfxFile() {
 	 * same directory */
 
 	Common::String basename[2];
-	Common::String tmp;
+	Common::Path tmp;
 
 	const char *ptr = strchr(_vm->_filenamePattern.pattern, '.');
 	if (ptr) {
@@ -1331,11 +1331,12 @@ void Sound::setupSfxFile() {
 		if ((_vm->_game.heversion <= 62 && _vm->_game.platform == Common::kPlatformMacintosh) || (_vm->_game.heversion >= 70)) {
 			tmp = _vm->generateFilename(-2);
 		} else {
-			tmp = basename[0] + "tlk";
+			tmp = basename[0];
+			tmp.appendInPlace("tlk");
 		}
 
-		if (file.open(tmp))
-			_sfxFilename = tmp;
+		if (file.open(Common::Path(tmp)))
+			_sfxFilename = tmp.toString('/');
 
 		if (_vm->_game.heversion <= 74)
 			_sfxFileEncByte = 0x69;
@@ -1344,10 +1345,11 @@ void Sound::setupSfxFile() {
 	} else {
 		for (uint j = 0; j < 2 && !file.isOpen(); ++j) {
 			for (int i = 0; extensions[i].ext; ++i) {
-				tmp = basename[j] + extensions[i].ext;
+				tmp = basename[j];
+				tmp.appendInPlace(extensions[i].ext);
 				if (_vm->openFile(file, tmp)) {
 					_soundMode = extensions[i].mode;
-					_sfxFilename = tmp;
+					_sfxFilename = tmp.toString('/');
 					break;
 				}
 			}


Commit: ff6f58a8b6156048b198760bce17ff84d7b1edfd
    https://github.com/scummvm/scummvm/commit/ff6f58a8b6156048b198760bce17ff84d7b1edfd
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SHERLOCK: Migrate engine to Path

Changed paths:
    engines/sherlock/animation.cpp
    engines/sherlock/animation.h
    engines/sherlock/debugger.cpp
    engines/sherlock/debugger.h
    engines/sherlock/events.cpp
    engines/sherlock/events.h
    engines/sherlock/fonts.cpp
    engines/sherlock/image_file.cpp
    engines/sherlock/image_file.h
    engines/sherlock/inventory.cpp
    engines/sherlock/music.cpp
    engines/sherlock/people.h
    engines/sherlock/resources.cpp
    engines/sherlock/resources.h
    engines/sherlock/scalpel/scalpel.cpp
    engines/sherlock/scalpel/scalpel.h
    engines/sherlock/scalpel/scalpel_people.cpp
    engines/sherlock/scalpel/scalpel_scene.cpp
    engines/sherlock/scalpel/scalpel_scene.h
    engines/sherlock/scalpel/scalpel_talk.cpp
    engines/sherlock/scalpel/scalpel_talk.h
    engines/sherlock/scalpel/scalpel_user_interface.cpp
    engines/sherlock/scalpel/tsage/resources.cpp
    engines/sherlock/scalpel/tsage/resources.h
    engines/sherlock/scene.cpp
    engines/sherlock/scene.h
    engines/sherlock/sound.cpp
    engines/sherlock/sound.h
    engines/sherlock/talk.cpp
    engines/sherlock/talk.h
    engines/sherlock/tattoo/tattoo.cpp
    engines/sherlock/tattoo/tattoo_map.cpp
    engines/sherlock/tattoo/tattoo_people.cpp
    engines/sherlock/tattoo/tattoo_scene.cpp
    engines/sherlock/tattoo/tattoo_scene.h
    engines/sherlock/tattoo/tattoo_talk.cpp
    engines/sherlock/tattoo/tattoo_talk.h
    engines/sherlock/tattoo/tattoo_user_interface.cpp


diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp
index 0df6fe9f136..7fe9bcdd874 100644
--- a/engines/sherlock/animation.cpp
+++ b/engines/sherlock/animation.cpp
@@ -33,7 +33,7 @@ static const int NO_FRAMES = FRAMES_END;
 Animation::Animation(SherlockEngine *vm) : _vm(vm) {
 }
 
-bool Animation::play(const Common::String &filename, bool intro, int minDelay, int fade,
+bool Animation::play(const Common::Path &filename, bool intro, int minDelay, int fade,
 		bool setPalette, int speed) {
 	Events &events = *_vm->_events;
 	Screen &screen = *_vm->_screen;
@@ -44,7 +44,8 @@ bool Animation::play(const Common::String &filename, bool intro, int minDelay, i
 	const int *soundFrames = checkForSoundFrames(filename, intro);
 
 	// Add on the VDX extension
-	Common::String vdxName = filename + ".vdx";
+	Common::Path vdxName(filename);
+	vdxName.appendInPlace(".vdx");
 
 	// Load the animation
 	Common::SeekableReadStream *stream;
@@ -56,7 +57,8 @@ bool Animation::play(const Common::String &filename, bool intro, int minDelay, i
 		stream = _vm->_res->load(vdxName, "epilogue.lib");
 
 	// Load initial image
-	Common::String vdaName = filename + ".vda";
+	Common::Path vdaName(filename);
+	vdaName.appendInPlace(".vda");
 	ImageFile images(vdaName, true, true);
 
 	events.wait(minDelay);
@@ -105,18 +107,18 @@ bool Animation::play(const Common::String &filename, bool intro, int minDelay, i
 				++soundNumber;
 				++soundFrames;
 
-				Common::String sampleFilename;
+				Common::Path sampleFilename;
 
 				if (!intro) {
 					// regular animation, append 1-digit number
-					sampleFilename = Common::String::format("%s%01d", filename.c_str(), soundNumber);
+					sampleFilename = filename.append(Common::String::format("%01d", soundNumber));
 				} else {
 					// intro animation, append 2-digit number
-					sampleFilename = Common::String::format("%s%02d", filename.c_str(), soundNumber);
+					sampleFilename = filename.append(Common::String::format("%02d", soundNumber));
 				}
 
 				if (sound._voices)
-					sound.playSound(sampleFilename, WAIT_RETURN_IMMEDIATELY, 100, _soundLibraryFilename.c_str());
+					sound.playSound(sampleFilename, WAIT_RETURN_IMMEDIATELY, 100, _soundLibraryFilename);
 			}
 
 			events.wait(speed * 3);
@@ -142,7 +144,7 @@ bool Animation::play(const Common::String &filename, bool intro, int minDelay, i
 	return !skipped && !_vm->shouldQuit();
 }
 
-bool Animation::play3DO(const Common::String &filename, bool intro, int minDelay, bool fadeFromGrey,
+bool Animation::play3DO(const Common::Path &filename, bool intro, int minDelay, bool fadeFromGrey,
 		int speed) {
 	Events &events = *_vm->_events;
 	Screen &screen = *_vm->_screen;
@@ -159,17 +161,21 @@ bool Animation::play3DO(const Common::String &filename, bool intro, int minDelay
 	const int *soundFrames = checkForSoundFrames(filename, intro);
 
 	// Add the VDX extension
-	Common::String indexName = "prologue/" + filename + ".3dx";
+	Common::Path indexName("prologue/");
+	indexName.appendInPlace(filename);
+	indexName.appendInPlace(".3dx");
 
 	// Load the animation
 	Common::File indexStream;
 	if (!indexStream.open(indexName)) {
-		warning("unable to open %s\n", indexName.c_str());
+		warning("unable to open %s\n", indexName.toString().c_str());
 		return false;
 	}
 
 	// Load initial image
-	Common::String graphicsName = "prologue/" + filename + ".3da";
+	Common::Path graphicsName("prologue/");
+	graphicsName.appendInPlace(filename);
+	graphicsName.appendInPlace(".3da");
 	ImageFile3DO images(graphicsName, kImageFile3DOType_Animation);
 
 	events.wait(minDelay);
@@ -234,10 +240,10 @@ bool Animation::play3DO(const Common::String &filename, bool intro, int minDelay
 				++soundNumber;
 				++soundFrames;
 
-				Common::String sampleFilename;
-
 				// append 1-digit number
-				sampleFilename = Common::String::format("prologue/sounds/%s%01d", filename.c_str(), soundNumber);
+				Common::Path sampleFilename("prologue/sounds/");
+				sampleFilename.appendInPlace(filename);
+				sampleFilename.appendInPlace(Common::String::format("%01d", soundNumber));
 
 				if (sound._voices)
 					sound.playSound(sampleFilename, WAIT_RETURN_IMMEDIATELY, 100); // no sound library
@@ -294,7 +300,7 @@ void Animation::setTitleFrames(const int *frames, int count, int maxFrames) {
 	}
 }
 
-const int *Animation::checkForSoundFrames(const Common::String &filename, bool intro) {
+const int *Animation::checkForSoundFrames(const Common::Path &filename, bool intro) {
 	const int *frames = &NO_FRAMES;
 
 	if (!intro) {
diff --git a/engines/sherlock/animation.h b/engines/sherlock/animation.h
index 6e20d73ade7..4b1a0c4afbc 100644
--- a/engines/sherlock/animation.h
+++ b/engines/sherlock/animation.h
@@ -23,7 +23,7 @@
 #define SHERLOCK_ANIMATION_H
 
 #include "common/scummsys.h"
-#include "common/str.h"
+#include "common/path.h"
 #include "common/array.h"
 
 namespace Sherlock {
@@ -44,10 +44,10 @@ private:
 	/**
 	 * Checks for whether an animation is being played that has associated sound
 	 */
-	const int *checkForSoundFrames(const Common::String &filename, bool intro);
+	const int *checkForSoundFrames(const Common::Path &filename, bool intro);
 public:
-	Common::String _soundLibraryFilename;
-	Common::String _gfxLibraryFilename;
+	Common::Path _soundLibraryFilename;
+	Common::Path _gfxLibraryFilename;
 
 public:
 	Animation(SherlockEngine *vm);
@@ -75,9 +75,9 @@ public:
 	/**
 	 * Play a full-screen animation
 	 */
-	bool play(const Common::String &filename, bool intro, int minDelay, int fade, bool setPalette, int speed);
+	bool play(const Common::Path &filename, bool intro, int minDelay, int fade, bool setPalette, int speed);
 
-	bool play3DO(const Common::String &filename, bool intro, int minDelay, bool fadeFromGrey, int speed);
+	bool play3DO(const Common::Path &filename, bool intro, int minDelay, bool fadeFromGrey, int speed);
 };
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/debugger.cpp b/engines/sherlock/debugger.cpp
index 79ec9466016..24572a17012 100644
--- a/engines/sherlock/debugger.cpp
+++ b/engines/sherlock/debugger.cpp
@@ -118,7 +118,7 @@ bool Debugger::cmdListFiles(int argc, const char **argv) {
 		return true;
 	}
 	Common::StringArray files;
-	_vm->_res->getResourceNames(Common::String(argv[1]), files);
+	_vm->_res->getResourceNames(Common::Path(argv[1]), files);
 	debugPrintColumns(files);
 	return true;
 }
diff --git a/engines/sherlock/debugger.h b/engines/sherlock/debugger.h
index c0472fb3358..ffe732f6254 100644
--- a/engines/sherlock/debugger.h
+++ b/engines/sherlock/debugger.h
@@ -23,6 +23,7 @@
 #define SHERLOCK_DEBUGGER_H
 
 #include "common/scummsys.h"
+#include "common/path.h"
 #include "gui/debugger.h"
 
 namespace Sherlock {
@@ -74,7 +75,7 @@ private:
 	bool cmdFlag(int argc, const char **argv);
 protected:
 	SherlockEngine *_vm;
-	Common::String _3doPlayMovieFile;
+	Common::Path _3doPlayMovieFile;
 public:
 	AllLocations _showAllLocations;
 public:
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index 282d240d661..6d6e11fa0fc 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -54,7 +54,7 @@ Events::~Events() {
 	delete _cursorImages;
 }
 
-void Events::loadCursors(const Common::String &filename) {
+void Events::loadCursors(const Common::Path &filename) {
 	hideCursor();
 	delete _cursorImages;
 
diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h
index a99cc48e4ba..ee1731e59e7 100644
--- a/engines/sherlock/events.h
+++ b/engines/sherlock/events.h
@@ -69,7 +69,7 @@ public:
 	/**
 	 * Load a set of cursors from the specified file
 	 */
-	void loadCursors(const Common::String &filename);
+	void loadCursors(const Common::Path &filename);
 
 	/**
 	 * Set the cursor to show
diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp
index 94bc1b6fefd..0b794342d47 100644
--- a/engines/sherlock/fonts.cpp
+++ b/engines/sherlock/fonts.cpp
@@ -71,7 +71,7 @@ void Fonts::setFont(int fontNum) {
 			fontNum = 2;
 	}
 
-	Common::String fontFilename;
+	Common::Path fontFilename;
 
 	if (_isModifiedEucCn && _chineseFont == nullptr) {
 		Common::File hzk;
@@ -96,7 +96,7 @@ void Fonts::setFont(int fontNum) {
 	if (_vm->getPlatform() != Common::kPlatform3DO) {
 		// PC
 		// use FONT[number].VGS, which is a regular sherlock graphic file
-		fontFilename = Common::String::format("FONT%d.VGS", fontNum + 1);
+		fontFilename = Common::Path(Common::String::format("FONT%d.VGS", fontNum + 1));
 
 		// load font data
 		_font = new ImageFile(fontFilename);
diff --git a/engines/sherlock/image_file.cpp b/engines/sherlock/image_file.cpp
index 7759826ad7d..2f2498259ef 100644
--- a/engines/sherlock/image_file.cpp
+++ b/engines/sherlock/image_file.cpp
@@ -37,7 +37,7 @@ ImageFile::ImageFile() {
 	_stream = nullptr;
 }
 
-ImageFile::ImageFile(const Common::String &name, bool skipPal, bool animImages) {
+ImageFile::ImageFile(const Common::Path &name, bool skipPal, bool animImages) {
 	// When we have a filename, the ImageFile class is responsible for
 	// decoding frames on demand, not all at once. But we don't want to
 	// recreate the stream every time since in the case where resources
@@ -326,12 +326,12 @@ void ImageFile3DO::setVm(SherlockEngine *vm) {
 	_vm = vm;
 }
 
-ImageFile3DO::ImageFile3DO(const Common::String &name, ImageFile3DOType imageFile3DOType) {
+ImageFile3DO::ImageFile3DO(const Common::Path &name, ImageFile3DOType imageFile3DOType) {
 #if 0
 	Common::File *dataStream = new Common::File();
 
 	if (!dataStream->open(name)) {
-		error("unable to open %s\n", name.c_str());
+		error("unable to open %s\n", name.toString().c_str());
 	}
 #endif
 	Common::SeekableReadStream *dataStream = _vm->_res->load(name);
diff --git a/engines/sherlock/image_file.h b/engines/sherlock/image_file.h
index caf6103682a..847dfbec587 100644
--- a/engines/sherlock/image_file.h
+++ b/engines/sherlock/image_file.h
@@ -24,10 +24,8 @@
 
 #include "common/array.h"
 #include "common/file.h"
-#include "common/hashmap.h"
-#include "common/hash-str.h"
+#include "common/path.h"
 #include "common/rect.h"
-#include "common/str.h"
 #include "common/stream.h"
 #include "graphics/surface.h"
 
@@ -81,7 +79,7 @@ class ImageFile {
 private:
 	static SherlockEngine *_vm;
 	Common::Array<ImageFrame> _frames;
-	Common::String _name;
+	Common::Path _name;
 	Common::SeekableReadStream *_stream;
 
 	/**
@@ -103,7 +101,7 @@ public:
 	byte _palette[256 * 3];
 public:
 	ImageFile();
-	ImageFile(const Common::String &name, bool skipPal = false, bool animImages = false);
+	ImageFile(const Common::Path &name, bool skipPal = false, bool animImages = false);
 	ImageFile(Common::SeekableReadStream &stream, bool skipPal = false);
 	virtual ~ImageFile();
 	static void setVm(SherlockEngine *vm);
@@ -166,7 +164,7 @@ protected:
 	void decodeFrame(ImageFrame &frame);
 
 public:
-	ImageFile3DO(const Common::String &name, ImageFile3DOType imageFile3DOType);
+	ImageFile3DO(const Common::Path &name, ImageFile3DOType imageFile3DOType);
 	ImageFile3DO(Common::SeekableReadStream &stream, bool isRoomData = false);
 	static void setVm(SherlockEngine *vm);
 };
diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp
index 27e86ba0eb6..e62b63c29a6 100644
--- a/engines/sherlock/inventory.cpp
+++ b/engines/sherlock/inventory.cpp
@@ -94,7 +94,7 @@ void Inventory::loadGraphics() {
 		// Get the name of the item to be displayed, figure out its accompanying
 		// .VGS file with its picture, and then load it
 		int invNum = findInv((*this)[idx]._name);
-		Common::String filename = Common::String::format("item%02d.vgs", invNum + 1);
+		Common::Path filename(Common::String::format("item%02d.vgs", invNum + 1));
 
 		if (!IS_3DO) {
 			// PC
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index 022629131ab..8f5c16c50ea 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -407,7 +407,7 @@ bool Music::playMusic(const Common::String &name) {
 			return false;
 
 		Common::String midiMusicName = (IS_SERRATED_SCALPEL) ? name + ".MUS" : name + ".XMI";
-		Common::SeekableReadStream *stream = _vm->_res->load(midiMusicName, "MUSIC.LIB");
+		Common::SeekableReadStream *stream = _vm->_res->load(Common::Path(midiMusicName), "MUSIC.LIB");
 
 		byte *midiMusicData     = new byte[stream->size()];
 		int32 midiMusicDataSize = stream->size();
@@ -476,7 +476,8 @@ bool Music::playMusic(const Common::String &name) {
 	} else {
 		// 3DO: sample based
 		Audio::AudioStream *musicStream;
-		Common::String digitalMusicName = "music/" + name + "_MW22.aifc";
+		Common::Path digitalMusicName("music/");
+		digitalMusicName.appendInPlace(name + "_MW22.aifc");
 
 		if (isPlaying()) {
 			_mixer->stopHandle(_digitalMusicHandle);
@@ -484,7 +485,7 @@ bool Music::playMusic(const Common::String &name) {
 
 		Common::File *digitalMusicFile = new Common::File();
 		if (!digitalMusicFile->open(digitalMusicName)) {
-			warning("playMusic: can not open 3DO music '%s'", digitalMusicName.c_str());
+			warning("playMusic: can not open 3DO music '%s'", digitalMusicName.toString().c_str());
 			delete digitalMusicFile;
 			return false;
 		}
@@ -492,7 +493,7 @@ bool Music::playMusic(const Common::String &name) {
 		// Try to load the given file as AIFF/AIFC
 		musicStream = Audio::makeAIFFStream(digitalMusicFile, DisposeAfterUse::YES);
 		if (!musicStream) {
-			warning("playMusic: can not load 3DO music '%s'", digitalMusicName.c_str());
+			warning("playMusic: can not load 3DO music '%s'", digitalMusicName.toString().c_str());
 			return false;
 		}
 		_mixer->playStream(Audio::Mixer::kMusicSoundType, &_digitalMusicHandle, musicStream);
@@ -589,7 +590,7 @@ void Music::getSongNames(Common::StringArray &songs) {
 	songs.clear();
 	if (IS_SERRATED_SCALPEL) {
 		if (IS_3DO) {
-			Common::FSDirectory gameDirectory(ConfMan.get("path"));
+			Common::FSDirectory gameDirectory(ConfMan.getPath("path"));
 			Common::FSDirectory *musicDirectory = gameDirectory.getSubDirectory("music");
 			Common::ArchiveMemberList files;
 
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index 0ac86e556c4..ef116b263b9 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -70,7 +70,7 @@ public:
 	Common::String _npcName;
 
 	// Rose Tattoo fields
-	Common::String _walkVGSName;		// Name of walk library person is using
+	Common::Path _walkVGSName;		// Name of walk library person is using
 public:
 	Person();
 	~Person() override {}
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 44368c35451..18348e1661f 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -30,11 +30,11 @@ namespace Sherlock {
 Cache::Cache(SherlockEngine *vm) : _vm(vm) {
 }
 
-bool Cache::isCached(const Common::String &filename) const {
+bool Cache::isCached(const Common::Path &filename) const {
 	return _resources.contains(filename);
 }
 
-void Cache::load(const Common::String &name) {
+void Cache::load(const Common::Path &name) {
 	// First check if the entry already exists
 	if (_resources.contains(name))
 		return;
@@ -42,14 +42,14 @@ void Cache::load(const Common::String &name) {
 	// Open the file for reading
 	Common::File f;
 	if (!f.open(name))
-		error("Could not read file - %s", name.c_str());
+		error("Could not read file - %s", name.toString().c_str());
 
 	load(name, f);
 
 	f.close();
 }
 
-void Cache::load(const Common::String &name, Common::SeekableReadStream &stream) {
+void Cache::load(const Common::Path &name, Common::SeekableReadStream &stream) {
 	// First check if the entry already exists
 	if (_resources.contains(name))
 		return;
@@ -76,7 +76,7 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream)
 	}
 }
 
-Common::SeekableReadStream *Cache::get(const Common::String &filename) const {
+Common::SeekableReadStream *Cache::get(const Common::Path &filename) const {
 	// Return a memory stream that encapsulates the data
 	const CacheEntry &cacheEntry = _resources[filename];
 	return new Common::MemoryReadStream(&cacheEntry[0], cacheEntry.size());
@@ -114,7 +114,7 @@ Resources::Resources(SherlockEngine *vm) : _vm(vm), _cache(vm) {
 	}
 }
 
-void Resources::addToCache(const Common::String &filename) {
+void Resources::addToCache(const Common::Path &filename) {
 	// Return immediately if the library has already been loaded
 	if (_indexes.contains(filename))
 		return;
@@ -133,7 +133,7 @@ void Resources::addToCache(const Common::String &filename) {
 	delete stream;
 }
 
-void Resources::addToCache(const Common::String &filename, const Common::String &libFilename) {
+void Resources::addToCache(const Common::Path &filename, const Common::Path &libFilename) {
 	// Get the resource
 	Common::SeekableReadStream *stream = load(filename, libFilename);
 
@@ -142,11 +142,11 @@ void Resources::addToCache(const Common::String &filename, const Common::String
 	delete stream;
 }
 
-void Resources::addToCache(const Common::String &filename, Common::SeekableReadStream &stream) {
+void Resources::addToCache(const Common::Path &filename, Common::SeekableReadStream &stream) {
 	_cache.load(filename, stream);
 }
 
-Common::SeekableReadStream *Resources::load(const Common::String &filename) {
+Common::SeekableReadStream *Resources::load(const Common::Path &filename) {
 	// First check if the file is directly in the cache
 	if (_cache.isCached(filename))
 		return _cache.get(filename);
@@ -172,7 +172,7 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) {
 	// At this point, fall back on a physical file with the given name
 	Common::File f;
 	if (!f.open(filename))
-		error("Could not load file - %s", filename.c_str());
+		error("Could not load file - %s", filename.toString().c_str());
 
 	Common::SeekableReadStream *stream = f.readStream(f.size());
 	f.close();
@@ -194,7 +194,7 @@ void Resources::decompressIfNecessary(Common::SeekableReadStream *&stream) {
 	}
 }
 
-Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile,
+Common::SeekableReadStream *Resources::load(const Common::Path &filename, const Common::Path &libraryFile,
 		bool suppressErrors) {
 	// Open up the library for access
 	Common::SeekableReadStream *libStream = load(libraryFile);
@@ -207,7 +207,7 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename, cons
 	// Handle if resource is not present
 	if (!libIndex.contains(filename)) {
 		if (!suppressErrors)
-			error("Could not find resource - %s", filename.c_str());
+			error("Could not find resource - %s", filename.toString().c_str());
 
 		delete libStream;
 		return nullptr;
@@ -223,12 +223,12 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename, cons
 	return stream;
 }
 
-bool Resources::exists(const Common::String &filename) const {
+bool Resources::exists(const Common::Path &filename) const {
 	Common::File f;
 	return f.exists(filename) || _cache.isCached(filename);
 }
 
-void Resources::loadLibraryIndex(const Common::String &libFilename,
+void Resources::loadLibraryIndex(const Common::Path &libFilename,
 		Common::SeekableReadStream *stream, bool isNewStyle) {
 	uint32 offset, nextOffset;
 
@@ -313,11 +313,11 @@ int Resources::resourceIndex() const {
 	return _resourceIndex;
 }
 
-void Resources::getResourceNames(const Common::String &libraryFile, Common::StringArray &names) {
+void Resources::getResourceNames(const Common::Path &libraryFile, Common::StringArray &names) {
 	addToCache(libraryFile);
 	LibraryIndex &libIndex = _indexes[libraryFile];
 	for (LibraryIndex::iterator i = libIndex.begin(); i != libIndex.end(); ++i) {
-		names.push_back(i->_key);
+		names.push_back(i->_key.toString('/'));
 	}
 }
 
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index a9d9b61f22c..0ef8986161b 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -35,7 +35,7 @@
 namespace Sherlock {
 
 typedef Common::Array<byte> CacheEntry;
-typedef Common::HashMap<Common::String, CacheEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CacheHash;
+typedef Common::HashMap<Common::Path, CacheEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> CacheHash;
 
 struct LibraryEntry {
 	uint32 _offset, _size;
@@ -45,8 +45,8 @@ struct LibraryEntry {
 	LibraryEntry(int index, uint32 offset, uint32 size) :
 		_index(index), _offset(offset), _size(size) {}
 };
-typedef Common::HashMap<Common::String, LibraryEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LibraryIndex;
-typedef Common::HashMap<Common::String, LibraryIndex, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LibraryIndexes;
+typedef Common::HashMap<Common::Path, LibraryEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> LibraryIndex;
+typedef Common::HashMap<Common::Path, LibraryIndex, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> LibraryIndexes;
 
 class SherlockEngine;
 
@@ -60,24 +60,24 @@ public:
 	/**
 	 * Returns true if a given file is currently being cached
 	 */
-	bool isCached(const Common::String &filename) const;
+	bool isCached(const Common::Path &filename) const;
 
 	/**
 	 * Loads a file into the cache if it's not already present, and returns it.
 	 * If the file is LZW compressed, automatically decompresses it and loads
 	 * the uncompressed version into memory
 	 */
-	void load(const Common::String &name);
+	void load(const Common::Path &name);
 
 	/**
 	 * Load a cache entry based on a passed stream
 	 */
-	void load(const Common::String &name, Common::SeekableReadStream &stream);
+	void load(const Common::Path &name, Common::SeekableReadStream &stream);
 
 	/**
 	 * Get a file from the cache
 	 */
-	Common::SeekableReadStream *get(const Common::String &filename) const;
+	Common::SeekableReadStream *get(const Common::Path &filename) const;
 };
 
 class Resources {
@@ -90,7 +90,7 @@ private:
 	/**
 	 * Reads in the index from a library file, and caches its index for later use
 	 */
-	void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream, bool isNewStyle);
+	void loadLibraryIndex(const Common::Path &libFilename, Common::SeekableReadStream *stream, bool isNewStyle);
 public:
 	Resources(SherlockEngine *vm);
 
@@ -98,19 +98,19 @@ public:
 	 * Adds the specified file to the cache. If it's a library file, takes care of
 	 * loading its index for future use
 	 */
-	void addToCache(const Common::String &filename);
+	void addToCache(const Common::Path &filename);
 
 	/**
 	 * Adds a resource from a library file to the cache
 	 */
-	void addToCache(const Common::String &filename, const Common::String &libFilename);
+	void addToCache(const Common::Path &filename, const Common::Path &libFilename);
 
 	/**
 	 * Adds a given stream to the cache under the given name
 	 */
-	void addToCache(const Common::String &filename, Common::SeekableReadStream &stream);
+	void addToCache(const Common::Path &filename, Common::SeekableReadStream &stream);
 
-	bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); }
+	bool isInCache(const Common::Path &filename) const { return _cache.isCached(filename); }
 
 	/**
 	 * Checks the passed stream, and if is compressed, deletes it and replaces it with its uncompressed data
@@ -120,17 +120,17 @@ public:
 	/**
 	 * Returns a stream for a given file
 	 */
-	Common::SeekableReadStream *load(const Common::String &filename);
+	Common::SeekableReadStream *load(const Common::Path &filename);
 
 	/**
 	 * Loads a specific resource from a given library file
 	 */
-	Common::SeekableReadStream *load(const Common::String &filename, const Common::String &libraryFile, bool suppressErrors = false);
+	Common::SeekableReadStream *load(const Common::Path &filename, const Common::Path &libraryFile, bool suppressErrors = false);
 
 	/**
 	 * Returns true if the given file exists on disk or in the cache
 	 */
-	bool exists(const Common::String &filename) const;
+	bool exists(const Common::Path &filename) const;
 
 	/**
 	 * Returns the index of the last loaded resource in its given library file.
@@ -142,7 +142,7 @@ public:
 	/**
 	 * Produces a list of all resource names within a file. Used by the debugger.
 	 */
-	void getResourceNames(const Common::String &libraryFile, Common::StringArray &names);
+	void getResourceNames(const Common::Path &libraryFile, Common::StringArray &names);
 
 	/**
 	 * Decompresses LZW compressed data
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index b42c600ea6d..9c15d1f9aff 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -992,7 +992,7 @@ void ScalpelEngine::loadInventory() {
 	inv.push_back(InventoryItem(586, "Pawn ticket", fixedText_PawnTicket, "_ITEM16A"));
 }
 
-void ScalpelEngine::showLBV(const Common::String &filename) {
+void ScalpelEngine::showLBV(const Common::Path &filename) {
 	Common::SeekableReadStream *stream = _res->load(filename, "title.lib");
 	ImageFile images(*stream);
 	delete stream;
@@ -1269,7 +1269,7 @@ void ScalpelEngine::showScummVMRestoreDialog() {
 	delete dialog;
 }
 
-bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait) {
+bool ScalpelEngine::play3doMovie(const Common::Path &filename, const Common::Point &pos, bool isPortrait) {
 	Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
 	Video::ThreeDOMovieDecoder *videoDecoder = new Video::ThreeDOMovieDecoder();
 	Graphics::ManagedSurface tempSurface;
@@ -1279,7 +1279,7 @@ bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::P
 	bool frameShown = false;
 
 	if (!videoDecoder->loadFile(filename)) {
-		warning("Scalpel3DOMoviePlay: could not open '%s'", filename.c_str());
+		warning("Scalpel3DOMoviePlay: could not open '%s'", filename.toString().c_str());
 		delete videoDecoder;
 		return false;
 	}
diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h
index aed2a6cf33f..9dd264e7650 100644
--- a/engines/sherlock/scalpel/scalpel.h
+++ b/engines/sherlock/scalpel/scalpel.h
@@ -101,7 +101,7 @@ private:
 	/**
 	 * Transition to show an image
 	 */
-	void showLBV(const Common::String &filename);
+	void showLBV(const Common::Path &filename);
 protected:
 	/**
 	 * Game initialization
@@ -149,7 +149,7 @@ public:
 	/**
 	 * Play back a 3do movie
 	 */
-	bool play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait = false);
+	bool play3doMovie(const Common::Path &filename, const Common::Point &pos, bool isPortrait = false);
 };
 
 } // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_people.cpp b/engines/sherlock/scalpel/scalpel_people.cpp
index 38e57b03f17..b363e09439c 100644
--- a/engines/sherlock/scalpel/scalpel_people.cpp
+++ b/engines/sherlock/scalpel/scalpel_people.cpp
@@ -396,7 +396,7 @@ void ScalpelPeople::setTalking(int speaker) {
 
 	if (_portraitsOn) {
 		delete _talkPics;
-		Common::String filename = Common::String::format("%s.vgs", _characters[speaker]._portrait);
+		Common::Path filename(Common::String::format("%s.vgs", _characters[speaker]._portrait));
 		_talkPics = new ImageFile(filename);
 
 		// Load portrait sequences
diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp
index 8ee01acf207..c23f94c880f 100644
--- a/engines/sherlock/scalpel/scalpel_scene.cpp
+++ b/engines/sherlock/scalpel/scalpel_scene.cpp
@@ -44,7 +44,7 @@ ScalpelScene::~ScalpelScene() {
 		delete _canimShapes[idx];
 }
 
-bool ScalpelScene::loadScene(const Common::String &filename) {
+bool ScalpelScene::loadScene(const Common::Path &filename) {
 	ScalpelMap &map = *(ScalpelMap *)_vm->_map;
 	bool result = Scene::loadScene(filename);
 
@@ -572,7 +572,7 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
 		if (tpPos.x != -1)
 			people[HOLMES]._type = REMOVE;
 
-		Common::String fname = cAnim._name + ".vgs";
+		Common::Path fname(cAnim._name + ".vgs");
 		if (!res.isInCache(fname)) {
 			// Set up RRM scene data
 			Common::SeekableReadStream *roomStream = res.load(_roomFilename);
diff --git a/engines/sherlock/scalpel/scalpel_scene.h b/engines/sherlock/scalpel/scalpel_scene.h
index c776efbe298..b8f62b869af 100644
--- a/engines/sherlock/scalpel/scalpel_scene.h
+++ b/engines/sherlock/scalpel/scalpel_scene.h
@@ -53,7 +53,7 @@ protected:
 	 * The _misc field of the structures contains the number of the graphic image
 	 * that it should point to after loading; _misc is then set to 0.
 	 */
-	bool loadScene(const Common::String &filename) override;
+	bool loadScene(const Common::Path &filename) override;
 
 	/**
 	 * Checks all the background shapes. If a background shape is animating,
diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp
index 3b41bd8bcc5..caa53dc8229 100644
--- a/engines/sherlock/scalpel/scalpel_talk.cpp
+++ b/engines/sherlock/scalpel/scalpel_talk.cpp
@@ -177,7 +177,7 @@ ScalpelTalk::ScalpelTalk(SherlockEngine *vm) : Talk(vm) {
 	_hotkeyWindowDown = toupper(_fixedTextWindowDown[0]);
 }
 
-void ScalpelTalk::talkTo(const Common::String filename) {
+void ScalpelTalk::talkTo(const Common::String &filename) {
 	ScalpelUserInterface &ui = *(ScalpelUserInterface *)_vm->_ui;
 
 	Talk::talkTo(filename);
@@ -474,7 +474,7 @@ OpcodeReturn ScalpelTalk::cmdPlayPrologue(const byte *&str) {
 	for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
 		tempString += str[idx];
 
-	anim.play(tempString, false, 1, 3, true, 4);
+	anim.play(Common::Path(tempString), false, 1, 3, true, 4);
 
 	return RET_SUCCESS;
 }
@@ -513,7 +513,7 @@ OpcodeReturn ScalpelTalk::cmdSfxCommand(const byte *&str) {
 	if (sound._voices) {
 		for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
 			tempString += str[idx];
-		sound.playSpeech(tempString);
+		sound.playSpeech(Common::Path(tempString));
 
 		// Set voices to wait for more
 		sound._voices = 2;
@@ -634,18 +634,19 @@ bool ScalpelTalk::talk3DOMovieTrigger(int subIndex) {
 	screen.update();
 
 	// Figure out that movie filename
-	Common::String movieFilename;
+	Common::String movieName;
 
-	movieFilename = _scriptName;
-	movieFilename.deleteChar(1); // remove 2nd character of scriptname
+	movieName = _scriptName;
+	movieName.deleteChar(1); // remove 2nd character of scriptname
 	// cut scriptname to 6 characters
-	while (movieFilename.size() > 6) {
-		movieFilename.deleteChar(6);
+	while (movieName.size() > 6) {
+		movieName.deleteChar(6);
 	}
 
-	movieFilename.insertChar(selector + 'a', movieFilename.size());
-	movieFilename.insertChar(subIndex + 'a', movieFilename.size());
-	movieFilename = Common::String::format("movies/%02d/%s.stream", roomNr, movieFilename.c_str());
+	movieName.insertChar(selector + 'a', movieName.size());
+	movieName.insertChar(subIndex + 'a', movieName.size());
+
+	Common::Path movieFilename(Common::String::format("movies/%02d/%s.stream", roomNr, movieName.c_str()));
 
 	warning("3DO movie player:");
 	warning("room: %d", roomNr);
diff --git a/engines/sherlock/scalpel/scalpel_talk.h b/engines/sherlock/scalpel/scalpel_talk.h
index effcbe78b6f..add106c198a 100644
--- a/engines/sherlock/scalpel/scalpel_talk.h
+++ b/engines/sherlock/scalpel/scalpel_talk.h
@@ -109,7 +109,7 @@ public:
 	 *	In their case, the conversation display is simply suppressed, and control is passed on to
 	 *	doScript to implement whatever action is required.
 	 */
-	void talkTo(const Common::String filename) override;
+	void talkTo(const Common::String &filename) override;
 
 	/**
 	 * When the talk window has been displayed, waits a period of time proportional to
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
index 14f2c60edc0..62734421a01 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.cpp
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -1802,7 +1802,7 @@ void ScalpelUserInterface::doTalkControl() {
 			people.setTalking(0);
 
 			if (!talk._statements[_selector]._voiceFile.empty() && sound._voices) {
-				sound.playSpeech(talk._statements[_selector]._voiceFile);
+				sound.playSpeech(Common::Path(talk._statements[_selector]._voiceFile));
 
 				// Set voices as an indicator for waiting
 				sound._voices = 2;
diff --git a/engines/sherlock/scalpel/tsage/resources.cpp b/engines/sherlock/scalpel/tsage/resources.cpp
index 3b7e773ccba..c1452d3a72b 100644
--- a/engines/sherlock/scalpel/tsage/resources.cpp
+++ b/engines/sherlock/scalpel/tsage/resources.cpp
@@ -51,7 +51,7 @@ uint16 BitReader::readToken() {
 
 /*-------------------------------------------------------------------------*/
 
-TLib::TLib(const Common::String &filename) : _filename(filename) {
+TLib::TLib(const Common::Path &filename) : _filename(filename) {
 
 	// If the resource strings list isn't yet loaded, load them
 	if (_resStrings.size() == 0) {
@@ -65,7 +65,7 @@ TLib::TLib(const Common::String &filename) : _filename(filename) {
 	}
 
 	if (!_file.open(filename))
-		error("Missing file %s", filename.c_str());
+		error("Missing file %s", filename.toString().c_str());
 
 	loadIndex();
 }
diff --git a/engines/sherlock/scalpel/tsage/resources.h b/engines/sherlock/scalpel/tsage/resources.h
index 0f0717fd7fe..1d5d43172bd 100644
--- a/engines/sherlock/scalpel/tsage/resources.h
+++ b/engines/sherlock/scalpel/tsage/resources.h
@@ -110,7 +110,7 @@ private:
 	Common::StringArray _resStrings;
 private:
 	Common::File _file;
-	Common::String _filename;
+	Common::Path _filename;
 	ResourceList _resources;
 	SectionList _sections;
 
@@ -120,10 +120,10 @@ private:
 	static bool scanIndex(Common::File &f, ResourceType resType, int rlbNum, int resNum, ResourceEntry &resEntry);
 	static void loadSection(Common::File &f, ResourceList &resources);
 public:
-	TLib(const Common::String &filename);
+	TLib(const Common::Path &filename);
 	~TLib();
 
-	const Common::String &getFilename() { return _filename; }
+	const Common::Path &getFilename() { return _filename; }
 	const SectionList &getSections() { return _sections; }
 	Common::SeekableReadStream *getResource(uint16 id, bool suppressErrors = false);
 	Common::SeekableReadStream *getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors = false);
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 9dfd7cdf6ec..5b6f0dab608 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -246,7 +246,7 @@ void Scene::selectScene() {
 	ui._menuMode = STD_MODE;
 
 	// Load the scene
-	Common::String sceneFile = Common::String::format("res%02d", _goToScene);
+	Common::Path sceneFile(Common::String::format("res%02d", _goToScene));
 	// _rrmName gets set during loadScene()
 	// _rrmName is for ScalpelScene::startCAnim
 	_currentScene = _goToScene;
@@ -303,7 +303,7 @@ void Scene::freeScene() {
 	_currentScene = -1;
 }
 
-bool Scene::loadScene(const Common::String &filename) {
+bool Scene::loadScene(const Common::Path &filename) {
 	Events &events = *_vm->_events;
 	Music &music = *_vm->_music;
 	People &people = *_vm->_people;
@@ -331,7 +331,7 @@ bool Scene::loadScene(const Common::String &filename) {
 
 	if (!IS_3DO) {
 		// PC version
-		Common::String roomFilename = filename + ".rrm";
+		Common::Path roomFilename = filename.append(".rrm");
 		_roomFilename = roomFilename;
 
 		flag = _vm->_res->exists(roomFilename);
@@ -659,7 +659,7 @@ bool Scene::loadScene(const Common::String &filename) {
 
 	} else {
 		// === 3DO version ===
-		_roomFilename = "rooms/" + filename + ".rrm";
+		_roomFilename = Common::Path("rooms/").appendInPlace(filename).appendInPlace(".rrm");
 		flag = _vm->_res->exists(_roomFilename);
 		if (!flag)
 			error("loadScene: 3DO room data file not found");
@@ -956,14 +956,16 @@ bool Scene::loadScene(const Common::String &filename) {
 		// load from file rooms\[filename].bg
 		// it's uncompressed 15-bit RGB555 data
 
-		Common::String roomBackgroundFilename = "rooms/" + filename + ".bg";
+		Common::Path roomBackgroundFilename("rooms/");
+		roomBackgroundFilename.appendInPlace(filename);
+		roomBackgroundFilename.appendInPlace(".bg");
 		flag = _vm->_res->exists(roomBackgroundFilename);
 		if (!flag)
-			error("loadScene: 3DO room background file not found (%s)", roomBackgroundFilename.c_str());
+			error("loadScene: 3DO room background file not found (%s)", roomBackgroundFilename.toString().c_str());
 
 		Common::File roomBackgroundStream;
 		if (!roomBackgroundStream.open(roomBackgroundFilename))
-			error("Could not open file - %s", roomBackgroundFilename.c_str());
+			error("Could not open file - %s", roomBackgroundFilename.toString().c_str());
 
 		int totalPixelCount = SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT;
 		uint16 *roomBackgroundDataPtr = nullptr;
@@ -1058,7 +1060,7 @@ void Scene::loadSceneSounds() {
 	Sound &sound = *_vm->_sound;
 
 	for (uint idx = 0; idx < _sounds.size(); ++idx)
-		sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
+		sound.loadSound(Common::Path(_sounds[idx]._name), _sounds[idx]._priority);
 }
 
 void Scene::checkSceneStatus() {
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 83534a43704..c4fd4f9aaeb 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -175,7 +175,7 @@ private:
 	void saveSceneStatus();
 protected:
 	SherlockEngine *_vm;
-	Common::String _roomFilename;
+	Common::Path _roomFilename;
 
 	/**
 	 * Loads the data associated for a given scene. The room resource file's format is:
@@ -186,7 +186,7 @@ protected:
 	 * The _misc field of the structures contains the number of the graphic image
 	 * that it should point to after loading; _misc is then set to 0.
 	 */
-	virtual bool loadScene(const Common::String &filename);
+	virtual bool loadScene(const Common::Path &filename);
 
 	/**
 	 * Checks all the background shapes. If a background shape is animating,
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index 62e62b55875..a887e7cd27e 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -91,7 +91,7 @@ void Sound::syncSoundSettings() {
 	_voices = _digitized ? 1 : 0;
 }
 
-void Sound::loadSound(const Common::String &name, int priority) {
+void Sound::loadSound(const Common::Path &name, int priority) {
 	// No implementation required in ScummVM
 	//warning("loadSound");
 }
@@ -118,16 +118,16 @@ byte Sound::decodeSample(byte sample, byte &reference, int16 &scale) {
 	return reference;
 }
 
-bool Sound::playSound(const Common::String &name, WaitType waitType, int priority, const char *libraryFilename) {
+bool Sound::playSound(const Common::Path &name, WaitType waitType, int priority, const Common::Path &libraryFilename) {
 	// Scalpel has only a single sound handle, so it must be stopped before starting a new sound
 	if (IS_SERRATED_SCALPEL)
 		stopSound();
 
-	Common::String filename = formFilename(name);
+	Common::Path filename = formFilename(name);
 
 	Audio::SoundHandle &soundHandle = (IS_SERRATED_SCALPEL) ? _scalpelEffectsHandle : getFreeSoundHandle();
 	if (!playSoundResource(filename, libraryFilename, Audio::Mixer::kSFXSoundType, soundHandle))
-		error("Could not find sound resource - %s", filename.c_str());
+		error("Could not find sound resource - %s", filename.toString().c_str());
 
 	_soundPlaying = true;
 	_curPriority = priority;
@@ -152,22 +152,22 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit
 	return retval;
 }
 
-Common::String Sound::formFilename(const Common::String &name) {
-	Common::String filename = name;
+Common::Path Sound::formFilename(const Common::Path &name) {
+	Common::Path filename = name;
 
-	if (!filename.contains('.')) {
+	if (!filename.baseName().contains('.')) {
 		if (!IS_3DO) {
 			if (IS_SERRATED_SCALPEL) {
-				filename += ".SND";
+				filename.appendInPlace(".SND");
 			} else {
-				filename += ".WAV";
+				filename.appendInPlace(".WAV");
 			}
 		} else {
 			// 3DO uses .aiff extension
-			filename += ".AIFF";
-			if (!filename.contains('/')) {
+			filename.appendInPlace(".AIFF");
+			if (filename.getParent().empty()) {
 				// if no directory was given, use the room sounds directory
-				filename = "rooms/sounds/" + filename;
+				filename = Common::Path("rooms/sounds/").appendInPlace(filename);
 			}
 		}
 	}
@@ -175,7 +175,7 @@ Common::String Sound::formFilename(const Common::String &name) {
 	return filename;
 }
 
-void Sound::playAiff(const Common::String &name, int volume, bool loop) {
+void Sound::playAiff(const Common::Path &name, int volume, bool loop) {
 	Common::File *file = new Common::File();
 	if (!file->open(name)) {
 		delete file;
@@ -207,7 +207,7 @@ void Sound::playLoadedSound(int bufNum, WaitType waitType) {
 		stopSound();
 	}
 
-	playSound(_vm->_scene->_sounds[bufNum]._name, waitType, _vm->_scene->_sounds[bufNum]._priority);
+	playSound(Common::Path(_vm->_scene->_sounds[bufNum]._name), waitType, _vm->_scene->_sounds[bufNum]._priority);
 }
 
 void Sound::freeLoadedSounds() {
@@ -245,7 +245,7 @@ void Sound::setVolume(int volume) {
 	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, volume);
 }
 
-void Sound::playSpeech(const Common::String &name) {
+void Sound::playSpeech(const Common::Path &name) {
 	Resources &res = *_vm->_res;
 	Scene &scene = *_vm->_scene;
 
@@ -253,14 +253,15 @@ void Sound::playSpeech(const Common::String &name) {
 	stopSpeech();
 
 	if (IS_SERRATED_SCALPEL) {
-		Common::String filename = formFilename(name);
-		if (playSoundResource(filename, Common::String(), Audio::Mixer::kSFXSoundType, _speechHandle))
+		Common::Path filename = formFilename(name);
+		if (playSoundResource(filename, Common::Path(), Audio::Mixer::kSFXSoundType, _speechHandle))
 			_speechPlaying = true;
 	} else {
 		// Figure out which speech library to use
-		Common::String libraryName = Common::String::format("speech%02d.lib", scene._currentScene);
-		if ((!scumm_strnicmp(name.c_str(), "SLVE12S", 7)) || (!scumm_strnicmp(name.c_str(), "WATS12X", 7))
-				|| (!scumm_strnicmp(name.c_str(), "HOLM12X", 7)))
+		Common::Path libraryName(Common::String::format("speech%02d.lib", scene._currentScene));
+		Common::String baseName(name.baseName());
+		if ((!scumm_strnicmp(baseName.c_str(), "SLVE12S", 7)) || (!scumm_strnicmp(baseName.c_str(), "WATS12X", 7))
+				|| (!scumm_strnicmp(baseName.c_str(), "HOLM12X", 7)))
 			libraryName = "SPEECH12.LIB";
 
 		// If the speech library file doesn't even exist, then we can't play anything
@@ -286,7 +287,7 @@ bool Sound::isSpeechPlaying() {
 	return _speechPlaying;
 }
 
-bool Sound::playSoundResource(const Common::String &name, const Common::String &libFilename,
+bool Sound::playSoundResource(const Common::Path &name, const Common::Path &libFilename,
 		Audio::Mixer::SoundType soundType, Audio::SoundHandle &handle) {
 	Resources &res = *_vm->_res;
 	Common::SeekableReadStream *stream = libFilename.empty() ? res.load(name) : res.load(name, libFilename, true);
diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h
index c766c1cd111..9c3738657eb 100644
--- a/engines/sherlock/sound.h
+++ b/engines/sherlock/sound.h
@@ -55,13 +55,13 @@ private:
 	/**
 	 * Handle playing a sound or speech
 	 */
-	bool playSoundResource(const Common::String &name, const Common::String &libFilename,
+	bool playSoundResource(const Common::Path &name, const Common::Path &libFilename,
 		Audio::Mixer::SoundType soundType, Audio::SoundHandle &handle);
 
 	/**
 	 * Form a filename from a passed sound resource name
 	 */
-	Common::String formFilename(const Common::String &name);
+	Common::Path formFilename(const Common::Path &name);
 public:
 	bool _digitized;
 	int _voices;
@@ -83,17 +83,17 @@ public:
 	/**
 	 * Load a sound
 	 */
-	void loadSound(const Common::String &name, int priority);
+	void loadSound(const Common::Path &name, int priority);
 
 	/**
 	 * Play the sound in the specified resource
 	 */
-	bool playSound(const Common::String &name, WaitType waitType, int priority = 100, const char *libraryFilename = nullptr);
+	bool playSound(const Common::Path &name, WaitType waitType, int priority = 100, const Common::Path &libraryFilename = Common::Path());
 
 	/**
 	 * Play the specified AIFF file. (Used for the 3DO Scalpel intro.)
 	 */
-	void playAiff(const Common::String &name, int volume = Audio::Mixer::kMaxChannelVolume, bool loop = false);
+	void playAiff(const Common::Path &name, int volume = Audio::Mixer::kMaxChannelVolume, bool loop = false);
 
 	/**
 	 * Stop the AIFF sound that was started with playAiff().
@@ -130,7 +130,7 @@ public:
 	/**
 	 * Play a specified voice resource
 	 */
-	void playSpeech(const Common::String &name);
+	void playSpeech(const Common::Path &name);
 
 	/**
 	 * Stop any currently playing speech
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 75ff5516658..60d90b926cb 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -130,7 +130,7 @@ Talk::Talk(SherlockEngine *vm) : _vm(vm) {
 	_talkHistory.resize(IS_ROSE_TATTOO ? 1500 : 500);
 }
 
-void Talk::talkTo(const Common::String filename) {
+void Talk::talkTo(const Common::String &filename) {
 	Events &events = *_vm->_events;
 	Inventory &inv = *_vm->_inventory;
 	Journal &journal = *_vm->_journal;
@@ -590,8 +590,8 @@ void Talk::loadTalkFile(const Common::String &filename) {
 	}
 
 	const char *chP = strchr(filename.c_str(), '.');
-	Common::String talkFile = chP ? Common::String(filename.c_str(), chP) + ".tlk" :
-		Common::String(filename.c_str(), filename.c_str() + 7) + ".tlk";
+	Common::Path talkFile = chP ? Common::Path(Common::String(filename.c_str(), chP)).appendInPlace(".tlk") :
+		Common::Path(Common::String(filename.c_str(), filename.c_str() + 7)).appendInPlace(".tlk");
 
 	// Create the base of the sound filename used for talking in Rose Tattoo
 	if (IS_ROSE_TATTOO && _scriptMoreFlag != 1)
@@ -880,7 +880,7 @@ int Talk::waitForMore(int delay) {
 	// Handle playing any speech associated with the text being displayed
 	switchSpeaker();
 	if (sound._speechOn && IS_ROSE_TATTOO) {
-		sound.playSpeech(sound._talkSoundFile);
+		sound.playSpeech(Common::Path(sound._talkSoundFile));
 		sound._talkSoundFile.setChar(sound._talkSoundFile.lastChar() + 1, sound._talkSoundFile.size() - 1);
 	}
 	playingSpeech = sound.isSpeechPlaying();
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index abe3ae6f915..546a2b5a7ae 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -282,7 +282,7 @@ public:
 	 *	In their case, the conversation display is simply suppressed, and control is passed on to
 	 *	doScript to implement whatever action is required.
 	 */
-	virtual void talkTo(const Common::String filename);
+	virtual void talkTo(const Common::String &filename);
 
 	/**
 	 * Parses a reply for control codes and display text. The found text is printed within
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 7867cb7cd98..c06b26f5c5a 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -104,7 +104,7 @@ void TattooEngine::startScene() {
 	case 53:
 	case 68:
 		// Load overlay mask(s) for the scene
-		ui._mask = _res->load(Common::String::format("res%02d.msk", _scene->_goToScene));
+		ui._mask = _res->load(Common::Path(Common::String::format("res%02d.msk", _scene->_goToScene)));
 		if (_scene->_goToScene == 8)
 			ui._mask1 = _res->load("res08a.msk");
 		else if (_scene->_goToScene == 18 || _scene->_goToScene == 68)
diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp
index 6bf3ff85acd..4f3ae9432d2 100644
--- a/engines/sherlock/tattoo/tattoo_map.cpp
+++ b/engines/sherlock/tattoo/tattoo_map.cpp
@@ -367,7 +367,7 @@ void TattooMap::showCloseUp(int closeUpNum) {
 	events.hideCursor();
 
 	// Get the closeup images
-	Common::String fname = Common::String::format("res%02d.vgs", closeUpNum + 1);
+	Common::Path fname(Common::String::format("res%02d.vgs", closeUpNum + 1));
 	ImageFile pic(fname);
 
 	Point32 closeUp(_data[closeUpNum].x * 100, _data[closeUpNum].y * 100);
diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp
index b35d50cfc30..fa5d2718172 100644
--- a/engines/sherlock/tattoo/tattoo_people.cpp
+++ b/engines/sherlock/tattoo/tattoo_people.cpp
@@ -909,7 +909,7 @@ void TattooPerson::checkWalkGraphics() {
 		return;
 	}
 
-	Common::String filename = Common::String::format("%s.vgs", _walkSequences[_sequenceNumber]._vgsName.c_str());
+	Common::Path filename(Common::String::format("%s.vgs", _walkSequences[_sequenceNumber]._vgsName.c_str()));
 
 	// Set the adjust depending on if we have to fine tune the x position of this particular graphic
 	_adjust.x = _adjust.y = 0;
@@ -949,10 +949,10 @@ void TattooPerson::checkWalkGraphics() {
 
 		if (npcNum != -1) {
 			// See if the VGS file called for is different than the main graphics which are already loaded
-			if (filename.compareToIgnoreCase(people[npcNum]._walkVGSName) != 0) {
+			if (!filename.equalsIgnoreCase(people[npcNum]._walkVGSName)) {
 				// See if this is one of the more used Walk Graphics stored in WALK.LIB
 				for (int idx = 0; idx < NUM_IN_WALK_LIB; ++idx) {
-					if (!scumm_stricmp(filename.c_str(), WALK_LIB_NAMES[idx])) {
+					if (filename.equalsIgnoreCase(WALK_LIB_NAMES[idx])) {
 						people._useWalkLib = true;
 						break;
 					}
@@ -994,7 +994,14 @@ void TattooPerson::synchronize(Serializer &s) {
 
 	s.syncAsSint32LE(_position.x);
 	s.syncAsSint32LE(_position.y);
-	s.syncString(_walkVGSName);
+	if (s.isSaving()) {
+		Common::String path(_walkVGSName.toString('/'));
+		s.syncString(path);
+	} else {
+		Common::String path;
+		s.syncString(path);
+		_walkVGSName = Common::Path(path);
+	}
 	s.syncString(_description);
 	s.syncString(_examine);
 
@@ -1417,7 +1424,7 @@ bool TattooPeople::loadWalk() {
 
 			// See if this is one of the more used Walk Graphics stored in WALK.LIB
 			for (int libNum = 0; libNum < NUM_IN_WALK_LIB; ++libNum) {
-				if (!person._walkVGSName.compareToIgnoreCase(WALK_LIB_NAMES[libNum])) {
+				if (person._walkVGSName.equalsIgnoreCase(WALK_LIB_NAMES[libNum])) {
 					_useWalkLib = true;
 					break;
 				}
@@ -1428,8 +1435,10 @@ bool TattooPeople::loadWalk() {
 			person._maxFrames = person._images->size();
 
 			// Load walk sequence data
-			Common::String fname = Common::String(person._walkVGSName.c_str(), strchr(person._walkVGSName.c_str(), '.'));
-			fname += ".SEQ";
+			Common::String baseName(person._walkVGSName.baseName());
+			baseName = Common::String(baseName.c_str(), strchr(baseName.c_str(), '.'));
+			baseName += ".SEQ";
+			Common::Path fname = person._walkVGSName.getParent().appendComponent(baseName);
 
 			// Load the walk sequence data
 			Common::SeekableReadStream *stream = res.load(fname, _useWalkLib ? "walk.lib" : "vgs.lib");
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index f66828cad90..f515a84ae48 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -65,7 +65,7 @@ TattooScene::TattooScene(SherlockEngine *vm) : Scene(vm), _labWidget(vm) {
 	_labTableScene = false;
 }
 
-bool TattooScene::loadScene(const Common::String &filename) {
+bool TattooScene::loadScene(const Common::Path &filename) {
 	TattooEngine &vm = *(TattooEngine *)_vm;
 	Events &events = *_vm->_events;
 	Music &music = *_vm->_music;
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
index c1c2c948a4e..61dff7424ed 100644
--- a/engines/sherlock/tattoo/tattoo_scene.h
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -75,7 +75,7 @@ protected:
 	 * The _misc field of the structures contains the number of the graphic image
 	 * that it should point to after loading; _misc is then set to 0.
 	 */
-	bool loadScene(const Common::String &filename) override;
+	bool loadScene(const Common::Path &filename) override;
 
 	/**
 	 * Checks all the background shapes. If a background shape is animating,
diff --git a/engines/sherlock/tattoo/tattoo_talk.cpp b/engines/sherlock/tattoo/tattoo_talk.cpp
index 57b4003f7b0..3d1cc8320a6 100644
--- a/engines/sherlock/tattoo/tattoo_talk.cpp
+++ b/engines/sherlock/tattoo/tattoo_talk.cpp
@@ -182,7 +182,7 @@ TattooTalk::TattooTalk(SherlockEngine *vm) : Talk(vm), _talkWidget(vm), _passwor
 	_opcodeTable = OPCODE_METHODS;
 }
 
-void TattooTalk::talkTo(const Common::String filename) {
+void TattooTalk::talkTo(const Common::String &filename) {
 	Events &events = *_vm->_events;
 	TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
 
@@ -728,11 +728,12 @@ OpcodeReturn TattooTalk::cmdSetNPCWalkGraphics(const byte *&str) {
 	Person &person = people[npcNum];
 
 	// Build up walk library name for the given NPC
-	person._walkVGSName = "";
+	Common::String walkVGSName;
 	for (int idx = 0; idx < 8 && str[idx + 1] != '~'; ++idx)
-		person._walkVGSName += str[idx + 1];
+		walkVGSName += str[idx + 1];
 
-	person._walkVGSName += ".VGS";
+	walkVGSName += ".VGS";
+	person._walkVGSName = Common::Path(walkVGSName);
 	people._forceWalkReload = true;
 	str += 8;
 
diff --git a/engines/sherlock/tattoo/tattoo_talk.h b/engines/sherlock/tattoo/tattoo_talk.h
index d40d8025dbd..8cb8a14b8fa 100644
--- a/engines/sherlock/tattoo/tattoo_talk.h
+++ b/engines/sherlock/tattoo/tattoo_talk.h
@@ -111,7 +111,7 @@ public:
 	 *	In their case, the conversation display is simply suppressed, and control is passed on to
 	 *	doScript to implement whatever action is required.
 	 */
-	void talkTo(const Common::String filename) override;
+	void talkTo(const Common::String &filename) override;
 
 	/**
 	 * Push the details of a passed object onto the saved sequences stack
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index 2a7321bbd36..ab3a13c470f 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -137,7 +137,7 @@ void TattooUserInterface::lookAtObject() {
 							if (!soundName.contains('.'))
 								soundName += ".wav";
 
-							sound.playSound(soundName, WAIT_RETURN_IMMEDIATELY);
+							sound.playSound(Common::Path(soundName), WAIT_RETURN_IMMEDIATELY);
 						}
 
 						break;


Commit: 98dc1933a56abdac8461bf118a5b2dc63a03e370
    https://github.com/scummvm/scummvm/commit/98dc1933a56abdac8461bf118a5b2dc63a03e370
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SKY: Migrate engine to Path

Changed paths:
    engines/sky/music/musicbase.cpp


diff --git a/engines/sky/music/musicbase.cpp b/engines/sky/music/musicbase.cpp
index d716e1c3ce5..92cd8359d28 100644
--- a/engines/sky/music/musicbase.cpp
+++ b/engines/sky/music/musicbase.cpp
@@ -118,7 +118,7 @@ void MusicBase::loadNewMusic() {
 		section = 4;
 		song = 4;
 	}
-	Common::String trackName = Common::String::format("music_%d%02d", section, song);
+	Common::Path trackName(Common::String::format("music_%d%02d", section, song));
 	Audio::SeekableAudioStream *stream = Audio::SeekableAudioStream::openStreamFile(trackName);
 	if (stream) {
 		// not all tracks should loop


Commit: 6ad766f8d8eee4f2154a56150b5766d3324b9fcc
    https://github.com/scummvm/scummvm/commit/6ad766f8d8eee4f2154a56150b5766d3324b9fcc
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SLUDGE: Migrate engine to Path

Changed paths:
    engines/sludge/builtin.cpp
    engines/sludge/detection.cpp
    engines/sludge/fileset.cpp
    engines/sludge/floor.cpp
    engines/sludge/imgloader.cpp
    engines/sludge/sludger.cpp


diff --git a/engines/sludge/builtin.cpp b/engines/sludge/builtin.cpp
index 4faacf3e9ef..7e10ff54837 100644
--- a/engines/sludge/builtin.cpp
+++ b/engines/sludge/builtin.cpp
@@ -250,7 +250,7 @@ builtIn(fileExists) {
 	bool exist = false;
 
 	Common::File fd;
-	if (fd.open(aaaaa)) {
+	if (fd.open(Common::Path(aaaaa))) {
 		exist = true;
 		fd.close();
 	} else {
@@ -884,7 +884,8 @@ builtIn(launch) {
 		return BR_CONTINUE;
 	}
 
-	Common::String gameDir = ConfMan.get("path");
+	// Convert game path to URL
+	Common::String gameDir = ConfMan.getPath("path").toString('/');
 	newText = gameDir + newText;
 
 	// local webpage?
@@ -2386,7 +2387,7 @@ builtIn(_rem_launchWith) {
 	trimStack(fun->stack);
 
 	if (filename.hasSuffix(".exe")) {
-		const Common::FSNode gameDataDir(ConfMan.get("path"));
+		const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 		Common::FSList files;
 		gameDataDir.getChildren(files, Common::FSNode::kListFilesOnly);
 
diff --git a/engines/sludge/detection.cpp b/engines/sludge/detection.cpp
index 3403578d477..096bd58ef04 100644
--- a/engines/sludge/detection.cpp
+++ b/engines/sludge/detection.cpp
@@ -115,9 +115,9 @@ ADDetectedGame SludgeMetaEngineDetection::fallbackDetect(const FileMap &allFiles
 		if (file->isDirectory())
 			continue;
 
-		Common::String fileName = file->getName();
+		Common::Path fileName = file->getPathInArchive();
 		fileName.toLowercase();
-		if (!(fileName.hasSuffix(".slg") || fileName == "gamedata"))
+		if (!(fileName.baseName().hasSuffix(".slg") || fileName == "gamedata"))
 			continue;
 
 		Common::File f;
@@ -141,7 +141,7 @@ ADDetectedGame SludgeMetaEngineDetection::fallbackDetect(const FileMap &allFiles
 			continue;
 		}
 
-		strncpy(s_fallbackFileNameBuffer, fileName.c_str(), 50);
+		strncpy(s_fallbackFileNameBuffer, fileName.toString('/').c_str(), 50);
 		s_fallbackFileNameBuffer[50] = '\0';
 		s_fallbackDesc.desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer;
 
diff --git a/engines/sludge/fileset.cpp b/engines/sludge/fileset.cpp
index fed753b1f14..c1c3bb88312 100644
--- a/engines/sludge/fileset.cpp
+++ b/engines/sludge/fileset.cpp
@@ -223,7 +223,7 @@ void ResourceManager::dumpFile(int num, const char *pattern) {
 		return;
 
 	Common::DumpFile dumpFile;
-	dumpFile.open(Common::String("dumps/") + Common::String::format(pattern, num));
+	dumpFile.open(Common::Path("dumps/").appendComponent(Common::String::format(pattern, num)));
 	uint32 pos = _bigDataFile->pos();
 
 	_bigDataFile->seek(_startOfDataIndex + (num << 2), 0);
diff --git a/engines/sludge/floor.cpp b/engines/sludge/floor.cpp
index 075d11d6982..15ca48951e8 100644
--- a/engines/sludge/floor.cpp
+++ b/engines/sludge/floor.cpp
@@ -258,7 +258,7 @@ void FloorManager::dumpFloor(int fileNum) {
 		return;
 
 	Common::DumpFile dumpFile;
-	dumpFile.open(Common::String::format("dumps/floor%04d.flo", fileNum));
+	dumpFile.open(Common::Path(Common::String::format("dumps/floor%04d.flo", fileNum)));
 
 	for (int i = 0; i < _currentFloor->numPolygons; i++) {
 		int nV = _currentFloor->polygon[i].numVertices;
diff --git a/engines/sludge/imgloader.cpp b/engines/sludge/imgloader.cpp
index bd71aff17ed..51525d1a755 100644
--- a/engines/sludge/imgloader.cpp
+++ b/engines/sludge/imgloader.cpp
@@ -58,12 +58,12 @@ bool ImgLoader::loadImage(int num, const char *fname, Common::SeekableReadStream
 	if (dumpPng || (fname && num == -1)) {
 		// Debug code to output light map image
 		Common::DumpFile *outFile = new Common::DumpFile();
-		Common::String outName;
+		Common::Path outName;
 
 		if (dumpPng)
-			outName = Common::String::format("dumps/%s%04d.png", fname, num);
+			outName = Common::Path(Common::String::format("dumps/%s%04d.png", fname, num));
 		else
-			outName = Common::String::format("dumps/%s.png", fname);
+			outName = Common::Path(Common::String::format("dumps/%s.png", fname));
 
 		outFile->open(outName);
 		Image::writePNG(*outFile, *dest);
diff --git a/engines/sludge/sludger.cpp b/engines/sludge/sludger.cpp
index bd0729089bc..caa5e7e52fe 100644
--- a/engines/sludge/sludger.cpp
+++ b/engines/sludge/sludger.cpp
@@ -67,7 +67,7 @@ extern bool allowAnyFilename;
 Common::File *openAndVerify(const Common::String &filename, char extra1, char extra2,
 		const char *er, int &fileVersion) {
 	Common::File *fp = new Common::File();
-	if (!fp->open(filename)) {
+	if (!fp->open(Common::Path(filename))) {
 		fatal("Can't open file", filename);
 		return NULL;
 	}


Commit: 03331e69649f63b4ef35dcee3040d47e75ac6b09
    https://github.com/scummvm/scummvm/commit/03331e69649f63b4ef35dcee3040d47e75ac6b09
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
STARK: Migrate engine to Path

Changed paths:
    engines/stark/console.cpp
    engines/stark/formats/xarc.cpp
    engines/stark/formats/xarc.h
    engines/stark/formats/xrc.cpp
    engines/stark/formats/xrc.h
    engines/stark/resources/anim.cpp
    engines/stark/resources/anim.h
    engines/stark/resources/bonesmesh.cpp
    engines/stark/resources/bonesmesh.h
    engines/stark/resources/fmv.cpp
    engines/stark/resources/fmv.h
    engines/stark/resources/image.cpp
    engines/stark/resources/image.h
    engines/stark/resources/sound.cpp
    engines/stark/resources/sound.h
    engines/stark/resources/textureset.cpp
    engines/stark/resources/textureset.h
    engines/stark/services/archiveloader.cpp
    engines/stark/services/archiveloader.h
    engines/stark/services/diary.cpp
    engines/stark/services/diary.h
    engines/stark/services/fontprovider.cpp
    engines/stark/services/gamechapter.cpp
    engines/stark/services/resourceprovider.cpp
    engines/stark/services/staticprovider.cpp
    engines/stark/services/staticprovider.h
    engines/stark/services/userinterface.cpp
    engines/stark/services/userinterface.h
    engines/stark/stark.cpp
    engines/stark/ui/menu/fmvmenu.h
    engines/stark/ui/world/fmvscreen.cpp
    engines/stark/ui/world/fmvscreen.h


diff --git a/engines/stark/console.cpp b/engines/stark/console.cpp
index 908143ee422..9045ede317b 100644
--- a/engines/stark/console.cpp
+++ b/engines/stark/console.cpp
@@ -94,12 +94,12 @@ bool Console::Cmd_DumpArchive(int argc, const char **argv) {
 	xarc.listMembers(members);
 
 	for (Common::ArchiveMemberList::const_iterator it = members.begin(); it != members.end(); it++) {
-		Common::String fileName = Common::String::format("dump/%s", it->get()->getName().c_str());
+		Common::Path fileName(Common::String::format("dump/%s", it->get()->getName().c_str()));
 
 		// Open the output file
 		Common::DumpFile outFile;
 		if (!outFile.open(fileName, true)) {
-			debugPrintf("Unable to open file '%s' for writing\n", fileName.c_str());
+			debugPrintf("Unable to open file '%s' for writing\n", fileName.toString().c_str());
 			return true;
 		}
 
@@ -387,8 +387,8 @@ void Console::walkAllArchives(ArchiveVisitor *visitor) {
 	for (uint i = 0; i < levels.size(); i++) {
 		Resources::Level *level = levels[i];
 
-		Common::String levelArchive = archiveLoader->buildArchiveName(level);
-		debug("%s - %s", levelArchive.c_str(), level->getName().c_str());
+		Common::Path levelArchive = archiveLoader->buildArchiveName(level);
+		debug("%s - %s", levelArchive.toString(Common::Path::kNativeSeparator).c_str(), level->getName().c_str());
 
 		// Load the detailed level archive
 		archiveLoader->load(levelArchive);
@@ -403,8 +403,8 @@ void Console::walkAllArchives(ArchiveVisitor *visitor) {
 		for (uint j = 0; j < locations.size(); j++) {
 			Resources::Location *location = locations[j];
 
-			Common::String locationArchive = archiveLoader->buildArchiveName(level, location);
-			debug("%s - %s", locationArchive.c_str(), location->getName().c_str());
+			Common::Path locationArchive = archiveLoader->buildArchiveName(level, location);
+			debug("%s - %s", locationArchive.toString(Common::Path::kNativeSeparator).c_str(), location->getName().c_str());
 
 			// Load the detailed location archive
 			archiveLoader->load(locationArchive);
@@ -648,8 +648,8 @@ bool Console::Cmd_ListLocations(int argc, const char **argv) {
 	for (uint i = 0; i < levels.size(); i++) {
 		Resources::Level *level = levels[i];
 
-		Common::String levelArchive = archiveLoader->buildArchiveName(level);
-		debugPrintf("%s - %s\n", levelArchive.c_str(), level->getName().c_str());
+		Common::Path levelArchive = archiveLoader->buildArchiveName(level);
+		debugPrintf("%s - %s\n", levelArchive.toString(Common::Path::kNativeSeparator).c_str(), level->getName().c_str());
 
 		// Load the detailed level archive
 		archiveLoader->load(levelArchive);
@@ -661,8 +661,8 @@ bool Console::Cmd_ListLocations(int argc, const char **argv) {
 		for (uint j = 0; j < locations.size(); j++) {
 			Resources::Location *location = locations[j];
 
-			Common::String roomArchive = archiveLoader->buildArchiveName(level, location);
-			debugPrintf("%s - %s\n", roomArchive.c_str(), location->getName().c_str());
+			Common::Path roomArchive = archiveLoader->buildArchiveName(level, location);
+			debugPrintf("%s - %s\n", roomArchive.toString(Common::Path::kNativeSeparator).c_str(), location->getName().c_str());
 		}
 
 		archiveLoader->returnRoot(levelArchive);
@@ -680,7 +680,7 @@ bool Console::Cmd_ListLocations(int argc, const char **argv) {
 bool Console::Cmd_ChangeLocation(int argc, const char **argv) {
 	if (argc >= 3) {
 		// Assert indices
-		Common::String xarcFileName = Common::String::format("%s/%s/%s.xarc", argv[1], argv[2], argv[2]);
+		Common::Path xarcFileName(Common::String::format("%s/%s/%s.xarc", argv[1], argv[2], argv[2]));
 		if (!Common::File::exists(xarcFileName)) {
 			debugPrintf("Invalid location %s %s. Use listLocations to get correct indices\n", argv[1], argv[2]);
 			return true;
diff --git a/engines/stark/formats/xarc.cpp b/engines/stark/formats/xarc.cpp
index b3d7687d678..0682923c7f6 100644
--- a/engines/stark/formats/xarc.cpp
+++ b/engines/stark/formats/xarc.cpp
@@ -40,15 +40,15 @@ public:
 
 	Common::SeekableReadStream *createReadStream() const override;
 	Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
-	Common::String getName() const override { return _name; }
+	Common::String getName() const override { return _name.baseName(); }
 	Common::Path getPathInArchive() const override { return _name; }
-	Common::String getFileName() const override { return _name; }
+	Common::String getFileName() const override { return _name.baseName(); }
 	uint32 getLength() const { return _length; }
 	uint32 getOffset() const { return _offset; }
 
 private:
 	const XARCArchive *_xarc;
-	Common::String _name;
+	Common::Path _name;
 	uint32 _offset;
 	uint32 _length;
 
@@ -60,16 +60,16 @@ XARCMember::XARCMember(const XARCArchive *xarc, Common::ReadStream &stream, uint
 	_xarc = xarc;
 
 	// Read the information about this archive member
-	_name = readString(stream);
+	_name = Common::Path(readString(stream));
 	_offset = offset;
 	_length = stream.readUint32LE();
-	debugC(20, kDebugArchive, "Stark::XARC Member: \"%s\" starts at offset=%d and has length=%d", _name.c_str(), _offset, _length);
+	debugC(20, kDebugArchive, "Stark::XARC Member: \"%s\" starts at offset=%d and has length=%d", _name.toString().c_str(), _offset, _length);
 
 	// Unknown value. English: 0, others: 1
 	uint32 unknown = stream.readUint32LE();
-	debugC(kDebugUnknown, "Stark::XARC Member: \"%s\" has unknown=%d", _name.c_str(), unknown);
+	debugC(kDebugUnknown, "Stark::XARC Member: \"%s\" has unknown=%d", _name.toString().c_str(), unknown);
 	if (unknown != 0 && unknown != 1) {
-		warning("Stark::XARC Member: \"%s\" has unknown=%d with unknown meaning", _name.c_str(), unknown);
+		warning("Stark::XARC Member: \"%s\" has unknown=%d with unknown meaning", _name.toString().c_str(), unknown);
 	}
 }
 
@@ -102,7 +102,7 @@ Common::String XARCMember::readString(Common::ReadStream &stream) {
 
 // ARCHIVE
 
-bool XARCArchive::open(const Common::String &filename) {
+bool XARCArchive::open(const Common::Path &filename) {
 	Common::File stream;
 	if (!stream.open(filename)) {
 		return false;
@@ -112,18 +112,18 @@ bool XARCArchive::open(const Common::String &filename) {
 
 	// Unknown: always 1? version?
 	uint32 unknown = stream.readUint32LE();
-	debugC(kDebugUnknown, "Stark::XARC: \"%s\" has unknown=%d", _filename.c_str(), unknown);
+	debugC(kDebugUnknown, "Stark::XARC: \"%s\" has unknown=%d", _filename.toString(Common::Path::kNativeSeparator).c_str(), unknown);
 	if (unknown != 1) {
-		warning("Stark::XARC: \"%s\" has unknown=%d with unknown meaning", _filename.c_str(), unknown);
+		warning("Stark::XARC: \"%s\" has unknown=%d with unknown meaning", _filename.toString(Common::Path::kNativeSeparator).c_str(), unknown);
 	}
 
 	// Read the number of contained files
 	uint32 numFiles = stream.readUint32LE();
-	debugC(20, kDebugArchive, "Stark::XARC: \"%s\" contains %d files", _filename.c_str(), numFiles);
+	debugC(20, kDebugArchive, "Stark::XARC: \"%s\" contains %d files", _filename.toString(Common::Path::kNativeSeparator).c_str(), numFiles);
 
 	// Read the offset to the contents of the first file
 	uint32 offset = stream.readUint32LE();
-	debugC(20, kDebugArchive, "Stark::XARC: \"%s\"'s first file has offset=%d", _filename.c_str(), offset);
+	debugC(20, kDebugArchive, "Stark::XARC: \"%s\"'s first file has offset=%d", _filename.toString(Common::Path::kNativeSeparator).c_str(), offset);
 
 	for (uint32 i = 0; i < numFiles; i++) {
 		XARCMember *member = new XARCMember(this, stream, offset);
@@ -136,7 +136,7 @@ bool XARCArchive::open(const Common::String &filename) {
 	return true;
 }
 
-Common::String XARCArchive::getFilename() const {
+Common::Path XARCArchive::getFilename() const {
 	return _filename;
 }
 
diff --git a/engines/stark/formats/xarc.h b/engines/stark/formats/xarc.h
index d7cc70a365d..7ee5ac9d8a2 100644
--- a/engines/stark/formats/xarc.h
+++ b/engines/stark/formats/xarc.h
@@ -32,8 +32,8 @@ class XARCMember;
 
 class XARCArchive : public Common::Archive {
 public:
-	bool open(const Common::String &filename);
-	Common::String getFilename() const;
+	bool open(const Common::Path &filename);
+	Common::Path getFilename() const;
 
 	// Archive API
 	bool hasFile(const Common::Path &path) const;
@@ -45,7 +45,7 @@ public:
 	Common::SeekableReadStream *createReadStreamForMember(const XARCMember *member) const;
 
 private:
-	Common::String _filename;
+	Common::Path _filename;
 	Common::ArchiveMemberList _members;
 };
 
diff --git a/engines/stark/formats/xrc.cpp b/engines/stark/formats/xrc.cpp
index a4c6f86854e..3bebd5e81f1 100644
--- a/engines/stark/formats/xrc.cpp
+++ b/engines/stark/formats/xrc.cpp
@@ -60,7 +60,7 @@
 namespace Stark {
 namespace Formats {
 
-XRCReadStream::XRCReadStream(const Common::String &archiveName,
+XRCReadStream::XRCReadStream(const Common::Path &archiveName,
 		Common::SeekableReadStream *parentStream, DisposeAfterUse::Flag disposeParentStream) :
 		SeekableSubReadStream(parentStream, 0, parentStream->size(), disposeParentStream),
 		_archiveName(archiveName) {
@@ -126,7 +126,7 @@ bool XRCReadStream::isDataLeft() {
 	return pos() < size();
 }
 
-Common::String XRCReadStream::getArchiveName() const {
+Common::Path XRCReadStream::getArchiveName() const {
 	return _archiveName;
 }
 
@@ -135,14 +135,14 @@ Resources::Object *XRCReader::importTree(XARCArchive *archive) {
 	Common::ArchiveMemberList members;
 	archive->listMatchingMembers(members, "*.xrc");
 	if (members.size() == 0) {
-		error("No resource tree in archive '%s'", archive->getFilename().c_str());
+		error("No resource tree in archive '%s'", archive->getFilename().toString(Common::Path::kNativeSeparator).c_str());
 	}
 	if (members.size() > 1) {
-		error("Too many resource scripts in archive '%s'", archive->getFilename().c_str());
+		error("Too many resource scripts in archive '%s'", archive->getFilename().toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	// Open the XRC file
-	Common::SeekableReadStream *stream = archive->createReadStreamForMember(members.front()->getName());
+	Common::SeekableReadStream *stream = archive->createReadStreamForMember(members.front()->getPathInArchive());
 	XRCReadStream *xrcStream = new XRCReadStream(archive->getFilename(), stream);
 
 	// Import the resource tree
diff --git a/engines/stark/formats/xrc.h b/engines/stark/formats/xrc.h
index aa08844310d..ab2e27d79be 100644
--- a/engines/stark/formats/xrc.h
+++ b/engines/stark/formats/xrc.h
@@ -44,11 +44,11 @@ class XARCArchive;
  */
 class XRCReadStream : public Common::SeekableSubReadStream {
 public:
-	XRCReadStream(const Common::String &archiveName, Common::SeekableReadStream *parentStream, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::YES);
+	XRCReadStream(const Common::Path &archiveName, Common::SeekableReadStream *parentStream, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::YES);
 	virtual ~XRCReadStream();
 
 	/** Obtain the file name of the archive containing the XRC tree */
-	Common::String getArchiveName() const;
+	Common::Path getArchiveName() const;
 
 	Common::String readString();
 	Resources::Type readResourceType();
@@ -60,7 +60,7 @@ public:
 	bool isDataLeft();
 
 private:
-	Common::String _archiveName;
+	Common::Path _archiveName;
 };
 
 /**
diff --git a/engines/stark/resources/anim.cpp b/engines/stark/resources/anim.cpp
index 2753f6b13d3..f56b71d5a38 100644
--- a/engines/stark/resources/anim.cpp
+++ b/engines/stark/resources/anim.cpp
@@ -235,7 +235,7 @@ void AnimProp::readData(Formats::XRCReadStream *stream) {
 
 	uint32 meshCount = stream->readUint32LE();
 	for (uint i = 0; i < meshCount; i++) {
-		_meshFilenames.push_back(stream->readString());
+		_meshFilenames.push_back(Common::Path(stream->readString()));
 	}
 
 	_textureFilename = stream->readString();
@@ -264,9 +264,9 @@ void AnimProp::printData() {
 
 	Common::String description;
 	for (uint32 i = 0; i < _meshFilenames.size(); i++) {
-		debug("meshFilename[%d]: %s", i, _meshFilenames[i].c_str());
+		debug("meshFilename[%d]: %s", i, _meshFilenames[i].toString().c_str());
 	}
-	debug("textureFilename: %s", _textureFilename.c_str());
+	debug("textureFilename: %s", _textureFilename.toString().c_str());
 	debug("movementSpeed: %d", _movementSpeed);
 }
 
@@ -352,21 +352,23 @@ void AnimVideo::onAllLoaded() {
 }
 
 Common::SeekableReadStream *AnimVideo::openOverrideFile(const Common::String &extension) const {
-	if (!_smackerFile.hasSuffixIgnoreCase(".sss")) {
+	Common::String baseName(_smackerFile.baseName());
+	if (!baseName.hasSuffixIgnoreCase(".sss")) {
 		return nullptr;
 	}
+	baseName = Common::String(baseName.c_str(), baseName.size() - 4) + extension;
 
-	Common::String filename = Common::String(_smackerFile.c_str(), _smackerFile.size() - 4) + extension;
-	Common::String filePath = StarkArchiveLoader->getExternalFilePath(filename, _archiveName);
+	Common::Path filePath(_smackerFile.getParent().appendComponent(baseName));
+	filePath = StarkArchiveLoader->getExternalFilePath(filePath, _archiveName);
 
-	debugC(kDebugModding, "Attempting to load %s", filePath.c_str());
+	debugC(kDebugModding, "Attempting to load %s", filePath.toString(Common::Path::kNativeSeparator).c_str());
 
 	Common::SeekableReadStream *smkStream = SearchMan.createReadStreamForMember(filePath);
 	if (!smkStream) {
 		return nullptr;
 	}
 
-	debugC(kDebugModding, "Loaded %s", filePath.c_str());
+	debugC(kDebugModding, "Loaded %s", filePath.toString(Common::Path::kNativeSeparator).c_str());
 
 	return smkStream;
 }
@@ -463,7 +465,7 @@ void AnimVideo::saveLoadCurrent(ResourceSerializer *serializer) {
 void AnimVideo::printData() {
 	Anim::printData();
 
-	debug("smackerFile: %s", _smackerFile.c_str());
+	debug("smackerFile: %s", _smackerFile.toString().c_str());
 	debug("size: x %d, y %d", _width, _height);
 
 	Common::String description;
@@ -664,7 +666,7 @@ uint32 AnimSkeleton::getIdleActionFrequency() const {
 void AnimSkeleton::printData() {
 	Anim::printData();
 
-	debug("filename: %s", _animFilename.c_str());
+	debug("filename: %s", _animFilename.toString().c_str());
 	debug("castsShadow: %d", _castsShadow);
 	debug("loop: %d", _loop);
 	debug("movementSpeed: %d", _movementSpeed);
diff --git a/engines/stark/resources/anim.h b/engines/stark/resources/anim.h
index 1470de45422..c7010fa5899 100644
--- a/engines/stark/resources/anim.h
+++ b/engines/stark/resources/anim.h
@@ -215,10 +215,10 @@ protected:
 	void printData() override;
 
 	Common::String _field_3C;
-	Common::Array<Common::String> _meshFilenames;
-	Common::String _textureFilename;
+	Common::Array<Common::Path> _meshFilenames;
+	Common::Path _textureFilename;
 	uint32 _movementSpeed;
-	Common::String _archiveName;
+	Common::Path _archiveName;
 
 	VisualProp *_visual;
 };
@@ -256,8 +256,8 @@ protected:
 	/** Update the position of the video for the current frame */
 	void updateSmackerPosition();
 
-	Common::String _smackerFile;
-	Common::String _archiveName;
+	Common::Path _smackerFile;
+	Common::Path _archiveName;
 
 	VisualSmacker *_smacker;
 
@@ -313,8 +313,8 @@ protected:
 	void printData() override;
 
 	bool _castsShadow;
-	Common::String _archiveName;
-	Common::String _animFilename;
+	Common::Path _archiveName;
+	Common::Path _animFilename;
 	bool _loop;
 	uint32 _movementSpeed;
 	uint32 _idleActionFrequency;
diff --git a/engines/stark/resources/bonesmesh.cpp b/engines/stark/resources/bonesmesh.cpp
index f164e4045a8..c5f11f85cd3 100644
--- a/engines/stark/resources/bonesmesh.cpp
+++ b/engines/stark/resources/bonesmesh.cpp
@@ -41,7 +41,7 @@ BonesMesh::BonesMesh(Object *parent, byte subType, uint16 index, const Common::S
 }
 
 void BonesMesh::readData(Formats::XRCReadStream *stream) {
-	_filename = stream->readString();
+	_filename = Common::Path(stream->readString());
 	_archiveName = stream->getArchiveName();
 }
 
@@ -59,7 +59,7 @@ Model *BonesMesh::getModel() {
 }
 
 void BonesMesh::printData() {
-	debug("filename: %s", _filename.c_str());
+	debug("filename: %s", _filename.toString().c_str());
 }
 
 } // End of namespace Resources
diff --git a/engines/stark/resources/bonesmesh.h b/engines/stark/resources/bonesmesh.h
index c8141fe44f3..761242d8094 100644
--- a/engines/stark/resources/bonesmesh.h
+++ b/engines/stark/resources/bonesmesh.h
@@ -22,6 +22,7 @@
 #ifndef STARK_RESOURCES_BONES_MESH_H
 #define STARK_RESOURCES_BONES_MESH_H
 
+#include "common/path.h"
 #include "common/str.h"
 
 #include "engines/stark/resources/object.h"
@@ -56,8 +57,8 @@ public:
 protected:
 	void printData() override;
 
-	Common::String _filename;
-	Common::String _archiveName;
+	Common::Path _filename;
+	Common::Path _archiveName;
 
 	Model *_model;
 };
diff --git a/engines/stark/resources/fmv.cpp b/engines/stark/resources/fmv.cpp
index b2d80e99872..61be11b158b 100644
--- a/engines/stark/resources/fmv.cpp
+++ b/engines/stark/resources/fmv.cpp
@@ -41,7 +41,7 @@ FMV::FMV(Object *parent, byte subType, uint16 index, const Common::String &name)
 }
 
 void FMV::readData(Formats::XRCReadStream *stream) {
-	_filename = stream->readString();
+	_filename = Common::Path(stream->readString());
 	_diaryAddEntryOnPlay = stream->readBool();
 	_gameDisc = stream->readUint32LE();
 }
@@ -55,7 +55,7 @@ void FMV::requestPlayback() {
 }
 
 void FMV::printData() {
-	debug("filename: %s", _filename.c_str());
+	debug("filename: %s", _filename.toString().c_str());
 	debug("diaryAddEntryOnPlay: %d", _diaryAddEntryOnPlay);
 	debug("gameDisc: %d", _gameDisc);
 }
diff --git a/engines/stark/resources/fmv.h b/engines/stark/resources/fmv.h
index 63aaad10a5d..84f186c0486 100644
--- a/engines/stark/resources/fmv.h
+++ b/engines/stark/resources/fmv.h
@@ -22,6 +22,7 @@
 #ifndef STARK_RESOURCES_FMV_H
 #define STARK_RESOURCES_FMV_H
 
+#include "common/path.h"
 #include "common/str.h"
 
 #include "engines/stark/resources/object.h"
@@ -53,7 +54,7 @@ public:
 protected:
 	void printData() override;
 
-	Common::String _filename;
+	Common::Path _filename;
 	bool _diaryAddEntryOnPlay;
 	uint32 _gameDisc;
 };
diff --git a/engines/stark/resources/image.cpp b/engines/stark/resources/image.cpp
index d63c54bf7d0..2d6fb0c677e 100644
--- a/engines/stark/resources/image.cpp
+++ b/engines/stark/resources/image.cpp
@@ -96,7 +96,7 @@ Visual *Image::getVisual() {
 }
 
 void Image::printData() {
-	debug("filename: %s", _filename.c_str());
+	debug("filename: %s", _filename.toString().c_str());
 	debug("hotspot: x %d, y %d", _hotspot.x, _hotspot.y);
 	debug("transparent: %d", _transparent);
 	debug("transparentColor: %d", _transparentColor);
@@ -230,14 +230,16 @@ void ImageStill::initVisual() {
 }
 
 bool ImageStill::loadPNGOverride(VisualImageXMG *visual) const {
-	if (!_filename.hasSuffixIgnoreCase(".xmg")) {
+	if (!_filename.baseName().hasSuffixIgnoreCase(".xmg")) {
 		return false;
 	}
 
-	Common::String pngFilename = Common::String(_filename.c_str(), _filename.size() - 4) + ".png";
-	Common::String pngFilePath = StarkArchiveLoader->getExternalFilePath(pngFilename, _archiveName);
+	Common::String pngFilename = _filename.baseName();
+	pngFilename = Common::String(pngFilename.c_str(), pngFilename.size() - 4) + ".png";
+	Common::Path pngFilePath = _filename.getParent().appendComponent(pngFilename);
+	pngFilePath = StarkArchiveLoader->getExternalFilePath(pngFilePath, _archiveName);
 
-	debugC(kDebugModding, "Attempting to load %s", pngFilePath.c_str());
+	debugC(kDebugModding, "Attempting to load %s", pngFilePath.toString(Common::Path::kNativeSeparator).c_str());
 
 	Common::SeekableReadStream *pngStream = SearchMan.createReadStreamForMember(pngFilePath);
 	if (!pngStream) {
@@ -245,12 +247,12 @@ bool ImageStill::loadPNGOverride(VisualImageXMG *visual) const {
 	}
 
 	if (!visual->loadPNG(pngStream)) {
-		warning("Failed to load %s. It is not a valid PNG file.", pngFilePath.c_str());
+		warning("Failed to load %s. It is not a valid PNG file.", pngFilePath.toString(Common::Path::kNativeSeparator).c_str());
 		delete pngStream;
 		return false;
 	}
 
-	debugC(kDebugModding, "Loaded %s", pngFilePath.c_str());
+	debugC(kDebugModding, "Loaded %s", pngFilePath.toString(Common::Path::kNativeSeparator).c_str());
 
 	delete pngStream;
 	return true;
diff --git a/engines/stark/resources/image.h b/engines/stark/resources/image.h
index e2c5bd1e53d..41fb8ce67eb 100644
--- a/engines/stark/resources/image.h
+++ b/engines/stark/resources/image.h
@@ -78,8 +78,8 @@ protected:
 
 	virtual void initVisual() = 0;
 
-	Common::String _filename;
-	Common::String _archiveName;
+	Common::Path _filename;
+	Common::Path _archiveName;
 
 	Visual *_visual;
 
diff --git a/engines/stark/resources/sound.cpp b/engines/stark/resources/sound.cpp
index d614b8040df..527f227b1ea 100644
--- a/engines/stark/resources/sound.cpp
+++ b/engines/stark/resources/sound.cpp
@@ -76,9 +76,11 @@ Audio::RewindableAudioStream *Sound::makeAudioStream() {
 
 	if (!audioStream) {
 		// The 2 CD version uses Ogg Vorbis
-		Common::String filename = _filename;
-		if (_filename.hasSuffix(".iss") || _filename.hasSuffix(".isn")) {
-			filename = Common::String(_filename.c_str(), _filename.size() - 4) + ".ovs";
+		Common::Path filename = _filename;
+		Common::String baseName(filename.baseName());
+		if (baseName.hasSuffix(".iss") || baseName.hasSuffix(".isn")) {
+			baseName = Common::String(baseName.c_str(), baseName.size() - 4) + ".ovs";
+			filename = _filename.getParent().appendComponent(baseName);
 		}
 
 		stream = StarkArchiveLoader->getExternalFile(filename, _archiveName);
@@ -86,14 +88,14 @@ Audio::RewindableAudioStream *Sound::makeAudioStream() {
 #ifdef USE_VORBIS
 			audioStream = Audio::makeVorbisStream(stream, DisposeAfterUse::YES);
 #else
-			warning("Cannot decode sound '%s', Vorbis support is not compiled in", filename.c_str());
+			warning("Cannot decode sound '%s', Vorbis support is not compiled in", filename.toString().c_str());
 			delete stream;
 #endif
 		}
 	}
 
 	if (!audioStream) {
-		warning("Unable to load sound '%s'", _filename.c_str());
+		warning("Unable to load sound '%s'", _filename.toString().c_str());
 	}
 
 	return audioStream;
@@ -169,7 +171,7 @@ void Sound::readData(Formats::XRCReadStream *stream) {
 }
 
 void Sound::printData() {
-	debug("filename: %s", _filename.c_str());
+	debug("filename: %s", _filename.toString().c_str());
 	debug("enabled: %d", _enabled);
 	debug("looping: %d", _looping);
 	debug("field_64: %d", _field_64);
diff --git a/engines/stark/resources/sound.h b/engines/stark/resources/sound.h
index a20007b4ca4..973333965f2 100644
--- a/engines/stark/resources/sound.h
+++ b/engines/stark/resources/sound.h
@@ -24,6 +24,7 @@
 
 #include "audio/mixer.h"
 
+#include "common/path.h"
 #include "common/str.h"
 
 #include "engines/stark/resources/object.h"
@@ -98,8 +99,8 @@ protected:
 	Audio::RewindableAudioStream *makeAudioStream();
 	Audio::Mixer::SoundType getMixerSoundType();
 
-	Common::String _filename;
-	Common::String _archiveName;
+	Common::Path _filename;
+	Common::Path _archiveName;
 	uint32 _enabled;
 	bool _looping;
 	uint32 _field_64;
diff --git a/engines/stark/resources/textureset.cpp b/engines/stark/resources/textureset.cpp
index 81cf77d65e3..79793573c0d 100644
--- a/engines/stark/resources/textureset.cpp
+++ b/engines/stark/resources/textureset.cpp
@@ -56,7 +56,7 @@ Gfx::TextureSet *TextureSet::getTexture() {
 }
 
 void TextureSet::readData(Formats::XRCReadStream *stream) {
-	_filename = stream->readString();
+	_filename = Common::Path(stream->readString());
 	_archiveName = stream->getArchiveName();
 }
 
@@ -87,10 +87,10 @@ void TextureSet::extractArchive() {
 
 	Common::Array<Formats::Texture *> textures = archive->listObjectsRecursive<Formats::Texture>();
 	for (uint i = 0; i < textures.size(); i++) {
-		Common::String filename = Common::String::format(
+		Common::Path filename(Common::String::format(
 		            "dump/%s/%s.png",
-		            _filename.c_str(),
-		            stripExtension(textures[i]->getName()).c_str());
+		            _filename.baseName().c_str(),
+		            stripExtension(textures[i]->getName()).c_str()));
 
 		if (Common::File::exists(filename)) {
 			continue;
@@ -98,7 +98,7 @@ void TextureSet::extractArchive() {
 
 		Common::DumpFile out;
 		if (!out.open(filename, true)) {
-			warning("Unable to open file '%s' for writing", filename.c_str());
+			warning("Unable to open file '%s' for writing", filename.toString().c_str());
 			return;
 		}
 
@@ -117,9 +117,9 @@ void TextureSet::extractArchive() {
 }
 
 Gfx::TextureSet *TextureSet::readOverrideDdsArchive() {
-	Common::String archiveName = _filename + ".zip";
+	Common::Path archiveName = _filename.append(".zip");
 
-	debugC(kDebugModding, "Attempting to load %s", archiveName.c_str());
+	debugC(kDebugModding, "Attempting to load %s", archiveName.toString().c_str());
 
 	Common::Archive *archive = Common::makeZipArchive(archiveName);
 	if (!archive) {
@@ -129,7 +129,7 @@ Gfx::TextureSet *TextureSet::readOverrideDdsArchive() {
 	Common::ArchiveMemberList files;
 	archive->listMatchingMembers(files, "*.dds");
 	if (files.empty()) {
-		warning("No DDS files found in archive %s", archiveName.c_str());
+		warning("No DDS files found in archive %s", archiveName.toString().c_str());
 		delete archive;
 		return nullptr;
 	}
@@ -144,12 +144,12 @@ Gfx::TextureSet *TextureSet::readOverrideDdsArchive() {
 
 		Common::SeekableReadStream *ddsStream = (*it)->createReadStream();
 		if (!ddsStream) {
-			warning("Unable to open %s for reading in %s", (*it)->getName().c_str(), archiveName.c_str());
+			warning("Unable to open %s for reading in %s", (*it)->getName().c_str(), archiveName.toString().c_str());
 			continue;
 		}
 
 		Formats::DDS dds;
-		if (!dds.load(*ddsStream, name + " in " + archiveName)) {
+		if (!dds.load(*ddsStream, name + " in " + archiveName.toString('/'))) {
 			delete ddsStream;
 			continue;
 		}
@@ -187,7 +187,7 @@ Gfx::TextureSet *TextureSet::readOverrideDdsArchive() {
 		loadedCount++;
 	}
 
-	debugC(kDebugModding, "Loaded %d textures from %s", loadedCount, archiveName.c_str());
+	debugC(kDebugModding, "Loaded %d textures from %s", loadedCount, archiveName.toString().c_str());
 
 	delete archive;
 
@@ -195,7 +195,7 @@ Gfx::TextureSet *TextureSet::readOverrideDdsArchive() {
 }
 
 void TextureSet::printData() {
-	debug("filename: %s", _filename.c_str());
+	debug("filename: %s", _filename.toString().c_str());
 }
 
 } // End of namespace Resources
diff --git a/engines/stark/resources/textureset.h b/engines/stark/resources/textureset.h
index a6da580453d..bb678564568 100644
--- a/engines/stark/resources/textureset.h
+++ b/engines/stark/resources/textureset.h
@@ -22,6 +22,7 @@
 #ifndef STARK_RESOURCES_TEXTURE_SET_H
 #define STARK_RESOURCES_TEXTURE_SET_H
 
+#include "common/path.h"
 #include "common/str.h"
 
 #include "engines/stark/resources/object.h"
@@ -69,8 +70,8 @@ protected:
 	void printData() override;
 	Gfx::TextureSet *readOverrideDdsArchive();
 
-	Common::String _filename;
-	Common::String _archiveName;
+	Common::Path _filename;
+	Common::Path _archiveName;
 
 	Gfx::TextureSet *_textureSet;
 };
diff --git a/engines/stark/services/archiveloader.cpp b/engines/stark/services/archiveloader.cpp
index 02976464a36..3aae189a568 100644
--- a/engines/stark/services/archiveloader.cpp
+++ b/engines/stark/services/archiveloader.cpp
@@ -27,12 +27,12 @@
 
 namespace Stark {
 
-ArchiveLoader::LoadedArchive::LoadedArchive(const Common::String& archiveName) :
+ArchiveLoader::LoadedArchive::LoadedArchive(const Common::Path& archiveName) :
 		_filename(archiveName),
 		_root(nullptr),
 		_useCount(0) {
 	if (!_xarc.open(archiveName)) {
-		error("Unable to open archive '%s'", archiveName.c_str());
+		error("Unable to open archive '%s'", archiveName.toString(Common::Path::kNativeSeparator).c_str());
 	}
 }
 
@@ -54,7 +54,7 @@ ArchiveLoader::~ArchiveLoader() {
 	}
 }
 
-bool ArchiveLoader::load(const Common::String &archiveName) {
+bool ArchiveLoader::load(const Common::Path &archiveName) {
 	if (hasArchive(archiveName)) {
 		// Already loaded
 		return false;
@@ -78,7 +78,7 @@ void ArchiveLoader::unloadUnused() {
 	}
 }
 
-ArchiveReadStream *ArchiveLoader::getFile(const Common::String &fileName, const Common::String &archiveName) {
+ArchiveReadStream *ArchiveLoader::getFile(const Common::Path &fileName, const Common::Path &archiveName) {
 	LoadedArchive *archive = findArchive(archiveName);
 	const Formats::XARCArchive &xarc = archive->getXArc();
 
@@ -90,14 +90,14 @@ ArchiveReadStream *ArchiveLoader::getFile(const Common::String &fileName, const
 	return new ArchiveReadStream(stream);
 }
 
-bool ArchiveLoader::returnRoot(const Common::String &archiveName) {
+bool ArchiveLoader::returnRoot(const Common::Path &archiveName) {
 	LoadedArchive *archive = findArchive(archiveName);
 	archive->decUsage();
 
 	return !archive->isInUse();
 }
 
-bool ArchiveLoader::hasArchive(const Common::String &archiveName) const {
+bool ArchiveLoader::hasArchive(const Common::Path &archiveName) const {
 	for (LoadedArchiveList::const_iterator it = _archives.begin(); it != _archives.end(); it++) {
 		if ((*it)->getFilename() == archiveName) {
 			return true;
@@ -107,17 +107,17 @@ bool ArchiveLoader::hasArchive(const Common::String &archiveName) const {
 	return false;
 }
 
-ArchiveLoader::LoadedArchive *ArchiveLoader::findArchive(const Common::String &archiveName) const {
+ArchiveLoader::LoadedArchive *ArchiveLoader::findArchive(const Common::Path &archiveName) const {
 	for (LoadedArchiveList::const_iterator it = _archives.begin(); it != _archives.end(); it++) {
 		if ((*it)->getFilename() == archiveName) {
 			return *it;
 		}
 	}
 
-	error("The archive with name '%s' is not loaded.", archiveName.c_str());
+	error("The archive with name '%s' is not loaded.", archiveName.toString(Common::Path::kNativeSeparator).c_str());
 }
 
-Common::String ArchiveLoader::buildArchiveName(Resources::Level *level, Resources::Location *location) const {
+Common::Path ArchiveLoader::buildArchiveName(Resources::Level *level, Resources::Location *location) const {
 	Common::String archive;
 
 	if (!location) {
@@ -135,24 +135,23 @@ Common::String ArchiveLoader::buildArchiveName(Resources::Level *level, Resource
 		archive = Common::String::format("%02x/%02x/%02x.xarc", level->getIndex(), location->getIndex(), location->getIndex());
 	}
 
-	return archive;
+	return Common::Path(archive, '/');
 }
 
-Common::String ArchiveLoader::getExternalFilePath(const Common::String &fileName, const Common::String &archiveName) const {
-	static const char separator = '/';
-
+Common::Path ArchiveLoader::getExternalFilePath(const Common::Path &fileName, const Common::Path &archiveName) const {
 	// Build a path of the type 45/00/
-	Common::String filePath = archiveName;
-	while (filePath.lastChar() != separator && !filePath.empty()) {
-		filePath.deleteLastChar();
+	Common::Path filePath = archiveName;
+	if (!filePath.isSeparatorTerminated()) {
+		filePath = filePath.getParent();
 	}
-	filePath += "xarc/" + fileName;
+	filePath.joinInPlace("xarc");
+	filePath.joinInPlace(fileName);
 
 	return filePath;
 }
 
-Common::SeekableReadStream *ArchiveLoader::getExternalFile(const Common::String &fileName, const Common::String &archiveName) const {
-	Common::String filePath = getExternalFilePath(fileName, archiveName);
+Common::SeekableReadStream *ArchiveLoader::getExternalFile(const Common::Path &fileName, const Common::Path &archiveName) const {
+	Common::Path filePath = getExternalFilePath(fileName, archiveName);
 	return SearchMan.createReadStreamForMember(filePath);
 }
 
diff --git a/engines/stark/services/archiveloader.h b/engines/stark/services/archiveloader.h
index 23dc368f454..c33592a0142 100644
--- a/engines/stark/services/archiveloader.h
+++ b/engines/stark/services/archiveloader.h
@@ -67,35 +67,35 @@ public:
 	~ArchiveLoader();
 
 	/** Load a Xarc archive, and add it to the managed archives list */
-	bool load(const Common::String &archiveName);
+	bool load(const Common::Path &archiveName);
 
 	/** Unload all the unused Xarc archives */
 	void unloadUnused();
 
 	/** Retrieve a file from a specified archive */
-	ArchiveReadStream *getFile(const Common::String &fileName, const Common::String &archiveName);
+	ArchiveReadStream *getFile(const Common::Path &fileName, const Common::Path &archiveName);
 
 	/** Get the resource tree root for an archive, and increment the archive use count */
 	template <class T>
-	T *useRoot(const Common::String &archiveName);
+	T *useRoot(const Common::Path &archiveName);
 
 	/** Decrement the root's archive use count */
-	bool returnRoot(const Common::String &archiveName);
+	bool returnRoot(const Common::Path &archiveName);
 
 	/** Build the archive filename for a level or a location */
-	Common::String buildArchiveName(Resources::Level *level, Resources::Location *location = nullptr) const;
+	Common::Path buildArchiveName(Resources::Level *level, Resources::Location *location = nullptr) const;
 
 	/** Retrieve a file relative to a specified archive */
-	Common::SeekableReadStream *getExternalFile(const Common::String &fileName, const Common::String &archiveName) const;
-	Common::String getExternalFilePath(const Common::String &fileName, const Common::String &archiveName) const;
+	Common::SeekableReadStream *getExternalFile(const Common::Path &fileName, const Common::Path &archiveName) const;
+	Common::Path getExternalFilePath(const Common::Path &fileName, const Common::Path &archiveName) const;
 
 private:
 	class LoadedArchive {
 	public:
-		explicit LoadedArchive(const Common::String &archiveName);
+		explicit LoadedArchive(const Common::Path &archiveName);
 		~LoadedArchive();
 
-		const Common::String &getFilename() const { return _filename; }
+		const Common::Path &getFilename() const { return _filename; }
 		const Formats::XARCArchive &getXArc() const { return _xarc; }
 		Resources::Object *getRoot() const { return _root; }
 
@@ -107,21 +107,21 @@ private:
 
 	private:
 		uint _useCount;
-		Common::String _filename;
+		Common::Path _filename;
 		Formats::XARCArchive _xarc;
 		Resources::Object *_root;
 	};
 
 	typedef Common::List<LoadedArchive *> LoadedArchiveList;
 
-	bool hasArchive(const Common::String &archiveName) const;
-	LoadedArchive *findArchive(const Common::String &archiveName) const;
+	bool hasArchive(const Common::Path &archiveName) const;
+	LoadedArchive *findArchive(const Common::Path &archiveName) const;
 
 	LoadedArchiveList _archives;
 };
 
 template <class T>
-T *ArchiveLoader::useRoot(const Common::String &archiveName) {
+T *ArchiveLoader::useRoot(const Common::Path &archiveName) {
 	LoadedArchive *archive = findArchive(archiveName);
 	archive->incUsage();
 	return Resources::Object::cast<T>(archive->getRoot());
diff --git a/engines/stark/services/diary.cpp b/engines/stark/services/diary.cpp
index 46a9370b7a8..33cc038b269 100644
--- a/engines/stark/services/diary.cpp
+++ b/engines/stark/services/diary.cpp
@@ -48,7 +48,7 @@ void Diary::addDiaryEntry(const Common::String &name) {
 	StarkUserInterface->notifyDiaryEntryEnabled();
 }
 
-void Diary::addFMVEntry(const Common::String &filename, const Common::String &title, int gameDisc) {
+void Diary::addFMVEntry(const Common::Path &filename, const Common::String &title, int gameDisc) {
 	if (!hasFMVEntry(filename)) {
 		FMVEntry entry;
 		entry.filename = filename;
@@ -58,7 +58,7 @@ void Diary::addFMVEntry(const Common::String &filename, const Common::String &ti
 	}
 }
 
-bool Diary::hasFMVEntry(const Common::String &filename) const {
+bool Diary::hasFMVEntry(const Common::Path &filename) const {
 	for (uint i = 0; i < _fmvEntries.size(); i++) {
 		if (_fmvEntries[i].filename == filename) {
 			return true;
@@ -94,7 +94,14 @@ void Diary::saveLoad(ResourceSerializer *serializer) {
 	// FMV entries
 	serializer->syncArraySize(_fmvEntries);
 	for (uint i = 0; i < _fmvEntries.size(); i++) {
-		serializer->syncAsString32(_fmvEntries[i].filename);
+		if (serializer->isSaving()) {
+			Common::String filename(_fmvEntries[i].filename.toString('/'));
+			serializer->syncAsString32(filename);
+		} else {
+			Common::String filename;
+			serializer->syncAsString32(filename);
+			_fmvEntries[i].filename = Common::Path(filename, '/');
+		}
 		serializer->syncAsString32(_fmvEntries[i].title);
 		serializer->syncAsUint32LE(_fmvEntries[i].gameDisc);
 	}
diff --git a/engines/stark/services/diary.h b/engines/stark/services/diary.h
index d4c913b8920..a8ad2f0b4c8 100644
--- a/engines/stark/services/diary.h
+++ b/engines/stark/services/diary.h
@@ -22,6 +22,7 @@
 #ifndef STARK_SERVICES_DIARY_H
 #define STARK_SERVICES_DIARY_H
 
+#include "common/path.h"
 #include "common/str.h"
 #include "common/str-array.h"
 
@@ -79,11 +80,11 @@ public:
 	void setPageIndex(uint32 pageIndex) { _pageIndex = pageIndex; }
 
 	/** Add a FMV entry to the list of movies available to play from the diary */
-	void addFMVEntry(const Common::String &filename, const Common::String &title, int gameDisc);
+	void addFMVEntry(const Common::Path &filename, const Common::String &title, int gameDisc);
 
 	/** Get info of added FMV entries */
 	uint countFMV() const { return _fmvEntries.size(); }
-	const Common::String &getFMVFilename(uint index) const { return _fmvEntries[index].filename; }
+	const Common::Path &getFMVFilename(uint index) const { return _fmvEntries[index].filename; }
 	const Common::String &getFMVTitle(uint index) const { return _fmvEntries[index].title; }
 
 	/** Get info of added Diary entries */
@@ -114,12 +115,12 @@ public:
 
 private:
 	struct FMVEntry {
-		Common::String filename;
+		Common::Path filename;
 		Common::String title;
 		int gameDisc;
 	};
 
-	bool hasFMVEntry(const Common::String &filename) const;
+	bool hasFMVEntry(const Common::Path &filename) const;
 	void saveLoad(ResourceSerializer *serializer);
 
 	Common::Array<Common::String> _diaryEntries;
diff --git a/engines/stark/services/fontprovider.cpp b/engines/stark/services/fontprovider.cpp
index d063c156806..64ebf2829c6 100644
--- a/engines/stark/services/fontprovider.cpp
+++ b/engines/stark/services/fontprovider.cpp
@@ -124,7 +124,8 @@ FontProvider::FontHolder::FontHolder(FontProvider *fontProvider, const Common::S
 	_scaledHeight = StarkGfx->scaleHeightOriginalToCurrent(_originalHeight);
 
 	// Fetch the font file name
-	Common::String ttfFileName = "fonts/" + fontProvider->_ttfFileMap[_name];
+	Common::Path ttfFileName("fonts");
+	ttfFileName.joinInPlace(fontProvider->_ttfFileMap[_name]);
 
 	// Initialize the font
 	Common::SeekableReadStream *s = SearchMan.createReadStreamForMember(ttfFileName);
@@ -138,7 +139,7 @@ FontProvider::FontHolder::FontHolder(FontProvider *fontProvider, const Common::S
 		);
 		delete s;
 	} else {
-		warning("Unable to load the font '%s'", ttfFileName.c_str());
+		warning("Unable to load the font '%s'", ttfFileName.toString().c_str());
 	}
 }
 
diff --git a/engines/stark/services/gamechapter.cpp b/engines/stark/services/gamechapter.cpp
index 644a4177284..a6428fccc12 100644
--- a/engines/stark/services/gamechapter.cpp
+++ b/engines/stark/services/gamechapter.cpp
@@ -23,6 +23,7 @@
 #include "engines/stark/services/services.h"
 #include "engines/stark/services/global.h"
 
+#include "common/path.h"
 #include "common/tokenizer.h"
 #include "common/formats/ini-file.h"
 
diff --git a/engines/stark/services/resourceprovider.cpp b/engines/stark/services/resourceprovider.cpp
index 8d6b0aaa407..7171557419e 100644
--- a/engines/stark/services/resourceprovider.cpp
+++ b/engines/stark/services/resourceprovider.cpp
@@ -65,7 +65,7 @@ void ResourceProvider::initGlobal() {
 	Resources::Level *global = root->findChildWithSubtype<Resources::Level>(Resources::Level::kGlobal);
 
 	// Load the global archive
-	Common::String globalArchiveName = _archiveLoader->buildArchiveName(global);
+	Common::Path globalArchiveName = _archiveLoader->buildArchiveName(global);
 	_archiveLoader->load(globalArchiveName);
 
 	// Set the global tree
@@ -162,7 +162,7 @@ void ResourceProvider::requestLocationChange(uint16 level, uint16 location) {
 	// Retrieve the level archive name
 	Resources::Root *root = _global->getRoot();
 	Resources::Level *rootLevelResource = root->findChildWithIndex<Resources::Level>(level);
-	Common::String levelArchive = _archiveLoader->buildArchiveName(rootLevelResource);
+	Common::Path levelArchive = _archiveLoader->buildArchiveName(rootLevelResource);
 
 	// Load the archive, and get the resource sub-tree root
 	bool newlyLoaded = _archiveLoader->load(levelArchive);
@@ -177,7 +177,7 @@ void ResourceProvider::requestLocationChange(uint16 level, uint16 location) {
 	// Retrieve the location archive name
 	Resources::Level *levelResource = currentLocation->getLevel();
 	Resources::Location *levelLocationResource = levelResource->findChildWithIndex<Resources::Location>(location);
-	Common::String locationArchive = _archiveLoader->buildArchiveName(levelResource, levelLocationResource);
+	Common::Path locationArchive = _archiveLoader->buildArchiveName(levelResource, levelLocationResource);
 
 	// Load the archive, and get the resource sub-tree root
 	newlyLoaded = _archiveLoader->load(locationArchive);
diff --git a/engines/stark/services/staticprovider.cpp b/engines/stark/services/staticprovider.cpp
index 5f79f5b3537..71bdeb222fc 100644
--- a/engines/stark/services/staticprovider.cpp
+++ b/engines/stark/services/staticprovider.cpp
@@ -116,14 +116,14 @@ Resources::Sound *StaticProvider::getUISound(UISound sound) const {
 	return sounds->findChildWithOrder<Resources::Sound>(sound);
 }
 
-Common::String StaticProvider::buildLocationArchiveName(const char *locationName) const {
-	return Common::String::format("static/%s/%s.xarc", locationName, locationName);
+Common::Path StaticProvider::buildLocationArchiveName(const char *locationName) const {
+	return Common::Path(Common::String::format("static/%s/%s.xarc", locationName, locationName));
 }
 
 Resources::Location *StaticProvider::loadLocation(const char *locationName) {
 	assert(!_location);
 
-	Common::String archiveName = buildLocationArchiveName(locationName);
+	Common::Path archiveName = buildLocationArchiveName(locationName);
 
 	_archiveLoader->load(archiveName);
 	_location = _archiveLoader->useRoot<Resources::Location>(archiveName);
@@ -145,7 +145,7 @@ void StaticProvider::unloadLocation(Resources::Location *location) {
 
 	location->onExitLocation();
 
-	Common::String archiveName = buildLocationArchiveName(location->getName().c_str());
+	Common::Path archiveName = buildLocationArchiveName(location->getName().c_str());
 	_archiveLoader->returnRoot(archiveName);
 	_archiveLoader->unloadUnused();
 
diff --git a/engines/stark/services/staticprovider.h b/engines/stark/services/staticprovider.h
index 833e3768ef0..f17738c530d 100644
--- a/engines/stark/services/staticprovider.h
+++ b/engines/stark/services/staticprovider.h
@@ -23,6 +23,7 @@
 #define STARK_SERVICES_STATIC_PROVIDER_H
 
 #include "common/array.h"
+#include "common/path.h"
 #include "common/scummsys.h"
 
 namespace Stark {
@@ -131,7 +132,7 @@ private:
 	Common::Array<Resources::Anim *> _stockAnims;
 	Common::Array<Resources::Image *> _stockImages;
 
-	Common::String buildLocationArchiveName(const char *locationName) const;
+	Common::Path buildLocationArchiveName(const char *locationName) const;
 };
 
 } // End of namespace Stark
diff --git a/engines/stark/services/userinterface.cpp b/engines/stark/services/userinterface.cpp
index 464bc95580b..448f5e2a298 100644
--- a/engines/stark/services/userinterface.cpp
+++ b/engines/stark/services/userinterface.cpp
@@ -213,7 +213,7 @@ void UserInterface::selectInventoryItem(int16 itemIndex) {
 	_gameScreen->getInventoryWindow()->setSelectedInventoryItem(itemIndex);
 }
 
-void UserInterface::requestFMVPlayback(const Common::String &name) {
+void UserInterface::requestFMVPlayback(const Common::Path &name) {
 	_shouldPlayFmv = name;
 }
 
diff --git a/engines/stark/services/userinterface.h b/engines/stark/services/userinterface.h
index c8bd534c8ac..ccdd205c9e5 100644
--- a/engines/stark/services/userinterface.h
+++ b/engines/stark/services/userinterface.h
@@ -93,7 +93,7 @@ public:
 	bool shouldExit() { return _exitGame; }
 
 	/** Start playing a FMV */
-	void requestFMVPlayback(const Common::String &name);
+	void requestFMVPlayback(const Common::Path &name);
 
 	/** FMV playback has just ended */
 	void onFMVStopped();
@@ -229,7 +229,7 @@ private:
 
 	// TODO: Generalize to all screen changes
 	bool _shouldGoBackToPreviousScreen;
-	Common::String _shouldPlayFmv;
+	Common::Path _shouldPlayFmv;
 
 	Graphics::Surface *_gameWindowThumbnail;
 };
diff --git a/engines/stark/stark.cpp b/engines/stark/stark.cpp
index 92487c2f404..c1511b1e1d8 100644
--- a/engines/stark/stark.cpp
+++ b/engines/stark/stark.cpp
@@ -266,7 +266,7 @@ static bool modsCompare(const Common::FSNode &a, const Common::FSNode &b) {
 }
 
 void StarkEngine::addModsToSearchPath() const {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	const Common::FSNode modsDir = gameDataDir.getChild("mods");
 	if (modsDir.exists()) {
 		Common::FSList list;
@@ -290,7 +290,7 @@ void StarkEngine::checkRecommendedDatafiles() {
 
 	Common::String message = _("You are missing recommended data files:");
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	Common::FSNode fontsDir = gameDataDir.getChild("fonts");
 	if (!fontsDir.isDirectory()) {
 		fontsDir = gameDataDir.getChild("Fonts"); // FSNode is case sensitive
diff --git a/engines/stark/ui/menu/fmvmenu.h b/engines/stark/ui/menu/fmvmenu.h
index f7a503944fe..221a59abadd 100644
--- a/engines/stark/ui/menu/fmvmenu.h
+++ b/engines/stark/ui/menu/fmvmenu.h
@@ -102,7 +102,7 @@ private:
 	int _fontHeight;
 	uint _fmvPerPage;
 
-	const Common::String &_filename;
+	const Common::Path &_filename;
 	VisualText _title;
 
 	int _width;
diff --git a/engines/stark/ui/world/fmvscreen.cpp b/engines/stark/ui/world/fmvscreen.cpp
index fa4bd7fbf8f..2193d8bbe22 100644
--- a/engines/stark/ui/world/fmvscreen.cpp
+++ b/engines/stark/ui/world/fmvscreen.cpp
@@ -52,18 +52,20 @@ FMVScreen::~FMVScreen() {
 	delete _surfaceRenderer;
 }
 
-void FMVScreen::play(const Common::String &name) {
+void FMVScreen::play(const Common::Path &name) {
 	Common::SeekableReadStream *stream = nullptr;
 
 	// Play the low-resolution video, if possible
 	if (!StarkSettings->getBoolSetting(Settings::kHighFMV) && StarkSettings->hasLowResFMV()) {
-		Common::String lowResName = name;
-		lowResName.erase(lowResName.size() - 4);
-		lowResName += "_lo_res.bbb";
+		Common::String lowResBaseName = name.baseName();
+		lowResBaseName.erase(lowResBaseName.size() - 4);
+		lowResBaseName += "_lo_res.bbb";
+
+		Common::Path lowResName(name.getParent().appendComponent(lowResBaseName));
 
 		stream = StarkArchiveLoader->getExternalFile(lowResName, "Global/");
 		if (!stream) {
-			debug("Could not open %s", lowResName.c_str());
+			debug("Could not open %s", lowResName.toString().c_str());
 		}
 	}
 
@@ -73,13 +75,13 @@ void FMVScreen::play(const Common::String &name) {
 	}
 
 	if (!stream) {
-		warning("Could not open %s", name.c_str());
+		warning("Could not open %s", name.toString().c_str());
 		return;
 	}
 
 	_decoder->loadStream(stream);
 	if (!_decoder->isVideoLoaded()) {
-		error("Could not open %s", name.c_str());
+		error("Could not open %s", name.toString().c_str());
 	}
 	_decoder->setOutputPixelFormat(_bitmap->getBestPixelFormat());
 	_decoder->start();
diff --git a/engines/stark/ui/world/fmvscreen.h b/engines/stark/ui/world/fmvscreen.h
index e6728ceda06..8db5ecb9792 100644
--- a/engines/stark/ui/world/fmvscreen.h
+++ b/engines/stark/ui/world/fmvscreen.h
@@ -47,7 +47,7 @@ class FMVScreen : public SingleWindowScreen {
 public:
 	FMVScreen(Gfx::Driver *gfx, Cursor *cursor);
 	virtual ~FMVScreen();
-	void play(const Common::String &name);
+	void play(const Common::Path &name);
 	void stop();
 
 protected:


Commit: 4400b8eea3802ab103cca874604d947941507b71
    https://github.com/scummvm/scummvm/commit/4400b8eea3802ab103cca874604d947941507b71
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
STARTREK: Migrate engine to Path

Changed paths:
    engines/startrek/console.cpp
    engines/startrek/resource.cpp
    engines/startrek/sound.cpp
    engines/startrek/startrek.cpp


diff --git a/engines/startrek/console.cpp b/engines/startrek/console.cpp
index 6d6f07cd882..cfc4cace364 100644
--- a/engines/startrek/console.cpp
+++ b/engines/startrek/console.cpp
@@ -137,7 +137,7 @@ void Console::dumpFile(Common::String fileName) {
 	delete stream;
 
 	Common::DumpFile out;
-	out.open(fileName);
+	out.open(Common::Path(fileName));
 	out.write(data, size);
 	out.flush();
 	out.close();
diff --git a/engines/startrek/resource.cpp b/engines/startrek/resource.cpp
index 47e7b464385..e9caf763358 100644
--- a/engines/startrek/resource.cpp
+++ b/engines/startrek/resource.cpp
@@ -201,9 +201,10 @@ Common::MemoryReadStreamEndian *Resource::loadFile(Common::String filename, int
 	bool bigEndian = _platform == Common::kPlatformAmiga;
 
 	// Load external patches
-	if (Common::File::exists(filename)) {
+	Common::Path path(filename);
+	if (Common::File::exists(path)) {
 		Common::File *patch = new Common::File();
-		patch->open(filename);
+		patch->open(path);
 		int32 size = patch->size();
 		byte *data = (byte *)malloc(size);
 		patch->read(data, size);
diff --git a/engines/startrek/sound.cpp b/engines/startrek/sound.cpp
index 1beb478e5b9..33284a47c86 100644
--- a/engines/startrek/sound.cpp
+++ b/engines/startrek/sound.cpp
@@ -214,12 +214,12 @@ void Sound::playVoc(const Common::String &baseSoundName) {
 		if (_vm->_system->getMixer()->isSoundHandleActive(_sfxHandles[i]))
 			continue;
 
-		Common::String soundName = Common::String("voc/sfx/") + baseSoundName + ".voc";
+		Common::Path soundName = Common::Path("voc/sfx/").appendComponent(baseSoundName + ".voc");
 		Common::SeekableReadStream *readStream = SearchMan.createReadStreamForMember(soundName);
 		if (readStream == nullptr)
-			error("Couldn't open '%s'", soundName.c_str());
+			error("Couldn't open '%s'", soundName.toString().c_str());
 
-		debugC(5, kDebugSound, "Playing sound effect '%s'", soundName.c_str());
+		debugC(5, kDebugSound, "Playing sound effect '%s'", soundName.toString().c_str());
 
 		Audio::RewindableAudioStream *srcStream = Audio::makeVOCStream(readStream, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
 		Audio::AudioStream *audioStream;
@@ -249,11 +249,11 @@ void Sound::playSpeech(const Common::String &basename) {
 			i++;
 		}
 
-		Common::String filename = "voc/" + Common::String(name.c_str(), name.c_str() + i) + ".voc";
-		debugC(5, kDebugSound, "Playing speech '%s'", filename.c_str());
+		Common::Path filename = Common::Path("voc/").appendComponent(Common::String(name.c_str(), name.c_str() + i) + ".voc");
+		debugC(5, kDebugSound, "Playing speech '%s'", filename.toString().c_str());
 		Common::SeekableReadStream *readStream = SearchMan.createReadStreamForMember(filename);
 		if (readStream == nullptr)
-			error("Couldn't open '%s'", filename.c_str());
+			error("Couldn't open '%s'", filename.toString().c_str());
 
 		Audio::AudioStream *audioStream = Audio::makeVOCStream(readStream, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
 		if (audioStream != nullptr) {
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index 7955705c29a..148266f4493 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -124,7 +124,7 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam
 	_awayMission.sins.missionScore = 0;
 	_awayMission.veng.missionScore = 0;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "patches");
 }
 
@@ -363,7 +363,7 @@ void StarTrekEngine::playMovieMac(Common::String filename) {
 
 	Video::QuickTimeDecoder *qtDecoder = new Video::QuickTimeDecoder();
 
-	if (!qtDecoder->loadFile(filename))
+	if (!qtDecoder->loadFile(Common::Path(filename)))
 		error("Could not open '%s'", filename.c_str());
 
 	bool continuePlaying = true;


Commit: c6969633438c108c72071b007fc9d2994f7f8b91
    https://github.com/scummvm/scummvm/commit/c6969633438c108c72071b007fc9d2994f7f8b91
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SUPERNOVA: Migrate engine to Path

Changed paths:
    engines/supernova/graphics.cpp
    engines/supernova/resman.cpp
    engines/supernova/supernova.cpp


diff --git a/engines/supernova/graphics.cpp b/engines/supernova/graphics.cpp
index dbfc3a77442..07ab0fa4a14 100644
--- a/engines/supernova/graphics.cpp
+++ b/engines/supernova/graphics.cpp
@@ -71,7 +71,7 @@ bool MSNImage::init(int filenumber) {
 	Common::File file;
 	_filenumber = filenumber;
 	if (_vm->_MSPart == 1) {
-		if (!file.open(Common::String::format("msn_data.%03d", filenumber))) {
+		if (!file.open(Common::Path(Common::String::format("msn_data.%03d", filenumber)))) {
 			warning("Image data file msn_data.%03d could not be read!", filenumber);
 			return false;
 		}
@@ -79,7 +79,7 @@ bool MSNImage::init(int filenumber) {
 	}
 	else if (_vm->_MSPart == 2) {
 		if (!loadFromEngineDataFile()) {
-			if (!file.open(Common::String::format("ms2_data.%03d", filenumber))) {
+			if (!file.open(Common::Path(Common::String::format("ms2_data.%03d", filenumber)))) {
 				warning("Image data file ms2_data.%03d could not be read!", filenumber);
 				return false;
 			}
diff --git a/engines/supernova/resman.cpp b/engines/supernova/resman.cpp
index 45074cfe763..51f19389cc6 100644
--- a/engines/supernova/resman.cpp
+++ b/engines/supernova/resman.cpp
@@ -188,7 +188,7 @@ void ResourceManager::initImages2() {
 // Skip those in the buffer
 void ResourceManager::loadSound1(AudioId id) {
 	Common::File file;
-	if (!file.open(Common::String::format("msn_data.%03d", audioInfo1[id]._filenumber))) {
+	if (!file.open(Common::Path(Common::String::format("msn_data.%03d", audioInfo1[id]._filenumber)))) {
 		error("File %s could not be read!", file.getName());
 	}
 
@@ -213,7 +213,7 @@ void ResourceManager::loadSound1(AudioId id) {
 
 void ResourceManager::loadSound2(AudioId id) {
 	Common::File file;
-	if (!file.open(Common::String::format("ms2_data.%03d", audioInfo2[id]._filenumber))) {
+	if (!file.open(Common::Path(Common::String::format("ms2_data.%03d", audioInfo2[id]._filenumber)))) {
 		error("File %s could not be read!", file.getName());
 	}
 
diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp
index a47abe7eb92..20256e45919 100644
--- a/engines/supernova/supernova.cpp
+++ b/engines/supernova/supernova.cpp
@@ -519,14 +519,14 @@ Common::Error SupernovaEngine::showTextReader(const char *extension) {
 	blockName.toUppercase();
 	if ((stream = getBlockFromDatFile(blockName)) == nullptr) {
 		Common::File file;
-		Common::String filename;
+		Common::Path filename;
 		if (_MSPart == 1)
-			filename = Common::String::format("msn.%s", extension);
+			filename = Common::Path(Common::String::format("msn.%s", extension));
 		if (_MSPart == 2)
-			filename = Common::String::format("ms2.%s", extension);
+			filename = Common::Path(Common::String::format("ms2.%s", extension));
 
 		if (!file.open(filename)) {
-			GUIErrorMessageFormat(_("Unable to find '%s' in game folder or the engine data file."), filename.c_str());
+			GUIErrorMessageFormat(_("Unable to find '%s' in game folder or the engine data file."), filename.toString().c_str());
 			return Common::kReadingFailed;
 		}
 		stream = file.readStream(file.size());


Commit: b9150691d9fb3c948a39946fd8a545c62198e7bf
    https://github.com/scummvm/scummvm/commit/b9150691d9fb3c948a39946fd8a545c62198e7bf
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SWORD1: Migrate engine to Path

Changed paths:
    engines/sword1/animation.cpp
    engines/sword1/sound.cpp
    engines/sword1/sound.h
    engines/sword1/sword1.cpp


diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index dfaee05560a..02d8cc1b120 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -119,11 +119,11 @@ MoviePlayer::~MoviePlayer() {
  * @param id the id of the file
  */
 bool MoviePlayer::load(uint32 id) {
-	Common::String filename;
+	Common::Path filename;
 
 	if (SwordEngine::_systemVars.showText) {
 		Common::File f;
-		filename = Common::String::format("%s.txt", sequenceList[id]);
+		filename = Common::Path(Common::String::format("%s.txt", sequenceList[id]));
 
 		if (f.open(filename)) {
 			Common::String line;
@@ -148,12 +148,12 @@ bool MoviePlayer::load(uint32 id) {
 					ptr++;
 
 				if (startFrame > endFrame) {
-					warning("%s:%d: startFrame (%d) > endFrame (%d)", filename.c_str(), lineNo, startFrame, endFrame);
+					warning("%s:%d: startFrame (%d) > endFrame (%d)", filename.toString().c_str(), lineNo, startFrame, endFrame);
 					continue;
 				}
 
 				if (startFrame <= lastEnd) {
-					warning("%s:%d startFrame (%d) <= lastEnd (%d)", filename.c_str(), lineNo, startFrame, lastEnd);
+					warning("%s:%d startFrame (%d) <= lastEnd (%d)", filename.toString().c_str(), lineNo, startFrame, lastEnd);
 					continue;
 				}
 
@@ -173,16 +173,16 @@ bool MoviePlayer::load(uint32 id) {
 
 	switch (_decoderType) {
 	case kVideoDecoderDXA:
-		filename = Common::String::format("%s.dxa", sequenceList[id]);
+		filename = Common::Path(Common::String::format("%s.dxa", sequenceList[id]));
 		break;
 	case kVideoDecoderSMK:
-		filename = Common::String::format("%s.smk", sequenceList[id]);
+		filename = Common::Path(Common::String::format("%s.smk", sequenceList[id]));
 		break;
 	case kVideoDecoderPSX:
-		filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo && id == 4) ? "intro" : sequenceListPSX[id]);
+		filename = Common::Path(Common::String::format("%s.str", (_vm->_systemVars.isDemo && id == 4) ? "intro" : sequenceListPSX[id]));
 		break;
 	case kVideoDecoderMP2:
-		filename = Common::String::format("%s.mp2", sequenceList[id]);
+		filename = Common::Path(Common::String::format("%s.mp2", sequenceList[id]));
 		break;
 	default:
 		break;
@@ -516,12 +516,12 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
 ///////////////////////////////////////////////////////////////////////////////
 
 MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Sound *sound, OSystem *system) {
-	Common::String filename;
+	Common::Path filename;
 
 	// For the PSX version, we'll try the PlayStation stream files
 	if (vm->isPsx()) {
 		// The demo uses the normal file names for the intro cutscene
-		filename = ((vm->_systemVars.isDemo && id == 4) ? "intro" : Common::String(sequenceListPSX[id])) + ".str";
+		filename = ((vm->_systemVars.isDemo && id == 4) ? Common::Path("intro") : Common::Path(Common::String(sequenceListPSX[id]) + ".str"));
 
 		if (Common::File::exists(filename)) {
 #ifdef USE_RGB_COLOR
@@ -536,14 +536,14 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
 		}
 	}
 
-	filename = Common::String::format("%s.smk", sequenceList[id]);
+	filename = Common::Path(Common::String::format("%s.smk", sequenceList[id]));
 
 	if (Common::File::exists(filename)) {
 		Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
 		return new MoviePlayer(vm, textMan, resMan, sound, system, smkDecoder, kVideoDecoderSMK);
 	}
 
-	filename = Common::String::format("%s.dxa", sequenceList[id]);
+	filename = Common::Path(Common::String::format("%s.dxa", sequenceList[id]));
 
 	if (Common::File::exists(filename)) {
 		Video::VideoDecoder *dxaDecoder = new Video::DXADecoder();
@@ -551,7 +551,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
 	}
 
 	// Old MPEG2 cutscenes
-	filename = Common::String::format("%s.mp2", sequenceList[id]);
+	filename = Common::Path(Common::String::format("%s.mp2", sequenceList[id]));
 
 	if (Common::File::exists(filename)) {
 #ifdef USE_MPEG2
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 4c3f9a1c8a6..03ad8931cf4 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -819,7 +819,7 @@ void Sound::stopSample(int32 fxNo) {
 	stopFX(fxNo);
 }
 
-bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int32 tuneId, uint32 volume, int8 pan, MusCompMode assignedMode) {
+bool Sound::prepareMusicStreaming(const Common::Path &filename, int newHandleId, int32 tuneId, uint32 volume, int8 pan, MusCompMode assignedMode) {
 	int sampleRate = DEFAULT_SAMPLE_RATE;
 	WaveHeader wavHead;
 	bool isStereo = false;
@@ -828,7 +828,7 @@ bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int3
 		return false;
 
 	if (!_musicFile[newHandleId].open(filename)) {
-		debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.c_str());
+		debug(5, "Sound::streamMusicFile(): couldn't find file %s, bailing out...", filename.toString().c_str());
 		return false;
 	}
 
@@ -836,7 +836,7 @@ bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int3
 
 	if (assignedMode == MusWav) {
 		if (_musicFile[newHandleId].read(&wavHead, sizeof(WaveHeader)) != sizeof(WaveHeader)) {
-			debug(5, "Sound::streamMusicFile(): couldn't read from file %s, bailing out...", filename.c_str());
+			debug(5, "Sound::streamMusicFile(): couldn't read from file %s, bailing out...", filename.toString().c_str());
 			_musicFile[newHandleId].close();
 			return false;
 		}
@@ -891,7 +891,7 @@ bool Sound::prepareMusicStreaming(Common::String filename, int newHandleId, int3
 	}
 
 	if (assignedMode != MusWav && !_compressedMusicStream[newHandleId]) {
-		debug(5, "Sound::streamMusicFile(): couldn't process compressed file %s, bailing out...", filename.c_str());
+		debug(5, "Sound::streamMusicFile(): couldn't process compressed file %s, bailing out...", filename.toString().c_str());
 		_musicFile[newHandleId].close();
 		return false;
 	}
@@ -916,25 +916,25 @@ void Sound::streamMusicFile(int32 tuneId, int32 looped) {
 	Common::String filename(_tuneList[tuneId]);
 
 	MusCompMode assignedMode = MusWav;
-	if (tmp.exists(filename + ".wav")) {
+	if (tmp.exists(Common::Path(filename + ".wav"))) {
 		filename = filename + ".wav";
 		assignedMode = MusWav;
 	} else if (SwordEngine::isPsx() && tmp.exists("tunes.dat") && tmp.exists("tunes.tab")) {
 		filename = "tunes.dat";
 		assignedMode = MusPSX;
-	} else if (tmp.exists(filename + ".fla")) {
+	} else if (tmp.exists(Common::Path(filename + ".fla"))) {
 		filename = filename + ".fla";
 		assignedMode = MusFLAC;
-	} else if (tmp.exists(filename + ".ogg")) {
+	} else if (tmp.exists(Common::Path(filename + ".ogg"))) {
 		filename = filename + ".ogg";
 		assignedMode = MusVorbis;
-	} else if (tmp.exists(filename + ".mp3")) {
+	} else if (tmp.exists(Common::Path(filename + ".mp3"))) {
 		filename = filename + ".mp3";
 		assignedMode = MusMP3;
-	} else if (tmp.exists(filename + ".flac")) {
+	} else if (tmp.exists(Common::Path(filename + ".flac"))) {
 		filename = filename + ".flac";
 		assignedMode = MusFLAC;
-	} else if (tmp.exists(filename + ".aif")) {
+	} else if (tmp.exists(Common::Path(filename + ".aif"))) {
 		filename = filename + ".aif";
 		assignedMode = MusAif;
 	} else {
@@ -960,7 +960,7 @@ void Sound::streamMusicFile(int32 tuneId, int32 looped) {
 			_mixer->stopHandle(_hSampleMusic[newHandleId]);
 			_musicFile[newHandleId].close();
 
-			bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
+			bool success = prepareMusicStreaming(Common::Path(filename), newHandleId, tuneId,
 												 2 * (2 * (_volMusic[0] + _volMusic[1])),
 												 scalePan(64 + (4 * (_volMusic[1] - _volMusic[0]))),
 												 assignedMode);
@@ -971,7 +971,7 @@ void Sound::streamMusicFile(int32 tuneId, int32 looped) {
 			return;
 		} else {
 			// All good! We got the non-busy one :-)
-			bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
+			bool success = prepareMusicStreaming(Common::Path(filename), newHandleId, tuneId,
 												 0,
 												 scalePan(64 + (4 * (_volMusic[1] - _volMusic[0]))),
 												 assignedMode);
@@ -981,7 +981,7 @@ void Sound::streamMusicFile(int32 tuneId, int32 looped) {
 		}
 	} else {
 		// No streams are busy, let's go!
-		bool success = prepareMusicStreaming(filename, newHandleId, tuneId,
+		bool success = prepareMusicStreaming(Common::Path(filename), newHandleId, tuneId,
 											 2 * (3 * (_volMusic[0] + _volMusic[1])),
 											 scalePan(64 + (4 * (_volMusic[1] - _volMusic[0]))),
 											 assignedMode);
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index 4b471337547..f2e970e2d4c 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -206,7 +206,7 @@ private:
 		bool *endiannessCheck = nullptr, uint32 *sizeForEndiannessCheck = nullptr);
 	int32 getSpeechSize(byte *compData, uint32 compSize);
 
-	bool prepareMusicStreaming(Common::String filename, int newHandleId, int32 tuneId,
+	bool prepareMusicStreaming(const Common::Path &filename, int newHandleId, int32 tuneId,
 							   uint32 volume, int8 pan, MusCompMode assignedMode);
 	void serveSample(Common::File *file, int32 i);
 	void reduceMusicVolume();
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 7bf03562525..a1099676492 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -51,7 +51,7 @@ SwordEngine::SwordEngine(OSystem *syst, const ADGameDescription *gameDesc)
 	_systemVars.platform = gameDesc->platform;
 
 	// Add default file directories
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "music");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "speech");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "streams"); // PSX videos


Commit: 78dc2d9eb91b444ba783252edbe412ae52110d5e
    https://github.com/scummvm/scummvm/commit/78dc2d9eb91b444ba783252edbe412ae52110d5e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SWORD2: Migrate engine to Path

Changed paths:
    engines/sword2/animation.cpp
    engines/sword2/sword2.cpp


diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index b6661325896..da24b49ab01 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -104,7 +104,7 @@ bool MoviePlayer::load(const char *name) {
 	if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
 		initGraphics(g_system->getWidth(), g_system->getHeight(), nullptr);
 
-	if (!_decoder->loadFile(filename)) {
+	if (!_decoder->loadFile(Common::Path(filename))) {
 		// Go back to 8bpp color
 		if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
 			initGraphics(g_system->getWidth(), g_system->getHeight());
@@ -418,7 +418,7 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system
 
 	filename = Common::String::format("%s.str", name);
 
-	if (Common::File::exists(filename)) {
+	if (Common::File::exists(Common::Path(filename))) {
 #ifdef USE_RGB_COLOR
 		Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x, frameCount);
 		return new MoviePlayer(vm, system, psxDecoder, kVideoDecoderPSX);
@@ -431,14 +431,14 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system
 
 	filename = Common::String::format("%s.smk", name);
 
-	if (Common::File::exists(filename)) {
+	if (Common::File::exists(Common::Path(filename))) {
 		Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder();
 		return new MoviePlayer(vm, system, smkDecoder, kVideoDecoderSMK);
 	}
 
 	filename = Common::String::format("%s.dxa", name);
 
-	if (Common::File::exists(filename)) {
+	if (Common::File::exists(Common::Path(filename))) {
 		Video::DXADecoder *dxaDecoder = new Video::DXADecoder();
 		return new MoviePlayer(vm, system, dxaDecoder, kVideoDecoderDXA);
 	}
@@ -446,7 +446,7 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system
 	// Old MPEG2 cutscenes
 	filename = Common::String::format("%s.mp2", name);
 
-	if (Common::File::exists(filename)) {
+	if (Common::File::exists(Common::Path(filename))) {
 #ifdef USE_MPEG2
 		// HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video
 		// to be played back at 12fps.
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index e36736bd610..a5f2ca20a92 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -51,7 +51,7 @@ Common::Platform Sword2Engine::_platform;
 
 Sword2Engine::Sword2Engine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _rnd("sword2") {
 	// Add default file directories
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "clusters");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "sword2");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "video");


Commit: 3f9512c7cbea69e3954051688454789e1f7c5ca3
    https://github.com/scummvm/scummvm/commit/3f9512c7cbea69e3954051688454789e1f7c5ca3
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
SWORD25: Migrate engine to Path

Changed paths:
    engines/sword25/kernel/filesystemutil.cpp
    engines/sword25/kernel/filesystemutil.h
    engines/sword25/kernel/kernel_script.cpp
    engines/sword25/kernel/persistenceservice.cpp
    engines/sword25/kernel/persistenceservice.h
    engines/sword25/package/packagemanager.cpp
    engines/sword25/package/packagemanager.h
    engines/sword25/sword25.cpp


diff --git a/engines/sword25/kernel/filesystemutil.cpp b/engines/sword25/kernel/filesystemutil.cpp
index 7e7658a6340..e540560d027 100644
--- a/engines/sword25/kernel/filesystemutil.cpp
+++ b/engines/sword25/kernel/filesystemutil.cpp
@@ -36,20 +36,23 @@
 
 namespace Sword25 {
 
-Common::String FileSystemUtil::getUserdataDirectory() {
+Common::Path FileSystemUtil::getUserdataDirectoryPath() {
 	// FIXME: This code is a hack which bypasses the savefile API,
 	// and should eventually be removed.
-	Common::String path = ConfMan.get("savepath");
+	Common::Path path = ConfMan.getPath("savepath");
 
 	if (path.empty()) {
 		error("No save path has been defined");
-		return "";
 	}
 
-	// Return the path
 	return path;
 }
 
+Common::String FileSystemUtil::getUserdataDirectory() {
+	// Return the path using / separator
+	return getUserdataDirectoryPath().toString('/');
+}
+
 Common::String FileSystemUtil::getPathSeparator() {
 	// FIXME: This code is a hack which bypasses the savefile API,
 	// and should eventually be removed.
@@ -58,7 +61,7 @@ Common::String FileSystemUtil::getPathSeparator() {
 
 bool FileSystemUtil::fileExists(const Common::String &filename) {
 	Common::File f;
-	if (f.exists(filename))
+	if (f.exists(Common::Path(filename)))
 		return true;
 
 	// Check if the file exists in the save folder
diff --git a/engines/sword25/kernel/filesystemutil.h b/engines/sword25/kernel/filesystemutil.h
index 12115486383..005fdc6323a 100644
--- a/engines/sword25/kernel/filesystemutil.h
+++ b/engines/sword25/kernel/filesystemutil.h
@@ -58,6 +58,14 @@ namespace Sword25 {
 class FileSystemUtil {
 public:
 
+	/**
+	 * This function returns the path of the directory in which all user data is to be stored.
+	 *
+	 * These are for example Screenshots, game saves, configuration files, log files, ...
+	 * @return              Returns the name of the directory for user data.
+	 */
+	static Common::Path   getUserdataDirectoryPath();
+
 	/**
 	 * This function returns the name of the directory in which all user data is to be stored.
 	 *
diff --git a/engines/sword25/kernel/kernel_script.cpp b/engines/sword25/kernel/kernel_script.cpp
index 445b217f1ee..071b691ec31 100644
--- a/engines/sword25/kernel/kernel_script.cpp
+++ b/engines/sword25/kernel/kernel_script.cpp
@@ -411,7 +411,7 @@ static int isSlotOccupied(lua_State *L) {
 }
 
 static int getSavegameDirectory(lua_State *L) {
-	lua_pushstring(L, PersistenceService::getInstance().getSavegameDirectory().c_str());
+	lua_pushstring(L, PersistenceService::getInstance().getSavegameDirectory().toString('/').c_str());
 	return 1;
 }
 
diff --git a/engines/sword25/kernel/persistenceservice.cpp b/engines/sword25/kernel/persistenceservice.cpp
index 8701033312e..4f843c53ff8 100644
--- a/engines/sword25/kernel/persistenceservice.cpp
+++ b/engines/sword25/kernel/persistenceservice.cpp
@@ -200,8 +200,8 @@ uint PersistenceService::getSlotCount() {
 	return SLOT_COUNT;
 }
 
-Common::String PersistenceService::getSavegameDirectory() {
-	Common::FSNode node(FileSystemUtil::getUserdataDirectory());
+Common::Path PersistenceService::getSavegameDirectory() {
+	Common::FSNode node(FileSystemUtil::getUserdataDirectoryPath());
 	Common::FSNode childNode = node.getChild(SAVEGAME_DIRECTORY);
 
 	// Try and return the path using the savegame subfolder. But if doesn't exist, fall back on the data directory
diff --git a/engines/sword25/kernel/persistenceservice.h b/engines/sword25/kernel/persistenceservice.h
index facb6d9904e..52f93a3f690 100644
--- a/engines/sword25/kernel/persistenceservice.h
+++ b/engines/sword25/kernel/persistenceservice.h
@@ -51,7 +51,7 @@ public:
 	// -----------------------------------------------------------------------------
 
 	static uint getSlotCount();
-	static Common::String getSavegameDirectory();
+	static Common::Path getSavegameDirectory();
 
 	void            reloadSlots();
 	bool            isSlotOccupied(uint slotID);
diff --git a/engines/sword25/package/packagemanager.cpp b/engines/sword25/package/packagemanager.cpp
index ec287bc10cf..bbb72417003 100644
--- a/engines/sword25/package/packagemanager.cpp
+++ b/engines/sword25/package/packagemanager.cpp
@@ -55,7 +55,7 @@ static Common::String normalizePath(const Common::String &path, const Common::St
 
 PackageManager::PackageManager(Kernel *pKernel) : Service(pKernel),
 	_currentDirectory(PATH_SEPARATOR),
-	_rootFolder(ConfMan.get("path")),
+	_rootFolder(ConfMan.getPath("path")),
 	_useEnglishSpeech(ConfMan.getBool("english_speech")),
 	_extractedFiles(false) {
 	if (!registerScriptBindings())
@@ -108,7 +108,7 @@ Common::ArchiveMemberPtr PackageManager::getArchiveMember(const Common::String &
 		Common::Archive *archiveFolder = (*i)->archive;
 
 		// Construct relative path
-		Common::String resPath(&fileName2.c_str()[(*i)->_mountPath.size()]);
+		Common::Path resPath(&fileName2.c_str()[(*i)->_mountPath.size()]);
 
 		if (archiveFolder->hasFile(resPath)) {
 			return archiveFolder->getMember(resPath);
@@ -118,15 +118,15 @@ Common::ArchiveMemberPtr PackageManager::getArchiveMember(const Common::String &
 	return Common::ArchiveMemberPtr();
 }
 
-bool PackageManager::loadPackage(const Common::String &fileName, const Common::String &mountPosition) {
-	debug(3, "loadPackage(%s, %s)", fileName.c_str(), mountPosition.c_str());
+bool PackageManager::loadPackage(const Common::Path &fileName, const Common::String &mountPosition) {
+	debug(3, "loadPackage(%s, %s)", fileName.toString(Common::Path::kNativeSeparator).c_str(), mountPosition.c_str());
 
 	Common::Archive *zipFile = Common::makeZipArchive(fileName);
 	if (zipFile == NULL) {
-		error("Unable to mount file \"%s\" to \"%s\"", fileName.c_str(), mountPosition.c_str());
+		error("Unable to mount file \"%s\" to \"%s\"", fileName.toString(Common::Path::kNativeSeparator).c_str(), mountPosition.c_str());
 		return false;
 	} else {
-		debugC(kDebugResource, "Package '%s' mounted as '%s'.", fileName.c_str(), mountPosition.c_str());
+		debugC(kDebugResource, "Package '%s' mounted as '%s'.", fileName.toString(Common::Path::kNativeSeparator).c_str(), mountPosition.c_str());
 		Common::ArchiveMemberList files;
 		zipFile->listMembers(files);
 		debug(3, "Capacity %d", files.size());
@@ -140,14 +140,14 @@ bool PackageManager::loadPackage(const Common::String &fileName, const Common::S
 	}
 }
 
-bool PackageManager::loadDirectoryAsPackage(const Common::String &directoryName, const Common::String &mountPosition) {
+bool PackageManager::loadDirectoryAsPackage(const Common::Path &directoryName, const Common::String &mountPosition) {
 	Common::FSNode directory(directoryName);
 	Common::Archive *folderArchive = new Common::FSDirectory(directory, 6, false, false, true);
 	if (!directory.exists() || (folderArchive == NULL)) {
-		error("Unable to mount directory \"%s\" to \"%s\".", directoryName.c_str(), mountPosition.c_str());
+		error("Unable to mount directory \"%s\" to \"%s\".", directoryName.toString(Common::Path::kNativeSeparator).c_str(), mountPosition.c_str());
 		return false;
 	} else {
-		debugC(kDebugResource, "Directory '%s' mounted as '%s'.", directoryName.c_str(), mountPosition.c_str());
+		debugC(kDebugResource, "Directory '%s' mounted as '%s'.", directoryName.toString(Common::Path::kNativeSeparator).c_str(), mountPosition.c_str());
 
 		Common::ArchiveMemberList files;
 		folderArchive->listMembers(files);
@@ -265,7 +265,7 @@ int PackageManager::doSearch(Common::ArchiveMemberList &list, const Common::Stri
 		}
 
 		// Construct relative path
-		Common::String resFilter(&normalizedFilter.c_str()[(*i)->_mountPath.size()]);
+		Common::Path resFilter(&normalizedFilter.c_str()[(*i)->_mountPath.size()]);
 
 		if ((*i)->archive->listMatchingMembers(memberList, resFilter) == 0)
 			continue;
diff --git a/engines/sword25/package/packagemanager.h b/engines/sword25/package/packagemanager.h
index 8dadb02ef1b..b4f135ca5db 100644
--- a/engines/sword25/package/packagemanager.h
+++ b/engines/sword25/package/packagemanager.h
@@ -87,7 +87,7 @@ private:
 	Common::FSNode _rootFolder;
 	Common::List<ArchiveEntry *> _archiveList;
 	bool _extractedFiles;
-	Common::String _directoryName;
+	Common::Path _directoryName;
 
 	bool _useEnglishSpeech;
 	Common::String ensureSpeechLang(const Common::String &fileName);
@@ -107,7 +107,7 @@ public:
 	 *
 	 * Set the PackageManager to run on extracted game files.s
 	 */
-	void setRunWithExtractedFiles(const Common::String &directoryName) {
+	void setRunWithExtractedFiles(const Common::Path &directoryName) {
 		_extractedFiles = true;
 		_directoryName = directoryName;
 	}
@@ -118,14 +118,14 @@ public:
 	 * @param MountPosition The directory name under which the package should be mounted
 	 * @return              Returns true if the mount was successful, otherwise false.
 	 */
-	bool loadPackage(const Common::String &fileName, const Common::String &mountPosition);
+	bool loadPackage(const Common::Path &fileName, const Common::String &mountPosition);
 	/**
 	 * Mounts the contents of a directory in the specified directory in the directory tree.
 	 * @param               The name of the directory to mount
 	 * @param MountPosition The directory name under which the package should be mounted
 	 * @return              Returns true if the mount was successful, otherwise false.
 	 */
-	bool loadDirectoryAsPackage(const Common::String &directoryName, const Common::String &mountPosition);
+	bool loadDirectoryAsPackage(const Common::Path &directoryName, const Common::String &mountPosition);
 	/**
 	 * Downloads a file from the directory tree
 	 * @param FileName      The filename of the file to load
diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp
index 5958ece48f7..f5ad39b83e3 100644
--- a/engines/sword25/sword25.cpp
+++ b/engines/sword25/sword25.cpp
@@ -103,7 +103,7 @@ Common::Error Sword25Engine::appStart() {
 	// Load packages
 	PackageManager *packageManagerPtr = Kernel::getInstance()->getPackage();
 	if (getGameFlags() & GF_EXTRACTED) {
-		Common::String gameDirectory = ConfMan.get("path");
+		Common::Path gameDirectory = ConfMan.getPath("path");
 		packageManagerPtr->setRunWithExtractedFiles(gameDirectory);
 		if (!packageManagerPtr->loadDirectoryAsPackage(gameDirectory, "/"))
 			return Common::kUnknownError;
@@ -157,7 +157,7 @@ bool Sword25Engine::loadPackages() {
 		return false;
 
 	// Get the contents of the main program directory and sort them alphabetically
-	Common::FSNode dir(ConfMan.get("path"));
+	Common::FSNode dir(ConfMan.getPath("path"));
 	Common::FSList files;
 	if (!dir.isDirectory() || !dir.getChildren(files, Common::FSNode::kListAll)) {
 		warning("Game data path does not exist or is not a directory");
@@ -174,7 +174,7 @@ bool Sword25Engine::loadPackages() {
 	// existing files in the virtual file system, if they include files with the same name.
 	for (Common::FSList::const_iterator it = files.begin(); it != files.end(); ++it) {
 		if (it->getName().matchString("patch???.b25c", true))
-			if (!packageManagerPtr->loadPackage(it->getName(), "/"))
+			if (!packageManagerPtr->loadPackage(it->getPathInArchive(), "/"))
 				return false;
 	}
 
@@ -182,7 +182,7 @@ bool Sword25Engine::loadPackages() {
 	// The filename of the packages have the form lang_*.b25c (eg. lang_de.b25c)
 	for (Common::FSList::const_iterator it = files.begin(); it != files.end(); ++it) {
 		if (it->getName().matchString("lang_*.b25c", true))
-			if (!packageManagerPtr->loadPackage(it->getName(), "/"))
+			if (!packageManagerPtr->loadPackage(it->getPathInArchive(), "/"))
 				return false;
 	}
 


Commit: ed0b59973a2d2c69dc6318a263d4aa10a0268828
    https://github.com/scummvm/scummvm/commit/ed0b59973a2d2c69dc6318a263d4aa10a0268828
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TEENAGENT: Migrate engine to Path

Changed paths:
    engines/teenagent/pack.cpp
    engines/teenagent/pack.h
    engines/teenagent/teenagent.cpp


diff --git a/engines/teenagent/pack.cpp b/engines/teenagent/pack.cpp
index 2a8d57b2071..23cd41a87f2 100644
--- a/engines/teenagent/pack.cpp
+++ b/engines/teenagent/pack.cpp
@@ -41,12 +41,12 @@ void FilePack::close() {
 	file.close();
 }
 
-bool FilePack::open(const Common::String &filename) {
+bool FilePack::open(const Common::Path &filename) {
 	if (!file.exists(filename) || !file.open(filename))
 		return false;
 
 	_fileCount = file.readUint32LE();
-	debugC(0, kDebugPack, "opened %s, found %u entries", filename.c_str(), _fileCount);
+	debugC(0, kDebugPack, "opened %s, found %u entries", filename.toString().c_str(), _fileCount);
 	offsets = new uint32[_fileCount + 1];
 	for (uint32 i = 0; i <= _fileCount; ++i) {
 		offsets[i] = file.readUint32LE();
@@ -90,7 +90,7 @@ void TransientFilePack::close() {
 	_filename.clear();
 }
 
-bool TransientFilePack::open(const Common::String &filename) {
+bool TransientFilePack::open(const Common::Path &filename) {
 	_filename = filename;
 
 	Common::File file;
@@ -98,7 +98,7 @@ bool TransientFilePack::open(const Common::String &filename) {
 		return false;
 
 	_fileCount = file.readUint32LE();
-	debugC(0, kDebugPack, "opened %s, found %u entries", filename.c_str(), _fileCount);
+	debugC(0, kDebugPack, "opened %s, found %u entries", filename.toString().c_str(), _fileCount);
 	offsets = new uint32[_fileCount + 1];
 	for (uint32 i = 0; i <= _fileCount; ++i) {
 		offsets[i] = file.readUint32LE();
@@ -151,13 +151,13 @@ void MemoryPack::close() {
 	chunks.clear();
 }
 
-bool MemoryPack::open(const Common::String &filename) {
+bool MemoryPack::open(const Common::Path &filename) {
 	Common::File file;
 	if (!file.exists(filename) || !file.open(filename))
 		return false;
 
 	uint32 count = file.readUint32LE();
-	debugC(0, kDebugPack, "opened %s, found %u entries [memory]", filename.c_str(), count);
+	debugC(0, kDebugPack, "opened %s, found %u entries [memory]", filename.toString().c_str(), count);
 	for (uint32 i = 0; i < count; ++i) {
 		uint32 offset = file.readUint32LE();
 		int32 pos = file.pos();
diff --git a/engines/teenagent/pack.h b/engines/teenagent/pack.h
index c62a727f3ed..d4c9d6d7ba7 100644
--- a/engines/teenagent/pack.h
+++ b/engines/teenagent/pack.h
@@ -34,7 +34,7 @@ protected:
 public:
 	Pack(): _fileCount(0) {}
 	virtual ~Pack() {}
-	virtual bool open(const Common::String &filename) = 0;
+	virtual bool open(const Common::Path &filename) = 0;
 	virtual void close() = 0;
 
 	virtual uint32 fileCount() const { return _fileCount; }
@@ -52,7 +52,7 @@ public:
 	FilePack();
 	~FilePack() override;
 
-	bool open(const Common::String &filename) override;
+	bool open(const Common::Path &filename) override;
 	void close() override;
 
 	uint32 getSize(uint32 id) const override;
@@ -65,13 +65,13 @@ public:
  **/
 class TransientFilePack : public Pack {
 	uint32 *offsets;
-	Common::String _filename;
+	Common::Path _filename;
 
 public:
 	TransientFilePack();
 	~TransientFilePack() override;
 
-	bool open(const Common::String &filename) override;
+	bool open(const Common::Path &filename) override;
 	void close() override;
 
 	uint32 getSize(uint32 id) const override;
@@ -102,7 +102,7 @@ class MemoryPack : public Pack {
 	Common::Array<Chunk> chunks;
 
 public:
-	bool open(const Common::String &filename) override;
+	bool open(const Common::Path &filename) override;
 	void close() override;
 
 	uint32 getSize(uint32 id) const override;
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index e041fc3738b..a76172b5d5b 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -525,7 +525,7 @@ bool TeenAgentEngine::showMetropolis() {
 }
 
 Common::Error TeenAgentEngine::run() {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "music");
 
 	if (!res->loadArchives(_gameDescription))


Commit: 17e1bd01ef29429ae2399bf71acef22be58bb3e1
    https://github.com/scummvm/scummvm/commit/17e1bd01ef29429ae2399bf71acef22be58bb3e1
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TESTBED: Migrate engine to Path

Changed paths:
    engines/testbed/cloud.cpp
    engines/testbed/config-params.cpp
    engines/testbed/config-params.h
    engines/testbed/config.cpp
    engines/testbed/fs.cpp
    engines/testbed/misc.cpp
    engines/testbed/sound.cpp
    engines/testbed/testbed.cpp
    engines/testbed/video.cpp


diff --git a/engines/testbed/cloud.cpp b/engines/testbed/cloud.cpp
index e39242426a6..ce3ab47b2ba 100644
--- a/engines/testbed/cloud.cpp
+++ b/engines/testbed/cloud.cpp
@@ -358,7 +358,7 @@ TestExitStatus CloudTests::testUploading() {
 		return kTestSkipped;
 	}
 
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::FSDirectory gameRoot(path);
 	Common::FSDirectory *directory = gameRoot.getSubDirectory("test1");
 	Common::FSNode node = directory->getFSNode().getChild("file.txt");
@@ -374,10 +374,10 @@ TestExitStatus CloudTests::testUploading() {
 			Testsuite::logPrintf("Warning! No Request is returned!\n");
 		}
 	} else {
-		Common::String filepath = node.getPath();
+		Common::Path filepath = node.getPath();
 		if (CloudMan.getCurrentStorage()->upload(
 				Common::String(getRemoteTestPath()) + "/testfile.txt",
-				filepath.c_str(),
+				filepath,
 				new Common::GlobalFunctionCallback<const Cloud::Storage::UploadResponse &>(&fileUploadedCallback),
 				new Common::GlobalFunctionCallback<const Networking::ErrorResponse &>(&errorCallback)
 			) == nullptr) {
@@ -441,13 +441,13 @@ TestExitStatus CloudTests::testDownloading() {
 		return kTestSkipped;
 	}
 
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::FSDirectory gameRoot(path);
 	Common::FSNode node = gameRoot.getFSNode().getChild("downloaded_file.txt");
-	Common::String filepath = node.getPath();
+	Common::Path filepath = node.getPath();
 	if (CloudMan.getCurrentStorage()->download(
 			Common::String(getRemoteTestPath()) + "/testfile.txt",
-			filepath.c_str(),
+			filepath,
 			new Common::GlobalFunctionCallback<const Cloud::Storage::BoolResponse &>(&fileDownloadedCallback),
 			new Common::GlobalFunctionCallback<const Networking::ErrorResponse &>(&errorCallback)
 		) == nullptr) {
@@ -488,13 +488,13 @@ TestExitStatus CloudTests::testFolderDownloading() {
 		return kTestSkipped;
 	}
 
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::FSDirectory gameRoot(path);
 	Common::FSNode node = gameRoot.getFSNode().getChild("downloaded_directory");
-	Common::String filepath = node.getPath();
+	Common::Path filepath = node.getPath();
 	if (CloudMan.downloadFolder(
 			getRemoteTestPath(),
-			filepath.c_str(),
+			filepath,
 			new Common::GlobalFunctionCallback<const Cloud::Storage::FileArrayResponse &>(&directoryDownloadedCallback),
 			new Common::GlobalFunctionCallback<const Networking::ErrorResponse &>(&errorCallback)
 		) == nullptr) {
@@ -535,10 +535,10 @@ TestExitStatus CloudTests::testSavesSync() {
 		return kTestSkipped;
 	}
 
-	const Common::String &path = ConfMan.get("path");
+	Common::Path path = ConfMan.getPath("path");
 	Common::FSDirectory gameRoot(path);
 	Common::FSNode node = gameRoot.getFSNode().getChild("downloaded_directory");
-	Common::String filepath = node.getPath();
+	Common::Path filepath = node.getPath();
 	if (CloudMan.syncSaves(
 			new Common::GlobalFunctionCallback<const Cloud::Storage::BoolResponse &>(&savesSyncedCallback),
 			new Common::GlobalFunctionCallback<const Networking::ErrorResponse &>(&errorCallback)
diff --git a/engines/testbed/config-params.cpp b/engines/testbed/config-params.cpp
index 9e2dfae5d7e..5b60900fc20 100644
--- a/engines/testbed/config-params.cpp
+++ b/engines/testbed/config-params.cpp
@@ -42,7 +42,7 @@ ConfigParams::ConfigParams() {
 	_testbedConfMan = 0;
 }
 
-void ConfigParams::initLogging(const char *dirname, const char *filename, bool enable) {
+void ConfigParams::initLogging(const Common::Path &dirname, const char *filename, bool enable) {
 	setLogDirectory(dirname);
 	setLogFilename(filename);
 	if (enable) {
@@ -54,7 +54,7 @@ void ConfigParams::initLogging(const char *dirname, const char *filename, bool e
 
 void ConfigParams::initLogging(bool enable) {
 	// Default Log Directory is game-data directory and filename is 'testbed.log'.
-	initLogging(ConfMan.get("path").c_str(), "testbed.log", enable);
+	initLogging(ConfMan.getPath("path"), "testbed.log", enable);
 }
 
 bool ConfigParams::isRerunRequired() {
diff --git a/engines/testbed/config-params.h b/engines/testbed/config-params.h
index 2783900e7bf..0bee488292e 100644
--- a/engines/testbed/config-params.h
+++ b/engines/testbed/config-params.h
@@ -38,7 +38,7 @@ private:
 	/**
 	 * Private variables related to log files.
 	 */
-	Common::String _logDirectory;
+	Common::Path _logDirectory;
 	Common::String _logFilename;
 	Common::WriteStream *_ws;
 
@@ -82,8 +82,8 @@ public:
 	TestbedConfigManager *getTestbedConfigManager() { return _testbedConfMan; }
 	void setTestbedConfigManager(TestbedConfigManager* confMan) { _testbedConfMan = confMan; }
 
-	Common::String &getLogDirectory() {	return _logDirectory; }
-	void setLogDirectory(const Common::String &dirname) { _logDirectory = dirname; }
+	Common::Path &getLogDirectory() {	return _logDirectory; }
+	void setLogDirectory(const Common::Path &dirname) { _logDirectory = dirname; }
 	Common::String &getLogFilename() { return _logFilename; }
 	void setLogFilename(const Common::String &filename) { _logFilename = filename; }
 
@@ -94,7 +94,7 @@ public:
 	/**
 	 * Note: To enable logging, this function must be called once first.
 	 */
-	void initLogging(const char *dirname, const char *filename, bool enable = true);
+	void initLogging(const Common::Path &dirname, const char *filename, bool enable = true);
 	void initLogging(bool enable = true);
 
 	void deleteWriteStream();
diff --git a/engines/testbed/config.cpp b/engines/testbed/config.cpp
index 82ccf47908f..aa9555fd67c 100644
--- a/engines/testbed/config.cpp
+++ b/engines/testbed/config.cpp
@@ -225,13 +225,13 @@ void TestbedConfigManager::writeTestbedConfigToStream(Common::WriteStream *ws) {
 
 Common::SeekableReadStream *TestbedConfigManager::getConfigReadStream() const {
 	// Look for config file using SearchMan
-	Common::SeekableReadStream *rs = SearchMan.createReadStreamForMember(_configFileName);
+	Common::SeekableReadStream *rs = SearchMan.createReadStreamForMember(Common::Path(_configFileName));
 	return rs;
 }
 
 Common::WriteStream *TestbedConfigManager::getConfigWriteStream() const {
 	// Look for config file in game-path
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::WriteStream *ws;
 	Common::FSNode gameRoot(path);
 	Common::FSNode config = gameRoot.getChild(_configFileName);
diff --git a/engines/testbed/fs.cpp b/engines/testbed/fs.cpp
index 18105237d10..8edf98f68dd 100644
--- a/engines/testbed/fs.cpp
+++ b/engines/testbed/fs.cpp
@@ -61,7 +61,7 @@ bool FStests::readDataFromFile(Common::FSDirectory *directory, const char *file)
 }
 
 TestExitStatus FStests::testReadFile() {
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::FSDirectory gameRoot(path);
 	int numFailed = 0;
 
@@ -76,7 +76,7 @@ TestExitStatus FStests::testReadFile() {
 	for (unsigned int i = 0; i < ARRAYSIZE(dirList); i++) {
 		Common::String dirName = dirList[i];
 		Common::String fileName = file[i];
-		Common::FSDirectory *directory = gameRoot.getSubDirectory(dirName);
+		Common::FSDirectory *directory = gameRoot.getSubDirectory(Common::Path(dirName));
 
 		if (!directory) {
 			Testsuite::logDetailedPrintf("Failed to open directory %s during FS tests\n", dirName.c_str());
@@ -91,7 +91,7 @@ TestExitStatus FStests::testReadFile() {
 		dirName.toLowercase();
 		fileName.toLowercase();
 		delete directory;
-		directory = gameRoot.getSubDirectory(dirName);
+		directory = gameRoot.getSubDirectory(Common::Path(dirName));
 
 		if (!directory) {
 			Testsuite::logDetailedPrintf("Failed to open directory %s during FS tests\n", dirName.c_str());
@@ -106,7 +106,7 @@ TestExitStatus FStests::testReadFile() {
 		dirName.toUppercase();
 		fileName.toUppercase();
 		delete directory;
-		directory = gameRoot.getSubDirectory(dirName);
+		directory = gameRoot.getSubDirectory(Common::Path(dirName));
 
 		if (!directory) {
 			Testsuite::logDetailedPrintf("Failed to open directory %s during FS tests\n", dirName.c_str());
@@ -133,10 +133,11 @@ TestExitStatus FStests::testReadFile() {
  * it is same by reading the file again.
  */
 TestExitStatus FStests::testWriteFile() {
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::FSNode gameRoot(path);
 	if (!gameRoot.exists()) {
-		Testsuite::logPrintf("Couldn't open the game data directory %s", path.c_str());
+		Testsuite::logPrintf("Couldn't open the game data directory %s",
+				path.toString(Common::Path::kNativeSeparator).c_str());
 		 return kTestFailed;
 	}
 
@@ -175,10 +176,11 @@ TestExitStatus FStests::testWriteFile() {
  * This test creates a directory testbed.dir, and confirms if the directory is created successfully
  */
 TestExitStatus FStests::testCreateDir() {
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::FSNode gameRoot(path);
 	if (!gameRoot.exists()) {
-		Testsuite::logPrintf("Couldn't open the game data directory %s", path.c_str());
+		Testsuite::logPrintf("Couldn't open the game data directory %s",
+				path.toString(Common::Path::kNativeSeparator).c_str());
 		 return kTestFailed;
 	}
 
@@ -204,7 +206,7 @@ TestExitStatus FStests::testCreateDir() {
 FSTestSuite::FSTestSuite() {
 	// FS tests depend on Game Data files.
 	// If those are not found. Disable this testsuite.
-	const Common::String &path = ConfMan.get("path");
+	const Common::Path &path = ConfMan.getPath("path");
 	Common::FSNode gameRoot(path);
 
 	Common::FSNode gameIdentificationFile = gameRoot.getChild("TESTBED");
diff --git a/engines/testbed/misc.cpp b/engines/testbed/misc.cpp
index c687e1c57d6..f809b8df18e 100644
--- a/engines/testbed/misc.cpp
+++ b/engines/testbed/misc.cpp
@@ -275,7 +275,7 @@ uint ImageAlbumImageSupplier::getNumSlots() const {
 }
 
 Common::U32String ImageAlbumImageSupplier::getDefaultFileNameForSlot(uint slot) const {
-	return Common::U32String(_slots[slot]._path.getLastComponent().toString());
+	return Common::U32String(_slots[slot]._path.baseName());
 }
 
 ImageAlbumImageSupplier::FileInfo::FileInfo(const Common::Path &path, Common::FormatInfo::FormatID format, bool dontReportFormat) {
diff --git a/engines/testbed/sound.cpp b/engines/testbed/sound.cpp
index dee18c3e9c9..dbf3ccd6aa9 100644
--- a/engines/testbed/sound.cpp
+++ b/engines/testbed/sound.cpp
@@ -195,7 +195,7 @@ TestExitStatus SoundSubsystem::modPlayback() {
 		return kTestSkipped;
 	}
 
-	Common::FSNode gameRoot(ConfMan.get("path"));
+	Common::FSNode gameRoot(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameRoot, "audiocd-files");
 
 	Common::File f;
@@ -353,7 +353,7 @@ SoundSubsystemTestSuite::SoundSubsystemTestSuite() {
 	addTest("MODPlayback", &SoundSubsystem::modPlayback, true);
 
 	// Make audio-files discoverable
-	Common::FSNode gameRoot(ConfMan.get("path"));
+	Common::FSNode gameRoot(ConfMan.getPath("path"));
 	if (gameRoot.exists()) {
 		SearchMan.addSubDirectoryMatching(gameRoot, "audiocd-files");
 		if (SearchMan.hasFile("track01.mp3") && SearchMan.hasFile("track02.mp3") && SearchMan.hasFile("track03.mp3") && SearchMan.hasFile("track04.mp3")) {
diff --git a/engines/testbed/testbed.cpp b/engines/testbed/testbed.cpp
index 5223832bbe5..1d6705864c6 100644
--- a/engines/testbed/testbed.cpp
+++ b/engines/testbed/testbed.cpp
@@ -77,10 +77,10 @@ void TestbedExitDialog::init() {
 	addList(0, _yOffset, 500, 200, strArray);
 	text = "More Details can be viewed in the Log file : " + ConfParams.getLogFilename();
 	addText(450, 20, text, Graphics::kTextAlignLeft, 0, 0);
-	if (ConfParams.getLogDirectory().size()) {
-		text = "Directory : " + ConfParams.getLogDirectory();
-	} else {
+	if (ConfParams.getLogDirectory().empty()) {
 		text = "Directory : .";
+	} else {
+		text = "Directory : " + ConfParams.getLogDirectory().toString(Common::Path::kNativeSeparator);
 	}
 	addText(500, 20, text, Graphics::kTextAlignLeft, 0, 0);
 	_yOffset += 5;
@@ -116,7 +116,7 @@ TestbedEngine::TestbedEngine(OSystem *syst)
 
 	// However this is the place to specify all default directories
 	// Put game-data dir in search path
-	Common::FSNode gameRoot(ConfMan.get("path"));
+	Common::FSNode gameRoot(ConfMan.getPath("path"));
 	if (gameRoot.exists()) {
 		SearchMan.addDirectory(gameRoot.getDisplayName(), gameRoot);
 	}
@@ -217,7 +217,7 @@ void TestbedEngine::checkForAllAchievements() {
 
 Common::Error TestbedEngine::run() {
 	if (ConfMan.hasKey("start_movie")) {
-		return Videotests::videoTest(ConfMan.get("start_movie"));
+		return Videotests::videoTest(ConfMan.getPath("start_movie"));
 	}
 
 	// Initialize graphics using following:
diff --git a/engines/testbed/video.cpp b/engines/testbed/video.cpp
index 3aed6695e3e..6d40f5291d2 100644
--- a/engines/testbed/video.cpp
+++ b/engines/testbed/video.cpp
@@ -35,11 +35,11 @@ namespace Testbed {
 Common::Error Videotests::videoTest(const Common::Path &path) {
 	Common::File *file = new Common::File();
 	if (!file->open(path)) {
-		warning("Cannot open file %s", path.toString().c_str());
+		warning("Cannot open file %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		delete file;
 		return Common::kNoGameDataFoundError;
 	}
-	return videoTest(file, path.toString());
+	return videoTest(file, path.toString(Common::Path::kNativeSeparator));
 }
 
 Common::Error Videotests::videoTest(const Common::FSNode &node) {


Commit: 468cdd81bdaf7c5ac2de0c3f41959deebbf76864
    https://github.com/scummvm/scummvm/commit/468cdd81bdaf7c5ac2de0c3f41959deebbf76864
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TETRAEDGE: Migrate engine to Path

Changed paths:
    engines/tetraedge/game/amerzone_game.cpp
    engines/tetraedge/game/application.h
    engines/tetraedge/game/billboard.cpp
    engines/tetraedge/game/billboard.h
    engines/tetraedge/game/bonus_menu.cpp
    engines/tetraedge/game/bonus_menu.h
    engines/tetraedge/game/character.cpp
    engines/tetraedge/game/character.h
    engines/tetraedge/game/confirm.cpp
    engines/tetraedge/game/confirm.h
    engines/tetraedge/game/credits.cpp
    engines/tetraedge/game/dialog2.cpp
    engines/tetraedge/game/documents_browser.cpp
    engines/tetraedge/game/documents_browser.h
    engines/tetraedge/game/game.cpp
    engines/tetraedge/game/game.h
    engines/tetraedge/game/in_game_scene.cpp
    engines/tetraedge/game/in_game_scene.h
    engines/tetraedge/game/inventory.cpp
    engines/tetraedge/game/inventory_object.cpp
    engines/tetraedge/game/inventory_object.h
    engines/tetraedge/game/lua_binds.cpp
    engines/tetraedge/game/main_menu.cpp
    engines/tetraedge/game/notifier.cpp
    engines/tetraedge/game/notifier.h
    engines/tetraedge/game/object3d.cpp
    engines/tetraedge/game/object3d.h
    engines/tetraedge/game/options_menu.cpp
    engines/tetraedge/game/puzzle_computer_hydra.cpp
    engines/tetraedge/game/puzzle_computer_pwd.cpp
    engines/tetraedge/game/puzzle_hanjie.cpp
    engines/tetraedge/game/puzzle_hanjie.h
    engines/tetraedge/game/question2.cpp
    engines/tetraedge/game/question2.h
    engines/tetraedge/game/splash_screens.cpp
    engines/tetraedge/game/syberia_game.cpp
    engines/tetraedge/game/syberia_game.h
    engines/tetraedge/te/te_3d_texture.cpp
    engines/tetraedge/te/te_3d_texture_opengl.cpp
    engines/tetraedge/te/te_3d_texture_tinygl.cpp
    engines/tetraedge/te/te_button_layout.cpp
    engines/tetraedge/te/te_button_layout.h
    engines/tetraedge/te/te_camera.cpp
    engines/tetraedge/te/te_core.cpp
    engines/tetraedge/te/te_core.h
    engines/tetraedge/te/te_font2.cpp
    engines/tetraedge/te/te_font2.h
    engines/tetraedge/te/te_font3.cpp
    engines/tetraedge/te/te_font3.h
    engines/tetraedge/te/te_free_move_zone.cpp
    engines/tetraedge/te/te_image.cpp
    engines/tetraedge/te/te_images_sequence.cpp
    engines/tetraedge/te/te_interpolation.cpp
    engines/tetraedge/te/te_lua_gui.cpp
    engines/tetraedge/te/te_lua_gui.h
    engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
    engines/tetraedge/te/te_lua_thread.cpp
    engines/tetraedge/te/te_material.cpp
    engines/tetraedge/te/te_material.h
    engines/tetraedge/te/te_model.cpp
    engines/tetraedge/te/te_model.h
    engines/tetraedge/te/te_model_animation.cpp
    engines/tetraedge/te/te_music.cpp
    engines/tetraedge/te/te_music.h
    engines/tetraedge/te/te_resource.h
    engines/tetraedge/te/te_resource_manager.cpp
    engines/tetraedge/te/te_resource_manager.h
    engines/tetraedge/te/te_scene_warp.cpp
    engines/tetraedge/te/te_scene_warp.h
    engines/tetraedge/te/te_scummvm_codec.h
    engines/tetraedge/te/te_sound_manager.cpp
    engines/tetraedge/te/te_sprite_layout.cpp
    engines/tetraedge/te/te_sprite_layout.h
    engines/tetraedge/te/te_tiled_surface.cpp
    engines/tetraedge/te/te_tiled_surface.h
    engines/tetraedge/te/te_tiled_texture.cpp
    engines/tetraedge/te/te_tiled_texture.h
    engines/tetraedge/te/te_warp.cpp
    engines/tetraedge/te/te_warp.h
    engines/tetraedge/te/te_xml_gui.cpp
    engines/tetraedge/tetraedge.cpp


diff --git a/engines/tetraedge/game/amerzone_game.cpp b/engines/tetraedge/game/amerzone_game.cpp
index 5af4b0cdeae..dc44e8ec3f1 100644
--- a/engines/tetraedge/game/amerzone_game.cpp
+++ b/engines/tetraedge/game/amerzone_game.cpp
@@ -81,11 +81,12 @@ bool AmerzoneGame::changeWarp(const Common::String &rawZone, const Common::Strin
 		_warpY->setFov((float)(fov * M_PI / 180.0));
 	}
 
-	Common::String zone = rawZone;
+	Common::Path zone;
 	if (rawZone.contains('\\')) {
-		// Replace '\'s which our core understands
-		Common::Path converted(rawZone, '\\');
-		zone = converted.toString();
+		// Split path components on '\'
+		zone = Common::Path(rawZone, '\\');
+	} else {
+		zone = Common::Path(rawZone, '/');
 	}
 
 	_warpY->load(zone, false);
@@ -108,13 +109,13 @@ bool AmerzoneGame::changeWarp(const Common::String &rawZone, const Common::Strin
 	}
 	_gameSounds.clear();
 
-	Common::String sceneXml = zone;
+	Common::String sceneXml = zone.baseName();
 	size_t dotpos = sceneXml.rfind('.');
 	if (dotpos != Common::String::npos)
 		sceneXml = sceneXml.substr(0, dotpos);
 	sceneXml += ".xml";
 	TeSceneWarp sceneWarp;
-	sceneWarp.load(sceneXml, _warpY, false);
+	sceneWarp.load(zone.getParent().appendComponent(sceneXml), _warpY, false);
 
 	// NOTE: Original uses FLT_MAX here but that can cause overflows, just use a big number.
 	_xAngleMin = 1e8;
@@ -125,7 +126,7 @@ bool AmerzoneGame::changeWarp(const Common::String &rawZone, const Common::Strin
 	dotpos = sceneXml.rfind('.');
 	Common::String sceneLua = sceneXml.substr(0, dotpos);
 	sceneLua += ".lua";
-	_luaScript.load(core->findFile(sceneLua));
+	_luaScript.load(core->findFile(zone.getParent().appendComponent(sceneLua)));
 	_luaScript.execute();
 	_luaScript.execute("OnWarpEnter");
 	if (fadeFlag) {
@@ -579,7 +580,7 @@ bool AmerzoneGame::onVideoFinished() {
 	_inGameGui.buttonLayoutChecked("videoBackgroundButton")->setVisible(false);
 	_inGameGui.buttonLayoutChecked("skipVideoButton")->setVisible(false);
 	TeSpriteLayout *video = _inGameGui.spriteLayoutChecked("video");
-	Common::String vidPath = video->_tiledSurfacePtr->loadedPath();
+	Common::Path vidPath = video->_tiledSurfacePtr->loadedPath();
 	video->setVisible(false);
 	video->_tiledSurfacePtr->unload();
 	video->_tiledSurfacePtr->setLoadedPath("");
@@ -588,7 +589,7 @@ bool AmerzoneGame::onVideoFinished() {
 	if (app->musicOn())
 		app->music().play();
 	_running = true;
-	_luaScript.execute("OnMovieFinished", vidPath);
+	_luaScript.execute("OnMovieFinished", vidPath.toString('/'));
 	return false;
 }
 
diff --git a/engines/tetraedge/game/application.h b/engines/tetraedge/game/application.h
index f3e307c5e79..088051e5f71 100644
--- a/engines/tetraedge/game/application.h
+++ b/engines/tetraedge/game/application.h
@@ -106,7 +106,7 @@ public:
 	const Common::String &firstWarpPath() { return _firstWarpPath; }
 	const Common::String &firstZone() { return _firstZone; }
 	const Common::String &firstScene() { return _firstScene; }
-	const Common::String &defaultCursor() { return _defaultCursor; }
+	const Common::Path &defaultCursor() { return _defaultCursor; }
 	TeLayout &frontLayout() { return _frontLayout; };
 	TeLayout &frontOrientationLayout() { return _frontOrientationLayout; }
 	TeLayout &backLayout() { return _backLayout; }
@@ -151,7 +151,7 @@ private:
 	Common::String _firstWarpPath;
 	Common::String _firstZone;
 	Common::String _firstScene;
-	Common::String _defaultCursor;
+	Common::Path _defaultCursor;
 
 	Common::Array<Common::String> _unrecalAnims;
 
diff --git a/engines/tetraedge/game/billboard.cpp b/engines/tetraedge/game/billboard.cpp
index edf113ed5fe..6cd6f1d8aa6 100644
--- a/engines/tetraedge/game/billboard.cpp
+++ b/engines/tetraedge/game/billboard.cpp
@@ -32,14 +32,14 @@ namespace Tetraedge {
 Billboard::Billboard() : _hasPos2(false) {
 }
 
-bool Billboard::load(const Common::String &path) {
+bool Billboard::load(const Common::Path &path) {
 	_model = new TeModel();
 	TeIntrusivePtr<Te3DTexture> texture = Te3DTexture::makeInstance();
 	SyberiaGame *game = dynamic_cast<SyberiaGame *>(g_engine->getGame());
 	TeCore *core = g_engine->getCore();
 	Common::FSNode texnode = core->findFile(game->sceneZonePath().join(path));
 	texture->load(texnode);
-	_model->setName(path);
+	_model->setName(path.toString('/'));
 	Common::Array<TeVector3f32> quad;
 	quad.resize(4);
 	_model->setQuad(texture, quad, TeColor(0xff, 0xff, 0xff, 0xff));
diff --git a/engines/tetraedge/game/billboard.h b/engines/tetraedge/game/billboard.h
index 3860294c713..d973d830afa 100644
--- a/engines/tetraedge/game/billboard.h
+++ b/engines/tetraedge/game/billboard.h
@@ -36,7 +36,7 @@ class Billboard : public TeObject {
 public:
 	Billboard();
 
-	bool load(const Common::String &path);
+	bool load(const Common::Path &path);
 
 	void calcVertex();
 	void position(const TeVector3f32 &pos);
diff --git a/engines/tetraedge/game/bonus_menu.cpp b/engines/tetraedge/game/bonus_menu.cpp
index 61459b70bb3..e0541620f5a 100644
--- a/engines/tetraedge/game/bonus_menu.cpp
+++ b/engines/tetraedge/game/bonus_menu.cpp
@@ -33,10 +33,10 @@ namespace Tetraedge {
 BonusMenu::BonusMenu() : _pageNo(0) {
 }
 
-void BonusMenu::enter(const Common::String &scriptName) {
+void BonusMenu::enter(const Common::Path &scriptName) {
 	bool loaded = load(scriptName);
 	if (!loaded)
-		error("BonusMenu::enter: failed to load %s", scriptName.c_str());
+		error("BonusMenu::enter: failed to load %s", scriptName.toString(Common::Path::kNativeSeparator).c_str());
 	Application *app = g_engine->getApplication();
 	app->frontLayout().addChild(layoutChecked("menu"));
 	SyberiaGame *game = dynamic_cast<SyberiaGame *>(g_engine->getGame());
@@ -102,7 +102,7 @@ void BonusMenu::enter(const Common::String &scriptName) {
 		rightBtn->onMouseClickValidated().add(this, &BonusMenu::onRightButton);
 
 	// TODO: more stuff here with "text" values
-	warning("TODO: Finish BonusMenu::enter(%s)", scriptName.c_str());
+	warning("TODO: Finish BonusMenu::enter(%s)", scriptName.toString(Common::Path::kNativeSeparator).c_str());
 
 	TeButtonLayout *pictureBtn = buttonLayout("fullScreenPictureButton");
 	if (pictureBtn) {
@@ -240,7 +240,7 @@ Common::String BonusMenu::SaveButton::path() const {
 bool BonusMenu::SaveButton::onLoadSave() {
 	_menu->buttonLayoutChecked("menu")->setVisible(false);
 	TeSpriteLayout *pic = _menu->spriteLayoutChecked("fullScreenPicture");
-	const Common::String picName = child(0)->child(4)->name();
+	const Common::Path picName(child(0)->child(4)->name());
 	pic->load(picName);
 
 	TeSpriteLayout *picLayout = _menu->spriteLayoutChecked("fullScreenPictureLayout");
diff --git a/engines/tetraedge/game/bonus_menu.h b/engines/tetraedge/game/bonus_menu.h
index 1baa34ee24c..39ee11248ce 100644
--- a/engines/tetraedge/game/bonus_menu.h
+++ b/engines/tetraedge/game/bonus_menu.h
@@ -48,7 +48,7 @@ public:
 	};
 
 	virtual void enter() override;
-	virtual void enter(const Common::String &scriptName);
+	virtual void enter(const Common::Path &scriptName);
 	void leave() override;
 
 	void loadGame(Common::String &name) {
diff --git a/engines/tetraedge/game/character.cpp b/engines/tetraedge/game/character.cpp
index 785875de15c..362e08c2388 100644
--- a/engines/tetraedge/game/character.cpp
+++ b/engines/tetraedge/game/character.cpp
@@ -132,7 +132,7 @@ void Character::addCallback(const Common::String &animKey, const Common::String
 
 		// Another difference.. the original messes with paths a bit - just
 		// use the file name, since it's already limited by character.
-		Common::String animName = animPath.getLastComponent().toString();
+		Common::String animName = animPath.baseName();
 		if (animName.empty())
 			animName = animPath.toString();
 
@@ -143,12 +143,12 @@ void Character::addCallback(const Common::String &animKey, const Common::String
 			Common::Array<Callback *> callbacks;
 			callbacks.push_back(c);
 
-			_callbacks.setVal(animKeyPath.getLastComponent().toString(), callbacks);
+			_callbacks.setVal(animKeyPath.baseName(), callbacks);
 		}
 	} else if (g_engine->gameType() == TetraedgeEngine::kSyberia2){
 		// Syberia 2 is simpler, it always uses a lower-case version of the anim
 		// file in the passed key.
-		Common::String key = Common::Path(animKey).getLastComponent().toString();
+		Common::String key = Common::Path(animKey).baseName();
 		key.toLowercase();
 		if (_callbacks.contains(key)) {
 			_callbacks[key].push_back(c);
@@ -302,7 +302,7 @@ void Character::deleteAnim() {
 void Character::deleteCallback(const Common::String &key, const Common::String &fnName, float f) {
 	_callbacksChanged = true;
 	assert(_model->anim());
-	Common::String animFile = _model->anim()->loadedPath().getLastComponent().toString();
+	Common::String animFile = _model->anim()->loadedPath().baseName();
 	if (!_callbacks.contains(animFile))
 		return;
 
@@ -347,7 +347,7 @@ bool Character::isFramePassed(int frameno) {
 }
 
 bool Character::isWalkEnd() {
-	const Common::String animFile = _model->anim()->loadedPath().getLastComponent().toString();
+	const Common::String animFile = _model->anim()->loadedPath().baseName();
 	for (const auto & walkSettings : _characterSettings._walkSettings) {
 		if (walkSettings._value._walkParts[WalkPart_EndD]._file.contains(animFile)
 				|| walkSettings._value._walkParts[WalkPart_EndG]._file.contains(animFile))
@@ -439,7 +439,7 @@ bool Character::loadModel(const Common::String &mname, bool unused) {
 }
 
 /*static*/
-bool Character::loadSettings(const Common::String &path) {
+bool Character::loadSettings(const Common::Path &path) {
 	CharacterSettingsXmlParser parser;
 	parser.setAllowText();
 	if (_globalCharacterSettings)
@@ -452,7 +452,7 @@ bool Character::loadSettings(const Common::String &path) {
 	// patch them before parsing.
 	Common::File xmlFile;
 	if (!xmlFile.open(path))
-		error("Character::loadSettings: Can't open %s", path.c_str());
+		error("Character::loadSettings: Can't open %s", path.toString(Common::Path::kNativeSeparator).c_str());
 	const int64 bufsize = xmlFile.size();
 	char *buf = new char[bufsize+1];
 	buf[bufsize] = '\0';
@@ -478,10 +478,10 @@ bool Character::loadSettings(const Common::String &path) {
 	}
 
 	if (!parser.loadBuffer((const byte *)fixedbuf.c_str(), bufsize))
-		error("Character::loadSettings: Can't open %s", path.c_str());
+		error("Character::loadSettings: Can't open %s", path.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (!parser.parse())
-		error("Character::loadSettings: Can't parse %s", path.c_str());
+		error("Character::loadSettings: Can't parse %s", path.toString(Common::Path::kNativeSeparator).c_str());
 
 	return true;
 }
@@ -492,7 +492,7 @@ bool Character::onBonesUpdate(const Common::String &boneName, TeMatrix4x4 &boneM
 
 	Game *game = g_engine->getGame();
 	if (boneName == rootBone()) {
-		const Common::String animfile = _model->anim()->loadedPath().getLastComponent().toString();
+		const Common::String animfile = _model->anim()->loadedPath().baseName();
 		bool resetX = false;
 		if (game->scene()._character == this) {
 			for (const auto &walkSettings : _characterSettings._walkSettings) {
@@ -604,7 +604,7 @@ bool Character::onModelAnimationFinished() {
 		return false;
 
 	const Common::Path loadedPath = _model->anim()->loadedPath();
-	const Common::String animfile = loadedPath.getLastComponent().toString();
+	const Common::String animfile = loadedPath.baseName();
 
 	bool shouldAdjust = true;
 	for (const auto &unrecal : g_engine->getApplication()->unrecalAnims()) {
@@ -661,9 +661,9 @@ bool Character::onModelAnimationFinished() {
 		_onCharacterAnimFinishedSignal.call(_model->name());
 	}
 
-	Common::Path setAnimNamePath = _setAnimName;
-	Common::String setAnimNameFile = setAnimNamePath.getLastComponent().toString();
-	Common::String loadedPathFile = loadedPath.getLastComponent().toString();
+	Common::Path setAnimNamePath(_setAnimName);
+	Common::String setAnimNameFile = setAnimNamePath.baseName();
+	Common::String loadedPathFile = loadedPath.baseName();
 	if (_returnToIdleAnim && loadedPathFile.contains(setAnimNameFile)) {
 		_notWalkAnim = false;
 		_returnToIdleAnim = false;
@@ -681,7 +681,7 @@ void Character::permanentUpdate() {
 	_callbacksChanged = false;
 	// Diverge from original - just use filename for anim callbacks as the
 	// original does werid things with paths.
-	Common::String animFile = animPath.getLastComponent().toString();
+	Common::String animFile = animPath.baseName();
 	if (g_engine->gameType() == TetraedgeEngine::kSyberia2)
 		animFile.toLowercase();
 
diff --git a/engines/tetraedge/game/character.h b/engines/tetraedge/game/character.h
index 9c63b80ce87..afe70b65eb1 100644
--- a/engines/tetraedge/game/character.h
+++ b/engines/tetraedge/game/character.h
@@ -126,7 +126,7 @@ public:
 	int leftStepFrame(enum WalkPart walkpart);
 	int rightStepFrame(enum WalkPart walkpart);
 	bool loadModel(const Common::String &name, bool unused);
-	static bool loadSettings(const Common::String &path);
+	static bool loadSettings(const Common::Path &path);
 
 	bool onBonesUpdate(const Common::String &boneName, TeMatrix4x4 &boneMatrix);
 	bool onModelAnimationFinished();
diff --git a/engines/tetraedge/game/confirm.cpp b/engines/tetraedge/game/confirm.cpp
index 3bc4bb41a47..b837e2141ba 100644
--- a/engines/tetraedge/game/confirm.cpp
+++ b/engines/tetraedge/game/confirm.cpp
@@ -32,7 +32,7 @@ namespace Tetraedge {
 Confirm::Confirm() {
 }
 
-void Confirm::enter(const Common::String &guiPath, const Common::String &y) {
+void Confirm::enter(const Common::Path &guiPath, const Common::String &y) {
 	_gui.load(guiPath);
 	TeLayout *backgroundLayout = _gui.layout("background");
 	if (!backgroundLayout) {
diff --git a/engines/tetraedge/game/confirm.h b/engines/tetraedge/game/confirm.h
index 7e3e5a4a1ff..a586d13da9c 100644
--- a/engines/tetraedge/game/confirm.h
+++ b/engines/tetraedge/game/confirm.h
@@ -33,7 +33,7 @@ class Confirm {
 public:
 	Confirm();
 
-	void enter(const Common::String &guiPath, const Common::String &y);
+	void enter(const Common::Path &guiPath, const Common::String &y);
 	void leave();
 
 	bool onButtonNo();
diff --git a/engines/tetraedge/game/credits.cpp b/engines/tetraedge/game/credits.cpp
index 3f48f112e95..fab8e05cff3 100644
--- a/engines/tetraedge/game/credits.cpp
+++ b/engines/tetraedge/game/credits.cpp
@@ -40,7 +40,7 @@ void Credits::enter(bool returnToOptions) {
 	Application *app = g_engine->getApplication();
 	app->frontLayout().addChild(_gui.layoutChecked("menu"));
 
-	Common::String musicPath = _gui.value("musicPath").toString();
+	Common::Path musicPath(_gui.value("musicPath").toString(), '/');
 	if (!app->music().isPlaying() || app->music().path() != musicPath) {
 		app->music().stop();
 		app->music().load(musicPath);
@@ -182,13 +182,13 @@ bool Credits::onBackgroundAnimFinishedSyb2() {
 		_curveAnim._endVal = clear;
 		TeSpriteLayout *fgLayout = _gui.spriteLayout("foreground");
 		TeVariant fgFile = _gui.value(Common::String::format("foregrounds%d", _animCounter));
-		fgLayout->load(fgFile.toString());
+		fgLayout->load(Common::Path(fgFile.toString()));
 	} else {
 		_curveAnim._startVal = clear;
 		_curveAnim._endVal = white;
 		TeSpriteLayout *fgLayout = _gui.spriteLayout("foreground1");
 		TeVariant fgFile = _gui.value(Common::String::format("foregrounds%d", _animCounter));
-		fgLayout->load(fgFile.toString());
+		fgLayout->load(Common::Path(fgFile.toString()));
 	}
 
 	_curveAnim.play();
diff --git a/engines/tetraedge/game/dialog2.cpp b/engines/tetraedge/game/dialog2.cpp
index b1b625480fb..f1b0885da67 100644
--- a/engines/tetraedge/game/dialog2.cpp
+++ b/engines/tetraedge/game/dialog2.cpp
@@ -63,7 +63,7 @@ void Dialog2::launchNextDialog() {
 		const Common::String formatStr = _gui.value("textFormat").toString();
 		Common::String formattedVal = Common::String::format(formatStr.c_str(), _currentDialogData._stringVal.c_str());
 		_gui.textLayout("text")->setText(formattedVal);
-		_music.load(_currentDialogData._sound.toString());
+		_music.load(_currentDialogData._sound);
 		_music.setChannelName("dialog");
 		_music.play();
 		if (!_currentDialogData._charname.empty()) {
diff --git a/engines/tetraedge/game/documents_browser.cpp b/engines/tetraedge/game/documents_browser.cpp
index d33218a01e3..e8671dfd5e7 100644
--- a/engines/tetraedge/game/documents_browser.cpp
+++ b/engines/tetraedge/game/documents_browser.cpp
@@ -122,7 +122,7 @@ void DocumentsBrowser::loadZoomed() {
 	}
 }
 
-void DocumentsBrowser::loadXMLFile(const Common::String &path) {
+void DocumentsBrowser::loadXMLFile(const Common::Path &path) {
 	Common::FSNode node = g_engine->getCore()->findFile(path);
 	Common::File xmlfile;
 	xmlfile.open(node);
diff --git a/engines/tetraedge/game/documents_browser.h b/engines/tetraedge/game/documents_browser.h
index 1d0594e78e1..5a6a6e9bedd 100644
--- a/engines/tetraedge/game/documents_browser.h
+++ b/engines/tetraedge/game/documents_browser.h
@@ -68,7 +68,7 @@ public:
 
 
 private:
-	void loadXMLFile(const Common::String &path);
+	void loadXMLFile(const Common::Path &path);
 
 	bool onDocumentSelected(Document &doc);
 	bool onNextPage();
diff --git a/engines/tetraedge/game/game.cpp b/engines/tetraedge/game/game.cpp
index fbf633d052f..31a8141ff49 100644
--- a/engines/tetraedge/game/game.cpp
+++ b/engines/tetraedge/game/game.cpp
@@ -295,7 +295,7 @@ void Game::pauseMovie() {
 }
 */
 
-bool Game::playMovie(const Common::String &vidPath, const Common::String &musicPath, float volume /* = 1.0f */) {
+bool Game::playMovie(const Common::Path &vidPath, const Common::Path &musicPath, float volume /* = 1.0f */) {
 	Application *app = g_engine->getApplication();
 	app->captureFade();
 	TeButtonLayout *videoBackgroundButton = _inGameGui.buttonLayoutChecked("videoBackgroundButton");
@@ -339,7 +339,7 @@ bool Game::playMovie(const Common::String &vidPath, const Common::String &musicP
 		app->fade();
 		return true;
 	} else {
-		warning("Failed to load movie %s", vidPath.c_str());
+		warning("Failed to load movie %s", vidPath.toString(Common::Path::kNativeSeparator).c_str());
 		// Ensure the correct finished event gets called anyway.
 		videoSpriteLayout->_tiledSurfacePtr->setLoadedPath(vidPath);
 		onVideoFinished();
@@ -356,7 +356,7 @@ void Game::playSound(const Common::String &name, int repeats, float volume) {
 		sound->setName(name);
 		sound->setChannelName("sfx");
 		sound->repeat(false);
-		sound->load(name);
+		sound->load(Common::Path(name));
 		sound->volume(volume);
 		if (!sound->play()) {
 			game->luaScript().execute("OnFreeSoundFinished", name);
@@ -369,9 +369,10 @@ void Game::playSound(const Common::String &name, int repeats, float volume) {
 			_gameSounds.push_back(sound);
 		}
 	} else if (repeats == -1) {
+		const Common::Path pathName(name);
 		for (GameSound *snd : _gameSounds) {
-			const Common::String accessName = snd->getAccessName();
-			if (accessName == name) {
+			const Common::Path accessName = snd->getAccessName();
+			if (accessName == pathName) {
 				snd->setRetain(true);
 				return;
 			}
@@ -379,7 +380,7 @@ void Game::playSound(const Common::String &name, int repeats, float volume) {
 
 		GameSound *sound = new GameSound();
 		sound->setChannelName("sfx");
-		sound->load(name);
+		sound->load(pathName);
 		sound->volume(volume);
 		if (!sound->play()) {
 			game->luaScript().execute("OnFreeSoundFinished", name);
@@ -420,11 +421,11 @@ void Game::saveBackup(const Common::String &saveName) {
 	app->showLoadingIcon(false);
 }
 
-bool Game::setBackground(const Common::String &name) {
+bool Game::setBackground(const Common::Path &name) {
 	return _scene.changeBackground(name);
 }
 
-void Game::setCurrentObjectSprite(const Common::String &spritePath) {
+void Game::setCurrentObjectSprite(const Common::Path &spritePath) {
 	TeSpriteLayout *currentSprite = _inGameGui.spriteLayout("currentObjectSprite");
 	if (currentSprite) {
 		if (spritePath.empty())
@@ -460,9 +461,10 @@ bool Game::startAnimation(const Common::String &animName, int loopcount, bool re
 }
 
 void Game::stopSound(const Common::String &name) {
+	Common::Path path(name);
 	for (uint i = 0; i < _gameSounds.size(); i++) {
 		GameSound *sound = _gameSounds[i];
-		if (sound->rawPath() == name) {
+		if (sound->filePath() == path) {
 			sound->stop();
 			sound->deleteLater();
 			_gameSounds.remove_at(i);
@@ -518,10 +520,10 @@ Common::Error Game::syncGame(Common::Serializer &s) {
 		s.syncAsByte(_objectsTakenBits[i]);
 	s.syncAsUint32LE(_dialogsTold);
 	s.syncString(_prevSceneName);
-	Common::String mpath = _videoMusic.rawPath();
+	Common::String mpath(_videoMusic.filePath().toString('/'));
 	s.syncString(mpath);
 	if (s.isLoading())
-		_videoMusic.load(mpath);
+		_videoMusic.load(Common::Path(mpath, '/'));
 	if (!g_engine->gameIsAmerzone()) {
 		assert(_scene._character);
 		s.syncString(_scene._character->walkModeStr());
diff --git a/engines/tetraedge/game/game.h b/engines/tetraedge/game/game.h
index 4aff95024f0..b2c8612c9c5 100644
--- a/engines/tetraedge/game/game.h
+++ b/engines/tetraedge/game/game.h
@@ -83,14 +83,14 @@ public:
 
 	//void pauseMovie(); // Unused
 	//void pauseSounds() {}; // Unused, does nothing?
-	bool playMovie(const Common::String &vidPath, const Common::String &musicPath, float volume = 1.0f);
+	bool playMovie(const Common::Path &vidPath, const Common::Path &musicPath, float volume = 1.0f);
 	void playSound(const Common::String &name, int param_2, float volume);
 	void removeNoScale2Child(TeLayout *layout);
 	void resumeMovie();
 	void resumeSounds() {}; // does nothing?
 	void saveBackup(const Common::String &saveName);
-	bool setBackground(const Common::String &name);
-	void setCurrentObjectSprite(const Common::String &spritePath);
+	bool setBackground(const Common::Path &name);
+	void setCurrentObjectSprite(const Common::Path &spritePath);
 	bool showMarkers(bool val);
 	bool startAnimation(const Common::String &animName, int loopcount, bool reversed);
 	// void startAnimationPart(const Common::String &param_1, int param_2, int param_3, int param_4, bool param_5) {}; // Unused.
diff --git a/engines/tetraedge/game/in_game_scene.cpp b/engines/tetraedge/game/in_game_scene.cpp
index 4765875797f..2deac8b0b2a 100644
--- a/engines/tetraedge/game/in_game_scene.cpp
+++ b/engines/tetraedge/game/in_game_scene.cpp
@@ -105,7 +105,7 @@ void InGameScene::addAnchorZone(const Common::String &s1, const Common::String &
 	_anchorZones.push_back(zone);
 }
 
-bool InGameScene::addMarker(const Common::String &markerName, const Common::String &imgPath, float x, float y, const Common::String &locType, const Common::String &markerVal, float anchorX, float anchorY) {
+bool InGameScene::addMarker(const Common::String &markerName, const Common::Path &imgPath, float x, float y, const Common::String &locType, const Common::String &markerVal, float anchorX, float anchorY) {
 	const TeMarker *marker = findMarker(markerName);
 	if (!marker) {
 		SyberiaGame *game = dynamic_cast<SyberiaGame *>(g_engine->getGame());
@@ -204,7 +204,7 @@ Billboard *InGameScene::billboard(const Common::String &name) {
 	return nullptr;
 }
 
-bool InGameScene::changeBackground(const Common::String &name) {
+bool InGameScene::changeBackground(const Common::Path &name) {
 	Common::FSNode node = g_engine->getCore()->findFile(name);
 	if (node.isReadable()) {
 		_bgGui.spriteLayoutChecked("root")->load(node);
@@ -616,9 +616,9 @@ float InGameScene::getHeadVerticalRotation(Character *cter, const TeVector3f32 &
 	return angle;
 }
 
-Common::String InGameScene::imagePathMarker(const Common::String &name) {
+Common::Path InGameScene::imagePathMarker(const Common::String &name) {
 	if (!isMarker(name))
-		return Common::String();
+		return Common::Path();
 	Game *game = g_engine->getGame();
 	TeLayout *bg = game->forGui().layoutChecked("background");
 	for (Te3DObject2 *child : bg->childList()) {
@@ -627,7 +627,7 @@ Common::String InGameScene::imagePathMarker(const Common::String &name) {
 			return spritelayout->_tiledSurfacePtr->loadedPath();
 		}
 	}
-	return Common::String();
+	return Common::Path();
 }
 
 void InGameScene::initScroll() {
@@ -819,7 +819,7 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
 		//
 		Common::File xmlFile;
 		if (!xmlFile.open(node))
-			error("InGameScene::loadXml: Can't open %s", node.getPath().c_str());
+			error("InGameScene::loadXml: Can't open %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		const int64 bufsize = xmlFile.size();
 		char *buf = new char[bufsize+1];
 		buf[bufsize] = '\0';
@@ -839,11 +839,11 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
 	} else {
 		// Regular loading.
 		if (!parser.loadFile(node))
-			error("InGameScene::loadXml: Can't load %s", node.getPath().c_str());
+			error("InGameScene::loadXml: Can't load %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	if (!parser.parse())
-		error("InGameScene::loadXml: Can't parse %s", node.getPath().c_str());
+		error("InGameScene::loadXml: Can't parse %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	// loadFlamme and loadSnowCustom are handled by the above.
 
@@ -867,9 +867,9 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
 		ParticleXmlParser pparser;
 		pparser._scene = this;
 		if (!pparser.loadFile(pnode))
-			error("InGameScene::loadXml: Can't load %s", pnode.getPath().c_str());
+			error("InGameScene::loadXml: Can't load %s", pnode.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		if (!pparser.parse())
-			error("InGameScene::loadXml: Can't parse %s", pnode.getPath().c_str());
+			error("InGameScene::loadXml: Can't parse %s", pnode.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	TeMatrix4x4 camMatrix = currentCamera() ?
@@ -951,9 +951,9 @@ bool InGameScene::loadLights(const Common::FSNode &node) {
 	SceneLightsXmlParser parser(&_lights);
 
 	if (!parser.loadFile(node))
-		error("InGameScene::loadLights: Can't load %s", node.getPath().c_str());
+		error("InGameScene::loadLights: Can't load %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	if (!parser.parse())
-		error("InGameScene::loadLights: Can't parse %s", node.getPath().c_str());
+		error("InGameScene::loadLights: Can't parse %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	_shadowColor = parser.getShadowColor();
 	_shadowLightNo = parser.getShadowLightNo();
@@ -1037,9 +1037,9 @@ bool InGameScene::loadObjectMaterials(const Common::String &name) {
 	return retval;
 }
 
-bool InGameScene::loadObjectMaterials(const Common::String &path, const Common::String &name) {
+bool InGameScene::loadObjectMaterials(const Common::Path &path, const Common::String &name) {
 	// Seems like this is never used?
-	error("InGameScene::loadObjectMaterials(%s, %s)", path.c_str(), name.c_str());
+	error("InGameScene::loadObjectMaterials(%s, %s)", path.toString(Common::Path::kNativeSeparator).c_str(), name.c_str());
 }
 
 bool InGameScene::loadPlayerCharacter(const Common::String &name) {
@@ -1085,7 +1085,7 @@ bool InGameScene::loadCurve(const Common::String &name) {
 	TeCore *core = g_engine->getCore();
 	Common::FSNode node = core->findFile(path);
 	if (!node.isReadable()) {
-		warning("[InGameScene::loadCurve] Can't open file : %s.", path.toString().c_str());
+		warning("[InGameScene::loadCurve] Can't open file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	TeIntrusivePtr<TeBezierCurve> curve = new TeBezierCurve();
@@ -1100,7 +1100,7 @@ bool InGameScene::loadDynamicLightBloc(const Common::String &name, const Common:
 	Common::FSNode datnode = g_engine->getCore()->findFile(pdat);
 	Common::FSNode texnode = g_engine->getCore()->findFile(ptex);
 	if (!datnode.isReadable()) {
-		warning("[InGameScene::loadDynamicLightBloc] Can't open file : %s.", pdat.toString().c_str());
+		warning("[InGameScene::loadDynamicLightBloc] Can't open file : %s.", pdat.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -1158,7 +1158,7 @@ bool InGameScene::loadLight(const Common::String &name, const Common::String &zo
 	Common::Path datpath = _sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin");
 	Common::FSNode datnode = g_engine->getCore()->findFile(datpath);
 	if (!datnode.isReadable()) {
-		warning("[InGameScene::loadLight] Can't open file : %s.", datpath.toString().c_str());
+		warning("[InGameScene::loadLight] Can't open file : %s.", datpath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -1181,7 +1181,7 @@ bool InGameScene::loadMask(const Common::String &name, const Common::String &tex
 	Common::Path texpath = _sceneFileNameBase(zone, scene).joinInPlace(texture);
 	Common::FSNode datnode = core->findFile(datpath);
 	if (!datnode.isReadable()) {
-		warning("[InGameScene::loadMask] Can't open file : %s.", datpath.toString().c_str());
+		warning("[InGameScene::loadMask] Can't open file : %s.", datpath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	TeModel *model = new TeModel();
@@ -1268,7 +1268,7 @@ bool InGameScene::loadShadowReceivingObject(const Common::String &name, const Co
 	Common::Path datpath = _sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin");
 	Common::FSNode datnode = g_engine->getCore()->findFile(datpath);
 	if (!datnode.isReadable()) {
-		warning("[InGameScene::loadShadowReceivingObject] Can't open file : %s.", datpath.toString().c_str());
+		warning("[InGameScene::loadShadowReceivingObject] Can't open file : %s.", datpath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	TeModel *model = new TeModel();
@@ -1313,7 +1313,7 @@ bool InGameScene::loadZBufferObject(const Common::String &name, const Common::St
 	Common::Path datpath = _sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin");
 	Common::FSNode datnode = g_engine->getCore()->findFile(datpath);
 	if (!datnode.isReadable()) {
-		warning("[InGameScene::loadZBufferObject] Can't open file : %s.", datpath.toString().c_str());
+		warning("[InGameScene::loadZBufferObject] Can't open file : %s.", datpath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	TeModel *model = new TeModel();
@@ -1371,7 +1371,7 @@ void InGameScene::loadBlockers() {
 
 	Common::File blockersfile;
 	if (!blockersfile.open(blockersPath)) {
-		warning("Couldn't open blockers file %s.", blockersPath.toString().c_str());
+		warning("Couldn't open blockers file %s.", blockersPath.toString(Common::Path::kNativeSeparator).c_str());
 		return;
 	}
 
@@ -1432,7 +1432,7 @@ bool InGameScene::loadBillboard(const Common::String &name) {
 	if (b)
 		return true;
 	b = new Billboard();
-	if (b->load(name)) {
+	if (b->load(Common::Path(name))) {
 		_billboards.push_back(b);
 		return true;
 	} else {
@@ -1532,7 +1532,7 @@ TeLight *InGameScene::shadowLight() {
 	return _lights[_shadowLightNo].get();
 }
 
-void InGameScene::setImagePathMarker(const Common::String &markerName, const Common::String &path) {
+void InGameScene::setImagePathMarker(const Common::String &markerName, const Common::Path &path) {
 	if (!isMarker(markerName))
 		return;
 
diff --git a/engines/tetraedge/game/in_game_scene.h b/engines/tetraedge/game/in_game_scene.h
index 01653c96aa4..4b5684d206f 100644
--- a/engines/tetraedge/game/in_game_scene.h
+++ b/engines/tetraedge/game/in_game_scene.h
@@ -142,13 +142,13 @@ public:
 		_blockingObjects.push_back(obj);
 	}
 	void addCallbackAnimation2D(const Common::String &param_1, const Common::String &param_2, float param_3);
-	bool addMarker(const Common::String &name, const Common::String &imgPath, float x, float y, const Common::String &locType, const Common::String &markerVal, float anchorX, float anchorY);
+	bool addMarker(const Common::String &name, const Common::Path &imgPath, float x, float y, const Common::String &locType, const Common::String &markerVal, float anchorX, float anchorY);
 	static float angularDistance(float a1, float a2);
 	bool aroundAnchorZone(const AnchorZone *zone);
 	TeLayout *background();
 	Billboard *billboard(const Common::String &name);
 	TeVector2f32 boundLayerSize();
-	bool changeBackground(const Common::String &name);
+	bool changeBackground(const Common::Path &name);
 	Character *character(const Common::String &name);
 	virtual void close() override;
 	// Original has a typo, "converPathToMesh", corrected.
@@ -178,7 +178,7 @@ public:
 	Common::Path getLightsFileName() const;
 	float getHeadHorizontalRotation(Character *cter, const TeVector3f32 &vec);
 	float getHeadVerticalRotation(Character *cter, const TeVector3f32 &vec);
-	Common::String imagePathMarker(const Common::String &name);
+	Common::Path imagePathMarker(const Common::String &name);
 	void initScroll();
 	bool isMarker(const Common::String &name);
 	bool isObjectBlocking(const Common::String &name);
@@ -195,7 +195,7 @@ public:
 	void loadMarkers(const Common::FSNode &node);
 	bool loadObject(const Common::String &oname);
 	bool loadObjectMaterials(const Common::String &name);
-	bool loadObjectMaterials(const Common::String &path, const Common::String &name);
+	bool loadObjectMaterials(const Common::Path &path, const Common::String &name);
 	bool loadPlayerCharacter(const Common::String &cname);
 
 	// Syberia 2 specific data..
@@ -228,7 +228,7 @@ public:
 	void removeBlockingObject(const Common::String &oname);
 
 	void reset();
-	void setImagePathMarker(const Common::String &markerName, const Common::String &path);
+	void setImagePathMarker(const Common::String &markerName, const Common::Path &path);
 	void setPositionCharacter(const Common::String &charName, const Common::String &freeMoveZoneName, const TeVector3f32 &position);
 	void setPositionMarker(const Common::String &name, const TeVector3f32 &vec);
 	void setStep(const Common::String &scene, const Common::String &step1, const Common::String &step2);
diff --git a/engines/tetraedge/game/inventory.cpp b/engines/tetraedge/game/inventory.cpp
index 314a9ae1cbc..5d7031eb194 100644
--- a/engines/tetraedge/game/inventory.cpp
+++ b/engines/tetraedge/game/inventory.cpp
@@ -515,8 +515,8 @@ void Inventory::selectedObject(InventoryObject *obj) {
 		pos.z() = selection->position().z();
 		selection->setPosition(pos);
 
-		const Common::String spritePathStr = obj->spritePath();
-		game->setCurrentObjectSprite(spritePathStr);
+		const Common::Path spritePath = obj->spritePath();
+		game->setCurrentObjectSprite(spritePath);
 
 		if (!g_engine->gameIsAmerzone()) {
 			const Common::String &objId = obj->name();
@@ -536,7 +536,7 @@ void Inventory::selectedObject(InventoryObject *obj) {
 					textObj->child(i)->setVisible(false);
 				}
 			}
-			game->inGameGui().spriteLayoutChecked("selectedObject")->load(spritePathStr);
+			game->inGameGui().spriteLayoutChecked("selectedObject")->load(spritePath);
 		}
 	}
 }
diff --git a/engines/tetraedge/game/inventory_object.cpp b/engines/tetraedge/game/inventory_object.cpp
index 8e4ce0f9d0e..8bf17bc5662 100644
--- a/engines/tetraedge/game/inventory_object.cpp
+++ b/engines/tetraedge/game/inventory_object.cpp
@@ -38,8 +38,8 @@ void InventoryObject::load(const Common::String &newName) {
 	// TODO: btn->setDoubleValidationProtectionEnabled(false)
 }
 
-Common::String InventoryObject::spritePath() {
-	return Common::Path("Inventory/Objects").join(name()).append(".png").toString();
+Common::Path InventoryObject::spritePath() {
+	return Common::Path("Inventory/Objects").join(name()).append(".png");
 }
 
 bool InventoryObject::onButtonDown() {
diff --git a/engines/tetraedge/game/inventory_object.h b/engines/tetraedge/game/inventory_object.h
index 0a9c4c782d8..ccee9fe5a14 100644
--- a/engines/tetraedge/game/inventory_object.h
+++ b/engines/tetraedge/game/inventory_object.h
@@ -33,7 +33,7 @@ public:
 	InventoryObject();
 
 	void load(const Common::String &name);
-	Common::String spritePath();
+	Common::Path spritePath();
 	bool onButtonDown();
 	TeSignal1Param<InventoryObject&> &selectedSignal() { return _selectedSignal; };
 
diff --git a/engines/tetraedge/game/lua_binds.cpp b/engines/tetraedge/game/lua_binds.cpp
index 80e299cb580..f2516f0ef76 100644
--- a/engines/tetraedge/game/lua_binds.cpp
+++ b/engines/tetraedge/game/lua_binds.cpp
@@ -62,7 +62,7 @@ static int tolua_ExportedFunctions_LoadObjectMaterials00(lua_State *L) {
 
 static void LoadObjectMaterials(const Common::String &imgname, const Common::String &objname) {
 	Game *game = g_engine->getGame();
-	bool result = game->scene().loadObjectMaterials(imgname, objname);
+	bool result = game->scene().loadObjectMaterials(Common::Path(imgname), objname);
 	if (!result)
 		error("[LoadObjectMaterials] Object \"%s\" doesn't exist in scene : \"%s\" or there is no material for this object.",
 				objname.c_str(), imgname.c_str());
@@ -89,17 +89,17 @@ static void PlayMovie(Common::String vidpath, Common::String musicpath) {
 		musicpath = "Videos/019.ogg";
 	if (vidpath == "Videos/sc18.ogv") {
 		// Need the correct path for callback, call this first.
-		game->playMovie(vidpath, musicpath);
+		game->playMovie(Common::Path(vidpath), Common::Path(musicpath));
 		vidpath = "Videos/I_018_P2_001.ogv";
 	}
 
-	game->playMovie(vidpath, musicpath);
+	game->playMovie(Common::Path(vidpath), Common::Path(musicpath));
 }
 
 static void PlayMovie(const Common::String &vidpath, const Common::String &musicpath, double volume) {
 	Game *game = g_engine->getGame();
 
-	if (!game->playMovie(vidpath, musicpath, (float)volume)) {
+	if (!game->playMovie(Common::Path(vidpath), Common::Path(musicpath), (float)volume)) {
 		warning("[PlayMovie] Movie \"%s\" doesn't exist.", vidpath.c_str());
 		return;
 	}
@@ -163,7 +163,7 @@ static int tolua_ExportedFunctions_PlayMovieAndWaitForEnd00(lua_State *L) {
 static void AddRandomSound(const Common::String &s1, const Common::String &s2, float f1, float f2){
 	SyberiaGame *game = dynamic_cast<SyberiaGame *>(g_engine->getGame());
 	assert(game);
-	game->addRandomSound(s1, s2, f1, f2);
+	game->addRandomSound(s1, Common::Path(s2), f1, f2);
 }
 
 static int tolua_ExportedFunctions_AddRandomSound00(lua_State *L) {
@@ -644,7 +644,7 @@ static int tolua_ExportedFunctions_DeleteCallbackPlayer00(lua_State *L) {
 static void AddMarker(const Common::String &markerName, const Common::String &imgPath, float x, float y,
 				const Common::String &loctype, const Common::String &markerVal, float anchorX, float anchorY) {
 	Game *game = g_engine->getGame();
-	game->scene().addMarker(markerName, imgPath, x, y, loctype, markerVal, anchorX, anchorY);
+	game->scene().addMarker(markerName, Common::Path(imgPath), x, y, loctype, markerVal, anchorX, anchorY);
 }
 
 static int tolua_ExportedFunctions_AddMarker00(lua_State *L) {
@@ -1478,7 +1478,7 @@ static int tolua_ExportedFunctions_RequestMainMenu00(lua_State *L) {
 
 static void SetBackground(const Common::String &name) {
 	Game *game = g_engine->getGame();
-	if (!game->setBackground(name))
+	if (!game->setBackground(Common::Path(name)))
 		warning("[SetBackground] Background \"%s\" doesn't exist.", name.c_str());
 }
 
@@ -1552,7 +1552,7 @@ static void PushAnswer(const Common::String &val, const Common::String &gui) {
 		locValStr = *locVal;
 	}
 	Game *game = g_engine->getGame();
-	game->question2().pushAnswer(val, locValStr, gui);
+	game->question2().pushAnswer(val, locValStr, Common::Path(gui));
 }
 
 static int tolua_ExportedFunctions_PushAnswer00(lua_State *L) {
@@ -2011,7 +2011,7 @@ static void PlayMusic(const Common::String &path, float volume) {
 	// change repeat value after starting.
 	music.stop();
 	music.repeat(g_engine->gameIsAmerzone());
-	music.load(path);
+	music.load(Common::Path(path));
 	if (!g_engine->getApplication()->musicOn())
 		return;
 	music.play();
diff --git a/engines/tetraedge/game/main_menu.cpp b/engines/tetraedge/game/main_menu.cpp
index c2b03298510..b324f90d6c3 100644
--- a/engines/tetraedge/game/main_menu.cpp
+++ b/engines/tetraedge/game/main_menu.cpp
@@ -94,7 +94,7 @@ void MainMenu::enter() {
 	if (music.isPlaying()) {
 		// TODO: something here??
 	}
-	music.load(value("musicPath").toString());
+	music.load(Common::Path(value("musicPath").toString()));
 	music.play();
 	music.volume(1.0f);
 
diff --git a/engines/tetraedge/game/notifier.cpp b/engines/tetraedge/game/notifier.cpp
index c4e3b6eafe2..8b9dcb7ff71 100644
--- a/engines/tetraedge/game/notifier.cpp
+++ b/engines/tetraedge/game/notifier.cpp
@@ -137,7 +137,7 @@ bool Notifier::onVisibleFinished() {
 	return false;
 }
 
-void Notifier::push(const Common::String &name, const Common::String &imgpath) {
+void Notifier::push(const Common::String &name, const Common::Path &imgpath) {
 	notifierData n = {name, imgpath};
 	_notifierDataArray.push_back(n);
 	launchNextnotifier();
diff --git a/engines/tetraedge/game/notifier.h b/engines/tetraedge/game/notifier.h
index afcea1aa2f2..6c39909f84c 100644
--- a/engines/tetraedge/game/notifier.h
+++ b/engines/tetraedge/game/notifier.h
@@ -36,7 +36,7 @@ public:
 	bool onFadeOutFinished();
 	bool onVisibleFinished();
 
-	void push(const Common::String &name, const Common::String &imgpath);
+	void push(const Common::String &name, const Common::Path &imgpath);
 	void unload();
 
 	TeLuaGUI &gui() { return _gui; }
@@ -44,7 +44,7 @@ public:
 private:
 	struct notifierData {
 		Common::String _name;
-		Common::String _imgpath;
+		Common::Path _imgpath;
 	};
 	Common::Array<notifierData> _notifierDataArray;
 	TeLuaGUI _gui;
diff --git a/engines/tetraedge/game/object3d.cpp b/engines/tetraedge/game/object3d.cpp
index 57f0000c263..c5507ae17f6 100644
--- a/engines/tetraedge/game/object3d.cpp
+++ b/engines/tetraedge/game/object3d.cpp
@@ -54,7 +54,7 @@ bool Object3D::loadModel(const Common::String &name) {
 		_modelFileName = settings->_value._modelFileName;
 		_defaultScale = settings->_value._defaultScale;
 		_modelPtr->setTexturePath("objects/Textures");
-		bool loaded = _modelPtr->load(Common::Path("objects").join(_modelFileName).toString());
+		bool loaded = _modelPtr->load(Common::Path("objects").join(_modelFileName));
 		if (loaded) {
 			_modelPtr->setName(name);
 			_modelPtr->setScale(_defaultScale);
@@ -93,7 +93,7 @@ void Object3D::setCurMovePos(const TeVector3f32 &vec) {
 }
 
 /*static*/
-bool Object3D::loadSettings(const Common::String &path) {
+bool Object3D::loadSettings(const Common::Path &path) {
 	if (_objectSettings)
 		delete _objectSettings;
 	_objectSettings = new Common::HashMap<Common::String, ObjectSettings>();
@@ -102,9 +102,9 @@ bool Object3D::loadSettings(const Common::String &path) {
 	parser.setAllowText();
 
 	if (!parser.loadFile(path))
-		error("Object3D::loadSettings: Can't load %s", path.c_str());
+		error("Object3D::loadSettings: Can't load %s", path.toString(Common::Path::kNativeSeparator).c_str());
 	if (!parser.parse())
-		error("Object3D::loadSettings: Can't parse %s", path.c_str());
+		error("Object3D::loadSettings: Can't parse %s", path.toString(Common::Path::kNativeSeparator).c_str());
 	parser.finalize();
 
 	return true;
diff --git a/engines/tetraedge/game/object3d.h b/engines/tetraedge/game/object3d.h
index a2ebd954a41..537bc1f941b 100644
--- a/engines/tetraedge/game/object3d.h
+++ b/engines/tetraedge/game/object3d.h
@@ -48,7 +48,7 @@ public:
 
 	bool loadModel(const Common::String &name);
 
-	static bool loadSettings(const Common::String &path);
+	static bool loadSettings(const Common::Path &path);
 	static void cleanup();
 
 	TeIntrusivePtr<TeModel> model() { return _modelPtr; }
diff --git a/engines/tetraedge/game/options_menu.cpp b/engines/tetraedge/game/options_menu.cpp
index 95ac29ee46b..cd20ae7204b 100644
--- a/engines/tetraedge/game/options_menu.cpp
+++ b/engines/tetraedge/game/options_menu.cpp
@@ -50,7 +50,7 @@ void OptionsMenu::enter() {
 	app->frontLayout().addChild(_gui2.buttonLayoutChecked("tuto"));
 	_gui2.buttonLayoutChecked("tuto")->setVisible(false);
 
-	const Common::String musicPath = value("musicPath").toString();
+	const Common::Path musicPath(value("musicPath").toString());
 	if (!app->music().isPlaying() || (app->music().getAccessName() != musicPath)) {
 		app->music().load(musicPath);
 		app->music().play();
@@ -157,7 +157,7 @@ bool OptionsMenu::onDialogVolumeMinusButton() {
 	if (!_music1.isPlaying()) {
 		_music1.setChannelName("dialog");
 		_music1.repeat(false);
-		_music1.load(value("dialogTestPath").toString());
+		_music1.load(Common::Path(value("dialogTestPath").toString()));
 		_music1.play();
 	}
 	return false;
@@ -176,7 +176,7 @@ bool OptionsMenu::onDialogVolumePlusButton() {
 	if (!_music1.isPlaying()) {
 		_music1.setChannelName("dialog");
 		_music1.repeat(false);
-		_music1.load(value("dialogTestPath").toString());
+		_music1.load(Common::Path(value("dialogTestPath").toString()));
 		_music1.play();
 	}
 	return false;
diff --git a/engines/tetraedge/game/puzzle_computer_hydra.cpp b/engines/tetraedge/game/puzzle_computer_hydra.cpp
index 777fd9356c5..c07deaf0db9 100644
--- a/engines/tetraedge/game/puzzle_computer_hydra.cpp
+++ b/engines/tetraedge/game/puzzle_computer_hydra.cpp
@@ -256,7 +256,7 @@ bool PuzzleComputerHydra::registerNewDigit(int digit) {
 	_enteredCoord[_axisNo] = digit;
 	_axisNo++;
 	const Common::String dname = Common::String::format("digit%d", _axisNo);
-	const Common::String dimg = Common::String::format("2D/puzzles/Computer_Hydra/%d.png", digit);
+	const Common::Path dimg(Common::String::format("2D/puzzles/Computer_Hydra/%d.png", digit));
 	_gui.spriteLayoutChecked(dname)->load(dimg);
 	_gui.spriteLayoutChecked(dname)->setVisible(true);
 	if (_axisNo == 3) {
diff --git a/engines/tetraedge/game/puzzle_computer_pwd.cpp b/engines/tetraedge/game/puzzle_computer_pwd.cpp
index 5f8ddcc5bb8..b2ab15c9472 100644
--- a/engines/tetraedge/game/puzzle_computer_pwd.cpp
+++ b/engines/tetraedge/game/puzzle_computer_pwd.cpp
@@ -152,14 +152,14 @@ bool PuzzleComputerPwd::registerNewDigit(int digit) {
 
 		TeSoundManager *sndMgr = g_engine->getSoundManager();
 		if (match) {
-			const Common::String snd = _gui.value("goodPassword").toString();
+			const Common::Path snd(_gui.value("goodPassword").toString());
 			sndMgr->playFreeSound(snd);
 			leave();
 			Game *game = g_engine->getGame();
 			game->luaScript().execute("OnComputerPwdPuzzleAnswered");
 			return true;
 		} else {
-			const Common::String snd = _gui.value("badPassword").toString();
+			const Common::Path snd(_gui.value("badPassword").toString());
 			sndMgr->playFreeSound(snd);
 			resetPwd();
 		}
diff --git a/engines/tetraedge/game/puzzle_hanjie.cpp b/engines/tetraedge/game/puzzle_hanjie.cpp
index 45d42b5ca2c..63e43378dca 100644
--- a/engines/tetraedge/game/puzzle_hanjie.cpp
+++ b/engines/tetraedge/game/puzzle_hanjie.cpp
@@ -60,7 +60,7 @@ void PuzzleHanjie::wakeUp() {
 		}
 	}
 	_backgroundNo = g_engine->getRandomNumber(4);
-	_bgImg = Common::String::format("%s%s.png", _gui.value("Background").c_str(), BG_NAMES[_backgroundNo]);
+	_bgImg = Common::Path(Common::String::format("%s%s.png", _gui.value("Background").c_str(), BG_NAMES[_backgroundNo]));
 	_bgSprite.load(_bgImg);
 	_bgSprite.setPosition(TeVector3f32(0, 0, 220));
 	_bgSprite.setVisible(true);
diff --git a/engines/tetraedge/game/puzzle_hanjie.h b/engines/tetraedge/game/puzzle_hanjie.h
index e8e09484bec..83b2f5362c3 100644
--- a/engines/tetraedge/game/puzzle_hanjie.h
+++ b/engines/tetraedge/game/puzzle_hanjie.h
@@ -51,7 +51,7 @@ private:
 	TeSpriteLayout *_foregroundSprite;
 	int _backgroundNo;
 	bool _entered;
-	Common::String _bgImg;
+	Common::Path _bgImg;
 	Common::String _soundBegin;
 	TeSpriteLayout _bgSprite;
 	bool _expectedVals[49];
diff --git a/engines/tetraedge/game/question2.cpp b/engines/tetraedge/game/question2.cpp
index 0d7394df0de..8df958a749b 100644
--- a/engines/tetraedge/game/question2.cpp
+++ b/engines/tetraedge/game/question2.cpp
@@ -91,13 +91,13 @@ bool Question2::onAnswerValidated(Answer &answer) {
 	return false;
 }
 
-void Question2::pushAnswer(const Common::String &name, const Common::String &locName, const Common::String &path) {
+void Question2::pushAnswer(const Common::String &name, const Common::String &locName, const Common::Path &path) {
 	Answer *answer = new Answer();
 	answer->load(name, locName, path);
 	answer->_onButtonValidatedSignal.add(this, &Question2::onAnswerValidated);
 	TeButtonLayout *blayout = dynamic_cast<TeButtonLayout *>(answer->layout());
 	if (!blayout)
-		error("No Answer button layout after loading %s!", path.c_str());
+		error("No Answer button layout after loading %s!", path.toString(Common::Path::kNativeSeparator).c_str());
 
 	blayout->setState(TeButtonLayout::BUTTON_STATE_UP);
 	_answers.push_back(answer);
@@ -105,7 +105,7 @@ void Question2::pushAnswer(const Common::String &name, const Common::String &loc
 	float xpos;
 	blayout->setSizeType(RELATIVE_TO_PARENT);
 	blayout->setPositionType(RELATIVE_TO_PARENT);
-	if (!path.contains("Cal_FIN.lua")) {
+	if (!path.baseName().contains("Cal_FIN.lua")) {
 		blayout->setSize(TeVector3f32(0.45f, 0.065f, 1.0f));
 		xpos = 0.3f;
 	} else {
@@ -133,7 +133,7 @@ TeLayout *Question2::Answer::layout() {
 	return _gui.layout("answer");
 }
 
-void Question2::Answer::load(const Common::String &name, const Common::String &locName, const Common::String &path) {
+void Question2::Answer::load(const Common::String &name, const Common::String &locName, const Common::Path &path) {
 	_str = name;
 	_gui.load(path);
 	TeButtonLayout *answerButton = _gui.buttonLayout("answer");
diff --git a/engines/tetraedge/game/question2.h b/engines/tetraedge/game/question2.h
index 4a2e9ad0f04..a73d4220017 100644
--- a/engines/tetraedge/game/question2.h
+++ b/engines/tetraedge/game/question2.h
@@ -36,7 +36,7 @@ public:
 	class Answer {
 	public:
 		TeLayout *layout();
-		void load(const Common::String &name, const Common::String &unk, const Common::String &path);
+		void load(const Common::String &name, const Common::String &unk, const Common::Path &path);
 		void unload();
 		bool onButtonValidated();
 
@@ -50,7 +50,7 @@ public:
 	void load();
 	bool isEntered() const { return _entered; }
 	bool onAnswerValidated(Answer &answer);
-	void pushAnswer(const Common::String &name, const Common::String &unk, const Common::String &path);
+	void pushAnswer(const Common::String &name, const Common::String &unk, const Common::Path &path);
 	void unload();
 	TeLuaGUI &gui() { return _gui; }
 	TeSignal1Param<const Common::String &> &onAnswerSignal() { return _onAnswerSignal; }
diff --git a/engines/tetraedge/game/splash_screens.cpp b/engines/tetraedge/game/splash_screens.cpp
index d7512307231..9378e8b93e2 100644
--- a/engines/tetraedge/game/splash_screens.cpp
+++ b/engines/tetraedge/game/splash_screens.cpp
@@ -64,7 +64,7 @@ bool SplashScreens::onAlarm() {
 	app->captureFade();
 	TeLuaGUI::unload();
 	const char *scriptStr = g_engine->gameIsAmerzone() ? "GUI/PC-MacOSX/Splash%d.lua" : "menus/splashes/splash%d.lua";
-	const Common::String scriptName = Common::String::format(scriptStr, _splashNo);
+	const Common::Path scriptName(Common::String::format(scriptStr, _splashNo));
 	_splashNo++;
 
 	if (ConfMan.getBool("skip_splash")) {
diff --git a/engines/tetraedge/game/syberia_game.cpp b/engines/tetraedge/game/syberia_game.cpp
index 3978ff56a98..22ed31aa86b 100644
--- a/engines/tetraedge/game/syberia_game.cpp
+++ b/engines/tetraedge/game/syberia_game.cpp
@@ -64,18 +64,19 @@ SyberiaGame::~SyberiaGame() {
 	delete _randomSound;
 }
 
-bool SyberiaGame::addAnimToSet(const Common::String &anim) {
+bool SyberiaGame::addAnimToSet(const Common::Path &anim) {
 	// Get path to lua script, eg scenes/ValVoralberg/14040/Set14040.lua
-	const Common::Path animPath(Common::String("scenes/") + anim + "/");
+	Common::Path animPath("scenes/");
+	animPath.joinInPlace(anim);
 
 	if (Common::File::exists(animPath)) {
-		const Common::StringArray parts = TetraedgeEngine::splitString(anim, '/');
+		const Common::StringArray parts = anim.splitComponents();
 		assert(parts.size() >= 2);
 
 		const Common::String layoutName = parts[1];
-		const Common::String path = Common::String("scenes/") + parts[0] + "/" + parts[1] + "/Set" + parts[1];
+		const Common::Path path = Common::Path("scenes/").appendComponent(parts[0]).appendComponent(parts[1]).appendComponent(Common::String::format("Set%s.lua", parts[1].c_str()));
 
-		_setAnimGui.load(path + ".lua");
+		_setAnimGui.load(path);
 
 		// Note: game makes this here, but never uses it..
 		// it seems like a random memory leak??
@@ -151,7 +152,7 @@ void SyberiaGame::addNoScaleChildren() {
 	_noScaleLayout->addChild(&_documentsBrowser.zoomedLayout());
 }
 
-void SyberiaGame::addRandomSound(const Common::String &name, const Common::String &path, float f1, float volume) {
+void SyberiaGame::addRandomSound(const Common::String &name, const Common::Path &path, float f1, float volume) {
 	if (!_randomSounds.contains(name)) {
 		_randomSounds[name] = Common::Array<RandomSound*>();
 	}
@@ -167,9 +168,7 @@ void SyberiaGame::addToBag(const Common::String &objid) {
 	if (_inventory.objectCount(objid) != 0)
 		return;
 	_inventory.addObject(objid);
-	Common::String imgpath("Inventory/Objects/");
-	imgpath += objid;
-	imgpath += ".png";
+	Common::Path imgpath = Common::Path("Inventory/Objects/").appendComponent(objid + ".png");
 	_notifier.push(_inventory.objectName(objid), imgpath);
 	for (int i = 0; i < NUM_OBJECTS_TAKEN_IDS; i++) {
 		if (objid == OBJECTS_TAKEN_IDS[i] && !_objectsTakenBits[i]) {
@@ -1130,7 +1129,7 @@ bool SyberiaGame::onVideoFinished() {
 	app->captureFade();
 
 	TeSpriteLayout *video = _inGameGui.spriteLayoutChecked("video");
-	Common::String vidPath = video->_tiledSurfacePtr->loadedPath();
+	Common::String vidPath = video->_tiledSurfacePtr->loadedPath().toString('/');
 	TeButtonLayout *btn = _inGameGui.buttonLayoutChecked("videoBackgroundButton");
 	btn->setVisible(false);
 	btn = _inGameGui.buttonLayoutChecked("skipVideoButton");
@@ -1228,7 +1227,7 @@ void SyberiaGame::playRandomSound(const Common::String &name) {
 		sound->_music.volume(sound->_volume);
 		sound->_music.onStopSignal().remove(sound, &RandomSound::onSoundFinished);
 		sound->_music.onStopSignal().add(sound, &RandomSound::onSoundFinished);
-		sound->_music.load(sound->_path.toString());
+		sound->_music.load(sound->_path);
 		sound->_music.repeat(false);
 		sound->_music.play();
 		// TODO: set a flag that it's playing?
diff --git a/engines/tetraedge/game/syberia_game.h b/engines/tetraedge/game/syberia_game.h
index f9a7d3e149b..9e8be38f9ab 100644
--- a/engines/tetraedge/game/syberia_game.h
+++ b/engines/tetraedge/game/syberia_game.h
@@ -75,7 +75,7 @@ public:
 	};
 
 	void addArtworkUnlocked(const Common::String &name, bool notify);
-	void addRandomSound(const Common::String &s1, const Common::String &s2, float f1, float f2);
+	void addRandomSound(const Common::String &s1, const Common::Path &s2, float f1, float f2);
 	void addToBag(const Common::String &objname) override;
 	void addToHand(const Common::String &objname);
 	void addToScore(int score);
@@ -125,7 +125,7 @@ public:
 	bool runModeEnabled() const { return _runModeEnabled; }
 
 private:
-	bool addAnimToSet(const Common::String &path);
+	bool addAnimToSet(const Common::Path &path);
 	void addNoScale2Children();
 	void addNoScaleChildren();
 
diff --git a/engines/tetraedge/te/te_3d_texture.cpp b/engines/tetraedge/te/te_3d_texture.cpp
index 9a2f95d8c3a..1918b914d1f 100644
--- a/engines/tetraedge/te/te_3d_texture.cpp
+++ b/engines/tetraedge/te/te_3d_texture.cpp
@@ -45,19 +45,19 @@ bool Te3DTexture::hasAlpha() const {
 
 /*static*/
 TeIntrusivePtr<Te3DTexture> Te3DTexture::load2(const Common::FSNode &node, bool alphaOnly) {
-	const Common::String fullPath = node.getPath() + ".3dtex";
+	const Common::Path fullPath = node.getPath().append(".3dtex");
 
 	TeResourceManager *resMgr = g_engine->getResourceManager();
 	if (!resMgr->exists(fullPath)) {
 		TeIntrusivePtr<Te3DTexture> retval(makeInstance());
 		if (!node.isReadable())
-			warning("Request to load unreadable texture %s", node.getPath().c_str());
+			warning("Request to load unreadable texture %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		if (alphaOnly)
 			retval->setLoadAlphaOnly();
 
 		bool result = retval->load(node);
 		if (!result)
-			warning("Failed loading texture %s", node.getPath().c_str());
+			warning("Failed loading texture %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 		retval->setAccessName(fullPath);
 		resMgr->addResource(retval.get());
@@ -71,7 +71,7 @@ bool Te3DTexture::load(const Common::FSNode &node) {
 	TeResourceManager *resmgr = g_engine->getResourceManager();
 	TeIntrusivePtr<TeImage> img = resmgr->getResource<TeImage>(node);
 	bool result = load(*img);
-	setAccessName(node.getPath() + ".3dtex");
+	setAccessName(node.getPath().append(".3dtex"));
 	return result;
 }
 
diff --git a/engines/tetraedge/te/te_3d_texture_opengl.cpp b/engines/tetraedge/te/te_3d_texture_opengl.cpp
index 65cb594629d..22102023ecd 100644
--- a/engines/tetraedge/te/te_3d_texture_opengl.cpp
+++ b/engines/tetraedge/te/te_3d_texture_opengl.cpp
@@ -111,7 +111,7 @@ void Te3DTextureOpenGL::forceTexData(uint gltexture, uint xsize, uint ysize) {
 }
 
 bool Te3DTextureOpenGL::load(const TeImage &img) {
-	setAccessName(img.getAccessName() + ".3dtex");
+	setAccessName(img.getAccessName().append(".3dtex"));
 
 	_width = img.w;
 	_height = img.h;
@@ -221,7 +221,7 @@ void Te3DTextureOpenGL::update(const TeImage &img, uint xoff, uint yoff) {
 	if (!img.w || !img.h)
 		return;
 
-	setAccessName(img.getAccessName() + ".3dtex");
+	setAccessName(img.getAccessName().append(".3dtex"));
 	glBindTexture(GL_TEXTURE_2D, _glTexture);
 	glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
 	glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
diff --git a/engines/tetraedge/te/te_3d_texture_tinygl.cpp b/engines/tetraedge/te/te_3d_texture_tinygl.cpp
index 9443f9d8119..745443fce8f 100644
--- a/engines/tetraedge/te/te_3d_texture_tinygl.cpp
+++ b/engines/tetraedge/te/te_3d_texture_tinygl.cpp
@@ -113,7 +113,7 @@ void Te3DTextureTinyGL::forceTexData(uint gltexture, uint xsize, uint ysize) {
 }
 
 bool Te3DTextureTinyGL::load(const TeImage &img) {
-	setAccessName(img.getAccessName() + ".3dtex");
+	setAccessName(img.getAccessName().append(".3dtex"));
 
 	_width = img.w;
 	_height = img.h;
@@ -184,7 +184,7 @@ void Te3DTextureTinyGL::update(const TeImage &img, uint xoff, uint yoff) {
 	if (!img.w || !img.h)
 		return;
 
-	setAccessName(img.getAccessName() + ".3dtex");
+	setAccessName(img.getAccessName().append(".3dtex"));
 	tglBindTexture(TGL_TEXTURE_2D, _glTexture);
 	// Note: these are unsupported in TGL but should be the defaults?
 	//tglPixelStorei(TGL_UNPACK_SWAP_BYTES, TGL_FALSE);
diff --git a/engines/tetraedge/te/te_button_layout.cpp b/engines/tetraedge/te/te_button_layout.cpp
index c1f422e83a9..a7dc0d433a1 100644
--- a/engines/tetraedge/te/te_button_layout.cpp
+++ b/engines/tetraedge/te/te_button_layout.cpp
@@ -107,28 +107,28 @@ bool TeButtonLayout::isMouseIn(const TeVector2s32 &mouseloc) {
 	}
 }
 
-void TeButtonLayout::load(const Common::String &upImg, const Common::String &downImg, const Common::String &overImg) {
+void TeButtonLayout::load(const Common::Path &upImg, const Common::Path &downImg, const Common::Path &overImg) {
 	TeSpriteLayout *upSprite = nullptr;
-	if (upImg.size()) {
+	if (!upImg.empty()) {
 		upSprite = new TeSpriteLayout();
 		if (!upSprite->load(upImg))
-			warning("Failed to load button up img %s", upImg.c_str());
+			warning("Failed to load button up img %s", upImg.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	setUpLayout(upSprite);
 
 	TeSpriteLayout *downSprite = nullptr;
-	if (downImg.size()) {
+	if (!downImg.empty()) {
 		downSprite = new TeSpriteLayout();
 		if (!downSprite->load(downImg))
-			warning("Failed to load button down img %s", downImg.c_str());
+			warning("Failed to load button down img %s", downImg.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	setDownLayout(downSprite);
 
 	TeSpriteLayout *overSprite = nullptr;
-	if (overImg.size()) {
+	if (!overImg.empty()) {
 		overSprite = new TeSpriteLayout();
 		if (!overSprite->load(overImg))
-			warning("Failed to load button over img %s", overImg.c_str());
+			warning("Failed to load button over img %s", overImg.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	setRollOverLayout(overSprite);
 	setHitZone(nullptr);
diff --git a/engines/tetraedge/te/te_button_layout.h b/engines/tetraedge/te/te_button_layout.h
index 18fb66cef68..1eca3c98f31 100644
--- a/engines/tetraedge/te/te_button_layout.h
+++ b/engines/tetraedge/te/te_button_layout.h
@@ -78,7 +78,7 @@ public:
 	void setClickPassThrough(bool val) {
 		_clickPassThrough = val;
 	}
-	void setValidationSound(const Common::String &val) {
+	void setValidationSound(const Common::Path &val) {
 		_validationSound = val;
 	}
 	void setValidationSoundVolume(float val) {
@@ -98,7 +98,7 @@ public:
 	void setIgnoreMouseEvents(bool val) { _ignoreMouseEvents = val; }
 
 	// From TeSpriteButton, a direct way to load the images.
-	void load(const Common::String &upImg, const Common::String &downImg, const Common::String &overImg);
+	void load(const Common::Path &upImg, const Common::Path &downImg, const Common::Path &overImg);
 
 private:
 	static bool _mousePositionChangedCatched;
@@ -111,7 +111,7 @@ private:
 
 	bool _clickPassThrough;
 	State _currentState;
-	Common::String _validationSound;
+	Common::Path _validationSound;
 	float _validationSoundVolume;
 
 	Common::Array<uint> _intArr;
diff --git a/engines/tetraedge/te/te_camera.cpp b/engines/tetraedge/te/te_camera.cpp
index bd294b1f1b4..5bee6b2235e 100644
--- a/engines/tetraedge/te/te_camera.cpp
+++ b/engines/tetraedge/te/te_camera.cpp
@@ -166,7 +166,7 @@ Math::Ray TeCamera::getRay(const TeVector2s32 &pxloc) {
 }
 
 void TeCamera::loadXml(const Common::Path &path) {
-	setName(path.getLastComponent().toString());
+	setName(path.baseName());
 	_projectionMatrixType = 3;
 	TeCore *core = g_engine->getCore();
 	Common::FSNode node = core->findFile(path);
@@ -179,17 +179,17 @@ void TeCamera::loadXml(const Common::Path &path) {
 		if (pos != Common::String::npos) {
 			spath.replace(pos + 4, 1, "0");
 		}
-		node = core->findFile(spath);
+		node = core->findFile(Common::Path(spath, '/'));
 	}
 	if (!node.isReadable()) {
-		warning("Can't open camera data %s", path.toString().c_str());
+		warning("Can't open camera data %s", path.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	TeCameraXmlParser parser;
 	parser._cam = this;
 	if (!parser.loadFile(node))
-		error("TeCamera::loadXml: can't load file %s", node.getPath().c_str());
+		error("TeCamera::loadXml: can't load file %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	if (!parser.parse())
-		error("TeCamera::loadXml: error parsing %s", node.getPath().c_str());
+		error("TeCamera::loadXml: error parsing %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 }
 
 /*
diff --git a/engines/tetraedge/te/te_core.cpp b/engines/tetraedge/te/te_core.cpp
index b08fab55068..d4a863534bd 100644
--- a/engines/tetraedge/te/te_core.cpp
+++ b/engines/tetraedge/te/te_core.cpp
@@ -84,7 +84,7 @@ TeICodec *TeCore::createVideoCodec(const Common::String &extn) {
 }
 
 TeICodec *TeCore::createVideoCodec(const Common::Path &path) {
-	const Common::String filename = path.getLastComponent().toString();
+	const Common::String filename = path.baseName();
 	if (!filename.contains('.'))
 		return nullptr;
 	Common::String extn = filename.substr(filename.findLastOf('.') + 1);
@@ -152,7 +152,7 @@ Common::FSNode TeCore::findFile(const Common::Path &path) const {
 	if (node.exists())
 		return node;
 
-	const Common::FSNode gameRoot(ConfMan.get("path"));
+	const Common::FSNode gameRoot(ConfMan.getPath("path"));
 	if (!gameRoot.isDirectory())
 		error("Game directory should be a directory");
 	const Common::FSNode resNode = (g_engine->getGamePlatform() == Common::kPlatformMacintosh
@@ -160,7 +160,7 @@ Common::FSNode TeCore::findFile(const Common::Path &path) const {
 	if (!resNode.isDirectory())
 		error("Resources directory should exist in game");
 
-	Common::String fname = path.getLastComponent().toString();
+	Common::String fname = path.baseName();
 
 	// Slight HACK: Remove 'comments' used to specify animated pngs
 	if (fname.contains('#'))
@@ -216,7 +216,7 @@ Common::FSNode TeCore::findFile(const Common::Path &path) const {
 	};
 
 	const Common::Path langs[] = {
-		language(),
+		Common::Path(language()),
 		"en",
 		"de-es-fr-it-en",
 		"en-es-fr-de-it",
@@ -257,7 +257,7 @@ Common::FSNode TeCore::findFile(const Common::Path &path) const {
 	}
 
 	// Didn't find it at all..
-	debug("TeCore::findFile Searched but didn't find %s", path.toString().c_str());
+	debug("TeCore::findFile Searched but didn't find %s", path.toString(Common::Path::kNativeSeparator).c_str());
 	return Common::FSNode(path);
 }
 
diff --git a/engines/tetraedge/te/te_core.h b/engines/tetraedge/te/te_core.h
index 4501a7b1707..1a0acb4fddb 100644
--- a/engines/tetraedge/te/te_core.h
+++ b/engines/tetraedge/te/te_core.h
@@ -57,7 +57,7 @@ public:
 
 	bool onActivityTrackingAlarm();
 	void enableActivityTracking(bool enable);
-	void setActivityTrackingFolder(const Common::String &path);
+	void setActivityTrackingFolder(const Common::Path &path);
 
 	// Note: this is not in the original, but it's not clear how the original
 	// adds things like "PC-MacOSX" to the path, and there is not clear logic
diff --git a/engines/tetraedge/te/te_font2.cpp b/engines/tetraedge/te/te_font2.cpp
index c48fecf0c04..6ca58ec8764 100644
--- a/engines/tetraedge/te/te_font2.cpp
+++ b/engines/tetraedge/te/te_font2.cpp
@@ -37,7 +37,7 @@ TeFont2::TeFont2() : _numChars(0), _hasKernData(false), _maxHeight(0) {
 TeFont2::~TeFont2() {
 }
 
-bool TeFont2::load(const Common::String &path) {
+bool TeFont2::load(const Common::Path &path) {
 	if (_loadedPath == path)
 		return true; // already open
 
@@ -47,14 +47,14 @@ bool TeFont2::load(const Common::String &path) {
 }
 
 bool TeFont2::load(const Common::FSNode &node) {
-	const Common::String path = node.getPath();
+	const Common::Path path = node.getPath();
 
 	unload();
 	setAccessName(path);
 	_loadedPath = path;
 
 	if (!node.isReadable()) {
-		warning("TeFont2::load: Can't read from %s", path.c_str());
+		warning("TeFont2::load: Can't read from %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -62,7 +62,7 @@ bool TeFont2::load(const Common::FSNode &node) {
 	file.open(node);
 
 	if (!Te3DObject2::loadAndCheckFourCC(file, "TESF")) {
-		warning("TeFont2::load: Invalid magic in %s", path.c_str());
+		warning("TeFont2::load: Invalid magic in %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -113,7 +113,7 @@ bool TeFont2::load(const Common::FSNode &node) {
 	}
 
 	if (!_texture.load(file, "png")) {
-		warning("Invalid png data in %s", path.c_str());
+		warning("Invalid png data in %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/engines/tetraedge/te/te_font2.h b/engines/tetraedge/te/te_font2.h
index aa798f60fe4..9d5dad7a9c5 100644
--- a/engines/tetraedge/te/te_font2.h
+++ b/engines/tetraedge/te/te_font2.h
@@ -70,7 +70,7 @@ public:
 	TeFont2();
 	virtual ~TeFont2();
 
-	bool load(const Common::String &path);
+	bool load(const Common::Path &path);
 	bool load(const Common::FSNode &node);
 	void unload();
 
@@ -88,7 +88,7 @@ public:
 	virtual float height(uint pxSize) override;
 
 private:
-	Common::String _loadedPath;
+	Common::Path _loadedPath;
 
 	uint32 _numChars;
 	TeVector2s32 _somePt;
diff --git a/engines/tetraedge/te/te_font3.cpp b/engines/tetraedge/te/te_font3.cpp
index ab37a9d5a98..27841879367 100644
--- a/engines/tetraedge/te/te_font3.cpp
+++ b/engines/tetraedge/te/te_font3.cpp
@@ -43,18 +43,18 @@ Graphics::Font *TeFont3::getAtSize(uint size) {
 		load(getAccessName());
 
 	if (!_fontFile.isOpen())
-		error("TeFont3::: Couldn't open font file %s.", getAccessName().c_str());
+		error("TeFont3::: Couldn't open font file %s.", getAccessName().toString(Common::Path::kNativeSeparator).c_str());
 
 	_fontFile.seek(0);
 	Graphics::Font *newFont = Graphics::loadTTFFont(_fontFile, size, Graphics::kTTFSizeModeCharacter, 0, Graphics::kTTFRenderModeNormal);
 	if (!newFont) {
-		error("TeFont3::: Couldn't load font %s at size %d.", _loadedPath.c_str(), size);
+		error("TeFont3::: Couldn't load font %s at size %d.", _loadedPath.toString(Common::Path::kNativeSeparator).c_str(), size);
 	}
 	_fonts.setVal(size, newFont);
 	return newFont;
 }
 
-bool TeFont3::load(const Common::String &path) {
+bool TeFont3::load(const Common::Path &path) {
 	if (_loadedPath == path && _fontFile.isOpen())
 		return true; // already open
 
@@ -64,7 +64,7 @@ bool TeFont3::load(const Common::String &path) {
 }
 
 bool TeFont3::load(const Common::FSNode &node) {
-	const Common::String path = node.getPath();
+	const Common::Path path = node.getPath();
 	if (_loadedPath == path && _fontFile.isOpen())
 		return true; // already open
 
@@ -72,7 +72,7 @@ bool TeFont3::load(const Common::FSNode &node) {
 	_loadedPath = path;
 
 	if (!node.isReadable()) {
-		warning("TeFont3::load: Can't read from %s", path.c_str());
+		warning("TeFont3::load: Can't read from %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -80,7 +80,7 @@ bool TeFont3::load(const Common::FSNode &node) {
 		_fontFile.close();
 
 	if (!_fontFile.open(node)) {
-		warning("TeFont3::load: can't open %s", path.c_str());
+		warning("TeFont3::load: can't open %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	return true;
diff --git a/engines/tetraedge/te/te_font3.h b/engines/tetraedge/te/te_font3.h
index d62e667c61a..c96d715f73c 100644
--- a/engines/tetraedge/te/te_font3.h
+++ b/engines/tetraedge/te/te_font3.h
@@ -51,7 +51,7 @@ public:
 	TeFont3();
 	virtual ~TeFont3();
 
-	bool load(const Common::String &path);
+	bool load(const Common::Path &path);
 	bool load(const Common::FSNode &node);
 	void unload();
 
@@ -64,7 +64,7 @@ private:
 	Graphics::Font *getAtSize(uint size) override;
 	Common::File _fontFile;
 	Common::HashMap<uint, Graphics::Font *> _fonts;
-	Common::String _loadedPath;
+	Common::Path _loadedPath;
 	Common::HashMap<uint, TeIntrusivePtr<Te3DTexture>> _fontSizeData;
 };
 
diff --git a/engines/tetraedge/te/te_free_move_zone.cpp b/engines/tetraedge/te/te_free_move_zone.cpp
index 39c3f161e19..06a60f10427 100644
--- a/engines/tetraedge/te/te_free_move_zone.cpp
+++ b/engines/tetraedge/te/te_free_move_zone.cpp
@@ -185,13 +185,13 @@ bool TeFreeMoveZone::loadAStar(const Common::Path &path, const TeVector2s32 &siz
 	Common::FSNode node = g_engine->getCore()->findFile(path);
 	Common::File file;
 	if (!node.isReadable() || !file.open(node)) {
-		warning("[TeFreeMoveZone::loadAStar] Can't open file : %s.", path.toString().c_str());
+		warning("[TeFreeMoveZone::loadAStar] Can't open file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	TeVector2s32 readSize;
 	readSize.deserialize(file, readSize);
 	if (size != readSize) {
-		warning("[TeFreeMoveZone::loadAStar] Wrong file : %s.", path.toString().c_str());
+		warning("[TeFreeMoveZone::loadAStar] Wrong file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	uint32 bytes = file.readUint32LE();
@@ -653,7 +653,7 @@ bool TeFreeMoveZone::loadBin(Common::ReadStream &stream, const Common::Array<TeB
 	_actzones = actzones;
 	updateGrid(false);
 	Common::Path p(name());
-	setName(p.getLastComponent().toString());
+	setName(p.baseName());
 
 	return true;
 }
diff --git a/engines/tetraedge/te/te_image.cpp b/engines/tetraedge/te/te_image.cpp
index 2cce0119cbf..29a37a1a5ca 100644
--- a/engines/tetraedge/te/te_image.cpp
+++ b/engines/tetraedge/te/te_image.cpp
@@ -101,9 +101,9 @@ bool TeImage::isExtensionSupported(const Common::Path &path) {
 
 bool TeImage::load(const Common::FSNode &node) {
 	TeCore *core = g_engine->getCore();
-	TeICodec *codec = core->createVideoCodec(Common::Path(node.getPath()));
+	TeICodec *codec = core->createVideoCodec(node.getPath());
 	if (!node.isReadable() || !codec->load(node)) {
-		warning("TeImage::load: Failed to load %s.", node.getPath().c_str());
+		warning("TeImage::load: Failed to load %s.", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		delete codec;
 		return false;
 	}
@@ -112,7 +112,7 @@ bool TeImage::load(const Common::FSNode &node) {
 	createImg(codec->width(), codec->height(), nullpal, codec->imageFormat(), codec->width(), codec->height());
 
 	if (!codec->update(0, *this)) {
-		error("TeImage::load: Failed to update from %s.", node.getPath().c_str());
+		error("TeImage::load: Failed to update from %s.", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	}
 	delete codec;
 	return true;
diff --git a/engines/tetraedge/te/te_images_sequence.cpp b/engines/tetraedge/te/te_images_sequence.cpp
index b8bf32a680d..fbbfc2719b2 100644
--- a/engines/tetraedge/te/te_images_sequence.cpp
+++ b/engines/tetraedge/te/te_images_sequence.cpp
@@ -44,19 +44,19 @@ bool TeImagesSequence::matchExtension(const Common::String &extn) {
 }
 
 static bool compareNodes(const Common::FSNode &left, const Common::FSNode &right) {
-	return left.getPath() < right.getPath();
+	return left.getPath().toString('/') < right.getPath().toString('/');
 }
 
 bool TeImagesSequence::load(const Common::FSNode &directory) {
-	const Common::String path = directory.getPath();
+	const Common::String path = directory.getPath().toString('/');
 	if (!directory.isDirectory()) {
-		warning("TeImagesSequence::load:: not a directory %s", path.c_str());
+		warning("TeImagesSequence::load:: not a directory %s", directory.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
 	Common::FSList children;
 	if (!directory.getChildren(children, Common::FSNode::kListFilesOnly) || children.empty()) {
-		warning("TeImagesSequence::load:: couldn't get children of %s", path.c_str());
+		warning("TeImagesSequence::load:: couldn't get children of %s", directory.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -80,7 +80,7 @@ bool TeImagesSequence::load(const Common::FSNode &directory) {
 
 		Common::SeekableReadStream *stream = child.createReadStream();
 		if (!stream) {
-			warning("TeImagesSequence::load can't open %s", child.getPath().c_str());
+			warning("TeImagesSequence::load can't open %s", child.getPath().toString(Common::Path::kNativeSeparator).c_str());
 			continue;
 		}
 
@@ -89,7 +89,7 @@ bool TeImagesSequence::load(const Common::FSNode &directory) {
 		if (!_width || (_width < 100 && _height < 100)) {
 			Image::PNGDecoder png;
 			if (!png.loadStream(*stream)) {
-				warning("Image sequence failed to load png %s", child.getPath().c_str());
+				warning("Image sequence failed to load png %s", child.getPath().toString(Common::Path::kNativeSeparator).c_str());
 				delete stream;
 				return false;
 			}
diff --git a/engines/tetraedge/te/te_interpolation.cpp b/engines/tetraedge/te/te_interpolation.cpp
index 0eb8b8c1ee5..419434d12b3 100644
--- a/engines/tetraedge/te/te_interpolation.cpp
+++ b/engines/tetraedge/te/te_interpolation.cpp
@@ -40,7 +40,7 @@ void TeInterpolation::load(Common::ReadStream &stream) {
 void TeInterpolation::load(Common::FSNode &node) {
 	Common::File f;
 	if (!f.open(node))
-		error("Couldn't open %s", node.getPath().c_str());
+		error("Couldn't open %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 
 	load(f);
 }
diff --git a/engines/tetraedge/te/te_lua_gui.cpp b/engines/tetraedge/te/te_lua_gui.cpp
index 97d596efc41..4d2abbfbdb1 100644
--- a/engines/tetraedge/te/te_lua_gui.cpp
+++ b/engines/tetraedge/te/te_lua_gui.cpp
@@ -154,7 +154,7 @@ TeButtonLayout *TeLuaGUI::buttonLayoutChecked(const Common::String &name) {
 	TeButtonLayout *l = buttonLayout(name);
 	if (!l) {
 		error("No button '%s' in gui data '%s'", name.c_str(),
-			  _scriptPath.c_str());
+			  _scriptPath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	return l;
 }
@@ -163,7 +163,7 @@ TeLayout *TeLuaGUI::layoutChecked(const Common::String &name) {
 	TeLayout *l = layout(name);
 	if (!l) {
 		error("No layout '%s' in gui data '%s'", name.c_str(),
-			  _scriptPath.c_str());
+			  _scriptPath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	return l;
 }
@@ -172,12 +172,12 @@ TeSpriteLayout *TeLuaGUI::spriteLayoutChecked(const Common::String &name) {
 	TeSpriteLayout *l = spriteLayout(name);
 	if (!l) {
 		error("No sprite layout '%s' in gui data '%s'", name.c_str(),
-			  _scriptPath.c_str());
+			  _scriptPath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 	return l;
 }
 
-bool TeLuaGUI::load(const Common::String &subPath) {
+bool TeLuaGUI::load(const Common::Path &subPath) {
 	TeCore *core = g_engine->getCore();
 	return load(core->findFile(subPath));
 }
diff --git a/engines/tetraedge/te/te_lua_gui.h b/engines/tetraedge/te/te_lua_gui.h
index 9232669f17f..2e7f8a1289f 100644
--- a/engines/tetraedge/te/te_lua_gui.h
+++ b/engines/tetraedge/te/te_lua_gui.h
@@ -77,7 +77,7 @@ public:
 	TeButtonLayout *buttonLayoutChecked(const Common::String &name);
 	TeSpriteLayout *spriteLayoutChecked(const Common::String &name);
 
-	bool load(const Common::String &subPath);
+	bool load(const Common::Path &subPath);
 	bool load(const Common::FSNode &node);
 	void unload();
 
@@ -99,13 +99,13 @@ public:
 	StringMap<TeCurveAnim2<Te3DObject2, TeColor> *> &colorLinearAnimations() { return _colorLinearAnimations; }
 
 	bool loaded() const { return _loaded; }
-	const Common::String &scriptPath() const { return _scriptPath; }
+	const Common::Path &scriptPath() const { return _scriptPath; }
 
 protected:
 	bool _loaded;
 
 private:
-	Common::String _scriptPath;
+	Common::Path _scriptPath;
 
 	TeLuaContext _luaContext;
 	TeLuaScript _luaScript;
diff --git a/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp b/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
index dfa0af98a78..e1fb38c5cfa 100644
--- a/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
+++ b/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
@@ -390,7 +390,7 @@ int spriteLayoutBindings(lua_State *L) {
 	}
 
 	if (!imgFullPath.empty())
-		layout->load(imgFullPath.toString());
+		layout->load(imgFullPath);
 
 	lua_pushnil(L);
 	while (lua_next(L, -2) != 0) {
@@ -471,7 +471,7 @@ int buttonLayoutBindings(lua_State *L) {
 			} else if (!strcmp(s, "clickPassThrough")) {
 				layout->setClickPassThrough(TeLuaToBool(L, -1));
 			} else if (!strcmp(s, "validationSound")) {
-				layout->setValidationSound(TeLuaToTeString(L, -1));
+				layout->setValidationSound(Common::Path(TeLuaToTeString(L, -1)));
 			} else if (!strcmp(s, "validationSoundVolume")) {
 				layout->setValidationSoundVolume(TeLuaToF32(L, -1));
 			} else if (!strcmp(s, "consoleNoStretch")) {
diff --git a/engines/tetraedge/te/te_lua_thread.cpp b/engines/tetraedge/te/te_lua_thread.cpp
index 4b1986773d0..b012a62ec36 100644
--- a/engines/tetraedge/te/te_lua_thread.cpp
+++ b/engines/tetraedge/te/te_lua_thread.cpp
@@ -273,7 +273,7 @@ void TeLuaThread::executeFile(const Common::FSNode &node) {
 
 	applyScriptWorkarounds(buf, node.getName());
 
-	_lastResumeResult = luaL_loadbuffer(_luaThread, buf, fileLen, node.getPath().c_str());
+	_lastResumeResult = luaL_loadbuffer(_luaThread, buf, fileLen, node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 	if (_lastResumeResult) {
 		const char *msg = lua_tostring(_luaThread, -1);
 		warning("TeLuaThread::executeFile: %s", msg);
diff --git a/engines/tetraedge/te/te_material.cpp b/engines/tetraedge/te/te_material.cpp
index eb06f5eaa56..e32b7b23bdf 100644
--- a/engines/tetraedge/te/te_material.cpp
+++ b/engines/tetraedge/te/te_material.cpp
@@ -60,7 +60,7 @@ Common::String TeMaterial::dump() const {
 			  _specularColor.dump().c_str(),
 			  _emissionColor.dump().c_str(),
 			  (int)_mode,
-			 _texture ? _texture->getAccessName().c_str() : "None",
+			 _texture ? _texture->getAccessName().toString('/').c_str() : "None",
 			  _shininess, _enableLights ? "on" : "off");
 }
 
@@ -89,7 +89,7 @@ TeMaterial &TeMaterial::operator=(const TeMaterial &other) {
 }
 
 /*static*/
-void TeMaterial::deserialize(Common::SeekableReadStream &stream, TeMaterial &material, const Common::String &texPath) {
+void TeMaterial::deserialize(Common::SeekableReadStream &stream, TeMaterial &material, const Common::Path &texPath) {
 	const Common::String nameStr = Te3DObject2::deserializeString(stream);
 
 	TeModel::loadAlign(stream);
@@ -97,10 +97,10 @@ void TeMaterial::deserialize(Common::SeekableReadStream &stream, TeMaterial &mat
 
 	if (nameStr.size()) {
 		TeCore *core = g_engine->getCore();
-		Common::FSNode texNode = core->findFile(Common::Path(texPath).join(nameStr));
+		Common::FSNode texNode = core->findFile(texPath.join(nameStr));
 		material._texture = Te3DTexture::load2(texNode, false);
 		if (!material._texture)
-			warning("failed to load texture %s (texpath %s)", nameStr.c_str(), texPath.c_str());
+			warning("failed to load texture %s (texpath %s)", nameStr.c_str(), texPath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	material._ambientColor.deserialize(stream);
@@ -118,7 +118,7 @@ void TeMaterial::deserialize(Common::SeekableReadStream &stream, TeMaterial &mat
 	Te3DTexture *tex = material._texture.get();
 	Common::String texName;
 	if (tex) {
-		texName = tex->getAccessName();
+		texName = tex->getAccessName().toString('/');
 		// "Remove extension" twice for some reason..
 		size_t offset = texName.rfind('.');
 		if (offset != Common::String::npos) {
diff --git a/engines/tetraedge/te/te_material.h b/engines/tetraedge/te/te_material.h
index 655898ead00..891b636189c 100644
--- a/engines/tetraedge/te/te_material.h
+++ b/engines/tetraedge/te/te_material.h
@@ -46,7 +46,7 @@ public:
 
 	// Note: apply() function from original moved to TeRenderer to remove OGL specific code from here
 	void defaultValues();
-	static void deserialize(Common::SeekableReadStream &stream, TeMaterial &material, const Common::String &path);
+	static void deserialize(Common::SeekableReadStream &stream, TeMaterial &material, const Common::Path &path);
 	static void serialize(Common::SeekableWriteStream &stream, TeMaterial &material);
 
 	bool operator==(const TeMaterial &other) const;
diff --git a/engines/tetraedge/te/te_model.cpp b/engines/tetraedge/te/te_model.cpp
index 38d52e907e4..6f81ff37a6a 100644
--- a/engines/tetraedge/te/te_model.cpp
+++ b/engines/tetraedge/te/te_model.cpp
@@ -422,7 +422,7 @@ bool TeModel::load(Common::SeekableReadStream &stream) {
 bool TeModel::load(const Common::Path &path) {
 	Common::File modelFile;
 	if (!modelFile.open(path)) {
-		warning("[TeModel::load] Can't open file : %s.", path.toString().c_str());
+		warning("[TeModel::load] Can't open file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
diff --git a/engines/tetraedge/te/te_model.h b/engines/tetraedge/te/te_model.h
index df74b9d3e57..005919b7c35 100644
--- a/engines/tetraedge/te/te_model.h
+++ b/engines/tetraedge/te/te_model.h
@@ -134,14 +134,14 @@ public:
 	TeIntrusivePtr<TeTiledTexture> tiledTexture() { return _tiledTexture; }
 
 	void setEnableLights(bool val) { _enableLights = val; }
-	void setTexturePath(const Common::String &path) { _texturePath = path; }
+	void setTexturePath(const Common::Path &path) { _texturePath = path; }
 	void setMeshCount(uint count);
 
 protected:
 	TeMatrix4x4 lerpElementsMatrix(uint weightNum, const Common::Array<TeMatrix4x4> &matricies);
 	void optimize();
 
-	Common::String _texturePath;
+	Common::Path _texturePath;
 	TeIntrusivePtr<TeTiledTexture> _tiledTexture;
 
 	bool _enableLights;
diff --git a/engines/tetraedge/te/te_model_animation.cpp b/engines/tetraedge/te/te_model_animation.cpp
index d213253f38d..0d55229c697 100644
--- a/engines/tetraedge/te/te_model_animation.cpp
+++ b/engines/tetraedge/te/te_model_animation.cpp
@@ -184,7 +184,7 @@ bool TeModelAnimation::load(const Common::Path &path) {
 	Common::FSNode foundFile = g_engine->getCore()->findFile(path);
 	Common::File modelFile;
 	if (!modelFile.open(foundFile)) {
-		warning("[TeModel::load] Can't open file : %s.", path.toString().c_str());
+		warning("[TeModel::load] Can't open file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 	bool retval;
diff --git a/engines/tetraedge/te/te_music.cpp b/engines/tetraedge/te/te_music.cpp
index 9dfcc9a9bc3..64046ad992b 100644
--- a/engines/tetraedge/te/te_music.cpp
+++ b/engines/tetraedge/te/te_music.cpp
@@ -162,7 +162,7 @@ bool TeMusic::isPlaying() {
 	return retval;
 }
 
-bool TeMusic::load(const Common::String &path) {
+bool TeMusic::load(const Common::Path &path) {
 	if (path.empty())
 		return false;
 
@@ -178,14 +178,14 @@ bool TeMusic::onSoundManagerVolumeChanged() {
 	return false;
 }
 
-Common::String TeMusic::path() {
+Common::Path TeMusic::path() {
 	_mutex.lock();
-	Common::String retval = _rawPath;
+	Common::Path retval = _rawPath;
 	_mutex.unlock();
 	return retval;
 }
 
-void TeMusic::setFilePath(const Common::String &name) {
+void TeMusic::setFilePath(const Common::Path &name) {
 	stop();
 	setAccessName(name);
 	_rawPath = name;
diff --git a/engines/tetraedge/te/te_music.h b/engines/tetraedge/te/te_music.h
index 691dbd3cd81..23aca56a2b2 100644
--- a/engines/tetraedge/te/te_music.h
+++ b/engines/tetraedge/te/te_music.h
@@ -49,20 +49,20 @@ public:
 
 	byte currentData();
 	void entry();
-	const Common::String &filePath() const {
+	const Common::Path &filePath() const {
 		return _rawPath;
 	}
 	bool isPlaying();
-	bool load(const Common::String &path);
+	bool load(const Common::Path &path);
 	bool onSoundManagerVolumeChanged();
-	Common::String path();
+	Common::Path path();
 	void setChannelName(const Common::String &name) {
 		_channelName = name;
 	}
 	const Common::String &channelName() const {
 		return _channelName;
 	}
-	void setFilePath(const Common::String &name);
+	void setFilePath(const Common::Path &name);
 	void update();
 	void volume(float vol);
 	float volume();
@@ -72,10 +72,8 @@ public:
 	void setRetain(bool retain) { _retain = retain; }
 	bool retain() const { return _retain; }
 
-	const Common::String &rawPath() { return _rawPath; }
-
 private:
-	Common::String _rawPath; // Plain name of file requested
+	Common::Path _rawPath; // Plain name of file requested
 	Common::FSNode _fileNode; // file after finding it
 	Common::String _channelName;
 
diff --git a/engines/tetraedge/te/te_resource.h b/engines/tetraedge/te/te_resource.h
index 025b99d6165..3c98ceccf4d 100644
--- a/engines/tetraedge/te/te_resource.h
+++ b/engines/tetraedge/te/te_resource.h
@@ -35,16 +35,16 @@ public:
 
 	void generateAccessName();
 
-	const Common::String &getAccessName() const {
+	const Common::Path &getAccessName() const {
 		return _accessName;
 	}
 
-	void setAccessName(const Common::String &name) {
+	void setAccessName(const Common::Path &name) {
 		_accessName = name;
 	}
 
 private:
-	Common::String _accessName;
+	Common::Path _accessName;
 	static uint32 _idCounter;
 };
 
diff --git a/engines/tetraedge/te/te_resource_manager.cpp b/engines/tetraedge/te/te_resource_manager.cpp
index cf3a3c8f03d..272c2a14ae7 100644
--- a/engines/tetraedge/te/te_resource_manager.cpp
+++ b/engines/tetraedge/te/te_resource_manager.cpp
@@ -43,7 +43,7 @@ void TeResourceManager::addResource(TeResource *resource) {
 	_resources.insert_at(0, TeIntrusivePtr<TeResource>(resource));
 }
 
-bool TeResourceManager::exists(const Common::String &path) {
+bool TeResourceManager::exists(const Common::Path &path) {
 	for (auto &resource : _resources) {
 		if (resource->getAccessName() == path)
 			return true;
diff --git a/engines/tetraedge/te/te_resource_manager.h b/engines/tetraedge/te/te_resource_manager.h
index fb63789fb60..1d23210b239 100644
--- a/engines/tetraedge/te/te_resource_manager.h
+++ b/engines/tetraedge/te/te_resource_manager.h
@@ -45,22 +45,22 @@ public:
 
 	void addResource(const TeIntrusivePtr<TeResource> &resource);
 	void addResource(TeResource *resource);
-	bool exists(const Common::String &path);
+	bool exists(const Common::Path &path);
 	void removeResource(const TeIntrusivePtr<TeResource> &resource);
 	void removeResource(const TeResource *resource);
 
-	template<class T> TeIntrusivePtr<T> getResourceByName(const Common::String &path) {
+	template<class T> TeIntrusivePtr<T> getResourceByName(const Common::Path &path) {
 		for (TeIntrusivePtr<TeResource> &resource : this->_resources) {
 			if (resource->getAccessName() == path) {
 				return TeIntrusivePtr<T>(dynamic_cast<T *>(resource.get()));
 			}
 		}
-		debug("getResourceByName: didn't find resource %s", path.c_str());
+		debug("getResourceByName: didn't find resource %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return TeIntrusivePtr<T>();
 	}
 
 	template<class T> TeIntrusivePtr<T> getResource(const Common::FSNode &node) {
-		Common::String path = node.getPath();
+		Common::Path path = node.getPath();
 		for (TeIntrusivePtr<TeResource> &resource : this->_resources) {
 			if (resource->getAccessName() == path) {
 				return TeIntrusivePtr<T>(dynamic_cast<T *>(resource.get()));
@@ -72,7 +72,7 @@ public:
 
 		if (retval.get()) {
 			if (!node.isReadable())
-				warning("getResource: asked to fetch unreadable resource %s", node.getPath().c_str());
+				warning("getResource: asked to fetch unreadable resource %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 			retval->load(node);
 			addResource(retval.get());
 		}
@@ -80,7 +80,7 @@ public:
 	}
 
 	template<class T> TeIntrusivePtr<T> getResourceOrMakeInstance(const Common::FSNode &node) {
-		Common::String path = node.getPath();
+		Common::Path path = node.getPath();
 		for (TeIntrusivePtr<TeResource> &resource : this->_resources) {
 			if (resource->getAccessName() == path) {
 				return TeIntrusivePtr<T>(dynamic_cast<T *>(resource.get()));
@@ -92,7 +92,7 @@ public:
 
 		if (retval.get()) {
 			if (!node.isReadable())
-				warning("getResourceOrMakeInstance: asked to fetch unreadable resource %s", node.getPath().c_str());
+				warning("getResourceOrMakeInstance: asked to fetch unreadable resource %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 			retval->load(node);
 			addResource(retval.get());
 		}
diff --git a/engines/tetraedge/te/te_scene_warp.cpp b/engines/tetraedge/te/te_scene_warp.cpp
index d949117fb97..8731a384e30 100644
--- a/engines/tetraedge/te/te_scene_warp.cpp
+++ b/engines/tetraedge/te/te_scene_warp.cpp
@@ -69,7 +69,7 @@ const TeSceneWarp::WarpEvent *TeSceneWarp::getWarpEvent(const Common::String &na
 	return nullptr;
 }
 
-bool TeSceneWarp::load(const Common::String &name, TeWarp *warp, bool flag) {
+bool TeSceneWarp::load(const Common::Path &name, TeWarp *warp, bool flag) {
 	close();
 	_warp = warp;
 	_numExitsCreated = 0;
@@ -79,9 +79,9 @@ bool TeSceneWarp::load(const Common::String &name, TeWarp *warp, bool flag) {
 	TeCore *core = g_engine->getCore();
 	Common::FSNode node = core->findFile(name);
 	if (!parser.loadFile(node))
-		error("TeSceneWarp::load: failed to load data from %s", name.c_str());
+		error("TeSceneWarp::load: failed to load data from %s", name.toString(Common::Path::kNativeSeparator).c_str());
 	if (!parser.parse())
-		error("TeSceneWarp::load: failed to parse data from %s", name.c_str());
+		error("TeSceneWarp::load: failed to parse data from %s", name.toString(Common::Path::kNativeSeparator).c_str());
 
 	if (flag) {
 		// Line 357 ~ 426, plus other fixups
diff --git a/engines/tetraedge/te/te_scene_warp.h b/engines/tetraedge/te/te_scene_warp.h
index bbb242bb08f..ed123a8ac0c 100644
--- a/engines/tetraedge/te/te_scene_warp.h
+++ b/engines/tetraedge/te/te_scene_warp.h
@@ -77,7 +77,7 @@ public:
 	const Exit *getExit(const Common::String &linkedWarp);
 	const Object *getObject(const Common::String &name);
 	const WarpEvent *getWarpEvent(const Common::String &name); // TODO: what's the right return type?
-	bool load(const Common::String &name, TeWarp *warp, bool flag);
+	bool load(const Common::Path &name, TeWarp *warp, bool flag);
 	//void moveIndicator(const Common::String &, const Common::String &, const TeVector2s32 &)); // unused
 	//void popBlockToExit(const Common::String &name, TePickMesh *mesh); // unused
 	//void pushBlockToExit(const Common::String &name, TePickMesh *mesh); // unused 
@@ -95,7 +95,7 @@ private:
 	Common::List<Exit> _exits;
 	Common::List<Animation> _animations;
 	Common::List<WarpEvent> _warpEvents;
-	Common::String _name;
+	Common::Path _name;
 	TeWarp *_warp;
 	int _numExitsCreated;
 };
diff --git a/engines/tetraedge/te/te_scummvm_codec.h b/engines/tetraedge/te/te_scummvm_codec.h
index c8fe269814e..2ee15fe0a11 100644
--- a/engines/tetraedge/te/te_scummvm_codec.h
+++ b/engines/tetraedge/te/te_scummvm_codec.h
@@ -55,7 +55,7 @@ public:
 
 protected:
 	Graphics::Surface *_loadedSurface;
-	Common::String _loadedPath;
+	Common::Path _loadedPath;
 	float _frameRate;
 	uint _bottomBorder;
 	uint _topBorder;
diff --git a/engines/tetraedge/te/te_sound_manager.cpp b/engines/tetraedge/te/te_sound_manager.cpp
index 335593ddf92..9dfd2000bde 100644
--- a/engines/tetraedge/te/te_sound_manager.cpp
+++ b/engines/tetraedge/te/te_sound_manager.cpp
@@ -47,12 +47,12 @@ void TeSoundManager::playFreeSound(const Common::Path &path, float vol, const Co
 
 	Common::File *streamfile = new Common::File();
 	if (!sndNode.isReadable() || !streamfile->open(sndNode)) {
-		warning("TeSoundManager::playFreeSound: couldn't open %s", sndNode.getPath().c_str());
+		warning("TeSoundManager::playFreeSound: couldn't open %s", sndNode.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		delete streamfile;
 		return;
 	}
 
-	Common::String fileName = path.getLastComponent().toString();
+	Common::String fileName = path.baseName();
 
 	Audio::AudioStream *stream;
 	if (fileName.contains(".wav"))
diff --git a/engines/tetraedge/te/te_sprite_layout.cpp b/engines/tetraedge/te/te_sprite_layout.cpp
index 54cc455453d..a845f5bc905 100644
--- a/engines/tetraedge/te/te_sprite_layout.cpp
+++ b/engines/tetraedge/te/te_sprite_layout.cpp
@@ -73,7 +73,7 @@ bool TeSpriteLayout::onParentWorldColorChanged() {
 	return false;
 }
 
-bool TeSpriteLayout::load(const Common::String &path) {
+bool TeSpriteLayout::load(const Common::Path &path) {
 	if (path.empty()) {
 		_tiledSurfacePtr->unload();
 		return true;
@@ -86,7 +86,7 @@ bool TeSpriteLayout::load(const Common::String &path) {
 	return true;
 }
 
-bool TeSpriteLayout::load(const Common::FSNode &node, const Common::String *forcePath) {
+bool TeSpriteLayout::load(const Common::FSNode &node, const Common::Path *forcePath) {
 	if (!node.exists()) {
 		_tiledSurfacePtr->unload();
 		return false;
@@ -95,7 +95,7 @@ bool TeSpriteLayout::load(const Common::FSNode &node, const Common::String *forc
 	stop();
 	unload();
 
-	_tiledSurfacePtr->setLoadedPath(forcePath ? *forcePath : Common::String());
+	_tiledSurfacePtr->setLoadedPath(forcePath ? *forcePath : Common::Path());
 	if (_tiledSurfacePtr->load(node)) {
 		const TeVector2s32 texSize = _tiledSurfacePtr->tiledTexture()->totalSize();
 		if (texSize._y <= 0) {
@@ -108,7 +108,7 @@ bool TeSpriteLayout::load(const Common::FSNode &node, const Common::String *forc
 		}
 		updateMesh();
 	} else {
-		debug("Failed to load TeSpriteLayout %s", node.getPath().c_str());
+		debug("Failed to load TeSpriteLayout %s", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 		_tiledSurfacePtr->setLoadedPath("");
 	}
 	return true;
@@ -131,7 +131,7 @@ bool TeSpriteLayout::load(TeIntrusivePtr<Te3DTexture> &texture) {
 		updateMesh();
 		return true;
 	} else {
-		debug("Failed to load TeSpriteLayout from texture %s", texture->getAccessName().c_str());
+		debug("Failed to load TeSpriteLayout from texture %s", texture->getAccessName().toString(Common::Path::kNativeSeparator).c_str());
 	}
 	return false;
 }
@@ -153,7 +153,7 @@ bool TeSpriteLayout::load(TeImage &img) {
 		updateMesh();
 		return true;
 	} else {
-		debug("Failed to load TeSpriteLayout from texture %s", img.getAccessName().c_str());
+		debug("Failed to load TeSpriteLayout from texture %s", img.getAccessName().toString(Common::Path::kNativeSeparator).c_str());
 	}
 	return false;
 }
diff --git a/engines/tetraedge/te/te_sprite_layout.h b/engines/tetraedge/te/te_sprite_layout.h
index 50a8eac3a07..8573bd9e0fc 100644
--- a/engines/tetraedge/te/te_sprite_layout.h
+++ b/engines/tetraedge/te/te_sprite_layout.h
@@ -37,8 +37,8 @@ public:
 
 	virtual bool onParentWorldColorChanged() override;
 
-	bool load(const Common::String &path);
-	bool load(const Common::FSNode &node, const Common::String *forcePath = nullptr);
+	bool load(const Common::Path &path);
+	bool load(const Common::FSNode &node, const Common::Path *forcePath = nullptr);
 	bool load(TeImage &img);
 	bool load(TeIntrusivePtr<Te3DTexture> &texture);
 
diff --git a/engines/tetraedge/te/te_tiled_surface.cpp b/engines/tetraedge/te/te_tiled_surface.cpp
index de8dbd8f701..957d234aaf9 100644
--- a/engines/tetraedge/te/te_tiled_surface.cpp
+++ b/engines/tetraedge/te/te_tiled_surface.cpp
@@ -67,9 +67,10 @@ bool TeTiledSurface::load(const Common::FSNode &node) {
 	if (_loadedPath.empty())
 		_loadedPath = node.getPath();
 
+	Common::Path ttPath(_loadedPath.append(".tt"));
 	TeIntrusivePtr<TeTiledTexture> texture;
-	if (resmgr->exists(_loadedPath + ".tt")) {
-		texture = resmgr->getResourceByName<TeTiledTexture>(_loadedPath + ".tt");
+	if (resmgr->exists(ttPath)) {
+		texture = resmgr->getResourceByName<TeTiledTexture>(ttPath);
 		// we don't own this one..
 	}
 
@@ -82,12 +83,12 @@ bool TeTiledSurface::load(const Common::FSNode &node) {
 		texture = new TeTiledTexture();
 
 		if (_codec->load(node)) {
-			texture->setAccessName(_loadedPath + ".tt");
+			texture->setAccessName(ttPath);
 			resmgr->addResource(texture.get());
 			_imgFormat = _codec->imageFormat();
 
 			if (_imgFormat == TeImage::INVALID) {
-				warning("TeTiledSurface::load: Wrong image format on file %s", _loadedPath.c_str());
+				warning("TeTiledSurface::load: Wrong image format on file %s", _loadedPath.toString(Common::Path::kNativeSeparator).c_str());
 				delete _codec;
 				_codec = nullptr;
 				return false;
@@ -117,7 +118,7 @@ bool TeTiledSurface::load(const Common::FSNode &node) {
 				texture->load(img);
 			}
 		} else {
-			warning("TeTiledSurface::load: failed to load %s", _loadedPath.c_str());
+			warning("TeTiledSurface::load: failed to load %s", _loadedPath.toString(Common::Path::kNativeSeparator).c_str());
 			delete _codec;
 			_codec = nullptr;
 		}
@@ -137,7 +138,7 @@ bool TeTiledSurface::load(const TeIntrusivePtr<Te3DTexture> &texture) {
 	TeResourceManager *resmgr = g_engine->getResourceManager();
 	TeIntrusivePtr<TeTiledTexture> tiledTexture;
 
-	const Common::String ttPath = texture->getAccessName() + ".tt";
+	const Common::Path ttPath = texture->getAccessName().append(".tt");
 
 	if (resmgr->exists(ttPath)) {
 		tiledTexture = resmgr->getResourceByName<TeTiledTexture>(ttPath);
@@ -159,7 +160,7 @@ bool TeTiledSurface::onFrameAnimCurrentFrameChanged() {
 		return false;
 
 	if (_imgFormat == TeImage::INVALID) {
-		warning("TeTiledSurface::load: Wrong image format on file %s", _loadedPath.c_str());
+		warning("TeTiledSurface::load: Wrong image format on file %s", _loadedPath.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -215,7 +216,7 @@ void TeTiledSurface::setTiledTexture(const TeIntrusivePtr<TeTiledTexture> &textu
 		for (uint i = 0; i < texture->numberOfColumns() * texture->numberOfRow(); i++)
 			_meshes.push_back(Common::SharedPtr<TeMesh>(TeMesh::makeInstance()));
 
-		setAccessName(texture->getAccessName() + ".surface");
+		setAccessName(texture->getAccessName().append(".surface"));
 		updateSurface();
 	} else {
 		_meshes.clear();
diff --git a/engines/tetraedge/te/te_tiled_surface.h b/engines/tetraedge/te/te_tiled_surface.h
index 2cb3a79e7d8..5866d26c008 100644
--- a/engines/tetraedge/te/te_tiled_surface.h
+++ b/engines/tetraedge/te/te_tiled_surface.h
@@ -83,8 +83,8 @@ public:
 	void updateSurface();
 	void updateVideoProperties();
 
-	const Common::String &loadedPath() const { return _loadedPath; }
-	void setLoadedPath(const Common::String &p) { _loadedPath = p; }
+	const Common::Path &loadedPath() const { return _loadedPath; }
+	void setLoadedPath(const Common::Path &p) { _loadedPath = p; }
 
 	TeFrameAnim _frameAnim;
 
@@ -106,7 +106,7 @@ private:
 
 	TeImage::Format _imgFormat;
 
-	Common::String _loadedPath;
+	Common::Path _loadedPath;
 
 };
 
diff --git a/engines/tetraedge/te/te_tiled_texture.cpp b/engines/tetraedge/te/te_tiled_texture.cpp
index 2a1c4bc02b2..967e4580dfe 100644
--- a/engines/tetraedge/te/te_tiled_texture.cpp
+++ b/engines/tetraedge/te/te_tiled_texture.cpp
@@ -41,7 +41,7 @@ bool TeTiledTexture::isLoaded() {
 }
 
 
-bool TeTiledTexture::load(const Common::String &path) {
+bool TeTiledTexture::load(const Common::Path &path) {
 	release();
 	TeIntrusivePtr<TeImage> img;
 	TeResourceManager *resmgr = g_engine->getResourceManager();
@@ -87,8 +87,8 @@ bool TeTiledTexture::load(const TeImage &img) {
 				TeImage *optimizedimg = optimisedTileImage(imgArray, newTileSize, Common::SharedPtr<TePalette>(), img.teFormat());
 				img.copy(*optimizedimg, TeVector2s32(0, 0), TeVector2s32(_tileSize._x * row, _tileSize._y * col), newTileSize);
 				//optimizedimg->_flipY = img._flipY;
-				Common::String accessName = Common::String::format("%s.Tile%dx%d", img.getAccessName().c_str(), row, col);
-				optimizedimg->setAccessName(accessName);
+				Common::String accessName = Common::String::format("%s.Tile%dx%d", img.getAccessName().toString('/').c_str(), row, col);
+				optimizedimg->setAccessName(Common::Path(accessName, '/'));
 				tileimage = optimizedimg;
 			} else {
 				tileimage = &img;
@@ -116,7 +116,7 @@ bool TeTiledTexture::load(const TeImage &img) {
 		_somethingSize._x = _somethingSize._x / cols;
 	if (rows)
 		_somethingSize._y = _somethingSize._y / rows;
-	setAccessName(img.getAccessName() + ".tt");
+	setAccessName(img.getAccessName().append(".tt"));
 	return true;
 }
 
@@ -130,7 +130,7 @@ bool TeTiledTexture::load(const TeIntrusivePtr<Te3DTexture> &texture) {
 	tileData->_texture = texture;
 	tileData->_vec2 = TeVector3f32(1, 1, 0);
 	tileData->_vec1 = TeVector3f32(0, 0, 0);
-	setAccessName(texture->getAccessName() + ".tt");
+	setAccessName(texture->getAccessName().append(".tt"));
 	return true;
 }
 
diff --git a/engines/tetraedge/te/te_tiled_texture.h b/engines/tetraedge/te/te_tiled_texture.h
index 203030f1c32..8a0b4e81b8f 100644
--- a/engines/tetraedge/te/te_tiled_texture.h
+++ b/engines/tetraedge/te/te_tiled_texture.h
@@ -46,7 +46,7 @@ public:
 
 	uint imageFormat();
 	bool isLoaded();
-	bool load(const Common::String &path);
+	bool load(const Common::Path &path);
 	bool load(const TeImage &image);
 	bool load(const TeIntrusivePtr<Te3DTexture> &texture);
 	uint32 numberOfColumns() const;
diff --git a/engines/tetraedge/te/te_warp.cpp b/engines/tetraedge/te/te_warp.cpp
index 9c6b66e6595..ff02d88d25d 100644
--- a/engines/tetraedge/te/te_warp.cpp
+++ b/engines/tetraedge/te/te_warp.cpp
@@ -174,8 +174,8 @@ void TeWarp::configMarker(const Common::String &objname, int markerImgNo, long m
 		warpMarker->marker()->visible(false);
 		frontLayout.removeChild(&warpMarker->marker()->button());
 	} else {
-		Common::String markerPath = Common::String::format("2D/Menus/InGame/Marker_%d.png#anim", markerImgNo);
-		Common::String markerPathDown = Common::String::format("2D/Menus/InGame/Marker_%d_over.png", markerImgNo);
+		Common::Path markerPath(Common::String::format("2D/Menus/InGame/Marker_%d.png#anim", markerImgNo));
+		Common::Path markerPathDown(Common::String::format("2D/Menus/InGame/Marker_%d_over.png", markerImgNo));
 		if (!exit)
 			warpMarker->setName(objname);
 		else
@@ -184,7 +184,7 @@ void TeWarp::configMarker(const Common::String &objname, int markerImgNo, long m
 		warpMarker->marker()->button().load(markerPath, markerPathDown, "");
 		TeSpriteLayout *btnUp = dynamic_cast<TeSpriteLayout*>(warpMarker->marker()->button().upLayout());
 		if (!btnUp)
-			error("Loading button image %s failed", markerPath.c_str());
+			error("Loading button image %s failed", markerPath.toString(Common::Path::kNativeSeparator).c_str());
 		//warning("TeWarp::configMarker: set anim values and something else here?");
 		btnUp->_tiledSurfacePtr->_frameAnim.setLoopCount(-1);
 		btnUp->play();
@@ -236,7 +236,7 @@ void TeWarp::init() {
 	warning("TODO: Finish TeWarp::init?");
 }
 
-void TeWarp::load(const Common::String &path, bool flag) {
+void TeWarp::load(const Common::Path &path, bool flag) {
 	if (_warpPath == path && _loaded)
 		return;
 	_warpPath = path;
@@ -247,7 +247,7 @@ void TeWarp::load(const Common::String &path, bool flag) {
 	TeCore *core = g_engine->getCore();
 	Common::FSNode node = core->findFile(_warpPath);
 	if (!node.isReadable()) {
-		error("Couldn't find TeWarp path data '%s'", _warpPath.c_str());
+		error("Couldn't find TeWarp path data '%s'", _warpPath.toString(Common::Path::kNativeSeparator).c_str());
 	}
 
 	if (_preloaded)
@@ -257,7 +257,7 @@ void TeWarp::load(const Common::String &path, bool flag) {
 	header[6] = '\0';
 	_file.read(header, 6);
 	if (Common::String(header) != "TeWarp")
-		error("Invalid header in warp data %s", _warpPath.c_str());
+		error("Invalid header in warp data %s", _warpPath.toString(Common::Path::kNativeSeparator).c_str());
 	uint32 globalTexDataOffset = _file.readUint32LE();
 	_texEncodingType = _file.readPascalString();
 	_xCount = _file.readUint32LE();
diff --git a/engines/tetraedge/te/te_warp.h b/engines/tetraedge/te/te_warp.h
index 4dd55f77b53..303c45834b0 100644
--- a/engines/tetraedge/te/te_warp.h
+++ b/engines/tetraedge/te/te_warp.h
@@ -95,9 +95,9 @@ public:
 	//int getAnimationFrame(const Common::String &name); // unused
 	bool hasObjectOrAnim(const Common::String &name) const;
 	void init();
-	void load(const Common::String &path, bool flag);
+	void load(const Common::Path &path, bool flag);
 	//void loadTextures(); // unused
-	//void preload(const Common::String &path); // unused
+	//void preload(const Common::Path &path); // unused
 	void putObject(const Common::String &name, bool enable);
 	void update();
 	void render();
@@ -126,7 +126,7 @@ private:
 	bool onMarkerValidated(const Common::String &name);
 
 	Common::File _file;
-	Common::String _warpPath;
+	Common::Path _warpPath;
 	TeCamera _camera;
 	bool _markersActive;
 	bool _visible1;
@@ -140,6 +140,7 @@ private:
 	TeFrustum _frustum;
 
 	Common::Array<TeWarpMarker *> _warpMarkers;
+	// FIXME: Seems useless
 	Common::List<Common::String> _paths;
 	Common::Array<AnimData *> _putAnimData;
 	Common::List<TeWarp::Exit> _exitList;
diff --git a/engines/tetraedge/te/te_xml_gui.cpp b/engines/tetraedge/te/te_xml_gui.cpp
index 767bb7953c5..c1c85d574f6 100644
--- a/engines/tetraedge/te/te_xml_gui.cpp
+++ b/engines/tetraedge/te/te_xml_gui.cpp
@@ -40,7 +40,7 @@ void TeXmlGui::load(const Common::Path &path) {
 	clear();
 
 	TeNameValXmlParser parser;
-	if (!parser.loadFile(path.toString()))
+	if (!parser.loadFile(path))
 		error("TeXmlGui::load: failed to load xml.");
 
 	_map = parser.getMap();
diff --git a/engines/tetraedge/tetraedge.cpp b/engines/tetraedge/tetraedge.cpp
index 77bac9ebf13..9e14f5a50d1 100644
--- a/engines/tetraedge/tetraedge.cpp
+++ b/engines/tetraedge/tetraedge.cpp
@@ -207,7 +207,7 @@ void TetraedgeEngine::closeGameDialogs() {
 }
 
 void TetraedgeEngine::configureSearchPaths() {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	if (_gameDescription->platform != Common::kPlatformIOS)
 		SearchMan.addSubDirectoryMatching(gameDataDir, "Resources", 0, 5);
 }


Commit: cd802da8aeb5648ed527b30c7ae873c252ee1ced
    https://github.com/scummvm/scummvm/commit/cd802da8aeb5648ed527b30c7ae873c252ee1ced
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TINSEL: Migrate engine to Path

Changed paths:
    engines/tinsel/detection.cpp
    engines/tinsel/drives.cpp
    engines/tinsel/drives.h
    engines/tinsel/handle.cpp
    engines/tinsel/handle.h
    engines/tinsel/music.cpp
    engines/tinsel/music.h
    engines/tinsel/tinsel.cpp


diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index 3e852998bac..751fea53892 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -73,8 +73,8 @@ struct SizeMD5 {
 	int size;
 	Common::String md5;
 };
-typedef Common::HashMap<Common::String, SizeMD5, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SizeMD5Map;
-typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+typedef Common::HashMap<Common::Path, SizeMD5, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> SizeMD5Map;
+typedef Common::HashMap<Common::Path, Common::FSNode, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
 typedef Common::Array<const ADGameDescription *> ADGameDescList;
 
 /**
@@ -110,7 +110,7 @@ ADDetectedGame TinselMetaEngineDetection::fallbackDetect(const FileMap &allFiles
 						if (file2->isDirectory())
 							continue;
 
-						Common::String fname = file2->getName();
+						Common::Path fname = file2->getPathInArchive();
 						allFiles[fname] = *file2;
 					}
 				}
@@ -118,7 +118,7 @@ ADDetectedGame TinselMetaEngineDetection::fallbackDetect(const FileMap &allFiles
 			continue;
 		}
 
-		Common::String tstr = file->getName();
+		Common::Path tstr = file->getPathInArchive();
 
 		allFiles[tstr] = *file;	// Record the presence of this file
 	}
@@ -141,7 +141,7 @@ ADDetectedGame TinselMetaEngineDetection::fallbackDetect(const FileMap &allFiles
 				} while (*pOne);
 			}
 
-			Common::String fname(tempFilename);
+			Common::Path fname(tempFilename);
 			if (allFiles.contains(fname) && !filesSizeMD5.contains(fname)) {
 				SizeMD5 tmp;
 				Common::File testFile;
@@ -181,7 +181,7 @@ ADDetectedGame TinselMetaEngineDetection::fallbackDetect(const FileMap &allFiles
 				} while (*pOne);
 			}
 
-			Common::String tstr(tempFilename);
+			Common::Path tstr(tempFilename);
 
 			if (!filesSizeMD5.contains(tstr)) {
 				fileMissing = true;
diff --git a/engines/tinsel/drives.cpp b/engines/tinsel/drives.cpp
index 931b2766fb3..8bc022379d9 100644
--- a/engines/tinsel/drives.cpp
+++ b/engines/tinsel/drives.cpp
@@ -168,15 +168,15 @@ TinselFile::~TinselFile() {
 	delete _stream;
 }
 
-bool TinselFile::openInternal(const Common::String &filename) {
+bool TinselFile::openInternal(const Common::Path &filename) {
 	_stream = SearchMan.createReadStreamForMember(filename);
 	if (!_stream)
-		_stream = SearchMan.createReadStreamForMember(filename + ".");
+		_stream = SearchMan.createReadStreamForMember(filename.append("."));
 	return _stream != 0;
 }
 
 bool TinselFile::open(const Common::String &filename) {
-	if (openInternal(filename))
+	if (openInternal(Common::Path(filename)))
 		return true;
 
 	if (TinselVersion <= 1)
diff --git a/engines/tinsel/drives.h b/engines/tinsel/drives.h
index d12badf1237..b69c12d2b85 100644
--- a/engines/tinsel/drives.h
+++ b/engines/tinsel/drives.h
@@ -27,6 +27,10 @@
 #include "common/stream.h"
 #include "tinsel/dw.h"
 
+namespace Common {
+class Path;
+}
+
 namespace Tinsel {
 
 // flags2
@@ -59,7 +63,7 @@ class TinselFile : public Common::SeekableReadStream, public Common::ReadStreamE
 private:
 	static bool _warningShown;
 	Common::SeekableReadStream *_stream;
-	bool openInternal(const Common::String &filename);
+	bool openInternal(const Common::Path &filename);
 public:
 	// This constructor is only used for _sampleStream inside sound.h
 	TinselFile();
diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp
index e425c8535b5..a07986dd3d9 100644
--- a/engines/tinsel/handle.cpp
+++ b/engines/tinsel/handle.cpp
@@ -174,7 +174,7 @@ void Handle::OpenCDGraphFile() {
 
 	_cdGraphStream = new Common::File;
 	if (!_cdGraphStream->open(_szCdPlayFile))
-		error(CANNOT_FIND_FILE, _szCdPlayFile.c_str());
+		error(CANNOT_FIND_FILE, _szCdPlayFile.toString().c_str());
 }
 
 void Handle::LoadCDGraphData(MEMHANDLE *pH) {
diff --git a/engines/tinsel/handle.h b/engines/tinsel/handle.h
index a52a6309bc8..4d2aea96304 100644
--- a/engines/tinsel/handle.h
+++ b/engines/tinsel/handle.h
@@ -23,7 +23,7 @@
 #ifndef TINSEL_HANDLE_H
 #define TINSEL_HANDLE_H
 
-#include "common/str.h"
+#include "common/path.h"
 #include "tinsel/dw.h"			// new data types
 
 namespace Common {
@@ -100,7 +100,7 @@ private:
 	SCNHANDLE _cdBaseHandle, _cdTopHandle;
 	Common::File *_cdGraphStream;
 
-	Common::String _szCdPlayFile;
+	Common::Path _szCdPlayFile;
 };
 
 } // End of namespace Tinsel
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index aa2e5593139..c833cd713eb 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -592,13 +592,13 @@ void MidiMusicPlayer::playSEQ(uint32 size, bool loop) {
 	uint8 *midiData = _vm->_music->GetMidiBuffer();
 	// MIDI.DAT holds the file names in DW1 PSX
 	Common::String baseName((char *)midiData, size);
-	Common::String seqName = baseName + ".SEQ";
+	Common::Path seqName(baseName + ".SEQ");
 
 	// TODO: Load the instrument bank (<baseName>.VB and <baseName>.VH)
 
 	Common::File seqFile;
 	if (!seqFile.open(seqName))
-		error("Failed to open SEQ file '%s'", seqName.c_str());
+		error("Failed to open SEQ file '%s'", seqName.toString().c_str());
 
 	if (seqFile.readUint32LE() != MKTAG('S', 'E', 'Q', 'p'))
 		error("Failed to find SEQp tag");
@@ -708,7 +708,7 @@ void PCMMusicPlayer::startPlay(int id) {
 	if (_filename.empty())
 		return;
 
-	debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _filename.c_str(), id);
+	debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _filename.toString().c_str(), id);
 
 	Common::StackLock slock(_mutex);
 
@@ -968,21 +968,21 @@ void PCMMusicPlayer::fadeOutIteration() {
 	_vm->_mixer->setChannelVolume(_handle, _fadeOutVolume);
 }
 
-Common::MemoryReadStream *readSampleData(const Common::String &filename, uint32 sampleOffset, uint32 sampleLength) {
+Common::MemoryReadStream *readSampleData(const Common::Path &filename, uint32 sampleOffset, uint32 sampleLength) {
 	Common::File file;
 	if (!file.open(filename))
-		error(CANNOT_FIND_FILE, filename.c_str());
+		error(CANNOT_FIND_FILE, filename.toString().c_str());
 
 	file.seek(sampleOffset);
 	if (file.eos() || file.err() || (uint32)file.pos() != sampleOffset)
-		error(FILE_IS_CORRUPT, filename.c_str());
+		error(FILE_IS_CORRUPT, filename.toString().c_str());
 
 	byte *buffer = (byte *) malloc(sampleLength);
 	assert(buffer);
 
 	// read all of the sample
 	if (file.read(buffer, sampleLength) != sampleLength)
-		error(FILE_IS_CORRUPT, filename.c_str());
+		error(FILE_IS_CORRUPT, filename.toString().c_str());
 
 	return new Common::MemoryReadStream(buffer, sampleLength, DisposeAfterUse::YES);
 }
diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h
index 04d6142e717..ccb02b85d0b 100644
--- a/engines/tinsel/music.h
+++ b/engines/tinsel/music.h
@@ -177,7 +177,7 @@ protected:
 	int32 _scriptIndex;
 	SCNHANDLE _hScript;
 	SCNHANDLE _hSegment;
-	Common::String _filename;
+	Common::Path _filename;
 
 	uint8 _volume;
 
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index 62f11527217..e78e16389f7 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -996,7 +996,7 @@ Common::String TinselEngine::getSavegameFilename(int16 saveNum) const {
 void TinselEngine::initializePath(const Common::FSNode &gamePath) {
 	if (TinselV1PSX) {
 		// Add subfolders needed for PSX versions of Discworld 1
-		SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 3, true);
+		SearchMan.addDirectory(gamePath, 0, 3, true);
 	} else {
 		// Add DW2 subfolder to search path in case user is running directly from the CDs
 		SearchMan.addSubDirectoryMatching(gamePath, "dw2");


Commit: da5f81d151354813c323e850f5cb91a427680fda
    https://github.com/scummvm/scummvm/commit/da5f81d151354813c323e850f5cb91a427680fda
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TITANIC: Migrate engine to Path

Changed paths:
    engines/titanic/support/avi_surface.cpp
    engines/titanic/support/files_manager.cpp
    engines/titanic/support/simple_file.cpp
    engines/titanic/true_talk/dialogue_file.cpp


diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp
index 09e52cf0d8c..78dd1f4da72 100644
--- a/engines/titanic/support/avi_surface.cpp
+++ b/engines/titanic/support/avi_surface.cpp
@@ -61,7 +61,7 @@ AVISurface::AVISurface(const CResourceKey &key) : _movieName(key.getString()) {
 		// The y222.avi is the bells animation for the music room.
 		// It needs on the fly fixing for the video header
 		_decoder->loadStream(new y222());
-	} else if (!_decoder->loadFile(_movieName)) {
+	} else if (!_decoder->loadFile(Common::Path(_movieName))) {
 		error("Could not open video - %s", key.getString().c_str());
 	}
 
diff --git a/engines/titanic/support/files_manager.cpp b/engines/titanic/support/files_manager.cpp
index 501400837e4..3b7ddd904a6 100644
--- a/engines/titanic/support/files_manager.cpp
+++ b/engines/titanic/support/files_manager.cpp
@@ -77,8 +77,7 @@ bool CFilesManager::loadResourceIndex() {
 }
 
 bool CFilesManager::fileExists(const CString &name) {
-	Common::File f;
-	return f.exists(name);
+	return Common::File::exists(Common::Path(name));
 }
 
 bool CFilesManager::scanForFile(const CString &name) {
diff --git a/engines/titanic/support/simple_file.cpp b/engines/titanic/support/simple_file.cpp
index a6205282250..7ecd07f6dc8 100644
--- a/engines/titanic/support/simple_file.cpp
+++ b/engines/titanic/support/simple_file.cpp
@@ -37,7 +37,7 @@ CString readStringFromStream(Common::SeekableReadStream *s) {
 
 bool File::open(const Common::Path &filename) {
 	if (!Common::File::open(filename))
-		error("Could not open file - %s", filename.toString().c_str());
+		error("Could not open file - %s", filename.toString(Common::Path::kNativeSeparator).c_str());
 	return true;
 }
 
@@ -477,7 +477,7 @@ bool StdCWadFile::open(const Common::String &filename) {
 	if (idx < 0) {
 		// Nope, so open up file for standard reading
 		assert(!name.empty());
-		if (!f.open(name))
+		if (!f.open(Common::Path(name)))
 			return false;
 
 		SimpleFile::open(f.readStream(f.size()));
@@ -492,7 +492,7 @@ bool StdCWadFile::open(const Common::String &filename) {
 	int resIndex = resStr.readInt();
 
 	// Open up the index for access
-	if (!f.open(fname))
+	if (!f.open(Common::Path(fname)))
 		return false;
 	int indexSize = f.readUint32LE() / 4;
 	assert(resIndex < indexSize);
diff --git a/engines/titanic/true_talk/dialogue_file.cpp b/engines/titanic/true_talk/dialogue_file.cpp
index 28b62756fbc..df16a8b2a73 100644
--- a/engines/titanic/true_talk/dialogue_file.cpp
+++ b/engines/titanic/true_talk/dialogue_file.cpp
@@ -31,7 +31,7 @@ void DialogueIndexEntry::load(Common::SeekableReadStream &s) {
 /*------------------------------------------------------------------------*/
 
 CDialogueFile::CDialogueFile(const CString &filename, uint count) {
-	if (!_file.open(filename))
+	if (!_file.open(Common::Path(filename)))
 		error("Could not locate dialogue file - %s", filename.c_str());
 
 	_cache.resize(count);


Commit: 7d05b3865480f1ceba910bca955d08e5eb820342
    https://github.com/scummvm/scummvm/commit/7d05b3865480f1ceba910bca955d08e5eb820342
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TOLTECS: Migrate engine to Path

Changed paths:
    engines/toltecs/resource.cpp


diff --git a/engines/toltecs/resource.cpp b/engines/toltecs/resource.cpp
index b7f62b0ddc5..83ef50d79fe 100644
--- a/engines/toltecs/resource.cpp
+++ b/engines/toltecs/resource.cpp
@@ -64,7 +64,7 @@ void ArchiveReader::dump(uint resIndex) {
 	int32 resourceSize = getResourceSize(resIndex);
 	byte *data = new byte[resourceSize];
 
-	Common::String fn = Common::String::format("toltecs_res.%03d", resIndex);
+	Common::Path fn(Common::String::format("toltecs_res.%03d", resIndex));
 
 	openResource(resIndex);
 	read(data, resourceSize);


Commit: 77a61aafc6642176c4c3b27a8580090193c6a68e
    https://github.com/scummvm/scummvm/commit/77a61aafc6642176c4c3b27a8580090193c6a68e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TONY: Migrate engine to Path

Changed paths:
    engines/tony/sound.cpp
    engines/tony/tony.cpp
    engines/tony/utils.cpp
    engines/tony/utils.h


diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp
index 1473ae2f04f..b7f08256a76 100644
--- a/engines/tony/sound.cpp
+++ b/engines/tony/sound.cpp
@@ -51,15 +51,15 @@ static int remapVolume(int volume) {
 }
 
 // Another obvious rip from gob engine. Hi DrMcCoy!
-Common::String setExtension(const Common::String &str, const Common::String &ext) {
+Common::Path setExtension(const Common::String &str, const Common::String &ext) {
 	if (str.empty())
-		return str;
+		return Common::Path();
 
 	const char *dot = strrchr(str.c_str(), '.');
 	if (dot)
-		return Common::String(str.c_str(), dot - str.c_str()) + ext;
+		return Common::Path(str.c_str(), dot - str.c_str()).appendInPlace(ext);
 
-	return str + ext;
+	return Common::Path(str + ext);
 }
 
 /****************************************************************************\
@@ -551,7 +551,7 @@ bool FPStream::loadFile(const Common::String &fileName, int bufSize) {
 	SoundCodecs codec = FPCODEC_UNKNOWN;
 
 	// Open the file stream for reading
-	if (_file.open(fileName))
+	if (_file.open(Common::Path(fileName)))
 		codec = FPCODEC_ADPCM;
 	else if (_file.open(setExtension(fileName, ".MP3")))
 		codec = FPCODEC_MP3;
@@ -560,7 +560,7 @@ bool FPStream::loadFile(const Common::String &fileName, int bufSize) {
 	else if (_file.open(setExtension(fileName, ".FLA")))
 		codec = FPCODEC_FLAC;
 	// Fallback: try with an extra '0' prefix
-	else if (_file.open("0" + fileName)) {
+	else if (_file.open(Common::Path("0" + fileName))) {
 		codec = FPCODEC_ADPCM;
 		warning("FPStream::loadFile(): Fallback from %s to %s", fileName.c_str(), _file.getName());
 	} else if (_file.open(setExtension("0" + fileName, ".MP3"))) {
diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp
index 482ddb92c10..d27a624c411 100644
--- a/engines/tony/tony.cpp
+++ b/engines/tony/tony.cpp
@@ -46,7 +46,7 @@ TonyEngine::TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc) : Eng
 	setDebugger(new Debugger());
 
 	// Add folders to the search directory list
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "Voices");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "Roasted");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "Music");
diff --git a/engines/tony/utils.cpp b/engines/tony/utils.cpp
index d5f27771b6c..2227b09322e 100644
--- a/engines/tony/utils.cpp
+++ b/engines/tony/utils.cpp
@@ -376,7 +376,7 @@ RMResUpdate::~RMResUpdate() {
 		_hFile.close();
 }
 
-void RMResUpdate::init(const Common::String &fileName) {
+void RMResUpdate::init(const Common::Path &fileName) {
 	// Open the resource update file
 	if (!_hFile.open(fileName))
 		// It doesn't exist, so exit immediately
diff --git a/engines/tony/utils.h b/engines/tony/utils.h
index da231b4de37..6e4935c1967 100644
--- a/engines/tony/utils.h
+++ b/engines/tony/utils.h
@@ -166,7 +166,7 @@ public:
 	RMResUpdate();
 	~RMResUpdate();
 
-	void init(const Common::String &fileName);
+	void init(const Common::Path &fileName);
 	MpalHandle queryResource(uint32 dwRes);
 };
 


Commit: c45606f1338c0089bb29f3f6992ea11298eed30e
    https://github.com/scummvm/scummvm/commit/c45606f1338c0089bb29f3f6992ea11298eed30e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TOON: Migrate engine to Path

Changed paths:
    engines/toon/anim.cpp
    engines/toon/audio.cpp
    engines/toon/audio.h
    engines/toon/font.cpp
    engines/toon/font.h
    engines/toon/hotspot.cpp
    engines/toon/hotspot.h
    engines/toon/movie.cpp
    engines/toon/movie.h
    engines/toon/picture.cpp
    engines/toon/picture.h
    engines/toon/resource.cpp
    engines/toon/resource.h
    engines/toon/script_func.cpp
    engines/toon/subtitles.cpp
    engines/toon/subtitles.h
    engines/toon/text.cpp
    engines/toon/text.h
    engines/toon/toon.cpp
    engines/toon/toon.h


diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp
index d9652cf6d78..cae43163e0b 100644
--- a/engines/toon/anim.cpp
+++ b/engines/toon/anim.cpp
@@ -32,7 +32,7 @@ bool Animation::loadAnimation(const Common::String &file) {
 	debugC(1, kDebugAnim, "loadAnimation(%s)", file.c_str());
 
 	uint32 fileSize = 0;
-	uint8 *fileData = _vm->resources()->getFileData(file, &fileSize);
+	uint8 *fileData = _vm->resources()->getFileData(Common::Path(file), &fileSize);
 	if (!fileData)
 		return false;
 
diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp
index 1ffa994f008..883dca3a18c 100644
--- a/engines/toon/audio.cpp
+++ b/engines/toon/audio.cpp
@@ -87,11 +87,11 @@ int AudioManager::playMusic(const Common::String &dir, const Common::String &mus
 	debugC(1, kDebugAudio, "playMusic(%s, %s)", dir.c_str(), music.c_str());
 
 	// two musics can be played at same time
-	Common::String path;
+	Common::Path path;
 	if (dir == "") {
-		path = Common::String::format("%s.MUS", music.c_str());
+		path = Common::Path(Common::String::format("%s.MUS", music.c_str()));
 	} else {
-		path = Common::String::format("ACT%d/%s/%s.MUS", _vm->state()->_currentChapter, dir.c_str(), music.c_str());
+		path = Common::Path(Common::String::format("ACT%d/%s/%s.MUS", _vm->state()->_currentChapter, dir.c_str(), music.c_str()));
 	}
 
 	if (_currentMusicName == music)
@@ -205,8 +205,8 @@ void AudioManager::closeAudioPack(int32 id) {
 	_audioPacks[id] = nullptr;
 }
 
-bool AudioManager::loadAudioPack(int32 id, const Common::String &indexFile, const Common::String &packFile) {
-	debugC(4, kDebugAudio, "loadAudioPack(%d, %s, %s)", id, indexFile.c_str(), packFile.c_str());
+bool AudioManager::loadAudioPack(int32 id, const Common::Path &indexFile, const Common::Path &packFile) {
+	debugC(4, kDebugAudio, "loadAudioPack(%d, %s, %s)", id, indexFile.toString().c_str(), packFile.toString().c_str());
 
 	closeAudioPack(id);
 	_audioPacks[id] = new AudioStreamPackage(_vm);
@@ -497,8 +497,8 @@ AudioStreamPackage::~AudioStreamPackage() {
 	delete _file;
 }
 
-bool AudioStreamPackage::loadAudioPackage(const Common::String &indexFile, const Common::String &streamFile) {
-	debugC(4, kDebugAudio, "loadAudioPackage(%s, %s)", indexFile.c_str(), streamFile.c_str());
+bool AudioStreamPackage::loadAudioPackage(const Common::Path &indexFile, const Common::Path &streamFile) {
+	debugC(4, kDebugAudio, "loadAudioPackage(%s, %s)", indexFile.toString().c_str(), streamFile.toString().c_str());
 
 	uint32 size = 0;
 	uint8 *fileData = _vm->resources()->getFileData(indexFile, &size);
diff --git a/engines/toon/audio.h b/engines/toon/audio.h
index bb7c7ae58c6..bfd4a0c05c9 100644
--- a/engines/toon/audio.h
+++ b/engines/toon/audio.h
@@ -102,7 +102,7 @@ public:
 	AudioStreamPackage(ToonEngine *vm);
 	~AudioStreamPackage();
 
-	bool loadAudioPackage(const Common::String &indexFile, const Common::String &streamFile);
+	bool loadAudioPackage(const Common::Path &indexFile, const Common::Path &streamFile);
 	void getInfo(int32 id, int32 *offset, int32 *size);
 	Common::SeekableReadStream *getStream(int32 id, bool ownMemory = false);
 protected:
@@ -152,7 +152,7 @@ public:
 	void setAmbientSFXVolume(int32 id, int volume);
 
 	void closeAudioPack(int32 id);
-	bool loadAudioPack(int32 id, const Common::String &indexFile, const Common::String &packFile);
+	bool loadAudioPack(int32 id, const Common::Path &indexFile, const Common::Path &packFile);
 
 	AudioStreamInstance *_channels[16];  // 0-1 : music
 	                                     // 2 : voice
diff --git a/engines/toon/font.cpp b/engines/toon/font.cpp
index 97bab432812..db4faceefce 100644
--- a/engines/toon/font.cpp
+++ b/engines/toon/font.cpp
@@ -321,7 +321,7 @@ void FontRenderer::renderMultiLineText(int16 x, int16 y, const Common::String &o
 	}
 }
 
-bool FontRenderer::loadDemoFont(const Common::String& filename) {
+bool FontRenderer::loadDemoFont(const Common::Path &filename) {
 	uint32 fileSize = 0;
 	uint8 *fileData = _vm->resources()->getFileData(filename, &fileSize);
 	if (!fileData)
diff --git a/engines/toon/font.h b/engines/toon/font.h
index d423edd13a1..6532ef4de58 100644
--- a/engines/toon/font.h
+++ b/engines/toon/font.h
@@ -34,7 +34,7 @@ public:
 	~FontRenderer();
 
 	void setFont(Animation *font);
-	bool loadDemoFont(const Common::String &filename);
+	bool loadDemoFont(const Common::Path &filename);
 	void computeSize(const Common::String &origText, int16 *retX, int16 *retY);
 	void renderText(int16 x, int16 y, const Common::String &origText, int32 mode);
 	void renderMultiLineText(int16 x, int16 y, const Common::String &origText, int32 mode, Graphics::Surface &frame);
diff --git a/engines/toon/hotspot.cpp b/engines/toon/hotspot.cpp
index a1b194dcf6b..c516be34b3a 100644
--- a/engines/toon/hotspot.cpp
+++ b/engines/toon/hotspot.cpp
@@ -95,8 +95,8 @@ int32 Hotspots::find(int16 x, int16 y) {
 	return foundId;
 }
 
-bool Hotspots::loadRif(const Common::String &rifName, const Common::String &additionalRifName) {
-	debugC(1, kDebugHotspot, "loadRif(%s, %s)", rifName.c_str(), additionalRifName.c_str());
+bool Hotspots::loadRif(const Common::Path &rifName, const Common::Path &additionalRifName) {
+	debugC(1, kDebugHotspot, "loadRif(%s, %s)", rifName.toString().c_str(), additionalRifName.toString().c_str());
 
 	uint32 size = 0;
 	uint8 *rifData = _vm->resources()->getFileData(rifName, &size);
@@ -107,7 +107,7 @@ bool Hotspots::loadRif(const Common::String &rifName, const Common::String &addi
 	uint8 *rifData2 = 0;
 
 	// English demo seems to have some invalid additional Rif data so do not load it
-	if (!_vm->isEnglishDemo() && additionalRifName.size())
+	if (!_vm->isEnglishDemo() && !additionalRifName.empty())
 		rifData2 = _vm->resources()->getFileData(additionalRifName, &size2);
 
 	// figure out the number of hotspots based on file size
diff --git a/engines/toon/hotspot.h b/engines/toon/hotspot.h
index 8e5455cccbc..f4961695d11 100644
--- a/engines/toon/hotspot.h
+++ b/engines/toon/hotspot.h
@@ -49,7 +49,7 @@ public:
 	Hotspots(ToonEngine *vm);
 	~Hotspots();
 
-	bool loadRif(const Common::String &rifName, const Common::String &additionalRifName);
+	bool loadRif(const Common::Path &rifName, const Common::Path &additionalRifName);
 	int32 find(int16 x, int16 y);
 	int32 findBasedOnCorner(int16 x, int16 y);
 	HotspotData *get(int32 id);
diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index ad5c180587e..552be3355e1 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -78,8 +78,8 @@ Movie::~Movie() {
 void Movie::init() const {
 }
 
-void Movie::play(const Common::String &video, int32 flags) {
-	debugC(1, kDebugMovie, "play(%s, %d)", video.c_str(), flags);
+void Movie::play(const Common::Path &video, int32 flags) {
+	debugC(1, kDebugMovie, "play(%s, %d)", video.toString().c_str(), flags);
 	bool isFirstIntroVideo = false;
 	if (video == "209_1M.SMK")
 		isFirstIntroVideo = true;
@@ -87,12 +87,12 @@ void Movie::play(const Common::String &video, int32 flags) {
 	_playing = true;
 	if (flags & 1)
 		_vm->getAudioManager()->setMusicVolume(0);
-	if (!_decoder->loadFile(video.c_str())) {
+	if (!_decoder->loadFile(video)) {
 		if (flags & 2)
 			return;
-		error("Unable to play video %s", video.c_str());
+		error("Unable to play video %s", video.toString().c_str());
 	}
-	_subtitle->load(video.c_str());
+	_subtitle->load(video);
 	playVideo(isFirstIntroVideo);
 	_vm->flushPalette(true);
 	if (flags & 1)
diff --git a/engines/toon/movie.h b/engines/toon/movie.h
index 3ed53f1d4fb..f6098be74e0 100644
--- a/engines/toon/movie.h
+++ b/engines/toon/movie.h
@@ -50,7 +50,7 @@ public:
 	virtual ~Movie(void);
 
 	void init() const;
-	void play(const Common::String &video, int32 flags = 0);
+	void play(const Common::Path &video, int32 flags = 0);
 	bool isPlaying() { return _playing; }
 
 protected:
diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index 8b0e0392949..c63b3eb5b05 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -29,8 +29,8 @@
 
 namespace Toon {
 
-bool Picture::loadPicture(const Common::String &file) {
-	debugC(1, kDebugPicture, "loadPicture(%s)", file.c_str());
+bool Picture::loadPicture(const Common::Path &file) {
+	debugC(1, kDebugPicture, "loadPicture(%s)", file.toString().c_str());
 
 	uint32 size = 0;
 	uint8 *fileData = _vm->resources()->getFileData(file, &size);
diff --git a/engines/toon/picture.h b/engines/toon/picture.h
index 63b3da67e74..2a955bc752c 100644
--- a/engines/toon/picture.h
+++ b/engines/toon/picture.h
@@ -25,7 +25,7 @@
 #include "common/stream.h"
 #include "common/array.h"
 #include "common/func.h"
-#include "common/str.h"
+#include "common/path.h"
 
 #include "toon/toon.h"
 
@@ -38,7 +38,7 @@ public:
 	Picture(ToonEngine *vm);
 	~Picture();
 
-	bool loadPicture(const Common::String &file);
+	bool loadPicture(const Common::Path &file);
 	void setupPalette();
 	void draw(Graphics::Surface &surface, int16 x, int16 y, int16 dx, int16 dy);
 	void drawWithRectList(Graphics::Surface& surface, int16 x, int16 y, int16 dx, int16 dy, Common::Array<Common::Rect>& rectArray);
diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp
index 6394ac41905..813c7df4ced 100644
--- a/engines/toon/resource.cpp
+++ b/engines/toon/resource.cpp
@@ -49,16 +49,16 @@ Resources::~Resources() {
 	purgeFileData();
 }
 
-void Resources::removePackageFromCache(const Common::String &packName) {
+void Resources::removePackageFromCache(const Common::Path &packName) {
 	// I'm not sure what's a good strategy here. It seems unnecessary to
 	// actually remove the cached resources, because the player may be
 	// wandering back and forth between rooms. So for now, do nothing.
 }
 
-bool Resources::getFromCache(const Common::String &fileName, uint32 *fileSize, uint8 **fileData) {
+bool Resources::getFromCache(const Common::Path &fileName, uint32 *fileSize, uint8 **fileData) {
 	for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
-		if ((*entry)->_data && (*entry)->_fileName.compareToIgnoreCase(fileName) == 0) {
-			debugC(5, kDebugResource, "getFromCache(%s) - Got %d bytes from %s", fileName.c_str(), (*entry)->_size, (*entry)->_packName.c_str());
+		if ((*entry)->_data && (*entry)->_fileName.equalsIgnoreCase(fileName)) {
+			debugC(5, kDebugResource, "getFromCache(%s) - Got %d bytes from %s", fileName.toString().c_str(), (*entry)->_size, (*entry)->_packName.toString().c_str());
 			(*entry)->_age = 0;
 			*fileSize = (*entry)->_size;
 			*fileData = (*entry)->_data;
@@ -68,8 +68,8 @@ bool Resources::getFromCache(const Common::String &fileName, uint32 *fileSize, u
 	return false;
 }
 
-void Resources::addToCache(const Common::String &packName, const Common::String &fileName, uint32 fileSize, uint8 *fileData) {
-	debugC(5, kDebugResource, "addToCache(%s, %s, %d) - Total Size: %d", packName.c_str(), fileName.c_str(), fileSize, _cacheSize + fileSize);
+void Resources::addToCache(const Common::Path &packName, const Common::Path &fileName, uint32 fileSize, uint8 *fileData) {
+	debugC(5, kDebugResource, "addToCache(%s, %s, %d) - Total Size: %d", packName.toString().c_str(), fileName.toString().c_str(), fileSize, _cacheSize + fileSize);
 	for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
 		if ((*entry)->_data) {
 			(*entry)->_age++;
@@ -92,7 +92,7 @@ void Resources::addToCache(const Common::String &packName, const Common::String
 		free(bestEntry->_data);
 		bestEntry->_data = nullptr;
 		_cacheSize -= bestEntry->_size;
-		debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.c_str(), bestEntry->_packName.c_str(), bestEntry->_size);
+		debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.toString().c_str(), bestEntry->_packName.toString().c_str(), bestEntry->_size);
 	}
 
 	for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
@@ -114,8 +114,8 @@ void Resources::addToCache(const Common::String &packName, const Common::String
 	_resourceCache.push_back(entry);
 }
 
-bool Resources::openPackage(const Common::String &fileName) {
-	debugC(1, kDebugResource, "openPackage(%s)", fileName.c_str());
+bool Resources::openPackage(const Common::Path &fileName) {
+	debugC(1, kDebugResource, "openPackage(%s)", fileName.toString().c_str());
 
 	Common::File file;
 	bool opened = file.open(fileName);
@@ -132,7 +132,7 @@ bool Resources::openPackage(const Common::String &fileName) {
 	return true;
 }
 
-void Resources::closePackage(const Common::String &fileName) {
+void Resources::closePackage(const Common::Path &fileName) {
 
 	removePackageFromCache(fileName);
 	for (uint32 i = 0; i < _pakFiles.size(); i++) {
@@ -144,8 +144,8 @@ void Resources::closePackage(const Common::String &fileName) {
 	}
 }
 
-uint8 *Resources::getFileData(const Common::String &fileName, uint32 *fileSize) {
-	debugC(4, kDebugResource, "getFileData(%s, fileSize)", fileName.c_str());
+uint8 *Resources::getFileData(const Common::Path &fileName, uint32 *fileSize) {
+	debugC(4, kDebugResource, "getFileData(%s, fileSize)", fileName.toString().c_str());
 
 	// first try to find files outside of .pak
 	// some patched files have not been included in package.
@@ -184,8 +184,8 @@ uint8 *Resources::getFileData(const Common::String &fileName, uint32 *fileSize)
 	}
 }
 
-Common::SeekableReadStream *Resources::openFile(const Common::String &fileName) {
-	debugC(1, kDebugResource, "openFile(%s)", fileName.c_str());
+Common::SeekableReadStream *Resources::openFile(const Common::Path &fileName) {
+	debugC(1, kDebugResource, "openFile(%s)", fileName.toString().c_str());
 
 	// first try to find files outside of .pak
 	// some patched files have not been included in package.
@@ -217,8 +217,8 @@ void Resources::purgeFileData() {
 	_allocatedFileData.clear();
 }
 
-Common::SeekableReadStream *PakFile::createReadStream(const Common::String &fileName) {
-	debugC(1, kDebugResource, "createReadStream(%s)", fileName.c_str());
+Common::SeekableReadStream *PakFile::createReadStream(const Common::Path &fileName) {
+	debugC(1, kDebugResource, "createReadStream(%s)", fileName.toString().c_str());
 
 	uint32 fileSize = 0;
 	uint8 *buffer = getFileData(fileName, &fileSize);
@@ -228,11 +228,11 @@ Common::SeekableReadStream *PakFile::createReadStream(const Common::String &file
 		return nullptr;
 }
 
-uint8 *PakFile::getFileData(const Common::String &fileName, uint32 *fileSize) {
-	debugC(4, kDebugResource, "getFileData(%s, fileSize)", fileName.c_str());
+uint8 *PakFile::getFileData(const Common::Path &fileName, uint32 *fileSize) {
+	debugC(4, kDebugResource, "getFileData(%s, fileSize)", fileName.toString().c_str());
 
 	for (uint32 i = 0; i < _numFiles; i++) {
-		if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
+		if (fileName.equalsIgnoreCase(_files[i]._name)) {
 			Common::File file;
 			if (file.open(_packName)) {
 					*fileSize = _files[i]._size;
@@ -251,7 +251,7 @@ uint8 *PakFile::getFileData(const Common::String &fileName, uint32 *fileSize) {
 	return 0;
 }
 
-void PakFile::open(Common::SeekableReadStream *rs, const Common::String &packName) {
+void PakFile::open(Common::SeekableReadStream *rs, const Common::Path &packName) {
 	debugC(1, kDebugResource, "open(rs)");
 
 	char buffer[64];
diff --git a/engines/toon/resource.h b/engines/toon/resource.h
index 5da43e9c191..c5a8b7f61e3 100644
--- a/engines/toon/resource.h
+++ b/engines/toon/resource.h
@@ -36,10 +36,10 @@ public:
 	PakFile();
 	~PakFile();
 
-	void open(Common::SeekableReadStream *rs, const Common::String &packName);
-	uint8 *getFileData(const Common::String &fileName, uint32 *fileSize);
-	Common::String getPackName() { return _packName; }
-	Common::SeekableReadStream *createReadStream(const Common::String &fileName);
+	void open(Common::SeekableReadStream *rs, const Common::Path &packName);
+	uint8 *getFileData(const Common::Path &fileName, uint32 *fileSize);
+	Common::Path getPackName() { return _packName; }
+	Common::SeekableReadStream *createReadStream(const Common::Path &fileName);
 	void close();
 
 protected:
@@ -48,7 +48,7 @@ protected:
 		int32 _offset;
 		int32 _size;
 	};
-	Common::String _packName;
+	Common::Path _packName;
 
 	uint32 _numFiles;
 	Common::Array<File> _files;
@@ -63,8 +63,8 @@ public:
 		free(_data);
 	}
 
-	Common::String _packName;
-	Common::String _fileName;
+	Common::Path _packName;
+	Common::Path _fileName;
 	uint32 _age;
 	uint32 _size;
 	uint8 *_data;
@@ -74,10 +74,10 @@ class Resources {
 public:
 	Resources(ToonEngine *vm);
 	~Resources();
-	bool openPackage(const Common::String &file);
-	void closePackage(const Common::String &fileName);
-	Common::SeekableReadStream *openFile(const Common::String &file);
-	uint8 *getFileData(const Common::String &fileName, uint32 *fileSize); // this memory must be copied to your own structures!
+	bool openPackage(const Common::Path &file);
+	void closePackage(const Common::Path &fileName);
+	Common::SeekableReadStream *openFile(const Common::Path &file);
+	uint8 *getFileData(const Common::Path &fileName, uint32 *fileSize); // this memory must be copied to your own structures!
 	void purgeFileData();
 
 protected:
@@ -87,9 +87,9 @@ protected:
 	uint32 _cacheSize;
 	Common::Array<CacheEntry *> _resourceCache;
 
-	void removePackageFromCache(const Common::String &packName);
-	bool getFromCache(const Common::String &fileName, uint32 *fileSize, uint8 **fileData);
-	void addToCache(const Common::String &packName, const Common::String &fileName, uint32 fileSize, uint8 *fileData);
+	void removePackageFromCache(const Common::Path &packName);
+	bool getFromCache(const Common::Path &fileName, uint32 *fileSize, uint8 **fileData);
+	void addToCache(const Common::Path &packName, const Common::Path &fileName, uint32 fileSize, uint8 *fileData);
 };
 
 } // End of namespace Toon
diff --git a/engines/toon/script_func.cpp b/engines/toon/script_func.cpp
index 8feddf248ed..af8c141e4ee 100644
--- a/engines/toon/script_func.cpp
+++ b/engines/toon/script_func.cpp
@@ -311,11 +311,11 @@ int32 ScriptFunc::sys_Cmd_Flip_Screens(EMCState *state) {
 
 int32 ScriptFunc::sys_Cmd_Play_Flic(EMCState *state) {
 	Common::String stateText = GetText(0, state);
-	Common::String name;
+	Common::Path name;
 
 	// workaround for the video of the beginning
 	if (stateText.contains("209")) {
-		name = stateText;
+		name = Common::Path(stateText);
 	} else {
 		name = _vm->createRoomFilename(stateText.c_str());
 	}
diff --git a/engines/toon/subtitles.cpp b/engines/toon/subtitles.cpp
index 194434d9140..aaa50b8b9d9 100644
--- a/engines/toon/subtitles.cpp
+++ b/engines/toon/subtitles.cpp
@@ -66,16 +66,16 @@ void SubtitleRenderer::render(const Graphics::Surface &frame, uint32 frameNumber
 	_vm->_system->copyRectToScreen(_subSurface->getBasePtr(0, 0), _subSurface->pitch, 0, 0, _subSurface->w,  _subSurface->h);
 }
 
-bool SubtitleRenderer::load(const Common::String &video) {
+bool SubtitleRenderer::load(const Common::Path &video) {
 	// warning(video.c_str());
 
 	_hasSubtitles = false;
 
-	Common::String subfile(video);
+	Common::String subfile(video.baseName());
 	Common::String ext("tss");
 	subfile.replace(subfile.size() - ext.size(), ext.size(), ext);
 
-	Common::ScopedPtr<Common::SeekableReadStream> subsStream(_vm->resources()->openFile(subfile));
+	Common::ScopedPtr<Common::SeekableReadStream> subsStream(_vm->resources()->openFile(video.getParent().appendComponent(subfile)));
 	if (subsStream == nullptr) {
 		return false;
 	}
diff --git a/engines/toon/subtitles.h b/engines/toon/subtitles.h
index fda4c772620..fe9f8d9cb56 100644
--- a/engines/toon/subtitles.h
+++ b/engines/toon/subtitles.h
@@ -44,7 +44,7 @@ public:
 	SubtitleRenderer(ToonEngine *vm);
 	~SubtitleRenderer();
 
-	bool load(const Common::String &video);
+	bool load(const Common::Path &video);
 	void render(const Graphics::Surface &frame, uint32 frameNumber, byte color);
 protected:
 	ToonEngine *_vm;
diff --git a/engines/toon/text.cpp b/engines/toon/text.cpp
index 9472af6c23c..52ea351525e 100644
--- a/engines/toon/text.cpp
+++ b/engines/toon/text.cpp
@@ -34,8 +34,8 @@ TextResource::~TextResource(void) {
 	delete[] _textData;
 }
 
-bool TextResource::loadTextResource(const Common::String &fileName) {
-	debugC(1, kDebugText, "loadTextResource(%s)", fileName.c_str());
+bool TextResource::loadTextResource(const Common::Path &fileName) {
+	debugC(1, kDebugText, "loadTextResource(%s)", fileName.toString().c_str());
 
 	uint32 fileSize = 0;
 	uint8 *data = _vm->resources()->getFileData(fileName, &fileSize);
diff --git a/engines/toon/text.h b/engines/toon/text.h
index a7a929f87d8..271a7ba84f1 100644
--- a/engines/toon/text.h
+++ b/engines/toon/text.h
@@ -31,7 +31,7 @@ public:
 	TextResource(ToonEngine *vm);
 	~TextResource(void);
 
-	bool loadTextResource(const Common::String &fileName);
+	bool loadTextResource(const Common::Path &fileName);
 	char *getText(int32 id);
 	int32 getId(int32 offset);
 	int32 getNext(int32 offset);
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index ee5b8e70e0f..da96470779a 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -98,7 +98,7 @@ void ToonEngine::init() {
 
 	_firstFrame = false;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "MISC");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "ACT1");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "ACT2");
@@ -1939,58 +1939,58 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
 	// load package
 	if (!resources()->openPackage(createRoomFilename(locationName + ".PAK"))) {
 		const char *msg = _s("Unable to locate the '%s' data file.");
-		Common::String roomFileName = createRoomFilename(locationName + ".PAK");
+		Common::Path roomFileName = createRoomFilename(locationName + ".PAK");
 
-		Common::U32String buf = Common::U32String::format(_(msg), roomFileName.c_str());
+		Common::U32String buf = Common::U32String::format(_(msg), roomFileName.toString(Common::Path::kNativeSeparator).c_str());
 		GUIErrorMessage(buf);
-		warning(msg, roomFileName.c_str());
+		warning(msg, roomFileName.toString().c_str());
 		_shouldQuit = true;
 		return;
 	}
 
-	loadAdditionalPalette(locationName + ".NPP", 0);
+	loadAdditionalPalette(Common::Path(locationName + ".NPP"), 0);
 
 	_additionalPalette2Present = false;
-	loadAdditionalPalette(locationName + ".NP2", 1);
+	loadAdditionalPalette(Common::Path(locationName + ".NP2"), 1);
 
-	loadAdditionalPalette(locationName + ".CUP", 2);
+	loadAdditionalPalette(Common::Path(locationName + ".CUP"), 2);
 
 	// load artwork
 	delete _currentPicture;
 	_currentPicture = new Picture(this);
-	_currentPicture->loadPicture(locationName + ".CPS");
+	_currentPicture->loadPicture(Common::Path(locationName + ".CPS"));
 	_currentPicture->setupPalette();
 
 	delete _currentMask;
 	_currentMask = new Picture(this);
-	if (_currentMask->loadPicture(locationName + ".MSC"))
+	if (_currentMask->loadPicture(Common::Path(locationName + ".MSC")))
 		_pathFinding->init(_currentMask);
 
 	delete _roomTexts;
 	_roomTexts = new TextResource(this);
-	_roomTexts->loadTextResource(locationName + ".TRE");
+	_roomTexts->loadTextResource(Common::Path(locationName + ".TRE"));
 
 	uint32 fileSize;
-	uint8 *sceneData = resources()->getFileData(locationName + ".DAT", &fileSize);
+	uint8 *sceneData = resources()->getFileData(Common::Path(locationName + ".DAT"), &fileSize);
 	if (sceneData) {
 		delete[] _roomScaleData;
 		_roomScaleData = new uint8[fileSize];
 		memcpy(_roomScaleData, sceneData, fileSize);
 	}
 
-	_audioManager->loadAudioPack(1, locationName + ".SVI", createRoomFilename(locationName + ".SVL"));
-	_audioManager->loadAudioPack(3, locationName + ".SEI", locationName + ".SEL");
+	_audioManager->loadAudioPack(1, Common::Path(locationName + ".SVI"), createRoomFilename(locationName + ".SVL"));
+	_audioManager->loadAudioPack(3, Common::Path(locationName + ".SEI"), Common::Path(locationName + ".SEL"));
 
 	if (state()->_locations[SceneId]._flags & 0x40) {
 		Common::String cutaway = state()->_locations[SceneId]._cutaway;
-		_hotspots->loadRif(locationName + ".RIC", cutaway + ".RIC");
+		_hotspots->loadRif(Common::Path(locationName + ".RIC"), Common::Path(cutaway + ".RIC"));
 	} else {
-		_hotspots->loadRif(locationName + ".RIC", "");
+		_hotspots->loadRif(Common::Path(locationName + ".RIC"), "");
 	}
 	restoreRifFlags(_gameState->_currentScene);
 
 	uint32 convfileSize;
-	uint8 *convData = resources()->getFileData(locationName + ".CNV", &convfileSize);
+	uint8 *convData = resources()->getFileData(Common::Path(locationName + ".CNV"), &convfileSize);
 	if (convData) {
 		assert(convfileSize < 4096 * sizeof(int16));
 		memcpy(_conversationData , convData, convfileSize);
@@ -2081,7 +2081,7 @@ void ToonEngine::setupGeneralPalette() {
 		_drew->setupPalette();
 }
 
-void ToonEngine::loadAdditionalPalette(const Common::String &fileName, int32 mode) {
+void ToonEngine::loadAdditionalPalette(const Common::Path &fileName, int32 mode) {
 
 	uint32 size = 0;
 	uint8 *palette = resources()->getFileData(fileName, &size);
@@ -3561,14 +3561,14 @@ void ToonEngine::deleteMouseItem() {
 	setCursor(0);
 }
 
-void ToonEngine::showCutaway(const Common::String &cutawayPicture) {
+void ToonEngine::showCutaway(const Common::Path &cutawayPicture) {
 	_gameState->_inCutaway = true;
 	delete _currentCutaway;
 	_currentCutaway = nullptr;
 	_currentCutaway = new Picture(this);
 	if (cutawayPicture.empty()) {
 		Common::String name = _gameState->_locations[_gameState->_currentScene]._cutaway;
-		_currentCutaway->loadPicture(name + ".CPS");
+		_currentCutaway->loadPicture(Common::Path(name + ".CPS"));
 	} else {
 		_currentCutaway->loadPicture(cutawayPicture);
 	}
@@ -4234,7 +4234,7 @@ const char *ToonEngine::getSpecialConversationMusic(int32 conversationId) {
 	return specialMusic[randRange(0, 1) + conversationId * 2];
 }
 
-void ToonEngine::viewInventoryItem(const Common::String &str, int32 lineId, int32 itemDest) {
+void ToonEngine::viewInventoryItem(const Common::Path &str, int32 lineId, int32 itemDest) {
 	storePalette();
 	fadeOut(5);
 
@@ -5335,8 +5335,8 @@ int32 ToonEngine::pauseSceneAnimationScript(int32 animScriptId, int32 tickToWait
 	return nextTicks;
 }
 
-Common::String ToonEngine::createRoomFilename(const Common::String& name) {
-	Common::String file = Common::String::format("ACT%d/%s/%s", _gameState->_currentChapter, _gameState->_locations[_gameState->_currentScene]._name, name.c_str());
+Common::Path ToonEngine::createRoomFilename(const Common::String& name) {
+	Common::Path file(Common::String::format("ACT%d/%s/%s", _gameState->_currentChapter, _gameState->_locations[_gameState->_currentScene]._name, name.c_str()));
 	return file;
 }
 
diff --git a/engines/toon/toon.h b/engines/toon/toon.h
index 44ed9f40bbe..75877236c9a 100644
--- a/engines/toon/toon.h
+++ b/engines/toon/toon.h
@@ -128,7 +128,7 @@ public:
 	void exitScene();
 	void loadCursor();
 	void setCursor(int32 type, bool inventory = false, int32 offsetX = 0, int offsetY = 0);
-	void loadAdditionalPalette(const Common::String &fileName, int32 mode);
+	void loadAdditionalPalette(const Common::Path &fileName, int32 mode);
 	void setupGeneralPalette();
 	void render();
 	void update(int32 timeIncrement);
@@ -169,7 +169,7 @@ public:
 	void rearrangeInventory();
 	void createMouseItem(int32 item);
 	void deleteMouseItem();
-	void showCutaway(const Common::String &cutawayPicture);
+	void showCutaway(const Common::Path &cutawayPicture);
 	void hideCutaway();
 	void drawPalette();
 	void newGame();
@@ -192,7 +192,7 @@ public:
 	int32 handleInventoryOnDrew(int32 itemId);
 	int32 pauseSceneAnimationScript(int32 animScriptId, int32 tickToWait);
 	void updateTimer(int32 timeIncrement);
-	Common::String createRoomFilename(const Common::String &name);
+	Common::Path createRoomFilename(const Common::String &name);
 	void createShadowLUT();
 	void playTalkAnimOnCharacter(int32 animID, int32 characterId, bool talker);
 	void updateScrolling(bool force, int32 timeIncrement);
@@ -203,7 +203,7 @@ public:
 	void makeLineNonWalkable(int32 x, int32 y, int32 x2, int32 y2);
 	void makeLineWalkable(int32 x, int32 y, int32 x2, int32 y2);
 	void renderInventory();
-	void viewInventoryItem(const Common::String &str, int32 lineId, int32 itemDest);
+	void viewInventoryItem(const Common::Path &str, int32 lineId, int32 itemDest);
 	void storePalette();
 	void restorePalette();
 	const char *getSpecialConversationMusic(int32 locationId);


Commit: a17ccbea7248c989b8e3a27f42b9dea86f685df5
    https://github.com/scummvm/scummvm/commit/a17ccbea7248c989b8e3a27f42b9dea86f685df5
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TOUCHE: Migrate engine to Path

Changed paths:
    engines/touche/touche.cpp


diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 9a88c33cec1..3ad521e13c3 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -98,7 +98,7 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language)
 	_menuRedrawCounter = 0;
 	memset(_paletteBuffer, 0, sizeof(_paletteBuffer));
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
 	SearchMan.addSubDirectoryMatching(gameDataDir, "database");
 
@@ -3418,7 +3418,7 @@ void ToucheEngine::initMusic() {
 	// Detect External Music Files
 	bool extMusic = true;
 	for (int num = 0; num < 26 && extMusic; num++) {
-		Common::String extMusicFilename = Common::String::format("track%02d", num+1);
+		Common::Path extMusicFilename(Common::String::format("track%02d", num+1));
 		Audio::SeekableAudioStream *musicStream = Audio::SeekableAudioStream::openStreamFile(extMusicFilename);
 		if (!musicStream)
 			extMusic = false;
@@ -3443,10 +3443,10 @@ void ToucheEngine::startMusic(int num) {
 		_fData.seek(offs);
 		_midiPlayer->play(_fData, size, true);
 	} else {
-		Common::String extMusicFilename = Common::String::format("track%02d", num);
+		Common::Path extMusicFilename(Common::String::format("track%02d", num));
 		Audio::SeekableAudioStream *extMusicFileStream = Audio::SeekableAudioStream::openStreamFile(extMusicFilename);
 		if (!extMusicFileStream) {
-			error("Unable to open %s for reading", extMusicFilename.c_str());
+			error("Unable to open %s for reading", extMusicFilename.toString().c_str());
 		}
 		Audio::LoopingAudioStream *loopStream = new Audio::LoopingAudioStream(extMusicFileStream, 0);
 		_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, loopStream, -1, _musicVolume);


Commit: e06e8761f1ecd58ae2caa036a02e579afd2fd307
    https://github.com/scummvm/scummvm/commit/e06e8761f1ecd58ae2caa036a02e579afd2fd307
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TRECISION: Migrate engine to Path

Changed paths:
    engines/trecision/animmanager.cpp
    engines/trecision/animmanager.h
    engines/trecision/animtype.cpp
    engines/trecision/console.cpp
    engines/trecision/fastfile.cpp
    engines/trecision/fastfile.h
    engines/trecision/graphics.cpp
    engines/trecision/resource.cpp
    engines/trecision/sound.cpp
    engines/trecision/sound.h
    engines/trecision/text.cpp
    engines/trecision/text.h
    engines/trecision/trecision.cpp
    engines/trecision/trecision.h
    engines/trecision/video.cpp
    engines/trecision/video.h


diff --git a/engines/trecision/animmanager.cpp b/engines/trecision/animmanager.cpp
index 125c92e58a3..0a04fcec3a1 100644
--- a/engines/trecision/animmanager.cpp
+++ b/engines/trecision/animmanager.cpp
@@ -65,7 +65,7 @@ AnimManager::~AnimManager() {
 	}
 }
 
-void AnimManager::playMovie(const Common::String &filename, int startFrame, int endFrame, bool singleChoice) {
+void AnimManager::playMovie(const Common::Path &filename, int startFrame, int endFrame, bool singleChoice) {
 	NightlongVideoDecoder *videoDecoder;
 
 	if (!_vm->isAmiga())
@@ -74,7 +74,7 @@ void AnimManager::playMovie(const Common::String &filename, int startFrame, int
 		videoDecoder = new NightlongAmigaDecoder();
 
 	if (!videoDecoder->loadFile(filename)) {
-		warning("playMovie: File %s not found", filename.c_str());
+		warning("playMovie: File %s not found", filename.toString().c_str());
 		delete videoDecoder;
 		_vm->_dialogMgr->afterChoice();
 		return;
@@ -160,11 +160,11 @@ void AnimManager::drawFrameSubtitles(Graphics::Surface *surface, int frameNum) {
 	_vm->_drawText.draw(_vm, false, surface);
 }
 
-void AnimManager::openSmkAnim(int slot, const Common::String &name) {
+void AnimManager::openSmkAnim(int slot, const Common::Path &name) {
 	for (int i = 0; i < 3; i++) {
 		// Open the animation, or swap the 3 CDs to find it
 		if (_animFile[slot].hasFile(name)) {
-			openSmk(slot, _animFile[slot].createReadStreamForMember(name));
+			openSmk(slot, name);
 			return;
 		}
 
@@ -172,21 +172,40 @@ void AnimManager::openSmkAnim(int slot, const Common::String &name) {
 		swapCD(_curCD);
 	}
 
-	error("openSmkAnim(): File %s not found", name.c_str());
+	error("openSmkAnim(): File %s not found", name.toString().c_str());
 }
 
-void AnimManager::openSmk(int slot, Common::SeekableReadStream *stream) {
-	if (!_vm->isAmiga())
-		_animations[slot] = new NightlongSmackerDecoder();
-	else
-		_animations[slot] = new NightlongAmigaDecoder();
-
-	if (!_animations[slot]->loadStream(stream)) {
-		warning("Invalid SMK file");
+void AnimManager::openSmk(int slot, const Common::Path &name) {
+	Common::SeekableReadStream *stream =_animFile[slot].createReadStreamForMember(name);
+	if (!stream) {
+		warning("Can't open SMK file");
 		closeSmk(slot);
+		return;
+	}
+	if (!_vm->isAmiga()) {
+		_animations[slot] = new NightlongSmackerDecoder();
+		if (!_animations[slot]->loadStream(stream)) {
+			warning("Invalid SMK file");
+			closeSmk(slot);
+			return;
+		}
 	} else {
-		_animations[slot]->start();
+		NightlongAmigaDecoder *amigaDecoder = new NightlongAmigaDecoder();
+		_animations[slot] = amigaDecoder;
+		if (!_animations[slot]->loadStream(stream)) {
+			warning("Invalid SMK file");
+			closeSmk(slot);
+			return;
+		}
+		Common::String baseName("a" + name.baseName());
+		Common::Path audioPath = name.getParent().appendComponent(baseName);
+
+		if (Common::File::exists(audioPath)) {
+			amigaDecoder->addAudioSideTrack(audioPath);
+		}
 	}
+
+	_animations[slot]->start();
 }
 
 void AnimManager::closeSmk(int slot) {
@@ -493,7 +512,7 @@ void AnimManager::drawSmkActionFrame() {
 }
 
 void AnimManager::swapCD(int cd) {
-	Common::String animFileName = Common::String::format("nlanim.cd%d", cd);
+	Common::Path animFileName(Common::String::format("nlanim.cd%d", cd));
 	for (uint8 i = 0; i < MAXACTIVEANIM; ++i) {
 		_animFile[i].close();
 		_animFile[i].open(_vm, animFileName);
diff --git a/engines/trecision/animmanager.h b/engines/trecision/animmanager.h
index d6bf04108b7..bee8c764a7c 100644
--- a/engines/trecision/animmanager.h
+++ b/engines/trecision/animmanager.h
@@ -61,8 +61,8 @@ private:
 	int _curCD;
 	bool _bgAnimRestarted;
 
-	void openSmk(int slot, Common::SeekableReadStream *stream);
-	void openSmkAnim(int slot, const Common::String &name);
+	void openSmk(int slot, const Common::Path &name);
+	void openSmkAnim(int slot, const Common::Path &name);
 	void toggleMuteBgAnim(uint16 animation);
 	void closeSmk(int slot);
 	void drawFrame(NightlongVideoDecoder *smkDecoder, uint16 x, uint16 y, bool updateScreen);
@@ -89,7 +89,7 @@ public:
 	void smkStop(uint16 slot);
 	void refreshActionAnimation() { refreshSmkAnim(_playingAnims[kSmackerAction]); }
 	bool isActionActive() const { return _playingAnims[kSmackerAction] != 0; }
-	void playMovie(const Common::String &filename, int startFrame = 0, int endFrame = -1, bool singleChoice = false);
+	void playMovie(const Common::Path &filename, int startFrame = 0, int endFrame = -1, bool singleChoice = false);
 	void startFullMotion();
 	void stopFullMotion();
 
diff --git a/engines/trecision/animtype.cpp b/engines/trecision/animtype.cpp
index 3e5a094335f..ad6244e37d6 100644
--- a/engines/trecision/animtype.cpp
+++ b/engines/trecision/animtype.cpp
@@ -249,13 +249,13 @@ void AnimTypeManager::processAtFrame(ATFHandle *h, int type, int atf) {
 	case ATFREADBOX:
 		switch (index) {
 		case 1: {
-			const Common::String filename = Common::String::format("%s.3d", _vm->_room[_vm->_curRoom]._baseName);
+			const Common::Path filename(Common::String::format("%s.3d", _vm->_room[_vm->_curRoom]._baseName));
 			_vm->read3D(filename);
 			_vm->_room[_vm->_curRoom].setExtra(false);
 			}
 			break;
 		case 2: {
-			const Common::String filename = Common::String::format("%s2.3d", _vm->_room[_vm->_curRoom]._baseName);
+			const Common::Path filename(Common::String::format("%s2.3d", _vm->_room[_vm->_curRoom]._baseName));
 			_vm->read3D(filename);
 			_vm->_room[_vm->_curRoom].setExtra(true);
 			if (_vm->_curRoom == kRoom37)
diff --git a/engines/trecision/console.cpp b/engines/trecision/console.cpp
index 5c4a495db16..b362b52226c 100644
--- a/engines/trecision/console.cpp
+++ b/engines/trecision/console.cpp
@@ -66,11 +66,11 @@ bool Console::Cmd_DumpAnim(int argc, const char **argv) {
 
 	FastFile animFile;
 
-	Common::String fileName = argv[1];
+	Common::Path fileName(argv[1]);
 
 	bool found = false;
 	for (int i = 1; i <= 3; i++) {
-		Common::String animFileName = Common::String::format("nlanim.cd%d", i);
+		Common::Path animFileName(Common::String::format("nlanim.cd%d", i));
 		animFile.open(_vm, animFileName);
 
 		if (animFile.hasFile(fileName)) {
@@ -88,7 +88,7 @@ bool Console::Cmd_DumpAnim(int argc, const char **argv) {
 	Common::SeekableReadStream *dataFile = animFile.createReadStreamForMember(fileName);
 
 	Common::DumpFile outFile;
-	Common::String outName = fileName + ".dump";
+	Common::Path outName = fileName.append(".dump");
 	outFile.open(outName);
 	outFile.writeStream(dataFile, dataFile->size());
 	outFile.finalize();
@@ -105,17 +105,17 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::String fileName = argv[1];
+	Common::Path fileName(argv[1]);
 
 	if (!_vm->_dataFile.hasFile(fileName)) {
 		debugPrintf("File not found\n");
 		return true;
 	}
 
-	Common::SeekableReadStream *dataFile = fileName.hasSuffix(".cr") ? _vm->_dataFile.createReadStreamForCompressedMember(fileName) : _vm->_dataFile.createReadStreamForMember(fileName);
+	Common::SeekableReadStream *dataFile = fileName.baseName().hasSuffix(".cr") ? _vm->_dataFile.createReadStreamForCompressedMember(fileName) : _vm->_dataFile.createReadStreamForMember(fileName);
 
 	Common::DumpFile outFile;
-	Common::String outName = fileName + ".dump";
+	Common::Path outName = fileName.append(".dump");
 	outFile.open(outName);
 	outFile.writeStream(dataFile, dataFile->size());
 	outFile.finalize();
diff --git a/engines/trecision/fastfile.cpp b/engines/trecision/fastfile.cpp
index f7d7e93a8da..1e4b83bce28 100644
--- a/engines/trecision/fastfile.cpp
+++ b/engines/trecision/fastfile.cpp
@@ -37,7 +37,7 @@ FastFile::~FastFile() {
 	close();
 }
 
-const FileEntry *FastFile::getEntry(const Common::String &name) const {
+const FileEntry *FastFile::getEntry(const Common::Path &name) const {
 	for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it) {
 		if (it->name.equalsIgnoreCase(name))
 			return it;
@@ -46,7 +46,7 @@ const FileEntry *FastFile::getEntry(const Common::String &name) const {
 	return nullptr;
 }
 
-bool FastFile::open(TrecisionEngine *vm, const Common::String &name) {
+bool FastFile::open(TrecisionEngine *vm, const Common::Path &name) {
 	close();
 
 	Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
@@ -58,7 +58,7 @@ bool FastFile::open(TrecisionEngine *vm, const Common::String &name) {
 	_fileEntries.resize(numFiles);
 	for (int i = 0; i < numFiles; ++i) {
 		FileEntry *entry = &_fileEntries[i];
-		entry->name = _stream->readString(0, 12);
+		entry->name = Common::Path(_stream->readString(0, 12));
 		entry->offset = _stream->readUint32();
 	}
 
@@ -74,8 +74,7 @@ void FastFile::close() {
 }
 
 bool FastFile::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	const FileEntry *entry = getEntry(name);
+	const FileEntry *entry = getEntry(path);
 	return entry != nullptr;
 }
 
@@ -92,12 +91,11 @@ const Common::ArchiveMemberPtr FastFile::getMember(const Common::Path &path) con
 }
 
 Common::SeekableReadStream *FastFile::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	if (!_stream)
 		return nullptr;
 
 	Common::SeekableReadStream *stream = nullptr;
-	const FileEntry *entry = getEntry(name);
+	const FileEntry *entry = getEntry(path);
 	if (entry) {
 		uint32 size = (entry + 1)->offset - entry->offset;
 		if ((int32)(entry->offset + size) <= _stream->size()) {
@@ -108,14 +106,14 @@ Common::SeekableReadStream *FastFile::createReadStreamForMember(const Common::Pa
 	if (!stream) {
 		// Load data from external file
 		Common::File *file = new Common::File();
-		if (file->open(name)) {
+		if (file->open(path)) {
 			stream = file;
 		} else {
 			delete file;
 		}
 	}
 	if (!stream) {
-		warning("FastFile - %s not found", name.c_str());
+		warning("FastFile - %s not found", path.toString().c_str());
 	}
 	return stream;
 }
@@ -160,16 +158,16 @@ void FastFile::decompress(const uint8 *src, uint32 srcSize, uint8 *dst, uint32 d
 }
 
 #define FAST_COOKIE 0xFA57F00D
-Common::SeekableReadStream *FastFile::createReadStreamForCompressedMember(const Common::String &name) {
+Common::SeekableReadStream *FastFile::createReadStreamForCompressedMember(const Common::Path &name) {
 	Common::SeekableReadStream *ff = createReadStreamForMember(name);
 	if (ff == nullptr)
-		error("createReadStreamForCompressedMember - File not found %s", name.c_str());
+		error("createReadStreamForCompressedMember - File not found %s", name.toString().c_str());
 
 	const int32 dataSize = ff->size() - 8;
 
 	const uint32 signature = ff->readUint32LE();
 	if (signature != FAST_COOKIE)
-		error("createReadStreamForCompressedMember - %s has a bad signature and can't be loaded", name.c_str());
+		error("createReadStreamForCompressedMember - %s has a bad signature and can't be loaded", name.toString().c_str());
 
 	const int32 decompSize = ff->readSint32LE();
 
diff --git a/engines/trecision/fastfile.h b/engines/trecision/fastfile.h
index b1f72ef0ed9..cfea17bf256 100644
--- a/engines/trecision/fastfile.h
+++ b/engines/trecision/fastfile.h
@@ -31,7 +31,7 @@ namespace Trecision {
 class TrecisionEngine;
 
 struct FileEntry {
-	Common::String name;
+	Common::Path name;
 	uint32 offset;
 };
 
@@ -40,10 +40,10 @@ public:
 	FastFile();
 	~FastFile() override;
 
-	bool open(TrecisionEngine *vm, const Common::String &filename);
+	bool open(TrecisionEngine *vm, const Common::Path &filename);
 	void close();
 	bool isOpen() const { return _stream != 0; }
-	Common::SeekableReadStream *createReadStreamForCompressedMember(const Common::String &name);
+	Common::SeekableReadStream *createReadStreamForCompressedMember(const Common::Path &name);
 
 	// Common::Archive API implementation
 	bool hasFile(const Common::Path &path) const override;
@@ -57,7 +57,7 @@ private:
 	Common::Array<FileEntry> _fileEntries;
 
 	uint8 *_compBuffer;
-	const FileEntry *getEntry(const Common::String &name) const;
+	const FileEntry *getEntry(const Common::Path &name) const;
 	void decompress(const uint8 *src, uint32 srcSize, uint8 *dst, uint32 decompSize);
 };
 
diff --git a/engines/trecision/graphics.cpp b/engines/trecision/graphics.cpp
index cfc7f5ed0ca..c96e0720df2 100644
--- a/engines/trecision/graphics.cpp
+++ b/engines/trecision/graphics.cpp
@@ -748,10 +748,10 @@ void GraphicsManager::hideCursor() {
 }
 
 void GraphicsManager::loadFont() {
-	Common::String fileName = "nlfont.fnt";
+	const char *fileName = "nlfont.fnt";
 	Common::SeekableReadStream *fontStream = _vm->_dataFile.createReadStreamForMember(fileName);
 	if (fontStream == nullptr)
-		error("readData(): File %s not found", fileName.c_str());
+		error("readData(): File %s not found", fileName);
 
 	uint16 fontDataOffset = 768;
 
diff --git a/engines/trecision/resource.cpp b/engines/trecision/resource.cpp
index 489b7284770..d9f2bb3a071 100644
--- a/engines/trecision/resource.cpp
+++ b/engines/trecision/resource.cpp
@@ -110,10 +110,10 @@ void TrecisionEngine::loadAll() {
 	dataNl.close();
 }
 
-byte *TrecisionEngine::readData(const Common::String &fileName) {
+byte *TrecisionEngine::readData(const Common::Path &fileName) {
 	Common::SeekableReadStream *stream = _dataFile.createReadStreamForMember(fileName);
 	if (stream == nullptr)
-		error("readData(): File %s not found", fileName.c_str());
+		error("readData(): File %s not found", fileName.toString().c_str());
 
 	byte *buf = new byte[stream->size()];
 	stream->read(buf, stream->size());
@@ -122,10 +122,10 @@ byte *TrecisionEngine::readData(const Common::String &fileName) {
 	return buf;
 }
 
-void TrecisionEngine::read3D(const Common::String &filename) {
+void TrecisionEngine::read3D(const Common::Path &filename) {
 	Common::SeekableReadStreamEndian *ff = readEndian(_dataFile.createReadStreamForMember(filename));
 	if (ff == nullptr)
-		error("read3D: Can't open 3D file %s", filename.c_str());
+		error("read3D: Can't open 3D file %s", filename.toString().c_str());
 
 	_actor->read3D(ff);
 	_pathFind->read3D(ff);
diff --git a/engines/trecision/sound.cpp b/engines/trecision/sound.cpp
index cb23c22a8ee..0c69e14d2af 100644
--- a/engines/trecision/sound.cpp
+++ b/engines/trecision/sound.cpp
@@ -63,7 +63,7 @@ void SoundManager::play(int soundId) {
 
 		if (curRoom->_sounds[soundSlot] == soundId) {
 			const SoundType soundType = (_gSample[soundId]._flag & kSoundFlagBgMusic) ? kSoundTypeMusic : kSoundTypeSfx;
-			Common::SeekableReadStream *soundFileStream = _vm->_dataFile.createReadStreamForMember(_gSample[soundId]._name);
+			Common::SeekableReadStream *soundFileStream = _vm->_dataFile.createReadStreamForMember(Common::Path(_gSample[soundId]._name));
 			if (!soundFileStream)
 				continue;
 
@@ -191,7 +191,7 @@ void SoundManager::soundStep(int midx, int midz, int act, int frame) {
 
 		if (stepRight && (_gSample[soundId]._flag & kSoundFlagStepRight)) {
 			if (!_stepRightStream) {
-				Common::SeekableReadStream *soundFileStream = _vm->_dataFile.createReadStreamForMember(_gSample[soundId]._name);
+				Common::SeekableReadStream *soundFileStream = _vm->_dataFile.createReadStreamForMember(Common::Path(_gSample[soundId]._name));
 				_stepRightStream = loadWAV(soundFileStream);
 			}
 			break;
@@ -199,7 +199,7 @@ void SoundManager::soundStep(int midx, int midz, int act, int frame) {
 
 		if (stepLeft && (_gSample[soundId]._flag & kSoundFlagStepLeft)) {
 			if (!_stepLeftStream) {
-				Common::SeekableReadStream *soundFileStream = _vm->_dataFile.createReadStreamForMember(_gSample[soundId]._name);
+				Common::SeekableReadStream *soundFileStream = _vm->_dataFile.createReadStreamForMember(Common::Path(_gSample[soundId]._name));
 				_stepLeftStream = loadWAV(soundFileStream);
 			}
 			break;
@@ -232,7 +232,7 @@ void SoundManager::soundStep(int midx, int midz, int act, int frame) {
 	);
 }
 
-int32 SoundManager::talkStart(const Common::String &name) {
+int32 SoundManager::talkStart(const Common::Path &name) {
 	if (!_speechFile.isOpen())
 		return 0;
 
diff --git a/engines/trecision/sound.h b/engines/trecision/sound.h
index 913fe5b46dc..7d7479383c9 100644
--- a/engines/trecision/sound.h
+++ b/engines/trecision/sound.h
@@ -77,7 +77,7 @@ public:
 	void stopAll();
 	void stopAllExceptMusic();
 	void soundStep(int midx, int midz, int act, int frame);
-	int32 talkStart(const Common::String &name);
+	int32 talkStart(const Common::Path &name);
 	void loadRoomSounds();
 
 	void loadSamples(Common::SeekableReadStreamEndian *stream);
diff --git a/engines/trecision/text.cpp b/engines/trecision/text.cpp
index 5372b88ee08..6377501e5ce 100644
--- a/engines/trecision/text.cpp
+++ b/engines/trecision/text.cpp
@@ -146,9 +146,9 @@ void TextManager::characterContinueTalk() {
 
 	if (!_vm->_flagDialogActive) {
 		if (_curSubString)
-			_lastFilename = Common::String::format("s%04d%c.wav", _curSentenceId, _curSubString + 'a');
+			_lastFilename = Common::Path(Common::String::format("s%04d%c.wav", _curSentenceId, _curSubString + 'a'));
 		else
-			_lastFilename = Common::String::format("s%04d.wav", _curSentenceId);
+			_lastFilename = Common::Path(Common::String::format("s%04d.wav", _curSentenceId));
 	}
 
 	_talkTime = _vm->_soundMgr->talkStart(_lastFilename);
@@ -194,9 +194,9 @@ void TextManager::someoneContinueTalk() {
 		addText(pos, _subString[_curSubString], HYELLOW);
 
 	if (_curSubString)
-		_lastFilename = Common::String::format("s%04d%c.wav", _curSentenceId, _curSubString + 'a');
+		_lastFilename = Common::Path(Common::String::format("s%04d%c.wav", _curSentenceId, _curSubString + 'a'));
 	else
-		_lastFilename = Common::String::format("s%04d.wav", _curSentenceId);
+		_lastFilename = Common::Path(Common::String::format("s%04d.wav", _curSentenceId));
 
 	_talkTime = _vm->_soundMgr->talkStart(_lastFilename);
 	if (!_talkTime)
diff --git a/engines/trecision/text.h b/engines/trecision/text.h
index f0d48dc5f9e..8b2e1824131 100644
--- a/engines/trecision/text.h
+++ b/engines/trecision/text.h
@@ -52,7 +52,7 @@ class TextManager {
 	uint16 _subStringStart;
 	uint16 _curSentenceId;
 	uint16 _curSubString;
-	Common::String _lastFilename;
+	Common::Path _lastFilename;
 	uint16 _talkingPersonId;
 	SDText _curString;
 	SDText _oldString;
diff --git a/engines/trecision/trecision.cpp b/engines/trecision/trecision.cpp
index f2fe5c3761a..9927742a5fb 100644
--- a/engines/trecision/trecision.cpp
+++ b/engines/trecision/trecision.cpp
@@ -53,7 +53,7 @@ namespace Trecision {
 TrecisionEngine::TrecisionEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst), _gameDescription(desc) {
 	_gameId = !strcmp(_gameDescription->gameId, "nl") ? GID_NightLong : GID_ArkOfTime;
 
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "AUTORUN");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "DATA");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "FMV");
@@ -382,13 +382,13 @@ void TrecisionEngine::reEvent() {
 }
 
 Common::SeekableReadStreamEndian *TrecisionEngine::getLocStream() {
-	Common::String filename;
+	Common::Path filename(_room[_curRoom]._baseName);
 
 	if (isAmiga()) {
-		filename = Common::String::format("%s.bm", _room[_curRoom]._baseName);
+		filename.appendInPlace(".bm");
 		return readEndian(_dataFile.createReadStreamForMember(filename));
 	} else {
-		filename = Common::String::format("%s.cr", _room[_curRoom]._baseName);
+		filename.appendInPlace(".cr");
 		return readEndian(_dataFile.createReadStreamForCompressedMember(filename));
 	}
 }
@@ -409,7 +409,7 @@ void TrecisionEngine::readLoc() {
 	if (_room[_curRoom]._sounds[0] != 0)
 		_soundMgr->loadRoomSounds();
 
-	Common::String fname = Common::String::format("%s.3d", _room[_curRoom]._baseName);
+	Common::Path fname(Common::String::format("%s.3d", _room[_curRoom]._baseName));
 	read3D(fname);
 
 	if (_room[_curRoom]._bkgAnim) {
diff --git a/engines/trecision/trecision.h b/engines/trecision/trecision.h
index 0b5eaf78a9e..e823bc24984 100644
--- a/engines/trecision/trecision.h
+++ b/engines/trecision/trecision.h
@@ -177,7 +177,7 @@ public:
 
 	// Data files
 	Common::SeekableReadStreamEndian *readEndian(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::YES);
-	void read3D(const Common::String &c);
+	void read3D(const Common::Path &c);
 
 	// Inventory
 	void setInventoryStart(uint8 startIcon, uint8 startLine);
@@ -238,7 +238,7 @@ public:
 	void readPositionerSnapshots();
 
 	// Data files
-	byte *readData(const Common::String &fileName);
+	byte *readData(const Common::Path &fileName);
 
 	const ADGameDescription *_gameDescription;
 
diff --git a/engines/trecision/video.cpp b/engines/trecision/video.cpp
index 2e3b74c4855..ecef2de33de 100644
--- a/engines/trecision/video.cpp
+++ b/engines/trecision/video.cpp
@@ -123,17 +123,9 @@ bool NightlongSmackerDecoder::endOfFrames() const {
 
 // ----------------------------------------------------------------------------
 
-NightlongAmigaDecoder::AmigaVideoTrack::AmigaVideoTrack(const Common::String &fileName) {
+NightlongAmigaDecoder::AmigaVideoTrack::AmigaVideoTrack(Common::SeekableReadStream *stream) {
 	memset(_palette, 0, sizeof(_palette));
 
-	Common::File *stream = new Common::File();
-	stream->open(fileName);
-
-	if (!stream->isOpen()) {
-		delete stream;
-		return;
-	}
-
 	_curFrame = 0;
 	_frameCount = 10; // TODO: Anything > 1 to keep playing till the audio is done
 
@@ -175,10 +167,8 @@ const Graphics::Surface *NightlongAmigaDecoder::AmigaVideoTrack::decodeNextFrame
 	return nullptr;
 }
 
-NightlongAmigaDecoder::AmigaAudioTrack::AmigaAudioTrack(const Common::String &fileName) :
+NightlongAmigaDecoder::AmigaAudioTrack::AmigaAudioTrack(Common::SeekableReadStream *stream) :
 	AudioTrack(Audio::Mixer::SoundType::kSFXSoundType) {
-	Common::File *stream = new Common::File();
-	stream->open(fileName);
 	_audioStream = Audio::makeRawStream(stream, 11025, 0, DisposeAfterUse::YES);
 }
 
@@ -192,14 +182,17 @@ void NightlongAmigaDecoder::readNextPacket() {
 }
 
 bool NightlongAmigaDecoder::loadStream(Common::SeekableReadStream *stream) {
-	Common::File *file = dynamic_cast<Common::File *>(stream);
-	if (!file)
-		return false;
-	Common::String fileName = file->getName();
-	addTrack(new AmigaVideoTrack(fileName));
-	if (Common::File::exists("a" + fileName))
-		addTrack(new AmigaAudioTrack("a" + fileName));
+	addTrack(new AmigaVideoTrack(stream));
+	return true;
+}
 
+bool NightlongAmigaDecoder::addAudioSideTrack(const Common::Path &path) {
+	Common::File *file = new Common::File();
+	if (!file->open(path)) {
+		delete file;
+		return false;
+	}
+	addTrack(new AmigaAudioTrack(file));
 	return true;
 }
 
diff --git a/engines/trecision/video.h b/engines/trecision/video.h
index d612607df9a..344169e20d9 100644
--- a/engines/trecision/video.h
+++ b/engines/trecision/video.h
@@ -50,6 +50,7 @@ public:
 class NightlongAmigaDecoder : public NightlongVideoDecoder {
 public:
 	bool loadStream(Common::SeekableReadStream *stream) override;
+	bool addAudioSideTrack(const Common::Path &path);
 	bool forceSeekToFrame(uint frame) override;
 	bool endOfFrames() const override;
 	const Common::Rect *getNextDirtyRect() override;
@@ -61,7 +62,7 @@ private:
 
 	class AmigaVideoTrack : public VideoTrack {
 	public:
-		AmigaVideoTrack(const Common::String &fileName);
+		AmigaVideoTrack(Common::SeekableReadStream *stream);
 
 	private:
 		byte _palette[3 * 256];
@@ -81,7 +82,7 @@ private:
 
 	class AmigaAudioTrack : public AudioTrack {
 	public:
-		AmigaAudioTrack(const Common::String &fileName);
+		AmigaAudioTrack(Common::SeekableReadStream *stream);
 	private:
 		Audio::AudioStream *getAudioStream() const override { return _audioStream; }
 		Audio::AudioStream *_audioStream;


Commit: c803257af948e9596da7a6d148c40bc667dccc75
    https://github.com/scummvm/scummvm/commit/c803257af948e9596da7a6d148c40bc667dccc75
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TSAGE: Migrate engine to Path

Changed paths:
    engines/tsage/metaengine.cpp
    engines/tsage/resources.cpp
    engines/tsage/resources.h
    engines/tsage/sound.cpp
    engines/tsage/sound.h
    engines/tsage/tsage.h


diff --git a/engines/tsage/metaengine.cpp b/engines/tsage/metaengine.cpp
index e9f5f09b249..c8db8f41d45 100644
--- a/engines/tsage/metaengine.cpp
+++ b/engines/tsage/metaengine.cpp
@@ -48,8 +48,8 @@ Common::Language TSageEngine::getLanguage() const {
 	return _gameDescription->desc.language;
 }
 
-Common::String TSageEngine::getPrimaryFilename() const {
-	return Common::String(_gameDescription->desc.filesDescriptions[0].fileName);
+Common::Path TSageEngine::getPrimaryFilename() const {
+	return Common::Path(_gameDescription->desc.filesDescriptions[0].fileName);
 }
 
 } // End of namespace TsAGE
diff --git a/engines/tsage/resources.cpp b/engines/tsage/resources.cpp
index 78de42de9ae..20bf03aa800 100644
--- a/engines/tsage/resources.cpp
+++ b/engines/tsage/resources.cpp
@@ -133,7 +133,7 @@ uint16 BitReader::readToken() {
 
 /*-------------------------------------------------------------------------*/
 
-TLib::TLib(MemoryManager &memManager, const Common::String &filename) :
+TLib::TLib(MemoryManager &memManager, const Common::Path &filename) :
 		_filename(filename), _memoryManager(memManager) {
 
 	// If the resource strings list isn't yet loaded, load them
@@ -156,7 +156,7 @@ TLib::TLib(MemoryManager &memManager, const Common::String &filename) :
 
 		Common::File f;
 		if (!f.open(filename))
-			error("Missing file %s", filename.c_str());
+			error("Missing file %s", filename.toString().c_str());
 
 		size = f.size() - 18; // First file header
 		data = (byte *)malloc(size);
@@ -167,10 +167,10 @@ TLib::TLib(MemoryManager &memManager, const Common::String &filename) :
 
 		if (filename.equals("BLUE.RLB")) {
 			for (int i = 2; i < 9; i++) {
-				Common::String partname = Common::String::format("BLUE.#0%d", i);
+				Common::Path partname(Common::String::format("BLUE.#0%d", i));
 
 				if (!f.open(partname))
-					error("Missing file %s", partname.c_str());
+					error("Missing file %s", partname.toString().c_str());
 
 				uint32 partsize = f.size() - 4;	// Further headers
 				byte *newdata = (byte *)realloc(data, size + partsize);
@@ -188,7 +188,7 @@ TLib::TLib(MemoryManager &memManager, const Common::String &filename) :
 			}
 		}
 
-		warning("File %s: resulting size is %d bytes", filename.c_str(), size);
+		warning("File %s: resulting size is %d bytes", filename.toString().c_str(), size);
 
 		Common::MemoryReadStream *stream = new Common::MemoryReadStream(data, size, DisposeAfterUse::YES);
 
@@ -198,7 +198,7 @@ TLib::TLib(MemoryManager &memManager, const Common::String &filename) :
 		Common::File *f = new Common::File;
 
 		if (!f->open(filename))
-			error("Missing file %s", filename.c_str());
+			error("Missing file %s", filename.toString().c_str());
 
 		_file = f;
 	}
@@ -516,7 +516,7 @@ ResourceManager::~ResourceManager() {
 		delete _libList[idx];
 }
 
-void ResourceManager::addLib(const Common::String &libName) {
+void ResourceManager::addLib(const Common::Path &libName) {
 	assert(_libList.size() < 5);
 
 	_libList.push_back(new TLib(g_vm->_memoryManager, libName));
diff --git a/engines/tsage/resources.h b/engines/tsage/resources.h
index fa1dc376e82..acb108b9413 100644
--- a/engines/tsage/resources.h
+++ b/engines/tsage/resources.h
@@ -144,17 +144,17 @@ private:
 	MemoryManager &_memoryManager;
 private:
 	Common::SeekableReadStream *_file;
-	Common::String _filename;
+	Common::Path _filename;
 	ResourceList _resources;
 	SectionList _sections;
 
 	void loadSection(uint32 fileOffset);
 	void loadIndex();
 public:
-	TLib(MemoryManager &memManager, const Common::String &filename);
+	TLib(MemoryManager &memManager, const Common::Path &filename);
 	~TLib();
 
-	const Common::String &getFilename() { return _filename; }
+	const Common::Path &getFilename() { return _filename; }
 	const SectionList &getSections() { return _sections; }
 	byte *getResource(uint16 id, bool suppressErrors = false);
 	byte *getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors = false);
@@ -170,7 +170,7 @@ private:
 public:
 	~ResourceManager();
 
-	void addLib(const Common::String &libName);
+	void addLib(const Common::Path &libName);
 
 	byte *getResource(uint16 id, bool suppressErrors = false);
 	byte *getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors = false);
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index e5cac06f589..7b640486a80 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -2553,7 +2553,7 @@ PlayStream::~PlayStream() {
 	remove();
 }
 
-bool PlayStream::setFile(const Common::String &filename) {
+bool PlayStream::setFile(const Common::Path &filename) {
 	remove();
 
 	// Open the resource file for access
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index 55b6e8d53cb..6e40073b637 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -438,7 +438,7 @@ public:
 	PlayStream();
 	~PlayStream() override;
 
-	bool setFile(const Common::String &filename);
+	bool setFile(const Common::Path &filename);
 	bool play(int voiceNum, EventHandler *endAction);
 	void stop();
 	bool isPlaying() const;
diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h
index 972329eb897..c02cfaf3211 100644
--- a/engines/tsage/tsage.h
+++ b/engines/tsage/tsage.h
@@ -57,7 +57,7 @@ public:
 	uint32 getGameID() const;
 	uint32 getFeatures() const;
 	Common::Language getLanguage() const;
-	Common::String getPrimaryFilename() const;
+	Common::Path getPrimaryFilename() const;
 
 	virtual Common::Error init();
 	Common::Error run() override;


Commit: a57eaeb342d7f7bb00fcf4e1db2943865d6388b1
    https://github.com/scummvm/scummvm/commit/a57eaeb342d7f7bb00fcf4e1db2943865d6388b1
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TUCKER: Migrate engine to Path

Changed paths:
    engines/tucker/resource.cpp
    engines/tucker/sequences.cpp


diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index 08145e3750c..77b0489559c 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -196,7 +196,7 @@ uint8 *TuckerEngine::loadFile(const char *fname, uint8 *p) {
 		}
 	}
 	Common::File f;
-	if (!f.open(filename)) {
+	if (!f.open(Common::Path(filename))) {
 		warning("Unable to open '%s'", filename.c_str());
 		return nullptr;
 	}
@@ -975,7 +975,7 @@ void TuckerEngine::loadSound(Audio::Mixer::SoundType type, int num, int volume,
 		}
 		Common::String fileName = Common::String::format(fmt, num);
 		Common::File *f = new Common::File;
-		if (f->open(fileName)) {
+		if (f->open(Common::Path(fileName))) {
 			stream = Audio::makeWAVStream(f, DisposeAfterUse::YES);
 		} else {
 			delete f;
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index e5cd6d22fce..d99c36f4973 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -601,7 +601,7 @@ Audio::RewindableAudioStream *AnimationSequencePlayer::loadSound(int index, Anim
 	if (stream)
 		return stream;
 
-	Common::String fileName = Common::String::format("audio/%s", _audioFileNamesTable[index]);
+	Common::Path fileName(Common::String::format("audio/%s", _audioFileNamesTable[index]));
 	Common::File *f = new Common::File();
 	if (f->open(fileName)) {
 		int size = 0, rate = 0;


Commit: 6d86d20e1cd4a2a149a79ebe80322cc61ae90055
    https://github.com/scummvm/scummvm/commit/6d86d20e1cd4a2a149a79ebe80322cc61ae90055
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
TWINE: Migrate engine to Path

Changed paths:
    engines/twine/audio/music.cpp
    engines/twine/audio/sound.cpp
    engines/twine/movies.cpp
    engines/twine/renderer/screens.cpp
    engines/twine/slideshow.cpp
    engines/twine/twine.cpp


diff --git a/engines/twine/audio/music.cpp b/engines/twine/audio/music.cpp
index 02857fccfde..c8cf1fd4f9b 100644
--- a/engines/twine/audio/music.cpp
+++ b/engines/twine/audio/music.cpp
@@ -236,7 +236,7 @@ bool Music::playMidiMusic(int32 midiIdx, int32 loop) {
 	stopMidiMusic();
 
 	if (_engine->isDotEmuEnhanced() || _engine->isLba1Classic()) {
-		const Common::String &trackName = Common::String::format("lba1-%02i", midiIdx + 1);
+		Common::Path trackName(Common::String::format("lba1-%02i", midiIdx + 1));
 		Audio::SeekableAudioStream *stream = Audio::SeekableAudioStream::openStreamFile(trackName);
 		if (stream != nullptr) {
 			const int volume = _engine->_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
diff --git a/engines/twine/audio/sound.cpp b/engines/twine/audio/sound.cpp
index 6a43f8e1f88..fc5e7b2faaa 100644
--- a/engines/twine/audio/sound.cpp
+++ b/engines/twine/audio/sound.cpp
@@ -130,7 +130,7 @@ bool Sound::playVoxSample(const TextEntry *text) {
 	}
 
 	if (_engine->isAndroid()) {
-		const Common::String &basename = Common::String::format("%s%03i", _engine->_text->_currentOggBaseFile.c_str(), text->index);
+		Common::Path basename(Common::String::format("%s%03i", _engine->_text->_currentOggBaseFile.c_str(), text->index));
 		Audio::SeekableAudioStream *audioStream = Audio::SeekableAudioStream::openStreamFile(basename);
 		if (audioStream != nullptr) {
 			return playSample(channelIdx, text->index, audioStream, 1, _engine->_text->_currentOggBaseFile.c_str(), Audio::Mixer::kSpeechSoundType);
diff --git a/engines/twine/movies.cpp b/engines/twine/movies.cpp
index a807b5e62bf..943b5d35aab 100644
--- a/engines/twine/movies.cpp
+++ b/engines/twine/movies.cpp
@@ -378,7 +378,7 @@ bool Movies::playMovie(const char *name) {
 	_fadeOutFrames = 0;
 
 	_file.close();
-	if (!_file.open(fileNamePath + FLA_EXT)) {
+	if (!_file.open(Common::Path(fileNamePath + FLA_EXT))) {
 		warning("Failed to open fla movie '%s'", fileNamePath.c_str());
 		playGIFMovie(fileNamePath.c_str());
 		return true;
diff --git a/engines/twine/renderer/screens.cpp b/engines/twine/renderer/screens.cpp
index c0a9e44a7b9..48a89e01ae8 100644
--- a/engines/twine/renderer/screens.cpp
+++ b/engines/twine/renderer/screens.cpp
@@ -118,20 +118,20 @@ bool Screens::loadImageDelay(TwineImage image, int32 seconds) {
 }
 
 template<class ImageDecoder>
-static bool loadImageDelayViaDecoder(TwinEEngine *engine, const Common::String &fileName, int32 seconds) {
+static bool loadImageDelayViaDecoder(TwinEEngine *engine, const Common::Path &fileName, int32 seconds) {
 	ImageDecoder decoder;
 	Common::File fileHandle;
 	if (!fileHandle.open(fileName)) {
-		warning("Failed to open %s", fileName.c_str());
+		warning("Failed to open %s", fileName.toString().c_str());
 		return false;
 	}
 	if (!decoder.loadStream(fileHandle)) {
-		warning("Failed to load %s", fileName.c_str());
+		warning("Failed to load %s", fileName.toString().c_str());
 		return false;
 	}
 	const Graphics::Surface *src = decoder.getSurface();
 	if (src == nullptr) {
-		warning("Failed to decode %s", fileName.c_str());
+		warning("Failed to decode %s", fileName.toString().c_str());
 		return false;
 	}
 	Graphics::ManagedSurface &target = engine->_frontVideoBuffer;
@@ -154,7 +154,8 @@ static bool loadImageDelayViaDecoder(TwinEEngine *engine, const Common::String &
 }
 
 bool Screens::loadBitmapDelay(const char *image, int32 seconds) {
-	Common::String filename(image);
+	Common::Path path(image);
+	Common::String filename = path.baseName();
 	size_t extPos = filename.rfind(".");
 	if (extPos == Common::String::npos) {
 		warning("Failed to extract extension %s", image);
@@ -163,7 +164,7 @@ bool Screens::loadBitmapDelay(const char *image, int32 seconds) {
 
 	struct ImageLoader {
 		const char *extension;
-		bool (*loadImageDelay)(TwinEEngine *engine, const Common::String &fileName, int32 seconds);
+		bool (*loadImageDelay)(TwinEEngine *engine, const Common::Path &fileName, int32 seconds);
 	};
 
 	static const ImageLoader s_imageLoaders[] = {
@@ -174,7 +175,7 @@ bool Screens::loadBitmapDelay(const char *image, int32 seconds) {
 	const Common::String &ext = filename.substr(extPos + 1);
 	for (const ImageLoader *loader = s_imageLoaders; loader->extension; ++loader) {
 		if (!scumm_stricmp(loader->extension, ext.c_str())) {
-			return loader->loadImageDelay(_engine, filename, seconds);
+			return loader->loadImageDelay(_engine, path, seconds);
 		}
 	}
 	warning("Failed to find suitable image handler %s", image);
diff --git a/engines/twine/slideshow.cpp b/engines/twine/slideshow.cpp
index c39447ab5f4..56e4eaeabfa 100644
--- a/engines/twine/slideshow.cpp
+++ b/engines/twine/slideshow.cpp
@@ -52,7 +52,7 @@ private:
 		_engine->setPalette(_pal);
 	}
 
-	bool loadPCX(const Common::String &pcx, bool onlyPalette = false) {
+	bool loadPCX(const Common::Path &pcx, bool onlyPalette = false) {
 		Image::PCXDecoder decoder;
 		Common::File file;
 		if (!file.open(pcx)) {
@@ -153,7 +153,7 @@ private:
 	}
 
 	void scriptPCX(const Common::String &params) {
-		loadPCX(params + ".PCX");
+		loadPCX(Common::Path(params + ".PCX"));
 	}
 
 	void scriptShow() {
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index a565a87b01c..7ac93a504b2 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -129,7 +129,7 @@ void TwineScreen::update() {
 TwinEEngine::TwinEEngine(OSystem *system, Common::Language language, uint32 flags, Common::Platform platform, TwineGameType gameType)
 	: Engine(system), _gameType(gameType), _gameLang(language), _frontVideoBuffer(this), _gameFlags(flags), _platform(platform), _rnd("twine") {
 	// Add default file directories
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	SearchMan.addSubDirectoryMatching(gameDataDir, "fla");
 	SearchMan.addSubDirectoryMatching(gameDataDir, "vox");
 	if (isLBA2()) {


Commit: ca246ba56a4b24fd738206738ff3238b5de0c9f7
    https://github.com/scummvm/scummvm/commit/ca246ba56a4b24fd738206738ff3238b5de0c9f7
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ULTIMA: Migrate engine to Path

Changed paths:
    engines/ultima/nuvie/actors/actor_manager.cpp
    engines/ultima/nuvie/actors/actor_manager.h
    engines/ultima/nuvie/conf/configuration.cpp
    engines/ultima/nuvie/conf/configuration.h
    engines/ultima/nuvie/core/book.cpp
    engines/ultima/nuvie/core/converse.cpp
    engines/ultima/nuvie/core/converse_speech.cpp
    engines/ultima/nuvie/core/converse_speech.h
    engines/ultima/nuvie/core/cursor.cpp
    engines/ultima/nuvie/core/cursor.h
    engines/ultima/nuvie/core/game.cpp
    engines/ultima/nuvie/core/game.h
    engines/ultima/nuvie/core/look.cpp
    engines/ultima/nuvie/core/map.cpp
    engines/ultima/nuvie/core/map.h
    engines/ultima/nuvie/core/obj_manager.cpp
    engines/ultima/nuvie/core/tile_manager.cpp
    engines/ultima/nuvie/core/tile_manager.h
    engines/ultima/nuvie/files/nuvie_bmp_file.cpp
    engines/ultima/nuvie/files/nuvie_bmp_file.h
    engines/ultima/nuvie/files/nuvie_file_list.cpp
    engines/ultima/nuvie/files/nuvie_file_list.h
    engines/ultima/nuvie/files/nuvie_io_file.cpp
    engines/ultima/nuvie/files/nuvie_io_file.h
    engines/ultima/nuvie/files/tmx_map.cpp
    engines/ultima/nuvie/files/tmx_map.h
    engines/ultima/nuvie/files/u6_bmp.cpp
    engines/ultima/nuvie/files/u6_bmp.h
    engines/ultima/nuvie/files/u6_lib_n.cpp
    engines/ultima/nuvie/files/u6_lib_n.h
    engines/ultima/nuvie/files/u6_lzw.cpp
    engines/ultima/nuvie/files/u6_lzw.h
    engines/ultima/nuvie/files/u6_shape.cpp
    engines/ultima/nuvie/files/u6_shape.h
    engines/ultima/nuvie/files/utils.cpp
    engines/ultima/nuvie/files/utils.h
    engines/ultima/nuvie/fonts/bmp_font.cpp
    engines/ultima/nuvie/fonts/bmp_font.h
    engines/ultima/nuvie/fonts/font_manager.cpp
    engines/ultima/nuvie/fonts/wou_font.cpp
    engines/ultima/nuvie/fonts/wou_font.h
    engines/ultima/nuvie/gui/gui.cpp
    engines/ultima/nuvie/gui/gui.h
    engines/ultima/nuvie/gui/gui_dialog.cpp
    engines/ultima/nuvie/gui/gui_scroll_bar.cpp
    engines/ultima/nuvie/gui/widgets/background.cpp
    engines/ultima/nuvie/gui/widgets/command_bar.cpp
    engines/ultima/nuvie/gui/widgets/converse_gump_wou.cpp
    engines/ultima/nuvie/gui/widgets/map_window.cpp
    engines/ultima/nuvie/menus/asset_viewer_dialog.h
    engines/ultima/nuvie/misc/sdl_compat.cpp
    engines/ultima/nuvie/misc/sdl_compat.h
    engines/ultima/nuvie/misc/u6_misc.cpp
    engines/ultima/nuvie/misc/u6_misc.h
    engines/ultima/nuvie/nuvie.cpp
    engines/ultima/nuvie/nuvie.h
    engines/ultima/nuvie/portraits/portrait_md.cpp
    engines/ultima/nuvie/portraits/portrait_se.cpp
    engines/ultima/nuvie/portraits/portrait_u6.cpp
    engines/ultima/nuvie/save/save_game.cpp
    engines/ultima/nuvie/screen/dither.cpp
    engines/ultima/nuvie/screen/game_palette.cpp
    engines/ultima/nuvie/script/script.cpp
    engines/ultima/nuvie/script/script_cutscene.cpp
    engines/ultima/nuvie/script/script_cutscene.h
    engines/ultima/nuvie/sound/adplug/adplug_player.h
    engines/ultima/nuvie/sound/adplug/mid.cpp
    engines/ultima/nuvie/sound/adplug/mid.h
    engines/ultima/nuvie/sound/adplug/u6m.cpp
    engines/ultima/nuvie/sound/adplug/u6m.h
    engines/ultima/nuvie/sound/custom_sfx_manager.cpp
    engines/ultima/nuvie/sound/custom_sfx_manager.h
    engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.cpp
    engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.h
    engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.cpp
    engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.h
    engines/ultima/nuvie/sound/origin_fx_adib_driver.cpp
    engines/ultima/nuvie/sound/song.h
    engines/ultima/nuvie/sound/song_adplug.cpp
    engines/ultima/nuvie/sound/song_adplug.h
    engines/ultima/nuvie/sound/song_filename.cpp
    engines/ultima/nuvie/sound/song_filename.h
    engines/ultima/nuvie/sound/sound.h
    engines/ultima/nuvie/sound/sound_manager.cpp
    engines/ultima/nuvie/sound/sound_manager.h
    engines/ultima/nuvie/sound/towns_sfx_manager.cpp
    engines/ultima/nuvie/sound/towns_sfx_manager.h
    engines/ultima/nuvie/views/container_view_gump.cpp
    engines/ultima/nuvie/views/container_view_gump.h
    engines/ultima/nuvie/views/doll_view_gump.cpp
    engines/ultima/nuvie/views/doll_widget.cpp
    engines/ultima/nuvie/views/map_editor_view.cpp
    engines/ultima/nuvie/views/md_sky_strip_widget.cpp
    engines/ultima/nuvie/views/portrait_view.cpp
    engines/ultima/nuvie/views/portrait_view_gump.cpp
    engines/ultima/nuvie/views/sign_view_gump.cpp
    engines/ultima/nuvie/views/spell_view.cpp
    engines/ultima/nuvie/views/spell_view_gump.cpp
    engines/ultima/nuvie/views/spell_view_gump.h
    engines/ultima/nuvie/views/sun_moon_ribbon.cpp
    engines/ultima/nuvie/views/view.cpp
    engines/ultima/nuvie/views/view.h
    engines/ultima/nuvie/views/view_manager.cpp
    engines/ultima/nuvie/views/view_manager.h
    engines/ultima/shared/conf/xml_node.cpp
    engines/ultima/shared/conf/xml_node.h
    engines/ultima/shared/conf/xml_tree.cpp
    engines/ultima/shared/conf/xml_tree.h
    engines/ultima/shared/core/file.cpp
    engines/ultima/shared/core/file.h
    engines/ultima/shared/early/ultima_early.cpp
    engines/ultima/shared/early/ultima_early.h
    engines/ultima/shared/engine/data_archive.cpp
    engines/ultima/shared/engine/data_archive.h
    engines/ultima/shared/engine/resources.cpp
    engines/ultima/shared/engine/resources.h
    engines/ultima/shared/engine/ultima.cpp
    engines/ultima/shared/engine/ultima.h
    engines/ultima/shared/gfx/bitmap.cpp
    engines/ultima/shared/gfx/bitmap.h
    engines/ultima/shared/gfx/sprites.cpp
    engines/ultima/shared/gfx/sprites.h
    engines/ultima/ultima4/controllers/intro_controller.cpp
    engines/ultima/ultima4/core/debugger.cpp
    engines/ultima/ultima4/filesys/u4file.cpp
    engines/ultima/ultima4/game/script.cpp
    engines/ultima/ultima4/gfx/imagemgr.cpp
    engines/ultima/ultima4/map/city.h
    engines/ultima/ultima4/map/map.h
    engines/ultima/ultima4/sound/music.cpp
    engines/ultima/ultima4/sound/sound.cpp
    engines/ultima/ultima4/sound/sound.h
    engines/ultima/ultima4/ultima4.cpp
    engines/ultima/ultima4/ultima4.h
    engines/ultima/ultima8/filesys/savegame.cpp
    engines/ultima/ultima8/filesys/savegame.h
    engines/ultima/ultima8/misc/debugger.cpp


diff --git a/engines/ultima/nuvie/actors/actor_manager.cpp b/engines/ultima/nuvie/actors/actor_manager.cpp
index 39bb9617970..e5e54a2ecf2 100644
--- a/engines/ultima/nuvie/actors/actor_manager.cpp
+++ b/engines/ultima/nuvie/actors/actor_manager.cpp
@@ -676,7 +676,7 @@ void ActorManager::moveActors() {
 }
 
 bool ActorManager::loadActorSchedules() {
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead schedule;
 	uint16 i;
 	uint16 total_schedules;
@@ -1091,8 +1091,8 @@ bool ActorManager::loadCustomTiles(nuvie_game_t game_type) {
 		return false;
 	}
 
-	Std::string datadir = "images";
-	Std::string path;
+	Common::Path datadir = "images";
+	Common::Path path;
 
 	build_path(datadir, "tiles", path);
 	datadir = path;
@@ -1108,16 +1108,16 @@ bool ActorManager::loadCustomTiles(nuvie_game_t game_type) {
 	return true;
 }
 
-void ActorManager::loadCustomBaseTiles(const Std::string &datadir) {
-	Std::string imagefile;
+void ActorManager::loadCustomBaseTiles(const Common::Path &datadir) {
+	Common::Path imagefile;
 	build_path(datadir, "custom_tiles.bmp", imagefile);
 
 	//attempt to load custom base tiles if the file exists.
 	tile_manager->loadCustomTiles(Game::get_game()->get_data_file_path(imagefile), true, true, 0);
 }
 
-void ActorManager::loadAvatarTiles(const Std::string &datadir) {
-	Std::string imagefile;
+void ActorManager::loadAvatarTiles(const Common::Path &datadir) {
+	Common::Path imagefile;
 
 	uint8 avatar_portrait = Game::get_game()->get_portrait()->get_avatar_portrait_num();
 
@@ -1134,7 +1134,7 @@ void ActorManager::loadAvatarTiles(const Std::string &datadir) {
 			num_str = filename.substr(11, 4);
 			uint16 obj_n = (uint16)strtol(num_str.c_str(), nullptr, 10);
 
-			Std::string path;
+			Common::Path path;
 			build_path(datadir, filename, path);
 			imagefile = Game::get_game()->get_data_file_path(path);
 			Tile *start_tile = tile_manager->loadCustomTiles(imagefile, false, true, actors[1]->get_tile_num());
@@ -1146,8 +1146,8 @@ void ActorManager::loadAvatarTiles(const Std::string &datadir) {
 	return;
 }
 
-void ActorManager::loadNPCTiles(const Std::string &datadir) {
-	Std::string imagefile;
+void ActorManager::loadNPCTiles(const Common::Path &datadir) {
+	Common::Path imagefile;
 
 	Std::set<Std::string> files = getCustomTileFilenames(datadir, "actor_");
 
@@ -1161,7 +1161,7 @@ void ActorManager::loadNPCTiles(const Std::string &datadir) {
 		num_str = filename.substr(10, 4);
 		uint16 obj_n = (uint16)strtol(num_str.c_str(), nullptr, 10);
 
-		Std::string path;
+		Common::Path path;
 		build_path(datadir, filename, path);
 		imagefile = Game::get_game()->get_data_file_path(path);
 		Tile *start_tile = tile_manager->loadCustomTiles(imagefile, false, true, actors[actor_num]->get_tile_num());
@@ -1172,17 +1172,17 @@ void ActorManager::loadNPCTiles(const Std::string &datadir) {
 	return;
 }
 
-Std::set<Std::string> ActorManager::getCustomTileFilenames(const Std::string &datadir, const Std::string &filenamePrefix) {
+Std::set<Std::string> ActorManager::getCustomTileFilenames(const Common::Path &datadir, const Std::string &filenamePrefix) {
 	NuvieFileList filelistDataDir;
 	NuvieFileList filelistSaveGameDir;
-	Std::string path;
+	Common::Path path;
 
-	build_path(GUI::get_gui()->get_data_dir(), datadir, path);
-	filelistDataDir.open(path.c_str(), filenamePrefix.c_str(), NUVIE_SORT_NAME_ASC);
+	path = GUI::get_gui()->get_data_dir().joinInPlace(datadir);
+	filelistDataDir.open(path, filenamePrefix.c_str(), NUVIE_SORT_NAME_ASC);
 
 	path = "data";
-	build_path(path, datadir, path);
-	filelistSaveGameDir.open(path.c_str(), filenamePrefix.c_str(), NUVIE_SORT_NAME_ASC);
+	path.joinInPlace(datadir);
+	filelistSaveGameDir.open(path, filenamePrefix.c_str(), NUVIE_SORT_NAME_ASC);
 
 	Std::set<Std::string> files = filelistSaveGameDir.get_filenames();
 	Std::set<Std::string> dataFiles = filelistDataDir.get_filenames();
diff --git a/engines/ultima/nuvie/actors/actor_manager.h b/engines/ultima/nuvie/actors/actor_manager.h
index 88c817b18d6..d5277f105b6 100644
--- a/engines/ultima/nuvie/actors/actor_manager.h
+++ b/engines/ultima/nuvie/actors/actor_manager.h
@@ -135,10 +135,10 @@ protected:
 private:
 
 	bool loadCustomTiles(nuvie_game_t game_type);
-	void loadNPCTiles(const Std::string &datadir);
-	void loadAvatarTiles(const Std::string &datadir);
-	void loadCustomBaseTiles(const Std::string &datadir);
-	Std::set<Std::string> getCustomTileFilenames(const Std::string &datadir, const Std::string &filenamePrefix);
+	void loadNPCTiles(const Common::Path &datadir);
+	void loadAvatarTiles(const Common::Path &datadir);
+	void loadCustomBaseTiles(const Common::Path &datadir);
+	Std::set<Std::string> getCustomTileFilenames(const Common::Path &datadir, const Std::string &filenamePrefix);
 };
 
 } // End of namespace Nuvie
diff --git a/engines/ultima/nuvie/conf/configuration.cpp b/engines/ultima/nuvie/conf/configuration.cpp
index b2aeb83e2de..369ff206a01 100644
--- a/engines/ultima/nuvie/conf/configuration.cpp
+++ b/engines/ultima/nuvie/conf/configuration.cpp
@@ -54,7 +54,7 @@ bool Configuration::readConfigFile(const Std::string &fname, const Std::string &
 	_configFilename = fname;
 	Shared::XMLTree *tree = new Shared::XMLTree();
 
-	if (!tree->readConfigFile(fname)) {
+	if (!tree->readConfigFile(Common::Path(fname))) {
 		delete tree;
 		return false;
 	}
@@ -164,13 +164,11 @@ void Configuration::value(const Std::string &key, bool &ret, bool defaultvalue)
 	ret = defaultvalue;
 }
 
-void Configuration::pathFromValue(const Std::string &key, const Std::string &file, Std::string &full_path) const {
-	value(key, full_path);
+void Configuration::pathFromValue(const Std::string &key, const Std::string &file, Common::Path &full_path) const {
+	Std::string tmp;
+	value(key, tmp);
 
-	if (full_path.length() > 0 && full_path[full_path.length() - 1] != U6PATH_DELIMITER)
-		full_path += U6PATH_DELIMITER + file;
-	else
-		full_path += file;
+	full_path = Common::Path(tmp).joinInPlace(file);
 }
 
 bool Configuration::set(const Std::string &key, const Std::string &value) {
diff --git a/engines/ultima/nuvie/conf/configuration.h b/engines/ultima/nuvie/conf/configuration.h
index 602a4db5e48..8ab38024c02 100644
--- a/engines/ultima/nuvie/conf/configuration.h
+++ b/engines/ultima/nuvie/conf/configuration.h
@@ -97,7 +97,7 @@ public:
 	void value(const Std::string &key, int &ret, int defaultvalue = 0) const;
 	void value(const Std::string &key, bool &ret, bool defaultvalue = false) const;
 
-	void pathFromValue(const Std::string &key, const Std::string &file, Std::string &full_path) const;
+	void pathFromValue(const Std::string &key, const Std::string &file, Common::Path &full_path) const;
 
 	// set value
 	bool set(const Std::string &key, const Std::string &value);
diff --git a/engines/ultima/nuvie/core/book.cpp b/engines/ultima/nuvie/core/book.cpp
index 1caa721caf3..91bcacd693b 100644
--- a/engines/ultima/nuvie/core/book.cpp
+++ b/engines/ultima/nuvie/core/book.cpp
@@ -37,7 +37,7 @@ Book::~Book() {
 }
 
 bool Book::init() {
-	Std::string filename;
+	Common::Path filename;
 
 	config_get_path(config, "book.dat", filename);
 
diff --git a/engines/ultima/nuvie/core/converse.cpp b/engines/ultima/nuvie/core/converse.cpp
index 815e6088262..18d0295fa60 100644
--- a/engines/ultima/nuvie/core/converse.cpp
+++ b/engines/ultima/nuvie/core/converse.cpp
@@ -124,7 +124,7 @@ void Converse::reset() {
 /* Load `convfilename' as src.
  */
 void Converse::load_conv(const Std::string &convfilename) {
-	string conv_lib_str;
+	Common::Path conv_lib_str;
 	if (gametype == NUVIE_GAME_U6 && using_fmtowns) {
 		config->pathFromValue("config/townsdir", convfilename, conv_lib_str);
 	} else {
diff --git a/engines/ultima/nuvie/core/converse_speech.cpp b/engines/ultima/nuvie/core/converse_speech.cpp
index 08ffe6fdf09..63a3831c39b 100644
--- a/engines/ultima/nuvie/core/converse_speech.cpp
+++ b/engines/ultima/nuvie/core/converse_speech.cpp
@@ -64,7 +64,7 @@ void ConverseSpeech::update() {
 }
 
 void ConverseSpeech::play_speech(uint16 actor_num, uint16 sample_num) {
-	Std::string sample_file;
+	Common::Path sample_file;
 	char filename[20]; // "/speech/charxxx.sam"
 	TownsSound sound;
 	SoundManager *sm = Game::get_game()->get_sound_manager();
@@ -86,7 +86,7 @@ void ConverseSpeech::play_speech(uint16 actor_num, uint16 sample_num) {
 
 	config->pathFromValue("config/townsdir", filename, sample_file);
 
-	DEBUG(0, LEVEL_DEBUGGING, "Loading Speech Sample %s:%d\n", sample_file.c_str(), sample_num);
+	DEBUG(0, LEVEL_DEBUGGING, "Loading Speech Sample %s:%d\n", sample_file.toString().c_str(), sample_num);
 
 	sound.filename = sample_file;
 	sound.sample_num = sample_num;
@@ -99,7 +99,7 @@ void ConverseSpeech::play_speech(uint16 actor_num, uint16 sample_num) {
 	return;
 }
 
-NuvieIOBuffer *ConverseSpeech::load_speech(Std::string filename, uint16 sample_num) {
+NuvieIOBuffer *ConverseSpeech::load_speech(const Common::Path &filename, uint16 sample_num) {
 	unsigned char *compressed_data, *raw_audio, *wav_data;
 	sint16 *converted_audio;
 	uint32 decomp_size;
diff --git a/engines/ultima/nuvie/core/converse_speech.h b/engines/ultima/nuvie/core/converse_speech.h
index f7ec26f3f30..d0277486a35 100644
--- a/engines/ultima/nuvie/core/converse_speech.h
+++ b/engines/ultima/nuvie/core/converse_speech.h
@@ -23,7 +23,6 @@
 #define NUVIE_CORE_CONVERSE_SPEECH_H
 
 #include "ultima/shared/std/containers.h"
-#include "ultima/shared/std/string.h"
 #include "audio/mixer.h"
 
 namespace Ultima {
@@ -34,10 +33,8 @@ class U6Lib_n;
 class U6Lzw;
 class NuvieIOBuffer;
 
-using Std::string;
-
 typedef struct TownsSound {
-	Std::string filename;
+	Common::Path filename;
 	uint16 sample_num;
 } TownsSound;
 
@@ -55,7 +52,7 @@ public:
 	void play_speech(uint16 actor_num, uint16 sample_num);
 
 protected:
-	NuvieIOBuffer *load_speech(Std::string filename, uint16 sample_num);
+	NuvieIOBuffer *load_speech(const Common::Path &filename, uint16 sample_num);
 	inline sint16 convert_sample(uint16 raw_sample);
 	void wav_init_header(NuvieIOBuffer *wav_buffer, uint32 audio_length) const;
 };
diff --git a/engines/ultima/nuvie/core/cursor.cpp b/engines/ultima/nuvie/core/cursor.cpp
index 0764bc93721..3cfbf5b5ceb 100644
--- a/engines/ultima/nuvie/core/cursor.cpp
+++ b/engines/ultima/nuvie/core/cursor.cpp
@@ -45,7 +45,8 @@ Cursor::Cursor() : cursor_id(0), cur_x(-1), cur_y(-1), cleanup(nullptr),
 /* Returns true if mouse pointers file was loaded.
  */
 bool Cursor::init(const Configuration *c, Screen *s, nuvie_game_t game_type) {
-	Std::string file, filename;
+	Std::string file;
+	Common::Path filename;
 	bool enable_cursors;
 
 	config = c;
@@ -82,7 +83,7 @@ bool Cursor::init(const Configuration *c, Screen *s, nuvie_game_t game_type) {
 /* Load pointers from `filename'. (lzw -> s_lib_32 -> shapes)
  * Returns the number found in the file.
  */
-uint32 Cursor::load_all(Std::string filename, nuvie_game_t game_type) {
+uint32 Cursor::load_all(const Common::Path &filename, nuvie_game_t game_type) {
 	U6Lzw decompressor;
 	U6Lib_n pointer_list;
 	NuvieIOBuffer iobuf;
diff --git a/engines/ultima/nuvie/core/cursor.h b/engines/ultima/nuvie/core/cursor.h
index cb5bb734d4f..d039b3a0ca8 100644
--- a/engines/ultima/nuvie/core/cursor.h
+++ b/engines/ultima/nuvie/core/cursor.h
@@ -69,7 +69,7 @@ public:
 		unload_all();
 	}
 	bool init(const Configuration *c, Screen *s, nuvie_game_t game_type);
-	uint32 load_all(Std::string filename, nuvie_game_t game_type);
+	uint32 load_all(const Common::Path &filename, nuvie_game_t game_type);
 	void unload_all();
 	bool set_pointer(uint8 ptr_num);
 
diff --git a/engines/ultima/nuvie/core/game.cpp b/engines/ultima/nuvie/core/game.cpp
index eaff2659734..37f537ea5d5 100644
--- a/engines/ultima/nuvie/core/game.cpp
+++ b/engines/ultima/nuvie/core/game.cpp
@@ -673,12 +673,12 @@ void Game::update_once_display() {
 /* return the fullpath to the datafile. First look for it in the savegame directory.
  * Then in the app data directory.
  */
-Std::string Game::get_data_file_path(Std::string datafile) {
-	Std::string path;
-	build_path("data", datafile, path);
+Common::Path Game::get_data_file_path(const Common::Path &datafile) {
+	Common::Path path("data");
+	path.joinInPlace(datafile);
 
-	if (!file_exists(path.c_str())) {
-		build_path(gui->get_data_dir(), datafile, path);
+	if (!file_exists(path)) {
+		path = gui->get_data_dir().joinInPlace(datafile);
 	}
 
 	return path;
diff --git a/engines/ultima/nuvie/core/game.h b/engines/ultima/nuvie/core/game.h
index d1fb3f91724..bff8e52d233 100644
--- a/engines/ultima/nuvie/core/game.h
+++ b/engines/ultima/nuvie/core/game.h
@@ -306,7 +306,7 @@ public:
 	uint16 get_game_y_offset() const {
 		return game_y_offset;
 	}
-	Std::string get_data_file_path(Std::string datafile);
+	Common::Path get_data_file_path(const Common::Path &datafile);
 
 	/* Return instances of Game classes */
 	static Game *get_game()          {
diff --git a/engines/ultima/nuvie/core/look.cpp b/engines/ultima/nuvie/core/look.cpp
index 3d6990602b7..c546265874e 100644
--- a/engines/ultima/nuvie/core/look.cpp
+++ b/engines/ultima/nuvie/core/look.cpp
@@ -41,7 +41,7 @@ Look::~Look() {
 }
 
 bool Look::init() {
-	Std::string filename;
+	Common::Path filename;
 	U6Lzw lzw;
 	uint32 decomp_size;
 	unsigned char *ptr;
diff --git a/engines/ultima/nuvie/core/map.cpp b/engines/ultima/nuvie/core/map.cpp
index 8a35d7453a3..621b1527bbc 100644
--- a/engines/ultima/nuvie/core/map.cpp
+++ b/engines/ultima/nuvie/core/map.cpp
@@ -359,7 +359,7 @@ const char *Map::look(uint16 x, uint16 y, uint8 level) {
 
 
 bool Map::loadMap(TileManager *tm, ObjManager *om) {
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead map_file;
 	NuvieIOFileRead chunks_file;
 
@@ -450,12 +450,14 @@ bool Map::has_roof(uint16 x, uint16 y, uint8 level) const {
 	return false;
 }
 
-Std::string Map::getRoofDataFilename() const {
-	Std::string game_type, datadir, path, mapfile;
+Common::Path Map::getRoofDataFilename() const {
+	Std::string game_type, tmp;
+	Common::Path datadir, path, mapfile;
 
-	config->value("config/datadir", datadir, "");
+	config->value("config/datadir", tmp, "");
 	config->value("config/GameID", game_type);
 
+	datadir = Common::Path(tmp);
 	build_path(datadir, "maps", path);
 	datadir = path;
 	build_path(datadir, game_type, path);
@@ -465,12 +467,15 @@ Std::string Map::getRoofDataFilename() const {
 	return mapfile;
 }
 
-Std::string Map::getRoofTilesetFilename() const {
-	Std::string datadir;
-	Std::string imagefile;
-	Std::string path;
+Common::Path Map::getRoofTilesetFilename() const {
+	Std::string tmp;
+	Common::Path datadir;
+	Common::Path imagefile;
+	Common::Path path;
 
-	config->value("config/datadir", datadir, "");
+	config->value("config/datadir", tmp, "");
+
+	datadir = Common::Path(tmp);
 	build_path(datadir, "images", path);
 	datadir = path;
 	build_path(datadir, "roof_tiles.bmp", imagefile);
diff --git a/engines/ultima/nuvie/core/map.h b/engines/ultima/nuvie/core/map.h
index 1be68e9e219..e68fa1219a9 100644
--- a/engines/ultima/nuvie/core/map.h
+++ b/engines/ultima/nuvie/core/map.h
@@ -194,10 +194,10 @@ public:
 	bool testIntersection(int x, int y, uint8 level, uint8 flags, LineTestResult &Result, Obj *excluded_obj = nullptr); // excluded_obj only works for LT_HitUnpassable
 
 	void saveRoofData();
-	Std::string getRoofTilesetFilename() const;
+	Common::Path getRoofTilesetFilename() const;
 
 protected:
-	Std::string getRoofDataFilename() const;
+	Common::Path getRoofDataFilename() const;
 	void insertSurfaceSuperChunk(const unsigned char *schunk_ptr, const unsigned char *chunk_data, uint8 schunk_num);
 	void insertSurfaceChunk(const unsigned char *chunk, uint16 x, uint16 y);
 
diff --git a/engines/ultima/nuvie/core/obj_manager.cpp b/engines/ultima/nuvie/core/obj_manager.cpp
index a799cc992c2..b7ae0c42a71 100644
--- a/engines/ultima/nuvie/core/obj_manager.cpp
+++ b/engines/ultima/nuvie/core/obj_manager.cpp
@@ -111,7 +111,7 @@ ObjManager::~ObjManager() {
 }
 
 bool ObjManager::load_basetile() {
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead basetile;
 
 	config_get_path(config, "basetile", filename);
@@ -128,7 +128,7 @@ bool ObjManager::load_basetile() {
 }
 
 bool ObjManager::load_weight_table() {
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead tileflag;
 
 	config_get_path(config, "tileflag", filename);
diff --git a/engines/ultima/nuvie/core/tile_manager.cpp b/engines/ultima/nuvie/core/tile_manager.cpp
index 68baf52ff3e..e834425e748 100644
--- a/engines/ultima/nuvie/core/tile_manager.cpp
+++ b/engines/ultima/nuvie/core/tile_manager.cpp
@@ -108,7 +108,7 @@ TileManager::~TileManager() {
 }
 
 bool TileManager::loadTiles() {
-	Std::string maptiles_path, masktype_path, path;
+	Common::Path maptiles_path, masktype_path, path;
 	NuvieIOFileRead objtiles_vga;
 	NuvieIOFileRead tileindx_vga;
 	NuvieIOFileRead file;
@@ -138,20 +138,20 @@ bool TileManager::loadTiles() {
 	case NUVIE_GAME_U6 :
 		tile_data = lzw->decompress_file(maptiles_path, maptiles_size);
 		if (tile_data == nullptr) {
-			ConsoleAddError("Decompressing " + maptiles_path);
+			ConsoleAddError("Decompressing " + maptiles_path.toString());
 			return false;
 		}
 
 		masktype = lzw->decompress_file(masktype_path, masktype_size);
 		if (masktype == nullptr) {
-			ConsoleAddError("Decompressing " + masktype_path);
+			ConsoleAddError("Decompressing " + masktype_path.toString());
 			return false;
 		}
 		break;
 	case NUVIE_GAME_MD :
 	case NUVIE_GAME_SE :
 		if (lib_file.open(maptiles_path, 4, game_type) == false) {
-			ConsoleAddError("Opening " + maptiles_path);
+			ConsoleAddError("Opening " + maptiles_path.toString());
 			return false;
 		}
 		maptiles_size = lib_file.get_item_size(0);
@@ -160,7 +160,7 @@ bool TileManager::loadTiles() {
 		lib_file.close();
 
 		if (lib_file.open(masktype_path, 4, game_type) == false) {
-			ConsoleAddError("Opening " + masktype_path);
+			ConsoleAddError("Opening " + masktype_path.toString());
 			return false;
 		}
 		//masktype_size = lib_file.get_item_size(0);
@@ -182,7 +182,7 @@ bool TileManager::loadTiles() {
 
 	config_get_path(config, "objtiles.vga", path);
 	if (objtiles_vga.open(path) == false) {
-		ConsoleAddError("Opening " + path);
+		ConsoleAddError("Opening " + path.toString());
 		return false;
 	}
 
@@ -195,7 +195,7 @@ bool TileManager::loadTiles() {
 	config_get_path(config, "tileindx.vga", path);
 
 	if (tileindx_vga.open(path) == false) {
-		ConsoleAddError("Opening " + path);
+		ConsoleAddError("Opening " + path.toString());
 		return false;
 	}
 
@@ -392,7 +392,7 @@ void TileManager::update() {
 
 
 bool TileManager::loadTileFlag() {
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead file;
 	uint16 i;
 
@@ -454,7 +454,7 @@ bool TileManager::loadTileFlag() {
 }
 
 bool TileManager::loadAnimData() {
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead file;
 	int gameType;
 	config->value("config/GameType", gameType);
@@ -546,7 +546,7 @@ void TileManager::decodePixelBlockTile(const unsigned char *tile_data, uint16 ti
 
 
 bool TileManager::loadAnimMask() {
-	Std::string filename;
+	Common::Path filename;
 	U6Lzw lzw;
 	uint16 i;
 	unsigned char *animmask;
@@ -791,7 +791,7 @@ const Tile *TileManager::get_gump_cursor_tile() {
 	return &gump_cursor;
 }
 
-Tile *TileManager::loadCustomTiles(const Std::string filename, bool overwrite_tiles, bool copy_tileflags, uint16 tile_num_start_offset) {
+Tile *TileManager::loadCustomTiles(const Common::Path &filename, bool overwrite_tiles, bool copy_tileflags, uint16 tile_num_start_offset) {
 	NuvieBmpFile bmp;
 
 	if (bmp.load(filename) == false) {
@@ -891,7 +891,7 @@ void TileManager::freeCustomTiles() {
 	}
 }
 
-void TileManager::exportTilesetToBmpFile(Std::string filename, bool fixupU6Shoreline) {
+void TileManager::exportTilesetToBmpFile(const Common::Path &filename, bool fixupU6Shoreline) {
 	NuvieBmpFile bmp;
 
 	unsigned char pal[256 * 4];
diff --git a/engines/ultima/nuvie/core/tile_manager.h b/engines/ultima/nuvie/core/tile_manager.h
index d40ee5aa575..5e28e090c45 100644
--- a/engines/ultima/nuvie/core/tile_manager.h
+++ b/engines/ultima/nuvie/core/tile_manager.h
@@ -201,9 +201,9 @@ public:
 	Tile *get_use_tile();
 	const Tile *get_gump_cursor_tile();
 
-	Tile *loadCustomTiles(const Std::string filename, bool overwrite_tiles, bool copy_tileflags, uint16 tile_num_start_offset);
+	Tile *loadCustomTiles(const Common::Path &filename, bool overwrite_tiles, bool copy_tileflags, uint16 tile_num_start_offset);
 	void freeCustomTiles();
-	void exportTilesetToBmpFile(Std::string filename, bool fixupU6Shoreline = true);
+	void exportTilesetToBmpFile(const Common::Path &filename, bool fixupU6Shoreline = true);
 protected:
 
 	bool loadAnimData();
diff --git a/engines/ultima/nuvie/files/nuvie_bmp_file.cpp b/engines/ultima/nuvie/files/nuvie_bmp_file.cpp
index 72c5133632a..dd06eb6a408 100644
--- a/engines/ultima/nuvie/files/nuvie_bmp_file.cpp
+++ b/engines/ultima/nuvie/files/nuvie_bmp_file.cpp
@@ -75,10 +75,10 @@ bool NuvieBmpFile::initNewBlankImage(sint32 width, sint32 height, const unsigned
 	return true;
 }
 
-bool NuvieBmpFile::load(Std::string filename) {
+bool NuvieBmpFile::load(const Common::Path &filename) {
 	NuvieIOFileRead file;
 
-	if (filename.length() == 0)
+	if (filename.empty())
 		return handleError("zero byte file");
 
 	if (!file.open(filename)) {
@@ -166,11 +166,11 @@ bool NuvieBmpFile::load(Std::string filename) {
 	return true;
 }
 
-bool NuvieBmpFile::save(Std::string filename) {
+bool NuvieBmpFile::save(const Common::Path &filename) {
 	NuvieIOFileWrite file;
 
 	if (!file.open(filename)) {
-		return handleError("Opening " + filename + ".");
+		return handleError("Opening " + filename.toString() + ".");
 	}
 
 	file.write2(header.type);
@@ -267,7 +267,7 @@ unsigned char *NuvieBmpFile::getRawIndexedDataCopy() {
 	return copy;
 }
 
-Graphics::ManagedSurface *NuvieBmpFile::getSdlSurface32(Std::string filename) {
+Graphics::ManagedSurface *NuvieBmpFile::getSdlSurface32(const Common::Path &filename) {
 	load(filename);
 	return getSdlSurface32();
 }
diff --git a/engines/ultima/nuvie/files/nuvie_bmp_file.h b/engines/ultima/nuvie/files/nuvie_bmp_file.h
index c6723290212..f04a5ea33e2 100644
--- a/engines/ultima/nuvie/files/nuvie_bmp_file.h
+++ b/engines/ultima/nuvie/files/nuvie_bmp_file.h
@@ -69,8 +69,8 @@ public:
 
 	bool initNewBlankImage(sint32 width, sint32 height, const unsigned char *palette);
 
-	bool load(Std::string filename);
-	bool save(Std::string filename);
+	bool load(const Common::Path &filename);
+	bool save(const Common::Path &filename);
 
 	uint16 getWidth() const {
 		return (uint16)infoHeader.width;
@@ -84,7 +84,7 @@ public:
 	unsigned char *getRawIndexedData();
 	unsigned char *getRawIndexedDataCopy();
 	Graphics::ManagedSurface *getSdlSurface32();
-	Graphics::ManagedSurface *getSdlSurface32(Std::string filename);
+	Graphics::ManagedSurface *getSdlSurface32(const Common::Path &filename);
 
 private:
 	bool handleError(Std::string error);
diff --git a/engines/ultima/nuvie/files/nuvie_file_list.cpp b/engines/ultima/nuvie/files/nuvie_file_list.cpp
index aff00bb6e82..297a3b457c5 100644
--- a/engines/ultima/nuvie/files/nuvie_file_list.cpp
+++ b/engines/ultima/nuvie/files/nuvie_file_list.cpp
@@ -35,7 +35,7 @@ NuvieFileList::NuvieFileList() : sort_mode(NUVIE_SORT_NAME_ASC) {
 NuvieFileList::~NuvieFileList() {
 }
 
-bool NuvieFileList::open(const char *directory, const char *search, uint8 s_mode) {
+bool NuvieFileList::open(const Common::Path &directory, const char *search, uint8 s_mode) {
 	Common::FSNode dir(directory);
 	Common::FSList list;
 
@@ -43,12 +43,12 @@ bool NuvieFileList::open(const char *directory, const char *search, uint8 s_mode
 	sort_mode = s_mode;
 
 	if (!dir.isDirectory()) {
-		ConsoleAddWarning(Std::string("Failed to open ") + directory);
+		ConsoleAddWarning(Std::string("Failed to open ") + directory.toString());
 		return false;
 	}
 
 	if (!dir.getChildren(list, Common::FSNode::kListFilesOnly)) {
-		ConsoleAddWarning(Std::string("Failed to get children of ") + directory);
+		ConsoleAddWarning(Std::string("Failed to get children of ") + directory.toString());
 		return false;
 	};
 	for (const Common::FSNode &node : list)
@@ -63,7 +63,7 @@ bool NuvieFileList::open(const char *directory, const char *search, uint8 s_mode
 bool NuvieFileList::add_filename(const Common::FSNode &file) {
 	NuvieFileDesc filedesc;
 	filedesc.m_time = 0;
-	filedesc.filename.assign(file.getName());
+	filedesc.filename.assign(file.getFileName());
 
 	file_list.push_front(filedesc);
 
diff --git a/engines/ultima/nuvie/files/nuvie_file_list.h b/engines/ultima/nuvie/files/nuvie_file_list.h
index ea58cb23e47..6fd6bf2a64d 100644
--- a/engines/ultima/nuvie/files/nuvie_file_list.h
+++ b/engines/ultima/nuvie/files/nuvie_file_list.h
@@ -65,7 +65,7 @@ public:
 	NuvieFileList();
 	~NuvieFileList();
 
-	bool open(const char *directory, const char *restrict, uint8 sort_mode);
+	bool open(const Common::Path &directory, const char *restrict, uint8 sort_mode);
 
 	Std::string *next();
 	const Std::string *get_latest() const;
diff --git a/engines/ultima/nuvie/files/nuvie_io_file.cpp b/engines/ultima/nuvie/files/nuvie_io_file.cpp
index becbf2a8dbb..8e3ee9c255e 100644
--- a/engines/ultima/nuvie/files/nuvie_io_file.cpp
+++ b/engines/ultima/nuvie/files/nuvie_io_file.cpp
@@ -33,24 +33,26 @@ NuvieIOFileRead::~NuvieIOFileRead() {
 	close();
 }
 
-bool NuvieIOFileRead::open(const Common::String &filename) {
+bool NuvieIOFileRead::open(const Common::Path &filename) {
 	if (isOpen())
 		// We already have a file open, lets bail.
 		return false;
 
 	// Handle any relative files under the game path, such as for FM-Towns sound. Though path
 	// delimiters can also be used for resources in ultima.dat
-	if (filename.contains(U6PATH_DELIMITER)) {
-		Common::FSNode node(ConfMan.get("path"));
-		Common::String fname = filename;
-
-		for (size_t sepPos = fname.findFirstOf(U6PATH_DELIMITER);
-			sepPos != Common::String::npos && node.exists(); sepPos = fname.findFirstOf(U6PATH_DELIMITER)) {
-			node = node.getChild(fname.substr(0, sepPos));
-			fname = fname.substr(sepPos + 1);
-		}
 
-		node = node.getChild(fname);
+        Common::StringArray components = filename.splitComponents();
+        if (components.empty()) {
+                return false;
+        }
+
+	if (components.size() >= 2) {
+		Common::FSNode node(ConfMan.getPath("path"));
+		for(Common::StringArray::const_iterator it = components.begin(); it != components.end(); it++) {
+			node = node.getChild(*it);
+			if (!node.exists())
+				break;
+		}
 		if (node.exists())
 			_srcFile.open(node);
 	}
@@ -59,7 +61,7 @@ bool NuvieIOFileRead::open(const Common::String &filename) {
 		_srcFile.open(filename);
 
 	if (!_srcFile.isOpen()) {
-		DEBUG(0, LEVEL_ERROR, "Failed opening '%s'\n", filename.c_str());
+		DEBUG(0, LEVEL_ERROR, "Failed opening '%s'\n", filename.toString().c_str());
 		return false;
 	}
 
@@ -141,16 +143,16 @@ NuvieIOFileWrite::~NuvieIOFileWrite() {
 	close();
 }
 
-bool NuvieIOFileWrite::open(const Common::String &filename) {
+bool NuvieIOFileWrite::open(const Common::Path &filename) {
 	if (isOpen())
 		// We already have an open file
 		return false;
 
 	// Ensure it's a relative path, that we can open for writing using a DumpFile
-	assert(filename.contains("/"));
+	assert(!filename.getParent().empty());
 
 	if (!_dumpFile.open(filename, true)) {
-		DEBUG(0, LEVEL_ERROR, "Failed opening '%s'\n", filename.c_str());
+		DEBUG(0, LEVEL_ERROR, "Failed opening '%s'\n", filename.toString().c_str());
 		return false;
 	}
 
diff --git a/engines/ultima/nuvie/files/nuvie_io_file.h b/engines/ultima/nuvie/files/nuvie_io_file.h
index ef90f328aa9..38bbbf9e2d8 100644
--- a/engines/ultima/nuvie/files/nuvie_io_file.h
+++ b/engines/ultima/nuvie/files/nuvie_io_file.h
@@ -36,7 +36,7 @@ public:
 	NuvieIOFile() {}
 	~NuvieIOFile() override {}
 
-	virtual bool open(const Common::String &filename) {
+	virtual bool open(const Common::Path &filename) {
 		return false;
 	};
 };
@@ -49,7 +49,7 @@ public:
 	NuvieIOFileRead() : NuvieIOFile(), _file(nullptr) {}
 	~NuvieIOFileRead() override;
 
-	bool open(const Common::String &filename) override;
+	bool open(const Common::Path &filename) override;
 	virtual bool open(Common::InSaveFile *saveFile);
 	void close() override;
 	void seek(uint32 new_pos) override;
@@ -87,7 +87,7 @@ protected:
 public:
 	NuvieIOFileWrite();
 	~NuvieIOFileWrite() override;
-	bool open(const Common::String &filename) override;
+	bool open(const Common::Path &filename) override;
 	bool open(const Common::String &filename, bool isAutosave);
 	void close() override;
 	void seek(uint32 new_pos) override;
diff --git a/engines/ultima/nuvie/files/tmx_map.cpp b/engines/ultima/nuvie/files/tmx_map.cpp
index b40b4092da5..2519ff3b1c5 100644
--- a/engines/ultima/nuvie/files/tmx_map.cpp
+++ b/engines/ultima/nuvie/files/tmx_map.cpp
@@ -36,10 +36,10 @@ TMXMap::~TMXMap() {
 
 }
 
-bool TMXMap::exportTmxMapFiles(Std::string dir, nuvie_game_t type) {
+bool TMXMap::exportTmxMapFiles(const Common::Path &dir, nuvie_game_t type) {
 	savedir = dir;
 	savename = get_game_tag(type);
-	Std::string filename;
+	Common::Path filename;
 	build_path(savedir, savename + "_tileset.bmp", filename);
 
 
@@ -59,8 +59,8 @@ void TMXMap::writeRoofTileset(uint8 level) {
 		return;
 	}
 
-	Std::string filename = map->getRoofTilesetFilename();
-	Std::string destFilename;
+	Common::Path filename = map->getRoofTilesetFilename();
+	Common::Path destFilename;
 	build_path(savedir, savename + "_roof_tileset.bmp", destFilename);
 	NuvieIOFileRead read;
 	NuvieIOFileWrite write;
@@ -190,7 +190,7 @@ bool TMXMap::exportMapLevel(uint8 level) {
 	uint16 width = map->get_width(level);
 	mapdata = map->get_map_data(level);
 	Common::String level_string = Common::String::format("%d", level); // 'nn\0'
-	Std::string filename;
+	Common::Path filename;
 	build_path(savedir, savename + "_" + Std::string(level_string.c_str()) + ".tmx", filename);
 
 	tmx.open(filename);
diff --git a/engines/ultima/nuvie/files/tmx_map.h b/engines/ultima/nuvie/files/tmx_map.h
index 86714976cf4..4f1a4fd7cc6 100644
--- a/engines/ultima/nuvie/files/tmx_map.h
+++ b/engines/ultima/nuvie/files/tmx_map.h
@@ -40,14 +40,14 @@ private:
 	TileManager *tile_manager;
 	Map *map;
 	ObjManager *obj_manager;
-	Std::string savedir;
+	Common::Path savedir;
 	Std::string savename;
 	//nuvie_game_t game_type;
 
 public:
 	TMXMap(TileManager *tm, Map *m, ObjManager *om);
 	virtual ~TMXMap();
-	bool exportTmxMapFiles(Std::string dir, nuvie_game_t type);
+	bool exportTmxMapFiles(const Common::Path &dir, nuvie_game_t type);
 private:
 	bool exportMapLevel(uint8 level);
 	void writeRoofTileset(uint8 level);
diff --git a/engines/ultima/nuvie/files/u6_bmp.cpp b/engines/ultima/nuvie/files/u6_bmp.cpp
index 15d0f4d563c..9f23eae1192 100644
--- a/engines/ultima/nuvie/files/u6_bmp.cpp
+++ b/engines/ultima/nuvie/files/u6_bmp.cpp
@@ -38,14 +38,14 @@ U6Bmp::~U6Bmp() {
 }
 
 
-bool U6Bmp::load(Std::string filename) {
+bool U6Bmp::load(const Common::Path &filename) {
 	U6Lzw lzw;
 	uint32 data_size;
 
 	if (data != nullptr)
 		return false;
 
-	if (filename.length() == 0)
+	if (filename.empty())
 		return false;
 
 	data = lzw.decompress_file(filename, data_size);
diff --git a/engines/ultima/nuvie/files/u6_bmp.h b/engines/ultima/nuvie/files/u6_bmp.h
index 98f8b333016..290bfd1fb49 100644
--- a/engines/ultima/nuvie/files/u6_bmp.h
+++ b/engines/ultima/nuvie/files/u6_bmp.h
@@ -38,7 +38,7 @@ public:
 	U6Bmp();
 	~U6Bmp() override;
 
-	bool load(Std::string filename) override;
+	bool load(const Common::Path &filename) override;
 
 };
 
diff --git a/engines/ultima/nuvie/files/u6_lib_n.cpp b/engines/ultima/nuvie/files/u6_lib_n.cpp
index e1c65345e4b..471aa6c9d33 100644
--- a/engines/ultima/nuvie/files/u6_lib_n.cpp
+++ b/engines/ultima/nuvie/files/u6_lib_n.cpp
@@ -38,7 +38,7 @@ U6Lib_n::~U6Lib_n(void) {
 }
 
 // load u6lib from `filename'
-bool U6Lib_n::open(const Std::string &filename, uint8 size, uint8 type) {
+bool U6Lib_n::open(const Common::Path &filename, uint8 size, uint8 type) {
 	NuvieIOFileRead *file;
 
 	file = new NuvieIOFileRead();
@@ -89,10 +89,10 @@ void U6Lib_n::close() {
 
 /* Open a ^new^ file for writing, with lib_size and type.
  */
-bool U6Lib_n::create(const Std::string &filename, uint8 size, uint8 type) {
+bool U6Lib_n::create(const Common::Path &filename, uint8 size, uint8 type) {
 	NuvieIOFileWrite *file = new NuvieIOFileWrite();
 	if (!file->open(filename)) {
-		DEBUG(0, LEVEL_ERROR, "U6Lib: Error creating %s\n", filename.c_str());
+		DEBUG(0, LEVEL_ERROR, "U6Lib: Error creating %s\n", filename.toString().c_str());
 		delete file;
 		return false;
 	}
diff --git a/engines/ultima/nuvie/files/u6_lib_n.h b/engines/ultima/nuvie/files/u6_lib_n.h
index 217d19f6f2a..ea25c74448d 100644
--- a/engines/ultima/nuvie/files/u6_lib_n.h
+++ b/engines/ultima/nuvie/files/u6_lib_n.h
@@ -56,10 +56,10 @@ public:
 	U6Lib_n();
 	~U6Lib_n();
 
-	bool open(const Std::string &filename, uint8 size, uint8 type = NUVIE_GAME_U6);
+	bool open(const Common::Path &filename, uint8 size, uint8 type = NUVIE_GAME_U6);
 	bool open(NuvieIO *new_data, uint8 size, uint8 type = NUVIE_GAME_U6);
 	void close();
-	bool create(const Std::string &filename, uint8 size, uint8 type = NUVIE_GAME_U6);
+	bool create(const Common::Path &filename, uint8 size, uint8 type = NUVIE_GAME_U6);
 	uint8 get_game_type() {
 		return game_type;
 	}
diff --git a/engines/ultima/nuvie/files/u6_lzw.cpp b/engines/ultima/nuvie/files/u6_lzw.cpp
index 0ce9c05ed7a..cfd0c49185e 100644
--- a/engines/ultima/nuvie/files/u6_lzw.cpp
+++ b/engines/ultima/nuvie/files/u6_lzw.cpp
@@ -264,7 +264,7 @@ bool U6Lzw::decompress_buffer(unsigned char *source, uint32 source_length, unsig
 // -----------------
 // from file to file
 // -----------------
-unsigned char *U6Lzw::decompress_file(Std::string filename, uint32 &destination_length) {
+unsigned char *U6Lzw::decompress_file(const Common::Path &filename, uint32 &destination_length) {
 	unsigned char *source_buffer;
 	unsigned char *destination_buffer;
 	uint32 source_buffer_size;
diff --git a/engines/ultima/nuvie/files/u6_lzw.h b/engines/ultima/nuvie/files/u6_lzw.h
index 6cc7d9ba211..5f66c85ea68 100644
--- a/engines/ultima/nuvie/files/u6_lzw.h
+++ b/engines/ultima/nuvie/files/u6_lzw.h
@@ -84,7 +84,7 @@ public:
 
 	unsigned char *decompress_buffer(unsigned char *source, uint32 source_length, uint32 &destination_length);
 	bool decompress_buffer(unsigned char *source, uint32 source_length, unsigned char *destination, uint32 destination_length);
-	unsigned char *decompress_file(Std::string filename, uint32 &destination_length);
+	unsigned char *decompress_file(const Common::Path &filename, uint32 &destination_length);
 	unsigned char *compress_buffer(unsigned char *src, uint32 src_len,
 	                               uint32 &dest_len);
 	const char *strerror() const {
diff --git a/engines/ultima/nuvie/files/u6_shape.cpp b/engines/ultima/nuvie/files/u6_shape.cpp
index 1166a791a8d..462bb931590 100644
--- a/engines/ultima/nuvie/files/u6_shape.cpp
+++ b/engines/ultima/nuvie/files/u6_shape.cpp
@@ -117,7 +117,7 @@ bool U6Shape::init(uint16 w, uint16 h, uint16 hx, uint16 hy) {
 	return true;
 }
 
-bool U6Shape::load(Std::string filename) {
+bool U6Shape::load(const Common::Path &filename) {
 	return false;
 }
 
@@ -134,7 +134,7 @@ bool U6Shape::load(U6Lib_n *file, uint32 index) {
 	return false;
 }
 
-bool U6Shape::load_from_lzc(const Std::string &filename, uint32 idx, uint32 sub_idx) {
+bool U6Shape::load_from_lzc(const Common::Path &filename, uint32 idx, uint32 sub_idx) {
 	U6Lib_n lib_n;
 
 	if (!lib_n.open(filename, 4, NUVIE_GAME_MD)) {
@@ -283,7 +283,7 @@ bool U6Shape::load(unsigned char *buf) {
 // TODO - allow for failure
 bool U6Shape::load_WoU_background(const Configuration *config, nuvie_game_t game_type) {
 	U6Lib_n file;
-	Std::string filename;
+	Common::Path filename;
 
 	if (game_type == NUVIE_GAME_MD)
 		config_get_path(config, "mdscreen.lzc", filename);
diff --git a/engines/ultima/nuvie/files/u6_shape.h b/engines/ultima/nuvie/files/u6_shape.h
index 145f32b8fe0..6289ed19844 100644
--- a/engines/ultima/nuvie/files/u6_shape.h
+++ b/engines/ultima/nuvie/files/u6_shape.h
@@ -57,10 +57,10 @@ public:
 	virtual ~U6Shape();
 
 	bool init(uint16 w, uint16 h, uint16 hx = 0, uint16 hy = 0);
-	virtual bool load(Std::string filename);
+	virtual bool load(const Common::Path &filename);
 	bool load(U6Lib_n *file, uint32 index);
 	virtual bool load(unsigned char *buf);
-	bool load_from_lzc(const Std::string &filename, uint32 idx, uint32 sub_idx);
+	bool load_from_lzc(const Common::Path &filename, uint32 idx, uint32 sub_idx);
 	bool load_WoU_background(const Configuration *config, nuvie_game_t game_type);
 
 	const unsigned char *get_data() const;
diff --git a/engines/ultima/nuvie/files/utils.cpp b/engines/ultima/nuvie/files/utils.cpp
index 7d2c73b5661..1e6f3b85854 100644
--- a/engines/ultima/nuvie/files/utils.cpp
+++ b/engines/ultima/nuvie/files/utils.cpp
@@ -27,8 +27,6 @@
 namespace Ultima {
 namespace Nuvie {
 
-using Std::string;
-
 /*
  *  Open a file for input,
  *  trying the original name (lower case), and the upper case version
@@ -37,11 +35,9 @@ using Std::string;
  *  Output: 0 if couldn't open.
  */
 
-bool openFile(Common::ReadStream *&in, const char *fname) {
+bool openFile(Common::ReadStream *&in, const Common::Path &fname) {
 	Common::File *f = new Common::File();
-	Common::String filename(fname);
-
-	if (f->open(filename)) {
+	if (f->open(fname)) {
 	    in = f;
 	    return true;
 	} else {
@@ -54,7 +50,7 @@ bool openFile(Common::ReadStream *&in, const char *fname) {
  *  See if a file exists.
  */
 
-bool fileExists(const char *fname) {
+bool fileExists(const Common::Path &fname) {
 	return Common::File::exists(fname);
 }
 
diff --git a/engines/ultima/nuvie/files/utils.h b/engines/ultima/nuvie/files/utils.h
index afc493e95c7..010251236dc 100644
--- a/engines/ultima/nuvie/files/utils.h
+++ b/engines/ultima/nuvie/files/utils.h
@@ -22,7 +22,7 @@
 #ifndef NUVIE_FILES_UTILS_H
 #define NUVIE_FILES_UTILS_H
 
-#include "ultima/shared/std/string.h" // exception handling include
+#include "common/path.h"
 #include "common/stream.h"
 
 namespace Ultima {
@@ -30,10 +30,10 @@ namespace Nuvie {
 
 bool openFile(
 	Common::ReadStream *&in,    // Input stream to open.
-	const char *fname           // Filename
+	const Common::Path &fname   // Filename
 );
 
-extern bool fileExists(const char *fname);
+extern bool fileExists(const Common::Path &fname);
 
 } // End of namespace Nuvie
 } // End of namespace Ultima
diff --git a/engines/ultima/nuvie/fonts/bmp_font.cpp b/engines/ultima/nuvie/fonts/bmp_font.cpp
index fe3e9fe4e7a..935f0ecb92a 100644
--- a/engines/ultima/nuvie/fonts/bmp_font.cpp
+++ b/engines/ultima/nuvie/fonts/bmp_font.cpp
@@ -41,15 +41,15 @@ BMPFont::~BMPFont() {
 		free(font_width_data);
 }
 
-bool BMPFont::init(Std::string bmp_filename, bool dual_fontmap) {
+bool BMPFont::init(const Common::Path &bmp_filename, bool dual_fontmap) {
 	dual_font_mode = dual_fontmap;
 	num_chars = 256;
 
-	Std::string full_filename = bmp_filename;
+	Common::Path full_filename = bmp_filename;
 
-	full_filename += ".bmp";
+	full_filename.appendInPlace(".bmp");
 
-	font_surface = SDL_LoadBMP(full_filename.c_str());
+	font_surface = SDL_LoadBMP(full_filename);
 
 	font_surface->setTransparentColor(font_surface->format.RGBToColor(0, 0x70, 0xfc));
 
@@ -58,7 +58,7 @@ bool BMPFont::init(Std::string bmp_filename, bool dual_fontmap) {
 
 	//read font width data. For variable width fonts.
 	full_filename = bmp_filename;
-	full_filename += ".dat";
+	full_filename.appendInPlace(".dat");
 
 	NuvieIOFileRead font_width_data_file;
 	if (font_width_data_file.open(full_filename)) {
diff --git a/engines/ultima/nuvie/fonts/bmp_font.h b/engines/ultima/nuvie/fonts/bmp_font.h
index e2963c34e5f..68ab5d7ff1a 100644
--- a/engines/ultima/nuvie/fonts/bmp_font.h
+++ b/engines/ultima/nuvie/fonts/bmp_font.h
@@ -44,7 +44,7 @@ public:
 	BMPFont();
 	~BMPFont() override;
 
-	bool init(Std::string bmp_filename, bool dual_fontmap = false);
+	bool init(const Common::Path &bmp_filename, bool dual_fontmap = false);
 
 	uint16 getCharWidth(uint8 c) override;
 	uint16 getCharHeight() override {
diff --git a/engines/ultima/nuvie/fonts/font_manager.cpp b/engines/ultima/nuvie/fonts/font_manager.cpp
index 0e13e1fb633..fac7a352473 100644
--- a/engines/ultima/nuvie/fonts/font_manager.cpp
+++ b/engines/ultima/nuvie/fonts/font_manager.cpp
@@ -73,7 +73,7 @@ bool FontManager::init(nuvie_game_t game_type) {
 bool FontManager::initU6() {
 	U6Font *font;
 	unsigned char *font_data;
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead u6_ch;
 
 	config_get_path(config, "u6.ch", filename);
@@ -103,7 +103,7 @@ bool FontManager::initU6() {
 
 bool FontManager::initWOU(Std::string filename) {
 	WOUFont *font;
-	Std::string path;
+	Common::Path path;
 	U6Lib_n lib_file;
 
 	config_get_path(config, filename, path);
@@ -126,7 +126,7 @@ bool FontManager::initWOU(Std::string filename) {
 
 bool FontManager::initWOUSystemFont() {
 	U6Font *font;
-	Std::string path;
+	Common::Path path;
 	U6Lib_n lib_file;
 
 	config_get_path(config, "system.lzc", path);
@@ -147,8 +147,8 @@ bool FontManager::initWOUSystemFont() {
 
 bool FontManager::initConvFonts(nuvie_game_t game_type) {
 	char filename[7]; // u6.bmp\0 or u6.dat\0
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path path;
 
 	build_path(datadir, "images", path);
 	datadir = path;
@@ -157,7 +157,7 @@ bool FontManager::initConvFonts(nuvie_game_t game_type) {
 	build_path(datadir, "fonts", path);
 	datadir = path;
 
-	Std::string imagefile;
+	Common::Path imagefile;
 	Common::sprintf_s(filename, "%s.bmp", get_game_tag(Game::get_game()->get_game_type()));
 
 	build_path(datadir, filename, imagefile);
@@ -168,7 +168,7 @@ bool FontManager::initConvFonts(nuvie_game_t game_type) {
 
 	conv_font_data = bmp.getRawIndexedDataCopy();
 
-	Std::string widthfile;
+	Common::Path widthfile;
 	Common::sprintf_s(filename, "%s.dat", get_game_tag(Game::get_game()->get_game_type()));
 
 	build_path(datadir, filename, widthfile);
diff --git a/engines/ultima/nuvie/fonts/wou_font.cpp b/engines/ultima/nuvie/fonts/wou_font.cpp
index 3964dcba2ce..339da5f70db 100644
--- a/engines/ultima/nuvie/fonts/wou_font.cpp
+++ b/engines/ultima/nuvie/fonts/wou_font.cpp
@@ -42,7 +42,7 @@ WOUFont::~WOUFont() {
 		free(char_buf);
 }
 
-bool WOUFont::init(const char *filename) {
+bool WOUFont::init(const Common::Path &filename) {
 
 	U6Lzw lzw;
 	uint32 decomp_size;
diff --git a/engines/ultima/nuvie/fonts/wou_font.h b/engines/ultima/nuvie/fonts/wou_font.h
index 86b653db9a9..cab5034ab80 100644
--- a/engines/ultima/nuvie/fonts/wou_font.h
+++ b/engines/ultima/nuvie/fonts/wou_font.h
@@ -43,7 +43,7 @@ public:
 	WOUFont();
 	~WOUFont() override;
 
-	bool init(const char *filename);
+	bool init(const Common::Path &filename);
 	bool initWithBuffer(unsigned char *buffer, uint32 buffer_len);
 
 
diff --git a/engines/ultima/nuvie/gui/gui.cpp b/engines/ultima/nuvie/gui/gui.cpp
index 6086b2960d7..0728f126f3d 100644
--- a/engines/ultima/nuvie/gui/gui.cpp
+++ b/engines/ultima/nuvie/gui/gui.cpp
@@ -397,12 +397,12 @@ void GUI::lock_input(GUI_Widget *widget) {
 	}
 }
 
-Std::string GUI::get_data_dir() const {
+Common::Path GUI::get_data_dir() const {
 	Std::string datadir;
 
 	config->value("config/datadir", datadir, "");
 
-	return datadir;
+	return Common::Path(datadir);
 }
 
 } // End of namespace Nuvie
diff --git a/engines/ultima/nuvie/gui/gui.h b/engines/ultima/nuvie/gui/gui.h
index 59111938ac6..1bb02ab8ce6 100644
--- a/engines/ultima/nuvie/gui/gui.h
+++ b/engines/ultima/nuvie/gui/gui.h
@@ -164,7 +164,7 @@ public:
 	void unblock() {
 		block_input = false;
 	}
-	Std::string get_data_dir() const ;
+	Common::Path get_data_dir() const;
 
 	uint16 get_width() const {
 		return screen->get_width();
diff --git a/engines/ultima/nuvie/gui/gui_dialog.cpp b/engines/ultima/nuvie/gui/gui_dialog.cpp
index 83fb57b72e5..f6d7c54769d 100644
--- a/engines/ultima/nuvie/gui/gui_dialog.cpp
+++ b/engines/ultima/nuvie/gui/gui_dialog.cpp
@@ -47,15 +47,15 @@ GUI_Dialog::~GUI_Dialog() {
 
 void GUI_Dialog::loadBorderImages() {
 	char filename[15]; // BorderU6_x.bmp\0
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
 
 	for (int i = 0; i < 8; i++) {
 		Common::sprintf_s(filename, "Border%s_%d.bmp", "U6", i + 1);
 		build_path(datadir, filename, imagefile);
-		border[i] = SDL_LoadBMP(imagefile.c_str());
+		border[i] = SDL_LoadBMP(imagefile);
 		if (border[i] == nullptr) {
-			DEBUG(0, LEVEL_ERROR, "Failed to load %s from '%s' directory\n", filename, datadir.c_str());
+			DEBUG(0, LEVEL_ERROR, "Failed to load %s from '%s' directory\n", filename, datadir.toString().c_str());
 		}
 	}
 }
diff --git a/engines/ultima/nuvie/gui/gui_scroll_bar.cpp b/engines/ultima/nuvie/gui/gui_scroll_bar.cpp
index db239a15d8f..e121acf7046 100644
--- a/engines/ultima/nuvie/gui/gui_scroll_bar.cpp
+++ b/engines/ultima/nuvie/gui/gui_scroll_bar.cpp
@@ -67,22 +67,22 @@ GUI_ScrollBar::GUI_ScrollBar(int x, int y, int h, GUI_CallBack *callback)
 
 
 void GUI_ScrollBar::loadButtons() {
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
 	Graphics::ManagedSurface *image, *image1;
 
 	build_path(datadir, "ScrollBarUp_1.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
 	build_path(datadir, "ScrollBarUp_2.bmp", imagefile);
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image1 = SDL_LoadBMP(imagefile);
 
 	up_button = new GUI_Button(nullptr, 0, 0, image, image1, this);
 	this->AddWidget(up_button);
 
 	build_path(datadir, "ScrollBarDown_1.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
 	build_path(datadir, "ScrollBarDown_2.bmp", imagefile);
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image1 = SDL_LoadBMP(imagefile);
 
 	button_height = image->h;
 
diff --git a/engines/ultima/nuvie/gui/widgets/background.cpp b/engines/ultima/nuvie/gui/widgets/background.cpp
index 0d168fa37e7..ac7cf278d94 100644
--- a/engines/ultima/nuvie/gui/widgets/background.cpp
+++ b/engines/ultima/nuvie/gui/widgets/background.cpp
@@ -49,7 +49,7 @@ Background::~Background() {
 }
 
 bool Background::init() {
-	Std::string filename;
+	Common::Path filename;
 
 	if (!Game::get_game()->is_new_style()) {
 		switch (game_type) {
diff --git a/engines/ultima/nuvie/gui/widgets/command_bar.cpp b/engines/ultima/nuvie/gui/widgets/command_bar.cpp
index 06de0dc88b0..09de360c885 100644
--- a/engines/ultima/nuvie/gui/widgets/command_bar.cpp
+++ b/engines/ultima/nuvie/gui/widgets/command_bar.cpp
@@ -202,7 +202,7 @@ bool CommandBar::init_buttons() {
 		icon[9] = &placeholder_tile; // quick save
 		icon[10] = &placeholder_tile; // quick load
 
-		Std::string filename;
+		Common::Path filename;
 		Configuration *config = Game::get_game()->get_config();
 		config_get_path(config, "mdscreen.lzc", filename);
 		lever_up = new U6Shape();
diff --git a/engines/ultima/nuvie/gui/widgets/converse_gump_wou.cpp b/engines/ultima/nuvie/gui/widgets/converse_gump_wou.cpp
index 37e163c2bbb..6187f45de8a 100644
--- a/engines/ultima/nuvie/gui/widgets/converse_gump_wou.cpp
+++ b/engines/ultima/nuvie/gui/widgets/converse_gump_wou.cpp
@@ -69,8 +69,8 @@ ConverseGumpWOU::ConverseGumpWOU(const Configuration *cfg, Font *f, Screen *s)
 		GUI_Widget::Init(nullptr, x_off + 8, y_off + 8, 160, 160);
 		bg_color = converse_bg_color = 0x31; //17;
 		if (game->get_game_width() >= 335) {
-			Std::string imagefile;
-			Std::string datadir = GUI::get_gui()->get_data_dir();
+			Common::Path imagefile;
+			Common::Path datadir = GUI::get_gui()->get_data_dir();
 			build_path(datadir, "U6_WOU_Scroll_bg.bmp", imagefile);
 			NuvieBmpFile bmp;
 			bg_image = bmp.getSdlSurface32(imagefile);
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.cpp b/engines/ultima/nuvie/gui/widgets/map_window.cpp
index 9ae102fb4a2..8529ef167fc 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.cpp
+++ b/engines/ultima/nuvie/gui/widgets/map_window.cpp
@@ -2565,8 +2565,8 @@ void MapWindow::set_roof_mode(bool roofs) {
 }
 
 void MapWindow::loadRoofTiles() {
-	const Std::string imagefile = map->getRoofTilesetFilename();
-	roof_tiles = SDL_LoadBMP(imagefile.c_str());
+	const Common::Path imagefile = map->getRoofTilesetFilename();
+	roof_tiles = SDL_LoadBMP(imagefile);
 	if (roof_tiles) {
 		roof_tiles->setTransparentColor(roof_tiles->format.RGBToColor(0, 0x70, 0xfc));
 	}
diff --git a/engines/ultima/nuvie/menus/asset_viewer_dialog.h b/engines/ultima/nuvie/menus/asset_viewer_dialog.h
index 2c597cd88cd..cc2e4e53cd0 100644
--- a/engines/ultima/nuvie/menus/asset_viewer_dialog.h
+++ b/engines/ultima/nuvie/menus/asset_viewer_dialog.h
@@ -49,7 +49,7 @@ protected:
 	int _shapeIdx;
 	ViewMode _viewMode;
 	U6Shape *_curShape;
-	Std::string _screenFile;
+	Common::Path _screenFile;
 public:
 	AssetViewerDialog(CallBack *callback);
 	~AssetViewerDialog() override;
diff --git a/engines/ultima/nuvie/misc/sdl_compat.cpp b/engines/ultima/nuvie/misc/sdl_compat.cpp
index 86ea8eeb5aa..1e339626b37 100644
--- a/engines/ultima/nuvie/misc/sdl_compat.cpp
+++ b/engines/ultima/nuvie/misc/sdl_compat.cpp
@@ -56,14 +56,14 @@ int SDL_FillRect(Graphics::ManagedSurface *surf, const Common::Rect *rect, uint
 	return 0;
 }
 
-Graphics::ManagedSurface *SDL_LoadBMP(const char *filename) {
+Graphics::ManagedSurface *SDL_LoadBMP(const Common::Path &filename) {
 	Common::File f;
 	Image::BitmapDecoder decoder;
 
 	if (!f.open(filename))
-		error("Could not open file - %s", filename);
+		error("Could not open file - %s", filename.toString().c_str());
 	if (!decoder.loadStream(f))
-		error("Could not load bitmap - %s", filename);
+		error("Could not load bitmap - %s", filename.toString().c_str());
 
 	const Graphics::Surface *src = decoder.getSurface();
 	Screen *const screen = Game::get_game()->get_screen();
diff --git a/engines/ultima/nuvie/misc/sdl_compat.h b/engines/ultima/nuvie/misc/sdl_compat.h
index e9e754b36bf..03285ab00ff 100644
--- a/engines/ultima/nuvie/misc/sdl_compat.h
+++ b/engines/ultima/nuvie/misc/sdl_compat.h
@@ -36,7 +36,7 @@ extern uint32 SDL_GetTicks();
 extern int SDL_BlitSurface(const Graphics::ManagedSurface *src, const Common::Rect *srcrect,
 	Graphics::ManagedSurface *dst, Common::Rect *dstrect);
 extern int SDL_FillRect(Graphics::ManagedSurface *surf, const Common::Rect *rect, uint color);
-extern Graphics::ManagedSurface *SDL_LoadBMP(const char *filename);
+extern Graphics::ManagedSurface *SDL_LoadBMP(const Common::Path &filename);
 
 } // End of namespace Nuvie
 } // End of namespace Ultima
diff --git a/engines/ultima/nuvie/misc/u6_misc.cpp b/engines/ultima/nuvie/misc/u6_misc.cpp
index c367e432863..1d7dbe45346 100644
--- a/engines/ultima/nuvie/misc/u6_misc.cpp
+++ b/engines/ultima/nuvie/misc/u6_misc.cpp
@@ -73,8 +73,9 @@ const char *get_game_tag(int game_type) {
 	return "";
 }
 
-void config_get_path(const Configuration *config, const Std::string &filename, Std::string &path) {
-	Std::string key, game_name, game_dir, tmp_path;
+void config_get_path(const Configuration *config, const Std::string &filename, Common::Path &path) {
+	Std::string key, game_name;
+	Common::Path game_dir, tmp_path;
 
 	config->value("config/GameName", game_name);
 
@@ -84,12 +85,12 @@ void config_get_path(const Configuration *config, const Std::string &filename, S
 
 	config->pathFromValue(key, "", game_dir);
 
-	tmp_path = game_dir + filename;
+	tmp_path = game_dir.appendComponent(filename);
 
 	path = tmp_path;
 }
 
-int mkdir_recursive(const Std::string &path, int mode) {
+int mkdir_recursive(const Common::Path &path, int mode) {
 #ifdef TODO
 	vector<string> directories;
 	string tmp_path;
@@ -147,15 +148,8 @@ nuvie_game_t get_game_type(const Configuration *config) {
 	return (nuvie_game_t)game_type;
 }
 
-void build_path(const Std::string &path, const Std::string &filename, Std::string &full_path) {
-	full_path = path;
-
-	if (full_path.length() > 0 && full_path[full_path.length() - 1] != U6PATH_DELIMITER)
-		full_path += U6PATH_DELIMITER + filename;
-	else
-		full_path += filename;
-
-	return;
+void build_path(const Common::Path &path, const Std::string &filename, Common::Path &full_path) {
+	full_path = path.appendComponent(filename);
 }
 
 bool has_fmtowns_support(const Configuration *config) {
@@ -167,12 +161,12 @@ bool has_fmtowns_support(const Configuration *config) {
 	return false;
 }
 
-bool directory_exists(const char *directory) {
-	Common::FSNode gameDir(ConfMan.get("path"));
-	return Common::FSNode(directory).exists() || gameDir.getChild(directory).exists();
+bool directory_exists(const Common::Path &directory) {
+	return Common::FSNode(directory).exists() ||
+		Common::FSNode(ConfMan.getPath("path").joinInPlace(directory)).exists();
 }
 
-bool file_exists(const char *path) {
+bool file_exists(const Common::Path &path) {
 	return Common::File::exists(path);
 }
 
diff --git a/engines/ultima/nuvie/misc/u6_misc.h b/engines/ultima/nuvie/misc/u6_misc.h
index b1c91cf5b3b..bdf8637e246 100644
--- a/engines/ultima/nuvie/misc/u6_misc.h
+++ b/engines/ultima/nuvie/misc/u6_misc.h
@@ -48,12 +48,12 @@ typedef enum {
 
 Std::string config_get_game_key(const Configuration *config);
 const char *get_game_tag(int game_type);
-void config_get_path(const Configuration *config, const Std::string &filename, Std::string &path);
+void config_get_path(const Configuration *config, const Std::string &filename, Common::Path &path);
 uint8 get_game_type(const char *string);
 nuvie_game_t get_game_type(const Configuration *config);
-void build_path(const Std::string &path, const Std::string &filename, Std::string &full_path);
-bool directory_exists(const char *directory);
-bool file_exists(const char *path);
+void build_path(const Common::Path &path, const Std::string &filename, Common::Path &full_path);
+bool directory_exists(const Common::Path &directory);
+bool file_exists(const Common::Path &path);
 void print_b(DebugLevelType level, uint8 num);
 void print_b16(DebugLevelType level, uint16 num);
 void print_indent(DebugLevelType level, uint8 indent);
@@ -90,7 +90,7 @@ inline uint32 divide_time(uint32 this_time, uint32 &last_time, uint32 *passed_ti
 	return (fraction);
 }
 
-int mkdir_recursive(const Std::string &path, int mode);
+int mkdir_recursive(const Common::Path &path, int mode);
 
 void draw_line_8bit(int sx, int sy, int ex, int ey, uint8 col, uint8 *pixels, uint16 w, uint16 h);
 
diff --git a/engines/ultima/nuvie/nuvie.cpp b/engines/ultima/nuvie/nuvie.cpp
index adb33fc3fc8..4c1766cc1c4 100644
--- a/engines/ultima/nuvie/nuvie.cpp
+++ b/engines/ultima/nuvie/nuvie.cpp
@@ -64,7 +64,7 @@ NuvieEngine::~NuvieEngine() {
 	g_engine = nullptr;
 }
 
-bool NuvieEngine::isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) {
+bool NuvieEngine::isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) {
 	folder = "ultima6";
 	majorVersion = 1;
 	minorVersion = 1;
@@ -213,10 +213,10 @@ void NuvieEngine::assignGameConfigValues(uint8 gameType) {
 }
 
 bool NuvieEngine::checkGameDir(uint8 gameType) {
-	Std::string path;
+	Common::Path path;
 
 	config_get_path(_config, "", path);
-	ConsoleAddInfo("gamedir: \"%s\"", path.c_str());
+	ConsoleAddInfo("gamedir: \"%s\"", path.toString().c_str());
 
 	return true;
 }
diff --git a/engines/ultima/nuvie/nuvie.h b/engines/ultima/nuvie/nuvie.h
index 5cfc2657a8e..ea074619d00 100644
--- a/engines/ultima/nuvie/nuvie.h
+++ b/engines/ultima/nuvie/nuvie.h
@@ -63,7 +63,7 @@ protected:
 	/**
 	 * Returns the data archive folder and version that's required
 	 */
-	bool isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) override;
+	bool isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) override;
 public:
 	const Std::string c_empty_string;
 public:
diff --git a/engines/ultima/nuvie/portraits/portrait_md.cpp b/engines/ultima/nuvie/portraits/portrait_md.cpp
index d6f2887dc4b..22f381c396a 100644
--- a/engines/ultima/nuvie/portraits/portrait_md.cpp
+++ b/engines/ultima/nuvie/portraits/portrait_md.cpp
@@ -38,7 +38,7 @@ namespace Ultima {
 namespace Nuvie {
 
 bool PortraitMD::init() {
-	Std::string filename;
+	Common::Path filename;
 
 	avatar_portrait_num = 0;
 
@@ -47,7 +47,7 @@ bool PortraitMD::init() {
 
 	config_get_path(config, "mdfaces.lzc", filename);
 	if (faces.open(filename, 4) == false) {
-		ConsoleAddError("Opening " + filename);
+		ConsoleAddError("Opening " + filename.toString());
 		return false;
 	}
 
@@ -110,7 +110,7 @@ unsigned char *PortraitMD::get_portrait_data(Actor *actor) {
 U6Shape *PortraitMD::get_background_shape(uint8 actor_num) {
 	U6Lib_n file;
 	U6Shape *bg = new U6Shape();
-	Std::string filename;
+	Common::Path filename;
 	config_get_path(config, "mdback.lzc", filename);
 	file.open(filename, 4, NUVIE_GAME_MD);
 	unsigned char *temp_buf = file.get_item(get_background_shape_num(actor_num));
diff --git a/engines/ultima/nuvie/portraits/portrait_se.cpp b/engines/ultima/nuvie/portraits/portrait_se.cpp
index 2b75632143f..7757b30ecc9 100644
--- a/engines/ultima/nuvie/portraits/portrait_se.cpp
+++ b/engines/ultima/nuvie/portraits/portrait_se.cpp
@@ -37,7 +37,7 @@ namespace Ultima {
 namespace Nuvie {
 
 bool PortraitSE::init() {
-	Std::string filename;
+	Common::Path filename;
 
 	avatar_portrait_num = 0;
 
@@ -46,7 +46,7 @@ bool PortraitSE::init() {
 
 	config_get_path(config, "faces.lzc", filename);
 	if (faces.open(filename, 4) == false) {
-		ConsoleAddError("Opening " + filename);
+		ConsoleAddError("Opening " + filename.toString());
 		return false;
 	}
 
@@ -78,7 +78,7 @@ uint8 PortraitSE::get_portrait_num(Actor *actor) const {
 U6Shape *PortraitSE::get_background_shape(Actor *actor) {
 	U6Lib_n file;
 	U6Shape *bg = new U6Shape();
-	Std::string filename;
+	Common::Path filename;
 	config_get_path(config, "bkgrnd.lzc", filename);
 	file.open(filename, 4, NUVIE_GAME_MD);
 	unsigned char *temp_buf = file.get_item(get_background_shape_num(actor));
diff --git a/engines/ultima/nuvie/portraits/portrait_u6.cpp b/engines/ultima/nuvie/portraits/portrait_u6.cpp
index d0ae1f6c4e3..c23fc472ca0 100644
--- a/engines/ultima/nuvie/portraits/portrait_u6.cpp
+++ b/engines/ultima/nuvie/portraits/portrait_u6.cpp
@@ -49,7 +49,7 @@ namespace Nuvie {
 
 
 bool PortraitU6::init() {
-	Std::string filename;
+	Common::Path filename;
 
 	avatar_portrait_num = 0;
 
@@ -58,17 +58,17 @@ bool PortraitU6::init() {
 
 	config_get_path(config, "portrait.a", filename);
 	if (portrait_a.open(filename, 4) == false) {
-		ConsoleAddError("Opening " + filename);
+		ConsoleAddError("Opening " + filename.toString());
 		return false;
 	}
 	config_get_path(config, "portrait.b", filename);
 	if (portrait_b.open(filename, 4) == false) {
-		ConsoleAddError("Opening " + filename);
+		ConsoleAddError("Opening " + filename.toString());
 		return false;
 	}
 	config_get_path(config, "portrait.z", filename);
 	if (portrait_z.open(filename, 4) == false) {
-		ConsoleAddError("Opening " + filename);
+		ConsoleAddError("Opening " + filename.toString());
 		return false;
 	}
 
diff --git a/engines/ultima/nuvie/save/save_game.cpp b/engines/ultima/nuvie/save/save_game.cpp
index 6b9e3ff24e7..617d2126791 100644
--- a/engines/ultima/nuvie/save/save_game.cpp
+++ b/engines/ultima/nuvie/save/save_game.cpp
@@ -80,7 +80,7 @@ void SaveGame::init(ObjManager *obj_manager) {
 
 
 bool SaveGame::load_new() {
-	Std::string filename;
+	Common::Path filename;
 	U6Lzw lzw;
 	NuvieIOBuffer buf;
 	uint32 decomp_size;
@@ -135,7 +135,8 @@ bool SaveGame::load_new() {
 }
 
 bool SaveGame::load_original() {
-	Std::string path, objlist_filename, objblk_filename;
+	Std::string objblk_filename;
+	Common::Path path, objlist_filename;
 	char x, y;
 	uint16 len;
 	NuvieIOFileRead objlist_file;
@@ -210,7 +211,7 @@ bool SaveGame::transfer_character() {
 	Common::FSNode folder = dialog.getResult();
 
 	// TODO: Load in character data from given folder and start new game
-	g_engine->GUIError(Common::String::format("Load party file from folder - %s", folder.getPath().c_str()));
+	g_engine->GUIError(Common::String::format("Load party file from folder - %s", folder.getPath().toString(Common::Path::kNativeSeparator).c_str()));
 
 	return false;
 }
diff --git a/engines/ultima/nuvie/screen/dither.cpp b/engines/ultima/nuvie/screen/dither.cpp
index 278b9b3c5fe..b95872458d6 100644
--- a/engines/ultima/nuvie/screen/dither.cpp
+++ b/engines/ultima/nuvie/screen/dither.cpp
@@ -45,7 +45,7 @@ Dither::~Dither() {
 }
 
 bool Dither::load_data() {
-	Std::string path;
+	Common::Path path;
 	NuvieIOFileRead file;
 
 	config_get_path(config, "dither", path);
diff --git a/engines/ultima/nuvie/screen/game_palette.cpp b/engines/ultima/nuvie/screen/game_palette.cpp
index 017025ecc62..f8819f304df 100644
--- a/engines/ultima/nuvie/screen/game_palette.cpp
+++ b/engines/ultima/nuvie/screen/game_palette.cpp
@@ -51,7 +51,7 @@ void GamePalette::set_palette() {
 
 bool GamePalette::loadPalette() {
 	uint16 i, j;
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead file;
 	Std::string game_name, game_id, pal_name;
 
@@ -107,7 +107,7 @@ bool GamePalette::loadPalette() {
 
 bool GamePalette::loadPaletteIntoBuffer(unsigned char *pal) {
 	uint16 i, j;
-	Std::string filename;
+	Common::Path filename;
 	NuvieIOFileRead file;
 	Std::string game_name, game_id, pal_name;
 
diff --git a/engines/ultima/nuvie/script/script.cpp b/engines/ultima/nuvie/script/script.cpp
index a8d79669c6e..6bb7f1855c4 100644
--- a/engines/ultima/nuvie/script/script.cpp
+++ b/engines/ultima/nuvie/script/script.cpp
@@ -882,8 +882,10 @@ Script::~Script() {
 }
 
 bool Script::init() {
-	Std::string dir, path;
-	config->value("config/datadir", dir, "");
+	Std::string tmp;
+	Common::Path dir, path;
+	config->value("config/datadir", tmp, "");
+	dir = Common::Path(tmp);
 	build_path(dir, "scripts", path);
 	dir = path;
 
@@ -902,7 +904,7 @@ bool Script::init() {
 
 	if (run_script(init_str.c_str()) == false) {
 		Std::string errorStr = "Loading ";
-		errorStr.append(path);
+		errorStr.append(path.toString());
 		ConsoleAddError(errorStr);
 		return false;
 	}
@@ -1389,19 +1391,20 @@ ScriptThread *Script::call_function_in_thread(const char *function_name) {
 }
 
 bool Script::run_lua_file(const char *filename) {
-	Std::string dir, path;
-	Script::get_script()->get_config()->value("config/datadir", dir, "");
+	Std::string tmp;
+	Script::get_script()->get_config()->value("config/datadir", tmp, "");
 
+	Common::Path dir(tmp), path;
 	build_path(dir, "scripts", path);
 	dir = path;
 	build_path(dir, filename, path);
 
-	if (luaL_loadfile(L, path.c_str()) != 0) {
-		DEBUG(0, LEVEL_ERROR, "loading script file %s", path.c_str());
+	if (luaL_loadfile(L, path.toString(Common::Path::kNativeSeparator).c_str()) != 0) {
+		DEBUG(0, LEVEL_ERROR, "loading script file %s", path.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
-	return call_function(path.c_str(), 0, 0);
+	return call_function(path.toString(Common::Path::kNativeSeparator).c_str(), 0, 0);
 }
 
 bool Script::call_moonstone_set_loc(uint8 phase, MapCoord location) {
@@ -2351,16 +2354,18 @@ static int nscript_display_prompt(lua_State *L) {
  */
 static int nscript_load(lua_State *L) {
 	const char *file = luaL_checkstring(L, 1);
-	string dir;
-	string path;
+	string tmp;
+	Common::Path dir;
+	Common::Path path;
 
-	Script::get_script()->get_config()->value("config/datadir", dir, "");
+	Script::get_script()->get_config()->value("config/datadir", tmp, "");
+	dir = Common::Path(tmp);
 
 	build_path(dir, "scripts", path);
 	dir = path;
 	build_path(dir, file, path);
 
-	if (luaL_loadfile(L, path.c_str()) == LUA_ERRFILE) {
+	if (luaL_loadfile(L, path.toString(Common::Path::kNativeSeparator).c_str()) == LUA_ERRFILE) {
 		lua_pop(L, 1);
 		return 0;
 	}
@@ -3220,19 +3225,19 @@ static int nscript_tileset_export(lua_State *L) {
 		overwriteFile = (bool)lua_toboolean(L, 1);
 	}
 
-	Std::string path;
+	Common::Path path;
 	path = "data";
 	build_path(path, "images", path);
 	build_path(path, "tiles", path);
 	build_path(path, get_game_tag(game->get_game_type()), path);
 
-	if (!directory_exists(path.c_str())) {
+	if (!directory_exists(path)) {
 		mkdir_recursive(path, 0700);
 	}
 
 	build_path(path, "custom_tiles.bmp", path);
 
-	if (!overwriteFile && file_exists(path.c_str())) {
+	if (!overwriteFile && file_exists(path)) {
 		lua_pushboolean(L, false);
 	} else {
 		game->get_tile_manager()->exportTilesetToBmpFile(path, false);
@@ -4595,7 +4600,7 @@ static int nscript_load_text_from_lzc(lua_State *L) {
 	Std::string filename(lua_tostring(L, 1));
 	U6Lib_n lib_n;
 
-	Std::string path;
+	Common::Path path;
 
 	config_get_path(Game::get_game()->get_config(), filename, path);
 
diff --git a/engines/ultima/nuvie/script/script_cutscene.cpp b/engines/ultima/nuvie/script/script_cutscene.cpp
index ea526bf3ab3..075ae343471 100644
--- a/engines/ultima/nuvie/script/script_cutscene.cpp
+++ b/engines/ultima/nuvie/script/script_cutscene.cpp
@@ -1106,18 +1106,18 @@ ScriptCutscene::ScriptCutscene(GUI *g, Configuration *cfg, SoundManager *sm) : G
 	sound_manager = sm;
 
 	//FIXME this should be loaded by script.
-	Std::string path;
+	Common::Path path;
 
 
 	font = new WOUFont();
 
 	if (game_type == NUVIE_GAME_U6) {
 		config_get_path(config, "u6.set", path);
-		font->init(path.c_str());
+		font->init(path);
 	}
 	//FIXME load other fonts for MD / SE if needed here.
 	if (game_type == NUVIE_GAME_SE) {
-		Std::string filePath;
+		Common::Path filePath;
 		U6Lib_n lib_file;
 
 		config_get_path(config, "savage.fnt", filePath);
@@ -1129,7 +1129,7 @@ ScriptCutscene::ScriptCutscene(GUI *g, Configuration *cfg, SoundManager *sm) : G
 	}
 
 	if (game_type == NUVIE_GAME_MD) {
-		Std::string filePath;
+		Common::Path filePath;
 		U6Lib_n lib_file;
 
 		config_get_path(config, "fonts.lzc", filePath);
@@ -1160,7 +1160,7 @@ bool ScriptCutscene::is_lzc(const char *filename) {
 	return false;
 }
 
-CSImage *ScriptCutscene::load_image_from_lzc(Std::string filename, uint16 idx, uint16 sub_idx) {
+CSImage *ScriptCutscene::load_image_from_lzc(const Common::Path &filename, uint16 idx, uint16 sub_idx) {
 	CSImage *image = nullptr;
 	U6Lib_n lib_n;
 	unsigned char *buf = nullptr;
@@ -1195,7 +1195,7 @@ CSImage *ScriptCutscene::load_image_from_lzc(Std::string filename, uint16 idx, u
 
 CSImage *ScriptCutscene::load_image(const char *filename, int idx, int sub_idx) {
 	U6Lib_n lib_n;
-	Std::string path;
+	Common::Path path;
 	CSImage *image = nullptr;
 
 	config_get_path(config, filename, path);
@@ -1210,7 +1210,7 @@ CSImage *ScriptCutscene::load_image(const char *filename, int idx, int sub_idx)
 		U6Lzw lzw;
 
 		uint32 decomp_size;
-		unsigned char *buf = lzw.decompress_file(path.c_str(), decomp_size);
+		unsigned char *buf = lzw.decompress_file(path, decomp_size);
 		NuvieIOBuffer io;
 		io.open(buf, decomp_size, false);
 		{
@@ -1236,7 +1236,7 @@ CSImage *ScriptCutscene::load_image(const char *filename, int idx, int sub_idx)
 }
 
 Std::vector<Std::vector<CSImage *> > ScriptCutscene::load_all_images(const char *filename) {
-	Std::string path;
+	Common::Path path;
 	CSImage *image = nullptr;
 
 	config_get_path(config, filename, path);
@@ -1272,7 +1272,7 @@ Std::vector<Std::vector<CSImage *> > ScriptCutscene::load_all_images(const char
 		}
 	} else {
 		uint32 decomp_size;
-		buf = lzw.decompress_file(path.c_str(), decomp_size);
+		buf = lzw.decompress_file(path, decomp_size);
 		if (!buf) // failed to open or decompress
 			return v;
 		NuvieIOBuffer io;
@@ -1323,7 +1323,7 @@ void load_images_from_lib(Std::vector<CSImage *> *images, U6Lib_n *lib, uint32 i
 }
 
 Std::vector<CSMidGameData> ScriptCutscene::load_midgame_file(const char *filename) {
-	Std::string path;
+	Common::Path path;
 	U6Lib_n lib_n;
 	Std::vector<CSMidGameData> v;
 	nuvie_game_t game_type = Game::get_game()->get_game_type();
@@ -1360,7 +1360,7 @@ Std::vector<CSMidGameData> ScriptCutscene::load_midgame_file(const char *filenam
 }
 
 Std::vector<Std::string> ScriptCutscene::load_text(const char *filename, uint8 idx) {
-	Std::string path;
+	Common::Path path;
 	U6Lib_n lib_n;
 	Std::vector<string> v;
 	unsigned char *buf = nullptr;
@@ -1452,12 +1452,12 @@ void ScriptCutscene::load_palette(const char *filename, int idx) {
 	NuvieIOFileRead file;
 	uint8 buf[0x240 + 1];
 	uint8 unpacked_palette[0x300];
-	Std::string path;
+	Common::Path path;
 
 	config_get_path(config, filename, path);
 
 
-	if (file.open(path.c_str()) == false) {
+	if (file.open(path) == false) {
 		DEBUG(0, LEVEL_ERROR, "loading palette.\n");
 		return;
 	}
diff --git a/engines/ultima/nuvie/script/script_cutscene.h b/engines/ultima/nuvie/script/script_cutscene.h
index 5a6ef5e642d..9a2fb5cb5ae 100644
--- a/engines/ultima/nuvie/script/script_cutscene.h
+++ b/engines/ultima/nuvie/script/script_cutscene.h
@@ -201,7 +201,7 @@ public:
 
 private:
 	bool is_lzc(const char *filename);
-	CSImage *load_image_from_lzc(Std::string filename, uint16 idx, uint16 sub_idx);
+	CSImage *load_image_from_lzc(const Common::Path &filename, uint16 idx, uint16 sub_idx);
 	void display_wrapped_text(CSSprite *s);
 	int display_wrapped_text_line(Std::string str, uint8 text_color, int x, int y, uint8 align_val);
 };
diff --git a/engines/ultima/nuvie/sound/adplug/adplug_player.h b/engines/ultima/nuvie/sound/adplug/adplug_player.h
index 8da447cb4eb..6ff4efdec33 100644
--- a/engines/ultima/nuvie/sound/adplug/adplug_player.h
+++ b/engines/ultima/nuvie/sound/adplug/adplug_player.h
@@ -25,6 +25,10 @@
 #include "ultima/shared/std/string.h"
 #include "ultima/nuvie/sound/adplug/opl.h"
 
+namespace Common {
+class Path;
+}
+
 namespace Ultima {
 namespace Nuvie {
 
@@ -36,7 +40,7 @@ public:
 	/***** Operational methods *****/
 	void seek(unsigned long ms);
 
-	virtual bool load(const Std::string &filename) = 0; // loads file
+	virtual bool load(const Common::Path &filename) = 0; // loads file
 	virtual bool update() = 0;          // executes replay code for 1 tick
 	virtual void rewind(int subsong = -1) = 0;  // rewinds to specified subsong
 	virtual float getrefresh() = 0;         // returns needed timer refresh rate
diff --git a/engines/ultima/nuvie/sound/adplug/mid.cpp b/engines/ultima/nuvie/sound/adplug/mid.cpp
index 3a0f97d85b7..ae1b6736812 100644
--- a/engines/ultima/nuvie/sound/adplug/mid.cpp
+++ b/engines/ultima/nuvie/sound/adplug/mid.cpp
@@ -112,11 +112,11 @@ unsigned long CmidPlayer::getval() {
 	return v;
 }
 
-bool CmidPlayer::load(const Std::string &filename) {
+bool CmidPlayer::load(const Common::Path &filename) {
 	return false;
 }
 
-bool CmidPlayer::load(Std::string &filename, int song_index) {
+bool CmidPlayer::load(const Common::Path &filename, int song_index) {
 	U6Lib_n f;
 	f.open(filename, 4, NUVIE_GAME_MD);
 	//binistream *f = fp.open(filename); if(!f) return false;
diff --git a/engines/ultima/nuvie/sound/adplug/mid.h b/engines/ultima/nuvie/sound/adplug/mid.h
index 6c956f85f9b..d38675ced5b 100644
--- a/engines/ultima/nuvie/sound/adplug/mid.h
+++ b/engines/ultima/nuvie/sound/adplug/mid.h
@@ -33,8 +33,8 @@ public:
 	CmidPlayer(Copl *newopl);
 	~CmidPlayer() override;
 
-	bool load(const Std::string &filename) override;
-	bool load(Std::string &filename, int song_index);
+	bool load(const Common::Path &filename) override;
+	bool load(const Common::Path &filename, int song_index);
 	//bool load(const Std::string &filename, const CFileProvider &fp);
 	bool update() override;
 	void rewind(int subsong) override;
diff --git a/engines/ultima/nuvie/sound/adplug/u6m.cpp b/engines/ultima/nuvie/sound/adplug/u6m.cpp
index eb26436ff93..77728e7e8be 100644
--- a/engines/ultima/nuvie/sound/adplug/u6m.cpp
+++ b/engines/ultima/nuvie/sound/adplug/u6m.cpp
@@ -35,7 +35,7 @@ CPlayer *Cu6mPlayer::factory(Copl *newopl) {
 	return new Cu6mPlayer(newopl);
 }
 
-bool Cu6mPlayer::load(const Std::string &filename) {
+bool Cu6mPlayer::load(const Common::Path &filename) {
 	uint32 decompressed_filesize;
 	U6Lzw lzw;
 
diff --git a/engines/ultima/nuvie/sound/adplug/u6m.h b/engines/ultima/nuvie/sound/adplug/u6m.h
index cb81812b489..9a3be0ff851 100644
--- a/engines/ultima/nuvie/sound/adplug/u6m.h
+++ b/engines/ultima/nuvie/sound/adplug/u6m.h
@@ -41,7 +41,7 @@ public:
 
 
 
-	bool load(const Std::string &filename) override;
+	bool load(const Common::Path &filename) override;
 	bool update() override;
 	void rewind(int subsong) override;
 	float getrefresh() override;
diff --git a/engines/ultima/nuvie/sound/custom_sfx_manager.cpp b/engines/ultima/nuvie/sound/custom_sfx_manager.cpp
index e13a51ddafb..ffbaf33934e 100644
--- a/engines/ultima/nuvie/sound/custom_sfx_manager.cpp
+++ b/engines/ultima/nuvie/sound/custom_sfx_manager.cpp
@@ -32,7 +32,7 @@ namespace Ultima {
 namespace Nuvie {
 
 CustomSfxManager::CustomSfxManager(const Configuration *cfg, Audio::Mixer *m) : SfxManager(cfg, m) {
-	Std::string cfg_filename;
+	Common::Path cfg_filename;
 
 	sfx_map = new Common::HashMap<uint16, uint16>();
 
@@ -48,7 +48,7 @@ CustomSfxManager::~CustomSfxManager() {
 }
 
 
-bool CustomSfxManager::loadSfxMapFile(Std::string cfg_filename, Common::HashMap<uint16, uint16> *m) {
+bool CustomSfxManager::loadSfxMapFile(const Common::Path &cfg_filename, Common::HashMap<uint16, uint16> *m) {
 	char seps[] = ";\r\n";
 	char *token1;
 	char *token2;
@@ -56,7 +56,7 @@ bool CustomSfxManager::loadSfxMapFile(Std::string cfg_filename, Common::HashMap<
 	char *sz;
 
 	if (niof.open(cfg_filename) == false) {
-		DEBUG(0, LEVEL_ERROR, "Failed to open '%s'", cfg_filename.c_str());
+		DEBUG(0, LEVEL_ERROR, "Failed to open '%s'", cfg_filename.toString().c_str());
 		return false;
 	}
 
@@ -98,7 +98,7 @@ bool CustomSfxManager::playSfxLooping(SfxIdType sfx_id, Audio::SoundHandle *hand
 void CustomSfxManager::playSoundSample(uint16 sample_num, Audio::SoundHandle *looping_handle, uint8 volume) {
 	Audio::AudioStream *stream = nullptr;
 	Audio::SoundHandle handle;
-	Std::string filename;
+	Common::Path filename;
 	char wavefile[10]; // "nnnnn.wav\0"
 
 	Common::sprintf_s(wavefile, "%d.wav", sample_num);
@@ -107,7 +107,7 @@ void CustomSfxManager::playSoundSample(uint16 sample_num, Audio::SoundHandle *lo
 
 	Common::File *readStream = new Common::File();
 	if (!readStream->open(filename)) {
-		DEBUG(0, LEVEL_ERROR, "Failed to open '%s'", filename.c_str());
+		DEBUG(0, LEVEL_ERROR, "Failed to open '%s'", filename.toString().c_str());
 		delete readStream;
 		return;
 	}
diff --git a/engines/ultima/nuvie/sound/custom_sfx_manager.h b/engines/ultima/nuvie/sound/custom_sfx_manager.h
index 9be0d0c3a00..321de5b6c12 100644
--- a/engines/ultima/nuvie/sound/custom_sfx_manager.h
+++ b/engines/ultima/nuvie/sound/custom_sfx_manager.h
@@ -43,10 +43,10 @@ public:
 	void playSoundSample(uint16 sample_num, Audio::SoundHandle *looping_handle, uint8 volume);
 
 private:
-	bool loadSfxMapFile(Std::string cfg_filename, Common::HashMap<uint16, uint16> *m);
+	bool loadSfxMapFile(const Common::Path &cfg_filename, Common::HashMap<uint16, uint16> *m);
 
 private:
-	Std::string custom_filepath;
+	Common::Path custom_filepath;
 
 	Common::HashMap<uint16, uint16> *sfx_map;
 };
diff --git a/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.cpp b/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.cpp
index 039bd5c0a49..c804c606584 100644
--- a/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.cpp
+++ b/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.cpp
@@ -35,7 +35,7 @@ FMtownsDecoderStream::FMtownsDecoderStream(unsigned char *buf, uint32 len) {
 	should_free_raw_data = false;
 }
 
-FMtownsDecoderStream::FMtownsDecoderStream(Std::string filename, uint16 sample_num, bool isCompressed) {
+FMtownsDecoderStream::FMtownsDecoderStream(const Common::Path &filename, uint16 sample_num, bool isCompressed) {
 	unsigned char *item_data;
 	uint32 decomp_size;
 	U6Lib_n sam_file;
diff --git a/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.h b/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.h
index 1d13addd35b..1705ffd8256 100644
--- a/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.h
+++ b/engines/ultima/nuvie/sound/decoder/fm_towns_decoder_stream.h
@@ -20,7 +20,6 @@
  */
 
 #include "ultima/nuvie/sound/decoder/random_collection_audio_stream.h"
-#include "ultima/shared/std/string.h"
 
 namespace Ultima {
 namespace Nuvie {
@@ -29,8 +28,6 @@ class U6Lib_n;
 class U6Lzw;
 class NuvieIOBuffer;
 
-using Std::string;
-
 class FMtownsDecoderStream : public Audio::RewindableAudioStream {
 public:
 	FMtownsDecoderStream() {
@@ -39,7 +36,7 @@ public:
 	}
 
 	FMtownsDecoderStream(unsigned char *buf, uint32 len);
-	FMtownsDecoderStream(Std::string filename, uint16 sample_num, bool isCompressed = true);
+	FMtownsDecoderStream(const Common::Path &filename, uint16 sample_num, bool isCompressed = true);
 	~FMtownsDecoderStream() override;
 
 	uint32 getLengthInMsec();
diff --git a/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.cpp b/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.cpp
index 5bf94645b69..fb91b5b9b17 100644
--- a/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.cpp
+++ b/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.cpp
@@ -27,17 +27,17 @@
 namespace Ultima {
 namespace Nuvie {
 
-U6AdPlugDecoderStream::U6AdPlugDecoderStream(CEmuopl *o, Std::string filename, uint16 song_num) {
+U6AdPlugDecoderStream::U6AdPlugDecoderStream(CEmuopl *o, const Common::Path &filename, uint16 song_num) {
 	is_midi_track = false;
 	opl = o;
 	samples_left = 0;
-	if (has_file_extension(filename.c_str(), ".lzc")) {
+	if (has_file_extension(filename.baseName().c_str(), ".lzc")) {
 		player = new CmidPlayer(opl);
 		((CmidPlayer *)player)->load(filename, song_num);
 		is_midi_track = true;
 	} else {
 		player = new Cu6mPlayer(opl);
-		player->load(filename.c_str());
+		player->load(filename);
 	}
 	player_refresh_count = (int)(opl->getRate() / player->getrefresh());
 
diff --git a/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.h b/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.h
index 1b5852a8090..0a6bf0cea05 100644
--- a/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.h
+++ b/engines/ultima/nuvie/sound/decoder/u6_adplug_decoder_stream.h
@@ -43,7 +43,7 @@ public:
 		player_refresh_count = 0;
 	}
 
-	U6AdPlugDecoderStream(CEmuopl *o, Std::string filename, uint16 song_num);
+	U6AdPlugDecoderStream(CEmuopl *o, const Common::Path &filename, uint16 song_num);
 	~U6AdPlugDecoderStream() override;
 
 	int readBuffer(sint16 *buffer, const int numSamples) override;
diff --git a/engines/ultima/nuvie/sound/origin_fx_adib_driver.cpp b/engines/ultima/nuvie/sound/origin_fx_adib_driver.cpp
index f633f9f6e24..ab76c97614a 100644
--- a/engines/ultima/nuvie/sound/origin_fx_adib_driver.cpp
+++ b/engines/ultima/nuvie/sound/origin_fx_adib_driver.cpp
@@ -88,7 +88,7 @@ sint16 OriginFXAdLibDriver::read_sint16(unsigned char *buf) {
 
 void OriginFXAdLibDriver::load_tim_file() {
 	U6Lib_n f;
-	Std::string filename;
+	Common::Path filename;
 
 	nuvie_game_t game_type = get_game_type(config);
 	if (game_type == NUVIE_GAME_SE) {
diff --git a/engines/ultima/nuvie/sound/song.h b/engines/ultima/nuvie/sound/song.h
index 15e852cb6bf..88276bc60df 100644
--- a/engines/ultima/nuvie/sound/song.h
+++ b/engines/ultima/nuvie/sound/song.h
@@ -30,10 +30,10 @@ namespace Nuvie {
 class Song : public Sound {
 public:
 
-	virtual bool Init(const char *filename, const char *fileId) {
+	virtual bool Init(const Common::Path &path, const char *fileId) {
 		return false;
 	}
-	virtual bool Init(const char *path, const char *fileId, uint16 songnum) {
+	virtual bool Init(const Common::Path &path, const char *fileId, uint16 songnum) {
 		return false;
 	}
 	bool Play(bool looping = false) override {
diff --git a/engines/ultima/nuvie/sound/song_adplug.cpp b/engines/ultima/nuvie/sound/song_adplug.cpp
index 1059b3c114f..4f03d5f9622 100644
--- a/engines/ultima/nuvie/sound/song_adplug.cpp
+++ b/engines/ultima/nuvie/sound/song_adplug.cpp
@@ -41,13 +41,13 @@ SongAdPlug::SongAdPlug(Audio::Mixer *m, CEmuopl *o) {
 SongAdPlug::~SongAdPlug() {
 }
 
-bool SongAdPlug::Init(const char *filename, const char *fileId, uint16 song_num) {
+bool SongAdPlug::Init(const Common::Path &filename, const char *fileId, uint16 song_num) {
 	if (filename == nullptr)
 		return false;
 
-	m_Filename = filename; // SB-X
+	m_Filename = filename.toString('/'); // SB-X
 
-	stream = new U6AdPlugDecoderStream(opl, string(filename), song_num);
+	stream = new U6AdPlugDecoderStream(opl, filename, song_num);
 
 	return true;
 }
diff --git a/engines/ultima/nuvie/sound/song_adplug.h b/engines/ultima/nuvie/sound/song_adplug.h
index 2a82b9c3a8b..b04623039c0 100644
--- a/engines/ultima/nuvie/sound/song_adplug.h
+++ b/engines/ultima/nuvie/sound/song_adplug.h
@@ -37,10 +37,10 @@ public:
 
 	SongAdPlug(Audio::Mixer *m, CEmuopl *o);
 	~SongAdPlug() override;
-	bool Init(const char *filename, const char *fileId) override {
-		return Init(filename, fileId, 0);
+	bool Init(const Common::Path &path, const char *fileId) override {
+		return Init(path, fileId, 0);
 	}
-	bool Init(const char *filename, const char *fileId, uint16 song_num) override;
+	bool Init(const Common::Path &path, const char *fileId, uint16 song_num) override;
 	bool Play(bool looping = false) override;
 	bool Stop() override;
 	bool SetVolume(uint8 volume) override;
diff --git a/engines/ultima/nuvie/sound/song_filename.cpp b/engines/ultima/nuvie/sound/song_filename.cpp
index c381165598d..6c8715962bb 100644
--- a/engines/ultima/nuvie/sound/song_filename.cpp
+++ b/engines/ultima/nuvie/sound/song_filename.cpp
@@ -32,15 +32,15 @@ namespace Nuvie {
 SongFilename::~SongFilename() {
 }
 
-bool SongFilename::Init(const char *path, const char *fileId) {
+bool SongFilename::Init(const Common::Path &path, const char *fileId) {
 	return Init(path, fileId, 0);
 }
 
-bool SongFilename::Init(const char *filename, const char *fileId, uint16 song_num) {
-	if (filename == nullptr)
+bool SongFilename::Init(const Common::Path &filename, const char *fileId, uint16 song_num) {
+	if (filename.empty())
 		return false;
 
-	m_Filename = filename; // SB-X
+	m_Filename = filename.toString(); // SB-X
 	m_FileId = fileId;
 
 	return true;
diff --git a/engines/ultima/nuvie/sound/song_filename.h b/engines/ultima/nuvie/sound/song_filename.h
index 687bb1196e4..626be37a592 100644
--- a/engines/ultima/nuvie/sound/song_filename.h
+++ b/engines/ultima/nuvie/sound/song_filename.h
@@ -30,8 +30,8 @@ namespace Nuvie {
 class SongFilename : public Song {
 public:
 	~SongFilename() override;
-	bool Init(const char *path, const char *fileId) override;
-	bool Init(const char *path, const char *fileId, uint16 song_num) override;
+	bool Init(const Common::Path &path, const char *fileId) override;
+	bool Init(const Common::Path &path, const char *fileId, uint16 song_num) override;
 	bool Play(bool looping = false) override;
 	bool Stop() override;
 	bool SetVolume(uint8 volume) override;
diff --git a/engines/ultima/nuvie/sound/sound.h b/engines/ultima/nuvie/sound/sound.h
index 4cdca37d72d..61b8908a9f0 100644
--- a/engines/ultima/nuvie/sound/sound.h
+++ b/engines/ultima/nuvie/sound/sound.h
@@ -50,6 +50,7 @@ public:
 		return m_FileId;
 	}
 protected:
+	// TODO: determine if filename should be a Common::Path
 	string m_Filename;
 	string m_Title;
 	string m_FileId;
diff --git a/engines/ultima/nuvie/sound/sound_manager.cpp b/engines/ultima/nuvie/sound/sound_manager.cpp
index 77d6b7d2f83..3cb29db0635 100644
--- a/engines/ultima/nuvie/sound/sound_manager.cpp
+++ b/engines/ultima/nuvie/sound/sound_manager.cpp
@@ -166,7 +166,7 @@ bool SoundManager::nuvieStartup(const Configuration *config) {
 		if (game_type == NUVIE_GAME_U6)
 			LoadNativeU6Songs(); //FIX need to handle MD & SE music too.
 	} else if (music_style == "custom")
-		LoadCustomSongs(sound_dir);
+		LoadCustomSongs(Common::Path(sound_dir));
 	else
 		DEBUG(0, LEVEL_WARNING, "Unknown music style '%s'\n", music_style.c_str());
 
@@ -240,70 +240,70 @@ bool SoundManager::initAudio() {
 bool SoundManager::LoadNativeU6Songs() {
 	Song *song;
 
-	string filename;
+	Common::Path filename;
 	string fileId;
 
 	fileId = "brit.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-// loadSong(song, filename.c_str());
-	loadSong(song, filename.c_str(), fileId.c_str(), "Rule Britannia");
+// loadSong(song, filename);
+	loadSong(song, filename, fileId.c_str(), "Rule Britannia");
 	groupAddSong("random", song);
 
 	fileId = "forest.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Wanderer (Forest)");
+	loadSong(song, filename, fileId.c_str(), "Wanderer (Forest)");
 	groupAddSong("random", song);
 
 	fileId = "stones.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Stones");
+	loadSong(song, filename, fileId.c_str(), "Stones");
 	groupAddSong("random", song);
 
 	fileId = "ultima.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Ultima VI Theme");
+	loadSong(song, filename, fileId.c_str(), "Ultima VI Theme");
 	groupAddSong("random", song);
 
 	fileId = "engage.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Engagement and Melee");
+	loadSong(song, filename, fileId.c_str(), "Engagement and Melee");
 	groupAddSong("combat", song);
 
 	fileId = "hornpipe.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Captain Johne's Hornpipe");
+	loadSong(song, filename, fileId.c_str(), "Captain Johne's Hornpipe");
 	groupAddSong("boat", song);
 
 	fileId = "gargoyle.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Audchar Gargl Zenmur");
+	loadSong(song, filename, fileId.c_str(), "Audchar Gargl Zenmur");
 	groupAddSong("gargoyle", song);
 
 	fileId = "dungeon.m";
 	config_get_path(m_Config, fileId, filename);
 	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Dungeon");
+	loadSong(song, filename, fileId.c_str(), "Dungeon");
 	groupAddSong("dungeon", song);
 
 	return true;
 }
 
-bool SoundManager::LoadCustomSongs(string sound_dir) {
+bool SoundManager::LoadCustomSongs(const Common::Path &sound_dir) {
 	char seps[] = ";\r\n";
 	char *token1;
 	char *token2;
 	char *sz;
 	NuvieIOFileRead niof;
 	Song *song;
-	Std::string scriptname;
-	Std::string filename;
+	Common::Path scriptname;
+	Common::Path filename;
 
 	build_path(sound_dir, "music.cfg", scriptname);
 
@@ -324,7 +324,7 @@ bool SoundManager::LoadCustomSongs(string sound_dir) {
 			// Note: the base class Song does not have an implementation for
 			// Init, so loading custom songs does not work.
 			song = new Song;
-			if (!loadSong(song, filename.c_str(), token2))
+			if (!loadSong(song, filename, token2))
 				continue; //error loading song
 		}
 
@@ -337,19 +337,19 @@ bool SoundManager::LoadCustomSongs(string sound_dir) {
 	return true;
 }
 
-bool SoundManager::loadSong(Song *song, const char *filename, const char *fileId) {
+bool SoundManager::loadSong(Song *song, const Common::Path &filename, const char *fileId) {
 	if (song->Init(filename, fileId)) {
 		m_Songs.push_back(song);       //add it to our global list
 		return true;
 	} else {
-		DEBUG(0, LEVEL_ERROR, "could not load %s\n", filename);
+		DEBUG(0, LEVEL_ERROR, "could not load %s\n", filename.toString().c_str());
 	}
 
 	return false;
 }
 
 // (SB-X)
-bool SoundManager::loadSong(Song *song, const char *filename, const char *fileId, const char *title) {
+bool SoundManager::loadSong(Song *song, const Common::Path &filename, const char *fileId, const char *title) {
 	if (loadSong(song, filename, fileId) == true) {
 		song->SetTitle(title);
 		return true;
@@ -574,7 +574,7 @@ void SoundManager::musicPlay() {
 		uint32 decompressed_filesize;
 		U6Lzw lzw;
 
-		_musicData = lzw.decompress_file(m_pCurrentSong->GetName(), decompressed_filesize);
+		_musicData = lzw.decompress_file(Common::Path(m_pCurrentSong->GetName()), decompressed_filesize);
 
 		bool result = _midiParser->loadMusic(_musicData, decompressed_filesize);
 		if (result) {
@@ -599,14 +599,14 @@ void SoundManager::musicPlay() {
 }
 
 void SoundManager::musicPlay(const char *filename, uint16 song_num) {
-	string path;
+	Common::Path path;
 
 	if (!music_enabled || !audio_enabled)
 		return;
 
 	config_get_path(m_Config, filename, path);
 	SongFilename *song = new SongFilename();
-	song->Init(path.c_str(), filename, song_num);
+	song->Init(path, filename, song_num);
 
 	Common::StackLock lock(_musicMutex);
 
@@ -824,7 +824,7 @@ Sound *SoundManager::RequestSong(const string &group) {
 	return nullptr;
 }
 
-Audio::SoundHandle SoundManager::playTownsSound(Std::string filename, uint16 sample_num) {
+Audio::SoundHandle SoundManager::playTownsSound(const Common::Path &filename, uint16 sample_num) {
 	FMtownsDecoderStream *stream = new FMtownsDecoderStream(filename, sample_num);
 	Audio::SoundHandle handle;
 	_mixer->playStream(Audio::Mixer::kSpeechSoundType, &handle, stream, -1);
diff --git a/engines/ultima/nuvie/sound/sound_manager.h b/engines/ultima/nuvie/sound/sound_manager.h
index 454ea1e8cf5..d9ec4470514 100644
--- a/engines/ultima/nuvie/sound/sound_manager.h
+++ b/engines/ultima/nuvie/sound/sound_manager.h
@@ -85,7 +85,7 @@ public:
 	void musicPlay(const char *filename, uint16 song_num = 0);
 
 	void musicStop(); // SB-X
-	Audio::SoundHandle playTownsSound(Std::string filename, uint16 sample_num);
+	Audio::SoundHandle playTownsSound(const Common::Path &filename, uint16 sample_num);
 	bool isSoundPLaying(Audio::SoundHandle handle);
 
 	bool playSfx(uint16 sfx_id, bool async = false);
@@ -129,10 +129,10 @@ public:
 	bool stop_music_on_group_change;
 
 private:
-	bool LoadCustomSongs(string scriptname);
+	bool LoadCustomSongs(const Common::Path &scriptname);
 	bool LoadNativeU6Songs();
-	bool loadSong(Song *song, const char *filename, const char *fileId);
-	bool loadSong(Song *song, const char *filename, const char *fileId, const char *title);
+	bool loadSong(Song *song, const Common::Path &filename, const char *fileId);
+	bool loadSong(Song *song, const Common::Path &filename, const char *fileId, const char *title);
 	bool groupAddSong(const char *group, Song *song);
 
 	//bool LoadObjectSamples(string sound_dir);
diff --git a/engines/ultima/nuvie/sound/towns_sfx_manager.cpp b/engines/ultima/nuvie/sound/towns_sfx_manager.cpp
index b221cd06496..e8e271b0eea 100644
--- a/engines/ultima/nuvie/sound/towns_sfx_manager.cpp
+++ b/engines/ultima/nuvie/sound/towns_sfx_manager.cpp
@@ -72,7 +72,7 @@ TownsSfxManager::~TownsSfxManager() {
 }
 
 void TownsSfxManager::loadSound1Dat() {
-	Std::string filename;
+	Common::Path filename;
 	U6Lzw decompressor;
 	U6Lib_n lib;
 	NuvieIOBuffer iobuf;
@@ -82,7 +82,7 @@ void TownsSfxManager::loadSound1Dat() {
 	unsigned char *slib32_data = decompressor.decompress_file(filename, slib32_len);
 
 	if (slib32_len == 0) {
-		error("Failed to load FM-Towns sound file %s", filename.c_str());
+		error("Failed to load FM-Towns sound file %s", filename.toString().c_str());
 		return;
 	}
 
@@ -90,7 +90,7 @@ void TownsSfxManager::loadSound1Dat() {
 	free(slib32_data);
 
 	if (!lib.open(&iobuf, 4)) {
-		error("Failed to load FM-Towns sound file %s", filename.c_str());
+		error("Failed to load FM-Towns sound file %s", filename.toString().c_str());
 		return;
 	}
 
diff --git a/engines/ultima/nuvie/sound/towns_sfx_manager.h b/engines/ultima/nuvie/sound/towns_sfx_manager.h
index dd3b09b43fc..11e4ed8f88a 100644
--- a/engines/ultima/nuvie/sound/towns_sfx_manager.h
+++ b/engines/ultima/nuvie/sound/towns_sfx_manager.h
@@ -48,7 +48,7 @@ public:
 	bool playSfxLooping(SfxIdType sfx_id, Audio::SoundHandle *handle, uint8 volume) override;
 
 private:
-	Std::string sounds2dat_filepath;
+	Common::Path sounds2dat_filepath;
 	TownsSampleData sounds1_dat[TOWNS_SFX_SOUNDS1_SIZE];
 	U6Audio::RandomCollectionAudioStream *fireStream;
 
diff --git a/engines/ultima/nuvie/views/container_view_gump.cpp b/engines/ultima/nuvie/views/container_view_gump.cpp
index 70c08160b66..180681821cd 100644
--- a/engines/ultima/nuvie/views/container_view_gump.cpp
+++ b/engines/ultima/nuvie/views/container_view_gump.cpp
@@ -55,9 +55,9 @@ bool ContainerViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, u
 
 	//actor = p->get_actor(p->get_leader()); don't have party leader as default, get owner of container obj or leave nullptr (moved to init_container_type)
 
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
+	Common::Path path;
 
 	build_path(datadir, "images", path);
 	datadir = path;
@@ -75,7 +75,7 @@ bool ContainerViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, u
 	return true;
 }
 
-void ContainerViewGump::init_container_type(Std::string datadir, Obj *obj_type) {
+void ContainerViewGump::init_container_type(const Common::Path &datadir, Obj *obj_type) {
 
 
 	if (obj_type != nullptr) {
@@ -105,24 +105,23 @@ void ContainerViewGump::init_container_type(Std::string datadir, Obj *obj_type)
 	return init_backpack(datadir, obj_type ? !obj_type->is_in_inventory() : true);
 }
 
-void ContainerViewGump::init_backpack(Std::string datadir, bool extend_area_w) {
-	Std::string imagefile, path;
+void ContainerViewGump::init_backpack(const Common::Path &datadir, bool extend_area_w) {
+	Common::Path imagefile, path;
 	uint8 check_y = 27;
 	gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
 
 	build_path(datadir, "container", path);
-	datadir = path;
 
-	up_arrow_button = loadButton(datadir, "cont_up", 83, 35);
-	down_arrow_button = loadButton(datadir, "cont_down", 83, 66);
+	up_arrow_button = loadButton(path, "cont_up", 83, 35);
+	down_arrow_button = loadButton(path, "cont_down", 83, 66);
 
-	build_path(datadir, "backpack_bg.bmp", imagefile);
+	build_path(path, "backpack_bg.bmp", imagefile);
 
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
-	doll_button = loadButton(datadir, "cont_doll", area.left + 18, area.top + bg_image->h);
-	left_arrow_button = loadButton(datadir, "cont_left", area.left + 18 + 11, area.top + bg_image->h);
-	right_arrow_button = loadButton(datadir, "cont_right", area.left + 18 + 22, area.top + bg_image->h);
+	doll_button = loadButton(path, "cont_doll", area.left + 18, area.top + bg_image->h);
+	left_arrow_button = loadButton(path, "cont_left", area.left + 18 + 11, area.top + bg_image->h);
+	right_arrow_button = loadButton(path, "cont_right", area.left + 18 + 22, area.top + bg_image->h);
 
 	SetRect(area.left, area.top, bg_image->w, bg_image->h + 16); //111, 101);
 
@@ -135,20 +134,19 @@ void ContainerViewGump::init_backpack(Std::string datadir, bool extend_area_w) {
 		area.right += 4;
 }
 
-void ContainerViewGump::init_chest(Std::string datadir) {
-	Std::string imagefile, path;
+void ContainerViewGump::init_chest(const Common::Path &datadir) {
+	Common::Path imagefile, path;
 	uint8 check_y = 56;
 	gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
 
 	build_path(datadir, "container", path);
-	datadir = path;
 
-	up_arrow_button = loadButton(datadir, "cont_up", 85, 31);
-	down_arrow_button = loadButton(datadir, "cont_down", 85, 47);
+	up_arrow_button = loadButton(path, "cont_up", 85, 31);
+	down_arrow_button = loadButton(path, "cont_down", 85, 47);
 
-	build_path(datadir, "chest_bg.bmp", imagefile);
+	build_path(path, "chest_bg.bmp", imagefile);
 
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
 	SetRect(area.left, area.top, bg_image->w, bg_image->h + 16); //111, 101);
 
@@ -159,20 +157,19 @@ void ContainerViewGump::init_chest(Std::string datadir) {
 	AddWidget(container_widget);
 }
 
-void ContainerViewGump::init_crate(Std::string datadir) {
-	Std::string imagefile, path;
+void ContainerViewGump::init_crate(const Common::Path &datadir) {
+	Common::Path imagefile, path;
 	uint8 check_y = 63;
 	gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
 
 	build_path(datadir, "container", path);
-	datadir = path;
 
-	up_arrow_button = loadButton(datadir, "cont_up", 100, 15);
-	down_arrow_button = loadButton(datadir, "cont_down", 100, 46);
+	up_arrow_button = loadButton(path, "cont_up", 100, 15);
+	down_arrow_button = loadButton(path, "cont_down", 100, 46);
 
-	build_path(datadir, "crate_bg.bmp", imagefile);
+	build_path(path, "crate_bg.bmp", imagefile);
 
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
 	SetRect(area.left, area.top, bg_image->w, bg_image->h);
 
@@ -183,20 +180,19 @@ void ContainerViewGump::init_crate(Std::string datadir) {
 	AddWidget(container_widget);
 }
 
-void ContainerViewGump::init_barrel(Std::string datadir) {
-	Std::string imagefile, path;
+void ContainerViewGump::init_barrel(const Common::Path &datadir) {
+	Common::Path imagefile, path;
 	uint8 check_y = 55;
 	gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
 
 	build_path(datadir, "container", path);
-	datadir = path;
 
-	up_arrow_button = loadButton(datadir, "cont_up", 102, 28);
-	down_arrow_button = loadButton(datadir, "cont_down", 102, 42);
+	up_arrow_button = loadButton(path, "cont_up", 102, 28);
+	down_arrow_button = loadButton(path, "cont_down", 102, 42);
 
-	build_path(datadir, "barrel_bg.bmp", imagefile);
+	build_path(path, "barrel_bg.bmp", imagefile);
 
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
 	SetRect(area.left, area.top, bg_image->w, bg_image->h);
 
@@ -207,20 +203,19 @@ void ContainerViewGump::init_barrel(Std::string datadir) {
 	AddWidget(container_widget);
 }
 
-void ContainerViewGump::init_corpse(Std::string datadir, Std::string bg_filename) {
-	Std::string imagefile, path;
+void ContainerViewGump::init_corpse(const Common::Path &datadir, Std::string bg_filename) {
+	Common::Path imagefile, path;
 	uint8 check_y = 25;
 	gump_button = loadButton(datadir, "gump", CHECK_X, check_y);
 
 	build_path(datadir, "container", path);
-	datadir = path;
 
 	up_arrow_button = loadButton(datadir, "cont_up", 67, 28);
 	down_arrow_button = loadButton(datadir, "cont_down", 67, 78);
 
-	build_path(datadir, bg_filename, imagefile);
+	build_path(path, bg_filename, imagefile);
 
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
 	SetRect(area.left, area.top, bg_image->w, bg_image->h);
 
diff --git a/engines/ultima/nuvie/views/container_view_gump.h b/engines/ultima/nuvie/views/container_view_gump.h
index 41c51b62c31..b83d3b81681 100644
--- a/engines/ultima/nuvie/views/container_view_gump.h
+++ b/engines/ultima/nuvie/views/container_view_gump.h
@@ -91,12 +91,12 @@ public:
 	GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
 protected:
 
-	void init_container_type(Std::string datadir, Obj *obj_type);
-	void init_backpack(Std::string datadir, bool extend_area_w);
-	void init_chest(Std::string datadir);
-	void init_crate(Std::string datadir);
-	void init_barrel(Std::string datadir);
-	void init_corpse(Std::string datadir, Std::string bg_filename);
+	void init_container_type(const Common::Path &datadir, Obj *obj_type);
+	void init_backpack(const Common::Path &datadir, bool extend_area_w);
+	void init_chest(const Common::Path &datadir);
+	void init_crate(const Common::Path &datadir);
+	void init_barrel(const Common::Path &datadir);
+	void init_corpse(const Common::Path &datadir, Std::string bg_filename);
 	void display_inventory_weight();
 
 	void left_arrow();
diff --git a/engines/ultima/nuvie/views/doll_view_gump.cpp b/engines/ultima/nuvie/views/doll_view_gump.cpp
index df5b6989183..012660264ab 100644
--- a/engines/ultima/nuvie/views/doll_view_gump.cpp
+++ b/engines/ultima/nuvie/views/doll_view_gump.cpp
@@ -63,9 +63,9 @@ bool DollViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16
 
 	AddWidget(doll_widget);
 
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
+	Common::Path path;
 
 	Graphics::ManagedSurface *image, *image1;
 
@@ -77,15 +77,15 @@ bool DollViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16
 	gump_button = loadButton(datadir, "gump", 0, 112);
 
 	build_path(datadir, "left_arrow.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
+	image1 = SDL_LoadBMP(imagefile);
 
 	left_button = new GUI_Button(this, 23, 7, image, image1, this);
 	this->AddWidget(left_button);
 
 	build_path(datadir, "right_arrow.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
+	image1 = SDL_LoadBMP(imagefile);
 
 	right_button = new GUI_Button(this, 86, 7, image, image1, this);
 	this->AddWidget(right_button);
@@ -94,14 +94,14 @@ bool DollViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16
 	datadir = path;
 
 	build_path(datadir, "doll_bg.bmp", imagefile);
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
 	set_bg_color_key(0, 0x70, 0xfc);
 
 	build_path(datadir, "combat_btn_up.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
 	build_path(datadir, "combat_btn_down.bmp", imagefile);
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image1 = SDL_LoadBMP(imagefile);
 
 	combat_button = new GUI_Button(nullptr, 23, 92, image, image1, this);
 	this->AddWidget(combat_button);
diff --git a/engines/ultima/nuvie/views/doll_widget.cpp b/engines/ultima/nuvie/views/doll_widget.cpp
index a4c534d77e8..e3f45d7ad32 100644
--- a/engines/ultima/nuvie/views/doll_widget.cpp
+++ b/engines/ultima/nuvie/views/doll_widget.cpp
@@ -187,7 +187,7 @@ void DollWidget::set_actor(Actor *a) {
 				actor_doll = vm->loadCustomActorDollImage(actor_doll, actor->get_actor_num(), true);
 			setColorKey(actor_doll);
 			if (actor_doll) {
-				Std::string imagefile;
+				Common::Path imagefile;
 				build_path(vm->getDollDataDirString(), "orig_style", imagefile);
 				build_path(imagefile, "doll_bg.bmp", imagefile);
 				NuvieBmpFile bmp;
@@ -215,7 +215,7 @@ void DollWidget::load_md_doll_shp() {
 
 	md_doll_shp = new U6Shape();
 	U6Lib_n file;
-	Std::string filename;
+	Common::Path filename;
 	config_get_path(config, "mdinv.lzc", filename);
 	file.open(filename, 4, NUVIE_GAME_MD);
 	uint8 num = actor->get_actor_num() + 1;
diff --git a/engines/ultima/nuvie/views/map_editor_view.cpp b/engines/ultima/nuvie/views/map_editor_view.cpp
index 74cec29fb85..51f8e132ade 100644
--- a/engines/ultima/nuvie/views/map_editor_view.cpp
+++ b/engines/ultima/nuvie/views/map_editor_view.cpp
@@ -50,8 +50,8 @@ bool MapEditorView::init(Screen *tmp_screen, void *view_manager, uint16 x, uint1
 	SetRect(area.left, area.top, 90, 200);
 	bg_color = 119;
 
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path path;
 
 	build_path(datadir, "images", path);
 	datadir = path;
diff --git a/engines/ultima/nuvie/views/md_sky_strip_widget.cpp b/engines/ultima/nuvie/views/md_sky_strip_widget.cpp
index 6e7a3b6e4a5..3fc4f1911b3 100644
--- a/engines/ultima/nuvie/views/md_sky_strip_widget.cpp
+++ b/engines/ultima/nuvie/views/md_sky_strip_widget.cpp
@@ -40,7 +40,7 @@ MDSkyStripWidget::~MDSkyStripWidget() {
 
 
 void MDSkyStripWidget::init(sint16 x, sint16 y) {
-	Std::string filename;
+	Common::Path filename;
 
 	GUI_Widget::Init(nullptr, x, y, 112, 11);
 	config_get_path(config, "mdscreen.lzc", filename);
diff --git a/engines/ultima/nuvie/views/portrait_view.cpp b/engines/ultima/nuvie/views/portrait_view.cpp
index 1e8ec0dc38f..f49f980d1b0 100644
--- a/engines/ultima/nuvie/views/portrait_view.cpp
+++ b/engines/ultima/nuvie/views/portrait_view.cpp
@@ -105,7 +105,7 @@ bool PortraitView::init(uint16 x, uint16 y, Font *f, Party *p, Player *player, T
 void PortraitView::load_background(const char *f, uint8 lib_offset) {
 	U6Lib_n file;
 	bg_data = new U6Shape();
-	Std::string path;
+	Common::Path path;
 	config_get_path(config, f, path);
 	file.open(path, 4, gametype);
 	unsigned char *temp_buf = file.get_item(lib_offset);
diff --git a/engines/ultima/nuvie/views/portrait_view_gump.cpp b/engines/ultima/nuvie/views/portrait_view_gump.cpp
index 7ffb8b4042b..5f932299761 100644
--- a/engines/ultima/nuvie/views/portrait_view_gump.cpp
+++ b/engines/ultima/nuvie/views/portrait_view_gump.cpp
@@ -56,9 +56,9 @@ bool PortraitViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, ui
 	portrait = por;
 	set_actor(a);
 
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
+	Common::Path path;
 
 	build_path(datadir, "images", path);
 	datadir = path;
@@ -68,7 +68,7 @@ bool PortraitViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, ui
 	gump_button = loadButton(datadir, "gump", 0, 67);
 
 	build_path(datadir, "portrait_bg.bmp", imagefile);
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
 	set_bg_color_key(0, 0x70, 0xfc);
 
@@ -78,15 +78,15 @@ bool PortraitViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, ui
 	Graphics::ManagedSurface *image, *image1;
 
 	build_path(datadir, "left_arrow.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
+	image1 = SDL_LoadBMP(imagefile);
 
 	left_button = new GUI_Button(this, 23, 6, image, image1, this);
 	this->AddWidget(left_button);
 
 	build_path(datadir, "right_arrow.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
+	image1 = SDL_LoadBMP(imagefile);
 
 	right_button = new GUI_Button(this, 166, 6, image, image1, this);
 	this->AddWidget(right_button);
diff --git a/engines/ultima/nuvie/views/sign_view_gump.cpp b/engines/ultima/nuvie/views/sign_view_gump.cpp
index 4e7a93de84c..f33e49a2fbd 100644
--- a/engines/ultima/nuvie/views/sign_view_gump.cpp
+++ b/engines/ultima/nuvie/views/sign_view_gump.cpp
@@ -36,9 +36,9 @@ static const int SIGN_BG_H = 101;
 SignViewGump::SignViewGump(const Configuration *cfg) : DraggableView(cfg), sign_text(nullptr) {
 	font = new BMPFont();
 
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
+	Common::Path path;
 
 	build_path(datadir, "images", path);
 	datadir = path;
@@ -71,9 +71,9 @@ bool SignViewGump::init(Screen *tmp_screen, void *view_manager, Font *f, Party *
 	View::init(x_off, y_off, f, p, tm, om);
 	SetRect(area.left, area.top, SIGN_BG_W, SIGN_BG_H);
 
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
+	Common::Path path;
 
 	build_path(datadir, "images", path);
 	datadir = path;
@@ -83,7 +83,7 @@ bool SignViewGump::init(Screen *tmp_screen, void *view_manager, Font *f, Party *
 	datadir = path;
 
 	build_path(datadir, "sign_bg.bmp", imagefile);
-	bg_image = SDL_LoadBMP(imagefile.c_str());
+	bg_image = SDL_LoadBMP(imagefile);
 
 	set_bg_color_key(0, 0x70, 0xfc);
 
diff --git a/engines/ultima/nuvie/views/spell_view.cpp b/engines/ultima/nuvie/views/spell_view.cpp
index 06a89498ed7..95353677f6b 100644
--- a/engines/ultima/nuvie/views/spell_view.cpp
+++ b/engines/ultima/nuvie/views/spell_view.cpp
@@ -66,7 +66,7 @@ bool SpellView::init(Screen *tmp_screen, void *view_manager, uint16 x, uint16 y,
 	View::init(x, y, f, p, tm, om);
 
 	SetRect(area.left, area.top, NEWMAGIC_BMP_W, NEWMAGIC_BMP_H + 16);
-	string filename;
+	Common::Path filename;
 
 	config_get_path(config, "newmagic.bmp", filename);
 	background = new U6Bmp();
diff --git a/engines/ultima/nuvie/views/spell_view_gump.cpp b/engines/ultima/nuvie/views/spell_view_gump.cpp
index d39cc6d8183..3424bdb14b0 100644
--- a/engines/ultima/nuvie/views/spell_view_gump.cpp
+++ b/engines/ultima/nuvie/views/spell_view_gump.cpp
@@ -47,9 +47,9 @@ bool SpellViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint1
 
 	SetRect(area.left, area.top, 162, 108);
 
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
+	Common::Path path;
 
 	Graphics::ManagedSurface *image, *image1;
 
@@ -59,9 +59,9 @@ bool SpellViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint1
 	datadir = path;
 
 	build_path(datadir, "gump_btn_up.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
 	build_path(datadir, "gump_btn_down.bmp", imagefile);
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image1 = SDL_LoadBMP(imagefile);
 
 	gump_button = new GUI_Button(nullptr, 0, 9, image, image1, this);
 	this->AddWidget(gump_button);
@@ -70,15 +70,15 @@ bool SpellViewGump::init(Screen *tmp_screen, void *view_manager, uint16 x, uint1
 	datadir = path;
 
 	build_path(datadir, "spellbook_left_arrow.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str()); //we load this twice as they are freed in ~GUI_Button()
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile); //we load this twice as they are freed in ~GUI_Button()
+	image1 = SDL_LoadBMP(imagefile);
 
 	left_button = new GUI_Button(this, 27, 4, image, image1, this);
 	this->AddWidget(left_button);
 
 	build_path(datadir, "spellbook_right_arrow.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
+	image1 = SDL_LoadBMP(imagefile);
 
 	right_button = new GUI_Button(this, 132, 4, image, image1, this);
 	this->AddWidget(right_button);
@@ -94,8 +94,8 @@ uint8 SpellViewGump::fill_cur_spell_list() {
 	uint8 count = SpellView::fill_cur_spell_list();
 
 	//load spell images
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path path;
 
 	build_path(datadir, "images", path);
 	datadir = path;
@@ -104,13 +104,13 @@ uint8 SpellViewGump::fill_cur_spell_list() {
 	build_path(datadir, "spellbook", path);
 	datadir = path;
 
-	Std::string imagefile;
+	Common::Path imagefile;
 	build_path(datadir, "spellbook_bg.bmp", imagefile);
 
 	delete bg_image;
 	bg_image = bmp.getSdlSurface32(imagefile);
 	if (bg_image == nullptr) {
-		DEBUG(0, LEVEL_ERROR, "Failed to load spellbook_bg.bmp from '%s' directory\n", datadir.c_str());
+		DEBUG(0, LEVEL_ERROR, "Failed to load spellbook_bg.bmp from '%s' directory\n", datadir.toString().c_str());
 		return count;
 	}
 
@@ -122,7 +122,7 @@ uint8 SpellViewGump::fill_cur_spell_list() {
 		build_path(datadir, filename, imagefile);
 		Graphics::ManagedSurface *spell_image = bmp.getSdlSurface32(imagefile);
 		if (spell_image == nullptr) {
-			DEBUG(0, LEVEL_ERROR, "Failed to load %s from '%s' directory\n", filename, datadir.c_str());
+			DEBUG(0, LEVEL_ERROR, "Failed to load %s from '%s' directory\n", filename, datadir.toString().c_str());
 		} else {
 			Common::Rect dst;
 
@@ -145,8 +145,8 @@ uint8 SpellViewGump::fill_cur_spell_list() {
 	return count;
 }
 
-void SpellViewGump::loadCircleString(const Std::string &datadir) {
-	Std::string imagefile;
+void SpellViewGump::loadCircleString(const Common::Path &datadir) {
+	Common::Path imagefile;
 	char filename[7]; // n.bmp\0
 
 	Common::sprintf_s(filename, "%d.bmp", level);
@@ -174,8 +174,8 @@ void SpellViewGump::loadCircleString(const Std::string &datadir) {
 	}
 }
 
-void SpellViewGump::loadCircleSuffix(const Std::string &datadir, const Std::string &image) {
-	Std::string imagefile;
+void SpellViewGump::loadCircleSuffix(const Common::Path &datadir, const Std::string &image) {
+	Common::Path imagefile;
 
 	build_path(datadir, image, imagefile);
 	Graphics::ManagedSurface *s = bmp.getSdlSurface32(imagefile);
diff --git a/engines/ultima/nuvie/views/spell_view_gump.h b/engines/ultima/nuvie/views/spell_view_gump.h
index 592387d5102..53da8ce4a1d 100644
--- a/engines/ultima/nuvie/views/spell_view_gump.h
+++ b/engines/ultima/nuvie/views/spell_view_gump.h
@@ -70,8 +70,8 @@ protected:
 	sint16 getSpell(int x, int y) const;
 
 	uint8 fill_cur_spell_list() override;
-	void loadCircleString(const Std::string &datadir);
-	void loadCircleSuffix(const Std::string &datadir, const Std::string &image);
+	void loadCircleString(const Common::Path &datadir);
+	void loadCircleSuffix(const Common::Path &datadir, const Std::string &image);
 	void printSpellQty(uint8 spell_num, uint16 x, uint16 y);
 
 	void close_spellbook();
diff --git a/engines/ultima/nuvie/views/sun_moon_ribbon.cpp b/engines/ultima/nuvie/views/sun_moon_ribbon.cpp
index 5af2027ef18..8ac2b3d54c3 100644
--- a/engines/ultima/nuvie/views/sun_moon_ribbon.cpp
+++ b/engines/ultima/nuvie/views/sun_moon_ribbon.cpp
@@ -58,9 +58,9 @@ void SunMoonRibbon::init(Screen *) {
 
 void SunMoonRibbon::loadBgImage(uint8 num) {
 	char filename[6]; // "n.bmp\0"
-	Std::string datadir = GUI::get_gui()->get_data_dir();
-	Std::string imagefile;
-	Std::string path;
+	Common::Path datadir = GUI::get_gui()->get_data_dir();
+	Common::Path imagefile;
+	Common::Path path;
 	NuvieBmpFile bmp;
 
 	build_path(datadir, "images", path);
diff --git a/engines/ultima/nuvie/views/view.cpp b/engines/ultima/nuvie/views/view.cpp
index 091ec3822d3..d47255029e3 100644
--- a/engines/ultima/nuvie/views/view.cpp
+++ b/engines/ultima/nuvie/views/view.cpp
@@ -192,16 +192,15 @@ GUI_status View::callback(uint16 msg, GUI_CallBack *caller, void *data) {
 	return GUI_PASS;
 }
 
-GUI_Button *View::loadButton(Std::string dir, Std::string name, uint16 x, uint16 y) {
+GUI_Button *View::loadButton(const Common::Path &dir, Std::string name, uint16 x, uint16 y) {
 	GUI_Button *button;
-	Std::string imagefile;
-	Std::string path;
+	Common::Path imagefile;
 
 	Graphics::ManagedSurface *image, *image1;
 	build_path(dir, name + "_btn_up.bmp", imagefile);
-	image = SDL_LoadBMP(imagefile.c_str());
+	image = SDL_LoadBMP(imagefile);
 	build_path(dir, name + "_btn_down.bmp", imagefile);
-	image1 = SDL_LoadBMP(imagefile.c_str());
+	image1 = SDL_LoadBMP(imagefile);
 
 	button = new GUI_Button(nullptr, x, y, image, image1, this);
 	this->AddWidget(button);
diff --git a/engines/ultima/nuvie/views/view.h b/engines/ultima/nuvie/views/view.h
index f92636b13e7..7aff41869a6 100644
--- a/engines/ultima/nuvie/views/view.h
+++ b/engines/ultima/nuvie/views/view.h
@@ -76,7 +76,7 @@ public:
 protected:
 
 	GUI_status callback(uint16 msg, GUI_CallBack *caller, void *data) override;
-	GUI_Button *loadButton(Std::string dir, Std::string name, uint16 x, uint16 y);
+	GUI_Button *loadButton(const Common::Path &dir, Std::string name, uint16 x, uint16 y);
 };
 
 } // End of namespace Nuvie
diff --git a/engines/ultima/nuvie/views/view_manager.cpp b/engines/ultima/nuvie/views/view_manager.cpp
index 356e7021c10..9bccdf3d170 100644
--- a/engines/ultima/nuvie/views/view_manager.cpp
+++ b/engines/ultima/nuvie/views/view_manager.cpp
@@ -509,11 +509,11 @@ unsigned int ViewManager::get_display_weight(float weight) {
 }
 
 // beginning of custom doll functions shared between DollWidget and DollViewGump
-Std::string ViewManager::getDollDataDirString() {
+Common::Path ViewManager::getDollDataDirString() {
 	if (!DollDataDirString.empty())
 		return DollDataDirString;
 	DollDataDirString = GUI::get_gui()->get_data_dir();
-	Std::string path;
+	Common::Path path;
 	build_path(DollDataDirString, "images", path);
 	DollDataDirString = path;
 	build_path(DollDataDirString, "gumps", path);
@@ -526,7 +526,7 @@ Std::string ViewManager::getDollDataDirString() {
 
 Graphics::ManagedSurface *ViewManager::loadAvatarDollImage(Graphics::ManagedSurface *avatar_doll, bool orig) {
 	char filename[17]; //avatar_nn_nn.bmp\0
-	Std::string imagefile;
+	Common::Path imagefile;
 	uint8 portrait_num = Game::get_game()->get_portrait()->get_avatar_portrait_num();
 
 	Common::sprintf_s(filename, "avatar_%s_%02d.bmp", get_game_tag(Game::get_game()->get_game_type()), portrait_num);
@@ -547,7 +547,7 @@ Graphics::ManagedSurface *ViewManager::loadAvatarDollImage(Graphics::ManagedSurf
 
 Graphics::ManagedSurface *ViewManager::loadCustomActorDollImage(Graphics::ManagedSurface *actor_doll, uint8 actor_num, bool orig) {
 	char filename[17]; //actor_nn_nnn.bmp\0
-	Std::string imagefile;
+	Common::Path imagefile;
 
 	if (actor_doll)
 		delete actor_doll;
@@ -569,7 +569,7 @@ Graphics::ManagedSurface *ViewManager::loadCustomActorDollImage(Graphics::Manage
 
 Graphics::ManagedSurface *ViewManager::loadGenericDollImage(bool orig) {
 	char filename[14]; //avatar_nn.bmp\0
-	Std::string imagefile;
+	Common::Path imagefile;
 
 	Common::sprintf_s(filename, "actor_%s.bmp", get_game_tag(Game::get_game()->get_game_type()));
 	if (orig) {
diff --git a/engines/ultima/nuvie/views/view_manager.h b/engines/ultima/nuvie/views/view_manager.h
index a2c8ecc6066..b38af7ec9e2 100644
--- a/engines/ultima/nuvie/views/view_manager.h
+++ b/engines/ultima/nuvie/views/view_manager.h
@@ -83,7 +83,7 @@ protected:
 	SunMoonRibbon *ribbon;
 	MDSkyStripWidget *mdSkyWidget;
 
-	Std::string DollDataDirString;
+	Common::Path DollDataDirString;
 
 public:
 
@@ -153,7 +153,7 @@ public:
 	unsigned int get_display_weight(float weight);
 
 // custom doll functions shared between DollWidget and DollViewGump
-	Std::string getDollDataDirString();
+	Common::Path getDollDataDirString();
 	Graphics::ManagedSurface *loadAvatarDollImage(Graphics::ManagedSurface *avatar_doll, bool orig = false);
 	Graphics::ManagedSurface *loadCustomActorDollImage(Graphics::ManagedSurface *actor_doll, uint8 actor_num, bool orig = false);
 	Graphics::ManagedSurface *loadGenericDollImage(bool orig);
diff --git a/engines/ultima/shared/conf/xml_node.cpp b/engines/ultima/shared/conf/xml_node.cpp
index 2f5a95d1de3..92d898bc3f6 100644
--- a/engines/ultima/shared/conf/xml_node.cpp
+++ b/engines/ultima/shared/conf/xml_node.cpp
@@ -367,7 +367,7 @@ XMLNode *XMLNode::xmlParse(XMLTree *tree, const Common::String &s, size_t &pos)
 				// Element is a placeholder for inclusion of a secondary XML file
 				Common::String fname = node->_attributes["href"];
 				delete node;
-				node = xmlParseFile(tree, fname);
+				node = xmlParseFile(tree, Common::Path(fname, '/'));
 			}
 
 			return node;
@@ -436,13 +436,13 @@ void XMLNode::parseNodeText(const Common::String &nodeText) {
 	}
 }
 
-XMLNode *XMLNode::xmlParseFile(XMLTree *tree, const Common::String &fname) {
-	const Common::String rootFile = tree->_filename;
-	Common::String filename = Common::String(rootFile.c_str(), rootFile.findLastOf('/') + 1) + fname;
+XMLNode *XMLNode::xmlParseFile(XMLTree *tree, const Common::Path &fname) {
+	const Common::Path rootFile = tree->_filename;
+	Common::Path filename = rootFile.getParent().join(fname);
 
 	Common::File f;
 	if (!f.open(filename))
-		error("Could not open xml file - %s", filename.c_str());
+		error("Could not open xml file - %s", filename.toString().c_str());
 
 	// Read in the file contents
 	char *buf = new char[f.size() + 1];
@@ -455,7 +455,7 @@ XMLNode *XMLNode::xmlParseFile(XMLTree *tree, const Common::String &fname) {
 	// Parse the sub-xml
 	XMLNode *result = xmlParseDoc(tree, text);
 	if (!result)
-		error("Error passing xml - %s", fname.c_str());
+		error("Error passing xml - %s", fname.toString().c_str());
 
 	return result;
 }
diff --git a/engines/ultima/shared/conf/xml_node.h b/engines/ultima/shared/conf/xml_node.h
index 91dbecb9a29..92393fcb01c 100644
--- a/engines/ultima/shared/conf/xml_node.h
+++ b/engines/ultima/shared/conf/xml_node.h
@@ -22,10 +22,11 @@
 #ifndef SHARED_CONF_XML_NODE_H
 #define SHARED_CONF_XML_NODE_H
 
-#include "common/util.h"
-#include "common/str.h"
 #include "common/array.h"
 #include "common/hash-str.h"
+#include "common/path.h"
+#include "common/str.h"
+#include "common/util.h"
 
 namespace Ultima {
 namespace Shared {
@@ -55,7 +56,7 @@ private:
 	/**
 	 * Parses a specified file and returns the root node for it
 	 */
-	static XMLNode *xmlParseFile(XMLTree *tree, const Common::String &fname);
+	static XMLNode *xmlParseFile(XMLTree *tree, const Common::Path &fname);
 
 	static Common::String closeTag(const Common::String &s);
 	static Common::String encodeEntity(const Common::String &s);
diff --git a/engines/ultima/shared/conf/xml_tree.cpp b/engines/ultima/shared/conf/xml_tree.cpp
index 797f93027c9..5d76970ff7e 100644
--- a/engines/ultima/shared/conf/xml_tree.cpp
+++ b/engines/ultima/shared/conf/xml_tree.cpp
@@ -31,7 +31,7 @@ XMLTree::XMLTree() : _tree(nullptr), _isFile(false),
 		_readOnly(false) {
 }
 
-XMLTree::XMLTree(const Common::String &fname) : _tree(nullptr), _isFile(true),
+XMLTree::XMLTree(const Common::Path &fname) : _tree(nullptr), _isFile(true),
 	  _readOnly(false) {
 	readConfigFile(fname);
 }
@@ -52,7 +52,7 @@ void XMLTree::clear() {
 	_readOnly = false;
 }
 
-bool XMLTree::readConfigFile(const Common::String &fname) {
+bool XMLTree::readConfigFile(const Common::Path &fname) {
 	Common::File f;
 	_filename = fname;
 
diff --git a/engines/ultima/shared/conf/xml_tree.h b/engines/ultima/shared/conf/xml_tree.h
index 685dc51971e..3ffc41183eb 100644
--- a/engines/ultima/shared/conf/xml_tree.h
+++ b/engines/ultima/shared/conf/xml_tree.h
@@ -23,6 +23,7 @@
 #define SHARED_CONF_XML_TREE_H
 
 #include "common/array.h"
+#include "common/path.h"
 #include "common/str.h"
 #include "common/stream.h"
 #include "common/util.h"
@@ -36,16 +37,16 @@ class XMLTree {
 	friend class XMLNode;
 private:
 	XMLNode *_tree;
-	Common::String _filename;
+	Common::Path _filename;
 	bool _isFile;
 	bool _readOnly;
 public:
 	XMLTree();
-	XMLTree(const Common::String &fname);
+	XMLTree(const Common::Path &fname);
 	XMLTree(Common::SeekableReadStream *stream);
 	~XMLTree();
 
-	bool readConfigFile(const Common::String &fname);
+	bool readConfigFile(const Common::Path &fname);
 	bool readConfigStream(Common::SeekableReadStream *stream);
 	bool readConfigString(const Common::String &s);
 
diff --git a/engines/ultima/shared/core/file.cpp b/engines/ultima/shared/core/file.cpp
index de1fd09a78b..e1a8aa5b7e1 100644
--- a/engines/ultima/shared/core/file.cpp
+++ b/engines/ultima/shared/core/file.cpp
@@ -27,13 +27,13 @@ namespace Ultima {
 namespace Shared {
 
 #define ERROR error("Could not open file - %s", name.c_str())
-#define PATH_ERROR error("Could not open file - %s", name.toString().c_str())
+#define PATH_ERROR error("Could not open file - %s", name.toString(Common::Path::kNativeSeparator).c_str())
 
-File::File(const Common::String &name) : Common::File(), _filesize(-1) {
+File::File(const Common::Path &name) : Common::File(), _filesize(-1) {
 	close();
 
 	if (!Common::File::open(name))
-		ERROR;
+		PATH_ERROR;
 }
 
 bool File::open(const Common::Path &name) {
diff --git a/engines/ultima/shared/core/file.h b/engines/ultima/shared/core/file.h
index 9a81bde40d8..e06bf8ef2ef 100644
--- a/engines/ultima/shared/core/file.h
+++ b/engines/ultima/shared/core/file.h
@@ -36,7 +36,7 @@ private:
 	int32 _filesize;
 public:
 	File() : Common::File(), _filesize(-1) {}
-	File(const Common::String &name);
+	File(const Common::Path &name);
 
 	/**
 	 * Open the file with the given filename, by searching SearchMan.
diff --git a/engines/ultima/shared/early/ultima_early.cpp b/engines/ultima/shared/early/ultima_early.cpp
index d60cd4374d1..8513c664149 100644
--- a/engines/ultima/shared/early/ultima_early.cpp
+++ b/engines/ultima/shared/early/ultima_early.cpp
@@ -151,7 +151,7 @@ bool UltimaEarlyEngine::canSaveGameStateCurrently(bool isAutosave) {
 	return _game->canSaveGameStateCurrently();
 }
 
-bool UltimaEarlyEngine::isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) {
+bool UltimaEarlyEngine::isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) {
 	folder = "ultima1";
 	majorVersion = 1;
 	minorVersion = 0;
diff --git a/engines/ultima/shared/early/ultima_early.h b/engines/ultima/shared/early/ultima_early.h
index 49a17b44555..13c29b5d433 100644
--- a/engines/ultima/shared/early/ultima_early.h
+++ b/engines/ultima/shared/early/ultima_early.h
@@ -82,7 +82,7 @@ private:
 	/**
 	 * Returns the data archive folder and version that's required
 	 */
-	bool isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) override;
+	bool isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) override;
 public:
 	GameBase *_game;
 	MouseCursor *_mouseCursor;
diff --git a/engines/ultima/shared/engine/data_archive.cpp b/engines/ultima/shared/engine/data_archive.cpp
index b2c89163525..5cf72d03762 100644
--- a/engines/ultima/shared/engine/data_archive.cpp
+++ b/engines/ultima/shared/engine/data_archive.cpp
@@ -33,11 +33,11 @@ namespace Shared {
 class UltimaDataArchiveMember : public Common::ArchiveMember {
 private:
 	Common::SharedPtr<Common::ArchiveMember> _member;
-	Common::String _publicFolder;
-	Common::String _innerfolder;
+	Common::Path _publicFolder;
+	Common::Path _innerfolder;
 public:
 	UltimaDataArchiveMember(Common::SharedPtr<Common::ArchiveMember> member,
-		const Common::String &subfolder) :
+		const Common::Path &subfolder) :
 		_member(member), _publicFolder("data/"), _innerfolder(subfolder) {
 	}
 	~UltimaDataArchiveMember() override {}
@@ -47,22 +47,22 @@ public:
 	Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override {
 		return _member->createReadStreamForAltStream(altStreamType);
 	}
-	Common::String getName() const override {
-		Common::String name = _member->getName();
-		assert(name.hasPrefixIgnoreCase(_innerfolder));
-		return _publicFolder + Common::String(name.c_str() + _innerfolder.size());
+	Common::Path getPathInArchive() const override {
+		Common::Path name = _member->getPathInArchive();
+		assert(name.isRelativeTo(_innerfolder));
+		return _publicFolder.join(name.relativeTo(_innerfolder));
 	}
 	Common::U32String getDisplayName() const override {
 		return _member->getDisplayName();
 	}
 	
-	Common::String getFileName() const override { return getName(); }
-	Common::Path getPathInArchive() const override { return getName(); }
+	Common::String getFileName() const override { return getFileName(); }
+	Common::String getName() const override { return getPathInArchive().toString('/'); }
 };
 
 /*-------------------------------------------------------------------*/
 
-bool UltimaDataArchive::load(const Common::String &subfolder,
+bool UltimaDataArchive::load(const Common::Path &subfolder,
 		int reqMajorVersion, int reqMinorVersion, Common::U32String &errorMsg) {
 	Common::Archive *dataArchive = nullptr;
 	Common::File f;
@@ -70,9 +70,9 @@ bool UltimaDataArchive::load(const Common::String &subfolder,
 #ifndef RELEASE_BUILD
 	Common::FSNode folder;
 	if (ConfMan.hasKey("extrapath")) {
-		if ((folder = Common::FSNode(ConfMan.get("extrapath"))).exists()
+		if ((folder = Common::FSNode(ConfMan.getPath("extrapath"))).exists()
 				&& (folder = folder.getChild("files")).exists()
-				&& (folder = folder.getChild(subfolder)).exists()) {
+				&& (folder = folder.getChild(subfolder.baseName())).exists()) {
 			f.open(folder.getChild("version.txt"));
 		}
 	}
@@ -81,7 +81,7 @@ bool UltimaDataArchive::load(const Common::String &subfolder,
 	if (!f.isOpen()) {
 		if (!Common::File::exists(DATA_FILENAME) ||
 			(dataArchive = Common::makeZipArchive(DATA_FILENAME)) == 0 ||
-			!f.open(Common::String::format("%s/version.txt", subfolder.c_str()), *dataArchive)) {
+			!f.open(subfolder.join("version.txt"), *dataArchive)) {
 			delete dataArchive;
 			errorMsg = Common::U32String::format(_("Could not locate engine data %s"), DATA_FILENAME);
 			return false;
@@ -122,17 +122,16 @@ bool UltimaDataArchive::load(const Common::String &subfolder,
 /*-------------------------------------------------------------------*/
 
 bool UltimaDataArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!name.hasPrefixIgnoreCase(_publicFolder))
+	if (!path.isRelativeTo(_publicFolder))
 		return false;
 
-	Common::String realFilename = innerToPublic(name);
+	Common::Path realFilename = innerToPublic(path);
 	return _zip->hasFile(realFilename);
 }
 
 int UltimaDataArchive::listMatchingMembers(Common::ArchiveMemberList &list, const Common::Path &pattern, bool matchPathComponents) const {
-	Common::String patt = pattern.toString();
-	if (patt.hasPrefixIgnoreCase(_publicFolder))
+	Common::Path patt(pattern);
+	if (patt.isRelativeTo(_publicFolder))
 		patt = innerToPublic(patt);
 
 	// Get any matching files
@@ -166,17 +165,15 @@ int UltimaDataArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr UltimaDataArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *UltimaDataArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (hasFile(name)) {
-		Common::String filename = innerToPublic(name);
+	if (hasFile(path)) {
+		Common::Path filename = innerToPublic(path);
 		return _zip->createReadStreamForMember(filename);
 	}
 
@@ -188,36 +185,36 @@ Common::SeekableReadStream *UltimaDataArchive::createReadStreamForMember(const C
 #ifndef RELEASE_BUILD
 
 const Common::ArchiveMemberPtr UltimaDataArchiveProxy::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *UltimaDataArchiveProxy::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (hasFile(name))
-		return getNode(name).createReadStream();
+	if (hasFile(path))
+		return getNode(path).createReadStream();
 
 	return nullptr;
 }
 
-Common::FSNode UltimaDataArchiveProxy::getNode(const Common::String &name) const {
-	Common::String remainingName = name.substr(_publicFolder.size());
+Common::FSNode UltimaDataArchiveProxy::getNode(const Common::Path &name) const {
+	Common::Path remainingName = name.relativeTo(_publicFolder);
 	Common::FSNode node = _folder;
-	size_t pos;
 
-	while ((pos = remainingName.findFirstOf('/')) != Common::String::npos) {
-		node = node.getChild(remainingName.substr(0, pos));
+	Common::StringArray components = remainingName.splitComponents();
+
+	if (components.empty()) {
+		return node;
+	}
+
+	for(Common::StringArray::const_iterator it = components.begin(); it != components.end() - 1; it++) {
+		node = node.getChild(*it);
 		if (!node.exists())
 			return node;
-
-		remainingName = remainingName.substr(pos + 1);
 	}
 
-	if (!remainingName.empty())
-		node = node.getChild(remainingName);
+	node = node.getChild(*(components.end() - 1));
 
 	return node;
 }
diff --git a/engines/ultima/shared/engine/data_archive.h b/engines/ultima/shared/engine/data_archive.h
index bf880a48ab7..c607a54f53e 100644
--- a/engines/ultima/shared/engine/data_archive.h
+++ b/engines/ultima/shared/engine/data_archive.h
@@ -24,7 +24,7 @@
 
 #include "common/archive.h"
 #include "common/fs.h"
-#include "common/str.h"
+#include "common/path.h"
 
 namespace Ultima {
 namespace Shared {
@@ -38,16 +38,16 @@ namespace Shared {
 class UltimaDataArchive : public Common::Archive {
 private:
 	Common::Archive *_zip;
-	Common::String _publicFolder;
-	Common::String _innerfolder;
+	Common::Path _publicFolder;
+	Common::Path _innerfolder;
 
 
-	UltimaDataArchive(Common::Archive *zip, const Common::String &subfolder) :
-		_zip(zip), _publicFolder("data/"), _innerfolder(subfolder + "/") {}
+	UltimaDataArchive(Common::Archive *zip, const Common::Path &subfolder) :
+		_zip(zip), _publicFolder("data/"), _innerfolder(subfolder) {}
 
-	Common::String innerToPublic(const Common::String &filename) const {
-		assert(filename.hasPrefixIgnoreCase(_publicFolder));
-		return _innerfolder + Common::String(filename.c_str() + _publicFolder.size());
+	Common::Path innerToPublic(const Common::Path &filename) const {
+		assert(filename.isRelativeTo(_publicFolder));
+		return _innerfolder.join(filename.relativeTo(_publicFolder));
 	}
 public:
 	/**
@@ -59,7 +59,7 @@ public:
 	 * if the required data is found, it returns the new archive.
 	 * Otherwise, returns an error message in the errorMsg field
 	 */
-	static bool load(const Common::String &subfolder,
+	static bool load(const Common::Path &subfolder,
 		int reqMajorVersion, int reqMinorVersion, Common::U32String &errorMsg);
 public:
 	~UltimaDataArchive() override {
@@ -118,14 +118,14 @@ class UltimaDataArchiveProxy : public Common::Archive {
 	friend class UltimaDataArchive;
 private:
 	Common::FSNode _folder;
-	const Common::String _publicFolder;
+	const Common::Path _publicFolder;
 
 	UltimaDataArchiveProxy(const Common::FSNode &folder) : _folder(folder), _publicFolder("data/") {}
 
 	/**
 	 * Gets a file node from the passed filename
 	 */
-	Common::FSNode getNode(const Common::String &name) const;
+	Common::FSNode getNode(const Common::Path &name) const;
 public:
 	~UltimaDataArchiveProxy() override {
 	}
@@ -136,8 +136,7 @@ public:
 	 * replacement.
 	 */
 	bool hasFile(const Common::Path &path) const override {
-		Common::String name = path.toString();
-		return name.hasPrefixIgnoreCase(_publicFolder) && getNode(name).exists();
+		return path.isRelativeTo(_publicFolder) && getNode(path).exists();
 	}
 
 	/**
diff --git a/engines/ultima/shared/engine/resources.cpp b/engines/ultima/shared/engine/resources.cpp
index e36c5c616cc..1633baf4a69 100644
--- a/engines/ultima/shared/engine/resources.cpp
+++ b/engines/ultima/shared/engine/resources.cpp
@@ -44,7 +44,7 @@ bool Resources::open() {
 	return true;
 }
 
-void Resources::addResource(const Common::String &name, const byte *data, size_t size) {
+void Resources::addResource(const Common::Path &name, const byte *data, size_t size) {
 	// Add a new entry to the local resources list for the passed data
 	_localResources.push_back(LocalResource());
 	LocalResource &lr = _localResources[_localResources.size() - 1];
@@ -55,9 +55,8 @@ void Resources::addResource(const Common::String &name, const byte *data, size_t
 }
 
 bool Resources::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (uint idx = 0; idx < _localResources.size(); ++idx)
-		if (!_localResources[idx]._name.compareToIgnoreCase(name))
+		if (_localResources[idx]._name.equalsIgnoreCase(path))
 			return true;
 
 	return false;
@@ -72,18 +71,16 @@ int Resources::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr Resources::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!hasFile(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *Resources::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (uint idx = 0; idx < _localResources.size(); ++idx) {
 		const LocalResource &lr = _localResources[idx];
-		if (!lr._name.compareToIgnoreCase(name))
+		if (lr._name.equalsIgnoreCase(path))
 			return new Common::MemoryReadStream(&lr._data[0], lr._data.size());
 	}
 
@@ -100,7 +97,7 @@ void Resources::FileResource::load(File &f) {
 
 /*-------------------------------------------------------------------*/
 
-ResourceFile::ResourceFile(const Common::String &filename) : _filename(filename), _bufferP(_buffer) {
+ResourceFile::ResourceFile(const Common::Path &filename) : _filename(filename), _bufferP(_buffer) {
 	Common::fill(_buffer, _buffer + STRING_BUFFER_SIZE, 0);
 }
 
diff --git a/engines/ultima/shared/engine/resources.h b/engines/ultima/shared/engine/resources.h
index 354fbbd1071..8fbdd3a6919 100644
--- a/engines/ultima/shared/engine/resources.h
+++ b/engines/ultima/shared/engine/resources.h
@@ -46,12 +46,12 @@ private:
 	char _buffer[STRING_BUFFER_SIZE];
 	char *_bufferP;
 protected:
-	Common::String _filename;
+	Common::Path _filename;
 protected:
 	/**
 	 * Constructor
 	 */
-	ResourceFile(const Common::String &filename);
+	ResourceFile(const Common::Path &filename);
 
 	/**
 	 * Destructor
@@ -93,12 +93,12 @@ protected:
 	/**
 	 * Constructor
 	 */
-	LocalResourceFile(const Common::String &filename) : ResourceFile(filename), _owner(nullptr), _file(DisposeAfterUse::YES) {}
+	LocalResourceFile(const Common::Path &filename) : ResourceFile(filename), _owner(nullptr), _file(DisposeAfterUse::YES) {}
 
 	/**
 	 * Constructor
 	 */
-	LocalResourceFile(Resources *owner, const Common::String &filename) : ResourceFile(filename),
+	LocalResourceFile(Resources *owner, const Common::Path &filename) : ResourceFile(filename),
 		_owner(owner), _file(DisposeAfterUse::YES) {}
 
 	/**
@@ -127,11 +127,11 @@ public:
  */
 class Resources : public Common::Archive {
 	struct LocalResource {
-		Common::String _name;
+		Common::Path _name;
 		Common::Array<byte> _data;
 	};
 	struct FileResource {
-		Common::String _name;
+		Common::Path _name;
 		size_t _offset, _size;
 
 		/**
@@ -159,7 +159,7 @@ public:
 	 * later opened like a normal file. Just as it will when eventually shifted to the
 	 * data file for the engine
 	 */
-	void addResource(const Common::String &name, const byte *data, size_t size);
+	void addResource(const Common::Path &name, const byte *data, size_t size);
 
 	// Archive implementation
 	/**
diff --git a/engines/ultima/shared/engine/ultima.cpp b/engines/ultima/shared/engine/ultima.cpp
index df0f66bd857..37f66002fc5 100644
--- a/engines/ultima/shared/engine/ultima.cpp
+++ b/engines/ultima/shared/engine/ultima.cpp
@@ -45,7 +45,7 @@ UltimaEngine::~UltimaEngine() {
 }
 
 bool UltimaEngine::initialize() {
-	Common::String folder;
+	Common::Path folder;
 	int reqMajorVersion, reqMinorVersion;
 
 	// Call syncSoundSettings to get default volumes set
@@ -90,7 +90,7 @@ GameId UltimaEngine::getGameId() const {
 }
 
 Common::FSNode UltimaEngine::getGameDirectory() const {
-	return Common::FSNode(ConfMan.get("path"));
+	return Common::FSNode(ConfMan.getPath("path"));
 }
 
 } // End of namespace Shared
diff --git a/engines/ultima/shared/engine/ultima.h b/engines/ultima/shared/engine/ultima.h
index d15bc4bac94..0287ebf11a5 100644
--- a/engines/ultima/shared/engine/ultima.h
+++ b/engines/ultima/shared/engine/ultima.h
@@ -50,7 +50,7 @@ protected:
 	/**
 	 * Returns the data archive folder and version that's required
 	 */
-	virtual bool isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) {
+	virtual bool isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) {
 		return false;
 	}
 
diff --git a/engines/ultima/shared/gfx/bitmap.cpp b/engines/ultima/shared/gfx/bitmap.cpp
index 5d1732fbd52..c296484cd28 100644
--- a/engines/ultima/shared/gfx/bitmap.cpp
+++ b/engines/ultima/shared/gfx/bitmap.cpp
@@ -28,7 +28,7 @@ namespace Ultima {
 namespace Shared {
 namespace Gfx {
 
-void Bitmap::load(const Common::String &filename) {
+void Bitmap::load(const Common::Path &filename) {
 	File srcFile(filename);
 	Common::MemoryWriteStreamDynamic decompressedFile(DisposeAfterUse::YES);
 	decompress(&srcFile, &decompressedFile);
diff --git a/engines/ultima/shared/gfx/bitmap.h b/engines/ultima/shared/gfx/bitmap.h
index 2a7f9e06671..14c384c3018 100644
--- a/engines/ultima/shared/gfx/bitmap.h
+++ b/engines/ultima/shared/gfx/bitmap.h
@@ -35,7 +35,7 @@ public:
 	/**
 	 * Loads an Ultima 6 bitmap
 	 */
-	void load(const Common::String &filename);
+	void load(const Common::Path &filename);
 
 	/**
 	 * Flips a bitmap horizontally
diff --git a/engines/ultima/shared/gfx/sprites.cpp b/engines/ultima/shared/gfx/sprites.cpp
index 979dda1c3b8..d2c230a6962 100644
--- a/engines/ultima/shared/gfx/sprites.cpp
+++ b/engines/ultima/shared/gfx/sprites.cpp
@@ -76,7 +76,7 @@ void Sprite::draw(Graphics::ManagedSurface &dest, const Common::Point &pt) {
 
 /*-------------------------------------------------------------------*/
 
-void Sprites::load(const Common::String &name, uint bpp, uint16 w, uint16 h) {
+void Sprites::load(const Common::Path &name, uint bpp, uint16 w, uint16 h) {
 	_spriteSize = Point(w, h);
 
 	// Open the tiles for access
diff --git a/engines/ultima/shared/gfx/sprites.h b/engines/ultima/shared/gfx/sprites.h
index 2d1b0bfbcee..beb5e4b828f 100644
--- a/engines/ultima/shared/gfx/sprites.h
+++ b/engines/ultima/shared/gfx/sprites.h
@@ -102,7 +102,7 @@ protected:
 	 * @param w				Width of tiles
 	 * @param h				Height of files
 	 */
-	void load(const Common::String &name, uint bpp, uint16 w = 16, uint16 h = 16);
+	void load(const Common::Path &name, uint bpp, uint16 w = 16, uint16 h = 16);
 public:
 	/**
 	 * Destructor
diff --git a/engines/ultima/ultima4/controllers/intro_controller.cpp b/engines/ultima/ultima4/controllers/intro_controller.cpp
index 188cc5f70d9..9fba5da2c07 100644
--- a/engines/ultima/ultima4/controllers/intro_controller.cpp
+++ b/engines/ultima/ultima4/controllers/intro_controller.cpp
@@ -109,7 +109,7 @@ IntroBinData::~IntroBinData() {
 }
 
 void IntroBinData::openFile(Shared::File &f, const Common::String &name) {
-	f.open(Common::String::format("data/intro/%s.dat", name.c_str()));
+	f.open(Common::Path(Common::String::format("data/intro/%s.dat", name.c_str())));
 }
 
 bool IntroBinData::load() {
diff --git a/engines/ultima/ultima4/core/debugger.cpp b/engines/ultima/ultima4/core/debugger.cpp
index 882fb96b77b..360b5056400 100644
--- a/engines/ultima/ultima4/core/debugger.cpp
+++ b/engines/ultima/ultima4/core/debugger.cpp
@@ -239,7 +239,7 @@ bool Debugger::cmdMove(int argc, const char **argv) {
 		return isDebuggerActive();
 	}
 
-	Common::String priorMap = g_context->_location->_map->_fname;
+	Common::Path priorMap = g_context->_location->_map->_fname;
 	MoveResult retval = g_context->_location->move(dir, true);
 
 	// horse doubles speed (make sure we're on the same map as the previous move first)
diff --git a/engines/ultima/ultima4/filesys/u4file.cpp b/engines/ultima/ultima4/filesys/u4file.cpp
index e4467fa7b98..70c3d027390 100644
--- a/engines/ultima/ultima4/filesys/u4file.cpp
+++ b/engines/ultima/ultima4/filesys/u4file.cpp
@@ -26,7 +26,7 @@ namespace Ultima {
 namespace Ultima4 {
 
 Std::vector<Common::String> u4read_stringtable(const Common::String &filename) {
-	Shared::File f(Common::String::format("data/text/%s.dat", filename.c_str()));
+	Shared::File f(Common::Path(Common::String::format("data/text/%s.dat", filename.c_str())));
 	Std::vector<Common::String> strs;
 	Common::String line;
 
diff --git a/engines/ultima/ultima4/game/script.cpp b/engines/ultima/ultima4/game/script.cpp
index a1e03b17ce0..89f2cbdf149 100644
--- a/engines/ultima/ultima4/game/script.cpp
+++ b/engines/ultima/ultima4/game/script.cpp
@@ -160,7 +160,7 @@ bool Script::load(const Common::String &filename, const Common::String &baseId,
 	 * Open and parse the .xml file
 	 */
 	Shared::XMLTree *doc = new Shared::XMLTree(
-		Common::String::format("data/conf/%s", filename.c_str()));
+		Common::Path(Common::String::format("data/conf/%s", filename.c_str())));
 	_vendorScriptDoc = root = doc->getTree();
 
 	if (!root->id().equalsIgnoreCase("scripts"))
diff --git a/engines/ultima/ultima4/gfx/imagemgr.cpp b/engines/ultima/ultima4/gfx/imagemgr.cpp
index 09bd94b4afa..549b921d124 100644
--- a/engines/ultima/ultima4/gfx/imagemgr.cpp
+++ b/engines/ultima/ultima4/gfx/imagemgr.cpp
@@ -508,7 +508,7 @@ Common::String ImageMgr::guessFileType(const Common::String &filename) {
 }
 
 bool ImageMgr::imageExists(ImageInfo *info) {
-	if (info->_filename == "") //If it is an abstract image like "screen"
+	if (info->_filename.empty()) //If it is an abstract image like "screen"
 		return true;
 	Common::File *file = getImageFile(info);
 	if (file) {
@@ -528,11 +528,11 @@ Common::File *ImageMgr::getImageFile(ImageInfo *info) {
 	Common::File *file = new Common::File();
 	if (!info->_xu4Graphic) {
 		// It's a file in the game folder
-		if (file->open(filename))
+		if (file->open(Common::Path(filename)))
 			return file;
 	}
 
-	if (file->open("data/graphics/" + filename))
+	if (file->open(Common::Path("data/graphics/").joinInPlace(filename)))
 		return file;
 
 	delete file;
diff --git a/engines/ultima/ultima4/map/city.h b/engines/ultima/ultima4/map/city.h
index e0ad81c0418..514aad985ce 100644
--- a/engines/ultima/ultima4/map/city.h
+++ b/engines/ultima/ultima4/map/city.h
@@ -75,7 +75,7 @@ public:
 	Common::String _name;
 	Common::String _type;
 	PersonList _persons;
-	Common::String _tlkFname;
+	Common::Path _tlkFname;
 	PersonRoleList _personRoles;
 	Std::vector<Dialogue *> _extraDialogues;
 };
diff --git a/engines/ultima/ultima4/map/map.h b/engines/ultima/ultima4/map/map.h
index 171b4d374e5..bbafc47b351 100644
--- a/engines/ultima/ultima4/map/map.h
+++ b/engines/ultima/ultima4/map/map.h
@@ -263,7 +263,7 @@ public:
 
 public:
 	MapId _id;
-	Common::String _fname;
+	Common::Path _fname;
 	Type _type;
 	uint _width, _height, _levels;
 	uint _chunkWidth, _chunkHeight;
diff --git a/engines/ultima/ultima4/sound/music.cpp b/engines/ultima/ultima4/sound/music.cpp
index 8c897d416f8..86a0965395b 100644
--- a/engines/ultima/ultima4/sound/music.cpp
+++ b/engines/ultima/ultima4/sound/music.cpp
@@ -124,7 +124,7 @@ void Music::playMusic(const Common::String &filename) {
 
 bool Music::startMusic(const Common::String &filename) {
 	Common::File musicFile;
-	if (!musicFile.open(Common::String::format("data/mid/%s", filename.c_str())))
+	if (!musicFile.open(Common::Path(Common::String::format("data/mid/%s", filename.c_str()))))
 		// No such file exists
 		return false;
 
diff --git a/engines/ultima/ultima4/sound/sound.cpp b/engines/ultima/ultima4/sound/sound.cpp
index 32ce3693323..ed41f7556b9 100644
--- a/engines/ultima/ultima4/sound/sound.cpp
+++ b/engines/ultima/ultima4/sound/sound.cpp
@@ -62,7 +62,7 @@ SoundManager::SoundManager(Audio::Mixer *mixer) : _mixer(mixer) {
 		if (i->getName() != "track")
 			continue;
 
-		_soundFilenames.push_back(i->getString("file"));
+		_soundFilenames.push_back(Common::Path(i->getString("file")));
 	}
 }
 
@@ -78,9 +78,10 @@ bool SoundManager::load(Sound sound) {
 	assertMsg(sound < SOUND_MAX, "Attempted to load an invalid sound");
 
 	if (_sounds[sound] == nullptr) {
-		Common::String pathname("data/sound/" + _soundFilenames[sound]);
-		Common::String basename = pathname.substr(pathname.findLastOf("/") + 1);
-		if (!basename.empty())
+		Common::Path pathname("data/sound/");
+		pathname.joinInPlace(_soundFilenames[sound]);
+		Common::String basename = pathname.baseName();
+		if (!basename.empty() && !basename.hasSuffix("/"))
 			return load_sys(sound, pathname);
 	}
 
@@ -103,28 +104,30 @@ void SoundManager::stop(int channel) {
 	stop_sys(channel);
 }
 
-bool SoundManager::load_sys(Sound sound, const Common::String &filename) {
+bool SoundManager::load_sys(Sound sound, const Common::Path &filename) {
 	Common::File f;
 	if (!f.open(filename))
 		return false;
 
 	Audio::SeekableAudioStream *audioStream = nullptr;
 
+	Common::String baseName(filename.baseName());
+
 #ifdef USE_FLAC
-	if (filename.hasSuffixIgnoreCase(".fla"))
+	if (baseName.hasSuffixIgnoreCase(".fla"))
 		audioStream = Audio::makeFLACStream(f.readStream(f.size()), DisposeAfterUse::YES);
 #endif
 #ifdef USE_VORBIS
-	if (filename.hasSuffixIgnoreCase(".ogg"))
+	if (baseName.hasSuffixIgnoreCase(".ogg"))
 		audioStream = Audio::makeVorbisStream(f.readStream(f.size()), DisposeAfterUse::YES);
 #endif
 #ifdef USE_MAD
-	if (filename.hasSuffixIgnoreCase(".mp3"))
+	if (baseName.hasSuffixIgnoreCase(".mp3"))
 		audioStream = Audio::makeMP3Stream(f.readStream(f.size()), DisposeAfterUse::YES);
 #endif
-	if (filename.hasSuffixIgnoreCase(".wav"))
+	if (baseName.hasSuffixIgnoreCase(".wav"))
 		audioStream = Audio::makeWAVStream(f.readStream(f.size()), DisposeAfterUse::YES);
-	if (filename.hasSuffixIgnoreCase(".voc"))
+	if (baseName.hasSuffixIgnoreCase(".voc"))
 		audioStream = Audio::makeVOCStream(f.readStream(f.size()), DisposeAfterUse::YES);
 
 	_sounds[sound] = audioStream;
diff --git a/engines/ultima/ultima4/sound/sound.h b/engines/ultima/ultima4/sound/sound.h
index 83d8ffc5ffd..fdd28fb8fc7 100644
--- a/engines/ultima/ultima4/sound/sound.h
+++ b/engines/ultima/ultima4/sound/sound.h
@@ -73,13 +73,13 @@ class SoundManager {
 private:
 	Audio::Mixer *_mixer;
 	Audio::SoundHandle _soundHandle;
-	Std::vector<Common::String> _soundFilenames;
+	Std::vector<Common::Path> _soundFilenames;
 	Std::vector<Audio::SeekableAudioStream *> _sounds;
 private:
 	bool load(Sound sound);
 
 	void play_sys(Sound sound, bool onlyOnce, int specificDurationMilli);
-	bool load_sys(Sound sound, const Common::String &filename);
+	bool load_sys(Sound sound, const Common::Path &filename);
 	void stop_sys(int channel);
 public:
 	SoundManager(Audio::Mixer *mixer);
diff --git a/engines/ultima/ultima4/ultima4.cpp b/engines/ultima/ultima4/ultima4.cpp
index 93bebcb76cf..0145a4c4947 100644
--- a/engines/ultima/ultima4/ultima4.cpp
+++ b/engines/ultima/ultima4/ultima4.cpp
@@ -186,7 +186,7 @@ Common::Error Ultima4Engine::run() {
 	return Common::kNoError;
 }
 
-bool Ultima4Engine::isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) {
+bool Ultima4Engine::isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) {
 	folder = "ultima4";
 	majorVersion = 1;
 	minorVersion = 0;
diff --git a/engines/ultima/ultima4/ultima4.h b/engines/ultima/ultima4/ultima4.h
index 720ad7dde7f..9f0db6ca9d4 100644
--- a/engines/ultima/ultima4/ultima4.h
+++ b/engines/ultima/ultima4/ultima4.h
@@ -64,7 +64,7 @@ protected:
 	/**
 	 * Returns the data archive folder and version that's required
 	 */
-	bool isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) override;
+	bool isDataRequired(Common::Path &folder, int &majorVersion, int &minorVersion) override;
 public:
 	Armors *_armors;
 	Codex *_codex;
diff --git a/engines/ultima/ultima8/filesys/savegame.cpp b/engines/ultima/ultima8/filesys/savegame.cpp
index 4434182b1ee..4a7b44e764a 100644
--- a/engines/ultima/ultima8/filesys/savegame.cpp
+++ b/engines/ultima/ultima8/filesys/savegame.cpp
@@ -38,7 +38,8 @@ class FileEntryArchive : public Common::Archive {
 		FileEntry() : _offset(0), _size(0) {}
 	};
 private:
-	Common::HashMap<Common::String, FileEntry> _index;
+	typedef Common::HashMap<Common::Path, FileEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> IndexMap;
+	IndexMap _index;
 	Common::SeekableReadStream *_file;
 
 public:
@@ -65,7 +66,7 @@ FileEntryArchive::FileEntryArchive(Common::SeekableReadStream *rs) : _file(rs) {
 		fe._size = _file->readUint32LE();
 		fe._offset = _file->pos();
 
-		_index[Common::String(name)] = fe;
+		_index[Common::Path(name, Common::Path::kNoSeparator)] = fe;
 		_file->skip(fe._size);
 	}
 }
@@ -74,12 +75,12 @@ FileEntryArchive::~FileEntryArchive() {
 }
 
 bool FileEntryArchive::hasFile(const Common::Path &path) const {
-	return _index.contains(path.toString());
+	return _index.contains(path);
 }
 
 int FileEntryArchive::listMembers(Common::ArchiveMemberList &list) const {
 	list.clear();
-	for (Common::HashMap<Common::String, FileEntry>::const_iterator it = _index.begin(); it != _index.end(); ++it)
+	for (IndexMap::const_iterator it = _index.begin(); it != _index.end(); ++it)
 		list.push_back(Common::ArchiveMemberPtr(new Common::GenericArchiveMember(it->_key, *this)));
 
 	return list.size();
@@ -89,14 +90,13 @@ const Common::ArchiveMemberPtr FileEntryArchive::getMember(const Common::Path &p
 	if (!hasFile(path))
 		return nullptr;
 
-	Common::String name = path.toString();
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *FileEntryArchive::createReadStreamForMember(const Common::Path &path) const {
-	assert(hasFile(path));
+	assert(_index.contains(path));
 
-	const FileEntry &fe = _index[path.toString()];
+	const FileEntry &fe = _index[path];
 	uint8 *data = (uint8 *)malloc(fe._size);
 	_file->seek(fe._offset);
 	_file->read(data, fe._size);
@@ -170,7 +170,7 @@ SavegameReader::State SavegameReader::isValid() const {
 	return SAVE_VALID;
 }
 
-Common::SeekableReadStream *SavegameReader::getDataSource(const Std::string &name) {
+Common::SeekableReadStream *SavegameReader::getDataSource(const Common::Path &name) {
 	assert(_archive);
 
 	return _archive->createReadStreamForMember(name);
diff --git a/engines/ultima/ultima8/filesys/savegame.h b/engines/ultima/ultima8/filesys/savegame.h
index 64595c6bc76..94601cd859d 100644
--- a/engines/ultima/ultima8/filesys/savegame.h
+++ b/engines/ultima/ultima8/filesys/savegame.h
@@ -53,7 +53,7 @@ public:
 	/**
 	 * Get an entry/section within the save
 	 */
-	Common::SeekableReadStream *getDataSource(const Std::string &name);
+	Common::SeekableReadStream *getDataSource(const Common::Path &name);
 };
 
 class SavegameWriter {
diff --git a/engines/ultima/ultima8/misc/debugger.cpp b/engines/ultima/ultima8/misc/debugger.cpp
index ec24c0b0d37..3a39af0323b 100644
--- a/engines/ultima/ultima8/misc/debugger.cpp
+++ b/engines/ultima/ultima8/misc/debugger.cpp
@@ -767,9 +767,9 @@ void Debugger::dumpCurrentMap() {
 	s->EndPainting();
 
 #ifdef USE_PNG
-	Std::string filename = Common::String::format("map_%03d.png", currentMap->getNum());
+	Common::Path filename(Common::String::format("map_%03d.png", currentMap->getNum()));
 #else
-	Std::string filename = Common::String::format("map_%03d.bmp", currentMap->getNum());
+	Common::Path filename(Common::String::format("map_%03d.bmp", currentMap->getNum()));
 #endif
 
 	Common::DumpFile dumpFile;
@@ -783,9 +783,9 @@ void Debugger::dumpCurrentMap() {
 	}
 
 	if (result) {
-		debugPrintf("Map dumped: %s\n", filename.c_str());
+		debugPrintf("Map dumped: %s\n", filename.toString().c_str());
 	} else {
-		debugPrintf("Could not write file: %s\n", filename.c_str());
+		debugPrintf("Could not write file: %s\n", filename.toString().c_str());
 	}
 
 	delete g;


Commit: 1968695f6e48143fe552659cc647c133d30fe9ae
    https://github.com/scummvm/scummvm/commit/1968695f6e48143fe552659cc647c133d30fe9ae
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
VCRUISE: Migrate engine to Path

Changed paths:
    engines/vcruise/runtime.cpp
    engines/vcruise/script.cpp
    engines/vcruise/script.h
    engines/vcruise/textparser.cpp
    engines/vcruise/textparser.h
    engines/vcruise/vcruise.cpp


diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index 14d81c26a3a..70d9865d322 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -421,11 +421,12 @@ void SfxData::load(Common::SeekableReadStream &stream, Audio::Mixer *mixer) {
 				sfxPath.trim();
 			}
 
-			sfxPath = Common::String("Sfx/") + sfxPath;
+			Common::Path sfxPath_("Sfx/");
+			sfxPath_.appendInPlace(sfxPath);
 
 			Common::File f;
-			if (!f.open(sfxPath)) {
-				warning("SfxData::load: Could not open sample file '%s'", sfxPath.c_str());
+			if (!f.open(sfxPath_)) {
+				warning("SfxData::load: Could not open sample file '%s'", sfxPath_.toString(Common::Path::kNativeSeparator).c_str());
 				continue;
 			}
 
@@ -2874,7 +2875,7 @@ void Runtime::changeToScreen(uint roomNumber, uint screenNumber) {
 		} else if (_gameID == GID_REAH) {
 			_scriptSet.reset();
 
-			Common::String logicFileName = Common::String::format("Log/Room%02i.log", static_cast<int>(roomNumber));
+			Common::Path logicFileName(Common::String::format("Log/Room%02i.log", static_cast<int>(roomNumber)));
 			Common::File logicFile;
 			if (logicFile.open(logicFileName)) {
 				_scriptSet = compileReahLogicFile(logicFile, static_cast<uint>(logicFile.size()), logicFileName);
@@ -2886,7 +2887,7 @@ void Runtime::changeToScreen(uint roomNumber, uint screenNumber) {
 
 		_map.clear();
 
-		Common::String mapFileName = Common::String::format("Map/Room%02i.map", static_cast<int>(roomNumber));
+		Common::Path mapFileName(Common::String::format("Map/Room%02i.map", static_cast<int>(roomNumber)));
 		Common::File mapFile;
 
 		if (mapFile.open(mapFileName)) {
@@ -3382,7 +3383,7 @@ void Runtime::changeMusicTrack(int track) {
 	if (_musicMute && !_musicMuteDisabled)
 		return;
 
-	Common::String wavFileName = Common::String::format("Sfx/Music-%02i.wav", static_cast<int>(track));
+	Common::Path wavFileName(Common::String::format("Sfx/Music-%02i.wav", static_cast<int>(track)));
 	Common::File *wavFile = new Common::File();
 	if (wavFile->open(wavFileName)) {
 		if (Audio::SeekableAudioStream *audioStream = Audio::makeWAVStream(wavFile, DisposeAfterUse::YES)) {
@@ -3392,7 +3393,7 @@ void Runtime::changeMusicTrack(int track) {
 			_musicPlayer->play(applyVolumeScale(_musicVolume), 0);
 		}
 	} else {
-		warning("Music file '%s' is missing", wavFileName.c_str());
+		warning("Music file '%s' is missing", wavFileName.toString(Common::Path::kNativeSeparator).c_str());
 		delete wavFile;
 	}
 }
@@ -3419,7 +3420,8 @@ void Runtime::startScoreSection() {
 			if (sectionDef.musicFileName.empty()) {
 				_scoreSectionEndTime = sectionDef.volumeOrDurationInSeconds * 1000u + g_system->getMillis();
 			} else {
-				Common::String trackFileName = Common::String("Sfx/") + sectionDef.musicFileName;
+				Common::Path trackFileName("Sfx/");
+				trackFileName.appendInPlace(sectionDef.musicFileName);
 
 				Common::File *trackFile = new Common::File();
 				if (trackFile->open(trackFileName)) {
@@ -3429,11 +3431,11 @@ void Runtime::startScoreSection() {
 
 						_scoreSectionEndTime = static_cast<uint32>(audioStream->getLength().msecs()) + g_system->getMillis();
 					} else {
-						warning("Couldn't create Vorbis stream for music file '%s'", trackFileName.c_str());
+						warning("Couldn't create Vorbis stream for music file '%s'", trackFileName.toString(Common::Path::kNativeSeparator).c_str());
 						delete trackFile;
 					}
 				} else {
-					warning("Music file '%s' is missing", trackFileName.c_str());
+					warning("Music file '%s' is missing", trackFileName.toString(Common::Path::kNativeSeparator).c_str());
 				}
 			}
 		}
@@ -3490,7 +3492,7 @@ void Runtime::changeAnimation(const AnimationDef &animDef, uint initialFrame, bo
 		_animDecoder.reset();
 		_animDecoderState = kAnimDecoderStateStopped;
 
-		Common::String aviFileName = Common::String::format("Anims/Anim%04i.avi", animFile);
+		Common::Path aviFileName(Common::String::format("Anims/Anim%04i.avi", animFile));
 		Common::File *aviFile = new Common::File();
 
 		if (aviFile->open(aviFileName)) {
@@ -3506,7 +3508,7 @@ void Runtime::changeAnimation(const AnimationDef &animDef, uint initialFrame, bo
 
 		applyAnimationVolume();
 
-		Common::String sfxFileName = Common::String::format("Sfx/Anim%04i.sfx", animFile);
+		Common::Path sfxFileName(Common::String::format("Sfx/Anim%04i.sfx", animFile));
 		Common::File sfxFile;
 
 		_sfxData.reset();
@@ -3515,14 +3517,14 @@ void Runtime::changeAnimation(const AnimationDef &animDef, uint initialFrame, bo
 			_sfxData.load(sfxFile, _mixer);
 		sfxFile.close();
 
-		Common::String dtaFileName = Common::String::format("Anims/Anim%04i.dta", animFile);
+		Common::Path dtaFileName(Common::String::format("Anims/Anim%04i.dta", animFile));
 		Common::File dtaFile;
 
 		if (dtaFile.open(dtaFileName))
 			loadFrameData(&dtaFile);
 		dtaFile.close();
 
-		Common::String twoDtFileName = Common::String::format("Dta/Anim%04i.2dt", animFile);
+		Common::Path twoDtFileName(Common::String::format("Dta/Anim%04i.2dt", animFile));
 		Common::File twoDtFile;
 
 		if (twoDtFile.open(twoDtFileName))
@@ -4231,11 +4233,11 @@ Common::SharedPtr<ScriptSet> Runtime::compileSchizmLogicSet(const uint *roomNumb
 		if (roomNumber < _roomDuplicationOffsets.size())
 			roomFile -= _roomDuplicationOffsets[roomNumber];
 
-		Common::String logicFileName = Common::String::format("Log/Room%02u.log", roomFile);
+		Common::Path logicFileName(Common::String::format("Log/Room%02u.log", roomFile));
 
 		Common::File logicFile;
 		if (logicFile.open(logicFileName)) {
-			debug(1, "Compiling script %s...", logicFileName.c_str());
+			debug(1, "Compiling script %s...", logicFileName.toString(Common::Path::kNativeSeparator).c_str());
 			compileSchizmLogicFile(*scriptSet, roomNumber, roomFile, logicFile, static_cast<uint>(logicFile.size()), logicFileName, gs.get());
 			logicFile.close();
 		}
@@ -4704,11 +4706,13 @@ Common::String Runtime::getFileNameForItemGraphic(uint itemID) const {
 }
 
 Common::SharedPtr<Graphics::Surface> Runtime::loadGraphic(const Common::String &graphicName, bool required) {
-	Common::String filePath = Common::String("Gfx/") + graphicName + ".bmp";
+	Common::Path filePath("Gfx/");
+	filePath.appendInPlace(graphicName);
+	filePath.appendInPlace(".bmp");
 
 	Common::File f;
 	if (!f.open(filePath)) {
-		warning("Couldn't open BMP file '%s'", filePath.c_str());
+		warning("Couldn't open BMP file '%s'", filePath.toString(Common::Path::kNativeSeparator).c_str());
 		return nullptr;
 	}
 
@@ -4718,7 +4722,7 @@ Common::SharedPtr<Graphics::Surface> Runtime::loadGraphic(const Common::String &
 
 	Image::BitmapDecoder bmpDecoder;
 	if (!bmpDecoder.loadStream(f)) {
-		warning("Failed to load BMP file '%s'", filePath.c_str());
+		warning("Failed to load BMP file '%s'", filePath.toString(Common::Path::kNativeSeparator).c_str());
 		return nullptr;
 	}
 
@@ -4729,7 +4733,7 @@ Common::SharedPtr<Graphics::Surface> Runtime::loadGraphic(const Common::String &
 }
 
 bool Runtime::loadSubtitles(Common::CodePage codePage, bool guessCodePage) {
-	Common::String filePath = Common::String::format("Log/Speech%02u.txt", _languageIndex);
+	Common::Path filePath(Common::String::format("Log/Speech%02u.txt", _languageIndex));
 
 	Common::INIFile ini;
 
diff --git a/engines/vcruise/script.cpp b/engines/vcruise/script.cpp
index 10359245b49..f86fe71f0b9 100644
--- a/engines/vcruise/script.cpp
+++ b/engines/vcruise/script.cpp
@@ -150,7 +150,7 @@ struct ScriptNamedInstruction {
 
 class ScriptCompiler {
 public:
-	ScriptCompiler(TextParser &parser, const Common::String &blamePath, ScriptDialect dialect, uint loadAsRoom, uint fileRoom, IScriptCompilerGlobalState *gs);
+	ScriptCompiler(TextParser &parser, const Common::Path &blamePath, ScriptDialect dialect, uint loadAsRoom, uint fileRoom, IScriptCompilerGlobalState *gs);
 
 	void compileScriptSet(ScriptSet *ss);
 
@@ -179,7 +179,7 @@ private:
 
 	TextParser &_parser;
 	NumberParsingMode _numberParsingMode;
-	const Common::String _blamePath;
+	const Common::Path _blamePath;
 
 	ScriptDialect _dialect;
 	uint _loadAsRoom;
@@ -226,7 +226,7 @@ private:
 	Common::Array<Common::SharedPtr<Script> > _functions;
 };
 
-ScriptCompiler::ScriptCompiler(TextParser &parser, const Common::String &blamePath, ScriptDialect dialect, uint loadAsRoom, uint fileRoom, IScriptCompilerGlobalState *gs)
+ScriptCompiler::ScriptCompiler(TextParser &parser, const Common::Path &blamePath, ScriptDialect dialect, uint loadAsRoom, uint fileRoom, IScriptCompilerGlobalState *gs)
 	: _numberParsingMode(kNumberParsingHex), _parser(parser), _blamePath(blamePath), _dialect(dialect), _loadAsRoom(loadAsRoom), _fileRoom(fileRoom), _gs(gs),
 	  _scrToken(nullptr), _eroomToken(nullptr) {
 }
@@ -1355,7 +1355,7 @@ ScriptSet::ScriptSet() {
 IScriptCompilerGlobalState::~IScriptCompilerGlobalState() {
 }
 
-static void compileLogicFile(ScriptSet &scriptSet, Common::ReadStream &stream, uint streamSize, const Common::String &blamePath, ScriptDialect dialect, uint loadAsRoom, uint fileRoom, IScriptCompilerGlobalState *gs) {
+static void compileLogicFile(ScriptSet &scriptSet, Common::ReadStream &stream, uint streamSize, const Common::Path &blamePath, ScriptDialect dialect, uint loadAsRoom, uint fileRoom, IScriptCompilerGlobalState *gs) {
 	LogicUnscrambleStream unscrambleStream(&stream, streamSize);
 	TextParser parser(&unscrambleStream);
 
@@ -1368,14 +1368,14 @@ Common::SharedPtr<IScriptCompilerGlobalState> createScriptCompilerGlobalState()
 	return Common::SharedPtr<IScriptCompilerGlobalState>(new ScriptCompilerGlobalState());
 }
 
-Common::SharedPtr<ScriptSet> compileReahLogicFile(Common::ReadStream &stream, uint streamSize, const Common::String &blamePath) {
+Common::SharedPtr<ScriptSet> compileReahLogicFile(Common::ReadStream &stream, uint streamSize, const Common::Path &blamePath) {
 	Common::SharedPtr<ScriptSet> scriptSet(new ScriptSet());
 
 	compileLogicFile(*scriptSet, stream, streamSize, blamePath, kScriptDialectReah, 0, 0, nullptr);
 	return scriptSet;
 }
 
-void compileSchizmLogicFile(ScriptSet &scriptSet, uint loadAsRoom, uint fileRoom, Common::ReadStream &stream, uint streamSize, const Common::String &blamePath, IScriptCompilerGlobalState *gs) {
+void compileSchizmLogicFile(ScriptSet &scriptSet, uint loadAsRoom, uint fileRoom, Common::ReadStream &stream, uint streamSize, const Common::Path &blamePath, IScriptCompilerGlobalState *gs) {
 	compileLogicFile(scriptSet, stream, streamSize, blamePath, kScriptDialectSchizm, loadAsRoom, fileRoom, gs);
 }
 
diff --git a/engines/vcruise/script.h b/engines/vcruise/script.h
index 6d4bc2492ca..39ff3dadcf1 100644
--- a/engines/vcruise/script.h
+++ b/engines/vcruise/script.h
@@ -284,8 +284,8 @@ struct IScriptCompilerGlobalState {
 };
 
 Common::SharedPtr<IScriptCompilerGlobalState> createScriptCompilerGlobalState();
-Common::SharedPtr<ScriptSet> compileReahLogicFile(Common::ReadStream &stream, uint streamSize, const Common::String &blamePath);
-void compileSchizmLogicFile(ScriptSet &scriptSet, uint loadAsRoom, uint fileRoom, Common::ReadStream &stream, uint streamSize, const Common::String &blamePath, IScriptCompilerGlobalState *gs);
+Common::SharedPtr<ScriptSet> compileReahLogicFile(Common::ReadStream &stream, uint streamSize, const Common::Path &blamePath);
+void compileSchizmLogicFile(ScriptSet &scriptSet, uint loadAsRoom, uint fileRoom, Common::ReadStream &stream, uint streamSize, const Common::Path &blamePath, IScriptCompilerGlobalState *gs);
 bool checkSchizmLogicForDuplicatedRoom(Common::ReadStream &stream, uint streamSize);
 void optimizeScriptSet(ScriptSet &scriptSet);
 
diff --git a/engines/vcruise/textparser.cpp b/engines/vcruise/textparser.cpp
index 03f3d355b77..f98514279ca 100644
--- a/engines/vcruise/textparser.cpp
+++ b/engines/vcruise/textparser.cpp
@@ -19,6 +19,7 @@
  *
  */
 
+#include "common/path.h"
 #include "common/stream.h"
 #include "common/textconsole.h"
 
@@ -125,36 +126,36 @@ void TextParser::requeue(const Common::String &str, const TextParserState &state
 	requeue(str.c_str(), str.size(), state);
 }
 
-void TextParser::expectToken(Common::String &outToken, const Common::String &blamePath) {
+void TextParser::expectToken(Common::String &outToken, const Common::Path &blamePath) {
 	TextParserState state;
 	expectTokenInternal(outToken, blamePath, state);
 }
 
-void TextParser::expectShort(int16 &outInt, const Common::String &blamePath) {
+void TextParser::expectShort(int16 &outInt, const Common::Path &blamePath) {
 	int i;
 	expectInt(i, blamePath);
 	outInt = static_cast<int16>(i);
 }
 
-void TextParser::expectInt(int &outInt, const Common::String &blamePath) {
+void TextParser::expectInt(int &outInt, const Common::Path &blamePath) {
 	Common::String token;
 	TextParserState state;
 	expectTokenInternal(token, blamePath, state);
 
 	if (!sscanf(token.c_str(), "%i", &outInt))
-		error("Parsing error in '%s' at line %i col %i: Integer was malformed", blamePath.c_str(), static_cast<int>(state._lineNum), static_cast<int>(state._col));
+		error("Parsing error in '%s' at line %i col %i: Integer was malformed", blamePath.toString(Common::Path::kNativeSeparator).c_str(), static_cast<int>(state._lineNum), static_cast<int>(state._col));
 }
 
-void TextParser::expectUInt(uint &outUInt, const Common::String &blamePath) {
+void TextParser::expectUInt(uint &outUInt, const Common::Path &blamePath) {
 	Common::String token;
 	TextParserState state;
 	expectTokenInternal(token, blamePath, state);
 
 	if (!sscanf(token.c_str(), "%u", &outUInt))
-		error("Parsing error in '%s' at line %i col %i: Unsigned integer was malformed", blamePath.c_str(), static_cast<int>(state._lineNum), static_cast<int>(state._col));
+		error("Parsing error in '%s' at line %i col %i: Unsigned integer was malformed", blamePath.toString(Common::Path::kNativeSeparator).c_str(), static_cast<int>(state._lineNum), static_cast<int>(state._col));
 }
 
-void TextParser::expectLine(Common::String &outToken, const Common::String &blamePath, bool continueToNextLine) {
+void TextParser::expectLine(Common::String &outToken, const Common::Path &blamePath, bool continueToNextLine) {
 	outToken.clear();
 
 	char c = 0;
@@ -187,13 +188,13 @@ void TextParser::expectLine(Common::String &outToken, const Common::String &blam
 		outToken = outToken.substr(0, nonWhitespaceLength);
 }
 
-void TextParser::expect(const char *str, const Common::String &blamePath) {
+void TextParser::expect(const char *str, const Common::Path &blamePath) {
 	Common::String token;
 	TextParserState state;
 	expectTokenInternal(token, blamePath, state);
 
 	if (token != str)
-		error("Parsing error in '%s' at line %i col %i: Expected token '%s' but found '%s'", blamePath.c_str(), static_cast<int>(state._lineNum), static_cast<int>(state._col), str, token.c_str());
+		error("Parsing error in '%s' at line %i col %i: Expected token '%s' but found '%s'", blamePath.toString(Common::Path::kNativeSeparator).c_str(), static_cast<int>(state._lineNum), static_cast<int>(state._col), str, token.c_str());
 }
 
 void TextParser::skipToEOL() {
@@ -236,9 +237,9 @@ bool TextParser::checkEOL() {
 	}
 }
 
-void TextParser::expectTokenInternal(Common::String &outToken, const Common::String &blamePath, TextParserState &outState) {
+void TextParser::expectTokenInternal(Common::String &outToken, const Common::Path &blamePath, TextParserState &outState) {
 	if (!parseToken(outToken, outState))
-		error("Parsing error in '%s' unexpected end of file", blamePath.c_str());
+		error("Parsing error in '%s' unexpected end of file", blamePath.toString(Common::Path::kNativeSeparator).c_str());
 }
 
 bool TextParser::parseToken(Common::String &outString, TextParserState &outState) {
diff --git a/engines/vcruise/textparser.h b/engines/vcruise/textparser.h
index f62dbaa690d..cde9902e572 100644
--- a/engines/vcruise/textparser.h
+++ b/engines/vcruise/textparser.h
@@ -29,6 +29,7 @@
 
 namespace Common {
 
+class Path;
 class ReadStream;
 
 } // End of namespace Common
@@ -56,19 +57,19 @@ public:
 	void requeue(const char *chars, uint numChars, const TextParserState &state);
 	void requeue(const Common::String &str, const TextParserState &state);
 
-	void expectToken(Common::String &outToken, const Common::String &blamePath);
-	void expectShort(int16 &outInt, const Common::String &blamePath);
-	void expectInt(int &outInt, const Common::String &blamePath);
-	void expectUInt(uint &outUInt, const Common::String &blamePath);
-	void expectLine(Common::String &outToken, const Common::String &blamePath, bool continueToNextLine);
+	void expectToken(Common::String &outToken, const Common::Path &blamePath);
+	void expectShort(int16 &outInt, const Common::Path &blamePath);
+	void expectInt(int &outInt, const Common::Path &blamePath);
+	void expectUInt(uint &outUInt, const Common::Path &blamePath);
+	void expectLine(Common::String &outToken, const Common::Path &blamePath, bool continueToNextLine);
 
-	void expect(const char *str, const Common::String &blamePath);
+	void expect(const char *str, const Common::Path &blamePath);
 
 	void skipToEOL();
 	bool checkEOL();
 
 private:
-	void expectTokenInternal(Common::String &outToken, const Common::String &blamePath, TextParserState &outState);
+	void expectTokenInternal(Common::String &outToken, const Common::Path &blamePath, TextParserState &outState);
 
 	static bool isDelimiter(char c);
 	static bool isCompoundDelimiter(char c1, char c2);
diff --git a/engines/vcruise/vcruise.cpp b/engines/vcruise/vcruise.cpp
index e3cc7490be1..e9546bd73f5 100644
--- a/engines/vcruise/vcruise.cpp
+++ b/engines/vcruise/vcruise.cpp
@@ -42,7 +42,7 @@
 namespace VCruise {
 
 VCruiseEngine::VCruiseEngine(OSystem *syst, const VCruiseGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 }
 
 VCruiseEngine::~VCruiseEngine() {


Commit: 17ceed4eb324657d654812b0517b44294606167b
    https://github.com/scummvm/scummvm/commit/17ceed4eb324657d654812b0517b44294606167b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
VOYEUR: Migrate engine to Path

Changed paths:
    engines/voyeur/animation.cpp
    engines/voyeur/animation.h
    engines/voyeur/files.cpp
    engines/voyeur/files.h
    engines/voyeur/files_threads.cpp
    engines/voyeur/sound.cpp
    engines/voyeur/sound.h
    engines/voyeur/voyeur.cpp
    engines/voyeur/voyeur.h
    engines/voyeur/voyeur_game.cpp


diff --git a/engines/voyeur/animation.cpp b/engines/voyeur/animation.cpp
index 2f5f9395ee4..96587d31946 100644
--- a/engines/voyeur/animation.cpp
+++ b/engines/voyeur/animation.cpp
@@ -47,12 +47,12 @@ RL2Decoder::~RL2Decoder() {
 }
 
 bool RL2Decoder::loadVideo(int videoId) {
-	Common::String filename = Common::String::format("%s.rl2",
-		::Voyeur::SZ_FILENAMES[videoId * 2]);
+	Common::Path filename(Common::String::format("%s.rl2",
+		::Voyeur::SZ_FILENAMES[videoId * 2]));
 	return loadRL2File(filename, false);
 }
 
-bool RL2Decoder::loadRL2File(const Common::String &file, bool palFlag) {
+bool RL2Decoder::loadRL2File(const Common::Path &file, bool palFlag) {
 	bool result = VideoDecoder::loadFile(file);
 	_paletteStart = palFlag ? 0 : 128;
 	return result;
diff --git a/engines/voyeur/animation.h b/engines/voyeur/animation.h
index b891b80922c..1b56952f6f2 100644
--- a/engines/voyeur/animation.h
+++ b/engines/voyeur/animation.h
@@ -173,7 +173,7 @@ public:
 	void close() override;
 
 	bool loadStream(Common::SeekableReadStream *stream) override;
-	bool loadRL2File(const Common::String &file, bool palFlag);
+	bool loadRL2File(const Common::Path &file, bool palFlag);
 	bool loadVideo(int videoId);
 	int getPaletteCount() const { return _header._colorCount; }
 
diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp
index f3d68aaa1a6..2e31beaffc6 100644
--- a/engines/voyeur/files.cpp
+++ b/engines/voyeur/files.cpp
@@ -180,16 +180,16 @@ FilesManager::~FilesManager() {
 	delete _boltFilesState;
 }
 
-bool FilesManager::openBoltLib(const Common::String &filename, BoltFile *&boltFile) {
+bool FilesManager::openBoltLib(const char *filename, BoltFile *&boltFile) {
 	if (boltFile != nullptr) {
 		_boltFilesState->_curLibPtr = boltFile;
 		return true;
 	}
 
 	// Create the bolt file interface object and load the index
-	if (filename == "bvoy.blt")
+	if (strcmp(filename, "bvoy.blt") == 0)
 		boltFile = _boltFilesState->_curLibPtr = new BVoyBoltFile(*_boltFilesState);
-	else if (filename == "stampblt.blt")
+	else if (strcmp(filename, "stampblt.blt") == 0)
 		boltFile = _boltFilesState->_curLibPtr = new StampBoltFile(*_boltFilesState);
 	else
 		error("Unknown bolt file specified");
@@ -197,7 +197,7 @@ bool FilesManager::openBoltLib(const Common::String &filename, BoltFile *&boltFi
 	return true;
 }
 
-byte *FilesManager::fload(const Common::String &filename, int *size) {
+byte *FilesManager::fload(const char *filename, int *size) {
 	Common::File f;
 	int filesize;
 	byte *data = nullptr;
@@ -218,9 +218,9 @@ byte *FilesManager::fload(const Common::String &filename, int *size) {
 
 /*------------------------------------------------------------------------*/
 
-BoltFile::BoltFile(const Common::String &filename, BoltFilesState &state): _state(state) {
+BoltFile::BoltFile(const char *filename, BoltFilesState &state): _state(state) {
 	if (!_file.open(filename))
-		error("Could not open %s", filename.c_str());
+		error("Could not open %s", filename);
 
 	// Read in the file header
 	byte header[16];
diff --git a/engines/voyeur/files.h b/engines/voyeur/files.h
index 540de9b4de1..672bde3173b 100644
--- a/engines/voyeur/files.h
+++ b/engines/voyeur/files.h
@@ -102,7 +102,7 @@ private:
 public:
 	Common::File _file;
 
-	BoltFile(const Common::String &filename, BoltFilesState &state);
+	BoltFile(const char *filename, BoltFilesState &state);
 	virtual ~BoltFile();
 
 	BoltGroup *getBoltGroup(uint16 id);
@@ -209,8 +209,8 @@ public:
 	FilesManager(VoyeurEngine *vm);
 	~FilesManager();
 
-	bool openBoltLib(const Common::String &filename, BoltFile *&boltFile);
-	byte *fload(const Common::String &filename, int *size);
+	bool openBoltLib(const char *filename, BoltFile *&boltFile);
+	byte *fload(const char *filename, int *size);
 };
 
 class RectEntry: public Common::Rect {
diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp
index 9ad98489ad0..837b18f5826 100644
--- a/engines/voyeur/files_threads.cpp
+++ b/engines/voyeur/files_threads.cpp
@@ -471,7 +471,7 @@ void ThreadResource::parsePlayCommands() {
 						_vm->_bVoy->freeBoltMember(_vm->_playStampGroupId + i * 2 + 1);
 					}
 
-					Common::String file = Common::String::format("news%d.voc", i + 1);
+					Common::Path file(Common::String::format("news%d.voc", i + 1));
 					_vm->_soundManager->startVOCPlay(file);
 
 					while (!_vm->shouldQuit() && !_vm->_eventsManager->_mouseClicked &&
@@ -1343,7 +1343,7 @@ int ThreadResource::doInterface() {
 	_vm->_currentVocId = 151 - _vm->getRandomNumber(5);
 	_vm->_voy->_vocSecondsOffset = _vm->getRandomNumber(29);
 
-	Common::String fname = _vm->_soundManager->getVOCFileName(_vm->_currentVocId);
+	Common::Path fname = _vm->_soundManager->getVOCFileName(_vm->_currentVocId);
 	_vm->_soundManager->startVOCPlay(fname);
 	_vm->_eventsManager->getMouseInfo();
 
diff --git a/engines/voyeur/sound.cpp b/engines/voyeur/sound.cpp
index 0708874f064..426d29f7b99 100644
--- a/engines/voyeur/sound.cpp
+++ b/engines/voyeur/sound.cpp
@@ -54,15 +54,15 @@ void SoundManager::setVOCOffset(int offset) {
 	_vocOffset = offset;
 }
 
-Common::String SoundManager::getVOCFileName(int idx) {
+Common::Path SoundManager::getVOCFileName(int idx) {
 	assert(idx >= 0);
-	return Common::String::format("%s.voc", SZ_FILENAMES[idx]);
+	return Common::Path(Common::String::format("%s.voc", SZ_FILENAMES[idx]));
 }
 
-void SoundManager::startVOCPlay(const Common::String &filename) {
+void SoundManager::startVOCPlay(const Common::Path &filename) {
 	Common::File f;
 	if (!f.open(filename))
-		error("Could not find voc file - %s", filename.c_str());
+		error("Could not find voc file - %s", filename.toString().c_str());
 
 	Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()),
 		Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
diff --git a/engines/voyeur/sound.h b/engines/voyeur/sound.h
index 807626a8af2..332c38da8de 100644
--- a/engines/voyeur/sound.h
+++ b/engines/voyeur/sound.h
@@ -23,7 +23,7 @@
 #define VOYEUR_SOUND_H
 
 #include "common/scummsys.h"
-#include "common/str.h"
+#include "common/path.h"
 #include "audio/mixer.h"
 
 namespace Voyeur {
@@ -40,8 +40,8 @@ public:
 	void stopVOCPlay();
 	void abortVOCMap();
 	void setVOCOffset(int offset);
-	Common::String getVOCFileName(int idx);
-	void startVOCPlay(const Common::String &filename);
+	Common::Path getVOCFileName(int idx);
+	void startVOCPlay(const Common::Path &filename);
 	void startVOCPlay(int soundId);
 	int getVOCStatus();
 	uint32 getVOCFrame();
diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp
index 1d8ab81d3a4..e0fc1872a7a 100644
--- a/engines/voyeur/voyeur.cpp
+++ b/engines/voyeur/voyeur.cpp
@@ -528,7 +528,7 @@ void VoyeurEngine::doOpening() {
 	_bVoy->freeBoltGroup(0x200);
 }
 
-void VoyeurEngine::playRL2Video(const Common::String &filename) {
+void VoyeurEngine::playRL2Video(const Common::Path &filename) {
 	RL2Decoder decoder;
 	decoder.loadRL2File(filename, false);
 	decoder.start();
@@ -625,7 +625,7 @@ void VoyeurEngine::playAudio(int audioId) {
 
 	_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
 	_soundManager->setVOCOffset(_voy->_vocSecondsOffset);
-	Common::String filename = _soundManager->getVOCFileName(
+	Common::Path filename = _soundManager->getVOCFileName(
 		audioId + 159);
 	_soundManager->startVOCPlay(filename);
 	_voy->_eventFlags |= EVTFLAG_RECORDING;
@@ -726,7 +726,7 @@ void VoyeurEngine::showEndingNews() {
 		_bVoy->freeBoltMember(_playStampGroupId + (idx - 1) * 2);
 		_bVoy->freeBoltMember(_playStampGroupId + (idx - 1) * 2 + 1);
 
-		Common::String fname = Common::String::format("news%d.voc", idx);
+		Common::Path fname(Common::String::format("news%d.voc", idx));
 		_soundManager->startVOCPlay(fname);
 
 		_eventsManager->getMouseInfo();
diff --git a/engines/voyeur/voyeur.h b/engines/voyeur/voyeur.h
index 8789923abfa..86d5630a614 100644
--- a/engines/voyeur/voyeur.h
+++ b/engines/voyeur/voyeur.h
@@ -210,7 +210,7 @@ public:
 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
 	void loadGame(int slot);
 
-	void playRL2Video(const Common::String &filename);
+	void playRL2Video(const Common::Path &filename);
 	void doTransitionCard(const Common::String &time, const Common::String &location);
 
 	/**
diff --git a/engines/voyeur/voyeur_game.cpp b/engines/voyeur/voyeur_game.cpp
index 2e8002688e9..d4b34074a63 100644
--- a/engines/voyeur/voyeur_game.cpp
+++ b/engines/voyeur/voyeur_game.cpp
@@ -695,7 +695,7 @@ void VoyeurEngine::reviewTape() {
 
 			// Play sound for the given duration
 			_soundManager->setVOCOffset(_voy->_vocSecondsOffset);
-			Common::String filename = _soundManager->getVOCFileName(
+			Common::Path filename = _soundManager->getVOCFileName(
 				_audioVideoId + 159);
 			_soundManager->startVOCPlay(filename);
 


Commit: dd374a778e42eae95aaaa708360ad75ef6f9f0e9
    https://github.com/scummvm/scummvm/commit/dd374a778e42eae95aaaa708360ad75ef6f9f0e9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
WATCHMAKER: Migrate engine to Path

Changed paths:
    engines/watchmaker/ll/ll_system.cpp


diff --git a/engines/watchmaker/ll/ll_system.cpp b/engines/watchmaker/ll/ll_system.cpp
index 1a707c5b175..5632ac5e868 100644
--- a/engines/watchmaker/ll/ll_system.cpp
+++ b/engines/watchmaker/ll/ll_system.cpp
@@ -128,24 +128,24 @@ bool t3dGetFileDate(uint32 *date, uint32 *time, const char *name) {
 	return checkFileExists(name);
 }
 
-Common::String adjustPath(const Common::String &path) {
-	Common::String adjustedPath;
+Common::Path adjustPath(const Common::String &path) {
+	Common::Path adjustedPath;
 	if (path.hasPrefix("./")) {
-		adjustedPath = path.substr(2, path.size());
+		adjustedPath = Common::Path(path.substr(2, path.size()));
 	} else {
-		adjustedPath = path;
+		adjustedPath = Common::Path(path);
 	}
 	return adjustedPath;
 }
 
 bool checkFileExists(const Common::String &filename) {
-	Common::String adjustedPath = adjustPath(filename);
+	Common::Path adjustedPath = adjustPath(filename);
 
 	return SearchMan.hasFile(adjustedPath);
 }
 
 Common::SharedPtr<Common::SeekableReadStream> openFile(const Common::String &filename, int offset, int size) {
-	Common::String adjustedPath = adjustPath(filename);
+	Common::Path adjustedPath = adjustPath(filename);
 
 	Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(adjustedPath);
 


Commit: ca31647aeba983e45bdfac094b62a0dedcb43588
    https://github.com/scummvm/scummvm/commit/ca31647aeba983e45bdfac094b62a0dedcb43588
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
WAGE: Migrate engine to Path

Changed paths:
    engines/wage/script.cpp
    engines/wage/wage.cpp
    engines/wage/world.cpp
    engines/wage/world.h


diff --git a/engines/wage/script.cpp b/engines/wage/script.cpp
index 7b3d31df4ff..e255012dcad 100644
--- a/engines/wage/script.cpp
+++ b/engines/wage/script.cpp
@@ -106,15 +106,15 @@ Script::Script(Common::SeekableReadStream *data, int num, WageEngine *engine) :
 
 	if (ConfMan.getBool("dump_scripts")) {
 		Common::DumpFile out;
-		Common::String name;
+		Common::Path name;
 
 		if (num == -1)
-			name = Common::String::format("./dumps/%s-global.txt", _engine->getTargetName());
+			name = Common::Path(Common::String::format("./dumps/%s-global.txt", _engine->getTargetName()));
 		else
-			name = Common::String::format("./dumps/%s-%d.txt", _engine->getTargetName(), num);
+			name = Common::Path(Common::String::format("./dumps/%s-%d.txt", _engine->getTargetName(), num));
 
 		if (!out.open(name)) {
-			warning("Can not open dump file %s", name.c_str());
+			warning("Can not open dump file %s", name.toString().c_str());
 			return;
 		}
 
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
index b37a630edc0..8c852b14809 100644
--- a/engines/wage/wage.cpp
+++ b/engines/wage/wage.cpp
@@ -124,7 +124,7 @@ Common::Error WageEngine::run() {
 
 	// Your main event loop should be (invoked from) here.
 	_resManager = new Common::MacResManager();
-	if (!_resManager->open(Common::Path(getGameFile()).punycodeDecode().toString('/')))
+	if (!_resManager->open(Common::Path(getGameFile()).punycodeDecode()))
 		error("Could not open %s as a resource fork", getGameFile());
 
 	_world = new World(this);
diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp
index 5eec4ebdc57..7e8ba7f6faf 100644
--- a/engines/wage/world.cpp
+++ b/engines/wage/world.cpp
@@ -160,11 +160,11 @@ bool World::loadWorld(Common::MacResManager *resMan) {
 		res->skip(3);
 		_aboutMessage = res->readPascalString();
 
-		if (!scumm_stricmp(resMan->getBaseFileName().toString().c_str(), "Scepters"))
+		if (!scumm_stricmp(_name.c_str(), "Scepters"))
 			res->skip(1); // ????
 
-		_soundLibrary1 = res->readPascalString();
-		_soundLibrary2 = res->readPascalString();
+		_soundLibrary1 = Common::Path(res->readPascalString());
+		_soundLibrary2 = Common::Path(res->readPascalString());
 
 		delete res;
 	}
@@ -390,10 +390,10 @@ void World::addSound(Sound *sound) {
 	_orderedSounds.push_back(sound);
 }
 
-void World::loadExternalSounds(Common::String fname) {
+void World::loadExternalSounds(const Common::Path &fname) {
 	Common::MacResManager resMan;
 	if (!resMan.open(fname)) {
-		warning("Cannot load sound file <%s>", fname.c_str());
+		warning("Cannot load sound file <%s>", fname.toString().c_str());
 		return;
 	}
 
diff --git a/engines/wage/world.h b/engines/wage/world.h
index d24a5660918..fac057a8a11 100644
--- a/engines/wage/world.h
+++ b/engines/wage/world.h
@@ -64,7 +64,7 @@ public:
 	~World();
 
 	bool loadWorld(Common::MacResManager *resMan);
-	void loadExternalSounds(Common::String fname);
+	void loadExternalSounds(const Common::Path &fname);
 	Common::String *loadStringFromDITL(Common::MacResManager *resMan, int resourceId, int itemIndex);
 	void move(Obj *obj, Chr *chr);
 	void move(Obj *obj, Scene *scene, bool skipSort = false);
@@ -78,8 +78,8 @@ public:
 
 	Common::String _name;
 	Common::String _aboutMessage;
-	Common::String _soundLibrary1;
-	Common::String _soundLibrary2;
+	Common::Path _soundLibrary1;
+	Common::Path _soundLibrary2;
 
 	bool _weaponMenuDisabled;
 	Script *_globalScript;


Commit: bdb515b913c840d3e1d28d42e34fa6a2ba016f9e
    https://github.com/scummvm/scummvm/commit/bdb515b913c840d3e1d28d42e34fa6a2ba016f9e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
WINTERMUTE: Migrate engine to Path

Changed paths:
    engines/wintermute/base/base_file_manager.cpp
    engines/wintermute/base/file/base_disk_file.cpp
    engines/wintermute/base/file/base_file_entry.h
    engines/wintermute/base/font/base_font_truetype.cpp
    engines/wintermute/debugger.cpp
    engines/wintermute/debugger/debugger_controller.cpp
    engines/wintermute/debugger/debugger_controller.h
    engines/wintermute/debugger/listing_provider.h
    engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp
    engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h
    engines/wintermute/debugger/listing_providers/blank_listing.cpp
    engines/wintermute/debugger/listing_providers/blank_listing.h
    engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp
    engines/wintermute/debugger/listing_providers/blank_listing_provider.h
    engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp
    engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h
    engines/wintermute/debugger/listing_providers/source_listing_provider.h
    engines/wintermute/metaengine.cpp
    engines/wintermute/wintermute.cpp


diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp
index 693d8fdf34b..449f8ab25da 100644
--- a/engines/wintermute/base/base_file_manager.cpp
+++ b/engines/wintermute/base/base_file_manager.cpp
@@ -159,7 +159,7 @@ bool BaseFileManager::initPaths() {
 	// Removed: Config-based file-path choice.
 
 	// package files paths
-	const Common::FSNode gameData(ConfMan.get("path"));
+	const Common::FSNode gameData(ConfMan.getPath("path"));
 	addPath(PATH_PACKAGE, gameData);
 
 	Common::FSNode dataSubFolder = gameData.getChild("data");
@@ -201,7 +201,7 @@ bool BaseFileManager::registerPackages() {
 	// and that has to be like that to support the detection-scheme.
 	Common::FSList files;
 	for (Common::FSList::const_iterator it = _packagePaths.begin(); it != _packagePaths.end(); ++it) {
-		debugC(kWintermuteDebugFileAccess, "Should register folder: %s %s", it->getPath().c_str(), it->getName().c_str());
+		debugC(kWintermuteDebugFileAccess, "Should register folder: %s %s", it->getPath().toString(Common::Path::kNativeSeparator).c_str(), it->getName().c_str());
 		if (!it->getChildren(files, Common::FSNode::kListFilesOnly)) {
 			warning("getChildren() failed for path: %s", it->getName().c_str());
 		}
@@ -316,7 +316,7 @@ bool BaseFileManager::registerPackages() {
 					continue;
 				}
 			}
-			debugC(kWintermuteDebugFileAccess, "Registering %s %s", fileIt->getPath().c_str(), fileIt->getName().c_str());
+			debugC(kWintermuteDebugFileAccess, "Registering %s %s", fileIt->getPath().toString(Common::Path::kNativeSeparator).c_str(), fileIt->getName().c_str());
 			registerPackage((*fileIt), fileName, searchSignature);
 		}
 	}
@@ -358,7 +358,7 @@ Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &f
 			upcName.setChar('\\', (uint32)i);
 		}
 	}
-	Common::ArchiveMemberPtr entry = _packages.getMember(upcName);
+	Common::ArchiveMemberPtr entry = _packages.getMember(Common::Path(upcName, '\\'));
 	if (!entry) {
 		return nullptr;
 	}
@@ -377,9 +377,13 @@ uint32 BaseFileManager::getPackageVersion(const Common::String &filename) {
 
 //////////////////////////////////////////////////////////////////////////
 bool BaseFileManager::hasFile(const Common::String &filename) {
-	Common::String backwardSlashesPath = filename;
-	// correct slashes
-	Common::replace(backwardSlashesPath.begin(), backwardSlashesPath.end(), '/', '\\');
+	Common::String backslashPath(filename);
+	for (uint32 i = 0; i < backslashPath.size(); i++) {
+		if (backslashPath[(int32)i] == '/') {
+			backslashPath.setChar('\\', (uint32)i);
+		}
+	}
+	Common::Path path(backslashPath, '\\');
 
 	if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) {
 		BasePersistenceManager pm(BaseEngine::instance().getGameTargetName());
@@ -395,10 +399,10 @@ bool BaseFileManager::hasFile(const Common::String &filename) {
 	if (diskFileExists(filename)) {
 		return true;
 	}
-	if (_packages.hasFile(backwardSlashesPath)) {
+	if (_packages.hasFile(path)) {
 		return true;    // We don't bother checking if the file can actually be opened, something bigger is wrong if that is the case.
 	}
-	if (!_detectionMode && _resources->hasFile(filename)) {
+	if (!_detectionMode && _resources->hasFile(path)) {
 		return true;
 	}
 	return false;
@@ -406,7 +410,7 @@ bool BaseFileManager::hasFile(const Common::String &filename) {
 
 //////////////////////////////////////////////////////////////////////////
 int BaseFileManager::listMatchingPackageMembers(Common::ArchiveMemberList &list, const Common::String &pattern) {
-	return _packages.listMatchingMembers(list, pattern);
+	return _packages.listMatchingMembers(list, Common::Path(pattern));
 }
 
 //////////////////////////////////////////////////////////////////////////
@@ -493,7 +497,7 @@ Common::SeekableReadStream *BaseFileManager::openFileRaw(const Common::String &f
 	}
 
 	if (!_detectionMode) {
-		ret = _resources->createReadStreamForMember(filename);
+		ret = _resources->createReadStreamForMember(Common::Path(filename));
 	}
 	if (ret) {
 		return ret;
diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp
index b672eba729e..c0f36a3b299 100644
--- a/engines/wintermute/base/file/base_disk_file.cpp
+++ b/engines/wintermute/base/file/base_disk_file.cpp
@@ -40,12 +40,14 @@
 
 namespace Wintermute {
 
-void correctSlashes(Common::String &fileName) {
-	for (size_t i = 0; i < fileName.size(); i++) {
-		if (fileName[i] == '\\') {
-			fileName.setChar('/', i);
+Common::Path correctSlashes(const Common::String &fileName) {
+	Common::String ret(fileName);
+	for (size_t i = 0; i < ret.size(); i++) {
+		if (ret[i] == '\\') {
+			ret.setChar('/', i);
 		}
 	}
+	return Common::Path(ret);
 }
 
 // Parse a relative path in the game-folder, and if it exists, return a FSNode to it.
@@ -60,42 +62,22 @@ static Common::FSNode getNodeForRelativePath(const Common::String &filename) {
 	}
 
 	// Relative path:
-	Common::String fixedFilename = filename;
-	correctSlashes(fixedFilename);
-	if (fixedFilename.contains('/')) {
-		Common::StringTokenizer path(fixedFilename, "/");
-
-		// Start traversing relative to the game-data-dir
-		const Common::FSNode gameDataDir(ConfMan.get("path"));
-		Common::FSNode curNode = gameDataDir;
-
-		// Parse all path-elements
-		while (!path.empty()) {
-			// Get the next path-component by slicing on '/'
-			Common::String pathPart = path.nextToken();
-			// Get the next FSNode in the chain, if it exists as a child from the previous.
-			curNode = curNode.getChild(pathPart);
-			if (!curNode.isReadable()) {
-				// Return an invalid FSNode.
-				return Common::FSNode();
-			}
-			// Following the comments in common/fs.h, anything not a directory is a file.
-			if (!curNode.isDirectory()) {
-				if (!path.empty()) {
-					error("Relative path %s reached a file before the end of the path", filename.c_str());
-				}
-				return curNode;
-			}
-		}
+	Common::Path fixedFilename = correctSlashes(filename);
+	Common::Path absolutePath(ConfMan.getPath("path"));
+	absolutePath.joinInPlace(fixedFilename);
+
+	Common::FSNode node(absolutePath);
+	if (node.exists()) {
+		return node;
+	} else {
+		return Common::FSNode();
 	}
-	// Return an invalid FSNode to mark that we didn't find the requested file.
-	return Common::FSNode();
 }
 
 bool diskFileExists(const Common::String &filename) {
 	// Try directly from SearchMan first
 	Common::ArchiveMemberList files;
-	SearchMan.listMatchingMembers(files, filename);
+	SearchMan.listMatchingMembers(files, Common::Path(filename));
 
 	for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
 		if ((*it)->getName() == filename) {
@@ -112,19 +94,18 @@ bool diskFileExists(const Common::String &filename) {
 
 
 int listMatchingDiskFileMembers(Common::ArchiveMemberList &list, const Common::String &pattern) {
-	return Common::FSDirectory(ConfMan.get("path")).listMatchingMembers(list, pattern);
+	return Common::FSDirectory(ConfMan.getPath("path")).listMatchingMembers(list, Common::Path(pattern));
 }
 
 Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
 	uint32 prefixSize = 0;
 	Common::SeekableReadStream *file = nullptr;
-	Common::String fixedFilename = filename;
-	correctSlashes(fixedFilename);
+	Common::Path fixedFilename = correctSlashes(filename);
 
 	// HACK: There are a few games around which mistakenly refer to absolute paths in the scripts.
 	// The original interpreter on Windows usually simply ignores them when it can't find them.
 	// We try to turn the known ones into relative paths.
-	if (fixedFilename.contains(':')) {
+	if (filename.contains(':')) {
 		const char* const knownPrefixes[] = { // Known absolute paths
 				"c:/documents and settings/radimk/plocha/projekt/", // Basis Octavus refers to several files named "c:\documents and settings\radimk\plocha\projekt\sprites\clock*.bmp"
 				"c:/program files/wme devkit beta/projects/amu/data/", // Five Magical Amulets refers to "c:\program files\wme devkit beta\projects\amu\data\scenes\prvnimenu\scr\scene_init.script"
@@ -158,8 +139,9 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
 		bool matched = false;
 
 		for (uint i = 0; i < ARRAYSIZE(knownPrefixes); i++) {
-			if (fixedFilename.hasPrefix(knownPrefixes[i])) {
-				fixedFilename = fixedFilename.c_str() + strlen(knownPrefixes[i]);
+			Common::Path root(knownPrefixes[i], '/');
+			if (fixedFilename.isRelativeTo(root)) {
+				fixedFilename = fixedFilename.relativeTo(root);
 				matched = true;
 			}
 		}
@@ -175,7 +157,7 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
 	SearchMan.listMatchingMembers(files, fixedFilename);
 
 	for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
-		if ((*it)->getName().equalsIgnoreCase(lastPathComponent(fixedFilename,'/'))) {
+		if ((*it)->getName().equalsIgnoreCase(fixedFilename.baseName())) {
 			file = (*it)->createReadStream();
 			break;
 		}
diff --git a/engines/wintermute/base/file/base_file_entry.h b/engines/wintermute/base/file/base_file_entry.h
index 9f53377d8dd..160ba585286 100644
--- a/engines/wintermute/base/file/base_file_entry.h
+++ b/engines/wintermute/base/file/base_file_entry.h
@@ -40,14 +40,14 @@ class BaseFileEntry : public Common::ArchiveMember {
 public:
 	Common::SeekableReadStream *createReadStream() const override;
 	Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
-	Common::String getName() const override { return _filename; }
+	Common::String getName() const override { return _filename.baseName(); }
 	Common::Path getPathInArchive() const override { return _filename; }
-	Common::String getFileName() const override { return _filename; }
+	Common::String getFileName() const override { return _filename.baseName(); }
 	uint32 _timeDate2;
 	uint32 _timeDate1;
 	uint32 _flags;
 	uint32 _journalTime;
-	Common::String _filename;
+	Common::Path _filename;
 	uint32 _compressedLength;
 	uint32 _length;
 	uint32 _offset;
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index 42ca219293b..ee68b569138 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -574,7 +574,7 @@ bool BaseFontTT::initFont() {
 		return STATUS_FAILED;
 	}
 #ifdef USE_FREETYPE2
-	Common::String fallbackFilename;
+	const char *fallbackFilename;
 	// Handle Bold atleast for the fallback-case.
 	// TODO: Handle italic. (Needs a test-case)
 	if (_isBold) {
@@ -608,7 +608,7 @@ bool BaseFontTT::initFont() {
 	// Fallback3: Try to ask FontMan for the FreeSans.ttf ScummModern.zip uses:
 	if (!_font) {
 		// Really not desireable, as we will get a font with dpi-72 then
-		Common::String fontName = Common::String::format("%s-%s@%d", fallbackFilename.c_str(), "ASCII", _fontHeight);
+		Common::String fontName = Common::String::format("%s-%s@%d", fallbackFilename, "ASCII", _fontHeight);
 		warning("Looking for %s", fontName.c_str());
 		_font = FontMan.getFontByName(fontName);
 	}
diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp
index 08bf7df0291..7d1f745a72f 100644
--- a/engines/wintermute/debugger.cpp
+++ b/engines/wintermute/debugger.cpp
@@ -323,7 +323,7 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) {
 	}
 
 	Common::DumpFile *outFile = new Common::DumpFile();
-	outFile->open(outFileName);
+	outFile->open(Common::Path(outFileName, Common::Path::kNativeSeparator));
 
 	byte *data = new byte[inFile->size()];
 	inFile->read(data, inFile->size());
@@ -344,8 +344,8 @@ bool Console::Cmd_SourcePath(int argc, const char **argv) {
 		debugPrintf("Usage: %s <source path>\n", argv[0]);
 		return true;
 	} else {
-		if (CONTROLLER->setSourcePath(Common::String(argv[1])).getErrorCode() == OK) {
-			debugPrintf("Source path set to '%s'\n", CONTROLLER->getSourcePath().c_str());
+		if (CONTROLLER->setSourcePath(Common::Path(argv[1], Common::Path::kNativeSeparator)).getErrorCode() == OK) {
+			debugPrintf("Source path set to '%s'\n", CONTROLLER->getSourcePath().toString(Common::Path::kNativeSeparator).c_str());
 		} else {
 			debugPrintf("Error setting source path. Note that \"\" is illegal.");
 		}
diff --git a/engines/wintermute/debugger/debugger_controller.cpp b/engines/wintermute/debugger/debugger_controller.cpp
index d69469b6ce8..c24da14a14e 100644
--- a/engines/wintermute/debugger/debugger_controller.cpp
+++ b/engines/wintermute/debugger/debugger_controller.cpp
@@ -287,11 +287,11 @@ uint32 DebuggerController::getLastLine() const {
 	return _lastLine;
 }
 
-Common::String DebuggerController::getSourcePath() const {
+Common::Path DebuggerController::getSourcePath() const {
 	return _sourceListingProvider->getPath();
 }
 
-Error DebuggerController::setSourcePath(const Common::String &sourcePath) {
+Error DebuggerController::setSourcePath(const Common::Path &sourcePath) {
 	ErrorCode err = _sourceListingProvider->setPath(sourcePath);
 	return Error((err == OK ? SUCCESS : ERROR), err);
 }
diff --git a/engines/wintermute/debugger/debugger_controller.h b/engines/wintermute/debugger/debugger_controller.h
index 225cfd27aeb..9029100b5fc 100644
--- a/engines/wintermute/debugger/debugger_controller.h
+++ b/engines/wintermute/debugger/debugger_controller.h
@@ -101,8 +101,8 @@ public:
 	 * @brief set value for a variable accessible from within the current scope.
 	 */
 	Error setValue(const Common::String &name, const Common::String &value, ScValue*&var);
-	Error setSourcePath(const Common::String &sourcePath);
-	Common::String getSourcePath() const;
+	Error setSourcePath(const Common::Path &sourcePath);
+	Common::Path getSourcePath() const;
 	Listing *getListing(Error* &err);
 	void showFps(bool show);
 	/**
diff --git a/engines/wintermute/debugger/listing_provider.h b/engines/wintermute/debugger/listing_provider.h
index b8abb226928..bab72e5d8de 100644
--- a/engines/wintermute/debugger/listing_provider.h
+++ b/engines/wintermute/debugger/listing_provider.h
@@ -25,6 +25,8 @@
 #include "engines/wintermute/debugger/listing.h"
 #include "engines/wintermute/debugger/error.h"
 
+#include "common/path.h"
+
 namespace Wintermute {
 
 class ListingProvider {
@@ -33,7 +35,7 @@ public:
 	/**
 	* Get a listing. When implementing this, the result should be safe to delete for the caller.
 	*/
-	virtual Listing *getListing(const Common::String &filename, ErrorCode &error) = 0;
+	virtual Listing *getListing(const Common::Path &filename, ErrorCode &error) = 0;
 };
 
 } // End of namespace Wintermute
diff --git a/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp
index 741db3eca3b..161de697733 100644
--- a/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp
+++ b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.cpp
@@ -29,24 +29,14 @@ BasicSourceListingProvider::BasicSourceListingProvider() : _fsDirectory(nullptr)
 BasicSourceListingProvider::~BasicSourceListingProvider() {
 }
 
-SourceListing *BasicSourceListingProvider::getListing(const Common::String &filename, ErrorCode &_err) {
+SourceListing *BasicSourceListingProvider::getListing(const Common::Path &filename, ErrorCode &_err) {
 	_err = OK;
 	if (!_fsDirectory) {
 		_err = SOURCE_PATH_NOT_SET;
 		return nullptr;
 	};
 
-	Common::String unixFilename;
-
-	for (uint i = 0; i < filename.size(); i++) {
-		if (filename[i] == '\\') {
-			unixFilename.insertChar('/', unixFilename.size());
-		}  else {
-			unixFilename.insertChar(filename[i], unixFilename.size());
-		}
-	}
-
-	Common::SeekableReadStream *file = _fsDirectory->createReadStreamForMember(unixFilename);
+	Common::SeekableReadStream *file = _fsDirectory->createReadStreamForMember(filename);
 	Common::Array<Common::String> strings;
 
 	if (!file) {
@@ -70,8 +60,8 @@ SourceListing *BasicSourceListingProvider::getListing(const Common::String &file
 	}
 }
 
-ErrorCode BasicSourceListingProvider::setPath(const Common::String &path) {
-	if (path == "")
+ErrorCode BasicSourceListingProvider::setPath(const Common::Path &path) {
+	if (path.empty())
 		return ILLEGAL_PATH;
 	delete _fsDirectory;
 	Common::FSNode node(path);
@@ -83,8 +73,8 @@ ErrorCode BasicSourceListingProvider::setPath(const Common::String &path) {
 	}
 }
 
-Common::String BasicSourceListingProvider::getPath() const {
-	if (!_fsDirectory) return "";
+Common::Path BasicSourceListingProvider::getPath() const {
+	if (!_fsDirectory) return Common::Path();
 	return _fsDirectory->getFSNode().getPath();
 }
 
diff --git a/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h
index 558d6be2055..f63f3bb6de7 100644
--- a/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h
+++ b/engines/wintermute/debugger/listing_providers/basic_source_listing_provider.h
@@ -34,9 +34,9 @@ class BasicSourceListingProvider : public SourceListingProvider {
 public:
 	BasicSourceListingProvider();
 	~BasicSourceListingProvider() override;
-	SourceListing *getListing(const Common::String &filename, ErrorCode &err) override;
-	ErrorCode setPath(const Common::String &path) override;
-	Common::String getPath() const override;
+	SourceListing *getListing(const Common::Path &filename, ErrorCode &err) override;
+	ErrorCode setPath(const Common::Path &path) override;
+	Common::Path getPath() const override;
 };
 
 }
diff --git a/engines/wintermute/debugger/listing_providers/blank_listing.cpp b/engines/wintermute/debugger/listing_providers/blank_listing.cpp
index d83994ce173..099643d900a 100644
--- a/engines/wintermute/debugger/listing_providers/blank_listing.cpp
+++ b/engines/wintermute/debugger/listing_providers/blank_listing.cpp
@@ -24,7 +24,7 @@
 
 namespace Wintermute {
 
-BlankListing::BlankListing(const Common::String filename) : _filename(filename) {}
+BlankListing::BlankListing(const Common::Path filename) : _filename(filename.toString(Common::Path::kNativeSeparator)) {}
 
 uint BlankListing::getLength() const { return UINT_MAX_VALUE; }
 
diff --git a/engines/wintermute/debugger/listing_providers/blank_listing.h b/engines/wintermute/debugger/listing_providers/blank_listing.h
index ee892f0d970..62aacb8227f 100644
--- a/engines/wintermute/debugger/listing_providers/blank_listing.h
+++ b/engines/wintermute/debugger/listing_providers/blank_listing.h
@@ -23,11 +23,13 @@
 #define BLANK_LISTING_H_
 #include "engines/wintermute/debugger/listing.h"
 
+#include "common/path.h"
+
 namespace Wintermute {
 class BlankListing : public Listing {
 	const Common::String _filename;
 public:
-	BlankListing(const Common::String filename);
+	BlankListing(const Common::Path filename);
 	~BlankListing() override;
 	uint getLength() const override;
 	Common::String getLine(uint n) override;
diff --git a/engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp b/engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp
index fa883ea1045..e3ad975e62f 100644
--- a/engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp
+++ b/engines/wintermute/debugger/listing_providers/blank_listing_provider.cpp
@@ -26,7 +26,7 @@ BlankListingProvider::BlankListingProvider() {}
 
 BlankListingProvider::~BlankListingProvider() {}
 
-Listing *BlankListingProvider::getListing(const Common::String &filename, ErrorCode &error) {
+Listing *BlankListingProvider::getListing(const Common::Path &filename, ErrorCode &error) {
 	Listing *l = new BlankListing(filename);
 	error = OK;
 	return l; // Delete this sometime please.
diff --git a/engines/wintermute/debugger/listing_providers/blank_listing_provider.h b/engines/wintermute/debugger/listing_providers/blank_listing_provider.h
index b4f98b21c3b..9d637a9f915 100644
--- a/engines/wintermute/debugger/listing_providers/blank_listing_provider.h
+++ b/engines/wintermute/debugger/listing_providers/blank_listing_provider.h
@@ -31,7 +31,7 @@ class BlankListingProvider : public ListingProvider {
 public:
 	BlankListingProvider();
 	~BlankListingProvider() override;
-	Listing *getListing(const Common::String &filename, ErrorCode &error) override;
+	Listing *getListing(const Common::Path &filename, ErrorCode &error) override;
 };
 } // End of namespace Wintermute
 #endif
diff --git a/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp
index 12957495380..a2230254d80 100644
--- a/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp
+++ b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.cpp
@@ -34,13 +34,13 @@ CachedSourceListingProvider::CachedSourceListingProvider() {
 CachedSourceListingProvider::~CachedSourceListingProvider() {
 	delete _sourceListingProvider;
 	delete _fallbackListingProvider;
-	for (Common::HashMap<Common::String, SourceListing*>::iterator it = _cached.begin();
+	for (CacheMap::iterator it = _cached.begin();
 			it != _cached.end(); it++) {
 		delete (it->_value);
 	}
 }
 
-Listing *CachedSourceListingProvider::getListing(const Common::String &filename, Wintermute::ErrorCode &error) {
+Listing *CachedSourceListingProvider::getListing(const Common::Path &filename, Wintermute::ErrorCode &error) {
 	if (_cached.contains(filename)) {
 		error = OK;
 		SourceListing *copy = new SourceListing(*_cached.getVal(filename));
@@ -60,19 +60,19 @@ Listing *CachedSourceListingProvider::getListing(const Common::String &filename,
 }
 
 void CachedSourceListingProvider::invalidateCache() {
-	for (Common::HashMap<Common::String, SourceListing*>::iterator it = _cached.begin();
+	for (CacheMap::iterator it = _cached.begin();
 			it != _cached.end(); it++) {
 		delete (it->_value);
 	}
 	_cached.clear();
 }
 
-ErrorCode CachedSourceListingProvider::setPath(const Common::String &path) {
+ErrorCode CachedSourceListingProvider::setPath(const Common::Path &path) {
 	invalidateCache();
 	return _sourceListingProvider->setPath(path);
 }
 
-Common::String CachedSourceListingProvider::getPath() const {
+Common::Path CachedSourceListingProvider::getPath() const {
 	return _sourceListingProvider->getPath();
 }
 
diff --git a/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h
index a9300fadd5a..4b89e017ad5 100644
--- a/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h
+++ b/engines/wintermute/debugger/listing_providers/cached_source_listing_provider.h
@@ -36,14 +36,15 @@ class Listing;
 class CachedSourceListingProvider : public SourceListingProvider {
 	BasicSourceListingProvider *_sourceListingProvider;
 	BlankListingProvider *_fallbackListingProvider;
-	Common::HashMap<Common::String, SourceListing *> _cached;
+	typedef Common::HashMap<Common::Path, SourceListing *, Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualTo> CacheMap;
+	CacheMap _cached;
 	void invalidateCache();
 public:
 	CachedSourceListingProvider();
 	~CachedSourceListingProvider() override;
-	ErrorCode setPath(const Common::String &path) override;
-	Common::String getPath() const override;
-	Listing *getListing(const Common::String &filename, ErrorCode &err) override;
+	ErrorCode setPath(const Common::Path &path) override;
+	Common::Path getPath() const override;
+	Listing *getListing(const Common::Path &filename, ErrorCode &err) override;
 };
 
 } // End of namespace Wintermute
diff --git a/engines/wintermute/debugger/listing_providers/source_listing_provider.h b/engines/wintermute/debugger/listing_providers/source_listing_provider.h
index 0f77ef3aaa2..840a19ff454 100644
--- a/engines/wintermute/debugger/listing_providers/source_listing_provider.h
+++ b/engines/wintermute/debugger/listing_providers/source_listing_provider.h
@@ -24,6 +24,7 @@
 
 #include "engines/wintermute/debugger/error.h"
 #include "engines/wintermute/debugger/listing_provider.h"
+#include "common/path.h"
 #include "common/str.h"
 
 namespace Wintermute {
@@ -37,9 +38,9 @@ public:
 	/**
 	 * Get a listing. When implementing this, the result should be safe to delete for the caller.
 	 */
-	Listing *getListing(const Common::String &filename, ErrorCode &err) override = 0;
-	virtual ErrorCode setPath(const Common::String &path) = 0;
-	virtual Common::String getPath() const = 0;
+	Listing *getListing(const Common::Path &filename, ErrorCode &err) override = 0;
+	virtual ErrorCode setPath(const Common::Path &path) = 0;
+	virtual Common::Path getPath() const = 0;
 
 };
 
diff --git a/engines/wintermute/metaengine.cpp b/engines/wintermute/metaengine.cpp
index d821ca46be6..469e07c04cf 100644
--- a/engines/wintermute/metaengine.cpp
+++ b/engines/wintermute/metaengine.cpp
@@ -226,9 +226,9 @@ public:
 			if (!file->getName().hasSuffixIgnoreCase(".dcp")) continue;
 
 			FileProperties tmp;
-			if (AdvancedMetaEngine::getFilePropertiesExtern(md5Bytes, allFiles, kMD5Head, file->getName(), tmp)) {
+			if (AdvancedMetaEngine::getFilePropertiesExtern(md5Bytes, allFiles, kMD5Head, file->getPathInArchive(), tmp)) {
 				game.hasUnknownFiles = true;
-				game.matchedFiles[file->getName()] = tmp;
+				game.matchedFiles[file->getPathInArchive()] = tmp;
 			}
 		}
 
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index e430dfe8bec..7906e174998 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -66,7 +66,7 @@ WintermuteEngine::WintermuteEngine(OSystem *syst, const WMEGameDescription *desc
 	// Do not initialize graphics here
 
 	// However this is the place to specify all default directories
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 	//SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
 
 	_game = nullptr;


Commit: 043e5ad420b95fbdc54ba13d41853f2682244aca
    https://github.com/scummvm/scummvm/commit/043e5ad420b95fbdc54ba13d41853f2682244aca
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
ZVISION: Migrate engine to Path

Changed paths:
    engines/zvision/core/console.cpp
    engines/zvision/file/save_manager.cpp
    engines/zvision/file/search_manager.cpp
    engines/zvision/file/search_manager.h
    engines/zvision/file/zfs_archive.cpp
    engines/zvision/file/zfs_archive.h
    engines/zvision/graphics/cursors/cursor.cpp
    engines/zvision/graphics/cursors/cursor.h
    engines/zvision/graphics/cursors/cursor_manager.cpp
    engines/zvision/graphics/effects/fog.cpp
    engines/zvision/graphics/effects/fog.h
    engines/zvision/graphics/render_manager.cpp
    engines/zvision/graphics/render_manager.h
    engines/zvision/scripting/actions.cpp
    engines/zvision/scripting/actions.h
    engines/zvision/scripting/controls/fist_control.cpp
    engines/zvision/scripting/controls/fist_control.h
    engines/zvision/scripting/controls/hotmov_control.cpp
    engines/zvision/scripting/controls/hotmov_control.h
    engines/zvision/scripting/controls/lever_control.cpp
    engines/zvision/scripting/controls/lever_control.h
    engines/zvision/scripting/controls/paint_control.cpp
    engines/zvision/scripting/controls/safe_control.cpp
    engines/zvision/scripting/controls/titler_control.cpp
    engines/zvision/scripting/controls/titler_control.h
    engines/zvision/scripting/effects/animation_effect.cpp
    engines/zvision/scripting/effects/animation_effect.h
    engines/zvision/scripting/effects/music_effect.cpp
    engines/zvision/scripting/effects/music_effect.h
    engines/zvision/scripting/effects/syncsound_effect.cpp
    engines/zvision/scripting/effects/syncsound_effect.h
    engines/zvision/scripting/effects/ttytext_effect.cpp
    engines/zvision/scripting/effects/ttytext_effect.h
    engines/zvision/scripting/scr_file_handling.cpp
    engines/zvision/scripting/script_manager.cpp
    engines/zvision/scripting/script_manager.h
    engines/zvision/sound/zork_raw.cpp
    engines/zvision/sound/zork_raw.h
    engines/zvision/text/string_manager.cpp
    engines/zvision/text/string_manager.h
    engines/zvision/text/subtitles.cpp
    engines/zvision/text/subtitles.h
    engines/zvision/text/truetype_font.cpp
    engines/zvision/video/video.cpp
    engines/zvision/zvision.cpp
    engines/zvision/zvision.h


diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp
index c542ffa4fce..0d9b78cd226 100644
--- a/engines/zvision/core/console.cpp
+++ b/engines/zvision/core/console.cpp
@@ -216,7 +216,7 @@ bool Console::cmdLocation(int argc, const char **argv) {
 	return true;
 }
 
-void dumpFile(Common::SeekableReadStream *s, const char *outName) {
+void dumpFile(Common::SeekableReadStream *s, const Common::Path &outName) {
 	byte *buffer = new byte[s->size()];
 	s->read(buffer, s->size());
 
@@ -248,7 +248,7 @@ bool Console::cmdDumpFile(int argc, const char **argv) {
 }
 
 bool Console::cmdDumpFiles(int argc, const char **argv) {
-	Common::String fileName;
+	Common::Path fileName;
 	Common::SeekableReadStream *in;
 
 	if (argc != 2) {
@@ -261,11 +261,11 @@ bool Console::cmdDumpFiles(int argc, const char **argv) {
 
 	for (SearchManager::MatchList::iterator iter = fileList.begin(); iter != fileList.end(); ++iter) {
 		fileName = iter->_value.name;
-		debugPrintf("Dumping %s\n", fileName.c_str());
+		debugPrintf("Dumping %s\n", fileName.toString().c_str());
 
 		in = iter->_value.arch->createReadStreamForMember(iter->_value.name);
 		if (in)
-			dumpFile(in, fileName.c_str());
+			dumpFile(in, fileName);
 		delete in;
 	}
 
@@ -278,28 +278,29 @@ bool Console::cmdDumpImage(int argc, const char **argv) {
 		return true;
 	}
 
-	Common::String fileName = argv[1];
-	if (!fileName.hasSuffix(".tga")) {
+	Common::Path fileName = Common::Path(argv[1], Common::Path::kNativeSeparator);
+	Common::String baseName(fileName.baseName());
+	if (!baseName.hasSuffix(".tga")) {
 		debugPrintf("%s is not an image file", argv[1]);
 	}
 
 	Common::File f;
-	if (!_engine->getSearchManager()->openFile(f, argv[1])) {
+	if (!_engine->getSearchManager()->openFile(f, fileName)) {
 		warning("File not found: %s", argv[1]);
 		return true;
 	}
 
 	Graphics::Surface surface;
-	_engine->getRenderManager()->readImageToSurface(argv[1], surface, false);
+	_engine->getRenderManager()->readImageToSurface(fileName, surface, false);
 
 	// Open file
 	Common::DumpFile out;
 
-	fileName.setChar('b', fileName.size() - 3);
-	fileName.setChar('m', fileName.size() - 2);
-	fileName.setChar('p', fileName.size() - 1);
+	baseName.setChar('b', baseName.size() - 3);
+	baseName.setChar('m', baseName.size() - 2);
+	baseName.setChar('p', baseName.size() - 1);
 
-	out.open(fileName);
+	out.open(fileName.getParent().appendComponent(baseName));
 
 	// Write BMP header
 	out.writeByte('B');
diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp
index 452e6e5bced..311a482520d 100644
--- a/engines/zvision/file/save_manager.cpp
+++ b/engines/zvision/file/save_manager.cpp
@@ -254,11 +254,11 @@ Common::SeekableReadStream *SaveManager::getSlotFile(uint slot) {
 	Common::SeekableReadStream *saveFile = g_system->getSavefileManager()->openForLoading(_engine->getSaveStateName(slot));
 	if (saveFile == NULL) {
 		// Try to load standard save file
-		Common::String filename;
+		Common::Path filename;
 		if (_engine->getGameId() == GID_GRANDINQUISITOR)
-			filename = Common::String::format("inqsav%u.sav", slot);
+			filename = Common::Path(Common::String::format("inqsav%u.sav", slot));
 		else if (_engine->getGameId() == GID_NEMESIS)
-			filename = Common::String::format("nemsav%u.sav", slot);
+			filename = Common::Path(Common::String::format("nemsav%u.sav", slot));
 
 		saveFile = _engine->getSearchManager()->openFile(filename);
 		if (saveFile == NULL) {
diff --git a/engines/zvision/file/search_manager.cpp b/engines/zvision/file/search_manager.cpp
index 93e2e2eef40..915c1ca5695 100644
--- a/engines/zvision/file/search_manager.cpp
+++ b/engines/zvision/file/search_manager.cpp
@@ -28,7 +28,7 @@
 
 namespace ZVision {
 
-SearchManager::SearchManager(const Common::String &rootPath, int depth) {
+SearchManager::SearchManager(const Common::Path &rootPath, int depth) {
 	Common::FSNode fsNode(rootPath);
 
 	// Retrieve the root path from the FSNode, since it may not be the
@@ -36,22 +36,16 @@ SearchManager::SearchManager(const Common::String &rootPath, int depth) {
 	// the current directory.
 
 	_root = fsNode.getPath();
-	if (_root.hasSuffix("\\") || _root.hasSuffix("/"))
-		_root.deleteLastChar();
 
 	listDirRecursive(_dirList, fsNode, depth);
 
-	for (Common::List<Common::String>::iterator it = _dirList.begin(); it != _dirList.end();) {
-		if ((*it).hasSuffix("\\") || (*it).hasSuffix("/"))
-			(*it).deleteLastChar();
-
-		if (it->size() == _root.size())
+	for (Common::List<Common::Path>::iterator it = _dirList.begin(); it != _dirList.end();) {
+		*it = it->relativeTo(_root);
+		if (it->empty()) {
 			it = _dirList.erase(it);
-		else if (it->size() > _root.size()) {
-			*it = Common::String(it->c_str() + _root.size() + 1);
-			it++;
-		} else
+		} else {
 			it++;
+		}
 	}
 }
 
@@ -65,7 +59,7 @@ SearchManager::~SearchManager() {
 	_archList.clear();
 }
 
-void SearchManager::addFile(const Common::String &name, Common::Archive *arch) {
+void SearchManager::addFile(const Common::Path &name, Common::Archive *arch) {
 	bool addArch = true;
 	Common::List<Common::Archive *>::iterator it = _archList.begin();
 	while (it != _archList.end()) {
@@ -78,7 +72,7 @@ void SearchManager::addFile(const Common::String &name, Common::Archive *arch) {
 	if (addArch)
 		_archList.push_back(arch);
 
-	Common::String lowerCaseName = name;
+	Common::Path lowerCaseName = name;
 	lowerCaseName.toLowercase();
 
 	SearchManager::Node nod;
@@ -101,11 +95,8 @@ void SearchManager::addFile(const Common::String &name, Common::Archive *arch) {
 	}
 }
 
-Common::File *SearchManager::openFile(const Common::String &name) {
-	Common::String lowerCaseName = name;
-	lowerCaseName.toLowercase();
-
-	SearchManager::MatchList::iterator fit = _files.find(lowerCaseName);
+Common::File *SearchManager::openFile(const Common::Path &name) {
+	SearchManager::MatchList::iterator fit = _files.find(name);
 
 	if (fit != _files.end()) {
 		Common::File *tmp = new Common::File();
@@ -115,29 +106,23 @@ Common::File *SearchManager::openFile(const Common::String &name) {
 	return NULL;
 }
 
-bool SearchManager::openFile(Common::File &file, const Common::String &name) {
-	Common::String lowerCaseName = name;
-	lowerCaseName.toLowercase();
-
-	SearchManager::MatchList::iterator fit = _files.find(lowerCaseName);
+bool SearchManager::openFile(Common::File &file, const Common::Path &name) {
+	SearchManager::MatchList::iterator fit = _files.find(name);
 
 	if (fit != _files.end())
 		return file.open(fit->_value.name, *fit->_value.arch);
 	return false;
 }
 
-bool SearchManager::hasFile(const Common::String &name) {
-	Common::String lowerCaseName = name;
-	lowerCaseName.toLowercase();
-
-	SearchManager::MatchList::iterator fit = _files.find(lowerCaseName);
+bool SearchManager::hasFile(const Common::Path &name) {
+	SearchManager::MatchList::iterator fit = _files.find(name);
 
 	if (fit != _files.end())
 		return true;
 	return false;
 }
 
-bool SearchManager::loadZix(const Common::String &name) {
+bool SearchManager::loadZix(const Common::Path &name) {
 	Common::File file;
 	if (!file.open(name))
 		return false;
@@ -151,7 +136,7 @@ bool SearchManager::loadZix(const Common::String &name) {
 	}
 
 	if (file.eos())
-		error("Corrupt ZIX file: %s", name.c_str());
+		error("Corrupt ZIX file: %s", name.toString(Common::Path::kNativeSeparator).c_str());
 
 	Common::Array<Common::Archive *> archives;
 
@@ -188,27 +173,29 @@ bool SearchManager::loadZix(const Common::String &name) {
 				path.deleteLastChar();
 
 			// Handle paths in case-sensitive file systems (bug #6775)
-			if (path.size()) {
-				for (Common::List<Common::String>::iterator it = _dirList.begin(); it != _dirList.end(); ++it) {
-					if (path.equalsIgnoreCase(*it)) {
-						path = *it;
+			Common::Path path_(path);
+			if (!path_.empty()) {
+				for (Common::List<Common::Path>::iterator it = _dirList.begin(); it != _dirList.end(); ++it) {
+					// FIXME: ignoreCase
+					if (path_ == *it) {
+						path_ = *it;
 						break;
 					}
 				}
 			}
 
 			if (path.matchString("*.zfs", true)) {
-				arc = new ZfsArchive(path);
+				arc = new ZfsArchive(path_);
 			} else {
-				path = Common::String::format("%s/%s", _root.c_str(), path.c_str());
-				arc = new Common::FSDirectory(path);
+				path_ = _root.join(path_);
+				arc = new Common::FSDirectory(path_);
 			}
 			archives.push_back(arc);
 		}
 	}
 
 	if (file.eos())
-		error("Corrupt ZIX file: %s", name.c_str());
+		error("Corrupt ZIX file: %s", name.toString(Common::Path::kNativeSeparator).c_str());
 
 	while (!file.eos()) {
 		line = file.readLine();
@@ -217,7 +204,7 @@ bool SearchManager::loadZix(const Common::String &name) {
 		char buf[32];
 		if (sscanf(line.c_str(), "%u %s", &dr, buf) == 2) {
 			if (dr <= archives.size() && dr > 0) {
-				addFile(Common::String(buf), archives[dr - 1]);
+				addFile(buf, archives[dr - 1]);
 			}
 		}
 	}
@@ -225,19 +212,20 @@ bool SearchManager::loadZix(const Common::String &name) {
 	return true;
 }
 
-void SearchManager::addDir(const Common::String &name) {
-	Common::String path;
-	for (Common::List<Common::String>::iterator it = _dirList.begin(); it != _dirList.end(); ++it)
-		if (name.equalsIgnoreCase(*it)) {
+void SearchManager::addDir(const Common::Path &name) {
+	Common::Path path;
+	for (Common::List<Common::Path>::iterator it = _dirList.begin(); it != _dirList.end(); ++it)
+		// FIXME: ignore case
+		if (name == *it) {
 			path = *it;
 			break;
 		}
 
-	if (path.size() == 0)
+	if (path.empty())
 		return;
 
-	path = Common::String::format("%s/%s", _root.c_str(), path.c_str());
 
+	path = _root.join(path);
 	Common::FSDirectory *dir = new Common::FSDirectory(path);
 
 	Common::ArchiveMemberList list;
@@ -246,13 +234,13 @@ void SearchManager::addDir(const Common::String &name) {
 	for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
 		Common::String flname = (*iter)->getName();
 
-		ZfsArchive *zfs = new ZfsArchive(Common::String::format("%s/%s", name.c_str(), flname.c_str()));
+		ZfsArchive *zfs = new ZfsArchive(name.join(flname));
 
 		Common::ArchiveMemberList zfslist;
 		zfs->listMembers(zfslist);
 
 		for (Common::ArchiveMemberList::iterator ziter = zfslist.begin(); ziter != zfslist.end(); ++ziter) {
-			Common::String zfsFileName = (*ziter)->getName();
+			Common::Path zfsFileName = (*ziter)->getPathInArchive();
 			addFile(zfsFileName, zfs);
 		}
 	}
@@ -261,12 +249,12 @@ void SearchManager::addDir(const Common::String &name) {
 	dir->listMembers(list);
 
 	for (Common::ArchiveMemberList::iterator iter = list.begin(); iter != list.end(); ++iter) {
-		Common::String flname = (*iter)->getName();
+		Common::Path flname = (*iter)->getPathInArchive();
 		addFile(flname, dir);
 	}
 }
 
-void SearchManager::listDirRecursive(Common::List<Common::String> &_list, const Common::FSNode &fsNode, int depth) {
+void SearchManager::listDirRecursive(Common::List<Common::Path> &_list, const Common::FSNode &fsNode, int depth) {
 	Common::FSList fsList;
 	if (fsNode.getChildren(fsList)) {
 
@@ -280,7 +268,7 @@ void SearchManager::listDirRecursive(Common::List<Common::String> &_list, const
 
 void SearchManager::listMembersWithExtension(MatchList &fileList, Common::String extension) {
 	for (SearchManager::MatchList::iterator it = _files.begin(); it != _files.end(); ++it) {
-		if (it->_key.hasSuffix(extension))
+		if (it->_key.baseName().hasSuffix(extension))
 			fileList[it->_key] = it->_value;
 	}
 }
diff --git a/engines/zvision/file/search_manager.h b/engines/zvision/file/search_manager.h
index 12f4704c93b..928ad8eff38 100644
--- a/engines/zvision/file/search_manager.h
+++ b/engines/zvision/file/search_manager.h
@@ -33,34 +33,34 @@ namespace ZVision {
 
 class SearchManager {
 public:
-	SearchManager(const Common::String &rootPath, int depth);
+	SearchManager(const Common::Path &rootPath, int depth);
 	~SearchManager();
 
-	void addFile(const Common::String &name, Common::Archive *arch);
-	void addDir(const Common::String &name);
+	void addFile(const Common::Path &name, Common::Archive *arch);
+	void addDir(const Common::Path &name);
 
-	Common::File *openFile(const Common::String &name);
-	bool openFile(Common::File &file, const Common::String &name);
-	bool hasFile(const Common::String &name);
+	Common::File *openFile(const Common::Path &name);
+	bool openFile(Common::File &file, const Common::Path &name);
+	bool hasFile(const Common::Path &name);
 
-	bool loadZix(const Common::String &name);
+	bool loadZix(const Common::Path &name);
 
 	struct Node {
-		Common::String name;
+		Common::Path name;
 		Common::Archive *arch;
 	};
 
-	typedef Common::HashMap<Common::String, Node, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> MatchList;
+	typedef Common::HashMap<Common::Path, Node, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> MatchList;
 
 	void listMembersWithExtension(MatchList &fileList, Common::String extension);
 
 private:
 
-	void listDirRecursive(Common::List<Common::String> &dirList, const Common::FSNode &fsNode, int depth);
+	void listDirRecursive(Common::List<Common::Path> &dirList, const Common::FSNode &fsNode, int depth);
 
-	Common::List<Common::String> _dirList;
+	Common::List<Common::Path> _dirList;
 	Common::List<Common::Archive *> _archList;
-	Common::String _root;
+	Common::Path _root;
 	MatchList _files;
 };
 
diff --git a/engines/zvision/file/zfs_archive.cpp b/engines/zvision/file/zfs_archive.cpp
index 7754f4e86c8..1803fb59cd7 100644
--- a/engines/zvision/file/zfs_archive.cpp
+++ b/engines/zvision/file/zfs_archive.cpp
@@ -28,7 +28,7 @@
 
 namespace ZVision {
 
-ZfsArchive::ZfsArchive(const Common::String &fileName) : _fileName(fileName) {
+ZfsArchive::ZfsArchive(const Common::Path &fileName) : _fileName(fileName) {
 	Common::File zfsFile;
 	memset(&_header, 0, sizeof(_header));
 
@@ -39,13 +39,13 @@ ZfsArchive::ZfsArchive(const Common::String &fileName) : _fileName(fileName) {
 
 	readHeaders(&zfsFile);
 
-	debug(1, "ZfsArchive::ZfsArchive(%s): Located %d files", _fileName.c_str(), _entryHeaders.size());
+	debug(1, "ZfsArchive::ZfsArchive(%s): Located %d files", _fileName.toString(Common::Path::kNativeSeparator).c_str(), _entryHeaders.size());
 }
 
-ZfsArchive::ZfsArchive(const Common::String &fileName, Common::SeekableReadStream *stream) : _fileName(fileName) {
+ZfsArchive::ZfsArchive(const Common::Path &fileName, Common::SeekableReadStream *stream) : _fileName(fileName) {
 	readHeaders(stream);
 
-	debug(1, "ZfsArchive::ZfsArchive(%s): Located %d files", _fileName.c_str(), _entryHeaders.size());
+	debug(1, "ZfsArchive::ZfsArchive(%s): Located %d files", _fileName.toString(Common::Path::kNativeSeparator).c_str(), _entryHeaders.size());
 }
 
 ZfsArchive::~ZfsArchive() {
@@ -120,11 +120,10 @@ int ZfsArchive::listMembers(Common::ArchiveMemberList &list) const {
 }
 
 const Common::ArchiveMemberPtr ZfsArchive::getMember(const Common::Path &path) const {
-	Common::String name = path.toString();
-	if (!_entryHeaders.contains(name))
+	if (!hasFile(path))
 		return Common::ArchiveMemberPtr();
 
-	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, *this));
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
 }
 
 Common::SeekableReadStream *ZfsArchive::createReadStreamForMember(const Common::Path &path) const {
diff --git a/engines/zvision/file/zfs_archive.h b/engines/zvision/file/zfs_archive.h
index d395aa5005f..4875cc52ff9 100644
--- a/engines/zvision/file/zfs_archive.h
+++ b/engines/zvision/file/zfs_archive.h
@@ -55,8 +55,8 @@ typedef Common::HashMap<Common::String, ZfsEntryHeader *, Common::IgnoreCase_Has
 
 class ZfsArchive : public Common::Archive {
 public:
-	ZfsArchive(const Common::String &fileName);
-	ZfsArchive(const Common::String &fileName, Common::SeekableReadStream *stream);
+	ZfsArchive(const Common::Path &fileName);
+	ZfsArchive(const Common::Path &fileName, Common::SeekableReadStream *stream);
 	~ZfsArchive() override;
 
 	/**
@@ -88,7 +88,7 @@ public:
 	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
 
 private:
-	const Common::String _fileName;
+	const Common::Path _fileName;
 	ZfsHeader _header;
 	ZfsEntryHeaderMap _entryHeaders;
 
diff --git a/engines/zvision/graphics/cursors/cursor.cpp b/engines/zvision/graphics/cursors/cursor.cpp
index 9081713ee54..49f83ae2700 100644
--- a/engines/zvision/graphics/cursors/cursor.cpp
+++ b/engines/zvision/graphics/cursors/cursor.cpp
@@ -35,18 +35,18 @@ ZorkCursor::ZorkCursor()
 	  _hotspotY(0) {
 }
 
-ZorkCursor::ZorkCursor(ZVision *engine, const Common::String &fileName)
+ZorkCursor::ZorkCursor(ZVision *engine, const Common::Path &fileName)
 	: _width(0),
 	  _height(0),
 	  _hotspotX(0),
 	  _hotspotY(0) {
 	Common::File file;
 	if (!engine->getSearchManager()->openFile(file, fileName))
-		error("Cursor file %s does not exist", fileName.c_str());
+		error("Cursor file %s does not exist", fileName.toString().c_str());
 
 	uint32 magic = file.readUint32BE();
 	if (magic != MKTAG('Z', 'C', 'R', '1')) {
-		warning("%s is not a Zork Cursor file", fileName.c_str());
+		warning("%s is not a Zork Cursor file", fileName.toString().c_str());
 		return;
 	}
 
diff --git a/engines/zvision/graphics/cursors/cursor.h b/engines/zvision/graphics/cursors/cursor.h
index cd4d0f32675..8288567caaa 100644
--- a/engines/zvision/graphics/cursors/cursor.h
+++ b/engines/zvision/graphics/cursors/cursor.h
@@ -38,7 +38,7 @@ namespace ZVision {
 class ZorkCursor {
 public:
 	ZorkCursor();
-	ZorkCursor(ZVision *engine, const Common::String &fileName);
+	ZorkCursor(ZVision *engine, const Common::Path &fileName);
 	ZorkCursor(const ZorkCursor &other);
 	~ZorkCursor();
 
diff --git a/engines/zvision/graphics/cursors/cursor_manager.cpp b/engines/zvision/graphics/cursors/cursor_manager.cpp
index 2c662721674..73064d242f9 100644
--- a/engines/zvision/graphics/cursors/cursor_manager.cpp
+++ b/engines/zvision/graphics/cursors/cursor_manager.cpp
@@ -53,15 +53,15 @@ CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat pixelF
 	  _currentCursor(CursorIndex_Idle) {
 	for (int i = 0; i < NUM_CURSORS; i++) {
 		if (_engine->getGameId() == GID_NEMESIS) {
-			Common::String name;
+			Common::Path name;
 			if (i == 1) {
 				// Cursors "arrowa.zcr" and "arrowb.zcr" are missing
 				_cursors[i][0] = _cursors[i][1] = ZorkCursor();
 				continue;
 			}
-			name = Common::String::format("%sa.zcr", _zNemCursorFileNames[i]);
+			name = Common::Path(Common::String::format("%sa.zcr", _zNemCursorFileNames[i]));
 			_cursors[i][0] = ZorkCursor(_engine, name); // Up cursor
-			name = Common::String::format("%sb.zcr", _zNemCursorFileNames[i]);
+			name = Common::Path(Common::String::format("%sb.zcr", _zNemCursorFileNames[i]));
 			_cursors[i][1] = ZorkCursor(_engine, name); // Down cursor
 		} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
 			_cursors[i][0] = ZorkCursor(_engine, _zgiCursorFileNames[i]); // Up cursor
@@ -77,24 +77,24 @@ CursorManager::CursorManager(ZVision *engine, const Graphics::PixelFormat pixelF
 void CursorManager::setItemID(int id) {
 	if (id != _item) {
 		if (id) {
-			Common::String file;
+			Common::Path file;
 			if (_engine->getGameId() == GID_NEMESIS) {
-				file = Common::String::format("%2.2d%s%c.zcr", id, "idle", 'a');
+				file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "idle", 'a'));
 				_cursors[NUM_CURSORS][0] = ZorkCursor(_engine, file);
-				file = Common::String::format("%2.2d%s%c.zcr", id, "idle", 'b');
+				file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "idle", 'b'));
 				_cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
-				file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'a');
+				file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "act", 'a'));
 				_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
-				file = Common::String::format("%2.2d%s%c.zcr", id, "act", 'b');
+				file = Common::Path(Common::String::format("%2.2d%s%c.zcr", id, "act", 'b'));
 				_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
 			} else if (_engine->getGameId() == GID_GRANDINQUISITOR) {
-				file = Common::String::format("g0b%cc%2.2x1.zcr", 'a' , id);
+				file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'a' , id));
 				_cursors[NUM_CURSORS][0] = ZorkCursor(_engine, file);
-				file = Common::String::format("g0b%cc%2.2x1.zcr", 'c' , id);
+				file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'c' , id));
 				_cursors[NUM_CURSORS][1] = ZorkCursor(_engine, file);
-				file = Common::String::format("g0b%cc%2.2x1.zcr", 'b' , id);
+				file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'b' , id));
 				_cursors[NUM_CURSORS + 1][0] = ZorkCursor(_engine, file);
-				file = Common::String::format("g0b%cc%2.2x1.zcr", 'd' , id);
+				file = Common::Path(Common::String::format("g0b%cc%2.2x1.zcr", 'd' , id));
 				_cursors[NUM_CURSORS + 1][1] = ZorkCursor(_engine, file);
 			} else
 				return;
diff --git a/engines/zvision/graphics/effects/fog.cpp b/engines/zvision/graphics/effects/fog.cpp
index 69aadfc828c..2669eb99827 100644
--- a/engines/zvision/graphics/effects/fog.cpp
+++ b/engines/zvision/graphics/effects/fog.cpp
@@ -29,7 +29,7 @@
 
 namespace ZVision {
 
-FogFx::FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds):
+FogFx::FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::Path &clouds):
 	GraphicsEffect(engine, key, region, ported) {
 
 	_map = Map;
diff --git a/engines/zvision/graphics/effects/fog.h b/engines/zvision/graphics/effects/fog.h
index 0a4189f675b..dd34689bca6 100644
--- a/engines/zvision/graphics/effects/fog.h
+++ b/engines/zvision/graphics/effects/fog.h
@@ -32,7 +32,7 @@ class ZVision;
 class FogFx : public GraphicsEffect {
 public:
 
-	FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::String &clouds);
+	FogFx(ZVision *engine, uint32 key, Common::Rect region, bool ported, EffectMap *Map, const Common::Path &clouds);
 	~FogFx() override;
 
 	const Graphics::Surface *draw(const Graphics::Surface &srcSubRect) override;
diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp
index b652db743da..139284ac0c4 100644
--- a/engines/zvision/graphics/render_manager.cpp
+++ b/engines/zvision/graphics/render_manager.cpp
@@ -148,7 +148,7 @@ void RenderManager::copyToScreen(const Graphics::Surface &surface, Common::Rect
 	delete outSurface;
 }
 
-void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY) {
+void RenderManager::renderImageToBackground(const Common::Path &fileName, int16 destX, int16 destY) {
 	Graphics::Surface surface;
 	readImageToSurface(fileName, surface);
 
@@ -156,7 +156,7 @@ void RenderManager::renderImageToBackground(const Common::String &fileName, int1
 	surface.free();
 }
 
-void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 keycolor) {
+void RenderManager::renderImageToBackground(const Common::Path &fileName, int16 destX, int16 destY, uint32 keycolor) {
 	Graphics::Surface surface;
 	readImageToSurface(fileName, surface);
 
@@ -164,7 +164,7 @@ void RenderManager::renderImageToBackground(const Common::String &fileName, int1
 	surface.free();
 }
 
-void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, int16  keyX, int16 keyY) {
+void RenderManager::renderImageToBackground(const Common::Path &fileName, int16 destX, int16 destY, int16  keyX, int16 keyY) {
 	Graphics::Surface surface;
 	readImageToSurface(fileName, surface);
 
@@ -174,16 +174,16 @@ void RenderManager::renderImageToBackground(const Common::String &fileName, int1
 	surface.free();
 }
 
-void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) {
+void RenderManager::readImageToSurface(const Common::Path &fileName, Graphics::Surface &destination) {
 	bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA;
 	readImageToSurface(fileName, destination, isTransposed);
 }
 
-void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed) {
+void RenderManager::readImageToSurface(const Common::Path &fileName, Graphics::Surface &destination, bool transposed) {
 	Common::File file;
 
 	if (!_engine->getSearchManager()->openFile(file, fileName)) {
-		warning("Could not open file %s", fileName.c_str());
+		warning("Could not open file %s", fileName.toString().c_str());
 		return;
 	}
 
@@ -306,7 +306,7 @@ RenderTable *RenderManager::getRenderTable() {
 	return &_renderTable;
 }
 
-void RenderManager::setBackgroundImage(const Common::String &fileName) {
+void RenderManager::setBackgroundImage(const Common::Path &fileName) {
 	readImageToSurface(fileName, _currentBackgroundImage);
 	_backgroundWidth = _currentBackgroundImage.w;
 	_backgroundHeight = _currentBackgroundImage.h;
@@ -566,13 +566,13 @@ Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) {
 	return srf;
 }
 
-Graphics::Surface *RenderManager::loadImage(Common::String file) {
+Graphics::Surface *RenderManager::loadImage(const Common::Path &file) {
 	Graphics::Surface *tmp = new Graphics::Surface;
 	readImageToSurface(file, *tmp);
 	return tmp;
 }
 
-Graphics::Surface *RenderManager::loadImage(Common::String file, bool transposed) {
+Graphics::Surface *RenderManager::loadImage(const Common::Path &file, bool transposed) {
 	Graphics::Surface *tmp = new Graphics::Surface;
 	readImageToSurface(file, *tmp, transposed);
 	return tmp;
diff --git a/engines/zvision/graphics/render_manager.h b/engines/zvision/graphics/render_manager.h
index 6965a06f60d..1336d85a3e4 100644
--- a/engines/zvision/graphics/render_manager.h
+++ b/engines/zvision/graphics/render_manager.h
@@ -150,7 +150,7 @@ public:
 	 * @param destinationX    X position where the image should be put. Coords are in working window space, not screen space!
 	 * @param destinationY    Y position where the image should be put. Coords are in working window space, not screen space!
 	 */
-	void renderImageToBackground(const Common::String &fileName, int16 destinationX, int16 destinationY);
+	void renderImageToBackground(const Common::Path &fileName, int16 destinationX, int16 destinationY);
 
 	/**
 	 * Blits the image or a portion of the image to the background.
@@ -160,7 +160,7 @@ public:
 	 * @param destY      Y position where the image should be put. Coords are in working window space, not screen space!
 	 * @param colorkey   Transparent color
 	 */
-	void renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 colorkey);
+	void renderImageToBackground(const Common::Path &fileName, int16 destX, int16 destY, uint32 colorkey);
 
 	/**
 	 * Blits the image or a portion of the image to the background.
@@ -171,7 +171,7 @@ public:
 	 * @param keyX       X position of transparent color
 	 * @param keyY       Y position of transparent color
 	 */
-	void renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, int16 keyX, int16 keyY);
+	void renderImageToBackground(const Common::Path &fileName, int16 destX, int16 destY, int16 keyX, int16 keyY);
 
 	/**
 	 * Sets the current background image to be used by the RenderManager and immediately
@@ -179,7 +179,7 @@ public:
 	 *
 	 * @param fileName    The name of the image file
 	 */
-	void setBackgroundImage(const Common::String &fileName);
+	void setBackgroundImage(const Common::Path &fileName);
 
 	/**
 	 * Set the background position (_backgroundOffset). If the current RenderState is PANORAMA, the offset
@@ -259,8 +259,8 @@ public:
 	Graphics::Surface *getBkgRect(Common::Rect &rect);
 
 	// Load image into new surface
-	Graphics::Surface *loadImage(Common::String file);
-	Graphics::Surface *loadImage(Common::String file, bool transposed);
+	Graphics::Surface *loadImage(const Common::Path &file);
+	Graphics::Surface *loadImage(const Common::Path &file, bool transposed);
 
 	// Clear whole/area of menu surface
 	void clearMenuSurface();
@@ -281,7 +281,7 @@ public:
 	 * @param fileName       The name of a .tga file
 	 * @param destination    A reference to the Surface to store the pixel data in
 	 */
-	void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination);
+	void readImageToSurface(const Common::Path &fileName, Graphics::Surface &destination);
 
 	/**
 	 * Reads an image file pixel data into a Surface buffer. Also, if the image
@@ -293,7 +293,7 @@ public:
 	 * @param destination    A reference to the Surface to store the pixel data in
 	 * @param transposed     Transpose flag
 	 */
-	void readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed);
+	void readImageToSurface(const Common::Path &fileName, Graphics::Surface &destination, bool transposed);
 
 	// Add visual effect to effects list
 	void addEffect(GraphicsEffect *_effect);
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index ead33a0f37f..6032a497509 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -484,7 +484,7 @@ ActionMusic::ActionMusic(ZVision *engine, int32 slotKey, const Common::String &l
 		if (volumeBuffer[0] != '[' && atoi(volumeBuffer) > 100) {
 			// I thought I saw a case like this in Zork Nemesis, so
 			// let's guard against it.
-			warning("ActionMusic: Adjusting volume for %s from %s to 100", _fileName.c_str(), volumeBuffer);
+			warning("ActionMusic: Adjusting volume for %s from %s to 100", _fileName.toString().c_str(), volumeBuffer);
 			Common::strcpy_s(volumeBuffer, "100");
 		}
 		_volume = new ValueSlot(_scriptManager, volumeBuffer);
@@ -785,14 +785,14 @@ bool ActionRegion::execute() {
 		char buf[64];
 		sscanf(_custom.c_str(), "%hd,%d,%s", &dum1, &dum2, buf);
 		Graphics::Surface tempMask;
-		_engine->getRenderManager()->readImageToSurface(_art, tempMask);
+		_engine->getRenderManager()->readImageToSurface(Common::Path(_art), tempMask);
 		if (_rect.width() != tempMask.w)
 			_rect.setWidth(tempMask.w);
 		if (_rect.height() != tempMask.h)
 			_rect.setHeight(tempMask.h);
 
 		EffectMap *_map = _engine->getRenderManager()->makeEffectMap(tempMask, 0);
-		effect = new FogFx(_engine, _slotKey, _rect, _unk1, _map, Common::String(buf));
+		effect = new FogFx(_engine, _slotKey, _rect, _unk1, _map, buf);
 	}
 	break;
 	default:
@@ -960,24 +960,27 @@ ActionStreamVideo::ActionStreamVideo(ZVision *engine, int32 slotKey, const Commo
 bool ActionStreamVideo::execute() {
 	Video::VideoDecoder *decoder;
 	Common::Rect destRect = Common::Rect(_x1, _y1, _x2 + 1, _y2 + 1);
-	Common::String subname = _fileName;
+	Common::String subname = _fileName.baseName();
 	subname.setChar('s', subname.size() - 3);
 	subname.setChar('u', subname.size() - 2);
 	subname.setChar('b', subname.size() - 1);
-	bool subtitleExists = _engine->getSearchManager()->hasFile(subname);
+	Common::Path subpath(_fileName.getParent().appendComponent(subname));
+	bool subtitleExists = _engine->getSearchManager()->hasFile(subpath);
 	bool switchToHires = false;
 
 // NOTE: We only show the hires MPEG2 videos when libmpeg2 and liba52 are compiled in,
 // otherwise we fall back to the lowres ones
 #if defined(USE_MPEG2) && defined(USE_A52)
-	Common::String hiresFileName = _fileName;
+	Common::String hiresFileName = _fileName.baseName();
 	hiresFileName.setChar('d', hiresFileName.size() - 8);
 	hiresFileName.setChar('v', hiresFileName.size() - 3);
 	hiresFileName.setChar('o', hiresFileName.size() - 2);
 	hiresFileName.setChar('b', hiresFileName.size() - 1);
 
-	if (_scriptManager->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresFileName)) {
-		_fileName = hiresFileName;
+	Common::Path hiresPath(_fileName.getParent().appendComponent(hiresFileName));
+
+	if (_scriptManager->getStateValue(StateKey_MPEGMovies) == 1 &&_engine->getSearchManager()->hasFile(hiresPath)) {
+		_fileName = hiresPath;
 		switchToHires = true;
 	} else if (!_engine->getSearchManager()->hasFile(_fileName))
 		return true;
@@ -987,7 +990,7 @@ bool ActionStreamVideo::execute() {
 #endif
 
 	decoder = _engine->loadAnimation(_fileName);
-	Subtitle *sub = (subtitleExists) ? new Subtitle(_engine, subname, switchToHires) : NULL;
+	Subtitle *sub = (subtitleExists) ? new Subtitle(_engine, subpath, switchToHires) : NULL;
 
 	_engine->getCursorManager()->showMouse(false);
 
diff --git a/engines/zvision/scripting/actions.h b/engines/zvision/scripting/actions.h
index b99b0bd8d57..deeba06ac5c 100644
--- a/engines/zvision/scripting/actions.h
+++ b/engines/zvision/scripting/actions.h
@@ -221,7 +221,7 @@ public:
 	bool execute() override;
 
 private:
-	Common::String _fileName;
+	Common::Path _fileName;
 	bool _loop;
 	ValueSlot *_volume;
 	bool _universe;
@@ -248,7 +248,7 @@ public:
 	bool execute() override;
 
 private:
-	Common::String _fileName;
+	Common::Path _fileName;
 	uint32 _x;
 	uint32 _y;
 	uint32 _x2;
@@ -283,7 +283,7 @@ public:
 	bool execute() override;
 
 private:
-	Common::String _fileName;
+	Common::Path _fileName;
 	int32 _mask;
 	int32 _framerate;
 };
@@ -344,7 +344,7 @@ public:
 	bool execute() override;
 
 private:
-	Common::String _fileName;
+	Common::Path _fileName;
 };
 
 class ActionRotateTo : public ResultAction {
@@ -365,7 +365,7 @@ public:
 private:
 	uint _x;
 	uint _y;
-	Common::String _fileName;
+	Common::Path _fileName;
 	int32 _backgroundColor;
 };
 
@@ -375,7 +375,7 @@ public:
 	bool execute() override;
 
 private:
-	Common::String _fileName;
+	Common::Path _fileName;
 };
 
 class ActionStop : public ResultAction {
@@ -397,7 +397,7 @@ private:
 		DIFFERENT_DIMENSIONS = 0x1 // 0x1 flags that the destRect dimensions are different from the original video dimensions
 	};
 
-	Common::String _fileName;
+	Common::Path _fileName;
 	uint _x1;
 	uint _y1;
 	uint _x2;
@@ -413,7 +413,7 @@ public:
 
 private:
 	int _syncto;
-	Common::String _fileName;
+	Common::Path _fileName;
 };
 
 class ActionTimer : public ResultAction {
@@ -432,7 +432,7 @@ public:
 	bool execute() override;
 
 private:
-	Common::String _filename;
+	Common::Path _filename;
 	uint32 _delay;
 	Common::Rect _r;
 };
diff --git a/engines/zvision/scripting/controls/fist_control.cpp b/engines/zvision/scripting/controls/fist_control.cpp
index f6bb72f7740..bfbd3263bd6 100644
--- a/engines/zvision/scripting/controls/fist_control.cpp
+++ b/engines/zvision/scripting/controls/fist_control.cpp
@@ -68,7 +68,7 @@ FistControl::FistControl(ZVision *engine, uint32 key, Common::SeekableReadStream
 		} else if (param.matchString("cursor", true)) {
 			_cursor = _engine->getCursorManager()->getCursorId(values);
 		} else if (param.matchString("descfile", true)) {
-			readDescFile(values);
+			readDescFile(Common::Path(values));
 		} else if (param.matchString("animation_id", true)) {
 			_animationId = atoi(values.c_str());
 		} else if (param.matchString("venus_id", true)) {
@@ -160,10 +160,10 @@ bool FistControl::onMouseUp(const Common::Point &screenSpacePos, const Common::P
 	return false;
 }
 
-void FistControl::readDescFile(const Common::String &fileName) {
+void FistControl::readDescFile(const Common::Path &fileName) {
 	Common::File file;
 	if (!_engine->getSearchManager()->openFile(file, fileName)) {
-		warning("Desc file %s could could be opened", fileName.c_str());
+		warning("Desc file %s could could be opened", fileName.toString().c_str());
 		return;
 	}
 
@@ -178,7 +178,7 @@ void FistControl::readDescFile(const Common::String &fileName) {
 		if (param.matchString("animation_id", true)) {
 			// Not used
 		} else if (param.matchString("animation", true)) {
-			_animation = _engine->loadAnimation(values);
+			_animation = _engine->loadAnimation(Common::Path(values));
 		} else if (param.matchString("anim_rect", true)) {
 			int left, top, right, bottom;
 			sscanf(values.c_str(), "%d %d %d %d", &left, &top, &right, &bottom);
diff --git a/engines/zvision/scripting/controls/fist_control.h b/engines/zvision/scripting/controls/fist_control.h
index 7f3caa88429..7b7ab780f70 100644
--- a/engines/zvision/scripting/controls/fist_control.h
+++ b/engines/zvision/scripting/controls/fist_control.h
@@ -71,7 +71,7 @@ public:
 	bool process(uint32 deltaTimeInMillis) override;
 
 private:
-	void readDescFile(const Common::String &fileName);
+	void readDescFile(const Common::Path &fileName);
 	void clearFistArray(Common::Array< Common::Array<Common::Rect> > &arr);
 	uint32 readBits(const char *str);
 	int mouseIn(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
diff --git a/engines/zvision/scripting/controls/hotmov_control.cpp b/engines/zvision/scripting/controls/hotmov_control.cpp
index 92fcdc7cd5d..4b81c89b981 100644
--- a/engines/zvision/scripting/controls/hotmov_control.cpp
+++ b/engines/zvision/scripting/controls/hotmov_control.cpp
@@ -55,7 +55,7 @@ HotMovControl::HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadSt
 
 	while (!stream.eos() && !line.contains('}')) {
 		if (param.matchString("hs_frame_list", true)) {
-			readHsFile(values);
+			readHsFile(Common::Path(values));
 		} else if (param.matchString("rectangle", true)) {
 			int x;
 			int y;
@@ -73,7 +73,7 @@ HotMovControl::HotMovControl(ZVision *engine, uint32 key, Common::SeekableReadSt
 			char filename[64];
 			sscanf(values.c_str(), "%s", filename);
 			values = Common::String(filename);
-			_animation = _engine->loadAnimation(values);
+			_animation = _engine->loadAnimation(Common::Path(values));
 			_animation->start();
 		} else if (param.matchString("venus_id", true)) {
 			_venusId = atoi(values.c_str());
@@ -153,13 +153,13 @@ bool HotMovControl::onMouseUp(const Common::Point &screenSpacePos, const Common:
 	return false;
 }
 
-void HotMovControl::readHsFile(const Common::String &fileName) {
+void HotMovControl::readHsFile(const Common::Path &fileName) {
 	if (_framesCount == 0)
 		return;
 
 	Common::File file;
 	if (!_engine->getSearchManager()->openFile(file, fileName)) {
-		warning("HS file %s could could be opened", fileName.c_str());
+		warning("HS file %s could could be opened", fileName.toString().c_str());
 		return;
 	}
 
diff --git a/engines/zvision/scripting/controls/hotmov_control.h b/engines/zvision/scripting/controls/hotmov_control.h
index fe8cdcbc1f7..06ad28d9ba6 100644
--- a/engines/zvision/scripting/controls/hotmov_control.h
+++ b/engines/zvision/scripting/controls/hotmov_control.h
@@ -52,7 +52,7 @@ public:
 	bool process(uint32 deltaTimeInMillis) override;
 
 private:
-	void readHsFile(const Common::String &fileName);
+	void readHsFile(const Common::Path &fileName);
 };
 
 } // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
index 46efe2b65bd..802112ddb79 100644
--- a/engines/zvision/scripting/controls/lever_control.cpp
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -88,10 +88,10 @@ LeverControl::~LeverControl() {
 	delete[] _frameInfo;
 }
 
-void LeverControl::parseLevFile(const Common::String &fileName) {
+void LeverControl::parseLevFile(const Common::Path &fileName) {
 	Common::File file;
 	if (!_engine->getSearchManager()->openFile(file, fileName)) {
-		warning("LEV file %s could could be opened", fileName.c_str());
+		warning("LEV file %s could could be opened", fileName.toString().c_str());
 		return;
 	}
 
@@ -106,7 +106,7 @@ void LeverControl::parseLevFile(const Common::String &fileName) {
 		if (param.matchString("animation_id", true)) {
 			// Not used
 		} else if (param.matchString("filename", true)) {
-			_animation = _engine->loadAnimation(values);
+			_animation = _engine->loadAnimation(Common::Path(values));
 		} else if (param.matchString("skipcolor", true)) {
 			// Not used
 		} else if (param.matchString("anim_coords", true)) {
diff --git a/engines/zvision/scripting/controls/lever_control.h b/engines/zvision/scripting/controls/lever_control.h
index 37565165dbd..9e19fd066b5 100644
--- a/engines/zvision/scripting/controls/lever_control.h
+++ b/engines/zvision/scripting/controls/lever_control.h
@@ -86,7 +86,7 @@ public:
 	bool process(uint32 deltaTimeInMillis) override;
 
 private:
-	void parseLevFile(const Common::String &fileName);
+	void parseLevFile(const Common::Path &fileName);
 	/**
 	 * Calculates the angle a vector makes with the negative y-axis
 	 *
diff --git a/engines/zvision/scripting/controls/paint_control.cpp b/engines/zvision/scripting/controls/paint_control.cpp
index 9c6bf2b5326..2c197704710 100644
--- a/engines/zvision/scripting/controls/paint_control.cpp
+++ b/engines/zvision/scripting/controls/paint_control.cpp
@@ -60,11 +60,11 @@ PaintControl::PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStre
 		} else if (param.matchString("cursor", true)) {
 			_cursor = _engine->getCursorManager()->getCursorId(values);
 		} else if (param.matchString("brush_file", true)) {
-			_brush = _engine->getRenderManager()->loadImage(values, false);
+			_brush = _engine->getRenderManager()->loadImage(Common::Path(values), false);
 		} else if (param.matchString("venus_id", true)) {
 			_venusId = atoi(values.c_str());
 		} else if (param.matchString("paint_file", true)) {
-			_paint = _engine->getRenderManager()->loadImage(values, false);
+			_paint = _engine->getRenderManager()->loadImage(Common::Path(values), false);
 		} else if (param.matchString("eligible_objects", true)) {
 			char buf[256];
 			memset(buf, 0, 256);
diff --git a/engines/zvision/scripting/controls/safe_control.cpp b/engines/zvision/scripting/controls/safe_control.cpp
index 09308fbd9ee..cb2585144dc 100644
--- a/engines/zvision/scripting/controls/safe_control.cpp
+++ b/engines/zvision/scripting/controls/safe_control.cpp
@@ -59,7 +59,7 @@ SafeControl::SafeControl(ZVision *engine, uint32 key, Common::SeekableReadStream
 
 	while (!stream.eos() && !line.contains('}')) {
 		if (param.matchString("animation", true)) {
-			_animation = _engine->loadAnimation(values);
+			_animation = _engine->loadAnimation(Common::Path(values));
 			_animation->start();
 		} else if (param.matchString("rectangle", true)) {
 			int x;
diff --git a/engines/zvision/scripting/controls/titler_control.cpp b/engines/zvision/scripting/controls/titler_control.cpp
index b8cd46e867e..92c506986a5 100644
--- a/engines/zvision/scripting/controls/titler_control.cpp
+++ b/engines/zvision/scripting/controls/titler_control.cpp
@@ -47,7 +47,7 @@ TitlerControl::TitlerControl(ZVision *engine, uint32 key, Common::SeekableReadSt
 
 	while (!stream.eos() && !line.contains('}')) {
 		if (param.matchString("string_resource_file", true)) {
-			readStringsFile(values);
+			readStringsFile(Common::Path(values));
 		} else if (param.matchString("rectangle", true)) {
 			int x;
 			int y;
@@ -87,10 +87,10 @@ void TitlerControl::setString(int strLine) {
 	}
 }
 
-void TitlerControl::readStringsFile(const Common::String &fileName) {
+void TitlerControl::readStringsFile(const Common::Path &fileName) {
 	Common::File file;
 	if (!_engine->getSearchManager()->openFile(file, fileName)) {
-		warning("String_resource_file %s could could be opened", fileName.c_str());
+		warning("String_resource_file %s could could be opened", fileName.toString().c_str());
 		return;
 	}
 
diff --git a/engines/zvision/scripting/controls/titler_control.h b/engines/zvision/scripting/controls/titler_control.h
index 35c5cdc53d8..bc47819b1f1 100644
--- a/engines/zvision/scripting/controls/titler_control.h
+++ b/engines/zvision/scripting/controls/titler_control.h
@@ -46,7 +46,7 @@ private:
 	int16 _curString;
 	Graphics::Surface *_surface;
 
-	void readStringsFile(const Common::String &fileName);
+	void readStringsFile(const Common::Path &fileName);
 };
 
 } // End of namespace ZVision
diff --git a/engines/zvision/scripting/effects/animation_effect.cpp b/engines/zvision/scripting/effects/animation_effect.cpp
index 6b8d8164821..928cd4eba72 100644
--- a/engines/zvision/scripting/effects/animation_effect.cpp
+++ b/engines/zvision/scripting/effects/animation_effect.cpp
@@ -32,7 +32,7 @@
 
 namespace ZVision {
 
-AnimationEffect::AnimationEffect(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse)
+AnimationEffect::AnimationEffect(ZVision *engine, uint32 controlKey, const Common::Path &fileName, int32 mask, int32 frate, bool disposeAfterUse)
 	: ScriptingEffect(engine, controlKey, SCRIPTING_EFFECT_ANIM),
 	  _disposeAfterUse(disposeAfterUse),
 	  _mask(mask),
diff --git a/engines/zvision/scripting/effects/animation_effect.h b/engines/zvision/scripting/effects/animation_effect.h
index d3b866ba11e..47bd3ed5076 100644
--- a/engines/zvision/scripting/effects/animation_effect.h
+++ b/engines/zvision/scripting/effects/animation_effect.h
@@ -40,7 +40,7 @@ class ZVision;
 
 class AnimationEffect : public ScriptingEffect {
 public:
-	AnimationEffect(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool disposeAfterUse = true);
+	AnimationEffect(ZVision *engine, uint32 controlKey, const Common::Path &fileName, int32 mask, int32 frate, bool disposeAfterUse = true);
 	~AnimationEffect() override;
 
 	struct playnode {
diff --git a/engines/zvision/scripting/effects/music_effect.cpp b/engines/zvision/scripting/effects/music_effect.cpp
index f2bfef69d3c..1aa3aa28157 100644
--- a/engines/zvision/scripting/effects/music_effect.cpp
+++ b/engines/zvision/scripting/effects/music_effect.cpp
@@ -55,7 +55,7 @@ namespace ZVision {
 83, 86, 89, 92, 96, 99, 103, 107, 111, 115, 119, 123, 128, 133, 137, 143,
 148, 153, 159, 165, 171, 177, 184, 191, 198, 205, 212, 220, 228, 237, 245, 255};*/
 
-MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, uint8 volume)
+MusicNode::MusicNode(ZVision *engine, uint32 key, Common::Path &filename, bool loop, uint8 volume)
 	: MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) {
 	_loop = loop;
 	_volume = volume;
@@ -70,7 +70,7 @@ MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool
 
 	Audio::RewindableAudioStream *audioStream = NULL;
 
-	if (filename.contains(".wav")) {
+	if (filename.baseName().contains(".wav")) {
 		Common::File *file = new Common::File();
 		if (_engine->getSearchManager()->openFile(*file, filename)) {
 			audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
@@ -93,13 +93,14 @@ MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool
 			_engine->getScriptManager()->setStateValue(_key, 1);
 
 		// Change filename.raw into filename.sub
-		Common::String subname = filename;
+		Common::String subname = filename.baseName();
 		subname.setChar('s', subname.size() - 3);
 		subname.setChar('u', subname.size() - 2);
 		subname.setChar('b', subname.size() - 1);
 
-		if (_engine->getSearchManager()->hasFile(subname))
-			_sub = new Subtitle(_engine, subname);
+		Common::Path subpath(filename.getParent().appendComponent(subname));
+		if (_engine->getSearchManager()->hasFile(subpath))
+			_sub = new Subtitle(_engine, subpath);
 
 		_loaded = true;
 	}
diff --git a/engines/zvision/scripting/effects/music_effect.h b/engines/zvision/scripting/effects/music_effect.h
index 063ca373318..e39aa3f20c8 100644
--- a/engines/zvision/scripting/effects/music_effect.h
+++ b/engines/zvision/scripting/effects/music_effect.h
@@ -56,7 +56,7 @@ public:
 
 class MusicNode : public MusicNodeBASE {
 public:
-	MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, uint8 volume);
+	MusicNode(ZVision *engine, uint32 key, Common::Path &file, bool loop, uint8 volume);
 	~MusicNode() override;
 
 	/**
diff --git a/engines/zvision/scripting/effects/syncsound_effect.cpp b/engines/zvision/scripting/effects/syncsound_effect.cpp
index 70f65787974..9a3b9087df3 100644
--- a/engines/zvision/scripting/effects/syncsound_effect.cpp
+++ b/engines/zvision/scripting/effects/syncsound_effect.cpp
@@ -34,14 +34,14 @@
 
 namespace ZVision {
 
-SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto)
+SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::Path &filename, int32 syncto)
 	: ScriptingEffect(engine, key, SCRIPTING_EFFECT_AUDIO) {
 	_syncto = syncto;
 	_sub = NULL;
 
 	Audio::RewindableAudioStream *audioStream = NULL;
 
-	if (filename.contains(".wav")) {
+	if (filename.baseName().contains(".wav")) {
 		Common::File *file = new Common::File();
 		if (_engine->getSearchManager()->openFile(*file, filename)) {
 			audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
@@ -52,13 +52,14 @@ SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filena
 
 	_engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream);
 
-	Common::String subname = filename;
+	Common::String subname = filename.baseName();
 	subname.setChar('s', subname.size() - 3);
 	subname.setChar('u', subname.size() - 2);
 	subname.setChar('b', subname.size() - 1);
 
-	if (_engine->getSearchManager()->hasFile(subname))
-		_sub = new Subtitle(_engine, subname);
+	Common::Path subpath(filename.getParent().appendComponent(subname));
+	if (_engine->getSearchManager()->hasFile(subpath))
+		_sub = new Subtitle(_engine, subpath);
 }
 
 SyncSoundNode::~SyncSoundNode() {
diff --git a/engines/zvision/scripting/effects/syncsound_effect.h b/engines/zvision/scripting/effects/syncsound_effect.h
index d778574c64d..7fd0d4bef26 100644
--- a/engines/zvision/scripting/effects/syncsound_effect.h
+++ b/engines/zvision/scripting/effects/syncsound_effect.h
@@ -33,7 +33,7 @@ class String;
 namespace ZVision {
 class SyncSoundNode : public ScriptingEffect {
 public:
-	SyncSoundNode(ZVision *engine, uint32 key, Common::String &file, int32 syncto);
+	SyncSoundNode(ZVision *engine, uint32 key, Common::Path &file, int32 syncto);
 	~SyncSoundNode() override;
 
 	/**
diff --git a/engines/zvision/scripting/effects/ttytext_effect.cpp b/engines/zvision/scripting/effects/ttytext_effect.cpp
index 576c556344d..1e991483231 100644
--- a/engines/zvision/scripting/effects/ttytext_effect.cpp
+++ b/engines/zvision/scripting/effects/ttytext_effect.cpp
@@ -33,7 +33,7 @@
 
 namespace ZVision {
 
-ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay) :
+ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::Path &file, const Common::Rect &r, int32 delay) :
 	ScriptingEffect(engine, key, SCRIPTING_EFFECT_TTYTXT),
 	_fnt(engine) {
 	_delay = delay;
diff --git a/engines/zvision/scripting/effects/ttytext_effect.h b/engines/zvision/scripting/effects/ttytext_effect.h
index 46093870fde..90c7dbed7f8 100644
--- a/engines/zvision/scripting/effects/ttytext_effect.h
+++ b/engines/zvision/scripting/effects/ttytext_effect.h
@@ -36,7 +36,7 @@ class String;
 namespace ZVision {
 class ttyTextNode : public ScriptingEffect {
 public:
-	ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay);
+	ttyTextNode(ZVision *engine, uint32 key, const Common::Path &file, const Common::Rect &r, int32 delay);
 	~ttyTextNode() override;
 
 	/**
diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp
index 729a2613b45..5721b9a0657 100644
--- a/engines/zvision/scripting/scr_file_handling.cpp
+++ b/engines/zvision/scripting/scr_file_handling.cpp
@@ -43,16 +43,16 @@
 
 namespace ZVision {
 
-void ScriptManager::parseScrFile(const Common::String &fileName, ScriptScope &scope) {
+void ScriptManager::parseScrFile(const Common::Path &fileName, ScriptScope &scope) {
 	Common::File file;
 	if (!_engine->getSearchManager()->openFile(file, fileName)) {
-		error("Script file not found: %s", fileName.c_str());
+		error("Script file not found: %s", fileName.toString().c_str());
 	}
 
 	while (!file.eos()) {
 		Common::String line = file.readLine();
 		if (file.err()) {
-			error("Error parsing scr file: %s", fileName.c_str());
+			error("Error parsing scr file: %s", fileName.toString().c_str());
 		}
 
 		trimCommentsAndWhiteSpace(&line);
diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp
index 2a297a5fb10..a87f5af9142 100644
--- a/engines/zvision/scripting/script_manager.cpp
+++ b/engines/zvision/scripting/script_manager.cpp
@@ -650,15 +650,15 @@ void ScriptManager::ChangeLocationReal(bool isLoading) {
 		cleanScriptScope(room);
 		cleanScriptScope(world);
 
-		Common::String fileName = Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view);
+		Common::Path fileName(Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view));
 		parseScrFile(fileName, nodeview);
 		addPuzzlesToReferenceTable(nodeview);
 
-		fileName = Common::String::format("%c%c.scr", _nextLocation.world, _nextLocation.room);
+		fileName = Common::Path(Common::String::format("%c%c.scr", _nextLocation.world, _nextLocation.room));
 		parseScrFile(fileName, room);
 		addPuzzlesToReferenceTable(room);
 
-		fileName = Common::String::format("%c.scr", _nextLocation.world);
+		fileName = Common::Path(Common::String::format("%c.scr", _nextLocation.world));
 		parseScrFile(fileName, world);
 		addPuzzlesToReferenceTable(world);
 	} else if (_nextLocation.room != _currentLocation.room) {
@@ -667,11 +667,11 @@ void ScriptManager::ChangeLocationReal(bool isLoading) {
 
 		addPuzzlesToReferenceTable(world);
 
-		Common::String fileName = Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view);
+		Common::Path fileName(Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view));
 		parseScrFile(fileName, nodeview);
 		addPuzzlesToReferenceTable(nodeview);
 
-		fileName = Common::String::format("%c%c.scr", _nextLocation.world, _nextLocation.room);
+		fileName = Common::Path(Common::String::format("%c%c.scr", _nextLocation.world, _nextLocation.room));
 		parseScrFile(fileName, room);
 		addPuzzlesToReferenceTable(room);
 
@@ -681,7 +681,7 @@ void ScriptManager::ChangeLocationReal(bool isLoading) {
 		addPuzzlesToReferenceTable(room);
 		addPuzzlesToReferenceTable(world);
 
-		Common::String fileName = Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view);
+		Common::Path fileName(Common::String::format("%c%c%c%c.scr", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view));
 		parseScrFile(fileName, nodeview);
 		addPuzzlesToReferenceTable(nodeview);
 	}
diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h
index 5d534f5d68b..04ed99ca8f3 100644
--- a/engines/zvision/scripting/script_manager.h
+++ b/engines/zvision/scripting/script_manager.h
@@ -317,7 +317,7 @@ private:
 	 * @param fileName    Name of the .scr file
 	 * @param isGlobal    Are the puzzles included in the file global (true). AKA, the won't be purged during location changes
 	 */
-	void parseScrFile(const Common::String &fileName, ScriptScope &scope);
+	void parseScrFile(const Common::Path &fileName, ScriptScope &scope);
 
 	/**
 	 * Parses the stream into a Puzzle object
diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp
index 437a3e16a1c..ba33d9898f5 100644
--- a/engines/zvision/sound/zork_raw.cpp
+++ b/engines/zvision/sound/zork_raw.cpp
@@ -240,46 +240,37 @@ Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stre
 	return new RawZorkStream(rate, stereo, disposeAfterUse, stream);
 }
 
-Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) {
+Audio::RewindableAudioStream *makeRawZorkStream(const Common::Path &filePath, ZVision *engine) {
 	Common::File *file = new Common::File();
-	Common::String actualName = filePath;
-	bool found = engine->getSearchManager()->openFile(*file, actualName);
-	bool isRaw = actualName.hasSuffix(".raw");
+	bool found = engine->getSearchManager()->openFile(*file, filePath);
+	Common::String baseName = filePath.baseName();
+	bool isRaw = baseName.hasSuffix(".raw");
 
 	if ((!found && isRaw) || (found && isRaw && file->size() < 10)) {
 		if (found)
 			file->close();
 
 		// Check for an audio patch (.src)
-		actualName.setChar('s', actualName.size() - 3);
-		actualName.setChar('r', actualName.size() - 2);
-		actualName.setChar('c', actualName.size() - 1);
+		baseName.setChar('s', baseName.size() - 3);
+		baseName.setChar('r', baseName.size() - 2);
+		baseName.setChar('c', baseName.size() - 1);
 
-		if (!engine->getSearchManager()->openFile(*file, actualName))
+		if (!engine->getSearchManager()->openFile(*file, filePath.getParent().appendComponent(baseName)))
 			return NULL;
 	} else if (!found && !isRaw) {
 		return NULL;
 	}
 
-	// Get the file name
-	Common::StringTokenizer tokenizer(actualName, "/\\");
-	Common::String fileName;
-	while (!tokenizer.empty()) {
-		fileName = tokenizer.nextToken();
-	}
-
-	fileName.toLowercase();
-
 	const SoundParams *soundParams = NULL;
 
 	if (engine->getGameId() == GID_NEMESIS) {
 		for (int i = 0; i < 32; ++i) {
-			if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == (fileName[6]))
+			if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == (baseName[6]))
 				soundParams = &RawZorkStream::_zNemSoundParamLookupTable[i];
 		}
 	} else if (engine->getGameId() == GID_GRANDINQUISITOR) {
 		for (int i = 0; i < 24; ++i) {
-			if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == (fileName[7]))
+			if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == (baseName[7]))
 				soundParams = &RawZorkStream::_zgiSoundParamLookupTable[i];
 		}
 	}
diff --git a/engines/zvision/sound/zork_raw.h b/engines/zvision/sound/zork_raw.h
index 14266fa19a6..257896a542f 100644
--- a/engines/zvision/sound/zork_raw.h
+++ b/engines/zvision/sound/zork_raw.h
@@ -134,7 +134,7 @@ Audio::RewindableAudioStream *makeRawZorkStream(Common::SeekableReadStream *stre
 		bool stereo,
 		DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
 
-Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine);
+Audio::RewindableAudioStream *makeRawZorkStream(const Common::Path &filePath, ZVision *engine);
 
 } // End of namespace ZVision
 
diff --git a/engines/zvision/text/string_manager.cpp b/engines/zvision/text/string_manager.cpp
index 827e91a0fb8..b3994cc4c48 100644
--- a/engines/zvision/text/string_manager.cpp
+++ b/engines/zvision/text/string_manager.cpp
@@ -47,10 +47,10 @@ void StringManager::initialize(ZVisionGameId gameId) {
 		loadStrFile("inquis.str");
 }
 
-void StringManager::loadStrFile(const Common::String &fileName) {
+void StringManager::loadStrFile(const Common::Path &fileName) {
 	Common::File file;
 	if (!_engine->getSearchManager()->openFile(file, fileName))
-		error("%s does not exist. String parsing failed", fileName.c_str());
+		error("%s does not exist. String parsing failed", fileName.toString().c_str());
 
 	uint lineNumber = 0;
 	while (!file.eos()) {
diff --git a/engines/zvision/text/string_manager.h b/engines/zvision/text/string_manager.h
index 40c177ae11f..286adf62e8d 100644
--- a/engines/zvision/text/string_manager.h
+++ b/engines/zvision/text/string_manager.h
@@ -59,7 +59,7 @@ public:
 	const Common::String getTextLine(uint stringNumber);
 
 private:
-	void loadStrFile(const Common::String &fileName);
+	void loadStrFile(const Common::Path &fileName);
 };
 
 } // End of namespace ZVision
diff --git a/engines/zvision/text/subtitles.cpp b/engines/zvision/text/subtitles.cpp
index fe6ca90134f..fb1edec1751 100644
--- a/engines/zvision/text/subtitles.cpp
+++ b/engines/zvision/text/subtitles.cpp
@@ -26,7 +26,7 @@
 
 namespace ZVision {
 
-Subtitle::Subtitle(ZVision *engine, const Common::String &subname, bool upscaleToHires) :
+Subtitle::Subtitle(ZVision *engine, const Common::Path &subname, bool upscaleToHires) :
 	_engine(engine),
 	_areaId(-1),
 	_subId(-1) {
@@ -50,7 +50,7 @@ Subtitle::Subtitle(ZVision *engine, const Common::String &subname, bool upscaleT
 				char filename[64];
 				sscanf(str.c_str(), "%*[^:]:%s", filename);
 				Common::File txt;
-				if (_engine->getSearchManager()->openFile(txt, filename)) {
+				if (_engine->getSearchManager()->openFile(txt, Common::Path(filename))) {
 					while (!txt.eos()) {
 						Common::String txtline = readWideLine(txt);
 						sub curSubtitle;
diff --git a/engines/zvision/text/subtitles.h b/engines/zvision/text/subtitles.h
index cf7f64ff7fa..4d2a1751a02 100644
--- a/engines/zvision/text/subtitles.h
+++ b/engines/zvision/text/subtitles.h
@@ -30,7 +30,7 @@ class ZVision;
 
 class Subtitle {
 public:
-	Subtitle(ZVision *engine, const Common::String &subname, bool upscaleToHires = false);
+	Subtitle(ZVision *engine, const Common::Path &subname, bool upscaleToHires = false);
 	~Subtitle();
 
 	void process(int32 time);
diff --git a/engines/zvision/text/truetype_font.cpp b/engines/zvision/text/truetype_font.cpp
index 107a24927e8..2801654fe09 100644
--- a/engines/zvision/text/truetype_font.cpp
+++ b/engines/zvision/text/truetype_font.cpp
@@ -118,9 +118,9 @@ bool StyledTTFont::loadFont(const Common::String &fontName, int32 point, uint st
 
 	Common::File file;
 	Graphics::Font *newFont;
-	if (!file.open(newFontName) && !_engine->getSearchManager()->openFile(file, newFontName) &&
-		!file.open(liberationFontName) && !_engine->getSearchManager()->openFile(file, liberationFontName) &&
-		!file.open(freeFontName) && !_engine->getSearchManager()->openFile(file, freeFontName)) {
+	if (!file.open(Common::Path(newFontName)) && !_engine->getSearchManager()->openFile(file, Common::Path(newFontName)) &&
+		!file.open(Common::Path(liberationFontName)) && !_engine->getSearchManager()->openFile(file, Common::Path(liberationFontName)) &&
+		!file.open(Common::Path(freeFontName)) && !_engine->getSearchManager()->openFile(file, Common::Path(freeFontName))) {
 		newFont = Graphics::loadTTFFontFromArchive(liberationFontName, point, Graphics::kTTFSizeModeCell, 0, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal));
 	} else {
 		newFont = Graphics::loadTTFFont(file, point, Graphics::kTTFSizeModeCell, 0, (sharp ? Graphics::kTTFRenderModeMonochrome : Graphics::kTTFRenderModeNormal));
diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp
index da8ebfd6eb3..4faa9929d93 100644
--- a/engines/zvision/video/video.cpp
+++ b/engines/zvision/video/video.cpp
@@ -40,8 +40,8 @@
 
 namespace ZVision {
 
-Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) {
-	Common::String tmpFileName = fileName;
+Video::VideoDecoder *ZVision::loadAnimation(const Common::Path &fileName) {
+	Common::String tmpFileName = fileName.baseName();
 	tmpFileName.toLowercase();
 	Video::VideoDecoder *animation = NULL;
 
@@ -56,15 +56,15 @@ Video::VideoDecoder *ZVision::loadAnimation(const Common::String &fileName) {
 	}
 #endif
 	else
-		error("Unknown suffix for animation %s", fileName.c_str());
+		error("Unknown suffix for animation %s", fileName.toString().c_str());
 
-	Common::File *_file = getSearchManager()->openFile(tmpFileName);
+	Common::File *_file = getSearchManager()->openFile(fileName);
 	if (!_file)
-		error("Error opening %s", tmpFileName.c_str());
+		error("Error opening %s", fileName.toString().c_str());
 
 	bool loaded = animation->loadStream(_file);
 	if (!loaded)
-		error("Error loading animation %s", tmpFileName.c_str());
+		error("Error loading animation %s", fileName.toString().c_str());
 
 	return animation;
 }
diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp
index 216dda43d38..863872d1dab 100644
--- a/engines/zvision/zvision.cpp
+++ b/engines/zvision/zvision.cpp
@@ -175,9 +175,9 @@ void ZVision::saveSettings() {
 }
 
 void ZVision::initialize() {
-	const Common::FSNode gameDataDir(ConfMan.get("path"));
+	const Common::FSNode gameDataDir(ConfMan.getPath("path"));
 
-	_searchManager = new SearchManager(ConfMan.get("path"), 6);
+	_searchManager = new SearchManager(ConfMan.getPath("path"), 6);
 
 	_searchManager->addDir("FONTS");
 	_searchManager->addDir("addon");
@@ -291,9 +291,9 @@ Common::Error ZVision::run() {
 			liberationFontName += liberationFontSuffixes[j];
 			liberationFontName += ".ttf";
 
-			if (!Common::File::exists(fontName) && !_searchManager->hasFile(fontName) &&
-				!Common::File::exists(liberationFontName) && !_searchManager->hasFile(liberationFontName) &&
-				!Common::File::exists(freeFontName) && !_searchManager->hasFile(freeFontName) &&
+			if (!Common::File::exists(Common::Path(fontName)) && !_searchManager->hasFile(Common::Path(fontName)) &&
+				!Common::File::exists(Common::Path(liberationFontName)) && !_searchManager->hasFile(Common::Path(liberationFontName)) &&
+				!Common::File::exists(Common::Path(freeFontName)) && !_searchManager->hasFile(Common::Path(freeFontName)) &&
 				!Common::File::exists("fonts.dat") && !_searchManager->hasFile("fonts.dat")) {
 				foundAllFonts = false;
 				break;
diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h
index 5a5081f36ab..23ab1ace099 100644
--- a/engines/zvision/zvision.h
+++ b/engines/zvision/zvision.h
@@ -236,7 +236,7 @@ public:
 	 * @param skippable       If true, the video can be skipped at any time using [Spacebar]
 	 */
 	void playVideo(Video::VideoDecoder &videoDecoder, const Common::Rect &destRect = Common::Rect(0, 0, 0, 0), bool skippable = true, Subtitle *sub = NULL);
-	Video::VideoDecoder *loadAnimation(const Common::String &fileName);
+	Video::VideoDecoder *loadAnimation(const Common::Path &fileName);
 
 	void setRenderDelay(uint);
 	bool canRender();


Commit: ed9ded9e839df379ba3980ee1baad2453f84541b
    https://github.com/scummvm/scummvm/commit/ed9ded9e839df379ba3980ee1baad2453f84541b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
GUI: Migrate GUI to Path class

Changed paths:
    backends/platform/dc/dcmain.cpp
    base/commandLine.cpp
    base/plugins.cpp
    common/zip-set.cpp
    gui/ThemeEngine.cpp
    gui/ThemeEngine.h
    gui/browser.cpp
    gui/debugger.cpp
    gui/dump-all-dialogs.cpp
    gui/editgamedialog.cpp
    gui/editgamedialog.h
    gui/launcher.cpp
    gui/massadd.cpp
    gui/massadd.h
    gui/options.cpp
    gui/options.h
    gui/predictivedialog.cpp
    gui/shaderbrowser-dialog.cpp
    gui/shaderbrowser-dialog.h
    gui/widgets/grid.cpp
    gui/widgets/richtext.h


diff --git a/backends/platform/dc/dcmain.cpp b/backends/platform/dc/dcmain.cpp
index f40aca0efed..d9b926b712e 100644
--- a/backends/platform/dc/dcmain.cpp
+++ b/backends/platform/dc/dcmain.cpp
@@ -298,7 +298,7 @@ int DCLauncherDialog::runModal()
   ConfMan.set("gameid", gameId, gameId);
 
   if (dir != NULL)
-	ConfMan.set("path", dir, gameId);
+	ConfMan.setPath("path", dir, gameId);
 
   // Set the game language.
   if (language != Common::UNK_LANG)
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 765a90da5d5..fa663ed2e6c 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -298,7 +298,7 @@ void registerDefaults() {
 	ConfMan.registerDefault("stretch_mode", "default");
 	ConfMan.registerDefault("scaler", "default");
 	ConfMan.registerDefault("scale_factor", -1);
-	ConfMan.registerDefault("shader", "default");
+	ConfMan.registerDefault("shader", Common::Path("default", Common::Path::kNoSeparator));
 	ConfMan.registerDefault("show_fps", false);
 	ConfMan.registerDefault("dirtyrects", true);
 	ConfMan.registerDefault("vsync", true);
@@ -333,7 +333,7 @@ void registerDefaults() {
 #endif
 
 	// Game specific
-	ConfMan.registerDefault("path", "");
+	ConfMan.registerDefault("path", Common::Path());
 	ConfMan.registerDefault("platform", Common::kPlatformDOS);
 	ConfMan.registerDefault("language", "en");
 	ConfMan.registerDefault("subtitles", false);
@@ -2127,7 +2127,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		if (!ConfMan.hasKey(key)) { \
 			Common::FSNode node(path); \
 			if (node.exists() && node.isDirectory() && node.isReadable()) \
-				ConfMan.set(key, path, Common::ConfigManager::kSessionDomain); \
+				ConfMan.setPath(key, path, Common::ConfigManager::kSessionDomain); \
 		}
 
 	ADD_DEFAULT_PATH("themepath", "gui/themes/")
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 5b7a438fde4..075dcefb1b6 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -751,14 +751,15 @@ const PluginList &EngineManager::getPlugins(const PluginType fetchPluginType) co
 	return PluginManager::instance().getPlugins(fetchPluginType);
 }
 
-namespace {
-
-void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) {
+static void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) {
 	if (!value.empty())
 		ConfMan.set(key, value, domain);
 }
 
-} // End of anonymous namespace
+static void addPathToConf(const Common::String &key, const Common::Path &value, const Common::String &domain) {
+	if (!value.empty())
+		ConfMan.setPath(key, value, domain);
+}
 
 Common::String EngineManager::generateUniqueDomain(const Common::String gameId) {
 	Common::String domainName(gameId);
@@ -787,7 +788,7 @@ Common::String EngineManager::createTargetForGame(const DetectedGame &game) {
 	addStringToConf("description", game.description, domain);
 	addStringToConf("language", Common::getLanguageCode(game.language), domain);
 	addStringToConf("platform", Common::getPlatformCode(game.platform), domain);
-	addStringToConf("path", game.path.toString(Common::Path::kNativeSeparator), domain);
+	addPathToConf("path", game.path, domain);
 	addStringToConf("extra", game.extra, domain);
 	addStringToConf("guioptions", game.getGUIOptions(), domain);
 
diff --git a/common/zip-set.cpp b/common/zip-set.cpp
index 3cf1d2e811e..34ff1d5c28b 100644
--- a/common/zip-set.cpp
+++ b/common/zip-set.cpp
@@ -37,8 +37,8 @@ bool generateZipSet(SearchSet &searchSet, const char *defaultFile, const char *p
 	Archive *dat;
 	bool changed = false;
 
-	if (!ConfMan.get(packsPath).empty()) {
-		FSDirectory *iconDir = new FSDirectory(ConfMan.get(packsPath));
+	if (!ConfMan.getPath(packsPath).empty()) {
+		FSDirectory *iconDir = new FSDirectory(ConfMan.getPath(packsPath));
 		ArchiveMemberList iconFiles;
 
 		iconDir->listMatchingMembers(iconFiles, packsMask);
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 7e982ff4fed..34b7babdc50 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -337,7 +337,7 @@ bool ThemeEngine::init() {
 		Common::FSNode node(_themeFile);
 		if (node.isDirectory()) {
 			_themeArchive = new Common::FSDirectory(node);
-		} else if (_themeFile.matchString("*.zip", true)) {
+		} else if (_themeFile.baseName().matchString("*.zip", true)) {
 			// TODO: Also use "node" directly?
 			// Look for the zip file via SearchMan
 			Common::ArchiveMemberPtr member = SearchMan.getMember(_themeFile);
@@ -349,7 +349,7 @@ bool ThemeEngine::init() {
 			} else {
 				_themeArchive = Common::makeZipArchive(node);
 				if (!_themeArchive) {
-					warning("Failed to open Zip archive '%s'.", node.getPath().c_str());
+					warning("Failed to open Zip archive '%s'.", node.getPath().toString(Common::Path::kNativeSeparator).c_str());
 				}
 			}
 		}
@@ -362,7 +362,7 @@ bool ThemeEngine::init() {
 	// We pass the theme file here by default, so the user will
 	// have a descriptive error message. The only exception will
 	// be the builtin theme which has no filename.
-	loadTheme(_themeFile.empty() ? _themeId : _themeFile);
+	loadTheme(_themeFile.empty() ? _themeId : _themeFile.toString(Common::Path::kNativeSeparator));
 
 	return ready();
 }
@@ -648,7 +648,7 @@ bool ThemeEngine::addBitmap(const Common::String &filename, const Common::String
 
 	if (!scalablefile.empty()) {
 		Common::ArchiveMemberList members;
-		_themeFiles.listMatchingMembers(members, scalablefile);
+		_themeFiles.listMatchingMembers(members, Common::Path(scalablefile, '/'));
 		for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
 			Common::SeekableReadStream *stream = (*i)->createReadStream();
 			if (stream) {
@@ -668,7 +668,7 @@ bool ThemeEngine::addBitmap(const Common::String &filename, const Common::String
 #ifdef USE_PNG
 		Image::PNGDecoder decoder;
 		Common::ArchiveMemberList members;
-		_themeFiles.listMatchingMembers(members, filename);
+		_themeFiles.listMatchingMembers(members, Common::Path(filename, '/'));
 		for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
 			Common::SeekableReadStream *stream = (*i)->createReadStream();
 			if (stream) {
@@ -691,7 +691,7 @@ bool ThemeEngine::addBitmap(const Common::String &filename, const Common::String
 		// If not, try to load the bitmap via the BitmapDecoder class.
 		Image::BitmapDecoder bitmapDecoder;
 		Common::ArchiveMemberList members;
-		_themeFiles.listMatchingMembers(members, filename);
+		_themeFiles.listMatchingMembers(members, Common::Path(filename, '/'));
 		for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
 			Common::SeekableReadStream *stream = (*i)->createReadStream();
 			if (stream) {
@@ -1723,7 +1723,7 @@ const Graphics::Font *ThemeEngine::loadScalableFont(const Common::String &filena
 		return font;
 
 	Common::ArchiveMemberList members;
-	_themeFiles.listMatchingMembers(members, filename);
+	_themeFiles.listMatchingMembers(members, Common::Path(filename, '/'));
 
 	for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
 		Common::SeekableReadStream *stream = (*i)->createReadStream();
@@ -1753,14 +1753,15 @@ const Graphics::Font *ThemeEngine::loadFont(const Common::String &filename, Comm
 		return font;
 
 	Common::ArchiveMemberList members;
-	const Common::String cacheFilename(genCacheFilename(filename));
+	const Common::Path pathName(filename);
+	const Common::Path cacheFilename(genCacheFilename(filename));
 	_themeFiles.listMatchingMembers(members, cacheFilename);
-	_themeFiles.listMatchingMembers(members, filename);
+	_themeFiles.listMatchingMembers(members, pathName);
 
 	for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
 		Common::SeekableReadStream *stream = (*i)->createReadStream();
 		if (stream) {
-			if ((*i)->getName().equalsIgnoreCase(cacheFilename)) {
+			if ((*i)->getPathInArchive().equalsIgnoreCase(cacheFilename)) {
 				font = Graphics::BdfFont::loadFromCache(*stream);
 			} else {
 				font = Graphics::BdfFont::loadFont(*stream);
@@ -2013,7 +2014,7 @@ void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<Them
 
 	for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) {
 		// We will only process zip files for now
-		if (!i->getPath().matchString("*.zip", true))
+		if (!i->getPath().baseName().matchString("*.zip", true))
 			continue;
 
 		td.name.clear();
@@ -2046,22 +2047,23 @@ void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<Them
 		listUsableThemes(*i, list, depth == -1 ? - 1 : depth - 1);
 }
 
-Common::String ThemeEngine::getThemeFile(const Common::String &id) {
+Common::Path ThemeEngine::getThemeFile(const Common::String &id) {
 	// FIXME: Actually "default" rather sounds like it should use
 	// our default theme which would mean "scummremastered" instead
 	// of the builtin one.
 	if (id.equalsIgnoreCase("default"))
-		return Common::String();
+		return Common::Path();
 
 	// For our builtin theme we don't have to do anything for now too
 	if (id.equalsIgnoreCase("builtin"))
-		return Common::String();
+		return Common::Path();
 
-	Common::FSNode node(id);
+	Common::Path path(id, Common::Path::kNativeSeparator);
+	Common::FSNode node(path);
 
 	// If the given id is a full path we'll just use it
 	if (node.exists() && (node.isDirectory() || node.getName().matchString("*.zip", true)))
-		return id;
+		return path;
 
 	// FIXME:
 	// A very ugly hack to map a id to a filename, this will generate
@@ -2079,10 +2081,10 @@ Common::String ThemeEngine::getThemeFile(const Common::String &id) {
 
 	// If no matching id has been found we will
 	// just fall back to the builtin theme
-	return Common::String();
+	return Common::Path();
 }
 
-Common::String ThemeEngine::getThemeId(const Common::String &filename) {
+Common::String ThemeEngine::getThemeId(const Common::Path &filename) {
 	// If no filename has been given we will initialize the builtin theme
 	if (filename.empty())
 		return "builtin";
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 269e8b09466..54c081fe1b4 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -727,7 +727,7 @@ public:
 	struct ThemeDescriptor {
 		Common::String name;
 		Common::String id;
-		Common::String filename;
+		Common::Path filename;
 	};
 
 	/**
@@ -739,8 +739,8 @@ private:
 	static bool themeConfigUsable(const Common::ArchiveMember &member, Common::String &themeName);
 	static bool themeConfigParseHeader(Common::String header, Common::String &themeName);
 
-	static Common::String getThemeFile(const Common::String &id);
-	static Common::String getThemeId(const Common::String &filename);
+	static Common::Path getThemeFile(const Common::String &id);
+	static Common::String getThemeId(const Common::Path &filename);
 	static void listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth = -1);
 	static void listUsableThemes(Common::Archive &archive, Common::List<ThemeDescriptor> &list);
 
@@ -812,7 +812,7 @@ protected:
 
 	Common::String _themeName; ///< Name of the currently loaded theme
 	Common::String _themeId;
-	Common::String _themeFile;
+	Common::Path _themeFile;
 	Common::Archive *_themeArchive;
 	Common::SearchSet _themeFiles;
 
diff --git a/gui/browser.cpp b/gui/browser.cpp
index 3c1a0a94a9c..30d29058a24 100644
--- a/gui/browser.cpp
+++ b/gui/browser.cpp
@@ -104,7 +104,7 @@ void BrowserDialog::open() {
 	Dialog::open();
 
 	if (ConfMan.hasKey("browser_lastpath"))
-		_node = Common::FSNode(ConfMan.get("browser_lastpath"));
+		_node = Common::FSNode(ConfMan.getPath("browser_lastpath"));
 
 	if (!_node.isDirectory())
 		_node = Common::FSNode(".");
@@ -119,7 +119,7 @@ void BrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
 	switch (cmd) {
 	//Search for typed-in directory
 	case kPathEditedCmd:
-		_node = Common::FSNode(Common::convertFromU32String(_currentPath->getEditString()));
+		_node = Common::FSNode(Common::Path(Common::convertFromU32String(_currentPath->getEditString()), Common::Path::kNativeSeparator));
 		updateListing();
 		break;
 	//Search by text input
diff --git a/gui/debugger.cpp b/gui/debugger.cpp
index 032061f5b43..0fc30b80610 100644
--- a/gui/debugger.cpp
+++ b/gui/debugger.cpp
@@ -674,7 +674,7 @@ bool Debugger::cmdMd5(int argc, const char **argv) {
 			filename = filename + " " + argv[i];
 		}
 		Common::ArchiveMemberList list;
-		SearchMan.listMatchingMembers(list, filename);
+		SearchMan.listMatchingMembers(list, Common::Path(filename, Common::Path::kNativeSeparator));
 		if (list.empty()) {
 			debugPrintf("File '%s' not found\n", filename.c_str());
 		} else {
@@ -727,10 +727,10 @@ bool Debugger::cmdMd5Mac(int argc, const char **argv) {
 		// manager to open a specific file. Instead, it takes a "base name"
 		// and constructs a file name out of that. While usually a desirable
 		// thing, it's not ideal here.
-		if (!macResMan.open(filename)) {
+		if (!macResMan.open(Common::Path(filename, Common::Path::kNativeSeparator))) {
 			debugPrintf("Resource file '%s' not found\n", filename.c_str());
 		} else {
-			Common::ScopedPtr<Common::SeekableReadStream> dataFork(Common::MacResManager::openFileOrDataFork(filename));
+			Common::ScopedPtr<Common::SeekableReadStream> dataFork(Common::MacResManager::openFileOrDataFork(Common::Path(filename, Common::Path::kNativeSeparator)));
 			if (!macResMan.hasResFork() && !dataFork) {
 				debugPrintf("'%s' has neither data not resource fork\n", macResMan.getBaseFileName().toString().c_str());
 			} else {
@@ -824,7 +824,7 @@ bool Debugger::cmdExecFile(int argc, const char **argv) {
 	}
 	const Common::String filename(argv[1]);
 	Common::File file;
-	if (!file.open(filename)) {
+	if (!file.open(Common::Path(filename, Common::Path::kNativeSeparator))) {
 		debugPrintf("Can't open file %s\n", filename.c_str());
 		return false;
 	}
diff --git a/gui/dump-all-dialogs.cpp b/gui/dump-all-dialogs.cpp
index 962c9a51987..7799dbb5b5d 100644
--- a/gui/dump-all-dialogs.cpp
+++ b/gui/dump-all-dialogs.cpp
@@ -52,7 +52,7 @@ void saveGUISnapshot(Graphics::Surface surf, const Common::String &filename) {
 	Common::DumpFile outFile;
 	Common::String outName = Common::String::format("snapshots/%s", filename.c_str());
 
-	if (outFile.open(outName)) {
+	if (outFile.open(Common::Path(outName, '/'))) {
 		Image::writePNG(outFile, surf);
 		outFile.finalize();
 		outFile.close();
diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index f0639a2517a..237d93af5d3 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -112,9 +112,9 @@ EditGameDialog::EditGameDialog(const Common::String &domain)
 	}
 
 	// GAME: Path to game data (r/o), extra data (r/o), and save data (r/w)
-	Common::String gamePath(ConfMan.get("path", _domain));
-	Common::String extraPath(ConfMan.get("extrapath", _domain));
-	Common::String savePath(ConfMan.get("savepath", _domain));
+	Common::Path gamePath(ConfMan.getPath("path", _domain));
+	Common::Path extraPath(ConfMan.getPath("extrapath", _domain));
+	Common::Path savePath(ConfMan.getPath("savepath", _domain));
 
 	// GAME: Determine the description string
 	Common::String description(ConfMan.get("description", domain));
@@ -308,14 +308,14 @@ EditGameDialog::EditGameDialog(const Common::String &domain)
 		new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _("Game Path:"), Common::U32String(), kCmdGameBrowser);
 	else
 		new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _c("Game Path:", "lowres"), Common::U32String(), kCmdGameBrowser);
-	_gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath);
+	_gamePathWidget = new PathWidget(tab, "GameOptions_Paths.GamepathText", gamePath);
 
 	// GUI:  Button + Label for the additional path
 	if (!g_gui.useLowResGUI())
 		new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _("Extra Path:"), _("Specifies path to additional data used by the game"), kCmdExtraBrowser);
 	else
 		new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _c("Extra Path:", "lowres"), _("Specifies path to additional data used by the game"), kCmdExtraBrowser);
-	_extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath, _("Specifies path to additional data used by the game"));
+	_extraPathWidget = new PathWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath, _c("None", "path"), _("Specifies path to additional data used by the game"));
 
 	_extraPathClearButton = addClearButton(tab, "GameOptions_Paths.ExtraPathClearButton", kCmdExtraPathClear);
 
@@ -324,7 +324,7 @@ EditGameDialog::EditGameDialog(const Common::String &domain)
 		new ButtonWidget(tab, "GameOptions_Paths.Savepath", _("Save Path:"), _("Specifies where your saved games are put"), kCmdSaveBrowser);
 	else
 		new ButtonWidget(tab, "GameOptions_Paths.Savepath", _c("Save Path:", "lowres"), _("Specifies where your saved games are put"), kCmdSaveBrowser);
-	_savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath, _("Specifies where your saved games are put"));
+	_savePathWidget = new PathWidget(tab, "GameOptions_Paths.SavepathText", savePath, _("Default"), _("Specifies where your saved games are put"));
 
 	_savePathClearButton = addClearButton(tab, "GameOptions_Paths.SavePathClearButton", kCmdSavePathClear);
 
@@ -361,16 +361,6 @@ void EditGameDialog::setupGraphicsTab() {
 void EditGameDialog::open() {
 	OptionsDialog::open();
 
-	Common::String extraPath(ConfMan.get("extrapath", _domain));
-	if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) {
-		_extraPathWidget->setLabel(_c("None", "path"));
-	}
-
-	Common::String savePath(ConfMan.get("savepath", _domain));
-	if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
-		_savePathWidget->setLabel(_("Default"));
-	}
-
 	int sel, i;
 	bool e;
 
@@ -460,19 +450,19 @@ void EditGameDialog::apply() {
 			ConfMan.set("language", Common::getLanguageCode(lang), _domain);
 	}
 
-	Common::U32String gamePath(_gamePathWidget->getLabel());
+	Common::Path gamePath(_gamePathWidget->getLabel());
 	if (!gamePath.empty())
-		ConfMan.set("path", gamePath, _domain);
+		ConfMan.setPath("path", gamePath, _domain);
 
-	Common::U32String extraPath(_extraPathWidget->getLabel());
-	if (!extraPath.empty() && (extraPath != _c("None", "path")))
-		ConfMan.set("extrapath", extraPath, _domain);
+	Common::Path extraPath(_extraPathWidget->getLabel());
+	if (!extraPath.empty())
+		ConfMan.setPath("extrapath", extraPath, _domain);
 	else
 		ConfMan.removeKey("extrapath", _domain);
 
-	Common::U32String savePath(_savePathWidget->getLabel());
-	if (!savePath.empty() && (savePath != _("Default")))
-		ConfMan.set("savepath", savePath, _domain);
+	Common::Path savePath(_savePathWidget->getLabel());
+	if (!savePath.empty())
+		ConfMan.setPath("savepath", savePath, _domain);
 	else
 		ConfMan.removeKey("savepath", _domain);
 
@@ -527,7 +517,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
 			Common::FSNode file(browser.getResult());
 			_soundFont->setLabel(file.getPath());
 
-			if (!file.getPath().empty() && (file.getPath() != Common::convertFromU32String(_c("None", "path"))))
+			if (!file.getPath().empty())
 				_soundFontClearButton->setEnabled(true);
 			else
 				_soundFontClearButton->setEnabled(false);
@@ -594,11 +584,11 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
 	}
 
 	case kCmdExtraPathClear:
-		_extraPathWidget->setLabel(_c("None", "path"));
+		_extraPathWidget->setLabel(Common::Path());
 		break;
 
 	case kCmdSavePathClear:
-		_savePathWidget->setLabel(_("Default"));
+		_savePathWidget->setLabel(Common::Path());
 		break;
 
 	case kOKCmd:
diff --git a/gui/editgamedialog.h b/gui/editgamedialog.h
index c2076bebe77..b7b31bc5758 100644
--- a/gui/editgamedialog.h
+++ b/gui/editgamedialog.h
@@ -70,9 +70,9 @@ protected:
 	EditTextWidget *_descriptionWidget;
 	DomainEditTextWidget *_domainWidget;
 
-	StaticTextWidget *_gamePathWidget;
-	StaticTextWidget *_extraPathWidget;
-	StaticTextWidget *_savePathWidget;
+	PathWidget *_gamePathWidget;
+	PathWidget *_extraPathWidget;
+	PathWidget *_savePathWidget;
 	ButtonWidget *_extraPathClearButton;
 	ButtonWidget *_savePathClearButton;
 
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 8e6a53b5c0b..fba7df8aba2 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -1136,7 +1136,7 @@ void LauncherSimple::updateListing() {
 
 		if (scanEntries) {
 			Common::String path;
-			if (!iter->domain->tryGetVal("path", path) || !Common::FSNode(path).isDirectory()) {
+			if (!iter->domain->tryGetVal("path", path) || !Common::FSNode(Common::Path::fromConfig(path)).isDirectory()) {
 				color = ThemeEngine::kFontColorAlternate;
 				// If more conditions which grey out entries are added we should consider
 				// enabling this so that it is easy to spot why a certain game entry cannot
@@ -1576,7 +1576,7 @@ void LauncherGrid::updateListing() {
 		iter->domain->tryGetVal("language", language);
 		iter->domain->tryGetVal("platform", platform);
 		iter->domain->tryGetVal("extra", extra);
-		valid_path = (!iter->domain->tryGetVal("path", path) || !Common::FSNode(path).isDirectory()) ? false : true;
+		valid_path = (!iter->domain->tryGetVal("path", path) || !Common::FSNode(Common::Path::fromConfig(path)).isDirectory()) ? false : true;
 		gridList.push_back(GridItemInfo(k++, engineid, gameid, iter->description, iter->title, extra, Common::parseLanguage(language), Common::parsePlatform(platform), valid_path));
 		_domains.push_back(iter->key);
 	}
diff --git a/gui/massadd.cpp b/gui/massadd.cpp
index 839e0027244..f279d8a04a4 100644
--- a/gui/massadd.cpp
+++ b/gui/massadd.cpp
@@ -96,15 +96,16 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir)
 	const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
 	Common::ConfigManager::DomainMap::const_iterator iter;
 	for (iter = domains.begin(); iter != domains.end(); ++iter) {
-		Common::String path(iter->_value.getVal("path"));
+		Common::Path path(Common::Path::fromConfig(iter->_value.getVal("path")));
+
 		// Remove trailing slash, so that "/foo" and "/foo/" match.
 		// This works around a bug in the POSIX FS code (and others?)
 		// where paths are not normalized (so FSNodes refering to identical
 		// FS objects may return different values in path()).
-		while (path != "/" && path.lastChar() == '/')
-			path.deleteLastChar();
-		if (!path.empty())
+		path.removeTrailingSeparators();
+		if (!path.empty()) {
 			_pathToTargets[path].push_back(iter->_key);
+		}
 	}
 }
 
@@ -193,11 +194,8 @@ void MassAddDialog::handleTickle() {
 		for (DetectedGames::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) {
 			const DetectedGame &result = *cand;
 
-			Common::String path = dir.getPath();
-
-			// Remove trailing slashes
-			while (path != "/" && path.lastChar() == '/')
-				path.deleteLastChar();
+			Common::Path path = dir.getPath();
+			path.removeTrailingSeparators();
 
 			// Check for existing config entries for this path/engineid/gameid/lang/platform combination
 			if (_pathToTargets.contains(path)) {
diff --git a/gui/massadd.h b/gui/massadd.h
index 99b493b2a30..c2206497d83 100644
--- a/gui/massadd.h
+++ b/gui/massadd.h
@@ -56,7 +56,8 @@ private:
 	 * Used to detect whether a potential new target is already present in the
 	 * config manager.
 	 */
-	Common::HashMap<Common::String, Common::StringArray>	_pathToTargets;
+	Common::HashMap<Common::Path, Common::StringArray,
+		Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> _pathToTargets;
 
 	int _dirsScanned;
 	int _oldGamesCount;
diff --git a/gui/options.cpp b/gui/options.cpp
index aa7455c2967..c48869d9e3d 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -428,17 +428,19 @@ void OptionsDialog::build() {
 		enableShaderControls(g_system->hasFeature(OSystem::kFeatureShaders));
 
 		if (g_system->hasFeature(OSystem::kFeatureShaders)) {
-			Common::String shader(ConfMan.get("shader", _domain));
+			Common::Path shader(ConfMan.getPath("shader", _domain));
 			if (ConfMan.isKeyTemporary("shader")) {
 				_shader->setFontColor(ThemeEngine::FontColor::kFontColorOverride);
 			}
-			if (shader.empty() || shader == "default" || !ConfMan.hasKey("shader", _domain)) {
-				_shader->setLabel(_c("None", "shader"));
+			if (shader == Common::Path("default", Common::Path::kNoSeparator)) {
+				shader.clear();
+			}
+			if (shader.empty() || !ConfMan.hasKey("shader", _domain)) {
 				_shaderClearButton->setEnabled(false);
 			} else {
-				_shader->setLabel(shader);
 				_shaderClearButton->setEnabled(true);
 			}
+			_shader->setLabel(shader);
 		}
 	}
 
@@ -474,20 +476,19 @@ void OptionsDialog::build() {
 		if (ConfMan.isKeyTemporary("multi_midi"))
 			_multiMidiCheckbox->setOverride(true);
 
-		Common::String soundFont(ConfMan.get("soundfont", _domain));
+		Common::Path soundFont(ConfMan.getPath("soundfont", _domain));
 		if (ConfMan.isKeyTemporary("soundfont")) {
 			_soundFont->setFontColor(ThemeEngine::FontColor::kFontColorOverride);
 		}
 		if (soundFont.empty()) {
-			_soundFont->setLabel(_c("None", "soundfont"));
 			_soundFontClearButton->setEnabled(false);
 		} else if (!ConfMan.hasKey("soundfont", _domain)) {
-			_soundFont->setLabel(_("Default"));
+			soundFont.clear();
 			_soundFontClearButton->setEnabled(false);
 		} else {
-			_soundFont->setLabel(soundFont);
 			_soundFontClearButton->setEnabled(true);
 		}
+		_soundFont->setLabel(soundFont);
 
 		// MIDI gain setting
 		_midiGainSlider->setValue(ConfMan.getInt("midi_gain", _domain));
@@ -742,23 +743,28 @@ void OptionsDialog::apply() {
 		}
 	}
 
-	Common::U32String previousShader;
+	Common::Path previousShader;
 
 	// Shader options
 	if (g_system->hasFeature(OSystem::kFeatureShaders) && _shader) {
-		if (ConfMan.hasKey("shader", _domain) && !ConfMan.get("shader", _domain).empty())
-			previousShader = ConfMan.get("shader", _domain);
-
-		Common::U32String shader(_shader->getLabel());
+		Common::Path shaderConf;
+		if (ConfMan.hasKey("shader", _domain)) {
+			shaderConf = ConfMan.getPath("shader", _domain);
+			if (!shaderConf.empty()) {
+				previousShader = ConfMan.getPath("shader", _domain);
+			}
+		}
 
-		if (shader == _c("None", "shader"))
-			shader = "default";
+		Common::Path shader(_shader->getLabel());
+		if (shader.empty()) {
+			shader = Common::Path("default", Common::Path::kNoSeparator);
+		}
 
-		if (!ConfMan.hasKey("shader", _domain) || shader != ConfMan.get("shader", _domain))
+		if (!ConfMan.hasKey("shader", _domain) || shader != shaderConf)
 			graphicsModeChanged = true;
 
 		if (_enableGraphicSettings)
-			ConfMan.set("shader", shader.encode(), _domain);
+			ConfMan.setPath("shader", shader, _domain);
 		else
 			ConfMan.removeKey("shader", _domain);
 
@@ -851,12 +857,9 @@ void OptionsDialog::apply() {
 			}
 
 			if (gfxError & OSystem::kTransactionShaderChangeFailed) {
-				if (previousShader == _c("None", "shader"))
-					previousShader = "default";
-
-				ConfMan.set("shader", previousShader.encode(), _domain);
-				if (previousShader.empty()) {
-					_shader->setLabel(_c("None", "shader"));
+				ConfMan.setPath("shader", previousShader, _domain);
+				if (previousShader.empty() || previousShader == Common::Path("default", Common::Path::kNoSeparator)) {
+					_shader->setLabel(Common::Path());
 					_shaderClearButton->setEnabled(false);
 				} else {
 					_shader->setLabel(previousShader);
@@ -872,19 +875,17 @@ void OptionsDialog::apply() {
 			dialog.runModal();
 		} else {
 			// Successful transaction. Check if we need to show test screen
-			Common::String shader;
+			Common::Path shader;
 			if (ConfMan.hasKey("shader", _domain))
-				shader = ConfMan.get("shader", _domain);
+				shader = ConfMan.getPath("shader", _domain);
 
 			// If shader was changed, show the test dialog
-			if (previousShader != shader && !shader.empty() && shader != "default") {
+			if (previousShader != shader && !shader.empty() &&
+					shader != Common::Path("default", Common::Path::kNoSeparator)) {
 				if (!testGraphicsSettings()) {
-					if (previousShader == _c("None", "shader"))
-						previousShader = "default";
-
-					ConfMan.set("shader", previousShader.encode(), _domain);
-					if (previousShader.empty()) {
-						_shader->setLabel(_c("None", "shader"));
+					ConfMan.setPath("shader", previousShader, _domain);
+					if (previousShader.empty() || previousShader == Common::Path("default", Common::Path::kNoSeparator)) {
+						_shader->setLabel(Common::Path());
 						_shaderClearButton->setEnabled(false);
 					} else {
 						_shader->setLabel(previousShader);
@@ -987,13 +988,13 @@ void OptionsDialog::apply() {
 				_midiGainDesc->setFontColor(ThemeEngine::FontColor::kFontColorNormal);
 			}
 
-			Common::U32String soundFont(_soundFont->getLabel());
-			if (soundFont != ConfMan.get("soundfont", _domain)) {
+			Common::Path soundFont(_soundFont->getLabel());
+			if (soundFont != ConfMan.getPath("soundfont", _domain)) {
 				_soundFont->setFontColor(ThemeEngine::FontColor::kFontColorNormal);
-				if (soundFont.empty() || (soundFont == _c("None", "soundfont")) || (soundFont == _("Default")))
+				if (soundFont.empty())
 					ConfMan.removeKey("soundfont", _domain);
 				else
-					ConfMan.set("soundfont", soundFont.encode(), _domain);
+					ConfMan.setPath("soundfont", soundFont, _domain);
 			}
 		} else {
 			ConfMan.removeKey("gm_device", _domain);
@@ -1088,7 +1089,7 @@ void OptionsDialog::close() {
 void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
 	switch (cmd) {
 	case kClearShaderCmd:
-		_shader->setLabel(_c("None", "shader"));
+		_shader->setLabel(Common::Path());
 		_shaderClearButton->setEnabled(false);
 		break;
 	case kMidiGainChanged:
@@ -1154,10 +1155,7 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
 		_subSpeedLabel->markAsDirty();
 		break;
 	case kClearSoundFontCmd:
-		if (ConfMan.hasDefault("soundfont"))
-			_soundFont->setLabel(_("Default"));
-		else
-			_soundFont->setLabel(_c("None", "soundfont"));
+		_soundFont->setLabel(Common::Path());
 		_soundFontClearButton->setEnabled(false);
 		break;
 	case kKbdMouseSpeedChanged:
@@ -1175,12 +1173,12 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
 		g_gui.scheduleTopDialogRedraw();
 		break;
 	case kChooseShaderCmd: {
-		ShaderBrowserDialog browser(ConfMan.get("shader", _domain));
+		ShaderBrowserDialog browser(ConfMan.getPath("shader", _domain));
 		if (browser.runModal() > 0) {
 			// User made his choice...
 			_shader->setLabel(browser.getResult());
 
-			if (!browser.getResult().empty() && (browser.getResult().decode() != _c("None", "path")))
+			if (!browser.getResult().empty())
 				_shaderClearButton->setEnabled(true);
 			else
 				_shaderClearButton->setEnabled(false);
@@ -1313,7 +1311,7 @@ void OptionsDialog::setMIDISettingsState(bool enabled) {
 	_soundFontButton->setEnabled(enabled);
 	_soundFont->setEnabled(enabled);
 
-	if (enabled && !_soundFont->getLabel().empty() && (_soundFont->getLabel() != _c("None", "soundfont")) && (_soundFont->getLabel() != _("Default")))
+	if (enabled && !_soundFont->getLabel().empty())
 		_soundFontClearButton->setEnabled(enabled);
 	else
 		_soundFontClearButton->setEnabled(false);
@@ -1625,7 +1623,7 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const Common::String &pr
 		_shaderButton = new ButtonWidget(boss, prefix + "grShaderButton", _("Shader:"), _("Specifies path to the shader used for scaling the game screen"), kChooseShaderCmd);
 	else
 		_shaderButton = new ButtonWidget(boss, prefix + "grShaderButton", _c("Shader Path:", "lowres"), _("Specifies path to the shader used for scaling the game screen"), kChooseShaderCmd);
-	_shader = new StaticTextWidget(boss, prefix + "grShader", _c("None", "shader"), _("Specifies path to the shader used for scaling the game screen"));
+	_shader = new PathWidget(boss, prefix + "grShader", Common::Path(), _c("None", "shader"), _("Specifies path to the shader used for scaling the game screen"));
 
 	_shaderClearButton = addClearButton(boss, prefix + "grShaderClearButton", kClearShaderCmd);
 
@@ -1780,7 +1778,14 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi
 		_soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"), kChooseSoundFontCmd);
 	else
 		_soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _c("SoundFont:", "lowres"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"), kChooseSoundFontCmd);
-	_soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", _c("None", "soundfont"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"));
+
+	Common::U32String soundFountPlaceholder;
+	if (ConfMan.hasDefault("soundfont")) {
+		soundFountPlaceholder = _("Default");
+	} else {
+		soundFountPlaceholder = _c("None", "soundfont");
+	}
+	_soundFont = new PathWidget(boss, prefix + "mcFontPath", Common::Path(), soundFountPlaceholder, _("SoundFont is supported by some audio cards, FluidSynth and Timidity"));
 
 	_soundFontClearButton = addClearButton(boss, prefix + "mcFontClearButton", kClearSoundFontCmd);
 
@@ -2344,33 +2349,31 @@ void GlobalOptionsDialog::build() {
 
 #if !defined(__DC__)
 	const auto setPath =
-	[&](GUI::StaticTextWidget *const widget, const Common::String &pathType, const Common::U32String &defaultLabel) {
-		Common::String path(ConfMan.get(pathType));
+	[&](GUI::PathWidget *const widget, const Common::String &pathType) {
+		Common::Path path(ConfMan.getPath(pathType));
 		if (ConfMan.isKeyTemporary(pathType)) {
 			widget->setFontColor(ThemeEngine::FontColor::kFontColorOverride);
 		}
-		if (path.empty() || !ConfMan.hasKey(pathType, _domain)) {
-			widget->setLabel(defaultLabel);
-		} else {
-			widget->setLabel(path);
+		if (!ConfMan.hasKey(pathType, _domain)) {
+			path.clear();
 		}
+		widget->setLabel(path);
 	};
 
-	setPath(_savePath, "savepath", _("Default"));
-	setPath(_themePath, "themepath", _c("None", "path"));
-	setPath(_iconPath, "iconspath", _("Default"));
+	setPath(_savePath, "savepath");
+	setPath(_themePath, "themepath");
+	setPath(_iconPath, "iconspath");
 #ifdef USE_DLC
-	setPath(_dlcPath, "dlcspath", _("Default"));
+	setPath(_dlcPath, "dlcspath");
 #endif
-	setPath(_extraPath, "extrapath", _c("None", "path"));
+	setPath(_extraPath, "extrapath");
 
 #ifdef DYNAMIC_MODULES
-	Common::String pluginsPath(ConfMan.get("pluginspath", _domain));
-	if (pluginsPath.empty() || !ConfMan.hasKey("pluginspath", _domain)) {
-		_pluginsPath->setLabel(_c("None", "path"));
-	} else {
-		_pluginsPath->setLabel(pluginsPath);
+	Common::Path pluginsPath(ConfMan.getPath("pluginspath", _domain));
+	if (!ConfMan.hasKey("pluginspath", _domain)) {
+		pluginsPath.clear();
 	}
+	_pluginsPath->setLabel(pluginsPath);
 #endif
 #endif
 
@@ -2398,12 +2401,8 @@ void GlobalOptionsDialog::build() {
 
 #ifdef USE_CLOUD
 #ifdef USE_SDL_NET
-	Common::String rootPath(ConfMan.get("rootpath", "cloud"));
-	if (rootPath.empty() || !ConfMan.hasKey("rootpath", "cloud")) {
-		_rootPath->setLabel(_c("None", "path"));
-	} else {
-		_rootPath->setLabel(rootPath);
-	}
+	Common::Path rootPath(ConfMan.getPath("rootpath", "cloud"));
+	_rootPath->setLabel(rootPath);
 #endif
 #endif
 }
@@ -2435,7 +2434,7 @@ void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String
 		new ButtonWidget(boss, prefix + "SaveButton", _("Save Path:"), _("Specifies where your saved games are put"), kChooseSaveDirCmd);
 	else
 		new ButtonWidget(boss, prefix + "SaveButton", _c("Save Path:", "lowres"), _("Specifies where your saved games are put"), kChooseSaveDirCmd);
-	_savePath = new StaticTextWidget(boss, prefix + "SavePath", Common::U32String("/foo/bar"), _("Specifies where your saved games are put. A red coloring indicates the value is temporary and will not get saved"));
+	_savePath = new PathWidget(boss, prefix + "SavePath", Common::Path(), _("Default"), _("Specifies where your saved games are put. A red coloring indicates the value is temporary and will not get saved"));
 
 	_savePathClearButton = addClearButton(boss, prefix + "SavePathClearButton", kSavePathClearCmd);
 
@@ -2443,7 +2442,7 @@ void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String
 		new ButtonWidget(boss, prefix + "ThemeButton", _("Theme Path:"), Common::U32String(), kChooseThemeDirCmd);
 	else
 		new ButtonWidget(boss, prefix + "ThemeButton", _c("Theme Path:", "lowres"), Common::U32String(), kChooseThemeDirCmd);
-	_themePath = new StaticTextWidget(boss, prefix + "ThemePath", _c("None", "path"));
+	_themePath = new PathWidget(boss, prefix + "ThemePath", Common::Path(), _c("None", "path"));
 
 	_themePathClearButton = addClearButton(boss, prefix + "ThemePathClearButton", kThemePathClearCmd);
 
@@ -2451,7 +2450,7 @@ void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String
 		new ButtonWidget(boss, prefix + "IconButton", _("Icon Path:"), Common::U32String(), kChooseIconDirCmd);
 	else
 		new ButtonWidget(boss, prefix + "IconButton", _c("Icon Path:", "lowres"), Common::U32String(), kChooseIconDirCmd);
-	_iconPath = new StaticTextWidget(boss, prefix + "IconPath", _c("Default", "path"));
+	_iconPath = new PathWidget(boss, prefix + "IconPath", Common::Path(), _c("Default", "path"));
 
 	_iconPathClearButton = addClearButton(boss, prefix + "IconPathClearButton", kIconPathClearCmd);
 
@@ -2461,7 +2460,7 @@ void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String
 			new ButtonWidget(boss, prefix + "DLCButton", _("DLC Path:"), Common::U32String(), kChooseDLCDirCmd);
 		else
 			new ButtonWidget(boss, prefix + "DLCButton", _c("DLC Path:", "lowres"), Common::U32String(), kChooseDLCDirCmd);
-		_dlcPath = new StaticTextWidget(boss, prefix + "DLCPath", _c("Default", "path"));
+		_dlcPath = new PathWidget(boss, prefix + "DLCPath", Common::Path(), _c("Default", "path"));
 
 		_dlcPathClearButton = addClearButton(boss, prefix + "DLCPathClearButton", kDLCPathClearCmd);
 	}
@@ -2471,7 +2470,7 @@ void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String
 		new ButtonWidget(boss, prefix + "ExtraButton", _("Extra Path:"), _("Specifies path to additional data used by all games or ScummVM"), kChooseExtraDirCmd);
 	else
 		new ButtonWidget(boss, prefix + "ExtraButton", _c("Extra Path:", "lowres"), _("Specifies path to additional data used by all games or ScummVM"), kChooseExtraDirCmd);
-	_extraPath = new StaticTextWidget(boss, prefix + "ExtraPath", _c("None", "path"), _("Specifies path to additional data used by all games or ScummVM"));
+	_extraPath = new PathWidget(boss, prefix + "ExtraPath", Common::Path(), _c("None", "path"), _("Specifies path to additional data used by all games or ScummVM"));
 
 	_extraPathClearButton = addClearButton(boss, prefix + "ExtraPathClearButton", kExtraPathClearCmd);
 
@@ -2750,7 +2749,7 @@ void GlobalOptionsDialog::addNetworkControls(GuiObject *boss, const Common::Stri
 		_rootPathButton = new ButtonWidget(boss, prefix + "RootPathButton", _c("/root/ Path:", "lowres"), _("Select which directory will be shown as /root/ in the Files Manager"), kChooseRootDirCmd);
 	else
 		_rootPathButton = new ButtonWidget(boss, prefix + "RootPathButton", _("/root/ Path:"), _("Select which directory will be shown as /root/ in the Files Manager"), kChooseRootDirCmd);
-	_rootPath = new StaticTextWidget(boss, prefix + "RootPath", Common::U32String("/foo/bar"), _("Select which directory will be shown as /root/ in the Files Manager"));
+	_rootPath = new PathWidget(boss, prefix + "RootPath", Common::Path(), _c("None", "path"), _("Select which directory will be shown as /root/ in the Files Manager"));
 	_rootPathClearButton = addClearButton(boss, prefix + "RootPathClearButton", kRootPathClearCmd);
 
 	uint32 port = Networking::LocalWebserver::getPort();
@@ -2898,38 +2897,38 @@ void GlobalOptionsDialog::apply() {
 	bool isRebuildNeeded = false;
 
 	const auto changePath =
-	[&](GUI::StaticTextWidget *const widget, const Common::String &pathType, const Common::U32String &defaultLabel) {
-		Common::U32String label(widget->getLabel());
-		if (label != ConfMan.get(pathType)) {
+	[&](GUI::PathWidget *const widget, const Common::String &pathType) {
+		Common::Path label(widget->getLabel());
+		if (label != ConfMan.getPath(pathType)) {
 			widget->setFontColor(ThemeEngine::FontColor::kFontColorNormal);
-			if (label.empty() || (label == defaultLabel))
+			if (label.empty())
 				ConfMan.removeKey(pathType, _domain);
 			else
-				ConfMan.set(pathType, label.encode(), _domain);
+				ConfMan.setPath(pathType, label, _domain);
 		}
 	};
 
-	changePath(_savePath, "savepath", _("Default"));
-	changePath(_themePath, "themepath", _c("None", "path"));
-	changePath(_iconPath, "iconspath", _("Default"));
+	changePath(_savePath, "savepath");
+	changePath(_themePath, "themepath");
+	changePath(_iconPath, "iconspath");
 #ifdef USE_DLC
-	changePath(_dlcPath, "dlcspath", _("Default"));
+	changePath(_dlcPath, "dlcspath");
 #endif
-	changePath(_extraPath, "extrapath", _c("None", "path"));
+	changePath(_extraPath, "extrapath");
 
 #ifdef DYNAMIC_MODULES
-	Common::U32String pluginsPath(_pluginsPath->getLabel());
-	if (!pluginsPath.empty() && (pluginsPath != _c("None", "path")))
-		ConfMan.set("pluginspath", pluginsPath.encode(), _domain);
+	Common::Path pluginsPath(_pluginsPath->getLabel());
+	if (!pluginsPath.empty())
+		ConfMan.setPath("pluginspath", pluginsPath, _domain);
 	else
 		ConfMan.removeKey("pluginspath", _domain);
 #endif // DYNAMIC_MODULES
 
 #ifdef USE_CLOUD
 #ifdef USE_SDL_NET
-	Common::U32String rootPath(_rootPath->getLabel());
-	if (!rootPath.empty() && (rootPath != _c("None", "path")))
-		ConfMan.set("rootpath", rootPath.encode(), "cloud");
+	Common::Path rootPath(_rootPath->getLabel());
+	if (!rootPath.empty())
+		ConfMan.setPath("rootpath", rootPath, "cloud");
 	else
 		ConfMan.removeKey("rootpath", "cloud");
 #endif // USE_SDL_NET
@@ -3228,9 +3227,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 		if (browser.runModal() > 0) {
 			// User made his choice...
 			Common::FSNode dir(browser.getResult());
-			Common::String path = dir.getPath();
-			if (path.empty())
-				path = "/"; // absolute root
+			Common::Path path = dir.getPath();
 			_rootPath->setLabel(path);
 			g_gui.scheduleTopDialogRedraw();
 		}
@@ -3259,25 +3256,25 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 
 #endif
 	case kThemePathClearCmd:
-		_themePath->setLabel(_c("None", "path"));
+		_themePath->setLabel(Common::Path());
 		break;
 	case kIconPathClearCmd:
-		_iconPath->setLabel(_("Default"));
+		_iconPath->setLabel(Common::Path());
 		break;
 #ifdef USE_DLC
 	case kDLCPathClearCmd:
-		_dlcPath->setLabel(_("Default"));
+		_dlcPath->setLabel(Common::Path());
 		break;
 #endif
 	case kExtraPathClearCmd:
-		_extraPath->setLabel(_c("None", "path"));
+		_extraPath->setLabel(Common::Path());
 		break;
 	case kSavePathClearCmd:
-		_savePath->setLabel(_("Default"));
+		_savePath->setLabel(Common::Path());
 		break;
 #ifdef DYNAMIC_MODULES
 	case kPluginsPathClearCmd:
-		_pluginsPath->setLabel(_c("None", "path"));
+		_pluginsPath->setLabel(Common::Path());
 		break;
 #endif
 	case kBrowserPathClearCmd:
@@ -3302,7 +3299,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 #ifdef USE_CLOUD
 #ifdef USE_SDL_NET
 	case kRootPathClearCmd:
-		_rootPath->setLabel(_c("None", "path"));
+		_rootPath->setLabel(Common::Path());
 		break;
 #endif
 #endif
@@ -3313,7 +3310,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 			Common::FSNode file(browser.getResult());
 			_soundFont->setLabel(file.getPath());
 
-			if (!file.getPath().empty() && (file.getPath().decode() != _c("None", "path")))
+			if (!file.getPath().empty())
 				_soundFontClearButton->setEnabled(true);
 			else
 				_soundFontClearButton->setEnabled(false);
diff --git a/gui/options.h b/gui/options.h
index ea420590bca..b3160e0bdeb 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -54,6 +54,7 @@ class CommandSender;
 class GuiObject;
 class RadiobuttonGroup;
 class RadiobuttonWidget;
+class PathWidget;
 class OptionsContainerWidget;
 
 class OptionsDialog : public Dialog {
@@ -80,7 +81,7 @@ protected:
 	Common::String _domain;
 
 	ButtonWidget *_soundFontButton;
-	StaticTextWidget *_soundFont;
+	PathWidget *_soundFont;
 	ButtonWidget *_soundFontClearButton;
 
 	virtual void build();
@@ -121,7 +122,7 @@ protected:
 	int _midiTabId;
 	int _pathsTabId;
 
-	StaticTextWidget *_shader;
+	PathWidget *_shader;
 	ButtonWidget *_shaderClearButton;
 	ButtonWidget *_updateShadersButton = nullptr;
 
@@ -275,20 +276,20 @@ protected:
 
 	void addMIDIControls(GuiObject *boss, const Common::String &prefix);
 
-	StaticTextWidget *_savePath;
+	PathWidget       *_savePath;
 	ButtonWidget	 *_savePathClearButton;
-	StaticTextWidget *_themePath;
+	PathWidget       *_themePath;
 	ButtonWidget	 *_themePathClearButton;
-	StaticTextWidget *_iconPath;
+	PathWidget       *_iconPath;
 	ButtonWidget	 *_iconPathClearButton;
 #ifdef USE_DLC
-	StaticTextWidget *_dlcPath;
+	PathWidget       *_dlcPath;
 	ButtonWidget	 *_dlcPathClearButton;
 #endif
-	StaticTextWidget *_extraPath;
+	PathWidget       *_extraPath;
 	ButtonWidget	 *_extraPathClearButton;
 #ifdef DYNAMIC_MODULES
-	StaticTextWidget *_pluginsPath;
+	PathWidget       *_pluginsPath;
 	ButtonWidget	 *_pluginsPathClearButton;
 #endif
 	StaticTextWidget *_browserPath;
@@ -376,7 +377,7 @@ protected:
 	ButtonWidget	 *_runServerButton;
 	StaticTextWidget *_serverInfoLabel;
 	ButtonWidget	 *_rootPathButton;
-	StaticTextWidget *_rootPath;
+	PathWidget       *_rootPath;
 	ButtonWidget	 *_rootPathClearButton;
 	StaticTextWidget *_serverPortDesc;
 	EditTextWidget   *_serverPort;
diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp
index e60ad2a5250..94943713155 100644
--- a/gui/predictivedialog.cpp
+++ b/gui/predictivedialog.cpp
@@ -984,7 +984,7 @@ void PredictiveDialog::loadAllDictionary(Dict &dict) {
 
 	if (dict.nameDict == "predictive_dictionary") {
 		Common::File *inFile = new Common::File();
-		if (!inFile->open(ConfMan.get(dict.nameDict))) {
+		if (!inFile->open(ConfMan.getPath(dict.nameDict))) {
 			warning("Predictive Dialog: cannot read file: %s", dict.defaultFilename.c_str());
 			delete inFile;
 			return;
diff --git a/gui/shaderbrowser-dialog.cpp b/gui/shaderbrowser-dialog.cpp
index c7beca110ad..d5388e6c7e4 100644
--- a/gui/shaderbrowser-dialog.cpp
+++ b/gui/shaderbrowser-dialog.cpp
@@ -47,12 +47,11 @@ enum {
 const char *kFileMask = "*.glslp";
 const char *kFileExt  = "glslp";
 
-ShaderBrowserDialog::ShaderBrowserDialog(const Common::String &initialSelection) : Dialog("ShaderBrowser") {
+ShaderBrowserDialog::ShaderBrowserDialog(const Common::Path &initialSelection) : Dialog("ShaderBrowser") {
 
 	new StaticTextWidget(this, "ShaderBrowser.Headline", _("Choose shader from the list below (or pick a file instead)"));
 
-	_fileName = new EditTextWidget(this, "ShaderBrowser.Filename", Common::U32String());
-	_fileName->setEditString(initialSelection);
+	_fileName = new PathWidget(this, "ShaderBrowser.Filename", initialSelection);
 
 	// Search box
 	_searchDesc = nullptr;
@@ -125,10 +124,10 @@ void ShaderBrowserDialog::reflowLayout() {
 void ShaderBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
 	switch (cmd) {
 	case kChooseCmd:
-		if (_fileName->getEditString().empty())
+		if (_fileName->getLabel().empty())
 			break;
 
-		normalieFileName();
+		normalizeFileName();
 
 		setResult(1);
 		close();
@@ -138,7 +137,7 @@ void ShaderBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 		if (browser.runModal() > 0) {
 			// User made his choice...
 			Common::FSNode file(browser.getResult());
-			_fileName->setEditString(file.getPath());
+			_fileName->setLabel(file.getPath());
 
 			setResult(1);
 			close();
@@ -155,11 +154,11 @@ void ShaderBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 		_fileList->setFilter(Common::U32String());
 		break;
 	case kListSelectionChangedCmd:
-		_fileName->setEditString(_fileList->getList().operator[](_fileList->getSelected()));
+		_fileName->setLabel(Common::Path(_fileList->getList().operator[](_fileList->getSelected()).encode()));
 		break;
 	case kListItemActivatedCmd:
 	case kListItemDoubleClickedCmd:
-		normalieFileName();
+		normalizeFileName();
 		setResult(1);
 		close();
 		break;
@@ -168,13 +167,15 @@ void ShaderBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 	}
 }
 
-void ShaderBrowserDialog::normalieFileName() {
-	Common::String filename = Common::convertFromU32String(_fileName->getEditString());
+void ShaderBrowserDialog::normalizeFileName() {
+	Common::Path filename = _fileName->getLabel();
 
-	if (filename.matchString(kFileMask, true))
+	Common::String basename = filename.baseName();
+	if (basename.matchString(kFileMask, true))
 		return;
 
-	_fileName->setEditString(filename + "." + kFileExt);
+	filename.appendInPlace(".").appendInPlace(kFileExt);
+	_fileName->setLabel(filename);
 }
 
 
@@ -187,7 +188,7 @@ void ShaderBrowserDialog::updateListing() {
 	Common::sort(files.begin(), files.end(), Common::ArchiveMemberListComparator());
 
 	for (auto &file : files) {
-		list.push_back(Common::U32String(file->getName()));
+		list.push_back(file->getPathInArchive().toString().decode());
 	}
 
 	_fileList->setList(list);
diff --git a/gui/shaderbrowser-dialog.h b/gui/shaderbrowser-dialog.h
index 6cfeb3e6e56..3e1b9417ba2 100644
--- a/gui/shaderbrowser-dialog.h
+++ b/gui/shaderbrowser-dialog.h
@@ -38,17 +38,17 @@ enum {
 
 class ShaderBrowserDialog : public Dialog {
 public:
-	ShaderBrowserDialog(const Common::String &initialSelection);
+	ShaderBrowserDialog(const Common::Path &initialSelection);
 
 	void open() override;
 	void reflowLayout() override;
 
 	void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
 
-	Common::String getResult() { return Dialog::getResult() ? _fileName->getEditString().encode() : Common::String(); }
+	Common::Path getResult() { return Dialog::getResult() ? _fileName->getLabel() : Common::Path(); }
 
 protected:
-	EditTextWidget   *_fileName;
+	PathWidget       *_fileName;
 	ListWidget	     *_fileList;
 	Common::SearchSet _shaderSet;
 	Common::String	  _search;
@@ -61,7 +61,7 @@ protected:
 	ButtonWidget     *_searchClearButton;
 
 	void updateListing();
-	void normalieFileName();
+	void normalizeFileName();
 };
 
 } // End of namespace GUI
diff --git a/gui/widgets/grid.cpp b/gui/widgets/grid.cpp
index e45beb9f328..a31efbe0837 100644
--- a/gui/widgets/grid.cpp
+++ b/gui/widgets/grid.cpp
@@ -344,14 +344,15 @@ void GridItemTray::handleMouseMoved(int x, int y, int button) {
 // Load an image file by String name, provide additional render dimensions for SVG images.
 // TODO: Add BMP support, and add scaling of non-vector images.
 Graphics::ManagedSurface *loadSurfaceFromFile(const Common::String &name, int renderWidth = 0, int renderHeight = 0) {
+	Common::Path path(name);
 	Graphics::ManagedSurface *surf = nullptr;
 	if (name.hasSuffix(".png")) {
 #ifdef USE_PNG
 		const Graphics::Surface *srcSurface = nullptr;
 		Image::PNGDecoder decoder;
 		g_gui.lockIconsSet();
-		if (g_gui.getIconsSet().hasFile(name)) {
-			Common::SeekableReadStream *stream = g_gui.getIconsSet().createReadStreamForMember(name);
+		if (g_gui.getIconsSet().hasFile(path)) {
+			Common::SeekableReadStream *stream = g_gui.getIconsSet().createReadStreamForMember(path);
 			if (!decoder.loadStream(*stream)) {
 				g_gui.unlockIconsSet();
 				warning("Error decoding PNG");
@@ -374,8 +375,8 @@ Graphics::ManagedSurface *loadSurfaceFromFile(const Common::String &name, int re
 #endif
 	} else if (name.hasSuffix(".svg")) {
 		g_gui.lockIconsSet();
-		if (g_gui.getIconsSet().hasFile(name)) {
-			Common::SeekableReadStream *stream = g_gui.getIconsSet().createReadStreamForMember(name);
+		if (g_gui.getIconsSet().hasFile(path)) {
+			Common::SeekableReadStream *stream = g_gui.getIconsSet().createReadStreamForMember(path);
 			surf = new Graphics::SVGBitmap(stream, renderWidth, renderHeight);
 			delete stream;
 		} else {
diff --git a/gui/widgets/richtext.h b/gui/widgets/richtext.h
index 6a3888f7301..e7f2429375d 100644
--- a/gui/widgets/richtext.h
+++ b/gui/widgets/richtext.h
@@ -51,7 +51,7 @@ protected:
 	int _textWidth;
 	int _textHeight;
 
-	Common::String _imageArchive;
+	Common::Path _imageArchive;
 
 public:
 	RichTextWidget(GuiObject *boss, int x, int y, int w, int h, bool scale, const Common::U32String &text, const Common::U32String &tooltip = Common::U32String());
@@ -74,7 +74,7 @@ public:
 
 	bool containsWidget(Widget *) const override;
 
-	void setImageArchive(Common::String fname) { _imageArchive = fname; }
+	void setImageArchive(const Common::Path &fname) { _imageArchive = fname; }
 
 protected:
 	void init();


Commit: 04d68d87c01452086b290f40c03261b605f7e13f
    https://github.com/scummvm/scummvm/commit/04d68d87c01452086b290f40c03261b605f7e13f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BASE: Migrate to Path class

Changed paths:
    base/commandLine.cpp
    base/main.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index fa663ed2e6c..6d50eb61294 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -1489,7 +1489,7 @@ static DetectedGames recListGames(const Common::FSNode &dir, const Common::Strin
 }
 
 /** Display all games in the given directory, return ID of first detected game */
-static Common::String detectGames(const Common::String &path, const Common::String &engineId, const Common::String &gameId, bool recursive) {
+static Common::String detectGames(const Common::Path &path, const Common::String &engineId, const Common::String &gameId, bool recursive) {
 	bool noPath = path.empty();
 	//Current directory
 	Common::FSNode dir(path);
@@ -1633,7 +1633,7 @@ static void calcMD5Mac(Common::Path &filePath, int32 length) {
 	}
 }
 
-static bool addGames(const Common::String &path, const Common::String &engineId, const Common::String &gameId, bool recursive) {
+static bool addGames(const Common::Path &path, const Common::String &engineId, const Common::String &gameId, bool recursive) {
 	//Current directory
 	Common::FSNode dir(path);
 	int added = recAddGames(dir, engineId, gameId, recursive);
@@ -1971,17 +1971,20 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 			// From an UX point of view, however, it might get confusing.
 			// Consider removing this if consensus says otherwise.
 		} else {
-			command = detectGames(settings["path"], gameOption.engineId, gameOption.gameId, resursive);
+			Common::Path path(settings["path"], Common::Path::kNativeSeparator);
+			command = detectGames(path, gameOption.engineId, gameOption.gameId, resursive);
 			if (command.empty()) {
 				err = Common::kNoGameDataFoundError;
 				return cmdDoExit;
 			}
 		}
 	} else if (command == "detect") {
-		detectGames(settings["path"], gameOption.engineId, gameOption.gameId, settings["recursive"] == "true");
+		Common::Path path(settings["path"], Common::Path::kNativeSeparator);
+		detectGames(path, gameOption.engineId, gameOption.gameId, settings["recursive"] == "true");
 		return cmdDoExit;
 	} else if (command == "add") {
-		addGames(settings["path"], gameOption.engineId, gameOption.gameId, settings["recursive"] == "true");
+		Common::Path path(settings["path"], Common::Path::kNativeSeparator);
+		addGames(path, gameOption.engineId, gameOption.gameId, settings["recursive"] == "true");
 		return cmdDoExit;
 	} else if (command == "md5" || command == "md5mac") {
 		Common::String filename = settings.getValOrDefault("md5-path", "scummvm");
diff --git a/base/main.cpp b/base/main.cpp
index fd5cc35504f..f70085737e5 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -467,13 +467,14 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 	}
 
 	// Load the config file (possibly overridden via command line):
-	Common::String initConfigFilename;
+	Common::Path initConfigFilename;
 	if (settings.contains("initial-cfg"))
-		initConfigFilename = settings["initial-cfg"];
+		initConfigFilename = Common::Path(settings["initial-cfg"], Common::Path::kNativeSeparator);
 
 	bool configLoadStatus;
 	if (settings.contains("config")) {
-		configLoadStatus = ConfMan.loadConfigFile(settings["config"], initConfigFilename);
+		configLoadStatus = ConfMan.loadConfigFile(
+			Common::Path(settings["config"], Common::Path::kNativeSeparator), initConfigFilename);
 	} else {
 		configLoadStatus = ConfMan.loadDefaultConfigFile(initConfigFilename);
 	}


Commit: 9bdf1233b11b7183a35a3df21e3605c5a0ebc8c8
    https://github.com/scummvm/scummvm/commit/9bdf1233b11b7183a35a3df21e3605c5a0ebc8c8
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
BACKENDS: Migrate to Path API

Changed paths:
    backends/dialogs/macosx/macosx-dialogs.mm
    backends/platform/android/asset-archive.cpp
    backends/platform/psp/image_viewer.cpp
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/posix/posix.cpp
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/win32/win32.cpp


diff --git a/backends/dialogs/macosx/macosx-dialogs.mm b/backends/dialogs/macosx/macosx-dialogs.mm
index 14336c244f4..a6244eab0a2 100644
--- a/backends/dialogs/macosx/macosx-dialogs.mm
+++ b/backends/dialogs/macosx/macosx-dialogs.mm
@@ -163,7 +163,7 @@ Common::DialogManager::DialogResult MacOSXDialogManager::showFileBrowser(const C
 	BrowserDialogPresenter* presenter = [[BrowserDialogPresenter alloc] init];
 	[presenter performSelectorOnMainThread:@selector(showOpenPanel:) withObject:panel waitUntilDone:YES];
 	if (presenter->_url) {
-		Common::String filename = [[presenter->_url path] UTF8String];
+		Common::Path filename([[presenter->_url path] UTF8String]);
 		choice = Common::FSNode(filename);
 		result = kDialogOk;
 	}
diff --git a/backends/platform/android/asset-archive.cpp b/backends/platform/android/asset-archive.cpp
index f8cb01499b0..e7b929ecd0f 100644
--- a/backends/platform/android/asset-archive.cpp
+++ b/backends/platform/android/asset-archive.cpp
@@ -39,7 +39,7 @@
 
 class AssetInputStream : public Common::SeekableReadStream {
 public:
-	AssetInputStream(AAssetManager *as, const Common::String &path);
+	AssetInputStream(AAssetManager *as, const Common::Path &path);
 	virtual ~AssetInputStream();
 
 	virtual bool eos() const { return _eos; }
@@ -63,9 +63,9 @@ private:
 	bool _eos;
 };
 
-AssetInputStream::AssetInputStream(AAssetManager *as, const Common::String &path) :
+AssetInputStream::AssetInputStream(AAssetManager *as, const Common::Path &path) :
 	_eos(false), _pos(0) {
-	_asset = AAssetManager_open(as, path.c_str(), AASSET_MODE_RANDOM);
+	_asset = AAssetManager_open(as, path.toString(Common::Path::kNativeSeparator).c_str(), AASSET_MODE_RANDOM);
 	_len = AAsset_getLength64(_asset);
 }
 
@@ -115,7 +115,7 @@ AndroidAssetArchive::~AndroidAssetArchive() {
 }
 
 bool AndroidAssetArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
+	Common::String name = path.toString(Common::Path::kNativeSeparator);
 	AAsset *asset = AAssetManager_open(_am, name.c_str(), AASSET_MODE_RANDOM);
 	bool exists = false;
 	if (asset != NULL) {
@@ -132,14 +132,14 @@ int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) con
 	}
 
 	int count = 0;
-	Common::List<Common::String> dirs;
+	Common::List<Common::Path> dirs;
 	dirs.push_back("");
 	for (const auto& currentDir : dirs) {
 		AAssetDir *dir = AAssetManager_openDir(_am, "");
 		const char *file = AAssetDir_getNextFileName(dir);
 
 		while (file) {
-			member_list.push_back(getMember(currentDir + Common::String(file)));
+			member_list.push_back(getMember(currentDir.appendComponent(file)));
 			++count;
 			file = AAssetDir_getNextFileName(dir);
 		}
@@ -160,7 +160,7 @@ Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const
 	if (!hasFile(path)) {
 		return nullptr;
 	}
-	return new AssetInputStream(_am, path.toString());
+	return new AssetInputStream(_am, path);
 }
 
 #endif
diff --git a/backends/platform/psp/image_viewer.cpp b/backends/platform/psp/image_viewer.cpp
index 9a2e8ddcb24..f9da713a041 100644
--- a/backends/platform/psp/image_viewer.cpp
+++ b/backends/platform/psp/image_viewer.cpp
@@ -46,14 +46,11 @@ bool ImageViewer::load(int imageNum) {
 		unload();
 
 	// build string
-	char number[8];
-	Common::sprintf_s(number, "%d", imageNum);
-	Common::String imageNameStr(imageName);
-	Common::String specificImageName = imageNameStr + Common::String(number) + Common::String(".png");
+	Common::Path specificImageName(Common::String::format("%s%d.png",imageName, imageNum));
 
 	// search for image file
 	if (!SearchMan.hasFile(specificImageName)) {
-		PSP_ERROR("file %s not found\n", specificImageName.c_str());
+		PSP_ERROR("file %s not found\n", specificImageName.toString(Common::Path::kNativeSeparator).c_str());
 		return false;
 	}
 
@@ -74,19 +71,19 @@ bool ImageViewer::load(int imageNum) {
 
 	char error[100];
 	if (status == PngLoader::BAD_FILE) {
-		Common::sprintf_s(error, "Cannot display %s. Not a proper PNG file", specificImageName.c_str());
+		Common::sprintf_s(error, "Cannot display %s. Not a proper PNG file", specificImageName.toString(Common::Path::kNativeSeparator).c_str());
 		GUI::TimedMessageDialog dialog(Common::U32String(error), 4000);
 		dialog.runModal();
 		return false;
 	} else if (status == PngLoader::OUT_OF_MEMORY) {
-		Common::sprintf_s(error, "Out of memory loading %s. Try making the image smaller", specificImageName.c_str());
+		Common::sprintf_s(error, "Out of memory loading %s. Try making the image smaller", specificImageName.toString(Common::Path::kNativeSeparator).c_str());
 		GUI::TimedMessageDialog dialog(Common::U32String(error), 4000);
 		dialog.runModal();
 		return false;
 	}
 	// try to load the image file
 	if (!image.load()) {
-		Common::sprintf_s(error, "Cannot display %s. Not a proper PNG file", specificImageName.c_str());
+		Common::sprintf_s(error, "Cannot display %s. Not a proper PNG file", specificImageName.toString(Common::Path::kNativeSeparator).c_str());
 		GUI::TimedMessageDialog dialog(Common::U32String(error), 4000);
 		dialog.runModal();
 		return false;
diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index 689cbeb6736..67f7bb5b1d2 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -132,7 +132,7 @@ void OSystem_MacOSX::addSysArchivesToSearchSet(Common::SearchSet &s, int priorit
 	OSystem_POSIX::addSysArchivesToSearchSet(s, priority);
 
 	// Get URL of the Resource directory of the .app bundle
-	Common::String bundlePath = getResourceAppBundlePathMacOSX();
+	Common::Path bundlePath(getResourceAppBundlePathMacOSX(), Common::Path::kNativeSeparator);
 	if (!bundlePath.empty()) {
 		// Success: search with a depth of 2 so the shaders are found
 		s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath, 2), priority);
@@ -265,7 +265,7 @@ Common::Path OSystem_MacOSX::getDefaultIconsPath() {
 Common::Path OSystem_MacOSX::getDefaultDLCsPath() {
 	const Common::Path defaultDLCsPath(getAppSupportPathMacOSX() + "/DLCs");
 
-	if (!Posix::assureDirectoryExists(defaultDLCsPath.toString())) {
+	if (!Posix::assureDirectoryExists(defaultDLCsPath.toString(Common::Path::kNativeSeparator))) {
 		return Common::Path();
 	}
 
diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index b79d2837a59..b55a76eb444 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -129,7 +129,7 @@ Common::Path OSystem_POSIX::getDefaultConfigFileName() {
 		if (configFile.size() < MAXPATHLEN) {
 			struct stat sb;
 			if (stat(configFile.c_str(), &sb) == 0) {
-				return configFile;
+				return Common::Path(configFile, '/');
 			}
 		}
 	}
@@ -164,7 +164,7 @@ Common::Path OSystem_POSIX::getDefaultConfigFileName() {
 		configFile = baseConfigName;
 	}
 
-	return configFile;
+	return Common::Path(configFile, '/');
 }
 
 Common::String OSystem_POSIX::getXdgUserDir(const char *name) {
@@ -182,7 +182,7 @@ Common::String OSystem_POSIX::getXdgUserDir(const char *name) {
 
 	// Find the requested directory line in the xdg-user-dirs configuration file
 	//   Example line value: XDG_PICTURES_DIR="$HOME/Pictures"
-	Common::FSNode userDirsFile(configHome + "/user-dirs.dirs");
+	Common::FSNode userDirsFile(Common::Path(configHome + "/user-dirs.dirs", '/'));
 	if (!userDirsFile.exists() || !userDirsFile.isReadable() || userDirsFile.isDirectory()) {
 		return "";
 	}
@@ -245,7 +245,7 @@ Common::Path OSystem_POSIX::getDefaultIconsPath() {
 	if (prefix == nullptr || !*prefix) {
 		prefix = getenv("HOME");
 		if (prefix == nullptr) {
-			return Common::String();
+			return Common::Path();
 		}
 
 		iconsPath = ".cache/";
@@ -254,14 +254,14 @@ Common::Path OSystem_POSIX::getDefaultIconsPath() {
 	iconsPath += "scummvm/icons";
 
 	if (!Posix::assureDirectoryExists(iconsPath, prefix)) {
-		return Common::String();
+		return Common::Path();
 	}
 
 	return Common::Path(prefix).join(iconsPath);
 }
 
 Common::Path OSystem_POSIX::getDefaultDLCsPath() {
-	Common::Path dlcsPath;
+	Common::String dlcsPath;
 
 	// On POSIX systems we follow the XDG Base Directory Specification for
 	// where to store files. The version we based our code upon can be found
@@ -270,17 +270,19 @@ Common::Path OSystem_POSIX::getDefaultDLCsPath() {
 	if (prefix == nullptr || !*prefix) {
 		prefix = getenv("HOME");
 		if (prefix == nullptr) {
-			return Common::String();
+			return Common::Path();
 		}
 
 		dlcsPath = ".cache/";
 	}
-	dlcsPath = dlcsPath.join(Common::Path("scummvm/dlcs"));
-	if (!Posix::assureDirectoryExists(dlcsPath.toString(), prefix)) {
+
+	dlcsPath += "scummvm/dlcs";
+
+	if (!Posix::assureDirectoryExists(dlcsPath, prefix)) {
 		return Common::Path();
 	}
 
-	return dlcsPath;
+	return Common::Path(prefix).join(dlcsPath);
 }
 
 Common::Path OSystem_POSIX::getScreenshotsPath() {
@@ -345,7 +347,7 @@ Common::Path OSystem_POSIX::getDefaultLogFileName() {
 	if (prefix == nullptr || !*prefix) {
 		prefix = getenv("HOME");
 		if (prefix == nullptr) {
-			return Common::String();
+			return Common::Path();
 		}
 
 		logFile = ".cache/";
@@ -354,7 +356,7 @@ Common::Path OSystem_POSIX::getDefaultLogFileName() {
 	logFile += "scummvm/logs";
 
 	if (!Posix::assureDirectoryExists(logFile, prefix)) {
-		return Common::String();
+		return Common::Path();
 	}
 
 	Common::Path logPath(prefix);
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 674e22ecc06..a9ebb363b97 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -332,7 +332,7 @@ void OSystem_SDL::initBackend() {
 #endif
 
 	ConfMan.registerDefault("iconspath", this->getDefaultIconsPath());
-	ConfMan.registerDefault("dlcspath", this->getDefaultDLCsPath().toString());
+	ConfMan.registerDefault("dlcspath", this->getDefaultDLCsPath());
 
 	_inited = true;
 
diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp
index e3cd617fd36..607d015f6aa 100644
--- a/backends/platform/sdl/win32/win32.cpp
+++ b/backends/platform/sdl/win32/win32.cpp
@@ -438,7 +438,7 @@ public:
 	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
 	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
 private:
-	typedef Common::List<Common::String> FilenameList;
+	typedef Common::List<Common::Path> FilenameList;
 
 	FilenameList _files;
 };
@@ -449,7 +449,8 @@ BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName
 
 	Win32ResourceArchive *arch = (Win32ResourceArchive *)lParam;
 	Common::String filename = Win32::tcharToString(lpszName);
-	arch->_files.push_back(filename);
+	// We use / as path separator in resources
+	arch->_files.push_back(Common::Path(filename, '/'));
 	return TRUE;
 }
 
@@ -458,9 +459,8 @@ Win32ResourceArchive::Win32ResourceArchive() {
 }
 
 bool Win32ResourceArchive::hasFile(const Common::Path &path) const {
-	Common::String name = path.toString();
 	for (FilenameList::const_iterator i = _files.begin(); i != _files.end(); ++i) {
-		if (i->equalsIgnoreCase(name))
+		if (i->equalsIgnoreCase(path))
 			return true;
 	}
 
@@ -481,7 +481,8 @@ const Common::ArchiveMemberPtr Win32ResourceArchive::getMember(const Common::Pat
 }
 
 Common::SeekableReadStream *Win32ResourceArchive::createReadStreamForMember(const Common::Path &path) const {
-	Common::String name = path.toString();
+	// We store paths in resources using / separator
+	Common::String name = path.toString('/');
 	TCHAR *tName = Win32::stringToTchar(name);
 	HRSRC resource = FindResource(nullptr, tName, MAKEINTRESOURCE(256));
 	free(tName);


Commit: 431af3e37dd921e318330e45b24f5524f9c4598f
    https://github.com/scummvm/scummvm/commit/431af3e37dd921e318330e45b24f5524f9c4598f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Delete getPath compatibility shim

It's not needed anymore

Changed paths:
    backends/platform/sdl/posix/posix.cpp
    common/fs.cpp
    common/fs.h


diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp
index b55a76eb444..2d464c52931 100644
--- a/backends/platform/sdl/posix/posix.cpp
+++ b/backends/platform/sdl/posix/posix.cpp
@@ -328,7 +328,7 @@ void OSystem_POSIX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority
 		if (dataNode.exists() && dataNode.isDirectory()) {
 			// This is the same priority which is used for the data path (below),
 			// but we insert this one first, so it will be searched first.
-			s.add(dataNode.getPath(), new Common::FSDirectory(dataNode, 4), priority);
+			s.addDirectory(dataNode, priority, 4);
 		}
 	}
 #endif
diff --git a/common/fs.cpp b/common/fs.cpp
index 843db5c6110..87876adc429 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -203,9 +203,9 @@ FSNode FSNode::getParent() const {
 	}
 }
 
-PathProxy FSNode::getPath() const {
+Path FSNode::getPath() const {
 	assert(_realNode);
-	return PathProxy(_realNode->getPath(), Common::Path::kNativeSeparator);
+	return Path(_realNode->getPath(), Common::Path::kNativeSeparator);
 }
 
 bool FSNode::isDirectory() const {
diff --git a/common/fs.h b/common/fs.h
index ec282731e09..0c999725430 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -49,31 +49,6 @@ class SeekableReadStream;
 class WriteStream;
 class SeekableWriteStream;
 
-/**
- * A minimal and temporary class which can act like a Path and like a String
- * This is used to ease transition of getPath() from String to Path
- * FIXME: Remove this class when it's not needed anymore
- */
-class PathProxy : public Path {
-private:
-	String str() const { return toString(Path::kNativeSeparator); }
-public:
-	using Path::Path;
-
-	operator String() const { return str(); };
-	operator U32String() const { return decode(); }
-
-	const char *c_str() const { return str().c_str(); }
-	U32String decode(CodePage page = kUtf8) const { return str().decode(page); }
-	bool matchString(const char *pat, bool ignoreCase = false, const char *wildcardExclusions = NULL) const {
-		return str().matchString(pat, ignoreCase, wildcardExclusions);
-	}
-
-	String substr(size_t pos = 0, size_t len = String::npos) const {
-		return str().substr(pos, len);
-	}
-};
-
 /**
  * List of multiple file system nodes. For example, the contents of a given directory.
  * This is a subclass instead of just a typedef so that forward declarations
@@ -226,7 +201,7 @@ public:
 	 *
 	 * @return The 'path' represented by this file system node.
 	 */
-	PathProxy getPath() const;
+	Path getPath() const;
 
 	/**
 	 * Get the parent node of this node. If this node has no parent node,


Commit: c2bbb608cdf86261f24aa21eba205e8b3281a9c3
    https://github.com/scummvm/scummvm/commit/c2bbb608cdf86261f24aa21eba205e8b3281a9c3
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-12-24T13:19:25+01:00

Commit Message:
COMMON: Make String to Path conversion explicit

This will make sure engines use Path where appropriate.

Changed paths:
    common/path.h


diff --git a/common/path.h b/common/path.h
index b5b095731ac..7002656ad1e 100644
--- a/common/path.h
+++ b/common/path.h
@@ -256,13 +256,14 @@ public:
 
 	/**
 	 * Construct a new path from the given String.
+	 * This is explicit to limit mixing strings and paths in the codebase.
 	 *
 	 * @param str       A String representing a path, e.g. "foo/bar/baz"
 	 * @param separator The directory separator used in the path string.
 	 *                  Use kNoSeparator if there is no separator.
 	 *                  Defaults to '/'.
 	 */
-	Path(const String &str, char separator = '/') :
+	explicit Path(const String &str, char separator = '/') :
 		_str(needsEncoding(str.c_str(), separator) ? encode(str.c_str(), separator) : str) { }
 
 	/**




More information about the Scummvm-git-logs mailing list