[Scummvm-git-logs] scummvm master -> 0cc45aabf83754db24f46835ecb9997527ac7125
sev-
noreply at scummvm.org
Sat Jan 11 13:21:07 UTC 2025
This automated email contains information about 19 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
78859312f8 COMMON: Make Archive listable
3c0a1312a0 COMMON: Allow specifying XMLParser stream name
d31e9e97bb COMMON: Add PS3 and Nintendo Switch Platforms
4ebf8329ee TETRAEDGE: Add detection entries for Android and Nintendo Switch releases
42cfbdac2e TETRAEDGE: Support rippletexture tag
f8be466549 TETRAEDGE: Declare platforms other than OSX
695d99e906 TETRAEDGE: Add Nintendo Switch Lua bind
bd80dd012a TETRAEDGE: Tolerate missing images on non-Amerzone
4e1cb6d624 TETRAEDGE: Extend filters to include PS3-named scripts
17d76a9721 TETRAEDGE: Introduce TetraedgeFSNode to refer inside archives
440cda29a4 TETRAEDGE: Mark Android as using UTF-8
56d21368bd TETRAEDGE: Support animations in animcached directory
c5b04b43a2 TETRAEDGE: workaround invalid XML in Nintendo Switch release
0fd5bc2090 TETRAEDGE: Mark Russian as available on Syberia2
8763d4383b TETRAEDGE: Support accessing files inside Android OBB archive
22666274a4 TETRAEDGE: Skip pausable attribute
d3e1834e96 TETRAEDGE: Fallback to English if selected language is not available
ede5b4b77e TETRAEDGE: Support UTF-8 Switch releases
0cc45aabf8 TETRAEDGE: Declare Polish and Japanese translations
Commit: 78859312f8e2d70002abe1001f10dbe99f6209f0
https://github.com/scummvm/scummvm/commit/78859312f8e2d70002abe1001f10dbe99f6209f0
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
COMMON: Make Archive listable
This allows efficient listing of files in a subdir even if archive has
a large amount of unrelated files.
Changed paths:
common/archive.cpp
common/archive.h
common/fs.cpp
common/fs.h
diff --git a/common/archive.cpp b/common/archive.cpp
index 0c74d3b809c..db488ddb50a 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -90,7 +90,9 @@ void GenericArchiveMember::listChildren(ArchiveMemberList &childList, const char
}
bool Archive::isPathDirectory(const Path &path) const {
- return false;
+ prepareMaps();
+ Common::Path pathNorm = path.normalize();
+ return _directoryMap.contains(pathNorm) || _fileMap.contains(pathNorm);
}
int Archive::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, bool matchPathComponents) const {
@@ -176,6 +178,60 @@ char Archive::getPathSeparator() const {
return '/';
}
+bool Archive::getChildren(const Common::Path &path, Common::Array<Common::String> &list, ListMode mode, bool hidden) const {
+ list.clear();
+ prepareMaps();
+ Common::Path pathNorm = path.normalize();
+ if (!_fileMap.contains(pathNorm) && !_directoryMap.contains(pathNorm))
+ return false;
+ if (mode == kListDirectoriesOnly || mode == kListAll)
+ for (SubfileSet::iterator its = _directoryMap[pathNorm].begin(); its != _directoryMap[pathNorm].end(); its++)
+ if (hidden || its->_key.firstChar() != '.')
+ list.push_back(its->_key);
+ if (mode == kListFilesOnly || mode == kListAll)
+ for (SubfileSet::iterator its = _fileMap[pathNorm].begin(); its != _fileMap[pathNorm].end(); its++)
+ if (hidden || its->_key.firstChar() != '.')
+ list.push_back(its->_key);
+ return true;
+}
+
+void Archive::prepareMaps() const {
+ if (_mapsAreReady)
+ return;
+
+ /* In order to avoid call-loop we need to set this variable before calling isDirectory on any members as the
+ default implementation uses maps.
+ */
+ _mapsAreReady = true;
+
+ ArchiveMemberList list;
+ listMembers(list);
+
+ for (ArchiveMemberList::iterator it = list.begin(); it != list.end(); it++) {
+ Common::Path cur = (*it)->getPathInArchive().normalize();
+ if (!(*it)->isDirectory()) {
+ Common::Path parent = cur.getParent().normalize();
+ Common::String fname = cur.baseName();
+ _fileMap[parent][fname] = true;
+ cur = parent;
+ }
+
+ while (!cur.empty()) {
+ Common::Path parent = cur.getParent().normalize();
+ Common::String dname = cur.baseName();
+ _directoryMap[parent][dname] = true;
+ cur = parent;
+ }
+ }
+
+ for (AllfileMap::iterator itd = _directoryMap.begin();
+ itd != _directoryMap.end(); itd++) {
+ for (SubfileSet::iterator its = itd->_value.begin(); its != itd->_value.end(); its++) {
+ _fileMap[itd->_key].erase(its->_key);
+ }
+ }
+}
+
SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMember(const Path &path) const {
return createReadStreamForMemberImpl(path, false, Common::AltStreamType::Invalid);
}
@@ -451,6 +507,21 @@ bool SearchSet::isPathDirectory(const Path &path) const {
return false;
}
+bool SearchSet::getChildren(const Common::Path &path, Common::Array<Common::String> &list, ListMode mode, bool hidden) const {
+ bool hasAny = false;
+ ArchiveNodeList::const_iterator it = _list.begin();
+ list.clear();
+ for (; it != _list.end(); ++it) {
+ Common::Array<Common::String> tmpList;
+ if (it->_arc->getChildren(path, tmpList, mode, hidden)) {
+ list.push_back(tmpList);
+ hasAny = true;
+ }
+ }
+
+ return hasAny;
+}
+
int SearchSet::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, bool matchPathComponents) const {
int matches = 0;
diff --git a/common/archive.h b/common/archive.h
index f46686e545b..c479b10ccf8 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -140,6 +140,8 @@ private:
*/
class Archive {
public:
+ Archive() : _mapsAreReady(false) { }
+
virtual ~Archive() { }
/**
@@ -211,6 +213,22 @@ public:
* Returns the separator used by internal paths in the archive
*/
virtual char getPathSeparator() const;
+
+ enum ListMode {
+ kListFilesOnly = 1,
+ kListDirectoriesOnly = 2,
+ kListAll = 3
+ };
+
+ virtual bool getChildren(const Common::Path &path, Common::Array<Common::String> &list, ListMode mode = kListDirectoriesOnly, bool hidden = true) const;
+
+private:
+ void prepareMaps() const;
+
+ mutable bool _mapsAreReady;
+ typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> SubfileSet;
+ typedef HashMap<Path, SubfileSet, Path::IgnoreCase_Hash, Path::IgnoreCase_EqualTo> AllfileMap;
+ mutable AllfileMap _directoryMap, _fileMap;
};
class MemcachingCaseInsensitiveArchive;
@@ -299,6 +317,7 @@ private:
mutable HashMap<CacheKey, SharedArchiveContents, CacheKey_Hash, CacheKey_EqualTo> _cache;
uint32 _maxStronglyCachedSize;
+ char _separator;
};
/**
@@ -333,6 +352,8 @@ public:
SearchSet() : _ignoreClashes(false) { }
virtual ~SearchSet() { clear(); }
+ char getPathSeparator() const override { return '/'; }
+
/**
* Add a new archive to the searchable set.
*/
@@ -455,6 +476,8 @@ public:
* in @ref FSDirectory documentation.
*/
void setIgnoreClashes(bool ignoreClashes) { _ignoreClashes = ignoreClashes; }
+
+ bool getChildren(const Common::Path &path, Common::Array<Common::String> &list, ListMode mode = kListDirectoriesOnly, bool hidden = true) const override;
};
diff --git a/common/fs.cpp b/common/fs.cpp
index 5cf79e1c172..c8360bec17a 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -450,6 +450,7 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const Path& pr
}
cacheDirectoryRecursive(*it, depth - 1, _flat ? prefix : name);
_subDirCache[name] = *it;
+ _dirMapCache[prefix].push_back(it->getRealName());
}
} else {
if (_fileCache.contains(name)) {
@@ -457,8 +458,10 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const Path& pr
warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'",
Common::toPrintable(name.toString(Common::Path::kNativeSeparator)).c_str());
}
- } else
+ } else {
_fileCache[name] = *it;
+ _fileMapCache[prefix].push_back(it->getRealName());
+ }
}
}
@@ -471,6 +474,38 @@ void FSDirectory::ensureCached() const {
_cached = true;
}
+bool FSDirectory::getChildren(const Common::Path &path, Common::Array<Common::String> &list, ListMode mode, bool hidden) const {
+ if (!_node.isDirectory())
+ return 0;
+
+ // Cache dir data
+ ensureCached();
+
+ Common::Path pathNormalized = path.normalize();
+
+ int matches = 0;
+
+ if (mode == kListDirectoriesOnly || mode == kListAll) {
+ for (Array<String>::const_iterator it = _dirMapCache[pathNormalized].begin(); it != _dirMapCache[pathNormalized].end(); ++it) {
+ if (hidden || it->firstChar() != '.') {
+ list.push_back(*it);
+ matches++;
+ }
+ }
+ }
+
+ if (mode == kListFilesOnly || mode == kListAll) {
+ for (Array<String>::const_iterator it = _fileMapCache[pathNormalized].begin(); it != _fileMapCache[pathNormalized].end(); ++it) {
+ if (hidden || it->firstChar() != '.') {
+ list.push_back(*it);
+ matches++;
+ }
+ }
+ }
+
+ return matches;
+}
+
int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const Path &pattern, bool matchPathComponents) const {
if (!_node.isDirectory())
return 0;
diff --git a/common/fs.h b/common/fs.h
index b5c6f8d95a8..70081d8f0f7 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -351,7 +351,9 @@ 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_EqualTo> NodeCache;
+ typedef HashMap<Path, Array<String>, Path::IgnoreCaseAndMac_Hash, Path::IgnoreCaseAndMac_EqualTo> NodeMapCache;
mutable NodeCache _fileCache, _subDirCache;
+ mutable NodeMapCache _fileMapCache, _dirMapCache;
mutable bool _cached;
// look for a match
@@ -443,6 +445,8 @@ public:
*/
SeekableReadStream *createReadStreamForMember(const Path &path) const override;
+ bool getChildren(const Common::Path &path, Common::Array<Common::String> &list, ListMode mode = kListDirectoriesOnly, bool hidden = true) const override;
+
/**
* Open an alternate stream for a specified file. A full match of relative path and file name is needed
* for success.
Commit: 3c0a1312a0531bab9469f80a76f88fd9e1794891
https://github.com/scummvm/scummvm/commit/3c0a1312a0531bab9469f80a76f88fd9e1794891
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
COMMON: Allow specifying XMLParser stream name
Changed paths:
common/formats/xmlparser.cpp
common/formats/xmlparser.h
diff --git a/common/formats/xmlparser.cpp b/common/formats/xmlparser.cpp
index 22a25764e39..3cca5a4ef76 100644
--- a/common/formats/xmlparser.cpp
+++ b/common/formats/xmlparser.cpp
@@ -65,9 +65,9 @@ bool XMLParser::loadBuffer(const byte *buffer, uint32 size, DisposeAfterUse::Fla
return true;
}
-bool XMLParser::loadStream(SeekableReadStream *stream) {
+bool XMLParser::loadStream(SeekableReadStream *stream, const String &name) {
_stream = stream;
- _fileName = "File Stream";
+ _fileName = name;
return _stream != nullptr;
}
diff --git a/common/formats/xmlparser.h b/common/formats/xmlparser.h
index db68719145f..5676b231560 100644
--- a/common/formats/xmlparser.h
+++ b/common/formats/xmlparser.h
@@ -185,7 +185,7 @@ public:
*/
bool loadBuffer(const byte *buffer, uint32 size, DisposeAfterUse::Flag disposable = DisposeAfterUse::NO);
- bool loadStream(SeekableReadStream *stream);
+ bool loadStream(SeekableReadStream *stream, const String &name = "File Stream");
void close();
Commit: d31e9e97bb2e53972004e892cedc1233bfaf5115
https://github.com/scummvm/scummvm/commit/d31e9e97bb2e53972004e892cedc1233bfaf5115
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
COMMON: Add PS3 and Nintendo Switch Platforms
Changed paths:
common/platform.cpp
common/platform.h
diff --git a/common/platform.cpp b/common/platform.cpp
index 157b05c5835..1741dfba8b0 100644
--- a/common/platform.cpp
+++ b/common/platform.cpp
@@ -54,6 +54,7 @@ const PlatformDescription g_platforms[] = {
{ "windows", "win", "win", "Windows", kPlatformWindows },
{ "playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX },
{ "playstation2", "ps2", "ps2", "Sony PlayStation 2", kPlatformPS2 },
+ { "playstation3", "ps3", "ps3", "Sony PlayStation 3", kPlatformPS3 },
{ "xbox", "xbox", "xbox", "Microsoft Xbox", kPlatformXbox },
{ "cdi", "cdi", "cdi", "Philips CD-i", kPlatformCDi },
{ "ios", "ios", "ios", "Apple iOS", kPlatformIOS },
@@ -68,6 +69,7 @@ const PlatformDescription g_platforms[] = {
{ "shockwave", "shockwave", "shock", "Shockwave", kPlatformShockwave },
{ "zx", "zx", "zx", "ZX Spectrum", kPlatformZX },
{ "ti994", "ti994", "ti994", "TI-99/4A", kPlatformTI994 },
+ { "switch", "switch", "switch", "Nintendo Switch", kPlatformNintendoSwitch },
{ nullptr, nullptr, nullptr, "Default", kPlatformUnknown }
};
diff --git a/common/platform.h b/common/platform.h
index 54f159f1b7e..7b2b07b2016 100644
--- a/common/platform.h
+++ b/common/platform.h
@@ -67,6 +67,7 @@ enum Platform : int8 {
kPlatformWii,
kPlatformPSX,
kPlatformPS2,
+ kPlatformPS3,
kPlatformXbox,
kPlatformCDi,
kPlatformIOS,
@@ -81,6 +82,7 @@ enum Platform : int8 {
kPlatformShockwave,
kPlatformZX,
kPlatformTI994,
+ kPlatformNintendoSwitch,
kPlatformUnknown = -1
};
Commit: 4ebf8329eeb084a500b6b0c265434375902b4658
https://github.com/scummvm/scummvm/commit/4ebf8329eeb084a500b6b0c265434375902b4658
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Add detection entries for Android and Nintendo Switch releases
Changed paths:
engines/tetraedge/detection_tables.h
diff --git a/engines/tetraedge/detection_tables.h b/engines/tetraedge/detection_tables.h
index 8442d8b92e3..4464ec7f81e 100644
--- a/engines/tetraedge/detection_tables.h
+++ b/engines/tetraedge/detection_tables.h
@@ -76,6 +76,153 @@ const ADGameDescription GAME_DESCRIPTIONS[] = {
GUIO2(GAMEOPTION_CORRECT_MOVIE_ASPECT, GAMEOPTION_RESTORE_SCENES)
},
+ // Nintendo Switch, from Syberia1-3 cartridge
+ {
+ "syberia",
+ nullptr,
+ AD_ENTRY1s("InGame.lua", "acaf61504a12aebf3862648e04cf29aa", 3920),
+ Common::UNK_LANG,
+ Common::kPlatformNintendoSwitch,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+ {
+ "syberia2",
+ nullptr,
+ AD_ENTRY2s("Debug.lua", "a2ea493892e96bea64013819195c081e", 7024,
+ "InGame.lua", "a7df110fe816cb342574150c6f992964", 4654),
+ Common::UNK_LANG,
+ Common::kPlatformNintendoSwitch,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ // Android v1.0.5
+ {
+ "syberia",
+ "Extracted",
+ AD_ENTRY1s("InGame.lua", "12ee6a8eade070b905136cd4cdfc3726", 4471),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ {
+ "syberia",
+ nullptr,
+ AD_ENTRY1s("main.12.com.microids.syberia.obb", "b82f9295c4bafe4af58450cbacfd261e", 1000659045),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ // Buka release v1.0.3
+ {
+ "syberia",
+ "Extracted",
+ AD_ENTRY1s("InGame.lua", "6577b0151ca4532e94a63a91c22a17c1", 2646),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+ {
+ "syberia",
+ nullptr,
+ AD_ENTRY1s("main.2.ru.buka.syberia1.obb", "7af875e74acfceee5d9b78c705da212e", 771058907),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ // v1.0.1
+ {
+ "syberia",
+ nullptr,
+ AD_ENTRY1s("main.5.com.microids.syberia.obb", "6a39b40edca885bb9508ec09675c1923", 1389534445),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+ {
+ "syberia",
+ "Extracted",
+ AD_ENTRY1s("InGame.lua", "8698770015e103725db60a65f3e21657", 2478),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ {
+ "syberia",
+ nullptr,
+ AD_ENTRY1s("InGame.data", "5cb78f2c8aac837fe53596ecfe921b38", 2195),
+ Common::UNK_LANG,
+ Common::kPlatformPS3,
+ ADGF_UNSUPPORTED,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ // v1.0.2 Buka release
+ {
+ "syberia2",
+ nullptr,
+ AD_ENTRY1s("main.2.ru.buka.syberia2.obb", "e9d8516610d33f375a3f6800232e3224", 1038859725),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+ {
+ "syberia2",
+ "Extracted",
+ AD_ENTRY2s("Debug.lua", "a2ea493892e96bea64013819195c081e", 7024,
+ "filelist.bin", "eb189789a74286c5023e102ec1c44fd4", 2099822),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ // v1.0.1 Android release
+ {
+ "syberia2",
+ nullptr,
+ AD_ENTRY1s("main.4.com.microids.syberia2.obb", "d8aa60562ffad83d3bcaa7b611fc4299", 1473221971),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+ {
+ "syberia2",
+ "Extracted",
+ AD_ENTRY2s("Debug.lua", "a2ea493892e96bea64013819195c081e", 7024,
+ "filelist.bin", "dc40f150ee291a30e0bc6cd8a0127aab", 2100007),
+ Common::UNK_LANG,
+ Common::kPlatformAndroid,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ // v1.0.0 iOS release
+ {
+ "syberia2",
+ nullptr,
+ AD_ENTRY2s("Debug.lua", "a2ea493892e96bea64013819195c081e", 7024,
+ "Info.plist", nullptr, (uint32_t)-1),
+ Common::UNK_LANG,
+ Common::kPlatformIOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+
// GOG release
{
"syberia2",
@@ -98,6 +245,16 @@ const ADGameDescription GAME_DESCRIPTIONS[] = {
GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
},
+ {
+ "syberia2",
+ nullptr,
+ AD_ENTRY1s("Debug.data", "d5cfcba9b725e746df39109e7e1b0564", 7024),
+ Common::UNK_LANG,
+ Common::kPlatformPS3,
+ ADGF_UNSUPPORTED,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
AD_TABLE_END_MARKER
};
Commit: 42cfbdac2e4949675bd83dd14a5b1cf07fddd967
https://github.com/scummvm/scummvm/commit/42cfbdac2e4949675bd83dd14a5b1cf07fddd967
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Support rippletexture tag
Changed paths:
engines/tetraedge/game/character_settings_xml_parser.cpp
engines/tetraedge/game/character_settings_xml_parser.h
diff --git a/engines/tetraedge/game/character_settings_xml_parser.cpp b/engines/tetraedge/game/character_settings_xml_parser.cpp
index 059bd659db6..3e96c5bf9cd 100644
--- a/engines/tetraedge/game/character_settings_xml_parser.cpp
+++ b/engines/tetraedge/game/character_settings_xml_parser.cpp
@@ -110,6 +110,11 @@ bool CharacterSettingsXmlParser::parserCallback_position(ParserNode *node) {
return true;
}
+bool CharacterSettingsXmlParser::parserCallback_rippleTexture(ParserNode *node) {
+ // Ignored
+ return true;
+}
+
bool CharacterSettingsXmlParser::parserCallback_face(ParserNode *node) {
// Handled in "face" and "eyes" callbacks.
return true;
diff --git a/engines/tetraedge/game/character_settings_xml_parser.h b/engines/tetraedge/game/character_settings_xml_parser.h
index 919135a8ea3..6b49b25f0a8 100644
--- a/engines/tetraedge/game/character_settings_xml_parser.h
+++ b/engines/tetraedge/game/character_settings_xml_parser.h
@@ -88,6 +88,9 @@ public:
XML_KEY(body)
XML_PROP(name, true)
KEY_END()
+ XML_KEY(rippleTexture)
+ XML_PROP(path, true)
+ KEY_END()
KEY_END()
KEY_END()
} PARSER_END()
@@ -112,6 +115,7 @@ public:
bool parserCallback_mouth(ParserNode *node);
bool parserCallback_body(ParserNode *node);
bool parserCallback_invertNormals(ParserNode *node);
+ bool parserCallback_rippleTexture(ParserNode *node);
bool textCallback(const Common::String &val) override;
bool handleUnknownKey(ParserNode *node) override;
Commit: f8be466549a18ee01660f65a9a67899ec24dca07
https://github.com/scummvm/scummvm/commit/f8be466549a18ee01660f65a9a67899ec24dca07
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Declare platforms other than OSX
Changed paths:
engines/tetraedge/game/application.cpp
diff --git a/engines/tetraedge/game/application.cpp b/engines/tetraedge/game/application.cpp
index 58ab79e1953..523277fa579 100644
--- a/engines/tetraedge/game/application.cpp
+++ b/engines/tetraedge/game/application.cpp
@@ -60,12 +60,35 @@ _permanentHelp(true), _musicOn(true) {
TeCore *core = g_engine->getCore();
core->_coreNotReady = true;
- core->fileFlagSystemSetFlag("platform", "MacOSX");
+ const char *platform = "";
+ switch (g_engine->getGamePlatform()) {
+ case Common::Platform::kPlatformAndroid:
+ platform = "Android";
+ core->fileFlagSystemSetFlag("pad", "padDisabled");
+ break;
+ case Common::Platform::kPlatformMacintosh:
+ platform = "MacOSX";
+ break;
+ case Common::Platform::kPlatformIOS:
+ platform = "iPhone";
+ break;
+ case Common::Platform::kPlatformNintendoSwitch:
+ platform = "NX";
+ core->fileFlagSystemSetFlag("pad", "padDisabled");
+ break;
+ case Common::Platform::kPlatformPS3:
+ platform = "PS3";
+ break;
+ default:
+ error("Unsupported platform");
+ }
+ core->fileFlagSystemSetFlag("platform", platform);
//
// WORKAROUND: Syberia 2 A5_ValDomaine/54000/Logic54000.lua
// checks a typo of this flag..
//
- core->fileFlagSystemSetFlag("plateform", "MacOSX");
+ core->fileFlagSystemSetFlag("plateform", platform);
+
core->fileFlagSystemSetFlag("part", "Full");
if (g_engine->isGameDemo())
core->fileFlagSystemSetFlag("distributor", "Freemium");
Commit: 695d99e9068f7fed824abf474c33161b5f3c64fa
https://github.com/scummvm/scummvm/commit/695d99e9068f7fed824abf474c33161b5f3c64fa
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Add Nintendo Switch Lua bind
Changed paths:
engines/tetraedge/game/lua_binds.cpp
diff --git a/engines/tetraedge/game/lua_binds.cpp b/engines/tetraedge/game/lua_binds.cpp
index f2516f0ef76..b3c3fa0952f 100644
--- a/engines/tetraedge/game/lua_binds.cpp
+++ b/engines/tetraedge/game/lua_binds.cpp
@@ -2651,6 +2651,12 @@ static int tolua_ExportedFunctions_PlayVerticalScrolling00(lua_State *L) {
error("#ferror in function 'SetObjectMoveTime': %d %d %s", err.index, err.array, err.type);
}
+static int tolua_ExportedFunctions_GetNXPadType(lua_State *L) {
+ // TODO: Actually implement this
+ tolua_pushstring(L, "Handheld");
+ return 1;
+}
+
// Not your imagination, the implementation of these two is quite different to the others.
static int tolua_GetParticleIndex(lua_State *L) {
Common::String s1(tolua_tostring(L, 1, nullptr));
@@ -2849,6 +2855,7 @@ static void LuaOpenBinds_Syberia(lua_State *L) {
tolua_function(L, "PlayVerticalScrolling", tolua_ExportedFunctions_PlayVerticalScrolling00);
tolua_function(L, "GetParticleIndex", tolua_GetParticleIndex);
tolua_function(L, "EnableParticle", tolua_EnableParticle);
+ tolua_function(L, "GetNXPadType", tolua_ExportedFunctions_GetNXPadType);
tolua_endmodule(L);
}
Commit: bd80dd012a30193941c1b30531995d5e77782ccd
https://github.com/scummvm/scummvm/commit/bd80dd012a30193941c1b30531995d5e77782ccd
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Tolerate missing images on non-Amerzone
Changed paths:
engines/tetraedge/game/notifier.cpp
diff --git a/engines/tetraedge/game/notifier.cpp b/engines/tetraedge/game/notifier.cpp
index 8b9dcb7ff71..a0a990f7e33 100644
--- a/engines/tetraedge/game/notifier.cpp
+++ b/engines/tetraedge/game/notifier.cpp
@@ -77,8 +77,8 @@ void Notifier::launchNextnotifier() {
colorAnim->_callbackObj = _gui.layoutChecked("sprite");
colorAnim->play();
- if (!g_engine->gameIsAmerzone()) {
- colorAnim = _gui.colorLinearAnimation("fadeInImage");
+ colorAnim = g_engine->gameIsAmerzone() ? nullptr : _gui.colorLinearAnimation("fadeInImage");
+ if (colorAnim) {
colorAnim->_callbackObj = _gui.layoutChecked("image");
colorAnim->play();
}
@@ -108,8 +108,8 @@ bool Notifier::onFadeInFinished() {
colorAnim->_callbackObj = _gui.layout("sprite");
colorAnim->play();
- if (!g_engine->gameIsAmerzone()) {
- colorAnim = _gui.colorLinearAnimation("visibleImage");
+ colorAnim = g_engine->gameIsAmerzone() ? nullptr : _gui.colorLinearAnimation("visibleImage");
+ if (colorAnim) {
colorAnim->_callbackObj = _gui.layout("image");
colorAnim->play();
}
@@ -129,8 +129,8 @@ bool Notifier::onVisibleFinished() {
colorAnim->_callbackObj = _gui.layout("sprite");
colorAnim->play();
- if (!g_engine->gameIsAmerzone()) {
- colorAnim = _gui.colorLinearAnimation("fadeOutImage");
+ colorAnim = g_engine->gameIsAmerzone() ? nullptr : _gui.colorLinearAnimation("fadeOutImage");
+ if (colorAnim) {
colorAnim->_callbackObj = _gui.layout("image");
colorAnim->play();
}
Commit: 4e1cb6d62491728d22e1630b4438af0fed29504f
https://github.com/scummvm/scummvm/commit/4e1cb6d62491728d22e1630b4438af0fed29504f
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Extend filters to include PS3-named scripts
Changed paths:
engines/tetraedge/game/application.cpp
engines/tetraedge/game/question2.cpp
engines/tetraedge/te/te_lua_thread.cpp
diff --git a/engines/tetraedge/game/application.cpp b/engines/tetraedge/game/application.cpp
index 523277fa579..05bd0c372e4 100644
--- a/engines/tetraedge/game/application.cpp
+++ b/engines/tetraedge/game/application.cpp
@@ -400,7 +400,7 @@ bool Application::run() {
if (_finishedGame) {
game->leave(false);
_mainMenu.enter();
- if (Common::File::exists("finalURL.lua")) {
+ if (Common::File::exists("finalURL.lua") || Common::File::exists("finalURL.data")) {
TeLuaGUI finalGui;
finalGui.load("finalURL.lua");
/*TeVariant finalVal =*/ finalGui.value("finalURL");
diff --git a/engines/tetraedge/game/question2.cpp b/engines/tetraedge/game/question2.cpp
index c12e62676e1..cb8d139d285 100644
--- a/engines/tetraedge/game/question2.cpp
+++ b/engines/tetraedge/game/question2.cpp
@@ -108,7 +108,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.baseName().contains("Cal_FIN.lua")) {
+ if (!path.baseName().contains("Cal_FIN.lua") && !path.baseName().contains("Cal_FIN.data")) {
blayout->setSize(TeVector3f32(0.45f, 0.065f, 1.0f));
xpos = 0.3f;
} else {
diff --git a/engines/tetraedge/te/te_lua_thread.cpp b/engines/tetraedge/te/te_lua_thread.cpp
index b2f7ebf9b5c..b0411d54bf8 100644
--- a/engines/tetraedge/te/te_lua_thread.cpp
+++ b/engines/tetraedge/te/te_lua_thread.cpp
@@ -161,9 +161,15 @@ void TeLuaThread::execute(const Common::String &fname, const TeVariant &p1, cons
}
}
-void TeLuaThread::applyScriptWorkarounds(char *buf, const Common::String &fileName) {
+void TeLuaThread::applyScriptWorkarounds(char *buf, const Common::String &fileNameIn) {
char *fixline;
+ Common::String fileName(fileNameIn);
+
+ if (fileName.hasSuffix(".data")) {
+ fileName = fileName.substr(0, fileName.size() - 5) + ".lua";
+ }
+
//
// WORKAROUND: Some script files have rogue ";" lines in them with nothing
// else, and ScummVM common lua version doesn't like them. Clean those up.
Commit: 17d76a9721fe0a4b067d751ea3799aef0b402d67
https://github.com/scummvm/scummvm/commit/17d76a9721fe0a4b067d751ea3799aef0b402d67
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Introduce TetraedgeFSNode to refer inside archives
Changed paths:
engines/tetraedge/tetraedge.cpp
engines/tetraedge/tetraedge.h
diff --git a/engines/tetraedge/tetraedge.cpp b/engines/tetraedge/tetraedge.cpp
index 8545cc69457..4851d470f61 100644
--- a/engines/tetraedge/tetraedge.cpp
+++ b/engines/tetraedge/tetraedge.cpp
@@ -361,5 +361,121 @@ void TetraedgeEngine::getSavegameThumbnail(Graphics::Surface &thumb) {
g_engine->getApplication()->getSavegameThumbnail(thumb);
}
+bool TetraedgeFSNode::getChildren(TetraedgeFSList &fslist, Common::FSNode::ListMode mode, bool hidden) const {
+ if (!_archive)
+ return false;
+
+ Common::Array<Common::String> tmpsublist;
+ if(!_archive->getChildren(_archivePath, tmpsublist, (Common::Archive::ListMode) mode, hidden))
+ return false;
+ fslist.clear();
+ for(Common::Array<Common::String>::iterator it = tmpsublist.begin(); it != tmpsublist.end(); it++) {
+ fslist.push_back(TetraedgeFSNode(_archive, _archivePath.join(*it)));
+ }
+ return true;
+}
+
+class SubPathArchive : public Common::Archive {
+public:
+ SubPathArchive(Common::Archive *archive, const Common::Path &prefix) : _archive(archive), _prefix(prefix) {}
+
+ bool hasFile(const Common::Path &path) const override {
+ return _archive && _archive->hasFile(_prefix.join(path));
+ }
+
+ bool isPathDirectory(const Common::Path &path) const override {
+ return _archive && _archive->isPathDirectory(_prefix.join(path));
+ }
+
+ bool getChildren(const Common::Path &path, Common::Array<Common::String> &list, ListMode mode, bool hidden) const override {
+ return _archive && getChildren(_prefix.join(path), list, mode, hidden);
+ }
+
+ int listMembers(Common::ArchiveMemberList &list) const override {
+ Common::ArchiveMemberList tmpList;
+ if (!_archive)
+ return 0;
+ _archive->listMembers(tmpList);
+ Common::String prefixStr = _prefix.toString();
+ if (!prefixStr.hasSuffix("/"))
+ prefixStr += "/";
+ int count = 0;
+ for (Common::ArchiveMemberList::iterator it = tmpList.begin(); it != tmpList.end(); it++) {
+ if ((*it)->getName().hasPrefix(prefixStr)) {
+ list.push_back(*it);
+ count++;
+ }
+ }
+ return count;
+ }
+
+ const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override {
+ return _archive ? _archive->getMember(_prefix.join(path)) : nullptr;
+ }
+
+ Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override {
+ return _archive ? _archive->createReadStreamForMember(_prefix.join(path)) : nullptr;
+ }
+
+ char getPathSeparator() const override {
+ return _archive ? _archive->getPathSeparator() : '/';
+ }
+
+private:
+ Common::Archive *_archive;
+ Common::Path _prefix;
+};
+
+void TetraedgeFSNode::maybeAddToSearchMan() const {
+ const Common::String path = getPath().toString(Common::Path::kNativeSeparator);
+ if (SearchMan.hasArchive(path))
+ return;
+ if (!_archivePath.empty())
+ SearchMan.add(path, new SubPathArchive(_archive, _archivePath));
+}
+
+Common::SeekableReadStream *TetraedgeFSNode::createReadStream() const {
+ return _archive ? _archive->createReadStreamForMember(_archivePath) : nullptr;
+}
+
+bool TetraedgeFSNode::isReadable() const {
+ return _archive && _archive->hasFile(_archivePath);
+}
+
+bool TetraedgeFSNode::isDirectory() const {
+ return _archive && _archive->isPathDirectory(_archivePath);
+}
+
+Common::Path TetraedgeFSNode::getPath() const {
+ return _archivePath;
+}
+
+Common::String TetraedgeFSNode::toString() const {
+ return _archivePath.toString(Common::Path::kNativeSeparator);
+}
+
+TetraedgeFSNode TetraedgeFSNode::getChild(const Common::Path &path) const {
+ return TetraedgeFSNode(_archive, _archivePath.join(path));
+}
+
+bool TetraedgeFSNode::exists() const {
+ return isDirectory() || isReadable();
+}
+
+bool TetraedgeFSNode::loadXML(Common::XMLParser &parser) const {
+ return parser.loadStream(createReadStream(), _archivePath.toString());
+}
+
+Common::String TetraedgeFSNode::getName() const {
+ return _archivePath.getLastComponent().toString();
+}
+
+bool TetraedgeFSNode::operator<(const TetraedgeFSNode& node) const {
+ return getPath() < node.getPath();
+}
+
+int TetraedgeFSNode::getDepth() const {
+ return _archivePath.splitComponents().size();
+}
} // namespace Tetraedge
diff --git a/engines/tetraedge/tetraedge.h b/engines/tetraedge/tetraedge.h
index deab9e9e9c4..0ee7299f4c3 100644
--- a/engines/tetraedge/tetraedge.h
+++ b/engines/tetraedge/tetraedge.h
@@ -26,11 +26,13 @@
#include "common/system.h"
#include "common/error.h"
#include "common/events.h"
+#include "common/file.h"
#include "common/fs.h"
#include "common/hash-str.h"
#include "common/random.h"
#include "common/serializer.h"
#include "common/util.h"
+#include "common/formats/xmlparser.h"
#include "engines/engine.h"
#include "engines/savestate.h"
#include "graphics/screen.h"
@@ -50,6 +52,33 @@ class TeRenderer;
class TeResourceManager;
class TeInputMgr;
+class TetraedgeFSNode;
+
+class TetraedgeFSList : public Common::Array<TetraedgeFSNode> {};
+class TetraedgeFSNode {
+public:
+ TetraedgeFSNode() : _archive(nullptr) {}
+ explicit TetraedgeFSNode(Common::Archive *archive) : _archive(archive) {}
+ TetraedgeFSNode(Common::Archive *archive, const Common::Path &archivePath) : _archive(archive), _archivePath(archivePath) {}
+
+ Common::SeekableReadStream *createReadStream() const;
+ bool isReadable() const;
+ bool isDirectory() const;
+ Common::Path getPath() const;
+ Common::String toString() const;
+ int getDepth() const;
+ bool exists() const;
+ bool loadXML(Common::XMLParser &parser) const;
+ Common::String getName() const;
+ TetraedgeFSNode getChild(const Common::Path &path) const;
+ bool getChildren(TetraedgeFSList &fslist, Common::FSNode::ListMode mode = Common::FSNode::kListDirectoriesOnly, bool hidden = true) const;
+ bool operator<(const TetraedgeFSNode& node) const;
+ void maybeAddToSearchMan() const;
+private:
+ Common::Archive *_archive;
+ Common::Path _archivePath;
+};
+
class TetraedgeEngine : public Engine {
public:
enum TetraedgeGameType {
@@ -70,6 +99,7 @@ private:
TeResourceManager *_resourceManager;
TeInputMgr *_inputMgr;
enum TetraedgeGameType _gameType;
+ Common::Array<Common::Archive *> _rootArchives;
protected:
// Engine APIs
@@ -79,6 +109,8 @@ public:
TetraedgeEngine(OSystem *syst, const ADGameDescription *gameDesc);
~TetraedgeEngine() override;
+ const Common::Array<Common::Archive *>& getRootArchives() const { return _rootArchives; }
+
uint32 getFeatures() const;
void closeGameDialogs();
Commit: 440cda29a4c6b0878a7af19713313cfae5f3a6b2
https://github.com/scummvm/scummvm/commit/440cda29a4c6b0878a7af19713313cfae5f3a6b2
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Mark Android as using UTF-8
Changed paths:
engines/tetraedge/te/te_i_font.cpp
diff --git a/engines/tetraedge/te/te_i_font.cpp b/engines/tetraedge/te/te_i_font.cpp
index b0f30c93c16..65fb6034cbd 100644
--- a/engines/tetraedge/te/te_i_font.cpp
+++ b/engines/tetraedge/te/te_i_font.cpp
@@ -51,10 +51,12 @@ TeIFont::GlyphData TeIFont::glyph(uint pxSize, uint charcode) {
Common::CodePage TeIFont::codePage() const {
Common::String lang = g_engine->getCore()->language();
- if (lang == "he")
- return Common::kWindows1255;
if (lang == "ru")
return Common::kISO8859_5;
+ if (g_engine->getGamePlatform() == Common::Platform::kPlatformAndroid)
+ return Common::CodePage::kUtf8;
+ if (lang == "he")
+ return Common::kWindows1255;
return Common::kLatin1;
}
Commit: 56d21368bd882335454fe21dd998dc58c75dbcd2
https://github.com/scummvm/scummvm/commit/56d21368bd882335454fe21dd998dc58c75dbcd2
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Support animations in animcached directory
Changed paths:
engines/tetraedge/game/in_game_scene.cpp
engines/tetraedge/te/te_images_sequence.cpp
diff --git a/engines/tetraedge/game/in_game_scene.cpp b/engines/tetraedge/game/in_game_scene.cpp
index 9b5ea0c4aa2..a5aee934a3b 100644
--- a/engines/tetraedge/game/in_game_scene.cpp
+++ b/engines/tetraedge/game/in_game_scene.cpp
@@ -115,7 +115,8 @@ bool InGameScene::addMarker(const Common::String &markerName, const Common::Path
// Note: game checks paths here but seems to just use the original?
markerSprite->setName(markerName);
markerSprite->setAnchor(TeVector3f32(anchorX, anchorY, 0.0f));
- markerSprite->load(imgPath);
+ if (!markerSprite->load(imgPath) && imgPath.baseName().hasSuffix(".anim"))
+ markerSprite->load(imgPath.append("cached"));
markerSprite->setSizeType(TeILayout::RELATIVE_TO_PARENT);
markerSprite->setPositionType(TeILayout::RELATIVE_TO_PARENT);
TeVector3f32 newPos;
diff --git a/engines/tetraedge/te/te_images_sequence.cpp b/engines/tetraedge/te/te_images_sequence.cpp
index 0ec945e31b2..fb9dfddd047 100644
--- a/engines/tetraedge/te/te_images_sequence.cpp
+++ b/engines/tetraedge/te/te_images_sequence.cpp
@@ -42,7 +42,7 @@ TeImagesSequence::~TeImagesSequence() {
/*static*/
bool TeImagesSequence::matchExtension(const Common::String &extn) {
- return extn == "anim";
+ return extn == "anim" || extn == "animcached";
}
static bool compareNodes(const Common::FSNode &left, const Common::FSNode &right) {
Commit: c5b04b43a2fa2d2485019682c4be09dd12b5182b
https://github.com/scummvm/scummvm/commit/c5b04b43a2fa2d2485019682c4be09dd12b5182b
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: workaround invalid XML in Nintendo Switch release
Changed paths:
engines/tetraedge/te/te_text_layout.cpp
diff --git a/engines/tetraedge/te/te_text_layout.cpp b/engines/tetraedge/te/te_text_layout.cpp
index 7ce5889110c..dba780a098c 100644
--- a/engines/tetraedge/te/te_text_layout.cpp
+++ b/engines/tetraedge/te/te_text_layout.cpp
@@ -87,7 +87,13 @@ void TeTextLayout::setText(const Common::String &val) {
break;
const Common::String *replacement = loc->text(replaced.substr(bstart + 2, bend - bstart - 2));
if (replacement) {
- replaced.replace(bstart, bend - bstart + 1, *replacement);
+ /* Workaround: Syberia 2 on Switch has strings
+ <Forward> and <Backwards> via replacement
+ in xml embed in lua. Escape < and >. */
+ Common::String escaped = *replacement;
+ Common::replace(escaped, "<", "<");
+ Common::replace(escaped, ">", ">");
+ replaced.replace(bstart, bend - bstart + 1, escaped);
}
bstart = replaced.find("$(", bstart + 1);
}
Commit: 0fd5bc2090ac3bc03fff961ae8c5cef18ff406b0
https://github.com/scummvm/scummvm/commit/0fd5bc2090ac3bc03fff961ae8c5cef18ff406b0
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Mark Russian as available on Syberia2
Changed paths:
engines/tetraedge/detection.cpp
diff --git a/engines/tetraedge/detection.cpp b/engines/tetraedge/detection.cpp
index d47b9182d0b..d5edb2a4c3c 100644
--- a/engines/tetraedge/detection.cpp
+++ b/engines/tetraedge/detection.cpp
@@ -58,9 +58,6 @@ DetectedGame TetraedgeMetaEngineDetection::toDetectedGame(const ADDetectedGame &
// game language. All games support multiple languages. Only Syberia 1
// supports RU.
for (const Common::Language *language = getGameLanguages(); *language != Common::UNK_LANG; language++) {
- // "ru" only present on syberia 1
- if (game.gameId != "syberia" && *language == Common::RU_RUS)
- continue;
game.appendGUIOptions(Common::getGameGUIOptionsDescriptionLanguage(*language));
}
Commit: 8763d4383b8f3dc2d23ddf69f819fce89117cfbd
https://github.com/scummvm/scummvm/commit/8763d4383b8f3dc2d23ddf69f819fce89117cfbd
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Support accessing files inside Android OBB archive
Changed paths:
A engines/tetraedge/obb_archive.cpp
A engines/tetraedge/obb_archive.h
engines/tetraedge/game/application.cpp
engines/tetraedge/game/billboard.cpp
engines/tetraedge/game/document.cpp
engines/tetraedge/game/documents_browser.cpp
engines/tetraedge/game/in_game_scene.cpp
engines/tetraedge/game/in_game_scene.h
engines/tetraedge/game/loc_file.cpp
engines/tetraedge/game/loc_file.h
engines/tetraedge/game/splash_screens.cpp
engines/tetraedge/game/syberia_game.cpp
engines/tetraedge/module.mk
engines/tetraedge/te/te_3d_texture.cpp
engines/tetraedge/te/te_3d_texture.h
engines/tetraedge/te/te_bezier_curve.cpp
engines/tetraedge/te/te_bezier_curve.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_i_codec.h
engines/tetraedge/te/te_image.cpp
engines/tetraedge/te/te_image.h
engines/tetraedge/te/te_images_sequence.cpp
engines/tetraedge/te/te_images_sequence.h
engines/tetraedge/te/te_interpolation.cpp
engines/tetraedge/te/te_interpolation.h
engines/tetraedge/te/te_lua_gui.cpp
engines/tetraedge/te/te_lua_gui.h
engines/tetraedge/te/te_lua_script.cpp
engines/tetraedge/te/te_lua_script.h
engines/tetraedge/te/te_lua_thread.cpp
engines/tetraedge/te/te_lua_thread.h
engines/tetraedge/te/te_material.cpp
engines/tetraedge/te/te_model_animation.cpp
engines/tetraedge/te/te_music.cpp
engines/tetraedge/te/te_music.h
engines/tetraedge/te/te_png.cpp
engines/tetraedge/te/te_png.h
engines/tetraedge/te/te_resource_manager.h
engines/tetraedge/te/te_scene.h
engines/tetraedge/te/te_scene_warp.cpp
engines/tetraedge/te/te_scummvm_codec.cpp
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_text_layout.cpp
engines/tetraedge/te/te_theora.cpp
engines/tetraedge/te/te_theora.h
engines/tetraedge/te/te_tiled_surface.cpp
engines/tetraedge/te/te_tiled_surface.h
engines/tetraedge/te/te_warp.cpp
engines/tetraedge/te/te_warp.h
engines/tetraedge/te/te_warp_bloc.cpp
engines/tetraedge/te/te_warp_bloc.h
engines/tetraedge/tetraedge.cpp
diff --git a/engines/tetraedge/game/application.cpp b/engines/tetraedge/game/application.cpp
index 05bd0c372e4..9dcc69a8a4b 100644
--- a/engines/tetraedge/game/application.cpp
+++ b/engines/tetraedge/game/application.cpp
@@ -191,10 +191,10 @@ void Application::create() {
// Try alternate langs..
int i = 0;
- Common::Path textFilePath;
+ TetraedgeFSNode textFileNode;
while (i < ARRAYSIZE(allLangs)) {
- textFilePath = core->findFile(textsPath.join(core->language() + ".xml"));
- if (Common::File::exists(textFilePath))
+ textFileNode = core->findFile(textsPath.join(core->language() + ".xml"));
+ if (textFileNode.exists())
break;
core->language(allLangs[i]);
i++;
@@ -203,7 +203,7 @@ void Application::create() {
error("Couldn't find texts/[lang].xml for any language.");
}
- _loc.load(textFilePath);
+ _loc.load(textFileNode);
core->addLoc(&_loc);
if (!g_engine->gameIsAmerzone()) {
diff --git a/engines/tetraedge/game/billboard.cpp b/engines/tetraedge/game/billboard.cpp
index bf76f704bcc..1676baa0b63 100644
--- a/engines/tetraedge/game/billboard.cpp
+++ b/engines/tetraedge/game/billboard.cpp
@@ -37,8 +37,8 @@ bool Billboard::load(const Common::Path &path) {
TeIntrusivePtr<Te3DTexture> texture = Te3DTexture::makeInstance();
SyberiaGame *game = dynamic_cast<SyberiaGame *>(g_engine->getGame());
TeCore *core = g_engine->getCore();
- Common::Path texPath = core->findFile(game->sceneZonePath().join(path));
- texture->load(texPath);
+ TetraedgeFSNode texnode = core->findFile(game->sceneZonePath().join(path));
+ texture->load(texnode);
_model->setName(path.toString('/'));
Common::Array<TeVector3f32> quad;
quad.resize(4);
diff --git a/engines/tetraedge/game/document.cpp b/engines/tetraedge/game/document.cpp
index e7e62fbd060..a0457cb393c 100644
--- a/engines/tetraedge/game/document.cpp
+++ b/engines/tetraedge/game/document.cpp
@@ -38,7 +38,7 @@ void Document::load(const Common::String &name) {
addChild(_gui.layoutChecked("object"));
setName(name);
const Common::Path sprPath = spritePath();
- _gui.spriteLayoutChecked("upLayout")->load(g_engine->getCore()->findFile(sprPath));
+ _gui.spriteLayoutChecked("upLayout")->load(sprPath);
_gui.buttonLayoutChecked("object")->onMouseClickValidated().add(this, &Document::onButtonDown);
TeITextLayout *txtLayout = _gui.textLayout("text");
if (!txtLayout)
diff --git a/engines/tetraedge/game/documents_browser.cpp b/engines/tetraedge/game/documents_browser.cpp
index 2d17a420b3c..91a9f1ce139 100644
--- a/engines/tetraedge/game/documents_browser.cpp
+++ b/engines/tetraedge/game/documents_browser.cpp
@@ -123,16 +123,15 @@ void DocumentsBrowser::loadZoomed() {
}
void DocumentsBrowser::loadXMLFile(const Common::Path &path) {
- Common::Path xmlPath = g_engine->getCore()->findFile(path);
- Common::File xmlfile;
- xmlfile.open(xmlPath);
- int64 fileLen = xmlfile.size();
+ TetraedgeFSNode node = g_engine->getCore()->findFile(path);
+ Common::ScopedPtr<Common::SeekableReadStream> xmlfile(node.createReadStream());
+ int64 fileLen = xmlfile->size();
char *buf = new char[fileLen + 1];
buf[fileLen] = '\0';
- xmlfile.read(buf, fileLen);
+ xmlfile->read(buf, fileLen);
const Common::String xmlContents = Common::String::format("<?xml version=\"1.0\" encoding=\"UTF-8\"?><document>%s</document>", buf);
delete [] buf;
- xmlfile.close();
+ xmlfile.reset();
DocumentsBrowserXmlParser parser;
if (!parser.loadBuffer((const byte *)xmlContents.c_str(), xmlContents.size()))
@@ -306,10 +305,12 @@ void DocumentsBrowser::showDocument(const Common::String &docName, int startPage
TeCore *core = g_engine->getCore();
const char *pathPattern = g_engine->gameIsAmerzone() ? "DocumentsBrowser/Documents/%s_zoomed_%d" : "DocumentsBrowser/Documents/Documents/%s_zoomed_%d";
const Common::Path docPathBase(Common::String::format(pathPattern, docName.c_str(), (int)startPage));
- Common::Path docPath = core->findFile(docPathBase.append(".png"));
- if (!Common::File::exists(docPath)) {
- docPath = core->findFile(docPathBase.append(".jpg"));
- if (!Common::File::exists(docPath)) {
+ Common::Path docPath = docPathBase.append(".png");
+ TetraedgeFSNode docNode = core->findFile(docPath);
+ if (!docNode.exists()) {
+ docPath = docPathBase.append(".jpg");
+ docNode = core->findFile(docPath);
+ if (!docNode.exists()) {
// Probably the end of the doc
if (startPage == 0)
warning("Can't find first page of doc named %s", docName.c_str());
@@ -323,9 +324,9 @@ void DocumentsBrowser::showDocument(const Common::String &docName, int startPage
sprite->load(docPath);
TeVector2s32 spriteSize = sprite->_tiledSurfacePtr->tiledTexture()->totalSize();
- Common::Path luaPath = core->findFile(docPathBase.append(".lua"));
- if (Common::File::exists(luaPath)) {
- _zoomedDocGui.load(luaPath);
+ TetraedgeFSNode luaNode = core->findFile(docPathBase.append(".lua"));
+ if (luaNode.exists()) {
+ _zoomedDocGui.load(luaNode);
sprite->addChild(_zoomedDocGui.layoutChecked("root"));
TeButtonLayout *btn;
diff --git a/engines/tetraedge/game/in_game_scene.cpp b/engines/tetraedge/game/in_game_scene.cpp
index a5aee934a3b..a219003d6e9 100644
--- a/engines/tetraedge/game/in_game_scene.cpp
+++ b/engines/tetraedge/game/in_game_scene.cpp
@@ -206,9 +206,9 @@ Billboard *InGameScene::billboard(const Common::String &name) {
}
bool InGameScene::changeBackground(const Common::Path &name) {
- Common::Path path = g_engine->getCore()->findFile(name);
- if (Common::File::exists(path)) {
- _bgGui.spriteLayoutChecked("root")->load(path);
+ TetraedgeFSNode node = g_engine->getCore()->findFile(name);
+ if (node.isReadable()) {
+ _bgGui.spriteLayoutChecked("root")->load(name);
if (g_engine->gameType() == TetraedgeEngine::kSyberia2)
_bgGui.spriteLayoutChecked("root")->play();
return true;
@@ -666,7 +666,7 @@ TeVector2f32 InGameScene::layerSize() {
return TeVector2f32(sz.x(), sz.y());
}
-bool InGameScene::load(const Common::Path &scenePath) {
+bool InGameScene::load(const TetraedgeFSNode &sceneNode) {
// Syberia 1 has loadActZones function contents inline.
loadActZones();
@@ -680,38 +680,38 @@ bool InGameScene::load(const Common::Path &scenePath) {
_shadowLightNo = -1;
TeCore *core = g_engine->getCore();
- const Common::Path lightsPath = core->findFile(getLightsFileName());
- if (Common::File::exists(lightsPath))
- loadLights(lightsPath);
+ const TetraedgeFSNode lightsNode(core->findFile(getLightsFileName()));
+ if (lightsNode.isReadable())
+ loadLights(lightsNode);
- if (!Common::File::exists(scenePath))
+ if (!sceneNode.exists())
return false;
close();
- _loadedPath = scenePath.getParent();
- Common::File scenefile;
- if (!scenefile.open(scenePath))
+ _loadedPath = sceneNode.getPath();
+ Common::ScopedPtr<Common::SeekableReadStream> scenefile(sceneNode.createReadStream());
+ if (!scenefile)
return false;
- uint32 ncameras = scenefile.readUint32LE();
+ uint32 ncameras = scenefile->readUint32LE();
if (ncameras > 1024)
error("Improbable number of cameras %d", ncameras);
for (uint i = 0; i < ncameras; i++) {
TeIntrusivePtr<TeCamera> cam = new TeCamera();
- deserializeCam(scenefile, cam);
+ deserializeCam(*scenefile, cam);
cameras().push_back(cam);
}
- uint32 nobjects = scenefile.readUint32LE();
+ uint32 nobjects = scenefile->readUint32LE();
if (nobjects > 1024)
error("Improbable number of objects %d", nobjects);
for (uint i = 0; i < nobjects; i++) {
TeIntrusivePtr<TeModel> model = new TeModel();
- const Common::String modelname = Te3DObject2::deserializeString(scenefile);
+ const Common::String modelname = Te3DObject2::deserializeString(*scenefile);
model->setName(modelname);
- const Common::String objname = Te3DObject2::deserializeString(scenefile);
+ const Common::String objname = Te3DObject2::deserializeString(*scenefile);
TePickMesh2 *pickmesh = new TePickMesh2();
- deserializeModel(scenefile, model, pickmesh);
+ deserializeModel(*scenefile, model, pickmesh);
if (modelname.contains("Clic")) {
//debug("Loaded clickMesh %s", modelname.c_str());
_hitObjects.push_back(model);
@@ -737,39 +737,39 @@ bool InGameScene::load(const Common::Path &scenePath) {
}
}
- uint32 nfreemovezones = scenefile.readUint32LE();
+ uint32 nfreemovezones = scenefile->readUint32LE();
if (nfreemovezones > 1024)
error("Improbable number of free move zones %d", nfreemovezones);
for (uint i = 0; i < nfreemovezones; i++) {
TeFreeMoveZone *zone = new TeFreeMoveZone();
- TeFreeMoveZone::deserialize(scenefile, *zone, &_blockers, &_rectBlockers, &_actZones);
+ TeFreeMoveZone::deserialize(*scenefile, *zone, &_blockers, &_rectBlockers, &_actZones);
_freeMoveZones.push_back(zone);
zone->setVisible(false);
}
- uint32 ncurves = scenefile.readUint32LE();
+ uint32 ncurves = scenefile->readUint32LE();
if (ncurves > 1024)
error("Improbable number of curves %d", ncurves);
for (uint i = 0; i < ncurves; i++) {
TeIntrusivePtr<TeBezierCurve> curve = new TeBezierCurve();
- TeBezierCurve::deserialize(scenefile, *curve);
+ TeBezierCurve::deserialize(*scenefile, *curve);
curve->setVisible(true);
_bezierCurves.push_back(curve);
}
- uint32 ndummies = scenefile.readUint32LE();
+ uint32 ndummies = scenefile->readUint32LE();
if (ndummies > 1024)
error("Improbable number of dummies %d", ndummies);
for (uint i = 0; i < ndummies; i++) {
InGameScene::Dummy dummy;
TeVector3f32 vec;
TeQuaternion rot;
- dummy._name = Te3DObject2::deserializeString(scenefile);
- TeVector3f32::deserialize(scenefile, vec);
+ dummy._name = Te3DObject2::deserializeString(*scenefile);
+ TeVector3f32::deserialize(*scenefile, vec);
dummy._position = vec;
- TeQuaternion::deserialize(scenefile, rot);
+ TeQuaternion::deserialize(*scenefile, rot);
dummy._rotation = rot;
- TeVector3f32::deserialize(scenefile, vec);
+ TeVector3f32::deserialize(*scenefile, vec);
dummy._scale = vec;
_dummies.push_back(dummy);
}
@@ -806,7 +806,7 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
Common::Path xmlpath = _sceneFileNameBase(zone, scene).joinInPlace("Scene")
.appendInPlace(scene).appendInPlace(".xml");
- Common::Path path = g_engine->getCore()->findFile(xmlpath);
+ TetraedgeFSNode node = g_engine->getCore()->findFile(xmlpath);
InGameSceneXmlParser parser(this);
parser.setAllowText();
@@ -817,13 +817,13 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
// in Syberia 2 has an embedded comment, which is invalid XML.
// Patch the contents of the file before loading.
//
- Common::File xmlFile;
- if (!xmlFile.open(path))
- error("InGameScene::loadXml: Can't open %s", path.toString(Common::Path::kNativeSeparator).c_str());
- const int64 bufsize = xmlFile.size();
+ Common::ScopedPtr<Common::SeekableReadStream> xmlFile(node.createReadStream());
+ if (!xmlFile)
+ error("InGameScene::loadXml: Can't open %s", node.toString().c_str());
+ const int64 bufsize = xmlFile->size();
char *buf = new char[bufsize+1];
buf[bufsize] = '\0';
- xmlFile.read(buf, bufsize);
+ xmlFile->read(buf, bufsize);
fixedbuf = Common::String(buf);
delete [] buf;
size_t offset = fixedbuf.find("<!-- <rippleMask");
@@ -838,12 +838,12 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
parser.loadBuffer((const byte *)fixedbuf.c_str(), bufsize);
} else {
// Regular loading.
- if (!parser.loadFile(path))
- error("InGameScene::loadXml: Can't load %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!node.loadXML(parser))
+ error("InGameScene::loadXml: Can't load %s", node.toString().c_str());
}
if (!parser.parse())
- error("InGameScene::loadXml: Can't parse %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ error("InGameScene::loadXml: Can't parse %s", node.toString().c_str());
// loadFlamme and loadSnowCustom are handled by the above.
@@ -856,16 +856,17 @@ bool InGameScene::loadXml(const Common::String &zone, const Common::String &scen
_shadowLightNo = -1;
TeCore *core = g_engine->getCore();
- const Common::Path lightsPath = core->findFile(getLightsFileName());
- if (Common::File::exists(lightsPath))
- loadLights(lightsPath);
+ const TetraedgeFSNode lightsNode(core->findFile(getLightsFileName()));
+ if (lightsNode.isReadable())
+ loadLights(lightsNode);
- Common::Path pxmlpath = core->findFile(_sceneFileNameBase(zone, scene).joinInPlace("particles.xml"));
- if (Common::File::exists(pxmlpath)) {
+ Common::Path pxmlpath = _sceneFileNameBase(zone, scene).joinInPlace("particles.xml");
+ TetraedgeFSNode pnode = g_engine->getCore()->findFile(pxmlpath);
+ if (pnode.isReadable()) {
ParticleXmlParser pparser;
pparser._scene = this;
- if (!pparser.loadFile(pxmlpath))
- error("InGameScene::loadXml: Can't load %s", pxmlpath.toString(Common::Path::kNativeSeparator).c_str());
+ if (!pnode.loadXML(pparser))
+ error("InGameScene::loadXml: Can't load %s", pnode.toString().c_str());
if (!pparser.parse())
error("InGameScene::loadXml: Can't parse %s", pxmlpath.toString(Common::Path::kNativeSeparator).c_str());
}
@@ -945,13 +946,13 @@ bool InGameScene::loadFreeMoveZone(const Common::String &name, TeVector2f32 &gri
return true;
}
-bool InGameScene::loadLights(const Common::Path &path) {
+bool InGameScene::loadLights(const TetraedgeFSNode &node) {
SceneLightsXmlParser parser(&_lights);
- if (!parser.loadFile(path))
- error("InGameScene::loadLights: Can't load %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!node.loadXML(parser))
+ error("InGameScene::loadLights: Can't load %s", node.toString().c_str());
if (!parser.parse())
- error("InGameScene::loadLights: Can't parse %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ error("InGameScene::loadLights: Can't parse %s", node.toString().c_str());
_shadowColor = parser.getShadowColor();
_shadowLightNo = parser.getShadowLightNo();
@@ -989,8 +990,8 @@ bool InGameScene::loadLights(const Common::Path &path) {
return true;
}
-void InGameScene::loadMarkers(const Common::Path &path) {
- _markerGui.load(path);
+void InGameScene::loadMarkers(const TetraedgeFSNode &node) {
+ _markerGui.load(node);
TeLayout *bg = _bgGui.layoutChecked("background");
TeSpriteLayout *root = Game::findSpriteLayoutByName(bg, "root");
bg->setRatioMode(TeILayout::RATIO_MODE_NONE);
@@ -1080,13 +1081,13 @@ bool InGameScene::loadPlayerCharacter(const Common::String &name) {
bool InGameScene::loadCurve(const Common::String &name) {
TeCore *core = g_engine->getCore();
- const Common::Path path = core->findFile(_sceneFileNameBase().joinInPlace(name).appendInPlace(".bin"));
- if (!Common::File::exists(path)) {
- warning("[InGameScene::loadCurve] Can't open file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
+ TetraedgeFSNode node = core->findFile(_sceneFileNameBase().joinInPlace(name).appendInPlace(".bin"));
+ if (!node.isReadable()) {
+ warning("[InGameScene::loadCurve] Can't open file : %s.", node.toString().c_str());
return false;
}
TeIntrusivePtr<TeBezierCurve> curve = new TeBezierCurve();
- curve->loadBin(path);
+ curve->loadBin(node);
_bezierCurves.push_back(curve);
return true;
}
@@ -1094,25 +1095,24 @@ bool InGameScene::loadCurve(const Common::String &name) {
bool InGameScene::loadDynamicLightBloc(const Common::String &name, const Common::String &texture, const Common::String &zone, const Common::String &scene) {
const Common::Path pdat = _sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin");
const Common::Path ptex = _sceneFileNameBase(zone, scene).joinInPlace(texture);
- Common::Path datPath = g_engine->getCore()->findFile(pdat);
- Common::Path texPath = g_engine->getCore()->findFile(ptex);
- if (!Common::File::exists(datPath)) {
- warning("[InGameScene::loadDynamicLightBloc] Can't open file : %s.", pdat.toString(Common::Path::kNativeSeparator).c_str());
+ TetraedgeFSNode datNode = g_engine->getCore()->findFile(pdat);
+ TetraedgeFSNode texNode = g_engine->getCore()->findFile(ptex);
+ if (!datNode.isReadable()) {
+ warning("[InGameScene::loadDynamicLightBloc] Can't open file : %s.", pdat.toString('/').c_str());
return false;
}
- Common::File file;
- file.open(datPath);
+ Common::ScopedPtr<Common::SeekableReadStream> file(datNode.createReadStream());
TeModel *model = new TeModel();
model->setMeshCount(1);
- model->setName(datPath.baseName());
+ model->setName(datNode.getPath().baseName());
// Read position/rotation/scale.
- model->deserialize(file, *model);
+ model->deserialize(*file, *model);
- uint32 verts = file.readUint32LE();
- uint32 tricount = file.readUint32LE();
+ uint32 verts = file->readUint32LE();
+ uint32 tricount = file->readUint32LE();
if (verts > 100000 || tricount > 10000)
error("Improbable number of verts (%d) or triangles (%d)", verts, tricount);
@@ -1121,25 +1121,25 @@ bool InGameScene::loadDynamicLightBloc(const Common::String &name, const Common:
for (uint i = 0; i < verts; i++) {
TeVector3f32 vec;
- TeVector3f32::deserialize(file, vec);
+ TeVector3f32::deserialize(*file, vec);
mesh->setVertex(i, vec);
mesh->setNormal(i, TeVector3f32(0, 0, 1));
}
for (uint i = 0; i < verts; i++) {
TeVector2f32 vec2;
- TeVector2f32::deserialize(file, vec2);
+ TeVector2f32::deserialize(*file, vec2);
vec2.setY(1.0 - vec2.getY());
mesh->setTextureUV(i, vec2);
}
for (uint i = 0; i < tricount * 3; i++)
- mesh->setIndex(i, file.readUint16LE());
+ mesh->setIndex(i, file->readUint16LE());
- file.close();
+ file.reset();
- if (Common::File::exists(texPath)) {
+ if (texNode.exists()) {
TeIntrusivePtr<Te3DTexture> tex = Te3DTexture::makeInstance();
- tex->load2(texPath, false);
+ tex->load2(texNode, false);
mesh->defaultMaterial(tex);
} else if (texture.size()) {
warning("loadDynamicLightBloc: Failed to load texture %s", texture.c_str());
@@ -1152,20 +1152,20 @@ bool InGameScene::loadDynamicLightBloc(const Common::String &name, const Common:
}
bool InGameScene::loadLight(const Common::String &name, const Common::String &zone, const Common::String &scene) {
- Common::Path datPath = g_engine->getCore()->findFile(_sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin"));
- if (!Common::File::exists(datPath)) {
- warning("[InGameScene::loadLight] Can't open file : %s.", datPath.toString(Common::Path::kNativeSeparator).c_str());
+ Common::Path datpath = _sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin");
+ TetraedgeFSNode datnode = g_engine->getCore()->findFile(datpath);
+ if (!datnode.isReadable()) {
+ warning("[InGameScene::loadLight] Can't open file : %s.", datpath.toString(Common::Path::kNativeSeparator).c_str());
return false;
}
- Common::File file;
- file.open(datPath);
+ Common::ScopedPtr<Common::SeekableReadStream> file(datnode.createReadStream());
SceneLight light;
light._name = name;
- TeVector3f32::deserialize(file, light._v1);
- TeVector3f32::deserialize(file, light._v2);
- light._color.deserialize(file);
- light._f = file.readFloatLE();
+ TeVector3f32::deserialize(*file, light._v1);
+ TeVector3f32::deserialize(*file, light._v2);
+ light._color.deserialize(*file);
+ light._f = file->readFloatLE();
_sceneLights.push_back(light);
return true;
@@ -1173,24 +1173,23 @@ bool InGameScene::loadLight(const Common::String &name, const Common::String &zo
bool InGameScene::loadMask(const Common::String &name, const Common::String &texture, const Common::String &zone, const Common::String &scene) {
TeCore *core = g_engine->getCore();
- Common::Path datPath = core->findFile(_sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin"));
- Common::Path texPath = core->findFile(_sceneFileNameBase(zone, scene).joinInPlace(texture));
- if (!Common::File::exists(datPath)) {
- warning("[InGameScene::loadMask] Can't open file : %s.", datPath.toString(Common::Path::kNativeSeparator).c_str());
+ TetraedgeFSNode texnode = core->findFile(_sceneFileNameBase(zone, scene).joinInPlace(texture));
+ TetraedgeFSNode datnode = core->findFile(_sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin"));
+ if (!datnode.isReadable()) {
+ warning("[InGameScene::loadMask] Can't open file : %s.", datnode.toString().c_str());
return false;
}
TeModel *model = new TeModel();
model->setMeshCount(1);
model->setName(name);
- Common::File file;
- file.open(datPath);
+ Common::ScopedPtr<Common::SeekableReadStream> file(datnode.createReadStream());
// Load position, rotation, size.
- Te3DObject2::deserialize(file, *model, false);
+ Te3DObject2::deserialize(*file, *model, false);
- uint32 verts = file.readUint32LE();
- uint32 tricount = file.readUint32LE();
+ uint32 verts = file->readUint32LE();
+ uint32 tricount = file->readUint32LE();
if (verts > 100000 || tricount > 10000)
error("Improbable number of verts (%d) or triangles (%d)", verts, tricount);
@@ -1199,7 +1198,7 @@ bool InGameScene::loadMask(const Common::String &name, const Common::String &tex
for (uint i = 0; i < verts; i++) {
TeVector3f32 vec;
- TeVector3f32::deserialize(file, vec);
+ TeVector3f32::deserialize(*file, vec);
mesh->setVertex(i, vec);
mesh->setNormal(i, TeVector3f32(0, 0, 1));
if (_maskAlpha) {
@@ -1209,20 +1208,19 @@ bool InGameScene::loadMask(const Common::String &name, const Common::String &tex
for (uint i = 0; i < verts; i++) {
TeVector2f32 vec2;
- TeVector2f32::deserialize(file, vec2);
+ TeVector2f32::deserialize(*file, vec2);
vec2.setY(1.0 - vec2.getY());
mesh->setTextureUV(i, vec2);
}
// For some reason this one has the indexes in reverse order :(
for (uint i = 0; i < tricount * 3; i += 3) {
- mesh->setIndex(i + 2, file.readUint16LE());
- mesh->setIndex(i + 1, file.readUint16LE());
- mesh->setIndex(i, file.readUint16LE());
+ mesh->setIndex(i + 2, file->readUint16LE());
+ mesh->setIndex(i + 1, file->readUint16LE());
+ mesh->setIndex(i, file->readUint16LE());
}
- file.close();
- Common::Path texnode = core->findFile(texPath);
+ file.reset();
TeIntrusivePtr<Te3DTexture> tex = Te3DTexture::load2(texnode, !_maskAlpha);
if (tex) {
@@ -1260,23 +1258,22 @@ bool InGameScene::loadShadowMask(const Common::String &name, const Common::Strin
}
bool InGameScene::loadShadowReceivingObject(const Common::String &name, const Common::String &zone, const Common::String &scene) {
- Common::Path datPath = g_engine->getCore()->findFile(_sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin"));
- if (!Common::File::exists(datPath)) {
- warning("[InGameScene::loadShadowReceivingObject] Can't open file : %s.", datPath.toString(Common::Path::kNativeSeparator).c_str());
+ TetraedgeFSNode datnode = g_engine->getCore()->findFile(_sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin"));
+ if (!datnode.isReadable()) {
+ warning("[InGameScene::loadShadowReceivingObject] Can't open file : %s.", datnode.toString().c_str());
return false;
}
TeModel *model = new TeModel();
model->setMeshCount(1);
model->setName(name);
- Common::File file;
- file.open(datPath);
+ Common::ScopedPtr<Common::SeekableReadStream> file(datnode.createReadStream());
// Load position, rotation, size.
- Te3DObject2::deserialize(file, *model, false);
+ Te3DObject2::deserialize(*file, *model, false);
- uint32 verts = file.readUint32LE();
- uint32 tricount = file.readUint32LE();
+ uint32 verts = file->readUint32LE();
+ uint32 tricount = file->readUint32LE();
if (verts > 100000 || tricount > 10000)
error("Improbable number of verts (%d) or triangles (%d)", verts, tricount);
@@ -1285,42 +1282,41 @@ bool InGameScene::loadShadowReceivingObject(const Common::String &name, const Co
for (uint i = 0; i < verts; i++) {
TeVector3f32 vec;
- TeVector3f32::deserialize(file, vec);
+ TeVector3f32::deserialize(*file, vec);
mesh->setVertex(i, vec);
mesh->setNormal(i, TeVector3f32(0, 0, 1));
}
// Indexes in reverse order :(
for (uint i = 0; i < tricount * 3; i += 3) {
- mesh->setIndex(i + 2, file.readUint16LE());
- mesh->setIndex(i + 1, file.readUint16LE());
- mesh->setIndex(i, file.readUint16LE());
+ mesh->setIndex(i + 2, file->readUint16LE());
+ mesh->setIndex(i + 1, file->readUint16LE());
+ mesh->setIndex(i, file->readUint16LE());
}
- file.close();
+ file.reset();
_shadowReceivingObjects.push_back(model);
return true;
}
bool InGameScene::loadZBufferObject(const Common::String &name, const Common::String &zone, const Common::String &scene) {
- Common::Path datPath = g_engine->getCore()->findFile(_sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin"));
- if (!Common::File::exists(datPath)) {
- warning("[InGameScene::loadZBufferObject] Can't open file : %s.", datPath.toString(Common::Path::kNativeSeparator).c_str());
+ TetraedgeFSNode datnode = g_engine->getCore()->findFile(_sceneFileNameBase(zone, scene).joinInPlace(name).appendInPlace(".bin"));
+ if (!datnode.isReadable()) {
+ warning("[InGameScene::loadZBufferObject] Can't open file : %s.", datnode.toString().c_str());
return false;
}
TeModel *model = new TeModel();
model->setMeshCount(1);
model->setName(name);
- Common::File file;
- file.open(datPath);
+ Common::ScopedPtr<Common::SeekableReadStream> file(datnode.createReadStream());
// Load position, rotation, size.
- Te3DObject2::deserialize(file, *model, false);
+ Te3DObject2::deserialize(*file, *model, false);
- uint32 verts = file.readUint32LE();
- uint32 tricount = file.readUint32LE();
+ uint32 verts = file->readUint32LE();
+ uint32 tricount = file->readUint32LE();
if (verts > 100000 || tricount > 10000)
error("Improbable number of verts (%d) or triangles (%d)", verts, tricount);
@@ -1329,14 +1325,14 @@ bool InGameScene::loadZBufferObject(const Common::String &name, const Common::St
for (uint i = 0; i < verts; i++) {
TeVector3f32 vec;
- TeVector3f32::deserialize(file, vec);
+ TeVector3f32::deserialize(*file, vec);
mesh->setVertex(i, vec);
mesh->setNormal(i, TeVector3f32(0, 0, 1));
mesh->setColor(i, TeColor(128, 0, 255, 128));
}
for (uint i = 0; i < tricount * 3; i++) {
- mesh->setIndex(i, file.readUint16LE());
+ mesh->setIndex(i, file->readUint16LE());
}
_zoneModels.push_back(model);
@@ -1398,9 +1394,9 @@ void InGameScene::loadBlockers() {
}
}
-void InGameScene::loadBackground(const Common::Path &path) {
+void InGameScene::loadBackground(const TetraedgeFSNode &node) {
_youkiManager.reset();
- _bgGui.load(path);
+ _bgGui.load(node);
TeLayout *bg = _bgGui.layout("background");
TeLayout *root = _bgGui.layout("root");
bg->setRatioMode(TeILayout::RATIO_MODE_NONE);
@@ -1434,8 +1430,8 @@ bool InGameScene::loadBillboard(const Common::String &name) {
}
}
-void InGameScene::loadInteractions(const Common::Path &path) {
- _hitObjectGui.load(path);
+void InGameScene::loadInteractions(const TetraedgeFSNode &node) {
+ _hitObjectGui.load(node);
TeLayout *bgbackground = _bgGui.layoutChecked("background");
Game *game = g_engine->getGame();
TeSpriteLayout *root = game->findSpriteLayoutByName(bgbackground, "root");
diff --git a/engines/tetraedge/game/in_game_scene.h b/engines/tetraedge/game/in_game_scene.h
index 33da6b0d667..ade0e5b49aa 100644
--- a/engines/tetraedge/game/in_game_scene.h
+++ b/engines/tetraedge/game/in_game_scene.h
@@ -181,14 +181,14 @@ public:
bool isObjectBlocking(const Common::String &name);
TeVector2f32 layerSize();
- virtual bool load(const Common::Path &path) override;
- void loadBackground(const Common::Path &node);
+ virtual bool load(const TetraedgeFSNode &node) override;
+ void loadBackground(const TetraedgeFSNode &node);
bool loadBillboard(const Common::String &name);
void loadBlockers();
bool loadCharacter(const Common::String &name);
- void loadInteractions(const Common::Path &path);
- bool loadLights(const Common::Path &path);
- void loadMarkers(const Common::Path &path);
+ void loadInteractions(const TetraedgeFSNode &node);
+ bool loadLights(const TetraedgeFSNode &node);
+ void loadMarkers(const TetraedgeFSNode &node);
bool loadObject(const Common::String &oname);
bool loadObjectMaterials(const Common::String &name);
bool loadObjectMaterials(const Common::Path &path, const Common::String &name);
diff --git a/engines/tetraedge/game/loc_file.cpp b/engines/tetraedge/game/loc_file.cpp
index 0baca5b360e..09e078ca96b 100644
--- a/engines/tetraedge/game/loc_file.cpp
+++ b/engines/tetraedge/game/loc_file.cpp
@@ -31,25 +31,26 @@ namespace Tetraedge {
LocFile::LocFile() {
}
-void LocFile::load(const Common::Path &path) {
+void LocFile::load(const TetraedgeFSNode &fsnode) {
TeNameValXmlParser parser;
const Common::String xmlHeader("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
- Common::File locFile;
- if (!locFile.open(path))
- error("LocFile::load: failed to open %s.", path.baseName().c_str());
+ Common::ScopedPtr<Common::SeekableReadStream> locFile(fsnode.createReadStream());
+ const Common::String path = fsnode.getName();
+ if (!locFile)
+ error("LocFile::load: failed to open %s.", path.c_str());
- int64 fileLen = locFile.size();
+ int64 fileLen = locFile->size();
char *buf = new char[fileLen + 1];
buf[fileLen] = '\0';
- locFile.read(buf, fileLen);
+ locFile->read(buf, fileLen);
const Common::String xmlContents = xmlHeader + buf;
delete [] buf;
- locFile.close();
+ locFile.reset();
if (!parser.loadBuffer((const byte *)xmlContents.c_str(), xmlContents.size()))
- error("LocFile::load: failed to load %s.", path.baseName().c_str());
+ error("LocFile::load: failed to load %s.", path.c_str());
if (!parser.parse())
- error("LocFile::load: failed to parse %s.", path.baseName().c_str());
+ error("LocFile::load: failed to parse %s.", path.c_str());
_map = parser.getMap();
}
diff --git a/engines/tetraedge/game/loc_file.h b/engines/tetraedge/game/loc_file.h
index 1c033ab000f..b54d81c13bf 100644
--- a/engines/tetraedge/game/loc_file.h
+++ b/engines/tetraedge/game/loc_file.h
@@ -26,6 +26,7 @@
#include "common/fs.h"
#include "tetraedge/te/te_i_loc.h"
+#include "tetraedge/tetraedge.h"
namespace Tetraedge {
@@ -33,7 +34,7 @@ class LocFile : public TeILoc {
public:
LocFile();
- void load(const Common::Path &path);
+ void load(const TetraedgeFSNode &fsnode);
const Common::String *value(const Common::String &key) const;
};
diff --git a/engines/tetraedge/game/splash_screens.cpp b/engines/tetraedge/game/splash_screens.cpp
index c8eab33aa5c..ab749745c59 100644
--- a/engines/tetraedge/game/splash_screens.cpp
+++ b/engines/tetraedge/game/splash_screens.cpp
@@ -40,9 +40,9 @@ void SplashScreens::enter() {
_entered = true;
_splashNo = 0;
const char *scriptStr = g_engine->gameIsAmerzone() ? "GUI/PC-MacOSX/Splash0.lua" : "menus/splashes/splash0.lua";
- Common::Path path = g_engine->getCore()->findFile(scriptStr);
- if (Common::File::exists(path)) {
- load(path);
+ TetraedgeFSNode node = g_engine->getCore()->findFile(scriptStr);
+ if (node.exists()) {
+ load(node);
Application *app = g_engine->getApplication();
TeLayout *splash = layoutChecked("splash");
@@ -72,11 +72,11 @@ bool SplashScreens::onAlarm() {
return true;
}
- Common::Path path = g_engine->getCore()->findFile(scriptName);
- if (!Common::File::exists(path)) {
+ TetraedgeFSNode node = g_engine->getCore()->findFile(scriptName);
+ if (!node.exists()) {
onQuitSplash();
} else {
- load(path);
+ load(node);
TeButtonLayout *splash = buttonLayoutChecked("splash");
splash->onMouseClickValidated().add(this, &SplashScreens::onQuitSplash);
diff --git a/engines/tetraedge/game/syberia_game.cpp b/engines/tetraedge/game/syberia_game.cpp
index 9ca07453fdb..fc753400072 100644
--- a/engines/tetraedge/game/syberia_game.cpp
+++ b/engines/tetraedge/game/syberia_game.cpp
@@ -224,7 +224,7 @@ bool SyberiaGame::changeWarp2(const Common::String &zone, const Common::String &
luapath.appendInPlace(scene);
luapath.appendInPlace(".lua");
- if (Common::File::exists(g_engine->getCore()->findFile(luapath))) {
+ if (g_engine->getCore()->findFile(luapath).exists()) {
_luaScript.execute("OnLeave");
_luaContext.removeGlobal("On");
_luaContext.removeGlobal("OnEnter");
@@ -462,17 +462,17 @@ bool SyberiaGame::initWarp(const Common::String &zone, const Common::String &sce
TeCore *core = g_engine->getCore();
- const Common::Path intLuaPath = core->findFile(scenePath.join(Common::String::format("Int%s.lua", scene.c_str())));
- const Common::Path logicLuaPath = core->findFile(scenePath.join(Common::String::format("Logic%s.lua", scene.c_str())));
- const Common::Path setLuaPath = core->findFile(scenePath.join(Common::String::format("Set%s.lua", scene.c_str())));
- const Common::Path forLuaPath = core->findFile(scenePath.join(Common::String::format("For%s.lua", scene.c_str())));
- const Common::Path markerLuaPath = core->findFile(scenePath.join(Common::String::format("Marker%s.lua", scene.c_str())));
+ const TetraedgeFSNode intLuaPath = core->findFile(scenePath.join(Common::String::format("Int%s.lua", scene.c_str())));
+ const TetraedgeFSNode logicLuaPath = core->findFile(scenePath.join(Common::String::format("Logic%s.lua", scene.c_str())));
+ const TetraedgeFSNode setLuaPath = core->findFile(scenePath.join(Common::String::format("Set%s.lua", scene.c_str())));
+ const TetraedgeFSNode forLuaPath = core->findFile(scenePath.join(Common::String::format("For%s.lua", scene.c_str())));
+ const TetraedgeFSNode markerLuaPath = core->findFile(scenePath.join(Common::String::format("Marker%s.lua", scene.c_str())));
- bool intLuaExists = Common::File::exists(intLuaPath);
- bool logicLuaExists = Common::File::exists(logicLuaPath);
- bool setLuaExists = Common::File::exists(setLuaPath);
- bool forLuaExists = Common::File::exists(forLuaPath);
- bool markerLuaExists = Common::File::exists(markerLuaPath);
+ bool intLuaExists = intLuaPath.exists();
+ bool logicLuaExists = logicLuaPath.exists();
+ bool setLuaExists = setLuaPath.exists();
+ bool forLuaExists = forLuaPath.exists();
+ bool markerLuaExists = markerLuaPath.exists();
if (!intLuaExists && !logicLuaExists && !setLuaExists && !forLuaExists && !markerLuaExists) {
debug("No lua scripts for scene %s zone %s", scene.c_str(), zone.c_str());
@@ -500,10 +500,10 @@ bool SyberiaGame::initWarp(const Common::String &zone, const Common::String &sce
_scene.hitObjectGui().unload();
Common::Path geomPath(Common::String::format("scenes/%s/Geometry%s.bin",
zone.c_str(), zone.c_str()));
- geomPath = core->findFile(geomPath);
- if (Common::File::exists(geomPath)) {
+ TetraedgeFSNode geomFile = core->findFile(geomPath);
+ if (geomFile.isReadable()) {
// Syberia 1, load geom bin
- _scene.load(geomPath);
+ _scene.load(geomFile);
} else {
// Syberia 2, load from xml
_scene.loadXml(zone, scene);
diff --git a/engines/tetraedge/module.mk b/engines/tetraedge/module.mk
index 30ac79e4496..4ad639e9a97 100644
--- a/engines/tetraedge/module.mk
+++ b/engines/tetraedge/module.mk
@@ -142,7 +142,8 @@ MODULE_OBJS := \
te/te_xml_parser.o \
te/te_zlib_jpeg.o \
te/te_xml_gui.o \
- metaengine.o
+ metaengine.o \
+ obb_archive.o
ifdef USE_TINYGL
MODULE_OBJS += \
@@ -171,4 +172,4 @@ endif
include $(srcdir)/rules.mk
# Detection objects
-DETECT_OBJS += $(MODULE)/detection.o
+DETECT_OBJS += $(MODULE)/detection.o $(MODULE)/obb_archive.o
diff --git a/engines/tetraedge/obb_archive.cpp b/engines/tetraedge/obb_archive.cpp
new file mode 100644
index 00000000000..5869f48e0b0
--- /dev/null
+++ b/engines/tetraedge/obb_archive.cpp
@@ -0,0 +1,116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/endian.h"
+#include "common/debug.h"
+#include "common/str.h"
+#include "common/file.h"
+#include "common/util.h"
+#include "common/substream.h"
+#include "common/compression/dcl.h"
+#include "tetraedge/obb_archive.h"
+
+namespace Tetraedge {
+
+bool ObbArchive::readFileMap(Common::SeekableReadStream &indexFile, FileMap &files) {
+ byte ver = indexFile.readByte();
+ if (ver != 1) {
+ warning("Unsupported tetraedge OBB version %d", ver);
+ return false;
+ }
+
+ uint32 filecnt = indexFile.readUint32LE();
+
+ for (uint i = 0; i < filecnt; i++) {
+ uint32 namelen = indexFile.readUint32LE();
+
+ if (namelen > 0x8000) {
+ warning("ObbArchive::readFileMap: Name too long: 0x%x",
+ namelen);
+ return false;
+ }
+
+ char *buf = (char *)malloc(namelen + 1);
+ assert(buf);
+ indexFile.read(buf, namelen);
+ buf[namelen] = 0;
+ uint32 offset = indexFile.readUint32LE();
+ uint32 sz = indexFile.readUint32LE();
+ if (offset > indexFile.size() || sz > indexFile.size()
+ || offset + sz > indexFile.size()) {
+ warning("ObbArchive::readFileMap: File outside of container: 0x%x+0x%x > 0x%llx",
+ offset, sz, (unsigned long long) indexFile.size());
+ return false;
+ }
+ files[buf] = FileDescriptor(offset, sz);
+
+ free(buf);
+ }
+
+ return true;
+}
+
+ObbArchive* ObbArchive::open(const Common::Path& obbName) {
+ Common::File indexFile;
+ FileMap files;
+
+ if (!indexFile.open(obbName))
+ return nullptr;
+
+ if (!readFileMap(indexFile, files))
+ return nullptr;
+
+ return new ObbArchive(files, obbName);
+}
+
+bool ObbArchive::hasFile(const Common::Path &path) const {
+ return _files.contains(path.toString('/'));
+}
+
+int ObbArchive::listMembers(Common::ArchiveMemberList &list) const {
+ for (FileMap::const_iterator i = _files.begin(), end = _files.end(); i != end; ++i) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(i->_key, *this)));
+ }
+
+ return _files.size();
+}
+
+const Common::ArchiveMemberPtr ObbArchive::getMember(const Common::Path &path) const {
+ FileMap::const_iterator i = _files.find(path.toString('/'));
+ if (i == _files.end())
+ return nullptr;
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(i->_key, *this));
+}
+
+Common::SeekableReadStream *ObbArchive::createReadStreamForMember(const Common::Path &path) const {
+ Common::String translated = path.toString('/');
+ if (!_files.contains(translated))
+ return nullptr;
+ FileDescriptor desc = _files.getVal(translated);
+
+ Common::File *f = new Common::File();
+ if (!f->open(_obbName))
+ return nullptr;
+
+ return new Common::SeekableSubReadStream(f, desc._fileOffset, desc._fileOffset + desc._fileSize, DisposeAfterUse::YES);
+}
+}
diff --git a/engines/tetraedge/obb_archive.h b/engines/tetraedge/obb_archive.h
new file mode 100644
index 00000000000..b68813a4f90
--- /dev/null
+++ b/engines/tetraedge/obb_archive.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TETRAEDGE_OBB_ARCHIVE_H
+#define TETRAEDGE_OBB_ARCHIVE_H
+
+#include "common/archive.h"
+#include "common/ptr.h"
+#include "common/stream.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+namespace Tetraedge {
+
+class ObbArchive : public Common::Archive {
+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::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
+
+ // Similar to FileDescriptionBin but in native-endian and native strings.
+ struct FileDescriptor {
+ FileDescriptor() : _fileOffset(0), _fileSize(0) {}
+ FileDescriptor(uint32 offset,
+ uint32 size) : _fileOffset(offset), _fileSize(size) {}
+
+ uint32 _fileOffset;
+ uint32 _fileSize;
+ };
+
+ typedef Common::HashMap<Common::String, FileDescriptor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+
+ static bool readFileMap(Common::SeekableReadStream &indexFile, FileMap &files);
+ static ObbArchive* open(const Common::Path& obbName);
+
+private:
+ ObbArchive(const FileMap& files,
+ const Common::Path& obbName) : _files(files), _obbName(obbName) {}
+
+ FileMap _files;
+ Common::Path _obbName;
+};
+}
+
+#endif
diff --git a/engines/tetraedge/te/te_3d_texture.cpp b/engines/tetraedge/te/te_3d_texture.cpp
index e06e1763a63..aa15686e1b3 100644
--- a/engines/tetraedge/te/te_3d_texture.cpp
+++ b/engines/tetraedge/te/te_3d_texture.cpp
@@ -44,20 +44,20 @@ bool Te3DTexture::hasAlpha() const {
}
/*static*/
-TeIntrusivePtr<Te3DTexture> Te3DTexture::load2(const Common::Path &path, bool alphaOnly) {
- const Common::Path fullPath = path.append(".3dtex");
+TeIntrusivePtr<Te3DTexture> Te3DTexture::load2(const TetraedgeFSNode &node, bool alphaOnly) {
+ const Common::Path fullPath = node.getPath().append(".3dtex");
TeResourceManager *resMgr = g_engine->getResourceManager();
if (!resMgr->exists(fullPath)) {
TeIntrusivePtr<Te3DTexture> retval(makeInstance());
- if (!Common::File::exists(path))
- warning("Request to load unreadable texture %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!node.exists())
+ warning("Request to load unreadable texture %s", node.toString().c_str());
if (alphaOnly)
retval->setLoadAlphaOnly();
- bool result = retval->load(path);
+ bool result = retval->load(node);
if (!result)
- warning("Failed loading texture %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ warning("Failed loading texture %s", node.toString().c_str());
retval->setAccessName(fullPath);
resMgr->addResource(retval.get());
@@ -67,11 +67,11 @@ TeIntrusivePtr<Te3DTexture> Te3DTexture::load2(const Common::Path &path, bool al
}
}
-bool Te3DTexture::load(const Common::Path &path) {
+bool Te3DTexture::load(const TetraedgeFSNode &node) {
TeResourceManager *resmgr = g_engine->getResourceManager();
- TeIntrusivePtr<TeImage> img = resmgr->getResource<TeImage>(path);
+ TeIntrusivePtr<TeImage> img = resmgr->getResource<TeImage>(node);
bool result = load(*img);
- setAccessName(path.append(".3dtex"));
+ setAccessName(node.getPath().append(".3dtex"));
return result;
}
diff --git a/engines/tetraedge/te/te_3d_texture.h b/engines/tetraedge/te/te_3d_texture.h
index 22e0cddd6ac..1ef73fc6f47 100644
--- a/engines/tetraedge/te/te_3d_texture.h
+++ b/engines/tetraedge/te/te_3d_texture.h
@@ -48,11 +48,11 @@ public:
TeImage::Format getFormat() const { return _format; }
bool hasAlpha() const;
- bool load(const Common::Path &path);
+ bool load(const TetraedgeFSNode &path);
virtual bool load(const TeImage &img) = 0;
// The original passes a GL enum param, but it's only ever GL_INVALID or GL_ALPHA.
// Simplify to avoid leaking gl types.
- static TeIntrusivePtr<Te3DTexture> load2(const Common::Path &path, bool alphaOnly);
+ static TeIntrusivePtr<Te3DTexture> load2(const TetraedgeFSNode &node, bool alphaOnly);
static TeVector2s32 optimisedSize(const TeVector2s32 &size);
diff --git a/engines/tetraedge/te/te_bezier_curve.cpp b/engines/tetraedge/te/te_bezier_curve.cpp
index 18e5065012f..fb8a221ebba 100644
--- a/engines/tetraedge/te/te_bezier_curve.cpp
+++ b/engines/tetraedge/te/te_bezier_curve.cpp
@@ -208,29 +208,28 @@ void TeBezierCurve::deserialize(Common::ReadStream &stream, TeBezierCurve &curve
}
}
-void TeBezierCurve::loadBin(const Common::Path &path) {
- Common::File file;
- file.open(path);
- Common::String fname = path.baseName();
+void TeBezierCurve::loadBin(TetraedgeFSNode &node) {
+ Common::ScopedPtr<Common::SeekableReadStream> file(node.createReadStream());
+ Common::String fname = node.getPath().baseName();
if (fname.size() < 4)
error("TeBezierCurve::loadBin fname %s is too short", fname.c_str());
setName(fname.substr(0, fname.size() - 4));
// Load position / rotation / size
- Te3DObject2::deserialize(file, *this, false);
+ Te3DObject2::deserialize(*file, *this, false);
// Then it resets them?
setPosition(TeVector3f32());
setRotation(TeQuaternion());
setSize(TeVector3f32(1, 1, 1));
_lengthNeedsUpdate = true;
- uint32 npoints = file.readUint32LE();
+ uint32 npoints = file->readUint32LE();
if (npoints > 1000000)
error("TeBezierCurve::loadBin improbable number of control ponts %d", npoints);
for (uint i = 0; i < npoints; i++) {
TeVector3f32 vec;
- TeVector3f32::deserialize(file, vec);
+ TeVector3f32::deserialize(*file, vec);
_controlPoints.push_back(vec);
}
}
diff --git a/engines/tetraedge/te/te_bezier_curve.h b/engines/tetraedge/te/te_bezier_curve.h
index 704d33f513c..d703e470970 100644
--- a/engines/tetraedge/te/te_bezier_curve.h
+++ b/engines/tetraedge/te/te_bezier_curve.h
@@ -26,6 +26,7 @@
#include "tetraedge/te/te_3d_object2.h"
#include "tetraedge/te/te_references_counter.h"
+#include "tetraedge/tetraedge.h"
namespace Tetraedge {
@@ -50,7 +51,7 @@ public:
static void serialize(Common::WriteStream &stream, const TeBezierCurve &curve);
static void deserialize(Common::ReadStream &stream, TeBezierCurve &curve);
- void loadBin(const Common::Path &path);
+ void loadBin(TetraedgeFSNode &node);
const Common::Array<TeVector3f32> &controlPoints() { return _controlPoints; }
uint numIterations() const { return _numIterations; }
diff --git a/engines/tetraedge/te/te_camera.cpp b/engines/tetraedge/te/te_camera.cpp
index 35fe552b54e..11b82cfe8c0 100644
--- a/engines/tetraedge/te/te_camera.cpp
+++ b/engines/tetraedge/te/te_camera.cpp
@@ -169,8 +169,8 @@ void TeCamera::loadXml(const Common::Path &path) {
setName(path.baseName());
_projectionMatrixType = 3;
TeCore *core = g_engine->getCore();
- Common::Path cameraPath = core->findFile(path);
- if (!Common::File::exists(cameraPath)) {
+ TetraedgeFSNode cameraNode = core->findFile(path);
+ if (!cameraNode.isReadable()) {
//
// WORKAROUND: scenes/A3_Village/34015 has Camera34010, not 34015
//
@@ -179,17 +179,17 @@ void TeCamera::loadXml(const Common::Path &path) {
if (pos != Common::String::npos) {
spath.replace(pos + 4, 1, "0");
}
- cameraPath = core->findFile(Common::Path(spath, '/'));
+ cameraNode = core->findFile(Common::Path(spath, '/'));
}
- if (!Common::File::exists(cameraPath)) {
- warning("Can't open camera data %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!cameraNode.isReadable()) {
+ warning("Can't open camera data %s", cameraNode.toString().c_str());
}
TeCameraXmlParser parser;
parser._cam = this;
- if (!parser.loadFile(cameraPath))
- error("TeCamera::loadXml: can't load file %s", cameraPath.toString(Common::Path::kNativeSeparator).c_str());
+ if (!cameraNode.loadXML(parser))
+ error("TeCamera::loadXml: can't load file %s", cameraNode.toString().c_str());
if (!parser.parse())
- error("TeCamera::loadXml: error parsing %s", cameraPath.toString(Common::Path::kNativeSeparator).c_str());
+ error("TeCamera::loadXml: error parsing %s", cameraNode.toString().c_str());
}
void TeCamera::orthogonalParams(float left, float right, float top, float bottom) {
diff --git a/engines/tetraedge/te/te_core.cpp b/engines/tetraedge/te/te_core.cpp
index 6f002c05c57..ffbad1ede04 100644
--- a/engines/tetraedge/te/te_core.cpp
+++ b/engines/tetraedge/te/te_core.cpp
@@ -24,6 +24,7 @@
#include "common/debug.h"
#include "common/config-manager.h"
#include "common/language.h"
+#include "common/tokenizer.h"
#include "tetraedge/te/te_core.h"
@@ -74,10 +75,6 @@ void TeCore::create() {
_resourcesRoot = Common::FSDirectory(resNode, 5, false, false, true);
}
-Common::FSNode TeCore::getFSNode(const Common::Path &path) const {
- return Common::FSNode(Common::Path(_resourcesRoot.getFSNode().getPath()).join(path));
-}
-
TeICodec *TeCore::createVideoCodec(const Common::String &extn) {
// The original engine has more formats and even checks for alpha maps,
// but it never uses them.
@@ -98,8 +95,8 @@ TeICodec *TeCore::createVideoCodec(const Common::String &extn) {
return nullptr;
}
-TeICodec *TeCore::createVideoCodec(const Common::Path &path) {
- const Common::String filename = path.baseName();
+TeICodec *TeCore::createVideoCodec(const TetraedgeFSNode &node) {
+ const Common::String filename = node.getPath().baseName();
if (!filename.contains('.'))
return nullptr;
Common::String extn = filename.substr(filename.findLastOf('.') + 1);
@@ -146,109 +143,92 @@ bool TeCore::onActivityTrackingAlarm() {
error("TODO: Implement TeCore::onActivityTrackingAlarm");
}
-Common::Path TeCore::findFile(const Common::Path &path) const {
- if (Common::File::exists(path))
- return path;
+static bool _checkFileFlag(const Common::String &fname, const Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> &activeTags) {
+ Common::StringTokenizer tokenizer(fname, "-");
+ while(!tokenizer.empty())
+ if (activeTags.getValOrDefault(tokenizer.nextToken(), false))
+ return true;
+ return false;
+}
- Common::String fname = path.baseName();
+static void _findFileRecursively(const TetraedgeFSNode &parent,
+ const Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> &activeTags,
+ const Common::String &fname,
+ Common::Array<TetraedgeFSNode> &foundFiles,
+ int maxDepth) {
+ if (parent.getChild(Common::Path(fname, '/')).exists()) {
+ foundFiles.push_back(parent.getChild(Common::Path(fname, '/')));
+ }
+
+ if (maxDepth <= 0)
+ return;
+
+ TetraedgeFSList list;
+ if (!parent.getChildren(list))
+ return;
+
+ for (TetraedgeFSList::const_iterator it = list.begin(); it != list.end(); it++)
+ if (_checkFileFlag(it->getName(), activeTags))
+ _findFileRecursively(*it, activeTags, fname, foundFiles, maxDepth - 1);
+}
+
+TetraedgeFSNode TeCore::findFile(const Common::Path &path, bool quiet) const {
+ Common::Array<TetraedgeFSNode> dirNodes;
+ const Common::Path dir = path.getParent();
+
+ TetraedgeFSNode node;
+
+ const Common::Array<Common::Archive *> &roots = g_engine->getRootArchives();
+ for (Common::Archive *const archive : roots) {
+ TetraedgeFSNode archiveNode(archive);
+ node = archiveNode.getChild(path);
+ if (node.exists())
+ return node;
+ dirNodes.push_back(archiveNode.getChild(dir));
+ }
+
+ Common::String fname = path.getLastComponent().toString();
// Slight HACK: Remove 'comments' used to specify animated pngs
if (fname.contains('#'))
fname = fname.substr(0, fname.find('#'));
- const Common::Path dir = path.getParent();
- static const Common::Path pathSuffixes[] = {
- "", // no suffix
- "PC-MacOSX",
- "PC-PS3-Android-MacOSX",
- "PC-MacOSX-Android-iPhone-iPad",
- "PC-MacOSX-Android-iPhone-iPad/HD",
- "PC-Android-MacOSX-iPhone-iPad",
- "PC-MacOSX-Xbox360-PS3",
- "PC-MacOSX-PS3-Xbox360",
- "PC-MacOSX-Xbox360-PS3/PC-MacOSX",
- "PC-MacOSX-MacOSXAppStore-Android-iPhone-iPad",
- "PC-MacOSX-MacOSXAppStore-Xbox360-Android-iPad-iPhone",
- "Android-iPhone-iPad-PC-MacOSX",
- "Android-MacOSX",
- "Full",
- "Part1-Full",
- "Part2-Full-Part1",
- "Part3-Full-Part1",
- "HD",
- "HD/PC-MacOSX-Xbox360-PS3",
- "PC-PS3-Android-MacOSX-iPhone-iPad", // iOS Syb 1
- "Android-iPhone-iPad", // iOS Syb 1
- "Android-iPhone-iPad/HD", // iOS Syb 1
- "HD/Android-iPhone-iPad", // iOS Syb 1
- "iPhone-iPad", // iOS Syb 1
- "iPhone-iPad/HD", // iOS Syb 1
- "iPhone-iPad/HD/Freemium", // iOS Syb 1
- "Android-MacOSX-iPhone-iPad", // iOS Syb 1
- "Freemium-BUKAFree/HD", // iOS Syb 1
- "Part3-Full", // iOS Syb 1 paid
- "DefaultDistributor-Freemium", // iOS Syb 1 paid
- "iPhone-iPad/DefaultDistributor", // iOS Syb 1 paid
- "Android-iPhone-iPad/iPhone-iPad", // iOS Syb 2
- "PC-MacOSX-Android-iPhone-iPad", // iOS Syb 2
- "Part2-Full", // Amerzone
- "Part3-Full", // Amerzone
- "Full/HD", // Amerzone
- "Part1-Full/PC-MacOSX/DefaultDistributor", // Amerzone
- "Part2-Full/PC-MacOSX/DefaultDistributor", // Amerzone
- "Part3-Full/PC-MacOSX/DefaultDistributor", // Amerzone
- "Part1-Full/iPhone-iPad-Android", // Amerzone
- "Part2-Full/iPhone-iPad-Android", // Amerzone
- "Part3-Full/iPhone-iPad-Android", // Amerzone
- "Part1-Part2-Part3-Full/HD", // Amerzone
- "Part1-Part2-Part3-Full", // Amerzone
- "Part1-Full/HD", // Amerzone
- "Part2-Full/HD", // Amerzone
- "Part3-Full/HD", // Amerzone
- };
-
- static const Common::Path langs[] = {
- Common::Path(language()),
- "en",
- "de-es-fr-it-en",
- "en-es-fr-de-it",
- "es-en-fr-de-it",
- "de-en-es-fr-it",
- ""
- };
-
- // Note: the audio files for a few videos have a weird path
- // structure where the language is first, followed by some other
- // part names, followed by the file.
- // Dialogs have part stuff followed by lang, so we have to try
- // adding language before *and* after the suffix.
-
- for (int langtype = 0; langtype < ARRAYSIZE(langs); langtype++) {
- const Common::Path &lang = langs[langtype];
- for (int i = 0; i < ARRAYSIZE(pathSuffixes); i++) {
- Common::Path suffix = pathSuffixes[i];
-
- Common::Path testPath = dir;
- if (!suffix.empty())
- testPath.joinInPlace(suffix);
- if (!lang.empty())
- testPath.joinInPlace(lang);
- testPath.joinInPlace(fname);
- if (Common::File::exists(testPath))
- return testPath;
-
- // also try the other way around
- if (!lang.empty() && !suffix.empty()) {
- testPath = dir.join(lang).joinInPlace(suffix).join(fname);
- if (Common::File::exists(testPath))
- return testPath;
+ Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> activeFlags;
+
+ for (Common::HashMap<Common::String, Common::String, Common::CaseSensitiveString_Hash, Common::CaseSensitiveString_EqualTo>::const_iterator it = _fileSystemFlags.begin();
+ it != _fileSystemFlags.end(); it++)
+ activeFlags[it->_value] = true;
+
+ // This is to keep behivour changes small when we migrated from old system.
+ // I'm not sure if it's needed
+ // TODO: Figure out what to do with this. Right now we set flag
+ // to "SD" but use assets from "HD". This seems to give the best
+ // results but is fundamentally wrong.
+ activeFlags.erase("SD");
+ activeFlags["HD"] = true;
+
+ for (uint dirNode = 0; dirNode < dirNodes.size(); dirNode++) {
+ Common::Array<TetraedgeFSNode> foundFiles;
+ _findFileRecursively(dirNodes[dirNode], activeFlags, fname, foundFiles, 5);
+ if (foundFiles.empty())
+ continue;
+ TetraedgeFSNode best = foundFiles[0];
+ int bestDepth = best.getDepth();
+ for (uint i = 1; i < foundFiles.size(); i++) {
+ int depth = foundFiles[i].getDepth();
+ if (depth > bestDepth) {
+ bestDepth = depth;
+ best = foundFiles[i];
}
}
+
+ return best;
}
// Didn't find it at all..
- debug("TeCore::findFile Searched but didn't find %s", path.toString(Common::Path::kNativeSeparator).c_str());
- return path;
+ if (!quiet)
+ debug("TeCore::findFile Searched but didn't find %s", path.toString().c_str());
+ return TetraedgeFSNode(nullptr, path);
}
} // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_core.h b/engines/tetraedge/te/te_core.h
index 360b333b913..1008b4e06c8 100644
--- a/engines/tetraedge/te/te_core.h
+++ b/engines/tetraedge/te/te_core.h
@@ -40,7 +40,7 @@ public:
void addLoc(TeILoc *loc);
void create();
- TeICodec *createVideoCodec(const Common::Path &path);
+ TeICodec *createVideoCodec(const TetraedgeFSNode &node);
TeICodec *createVideoCodec(const Common::String &extn);
const Common::String &fileFlagSystemFlag(const Common::String &name) const;
bool fileFlagSystemFlagsContains(const Common::String &name) const;
@@ -58,8 +58,8 @@ public:
// 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
// to them, so here we are.
- Common::Path findFile(const Common::Path &path) const;
- Common::FSNode getFSNode(const Common::Path &path) const;
+ TetraedgeFSNode findFile(const Common::Path &path, bool quiet = false) const;
+ TetraedgeFSNode getFSNode(const Common::Path &path) const;
bool _coreNotReady;
diff --git a/engines/tetraedge/te/te_font2.cpp b/engines/tetraedge/te/te_font2.cpp
index 2df962d1051..68c8cbcb650 100644
--- a/engines/tetraedge/te/te_font2.cpp
+++ b/engines/tetraedge/te/te_font2.cpp
@@ -42,42 +42,46 @@ bool TeFont2::load(const Common::Path &path) {
return true; // already open
TeCore *core = g_engine->getCore();
- Common::Path fontPath = core->findFile(path);
+ TetraedgeFSNode node = core->findFile(path);
+ return load(node);
+}
+
+bool TeFont2::load(const TetraedgeFSNode &node) {
+ const Common::Path path = node.getPath();
unload();
setAccessName(path);
_loadedPath = path;
- if (!Common::File::exists(fontPath)) {
- warning("TeFont2::load: Can't read from %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!node.exists()) {
+ warning("TeFont2::load: Can't read from %s", node.toString().c_str());
return false;
}
- Common::File file;
- file.open(fontPath);
+ Common::ScopedPtr<Common::SeekableReadStream> file(node.createReadStream());
- if (!Te3DObject2::loadAndCheckFourCC(file, "TESF")) {
- warning("TeFont2::load: Invalid magic in %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!Te3DObject2::loadAndCheckFourCC(*file, "TESF")) {
+ warning("TeFont2::load: Invalid magic in %s", node.toString().c_str());
return false;
}
- _numChars = file.readUint32LE();
+ _numChars = file->readUint32LE();
if (_numChars > 65535)
error("TeFont2::load: improbable number of char points %d", _numChars);
- TeVector2s32::deserialize(file, _somePt);
- TeVector3f32::deserialize(file, _someVec);
- _hasKernData = (file.readByte() != 0);
+ TeVector2s32::deserialize(*file, _somePt);
+ TeVector3f32::deserialize(*file, _someVec);
+ _hasKernData = (file->readByte() != 0);
if (_hasKernData) {
- uint32 numKernData = file.readUint32LE();
+ uint32 numKernData = file->readUint32LE();
if (numKernData > 10000)
error("TeFont2::load: improbable number of kerning points %d", numKernData);
for (uint32 i = 0; i < numKernData; i++) {
KernChars kc;
TeVector3f32 vec;
- kc._c1 = file.readUint32LE();
- kc._c2 = file.readUint32LE();
- vec.x() = file.readFloatLE();
- vec.y() = file.readFloatLE();
+ kc._c1 = file->readUint32LE();
+ kc._c2 = file->readUint32LE();
+ vec.x() = file->readFloatLE();
+ vec.y() = file->readFloatLE();
_kernData[kc] = vec;
//debug("KernChars: '%c'-'%c' (%.2f, %.2f)", (char)kc._c1, (char)kc._c2, vec.x(), vec.y());
}
@@ -85,19 +89,19 @@ bool TeFont2::load(const Common::Path &path) {
for (uint32 i = 0; i < _numChars; i++) {
GlyphData2 g;
- g._xSz = file.readFloatLE();
- g._ySz = file.readFloatLE();
+ g._xSz = file->readFloatLE();
+ g._ySz = file->readFloatLE();
_maxHeight = MAX(_maxHeight, g._ySz);
- g._xOff = file.readFloatLE();
- g._yOff = file.readFloatLE();
- g._xAdvance = file.readFloatLE();
+ g._xOff = file->readFloatLE();
+ g._yOff = file->readFloatLE();
+ g._xAdvance = file->readFloatLE();
// TODO: What are these other floats?
for (uint j = 0; j < 3; j++)
- g._floats[j] = file.readFloatLE();
- g._vec.x() = file.readFloatLE();
- g._vec.y() = file.readFloatLE();
+ g._floats[j] = file->readFloatLE();
+ g._vec.x() = file->readFloatLE();
+ g._vec.y() = file->readFloatLE();
_glyphs.push_back(g);
- uint32 charNo = file.readUint32LE();
+ uint32 charNo = file->readUint32LE();
_uintArray.push_back(charNo);
/*
if (i >= 35 && i <= 127)
@@ -107,8 +111,8 @@ bool TeFont2::load(const Common::Path &path) {
*/
}
- if (!_texture.load(file, "png")) {
- warning("Invalid png data in %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!_texture.load(*file, "png")) {
+ warning("Invalid png data in %s", node.toString().c_str());
return false;
}
diff --git a/engines/tetraedge/te/te_font2.h b/engines/tetraedge/te/te_font2.h
index 7a8343d47a3..eb395f5fd6b 100644
--- a/engines/tetraedge/te/te_font2.h
+++ b/engines/tetraedge/te/te_font2.h
@@ -71,6 +71,7 @@ public:
virtual ~TeFont2();
bool load(const Common::Path &path);
+ bool load(const TetraedgeFSNode &node);
void unload();
Graphics::Font *getAtSize(uint size) override;
diff --git a/engines/tetraedge/te/te_font3.cpp b/engines/tetraedge/te/te_font3.cpp
index fb796f25ad7..0a95c1b6edc 100644
--- a/engines/tetraedge/te/te_font3.cpp
+++ b/engines/tetraedge/te/te_font3.cpp
@@ -39,14 +39,14 @@ Graphics::Font *TeFont3::getAtSize(uint size) {
if (_fonts.contains(size))
return _fonts.getVal(size);
- if (!_fontFile.isOpen())
+ if (!_fontFile)
load(getAccessName());
- if (!_fontFile.isOpen())
+ if (!_fontFile)
error("TeFont3::: Couldn't open font file %s.", getAccessName().toString(Common::Path::kNativeSeparator).c_str());
- _fontFile.seek(0);
- Graphics::Font *newFont = Graphics::loadTTFFont(&_fontFile, DisposeAfterUse::NO, size, Graphics::kTTFSizeModeCharacter, 0, 0, Graphics::kTTFRenderModeNormal);
+ _fontFile->seek(0);
+ Graphics::Font *newFont = Graphics::loadTTFFont(_fontFile.get(), DisposeAfterUse::NO, size, Graphics::kTTFSizeModeCharacter, 0, 0, Graphics::kTTFRenderModeNormal);
if (!newFont) {
error("TeFont3::: Couldn't load font %s at size %d.", _loadedPath.toString(Common::Path::kNativeSeparator).c_str(), size);
}
@@ -55,24 +55,30 @@ Graphics::Font *TeFont3::getAtSize(uint size) {
}
bool TeFont3::load(const Common::Path &path) {
+ if (_loadedPath == path && _fontFile)
+ return true; // already open
+
TeCore *core = g_engine->getCore();
- const Common::Path fontPath = core->findFile(path);
- if (_loadedPath == fontPath && _fontFile.isOpen())
+ TetraedgeFSNode node = core->findFile(path);
+ return load(node);
+}
+
+bool TeFont3::load(const TetraedgeFSNode &node) {
+ const Common::Path fontPath = node.getPath();
+ if (_loadedPath == fontPath && _fontFile)
return true; // already open
setAccessName(fontPath);
_loadedPath = fontPath;
- if (!Common::File::exists(fontPath)) {
- warning("TeFont3::load: Can't find %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ if (!node.exists()) {
+ warning("TeFont3::load: Can't find %s", node.toString().c_str());
return false;
}
- if (_fontFile.isOpen())
- _fontFile.close();
-
- if (!_fontFile.open(fontPath)) {
- warning("TeFont3::load: can't open %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ _fontFile.reset(node.createReadStream());
+ if (!_fontFile) {
+ warning("TeFont3::load: can't open %s", node.toString().c_str());
return false;
}
return true;
@@ -83,7 +89,7 @@ void TeFont3::unload() {
delete entry._value;
}
_fonts.clear();
- _fontFile.close();
+ _fontFile.reset();
}
} // end namespace Tetraedge
diff --git a/engines/tetraedge/te/te_font3.h b/engines/tetraedge/te/te_font3.h
index 980278d0569..39551596dd2 100644
--- a/engines/tetraedge/te/te_font3.h
+++ b/engines/tetraedge/te/te_font3.h
@@ -52,6 +52,7 @@ public:
virtual ~TeFont3();
bool load(const Common::Path &path);
+ bool load(const TetraedgeFSNode &node);
void unload();
private:
@@ -61,7 +62,7 @@ private:
}
Graphics::Font *getAtSize(uint size) override;
- Common::File _fontFile;
+ Common::ScopedPtr<Common::SeekableReadStream> _fontFile;
Common::HashMap<uint, Graphics::Font *> _fonts;
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 be8885e4970..007c828856b 100644
--- a/engines/tetraedge/te/te_free_move_zone.cpp
+++ b/engines/tetraedge/te/te_free_move_zone.cpp
@@ -182,26 +182,31 @@ void TeFreeMoveZone::buildAStar() {
}
bool TeFreeMoveZone::loadAStar(const Common::Path &path, const TeVector2s32 &size) {
- Common::Path aStarPath = g_engine->getCore()->findFile(path);
- Common::File file;
- if (!file.open(aStarPath)) {
- warning("[TeFreeMoveZone::loadAStar] Can't open file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
+ TetraedgeFSNode node = g_engine->getCore()->findFile(path);
+ Common::ScopedPtr<Common::SeekableReadStream> file;
+ if (!node.isReadable()) {
+ warning("[TeFreeMoveZone::loadAStar] Can't open file : %s.", path.toString().c_str());
+ return false;
+ }
+ file.reset(node.createReadStream());
+ if (!file) {
+ warning("[TeFreeMoveZone::loadAStar] Can't open file : %s.", path.toString().c_str());
return false;
}
TeVector2s32 readSize;
- readSize.deserialize(file, readSize);
+ readSize.deserialize(*file, readSize);
if (size != readSize) {
warning("[TeFreeMoveZone::loadAStar] Wrong file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
return false;
}
- uint32 bytes = file.readUint32LE();
+ uint32 bytes = file->readUint32LE();
if (bytes > 100000)
error("Improbable size %d for compressed astar data", bytes);
unsigned long decompBytes = size._x * size._y;
byte *buf = new byte[bytes];
byte *outBuf = new byte[decompBytes];
- file.read(buf, bytes);
+ file->read(buf, bytes);
bool result = Common::inflateZlib(outBuf, &decompBytes, buf, bytes);
delete [] buf;
if (result) {
@@ -608,15 +613,14 @@ TeActZone *TeFreeMoveZone::isInZone(const TeVector3f32 &pt) {
bool TeFreeMoveZone::loadBin(const Common::Path &path, const Common::Array<TeBlocker> *blockers,
const Common::Array<TeRectBlocker> *rectblockers, const Common::Array<TeActZone> *actzones,
const TeVector2f32 &gridSize) {
- Common::Path binPath = g_engine->getCore()->findFile(path);
- if (!Common::File::exists(binPath)) {
- warning("[TeFreeMoveZone::loadBin] Can't open file : %s.", binPath.baseName().c_str());
+ TetraedgeFSNode node = g_engine->getCore()->findFile(path);
+ if (!node.isReadable()) {
+ warning("[TeFreeMoveZone::loadBin] Can't open file : %s.", node.getName().c_str());
return false;
}
_aszGridPath = path.append(".aszgrid");
- Common::File file;
- file.open(binPath);
- return loadBin(file, blockers, rectblockers, actzones, gridSize);
+ Common::ScopedPtr<Common::SeekableReadStream> file(node.createReadStream());
+ return loadBin(*file, blockers, rectblockers, actzones, gridSize);
}
bool TeFreeMoveZone::loadBin(Common::ReadStream &stream, const Common::Array<TeBlocker> *blockers,
diff --git a/engines/tetraedge/te/te_i_codec.h b/engines/tetraedge/te/te_i_codec.h
index 29909d34290..bb2f9bb9afe 100644
--- a/engines/tetraedge/te/te_i_codec.h
+++ b/engines/tetraedge/te/te_i_codec.h
@@ -36,7 +36,7 @@ public:
TeICodec() {};
virtual ~TeICodec() {};
- virtual bool load(const Common::Path &path) = 0;
+ virtual bool load(const TetraedgeFSNode &node) = 0;
virtual uint width() = 0;
virtual uint height() = 0;
virtual int nbFrames() = 0;
diff --git a/engines/tetraedge/te/te_image.cpp b/engines/tetraedge/te/te_image.cpp
index 95be9a7b860..f3a77f789cd 100644
--- a/engines/tetraedge/te/te_image.cpp
+++ b/engines/tetraedge/te/te_image.cpp
@@ -101,11 +101,11 @@ bool TeImage::isExtensionSupported(const Common::Path &path) {
error("TODO: Implement TeImage::isExtensionSupported");
}
-bool TeImage::load(const Common::Path &path) {
+bool TeImage::load(const TetraedgeFSNode &node) {
TeCore *core = g_engine->getCore();
- TeICodec *codec = core->createVideoCodec(path);
- if (!Common::File::exists(path) || !codec->load(path)) {
- warning("TeImage::load: Failed to load %s.", path.toString(Common::Path::kNativeSeparator).c_str());
+ TeICodec *codec = core->createVideoCodec(node);
+ if (!node.exists() || !codec->load(node)) {
+ warning("TeImage::load: Failed to load %s.", node.toString().c_str());
delete codec;
return false;
}
@@ -114,7 +114,7 @@ bool TeImage::load(const Common::Path &path) {
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.", path.toString(Common::Path::kNativeSeparator).c_str());
+ error("TeImage::load: Failed to update from %s.", node.toString().c_str());
}
delete codec;
return true;
diff --git a/engines/tetraedge/te/te_image.h b/engines/tetraedge/te/te_image.h
index 8266d410244..c4332384389 100644
--- a/engines/tetraedge/te/te_image.h
+++ b/engines/tetraedge/te/te_image.h
@@ -35,6 +35,8 @@
#include "tetraedge/te/te_vector2s32.h"
#include "tetraedge/te/te_resource.h"
+#include "tetraedge/tetraedge.h"
+
namespace Tetraedge {
class TeImage : public TeResource, public Graphics::ManagedSurface {
@@ -75,7 +77,7 @@ public:
void fill(byte r, byte g, byte b, byte a);
void getBuff(uint x, uint y, byte *pout, uint w, uint h);
bool isExtensionSupported(const Common::Path &path);
- bool load(const Common::Path &path);
+ bool load(const TetraedgeFSNode &node);
bool load(Common::SeekableReadStream &stream, const Common::String &type);
bool save(const Common::Path &path, enum SaveType type);
int serialize(Common::WriteStream &stream);
diff --git a/engines/tetraedge/te/te_images_sequence.cpp b/engines/tetraedge/te/te_images_sequence.cpp
index fb9dfddd047..8b2fe6b641a 100644
--- a/engines/tetraedge/te/te_images_sequence.cpp
+++ b/engines/tetraedge/te/te_images_sequence.cpp
@@ -45,30 +45,26 @@ bool TeImagesSequence::matchExtension(const Common::String &extn) {
return extn == "anim" || extn == "animcached";
}
-static bool compareNodes(const Common::FSNode &left, const Common::FSNode &right) {
+static bool compareNodes(const TetraedgeFSNode &left, const TetraedgeFSNode &right) {
return left.getPath().toString('/') < right.getPath().toString('/');
}
-bool TeImagesSequence::load(const Common::Path &directory) {
- Common::FSNode dir = g_engine->getCore()->getFSNode(directory);
-
- const Common::String path = directory.toString('/');
+bool TeImagesSequence::load(const TetraedgeFSNode &dir) {
if (!dir.isDirectory()) {
- warning("TeImagesSequence::load:: not a directory %s", directory.toString(Common::Path::kNativeSeparator).c_str());
+ warning("TeImagesSequence::load:: not a directory %s", dir.toString().c_str());
return false;
}
- Common::FSList children;
+ TetraedgeFSList children;
if (!dir.getChildren(children, Common::FSNode::kListFilesOnly) || children.empty()) {
- warning("TeImagesSequence::load:: couldn't get children of %s", directory.toString(Common::Path::kNativeSeparator).c_str());
+ warning("TeImagesSequence::load:: couldn't get children of %s", dir.toString().c_str());
return false;
}
Common::sort(children.begin(), children.end(), compareNodes);
- if (!SearchMan.hasArchive(path))
- SearchMan.addDirectory(path, directory);
+ dir.maybeAddToSearchMan();
- for (Common::FSNode &child : children) {
+ for (TetraedgeFSNode &child : children) {
const Common::String fileName = child.getName();
if (fileName.size() <= 10 || fileName.substr(fileName.size() - 7) != "fps.png")
@@ -84,7 +80,7 @@ bool TeImagesSequence::load(const Common::Path &directory) {
Common::SeekableReadStream *stream = child.createReadStream();
if (!stream) {
- warning("TeImagesSequence::load can't open %s", child.getPath().toString(Common::Path::kNativeSeparator).c_str());
+ warning("TeImagesSequence::load can't open %s", child.toString().c_str());
continue;
}
@@ -93,7 +89,7 @@ bool TeImagesSequence::load(const Common::Path &directory) {
if (!_width || (_width < 100 && _height < 100)) {
Image::PNGDecoder png;
if (!png.loadStream(*stream)) {
- warning("Image sequence failed to load png %s", child.getPath().toString(Common::Path::kNativeSeparator).c_str());
+ warning("Image sequence failed to load png %s", child.toString().c_str());
delete stream;
return false;
}
diff --git a/engines/tetraedge/te/te_images_sequence.h b/engines/tetraedge/te/te_images_sequence.h
index 92b004c1f12..0f9f1f1a402 100644
--- a/engines/tetraedge/te/te_images_sequence.h
+++ b/engines/tetraedge/te/te_images_sequence.h
@@ -37,7 +37,7 @@ public:
TeImagesSequence();
virtual ~TeImagesSequence();
- virtual bool load(const Common::Path &path) override;
+ virtual bool load(const TetraedgeFSNode &node) override;
virtual uint width() override { return _width; }
virtual uint height() override { return _height; }
virtual int nbFrames() override { return _files.size(); }
@@ -63,7 +63,7 @@ private:
float _frameRate;
uint _width;
uint _height;
- Common::Array<Common::FSNode> _files;
+ Common::Array<TetraedgeFSNode> _files;
Common::Array<Graphics::ManagedSurface *> _cachedSurfaces;
uint _curFrame;
};
diff --git a/engines/tetraedge/te/te_interpolation.cpp b/engines/tetraedge/te/te_interpolation.cpp
index 52a5db2c839..8cc916953c3 100644
--- a/engines/tetraedge/te/te_interpolation.cpp
+++ b/engines/tetraedge/te/te_interpolation.cpp
@@ -37,12 +37,12 @@ void TeInterpolation::load(Common::ReadStream &stream) {
_array[i] = stream.readFloatLE();
}
-void TeInterpolation::load(Common::Path &path) {
- Common::File f;
- if (!f.open(path))
- error("Couldn't open %s", path.toString(Common::Path::kNativeSeparator).c_str());
+void TeInterpolation::load(TetraedgeFSNode &node) {
+ Common::ScopedPtr<Common::SeekableReadStream> f(node.createReadStream());
+ if (!f)
+ error("Couldn't open %s", node.toString().c_str());
- load(f);
+ load(*f);
}
diff --git a/engines/tetraedge/te/te_interpolation.h b/engines/tetraedge/te/te_interpolation.h
index a9b154ca7c8..4916a27dc5b 100644
--- a/engines/tetraedge/te/te_interpolation.h
+++ b/engines/tetraedge/te/te_interpolation.h
@@ -26,6 +26,8 @@
#include "common/stream.h"
#include "common/fs.h"
+#include "tetraedge/tetraedge.h"
+
namespace Tetraedge {
class TeInterpolation {
@@ -33,7 +35,7 @@ public:
TeInterpolation();
void load(Common::ReadStream &stream);
- void load(Common::Path &path);
+ void load(TetraedgeFSNode &node);
// Note: this function is not in the original but simplifies
// the code for TeCurveAnim2 a lot.
diff --git a/engines/tetraedge/te/te_lua_gui.cpp b/engines/tetraedge/te/te_lua_gui.cpp
index 7fce15a0d61..58d6f9e5dfb 100644
--- a/engines/tetraedge/te/te_lua_gui.cpp
+++ b/engines/tetraedge/te/te_lua_gui.cpp
@@ -179,9 +179,12 @@ TeSpriteLayout *TeLuaGUI::spriteLayoutChecked(const Common::String &name) {
bool TeLuaGUI::load(const Common::Path &subPath) {
TeCore *core = g_engine->getCore();
+ return load(core->findFile(subPath));
+}
+bool TeLuaGUI::load(const TetraedgeFSNode &node) {
unload();
- _scriptPath = core->findFile(subPath);
+ _scriptPath = node.getPath();
// Not the same as original, we abstract the search logic a bit.
_luaContext.setGlobal("Pixel", 0);
_luaContext.setGlobal("Percent", 1);
@@ -210,7 +213,7 @@ bool TeLuaGUI::load(const Common::Path &subPath) {
_luaContext.registerCFunction("TeVideoLayout", spriteLayoutBindings);
_luaContext.setInRegistry("__TeLuaGUIThis", this);
_luaScript.attachToContext(&_luaContext);
- _luaScript.load(_scriptPath);
+ _luaScript.load(node);
_luaScript.execute();
_luaScript.unload();
_loaded = true;
diff --git a/engines/tetraedge/te/te_lua_gui.h b/engines/tetraedge/te/te_lua_gui.h
index d55b1fce1e2..0163cd23f6f 100644
--- a/engines/tetraedge/te/te_lua_gui.h
+++ b/engines/tetraedge/te/te_lua_gui.h
@@ -78,6 +78,7 @@ public:
TeSpriteLayout *spriteLayoutChecked(const Common::String &name);
bool load(const Common::Path &subPath);
+ bool load(const TetraedgeFSNode &node);
void unload();
TeVariant value(const Common::String &key);
diff --git a/engines/tetraedge/te/te_lua_script.cpp b/engines/tetraedge/te/te_lua_script.cpp
index 8987164a269..e79a4d7abc5 100644
--- a/engines/tetraedge/te/te_lua_script.cpp
+++ b/engines/tetraedge/te/te_lua_script.cpp
@@ -37,7 +37,7 @@ void TeLuaScript::attachToContext(TeLuaContext *context) {
void TeLuaScript::execute() {
if (_luaContext) {
- //debug("TeLuaScript::execute %s", _scriptNode.getPath().c_str());
+ //debug("TeLuaScript::execute %s", _scriptNode.toString().c_str());
lua_State *state = _luaContext->luaState();
if (state) {
TeLuaThread *thread = TeLuaThread::create(_luaContext);
@@ -50,7 +50,7 @@ void TeLuaScript::execute() {
void TeLuaScript::execute(const Common::String &fname) {
if (_luaContext) {
- //debug("TeLuaScript::execute %s %s", _scriptNode.getPath().c_str(), fname.c_str());
+ //debug("TeLuaScript::execute %s %s", _scriptNode.toString().c_str(), fname.c_str());
TeLuaThread *thread = TeLuaThread::create(_luaContext);
thread->execute(fname);
thread->release();
@@ -59,7 +59,7 @@ void TeLuaScript::execute(const Common::String &fname) {
void TeLuaScript::execute(const Common::String &fname, const TeVariant &p1) {
if (_luaContext) {
- //debug("TeLuaScript::execute %s %s(%s)", _scriptNode.getPath().c_str(), fname.c_str(), p1.toString().c_str());
+ //debug("TeLuaScript::execute %s %s(%s)", _scriptNode.toString().c_str(), fname.c_str(), p1.toString().c_str());
TeLuaThread *thread = TeLuaThread::create(_luaContext);
thread->execute(fname, p1);
thread->release();
@@ -82,13 +82,13 @@ void TeLuaScript::execute(const Common::String &fname, const TeVariant &p1, cons
}
}
-void TeLuaScript::load(const Common::Path &node) {
+void TeLuaScript::load(const TetraedgeFSNode &node) {
_started = false;
_scriptNode = node;
}
void TeLuaScript::unload() {
- _scriptNode = Common::Path();
+ _scriptNode = TetraedgeFSNode();
_started = false;
}
diff --git a/engines/tetraedge/te/te_lua_script.h b/engines/tetraedge/te/te_lua_script.h
index 9a878a00cbd..19cfe511e3e 100644
--- a/engines/tetraedge/te/te_lua_script.h
+++ b/engines/tetraedge/te/te_lua_script.h
@@ -25,6 +25,7 @@
#include "common/str.h"
#include "common/path.h"
#include "tetraedge/te/te_variant.h"
+#include "tetraedge/tetraedge.h"
namespace Tetraedge {
@@ -42,13 +43,13 @@ public:
void execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2);
void execute(const Common::String &fname, const TeVariant &p1, const TeVariant &p2, const TeVariant &p3);
- void load(const Common::Path &node);
+ void load(const TetraedgeFSNode &node);
void unload();
private:
TeLuaContext *_luaContext;
- Common::Path _scriptNode;
+ TetraedgeFSNode _scriptNode;
bool _started;
};
diff --git a/engines/tetraedge/te/te_lua_thread.cpp b/engines/tetraedge/te/te_lua_thread.cpp
index b0411d54bf8..e30cc4c9cf0 100644
--- a/engines/tetraedge/te/te_lua_thread.cpp
+++ b/engines/tetraedge/te/te_lua_thread.cpp
@@ -260,10 +260,10 @@ void TeLuaThread::applyScriptWorkarounds(char *buf, const Common::String &fileNa
}
}
-void TeLuaThread::executeFile(const Common::Path &node) {
- Common::File scriptFile;
- if (!scriptFile.open(node)) {
- warning("TeLuaThread::executeFile: File %s can't be opened", node.baseName().c_str());
+void TeLuaThread::executeFile(const TetraedgeFSNode &node) {
+ Common::ScopedPtr<Common::SeekableReadStream> scriptFile(node.createReadStream());
+ if (!scriptFile) {
+ warning("TeLuaThread::executeFile: File %s can't be opened", node.getName().c_str());
return;
}
@@ -271,15 +271,15 @@ void TeLuaThread::executeFile(const Common::Path &node) {
debug("TeLuaThread::executeFile: %s", node.getName().c_str());
#endif
- int64 fileLen = scriptFile.size();
+ int64 fileLen = scriptFile->size();
char *buf = new char[fileLen + 1];
- scriptFile.read(buf, fileLen);
+ scriptFile->read(buf, fileLen);
buf[fileLen] = 0;
- scriptFile.close();
+ scriptFile.reset();
- applyScriptWorkarounds(buf, node.baseName());
+ applyScriptWorkarounds(buf, node.getPath().baseName());
- _lastResumeResult = luaL_loadbuffer(_luaThread, buf, fileLen, node.toString(Common::Path::kNativeSeparator).c_str());
+ _lastResumeResult = luaL_loadbuffer(_luaThread, buf, fileLen, node.toString().c_str());
if (_lastResumeResult) {
const char *msg = lua_tostring(_luaThread, -1);
warning("TeLuaThread::executeFile: %s", msg);
diff --git a/engines/tetraedge/te/te_lua_thread.h b/engines/tetraedge/te/te_lua_thread.h
index 4e77f0e5bea..e925c082161 100644
--- a/engines/tetraedge/te/te_lua_thread.h
+++ b/engines/tetraedge/te/te_lua_thread.h
@@ -46,7 +46,7 @@ public:
void execute(const Common::String &str, const TeVariant &p1, const TeVariant &p2);
void execute(const Common::String &str, const TeVariant &p1, const TeVariant &p2, const TeVariant &p3);
- void executeFile(const Common::Path &node);
+ void executeFile(const TetraedgeFSNode &node);
void pushValue(const TeVariant &val);
void release();
diff --git a/engines/tetraedge/te/te_material.cpp b/engines/tetraedge/te/te_material.cpp
index 734dfb970d5..848a2cde80b 100644
--- a/engines/tetraedge/te/te_material.cpp
+++ b/engines/tetraedge/te/te_material.cpp
@@ -97,10 +97,10 @@ void TeMaterial::deserialize(Common::SeekableReadStream &stream, TeMaterial &mat
if (nameStr.size()) {
TeCore *core = g_engine->getCore();
- Common::Path matPath = core->findFile(texPath.join(nameStr));
+ TetraedgeFSNode matPath = core->findFile(Common::Path(texPath).join(nameStr));
material._texture = Te3DTexture::load2(matPath, false);
if (!material._texture)
- warning("failed to load texture %s (texpath %s)", nameStr.c_str(), matPath.toString(Common::Path::kNativeSeparator).c_str());
+ warning("failed to load texture %s (texpath %s)", nameStr.c_str(), matPath.toString().c_str());
}
material._ambientColor.deserialize(stream);
diff --git a/engines/tetraedge/te/te_model_animation.cpp b/engines/tetraedge/te/te_model_animation.cpp
index 25d8e4de1aa..979b463954c 100644
--- a/engines/tetraedge/te/te_model_animation.cpp
+++ b/engines/tetraedge/te/te_model_animation.cpp
@@ -181,22 +181,22 @@ int TeModelAnimation::lastFrame() const {
}
bool TeModelAnimation::load(const Common::Path &path) {
- Common::Path foundFile = g_engine->getCore()->findFile(path);
- Common::File modelFile;
- if (!modelFile.open(foundFile)) {
- warning("[TeModel::load] Can't open file : %s.", path.toString(Common::Path::kNativeSeparator).c_str());
+ TetraedgeFSNode foundFile = g_engine->getCore()->findFile(path);
+ Common::ScopedPtr<Common::SeekableReadStream> modelFile(foundFile.createReadStream());
+ if (!modelFile) {
+ warning("[TeModel::load] Can't open file : %s.", path.toString().c_str());
return false;
}
bool retval;
- if (Te3DObject2::loadAndCheckFourCC(modelFile, "TEZ0")) {
- Common::SeekableReadStream *zlibStream = TeModel::tryLoadZlibStream(modelFile);
+ if (Te3DObject2::loadAndCheckFourCC(*modelFile, "TEZ0")) {
+ Common::SeekableReadStream *zlibStream = TeModel::tryLoadZlibStream(*modelFile);
if (!zlibStream)
return false;
retval = load(*zlibStream);
delete zlibStream;
} else {
- modelFile.seek(0);
- retval = load(modelFile);
+ modelFile->seek(0);
+ retval = load(*modelFile);
}
_loadedPath = path;
return retval;
diff --git a/engines/tetraedge/te/te_music.cpp b/engines/tetraedge/te/te_music.cpp
index dc4aab77639..12292afc7ef 100644
--- a/engines/tetraedge/te/te_music.cpp
+++ b/engines/tetraedge/te/te_music.cpp
@@ -60,12 +60,11 @@ void TeMusic::pause() {
bool TeMusic::play() {
if (isPlaying())
return true;
- if (!Common::File::exists(_filePath))
+ if (!_fileNode.exists())
return false;
- Common::File *streamfile = new Common::File();
- if (!streamfile->open(_filePath)) {
- delete streamfile;
+ Common::SeekableReadStream *streamfile = _fileNode.createReadStream();
+ if (!streamfile) {
return false;
}
Audio::AudioStream *stream = Audio::makeVorbisStream(streamfile, DisposeAfterUse::YES);
@@ -82,7 +81,7 @@ bool TeMusic::play() {
soundType = Audio::Mixer::kMusicSoundType;
}
- //debug("playing %s on channel %s at vol %d", _fileNode.getPath().c_str(), _channelName.c_str(), vol);
+ //debug("playing %s on channel %s at vol %d", _fileNode.toString().c_str(), _channelName.c_str(), vol);
mixer->playStream(soundType, &_sndHandle, stream, -1, vol);
_sndHandleValid = true;
_isPaused = false;
@@ -191,7 +190,7 @@ void TeMusic::setFilePath(const Common::Path &name) {
_rawPath = name;
TeCore *core = g_engine->getCore();
// Note: original search logic here abstracted away in our version..
- _filePath = core->findFile(name);
+ _fileNode = core->findFile(name);
}
void TeMusic::update() {
diff --git a/engines/tetraedge/te/te_music.h b/engines/tetraedge/te/te_music.h
index ab5256008e9..ea27e12e469 100644
--- a/engines/tetraedge/te/te_music.h
+++ b/engines/tetraedge/te/te_music.h
@@ -29,6 +29,7 @@
#include "tetraedge/te/te_resource.h"
#include "tetraedge/te/te_signal.h"
+#include "tetraedge/tetraedge.h"
namespace Tetraedge {
@@ -74,7 +75,7 @@ public:
private:
Common::Path _rawPath; // Plain name of file requested
- Common::Path _filePath; // file after finding it
+ TetraedgeFSNode _fileNode; // file after finding it
Common::String _channelName;
bool _repeat;
diff --git a/engines/tetraedge/te/te_png.cpp b/engines/tetraedge/te/te_png.cpp
index 545e04213ec..02277db1ec9 100644
--- a/engines/tetraedge/te/te_png.cpp
+++ b/engines/tetraedge/te/te_png.cpp
@@ -44,8 +44,8 @@ bool TePng::matchExtension(const Common::String &extn) {
return extn == "png" || extn == "png#anim";
}
-bool TePng::load(const Common::Path &path) {
- if (!TeScummvmCodec::load(path))
+bool TePng::load(const TetraedgeFSNode &node) {
+ if (!TeScummvmCodec::load(node))
return false;
_height = _loadedSurface->h / _nbFrames;
diff --git a/engines/tetraedge/te/te_png.h b/engines/tetraedge/te/te_png.h
index 31a6114b5d7..b110e9e94e2 100644
--- a/engines/tetraedge/te/te_png.h
+++ b/engines/tetraedge/te/te_png.h
@@ -36,7 +36,7 @@ public:
TePng(const Common::String &extn);
virtual ~TePng();
- virtual bool load(const Common::Path &path) override;
+ virtual bool load(const TetraedgeFSNode &node) override;
virtual bool load(Common::SeekableReadStream &stream) override;
TeImage::Format imageFormat() override;
diff --git a/engines/tetraedge/te/te_resource_manager.h b/engines/tetraedge/te/te_resource_manager.h
index 27d2afb14c9..a67da4169b0 100644
--- a/engines/tetraedge/te/te_resource_manager.h
+++ b/engines/tetraedge/te/te_resource_manager.h
@@ -60,7 +60,8 @@ public:
}
template<class T>
- TeIntrusivePtr<T> getResource(const Common::Path &path) {
+ TeIntrusivePtr<T> getResource(const TetraedgeFSNode &node) {
+ Common::Path path = node.getPath();
for (TeIntrusivePtr<TeResource> &resource : this->_resources) {
if (resource->getAccessName() == path) {
return TeIntrusivePtr<T>(dynamic_cast<T *>(resource.get()));
@@ -70,9 +71,9 @@ public:
TeIntrusivePtr<T> retval = new T();
if (retval.get()) {
- if (!Common::File::exists(path))
- warning("getResource: asked to fetch unreadable resource %s", path.toString(Common::Path::kNativeSeparator).c_str());
- retval->load(path);
+ if (!node.isReadable())
+ warning("getResource: asked to fetch unreadable resource %s", node.toString().c_str());
+ retval->load(node);
addResource(retval.get());
}
return retval;
diff --git a/engines/tetraedge/te/te_scene.h b/engines/tetraedge/te/te_scene.h
index 8a5174ae7f8..de6f7a3b1c7 100644
--- a/engines/tetraedge/te/te_scene.h
+++ b/engines/tetraedge/te/te_scene.h
@@ -47,7 +47,7 @@ public:
Common::String currentCameraName() const;
virtual void draw();
- virtual bool load(const Common::Path &path) { return false; };
+ virtual bool load(const TetraedgeFSNode &node) { return false; };
void removeModel(const Common::String &mname);
void setCurrentCamera(const Common::String &cname);
diff --git a/engines/tetraedge/te/te_scene_warp.cpp b/engines/tetraedge/te/te_scene_warp.cpp
index 27f9df25744..f7c5486232b 100644
--- a/engines/tetraedge/te/te_scene_warp.cpp
+++ b/engines/tetraedge/te/te_scene_warp.cpp
@@ -77,8 +77,8 @@ bool TeSceneWarp::load(const Common::Path &name, TeWarp *warp, bool flag) {
TeSceneWarpXmlParser parser(this, flag);
TeCore *core = g_engine->getCore();
- Common::Path path = core->findFile(name);
- if (!parser.loadFile(path))
+ TetraedgeFSNode node = core->findFile(name);
+ if (!node.loadXML(parser))
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.toString(Common::Path::kNativeSeparator).c_str());
diff --git a/engines/tetraedge/te/te_scummvm_codec.cpp b/engines/tetraedge/te/te_scummvm_codec.cpp
index d46df2b95db..26953eee885 100644
--- a/engines/tetraedge/te/te_scummvm_codec.cpp
+++ b/engines/tetraedge/te/te_scummvm_codec.cpp
@@ -38,10 +38,10 @@ TeScummvmCodec::~TeScummvmCodec() {
}
}
-bool TeScummvmCodec::load(const Common::Path &path) {
- Common::File file;
- if (file.open(path) && load(static_cast<Common::SeekableReadStream &>(file))) {
- _loadedPath = path;
+bool TeScummvmCodec::load(const TetraedgeFSNode &node) {
+ Common::ScopedPtr<Common::SeekableReadStream> file(node.createReadStream());
+ if (file && load(*file)) {
+ _loadedPath = node.getPath();
return true;
}
return false;
diff --git a/engines/tetraedge/te/te_scummvm_codec.h b/engines/tetraedge/te/te_scummvm_codec.h
index 474f80b086b..ebbc6eba341 100644
--- a/engines/tetraedge/te/te_scummvm_codec.h
+++ b/engines/tetraedge/te/te_scummvm_codec.h
@@ -32,7 +32,7 @@ public:
TeScummvmCodec();
virtual ~TeScummvmCodec();
- virtual bool load(const Common::Path &path) override;
+ virtual bool load(const TetraedgeFSNode &node) override;
virtual bool load(Common::SeekableReadStream &stream) = 0;
virtual uint width() override;
virtual uint height() override;
diff --git a/engines/tetraedge/te/te_sound_manager.cpp b/engines/tetraedge/te/te_sound_manager.cpp
index 4763da20eb0..d21743f262e 100644
--- a/engines/tetraedge/te/te_sound_manager.cpp
+++ b/engines/tetraedge/te/te_sound_manager.cpp
@@ -43,12 +43,16 @@ void TeSoundManager::playFreeSound(const Common::Path &path) {
void TeSoundManager::playFreeSound(const Common::Path &path, float vol, const Common::String &channel) {
TeCore *core = g_engine->getCore();
- Common::Path sndPath = core->findFile(path);
+ TetraedgeFSNode sndNode = core->findFile(path);
- Common::File *streamfile = new Common::File();
- if (!streamfile->open(sndPath)) {
- warning("TeSoundManager::playFreeSound: couldn't open %s", sndPath.toString(Common::Path::kNativeSeparator).c_str());
- delete streamfile;
+ if (!sndNode.isReadable()) {
+ warning("TeSoundManager::playFreeSound: couldn't open %s", sndNode.toString().c_str());
+ return;
+ }
+
+ Common::SeekableReadStream *streamfile = sndNode.createReadStream();
+ if (!streamfile) {
+ warning("TeSoundManager::playFreeSound: couldn't open %s", sndNode.toString().c_str());
return;
}
diff --git a/engines/tetraedge/te/te_sprite_layout.cpp b/engines/tetraedge/te/te_sprite_layout.cpp
index 949b809d74e..31e91d906a8 100644
--- a/engines/tetraedge/te/te_sprite_layout.cpp
+++ b/engines/tetraedge/te/te_sprite_layout.cpp
@@ -82,28 +82,19 @@ bool TeSpriteLayout::load(const Common::Path &path) {
}
TeCore *core = g_engine->getCore();
- Common::FSNode spriteNode = core->getFSNode(path);
- Common::Path spritePath(path);
+ TetraedgeFSNode spriteNode = core->findFile(path);
// The path can point to a single file, or a folder with files
- if (spriteNode.isDirectory()) {
- if (!spriteNode.exists()) {
- _tiledSurfacePtr->unload();
- return false;
- }
- } else {
- spritePath = core->findFile(path);
- if (!Common::File::exists(spritePath)) {
- _tiledSurfacePtr->unload();
- return false;
- }
+ if (!spriteNode.exists()) {
+ _tiledSurfacePtr->unload();
+ return false;
}
stop();
unload();
_tiledSurfacePtr->setLoadedPath(path);
- if (_tiledSurfacePtr->load(spritePath)) {
+ if (_tiledSurfacePtr->load(spriteNode)) {
const TeVector2s32 texSize = _tiledSurfacePtr->tiledTexture()->totalSize();
if (texSize._y <= 0) {
setRatio(1.0);
@@ -115,7 +106,7 @@ bool TeSpriteLayout::load(const Common::Path &path) {
}
updateMesh();
} else {
- debug("Failed to load TeSpriteLayout %s", path.toString(Common::Path::kNativeSeparator).c_str());
+ debug("Failed to load TeSpriteLayout %s", spriteNode.toString().c_str());
_tiledSurfacePtr->setLoadedPath("");
}
return true;
diff --git a/engines/tetraedge/te/te_text_layout.cpp b/engines/tetraedge/te/te_text_layout.cpp
index dba780a098c..22ebdb632e1 100644
--- a/engines/tetraedge/te/te_text_layout.cpp
+++ b/engines/tetraedge/te/te_text_layout.cpp
@@ -125,12 +125,13 @@ void TeTextLayout::setText(const Common::String &val) {
_baseFontSize = parser.fontSize();
if (!parser.fontFile().empty()) {
- Common::Path fontPath(g_engine->getCore()->findFile(Common::Path(parser.fontFile())));
+ Common::Path fontPath(parser.fontFile());
+ TetraedgeFSNode fontNode = g_engine->getCore()->findFile(fontPath);
TeIntrusivePtr<TeIFont> font;
if (parser.fontFile().hasSuffixIgnoreCase(".ttf"))
- font = g_engine->getResourceManager()->getResource<TeFont3>(fontPath).get();
+ font = g_engine->getResourceManager()->getResource<TeFont3>(fontNode).get();
else
- font = g_engine->getResourceManager()->getResource<TeFont2>(fontPath).get();
+ font = g_engine->getResourceManager()->getResource<TeFont2>(fontNode).get();
_base.setFont(0, font);
}
if (parser.style().size())
diff --git a/engines/tetraedge/te/te_theora.cpp b/engines/tetraedge/te/te_theora.cpp
index ffd467e995b..1d69b514fe5 100644
--- a/engines/tetraedge/te/te_theora.cpp
+++ b/engines/tetraedge/te/te_theora.cpp
@@ -40,11 +40,9 @@ bool TeTheora::matchExtension(const Common::String &extn) {
return extn == "ogv";
}
-bool TeTheora::load(const Common::Path &path) {
- Common::File *theoraFile = new Common::File();
- theoraFile->open(path);
- _loadedPath = path;
- if (!_decoder->loadStream(theoraFile))
+bool TeTheora::load(const TetraedgeFSNode &node) {
+ _loadedNode = node;
+ if (!_decoder->loadStream(node.createReadStream()))
return false;
_decoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
return true;
@@ -108,10 +106,10 @@ bool TeTheora::update(uint i, TeImage &imgout) {
if (!_decoder->isPlaying())
_decoder->start();
- if (_decoder->getCurFrame() > (int)i && Common::File::exists(_loadedPath)) {
+ if (_decoder->getCurFrame() > (int)i && _loadedNode.exists()) {
// rewind.. no good way to do that, but it should
// only happen on loop.
- load(_loadedPath);
+ load(_loadedNode);
_decoder->start();
}
@@ -125,9 +123,9 @@ bool TeTheora::update(uint i, TeImage &imgout) {
//debug("TeTheora: %s %ld", _path.toString().c_str(), i);
imgout.copyFrom(*frame);
return true;
- } else if (_hitEnd && Common::File::exists(_loadedPath)) {
+ } else if (_hitEnd && _loadedNode.exists()) {
// Loop to the start.
- load(_loadedPath);
+ load(_loadedNode);
frame = _decoder->decodeNextFrame();
if (frame) {
imgout.copyFrom(*frame);
diff --git a/engines/tetraedge/te/te_theora.h b/engines/tetraedge/te/te_theora.h
index 933658163c2..17cefadfa1a 100644
--- a/engines/tetraedge/te/te_theora.h
+++ b/engines/tetraedge/te/te_theora.h
@@ -36,7 +36,7 @@ public:
TeTheora();
virtual ~TeTheora();
- virtual bool load(const Common::Path &path) override;
+ virtual bool load(const TetraedgeFSNode &node) override;
virtual uint width() override;
virtual uint height() override;
virtual int nbFrames() override;
@@ -61,7 +61,7 @@ public:
private:
Video::TheoraDecoder *_decoder;
- Common::Path _loadedPath;
+ TetraedgeFSNode _loadedNode;
bool _hitEnd;
};
diff --git a/engines/tetraedge/te/te_tiled_surface.cpp b/engines/tetraedge/te/te_tiled_surface.cpp
index 10fac11bcbb..0475cc7a9ed 100644
--- a/engines/tetraedge/te/te_tiled_surface.cpp
+++ b/engines/tetraedge/te/te_tiled_surface.cpp
@@ -60,12 +60,12 @@ byte TeTiledSurface::isLoaded() {
return _tiledTexture && _tiledTexture->isLoaded();
}
-bool TeTiledSurface::load(const Common::Path &path) {
+bool TeTiledSurface::load(const TetraedgeFSNode &node) {
unload();
TeResourceManager *resmgr = g_engine->getResourceManager();
if (_loadedPath.empty())
- _loadedPath = path;
+ _loadedPath = node.getPath();
Common::Path ttPath(_loadedPath.append(".tt"));
TeIntrusivePtr<TeTiledTexture> texture;
@@ -76,13 +76,13 @@ bool TeTiledSurface::load(const Common::Path &path) {
if (!texture) {
TeCore *core = g_engine->getCore();
- _codec = core->createVideoCodec(Common::Path(_loadedPath));
+ _codec = core->createVideoCodec(node);
if (!_codec)
return false;
texture = new TeTiledTexture();
- if (_codec->load(path)) {
+ if (_codec->load(node)) {
texture->setAccessName(ttPath);
resmgr->addResource(texture.get());
_imgFormat = _codec->imageFormat();
diff --git a/engines/tetraedge/te/te_tiled_surface.h b/engines/tetraedge/te/te_tiled_surface.h
index 8208a192234..53c8dbfa511 100644
--- a/engines/tetraedge/te/te_tiled_surface.h
+++ b/engines/tetraedge/te/te_tiled_surface.h
@@ -45,7 +45,7 @@ public:
void draw() override;
virtual void entry() {};
byte isLoaded();
- bool load(const Common::Path &path);
+ bool load(const TetraedgeFSNode &node);
bool load(const TeImage &image);
bool load(const TeIntrusivePtr<Te3DTexture> &texture);
diff --git a/engines/tetraedge/te/te_warp.cpp b/engines/tetraedge/te/te_warp.cpp
index be85e018de9..0a0986237c2 100644
--- a/engines/tetraedge/te/te_warp.cpp
+++ b/engines/tetraedge/te/te_warp.cpp
@@ -42,7 +42,7 @@ TeWarp::TeWarp() : _visible1(false), _loaded(false), _preloaded(false),
TeWarp::~TeWarp() {
_markerValidatedSignal.clear();
unload();
- _file.close();
+ _file.reset();
}
void TeWarp::activeMarkers(bool active) {
@@ -243,41 +243,41 @@ void TeWarp::load(const Common::Path &path, bool flag) {
error("Empty TeWarp path!");
TeCore *core = g_engine->getCore();
- Common::Path warpPath = core->findFile(_warpPath);
- if (!Common::File::exists(warpPath)) {
+ TetraedgeFSNode node = core->findFile(_warpPath);
+ if (!node.isReadable()) {
error("Couldn't find TeWarp path data '%s'", _warpPath.toString(Common::Path::kNativeSeparator).c_str());
}
if (_preloaded)
error("TODO: Support preloading in TeWarp::load");
- _file.open(warpPath);
+ _file.reset(node.createReadStream());
char header[7];
header[6] = '\0';
- _file.read(header, 6);
+ _file->read(header, 6);
if (Common::String(header) != "TeWarp")
- error("Invalid header in warp data %s", _warpPath.toString(Common::Path::kNativeSeparator).c_str());
- uint32 globalTexDataOffset = _file.readUint32LE();
- _texEncodingType = _file.readPascalString();
- _xCount = _file.readUint32LE();
- _yCount = _file.readUint32LE();
- uint32 numAnims = _file.readUint32LE();
- _someXVal = _file.readUint32LE();
- _someYVal = _file.readUint32LE();
- _someMeshX = _file.readUint32LE();
- _someMeshY = _file.readUint32LE();
+ error("Invalid header in warp data %s", _warpPath.toString().c_str());
+ uint32 globalTexDataOffset = _file->readUint32LE();
+ _texEncodingType = _file->readPascalString();
+ _xCount = _file->readUint32LE();
+ _yCount = _file->readUint32LE();
+ uint32 numAnims = _file->readUint32LE();
+ _someXVal = _file->readUint32LE();
+ _someYVal = _file->readUint32LE();
+ _someMeshX = _file->readUint32LE();
+ _someMeshY = _file->readUint32LE();
if (_xCount > 1000 || _yCount > 1000 || numAnims > 1000)
error("Improbable values in TeWarp data xCount %d yCount %d numAnims %d", _xCount, _yCount, numAnims);
_warpBlocs.resize(_xCount * _yCount * 6);
for (uint i = 0; i < _xCount * _yCount * 6; i++) {
- TeWarpBloc::CubeFace face = static_cast<TeWarpBloc::CubeFace>(_file.readByte());
+ TeWarpBloc::CubeFace face = static_cast<TeWarpBloc::CubeFace>(_file->readByte());
// TODO: This is strange, surely we only need to set the offset and create the bloc
// once but the code seems to do it xCount * yCount times..
for (uint j = 0; j < _xCount * _yCount; j++) {
- uint xoff = _file.readUint16LE();
- uint yoff = _file.readUint16LE();
+ uint xoff = _file->readUint16LE();
+ uint yoff = _file->readUint16LE();
if (xoff > 1000 || yoff > 1000)
error("TeWarp::load: Improbable offsets %d, %d", xoff, yoff);
- uint32 blocTexOffset = _file.readUint32LE();
+ uint32 blocTexOffset = _file->readUint32LE();
_warpBlocs[i].setTextureFileOffset(globalTexDataOffset + blocTexOffset);
_warpBlocs[i].create(face, _xCount, _yCount, TeVector2s32(xoff, yoff));
}
@@ -286,45 +286,45 @@ void TeWarp::load(const Common::Path &path, bool flag) {
_putAnimData.reserve(numAnims);
for (uint i = 0; i < numAnims; i++) {
char aname[5];
- _file.read(aname, 4);
+ _file->read(aname, 4);
aname[4] = '\0';
_loadedAnimData[i]._name = aname;
- uint numFrames = _file.readUint32LE();
+ uint numFrames = _file->readUint32LE();
if (numFrames > 1000)
error("TeWarp::load: Improbable frame count %d", numFrames);
- byte numSomething = _file.readByte();
+ byte numSomething = _file->readByte();
_loadedAnimData[i]._frameDatas.resize(numFrames);
for (uint j = 0; j < numFrames; j++) {
FrameData &frameData = _loadedAnimData[i]._frameDatas[j];
frameData._loadedTexCount = 0;
Common::Array<TeWarpBloc> warpBlocs;
for (uint k = 0; k < numSomething; k++) {
- uint blocCount = _file.readUint32LE();
+ uint blocCount = _file->readUint32LE();
if (blocCount > 1000)
error("TeWarp::load: Improbable bloc count %d", blocCount);
if (blocCount) {
- TeWarpBloc::CubeFace face = static_cast<TeWarpBloc::CubeFace>(_file.readByte());
+ TeWarpBloc::CubeFace face = static_cast<TeWarpBloc::CubeFace>(_file->readByte());
warpBlocs.resize(blocCount);
for (auto &warpBloc : warpBlocs) {
- uint xoff = _file.readUint16LE();
- uint yoff = _file.readUint16LE();
+ uint xoff = _file->readUint16LE();
+ uint yoff = _file->readUint16LE();
if (xoff > 10000 || yoff > 10000)
error("TeWarp::load: Improbable offsets %d, %d", xoff, yoff);
- uint32 texDataOff = _file.readUint32LE();
+ uint32 texDataOff = _file->readUint32LE();
warpBloc.setTextureFileOffset(globalTexDataOffset + texDataOff);
warpBloc.create(face, _someXVal, _someYVal, TeVector2s32(xoff, yoff));
if (flag)
warpBloc.color(TeColor(255, 0, 0, 255));
}
- uint meshSize = _file.readUint32LE();
+ uint meshSize = _file->readUint32LE();
if (meshSize > 1000)
error("TeWarp::load: Improbable meshSize %d", meshSize);
TePickMesh tmpMesh;
tmpMesh.setName(aname);
tmpMesh.nbTriangles(meshSize * 2);
for (uint m = 0; m < meshSize; m++) {
- uint xoff = _file.readUint16LE();
- uint yoff = _file.readUint16LE();
+ uint xoff = _file->readUint16LE();
+ uint yoff = _file->readUint16LE();
if (xoff > 10000 || yoff > 10000)
error("TeWarp::load: Improbable offsets %d, %d", xoff, yoff);
addQuadToPickMesh(tmpMesh, m * 2, face, TeVector2s32(xoff, yoff), _someMeshX, _someMeshY);
@@ -413,12 +413,12 @@ void TeWarp::putObject(const Common::String &name, bool enable) {
}
void TeWarp::update() {
- if (!_visible1 || !_file.isOpen())
+ if (!_visible1 || !_file)
return;
//Application *app = g_engine->getApplication();
_frustum.update(_camera);
for (auto &bloc : _warpBlocs) {
- bloc.loadTexture(_file, _texEncodingType);
+ bloc.loadTexture(*_file, _texEncodingType);
}
for (auto &anim : _loadedAnimData) {
@@ -441,7 +441,7 @@ void TeWarp::update() {
anim._frameDatas[lastFrame]._loadedTexCount = 0;
}
}
- anim._frameDatas[anim._curFrameNo].loadTextures(_frustum, _file, _texEncodingType);
+ anim._frameDatas[anim._curFrameNo].loadTextures(_frustum, *_file, _texEncodingType);
}
}
@@ -664,7 +664,7 @@ void TeWarp::updateCamera(const TeVector3f32 &screen) {
_camera.projectionMatrix();
}
-void TeWarp::FrameData::loadTextures(const TeFrustum &frustum, Common::File &file, const Common::String &fileType) {
+void TeWarp::FrameData::loadTextures(const TeFrustum &frustum, Common::SeekableReadStream &file, const Common::String &fileType) {
for (auto &b : _warpBlocs) {
if (!b.isLoaded() && (frustum.isTriangleInside(b.vertex(0), b.vertex(1), b.vertex(3))
|| frustum.isTriangleInside(b.vertex(1), b.vertex(2), b.vertex(3)))) {
diff --git a/engines/tetraedge/te/te_warp.h b/engines/tetraedge/te/te_warp.h
index 303c45834b0..2731fc2e78c 100644
--- a/engines/tetraedge/te/te_warp.h
+++ b/engines/tetraedge/te/te_warp.h
@@ -43,7 +43,7 @@ public:
int _loadedTexCount;
// Note: dropped "minblock" param from original as it's only
// ever set to 0
- void loadTextures(const TeFrustum &frustum, Common::File &file, const Common::String &fileType);
+ void loadTextures(const TeFrustum &frustum, Common::SeekableReadStream &file, const Common::String &fileType);
void unloadTextures();
};
@@ -125,7 +125,7 @@ private:
bool onMouseLeftDown(const Common::Point &pt);
bool onMarkerValidated(const Common::String &name);
- Common::File _file;
+ Common::ScopedPtr<Common::SeekableReadStream> _file;
Common::Path _warpPath;
TeCamera _camera;
bool _markersActive;
diff --git a/engines/tetraedge/te/te_warp_bloc.cpp b/engines/tetraedge/te/te_warp_bloc.cpp
index 5956e97917d..53b0ec38b54 100644
--- a/engines/tetraedge/te/te_warp_bloc.cpp
+++ b/engines/tetraedge/te/te_warp_bloc.cpp
@@ -123,7 +123,7 @@ bool TeWarpBloc::isLoaded() const {
return _mesh->materials().size() > 0 && _mesh->material(0)->_texture;
}
-void TeWarpBloc::loadTexture(Common::File &file, const Common::String &type) {
+void TeWarpBloc::loadTexture(Common::SeekableReadStream &file, const Common::String &type) {
if (isLoaded())
return;
diff --git a/engines/tetraedge/te/te_warp_bloc.h b/engines/tetraedge/te/te_warp_bloc.h
index f16868b8c78..c69f9c6e9e5 100644
--- a/engines/tetraedge/te/te_warp_bloc.h
+++ b/engines/tetraedge/te/te_warp_bloc.h
@@ -55,7 +55,7 @@ public:
void create();
void index(uint offset, uint val);
bool isLoaded() const;
- void loadTexture(Common::File &file, const Common::String &type);
+ void loadTexture(Common::SeekableReadStream &file, const Common::String &type);
//void operator=(const TeWarpBloc &other); // unused
//bool operator==(const TeWarpBloc &other); // unused
void render();
diff --git a/engines/tetraedge/tetraedge.cpp b/engines/tetraedge/tetraedge.cpp
index 4851d470f61..2b85ab44da5 100644
--- a/engines/tetraedge/tetraedge.cpp
+++ b/engines/tetraedge/tetraedge.cpp
@@ -41,6 +41,7 @@
#include "tetraedge/te/te_sound_manager.h"
#include "tetraedge/te/te_input_mgr.h"
#include "tetraedge/te/te_particle.h"
+#include "tetraedge/obb_archive.h"
namespace Tetraedge {
@@ -62,6 +63,8 @@ TetraedgeEngine::~TetraedgeEngine() {
delete _soundManager;
delete _resourceManager;
delete _inputMgr;
+ for (Common::Array<Common::Archive *>::iterator it = _rootArchives.begin(); it != _rootArchives.end(); it++)
+ delete *it;
Object3D::cleanup();
Character::cleanup();
TeAnimation::cleanup();
@@ -207,8 +210,19 @@ void TetraedgeEngine::closeGameDialogs() {
void TetraedgeEngine::configureSearchPaths() {
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
- if (_gameDescription->platform != Common::kPlatformIOS)
+ if (_gameDescription->platform == Common::kPlatformMacintosh) {
SearchMan.addSubDirectoryMatching(gameDataDir, "Resources", 0, 6);
+ _rootArchives.push_back(new Common::FSDirectory(gameDataDir.getChild("Resources"), 10));
+ } else
+ _rootArchives.push_back(new Common::FSDirectory(gameDataDir, 10));
+
+ if (_gameDescription->platform == Common::Platform::kPlatformAndroid
+ && strlen(_gameDescription->filesDescriptions[0].fileName) > 4
+ && scumm_stricmp(_gameDescription->filesDescriptions[0].fileName + strlen(_gameDescription->filesDescriptions[0].fileName) - 4, ".obb") == 0) {
+ ObbArchive *obb = ObbArchive::open(_gameDescription->filesDescriptions[0].fileName);
+ _rootArchives.push_back(obb);
+ SearchMan.add("obbarchive", obb, 0, false);
+ }
}
int TetraedgeEngine::getDefaultScreenWidth() const {
Commit: 22666274a40617356dddf3c08e9f5341b642ddeb
https://github.com/scummvm/scummvm/commit/22666274a40617356dddf3c08e9f5341b642ddeb
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Skip pausable attribute
Changed paths:
engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
diff --git a/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp b/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
index d66f27372e9..7ad66443b28 100644
--- a/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
+++ b/engines/tetraedge/te/te_lua_gui_lua_callbacks.cpp
@@ -602,8 +602,9 @@ int layoutPositionLinearAnimationBindings(lua_State *L) {
} else if (!strcmp(s, "endValue")) {
static const TeVector3f32 defaultEnd(0.0f, 0.0f, 0.0f);
anim->_endVal = TeLuaToTeVector3f32(L, -1, defaultEnd);
- } else if (!strcmp(s, "layout")) {
+ } else if (!strcmp(s, "layout") || !strcmp(s, "pausable")) {
// skip.
+ // TODO: What should we do with "pausable" attribute?
} else if (!strcmp(s, "curve")) {
const Common::Array<float> curve = TeLuaToFloatArray(L, -1);
anim->setCurve(curve);
Commit: d3e1834e969c01343fe24b79e9d365a122ad8fb9
https://github.com/scummvm/scummvm/commit/d3e1834e969c01343fe24b79e9d365a122ad8fb9
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Fallback to English if selected language is not available
Changed paths:
engines/tetraedge/te/te_core.cpp
diff --git a/engines/tetraedge/te/te_core.cpp b/engines/tetraedge/te/te_core.cpp
index ffbad1ede04..6e6e450eb3b 100644
--- a/engines/tetraedge/te/te_core.cpp
+++ b/engines/tetraedge/te/te_core.cpp
@@ -207,22 +207,29 @@ TetraedgeFSNode TeCore::findFile(const Common::Path &path, bool quiet) const {
activeFlags.erase("SD");
activeFlags["HD"] = true;
- for (uint dirNode = 0; dirNode < dirNodes.size(); dirNode++) {
- Common::Array<TetraedgeFSNode> foundFiles;
- _findFileRecursively(dirNodes[dirNode], activeFlags, fname, foundFiles, 5);
- if (foundFiles.empty())
- continue;
- TetraedgeFSNode best = foundFiles[0];
- int bestDepth = best.getDepth();
- for (uint i = 1; i < foundFiles.size(); i++) {
- int depth = foundFiles[i].getDepth();
- if (depth > bestDepth) {
- bestDepth = depth;
- best = foundFiles[i];
+ for (int attempt = 0; attempt < 2; attempt++) {
+ if (attempt == 1)
+ activeFlags["en"] = true;
+ for (uint dirNode = 0; dirNode < dirNodes.size(); dirNode++) {
+ Common::Array<TetraedgeFSNode> foundFiles;
+ _findFileRecursively(dirNodes[dirNode], activeFlags, fname, foundFiles, 5);
+ if (foundFiles.empty())
+ continue;
+ TetraedgeFSNode best = foundFiles[0];
+ int bestDepth = best.getDepth();
+ for (uint i = 1; i < foundFiles.size(); i++) {
+ int depth = foundFiles[i].getDepth();
+ if (depth > bestDepth) {
+ bestDepth = depth;
+ best = foundFiles[i];
+ }
}
- }
- return best;
+ if (attempt == 1 && !quiet)
+ debug("TeCore::findFile Falled back to English for %s", path.toString().c_str());
+
+ return best;
+ }
}
// Didn't find it at all..
Commit: ede5b4b77e921d8e02d132ef11c8f6e3e0707f97
https://github.com/scummvm/scummvm/commit/ede5b4b77e921d8e02d132ef11c8f6e3e0707f97
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Support UTF-8 Switch releases
Changed paths:
engines/tetraedge/detection.h
engines/tetraedge/detection_tables.h
engines/tetraedge/te/te_i_font.cpp
engines/tetraedge/tetraedge.cpp
engines/tetraedge/tetraedge.h
diff --git a/engines/tetraedge/detection.h b/engines/tetraedge/detection.h
index cf5bbf1c796..9908ab2a8c0 100644
--- a/engines/tetraedge/detection.h
+++ b/engines/tetraedge/detection.h
@@ -34,6 +34,10 @@ enum TetraedgeDebugChannels {
kDebugScript = 1 << 4
};
+enum GameFeatures {
+ GF_UTF8 = 1 << 0,
+};
+
extern const PlainGameDescriptor GAME_NAMES[];
extern const ADGameDescription GAME_DESCRIPTIONS[];
diff --git a/engines/tetraedge/detection_tables.h b/engines/tetraedge/detection_tables.h
index 4464ec7f81e..d7faebb1ed0 100644
--- a/engines/tetraedge/detection_tables.h
+++ b/engines/tetraedge/detection_tables.h
@@ -80,7 +80,8 @@ const ADGameDescription GAME_DESCRIPTIONS[] = {
{
"syberia",
nullptr,
- AD_ENTRY1s("InGame.lua", "acaf61504a12aebf3862648e04cf29aa", 3920),
+ AD_ENTRY2s("InGame.lua", "acaf61504a12aebf3862648e04cf29aa", 3920,
+ "texts/de.xml", "14681ac50bbfa50427058d2793b415eb", (uint32_t)-1),
Common::UNK_LANG,
Common::kPlatformNintendoSwitch,
ADGF_NO_FLAGS,
@@ -89,14 +90,50 @@ const ADGameDescription GAME_DESCRIPTIONS[] = {
{
"syberia2",
nullptr,
- AD_ENTRY2s("Debug.lua", "a2ea493892e96bea64013819195c081e", 7024,
- "InGame.lua", "a7df110fe816cb342574150c6f992964", 4654),
+ AD_ENTRY3s("Debug.lua", "a2ea493892e96bea64013819195c081e", 7024,
+ "InGame.lua", "a7df110fe816cb342574150c6f992964", 4654,
+ "texts/de.xml", "dabad822a917b1f87de8f09eadc3ec85", (uint32_t)-1),
Common::UNK_LANG,
Common::kPlatformNintendoSwitch,
ADGF_NO_FLAGS,
GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
},
+ // Nintendo Switch, from Syberia1+2 Online bundle, v0
+ {
+ "syberia",
+ nullptr,
+ AD_ENTRY2s("InGame.lua", "ca319e6f014d04baaf1e77f13f89b44f", 4271,
+ "texts/de.xml", "14681ac50bbfa50427058d2793b415eb", (uint32_t)-1),
+ Common::UNK_LANG,
+ Common::kPlatformNintendoSwitch,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
+ // Nintendo Switch, from Syberia1+2 Online bundle, v196608
+ {
+ "syberia",
+ nullptr,
+ AD_ENTRY2s("InGame.lua", "ca319e6f014d04baaf1e77f13f89b44f", 4271,
+ "texts/de.xml", "17d7a875e81a7761d2b30698bd947c15", (uint32_t)-1),
+ Common::UNK_LANG,
+ Common::kPlatformNintendoSwitch,
+ ADGF_NO_FLAGS | GF_UTF8,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+ {
+ "syberia2",
+ nullptr,
+ AD_ENTRY3s("Debug.lua", "a2ea493892e96bea64013819195c081e", 7024,
+ "InGame.lua", "7d7fdb9005675618220e7cd8962c6482", 4745,
+ "texts/de.xml", "78ed3567b3621459229f39c03132e5bb", (uint32_t)-1),
+ Common::UNK_LANG,
+ Common::kPlatformNintendoSwitch,
+ ADGF_NO_FLAGS | GF_UTF8,
+ GUIO1(GAMEOPTION_CORRECT_MOVIE_ASPECT)
+ },
+
// Android v1.0.5
{
"syberia",
diff --git a/engines/tetraedge/te/te_i_font.cpp b/engines/tetraedge/te/te_i_font.cpp
index 65fb6034cbd..4cd0a968e18 100644
--- a/engines/tetraedge/te/te_i_font.cpp
+++ b/engines/tetraedge/te/te_i_font.cpp
@@ -51,6 +51,8 @@ TeIFont::GlyphData TeIFont::glyph(uint pxSize, uint charcode) {
Common::CodePage TeIFont::codePage() const {
Common::String lang = g_engine->getCore()->language();
+ if (g_engine->isUtf8Release())
+ return Common::CodePage::kUtf8;
if (lang == "ru")
return Common::kISO8859_5;
if (g_engine->getGamePlatform() == Common::Platform::kPlatformAndroid)
diff --git a/engines/tetraedge/tetraedge.cpp b/engines/tetraedge/tetraedge.cpp
index 2b85ab44da5..3f927aac38a 100644
--- a/engines/tetraedge/tetraedge.cpp
+++ b/engines/tetraedge/tetraedge.cpp
@@ -149,6 +149,10 @@ Common::Platform TetraedgeEngine::getGamePlatform() const {
return _gameDescription->platform;
}
+bool TetraedgeEngine::isUtf8Release() const {
+ return !!(_gameDescription->flags & GF_UTF8);
+}
+
bool TetraedgeEngine::isGameDemo() const {
return (_gameDescription->flags & ADGF_DEMO) != 0;
}
diff --git a/engines/tetraedge/tetraedge.h b/engines/tetraedge/tetraedge.h
index 0ee7299f4c3..28904d8614e 100644
--- a/engines/tetraedge/tetraedge.h
+++ b/engines/tetraedge/tetraedge.h
@@ -124,6 +124,8 @@ public:
Common::Platform getGamePlatform() const;
+ bool isUtf8Release() const;
+
bool isGameDemo() const;
/**
Commit: 0cc45aabf83754db24f46835ecb9997527ac7125
https://github.com/scummvm/scummvm/commit/0cc45aabf83754db24f46835ecb9997527ac7125
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2025-01-11T14:20:56+01:00
Commit Message:
TETRAEDGE: Declare Polish and Japanese translations
Changed paths:
engines/tetraedge/detection.cpp
diff --git a/engines/tetraedge/detection.cpp b/engines/tetraedge/detection.cpp
index d5edb2a4c3c..77d70c7d31a 100644
--- a/engines/tetraedge/detection.cpp
+++ b/engines/tetraedge/detection.cpp
@@ -46,6 +46,8 @@ static const Common::Language *getGameLanguages() {
Common::ES_ESP,
Common::RU_RUS,
Common::HE_ISR, // This is a Fan-translation, which requires additional patch
+ Common::JA_JPN,
+ Common::PL_POL,
Common::UNK_LANG
};
return languages;
More information about the Scummvm-git-logs
mailing list