246 lines
8.0 KiB
C++
246 lines
8.0 KiB
C++
/* 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/file.h"
|
|
#include "common/fs.h"
|
|
#include "common/debug.h"
|
|
#include "common/config-manager.h"
|
|
#include "common/language.h"
|
|
#include "common/tokenizer.h"
|
|
|
|
#include "tetraedge/te/te_core.h"
|
|
|
|
#include "tetraedge/tetraedge.h"
|
|
|
|
#include "tetraedge/te/te_png.h"
|
|
#include "tetraedge/te/te_images_sequence.h"
|
|
#include "tetraedge/te/te_jpeg.h"
|
|
#include "tetraedge/te/te_zlib_jpeg.h"
|
|
#include "tetraedge/te/te_theora.h"
|
|
#include "tetraedge/te/te_tga.h"
|
|
|
|
namespace Tetraedge {
|
|
|
|
TeCore::TeCore() : _loc(nullptr), _coreNotReady(true), _resourcesRoot("") {
|
|
create();
|
|
}
|
|
|
|
void TeCore::addLoc(TeILoc *loc) {
|
|
if (_loc) {
|
|
warning("TeCore::addLoc: There is already a loc");
|
|
}
|
|
_loc = loc;
|
|
}
|
|
|
|
void TeCore::create() {
|
|
const char *langCode = getLanguageCode(g_engine->getGameLanguage());
|
|
const Common::String confLang = ConfMan.get("language");
|
|
Common::String useLang = "en";
|
|
if (langCode)
|
|
useLang = langCode;
|
|
if (!confLang.empty())
|
|
useLang = confLang;
|
|
language(useLang);
|
|
_coreNotReady = false;
|
|
_activityTrackingTimer.alarmSignal().add(this, &TeCore::onActivityTrackingAlarm);
|
|
warning("TODO: TeCore::create: Finish implementing me.");
|
|
|
|
const Common::FSNode gameRoot(ConfMan.getPath("path"));
|
|
if (!gameRoot.isDirectory())
|
|
error("Game directory should be a directory");
|
|
const Common::FSNode resNode = (g_engine->getGamePlatform() == Common::kPlatformMacintosh
|
|
? gameRoot.getChild("Resources")
|
|
: gameRoot);
|
|
if (!resNode.isDirectory())
|
|
error("Resources directory should exist in game");
|
|
|
|
_resourcesRoot = Common::FSDirectory(resNode, 5, false, false, true);
|
|
}
|
|
|
|
TeICodec *TeCore::createVideoCodec(const Common::String &extn) {
|
|
// The original engine has more formats and even checks for alpha maps,
|
|
// but it never uses them.
|
|
if (TePng::matchExtension(extn)) {
|
|
// png codec needs to know extension
|
|
return new TePng(extn);
|
|
} else if (TeJpeg::matchExtension(extn)) {
|
|
return new TeJpeg();
|
|
} else if (TeZlibJpeg::matchExtension(extn)) {
|
|
return new TeZlibJpeg();
|
|
} else if (TeTheora::matchExtension(extn)) {
|
|
return new TeTheora();
|
|
} else if (TeTga::matchExtension(extn)) {
|
|
return new TeTga();
|
|
} else if (TeImagesSequence::matchExtension(extn)) {
|
|
return new TeImagesSequence();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
TeICodec *TeCore::createVideoCodec(const TetraedgeFSNode &node, const Common::Path &origPath) {
|
|
//
|
|
// Need to use the original requested path (not the node path) as
|
|
// it might include the #anim directive for animated pngs.
|
|
//
|
|
const Common::String filename = origPath.baseName();
|
|
if (!filename.contains('.'))
|
|
return nullptr;
|
|
Common::String extn = filename.substr(filename.findLastOf('.') + 1);
|
|
extn.toLowercase();
|
|
TeICodec *codec = createVideoCodec(extn);
|
|
if (!codec)
|
|
error("TTeCore::createVideoCodec: Unrecognised format %s", filename.c_str());
|
|
return codec;
|
|
}
|
|
|
|
const Common::String &TeCore::fileFlagSystemFlag(const Common::String &name) const {
|
|
return _fileSystemFlags.find(name)->_value;
|
|
}
|
|
|
|
void TeCore::fileFlagSystemSetFlag(const Common::String &name, const Common::String &val) {
|
|
// TODO: Impmenent this fully to check possible values
|
|
_fileSystemFlags.setVal(name, val);
|
|
}
|
|
|
|
bool TeCore::fileFlagSystemFlagsContains(const Common::String &name) const {
|
|
error("TODO: Implement TeCore::fileFlagSystemFlagsContains");
|
|
return false;
|
|
}
|
|
|
|
Common::Array<Common::String> TeCore::fileFlagSystemPossibleFlags() {
|
|
error("TODO: Implement TeCore::fileFlagSystemPossibleFlags");
|
|
return Common::Array<Common::String>();
|
|
}
|
|
|
|
bool TeCore::fileFlagSystemPossibleFlagsContains(const Common::String &name) const {
|
|
error("TODO: Implement TeCore::fileFlagSystemPossibleFlagsContains");
|
|
return false;
|
|
}
|
|
|
|
const Common::String &TeCore::language() const {
|
|
return fileFlagSystemFlag("language");
|
|
}
|
|
|
|
void TeCore::language(const Common::String &val) {
|
|
return fileFlagSystemSetFlag("language", val);
|
|
}
|
|
|
|
bool TeCore::onActivityTrackingAlarm() {
|
|
error("TODO: Implement TeCore::onActivityTrackingAlarm");
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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) {
|
|
TetraedgeFSNode child = parent.getChild(Common::Path(fname, '/'));
|
|
if (child.exists())
|
|
foundFiles.push_back(child);
|
|
|
|
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('#'));
|
|
|
|
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 minimize functionality changes from the previous implementation.
|
|
// I'm not sure if it's needed
|
|
// TODO: Figure out what to do with this. Right now we set the 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 (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];
|
|
}
|
|
}
|
|
|
|
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..
|
|
if (!quiet)
|
|
debug("TeCore::findFile Searched but didn't find %s", path.toString().c_str());
|
|
return TetraedgeFSNode(nullptr, path);
|
|
}
|
|
|
|
} // end namespace Tetraedge
|