SWORD25: Add engine option to use English speech instead of German

When selecting non-English language, the scripts default to using
German voices. This commit edits the file path on the fly to use instead
English voices for all languages other than German. This implements bug
#6804 - SWORD25: add option to choose language speech.

If the English voice pack is not present it falls back to using German voices.

The way this is implemented here however does not allow to use German
voices with English text or English voices with German text. This could be
achieved with a slightly different implementation of the same idea.
This commit is contained in:
Thierry Crozat 2016-03-09 00:02:45 +00:00
parent fd470e3584
commit 90a86fd39c
4 changed files with 55 additions and 9 deletions

1
engines/sword25/POTFILES Normal file
View File

@ -0,0 +1 @@
engines/sword25/detection.cpp

View File

@ -21,6 +21,7 @@
*/
#include "base/plugins.h"
#include "common/translation.h"
#include "engines/advancedDetector.h"
#include "sword25/sword25.h"
@ -41,6 +42,13 @@ static const char *directoryGlobs[] = {
0
};
static const ExtraGuiOption sword25ExtraGuiOption = {
_s("Use English speech"),
_s("Use English speech instead of German for every language other than German"),
"english_speech",
false
};
class Sword25MetaEngine : public AdvancedMetaEngine {
public:
Sword25MetaEngine() : AdvancedMetaEngine(Sword25::gameDescriptions, sizeof(ADGameDescription), sword25Game) {
@ -58,6 +66,7 @@ public:
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
virtual int getMaximumSaveSlot() const { return Sword25::PersistenceService::getSlotCount(); }
virtual SaveStateList listSaves(const char *target) const;
};
@ -74,6 +83,12 @@ bool Sword25MetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsListSaves);
}
const ExtraGuiOptions Sword25MetaEngine::getExtraGuiOptions(const Common::String &target) const {
ExtraGuiOptions options;
options.push_back(sword25ExtraGuiOption);
return options;
}
SaveStateList Sword25MetaEngine::listSaves(const char *target) const {
Common::String pattern = target;
pattern = pattern + ".???";

View File

@ -56,7 +56,8 @@ static Common::String normalizePath(const Common::String &path, const Common::St
PackageManager::PackageManager(Kernel *pKernel) : Service(pKernel),
_currentDirectory(PATH_SEPARATOR),
_rootFolder(ConfMan.get("path")) {
_rootFolder(ConfMan.get("path")),
_useEnglishSpeech(ConfMan.getBool("english_speech")) {
if (!registerScriptBindings())
error("Script bindings could not be registered.");
else
@ -71,14 +72,34 @@ PackageManager::~PackageManager() {
}
Common::String PackageManager::ensureSpeechLang(const Common::String &fileName) {
if (!_useEnglishSpeech || fileName.size() < 9 || !fileName.hasPrefix("/speech/"))
return fileName;
// Always keep German speech as a fallback in case the English speech pack is not present.
// However this means we cannot play with German text and English voice.
if (fileName.hasPrefix("/speech/de"))
return fileName;
Common::String newFileName = "/speech/en";
int fileIdx = 9;
while (fileIdx < fileName.size() && fileName[fileIdx] != '/')
++fileIdx;
if (fileIdx < fileName.size())
newFileName += fileName.c_str() + fileIdx;
return newFileName;
}
/**
* Scans through the archive list for a specified file
*/
Common::ArchiveMemberPtr PackageManager::getArchiveMember(const Common::String &fileName) {
Common::String fileName2 = ensureSpeechLang(fileName);
// Loop through checking each archive
Common::List<ArchiveEntry *>::iterator i;
for (i = _archiveList.begin(); i != _archiveList.end(); ++i) {
if (!fileName.hasPrefix((*i)->_mountPath)) {
if (!fileName2.hasPrefix((*i)->_mountPath)) {
// The mount path is in different subtree. Skipping
continue;
}
@ -87,7 +108,7 @@ Common::ArchiveMemberPtr PackageManager::getArchiveMember(const Common::String &
Common::Archive *archiveFolder = (*i)->archive;
// Construct relative path
Common::String resPath(&fileName.c_str()[(*i)->_mountPath.size()]);
Common::String resPath(&fileName2.c_str()[(*i)->_mountPath.size()]);
if (archiveFolder->hasFile(resPath)) {
return archiveFolder->getMember(resPath);
@ -203,23 +224,29 @@ bool PackageManager::changeDirectory(const Common::String &directory) {
}
Common::String PackageManager::getAbsolutePath(const Common::String &fileName) {
return normalizePath(fileName, _currentDirectory);
return normalizePath(ensureSpeechLang(fileName), _currentDirectory);
}
bool PackageManager::fileExists(const Common::String &fileName) {
// FIXME: The current Zip implementation doesn't support getting a folder entry, which is needed for detecting
// the English voick pack
if (fileName == "/speech/en") {
// the English voice pack
Common::String fileName2 = ensureSpeechLang(fileName);
if (fileName2 == "/speech/en") {
// To get around this, change to detecting one of the files in the folder
return getArchiveMember(normalizePath(fileName + "/APO0001.ogg", _currentDirectory));
bool exists = getArchiveMember(normalizePath(fileName2 + "/APO0001.ogg", _currentDirectory));
if (!exists && _useEnglishSpeech) {
_useEnglishSpeech = false;
warning("English speech not found");
}
return exists;
}
Common::ArchiveMemberPtr fileNode = getArchiveMember(normalizePath(fileName, _currentDirectory));
Common::ArchiveMemberPtr fileNode = getArchiveMember(normalizePath(fileName2, _currentDirectory));
return fileNode;
}
int PackageManager::doSearch(Common::ArchiveMemberList &list, const Common::String &filter, const Common::String &path, uint typeFilter) {
Common::String normalizedFilter = normalizePath(filter, _currentDirectory);
Common::String normalizedFilter = normalizePath(ensureSpeechLang(filter), _currentDirectory);
int num = 0;
if (path.size() > 0)

View File

@ -87,6 +87,9 @@ private:
Common::String _currentDirectory;
Common::FSNode _rootFolder;
Common::List<ArchiveEntry *> _archiveList;
bool _useEnglishSpeech;
Common::String ensureSpeechLang(const Common::String &fileName);
Common::ArchiveMemberPtr getArchiveMember(const Common::String &fileName);