diff options
Diffstat (limited to 'engines')
122 files changed, 1844 insertions, 1518 deletions
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index d093c958e7..b0a304aad9 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -20,9 +20,6 @@ * */ -// FIXME: Avoid using printf -#define FORBIDDEN_SYMBOL_EXCEPTION_printf - #include "common/debug.h" #include "common/util.h" #include "common/hash-str.h" @@ -30,55 +27,13 @@ #include "common/macresman.h" #include "common/md5.h" #include "common/config-manager.h" +#include "common/system.h" #include "common/textconsole.h" +#include "common/translation.h" #include "engines/advancedDetector.h" -/** - * A list of pointers to ADGameDescription structs (or subclasses thereof). - */ -typedef Common::Array<const ADGameDescription*> ADGameDescList; - - -/** - * Detect games in specified directory. - * Parameters language and platform are used to pass on values - * specified by the user. I.e. this is used to restrict search scope. - * - * @param fslist FSList to scan or NULL for scanning all specified - * default directories. - * @param params a ADParams struct containing various parameters - * @param language restrict results to specified language only - * @param platform restrict results to specified platform only - * @return list of ADGameDescription (or subclass) pointers corresponding to matched games - */ -static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String &extra); - - -/** - * Returns list of targets supported by the engine. - * Distinguishes engines with single ID - */ -static GameList gameIDList(const ADParams ¶ms) { - if (params.singleid != NULL) { - GameList gl; - - const PlainGameDescriptor *g = params.list; - while (g->gameid) { - if (0 == scumm_stricmp(params.singleid, g->gameid)) { - gl.push_back(GameDescriptor(g->gameid, g->description)); - - return gl; - } - g++; - } - error("Engine %s doesn't have its singleid specified in ids list", params.singleid); - } - - return GameList(params.list); -} - -static void upgradeTargetIfNecessary(const ADParams ¶ms) { +void AdvancedMetaEngine::upgradeTargetIfNecessary() const { if (params.obsoleteList == 0) return; @@ -110,11 +65,11 @@ namespace AdvancedDetector { GameDescriptor findGameID( const char *gameid, - const PlainGameDescriptor *list, + const PlainGameDescriptor *gameDescriptors, const ADObsoleteGameID *obsoleteList ) { - // First search the list of supported game IDs for a match. - const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, list); + // First search the list of supported gameids for a match. + const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, gameDescriptors); if (g) return GameDescriptor(*g); @@ -124,7 +79,7 @@ GameDescriptor findGameID( const ADObsoleteGameID *o = obsoleteList; while (o->from) { if (0 == scumm_stricmp(gameid, o->from)) { - g = findPlainGameDescriptor(o->to, list); + g = findPlainGameDescriptor(o->to, gameDescriptors); if (g && g->description) return GameDescriptor(gameid, "Obsolete game ID (" + Common::String(g->description) + ")"); else @@ -190,7 +145,7 @@ static Common::String generatePreferredTarget(const Common::String &id, const AD return res; } -static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc, const ADParams ¶ms) { +void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const { if (params.singleid != NULL) { desc["preferredtarget"] = desc["gameid"]; desc["gameid"] = params.singleid; @@ -235,7 +190,7 @@ bool cleanupPirated(ADGameDescList &matched) { GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { - ADGameDescList matches = detectGame(fslist, params, Common::UNK_LANG, Common::kPlatformUnknown, ""); + ADGameDescList matches = detectGame(fslist, Common::UNK_LANG, Common::kPlatformUnknown, ""); GameList detectedGames; if (cleanupPirated(matches)) @@ -245,15 +200,15 @@ GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { // Use fallback detector if there were no matches by other means const ADGameDescription *fallbackDesc = fallbackDetect(fslist); if (fallbackDesc != 0) { - GameDescriptor desc(toGameDescriptor(*fallbackDesc, params.list)); - updateGameDescriptor(desc, fallbackDesc, params); + GameDescriptor desc(toGameDescriptor(*fallbackDesc, params.gameDescriptors)); + updateGameDescriptor(desc, fallbackDesc); detectedGames.push_back(desc); } } else { // Otherwise use the found matches for (uint i = 0; i < matches.size(); i++) { - GameDescriptor desc(toGameDescriptor(*matches[i], params.list)); - updateGameDescriptor(desc, matches[i], params); + GameDescriptor desc(toGameDescriptor(*matches[i], params.gameDescriptors)); + updateGameDescriptor(desc, matches[i]); detectedGames.push_back(desc); } } @@ -263,7 +218,7 @@ GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) const { assert(engine); - upgradeTargetIfNecessary(params); + upgradeTargetIfNecessary(); const ADGameDescription *agdDesc = 0; Common::Language language = Common::UNK_LANG; @@ -306,7 +261,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) return Common::kNoGameDataFoundError; } - ADGameDescList matches = detectGame(files, params, language, platform, extra); + ADGameDescList matches = detectGame(files, language, platform, extra); if (cleanupPirated(matches)) return Common::kNoGameDataFoundError; @@ -345,7 +300,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions, lang); - debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str()); + debug(2, "Running %s", toGameDescriptor(*agdDesc, params.gameDescriptors).description().c_str()); if (!createInstance(syst, engine, agdDesc)) return Common::kNoGameDataFoundError; else @@ -358,7 +313,6 @@ struct SizeMD5 { }; typedef Common::HashMap<Common::String, SizeMD5, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SizeMD5Map; -typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap; static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSizeMD5) { // TODO: This message should be cleaned up / made more specific. @@ -366,36 +320,36 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz // // Might also be helpful to display the full path (for when this is used // from the mass detector). - printf("The game in '%s' seems to be unknown.\n", path.getPath().c_str()); - printf("Please, report the following data to the ScummVM team along with name\n"); - printf("of the game you tried to add and its version/language/etc.:\n"); + Common::String report = Common::String::format(_("The game in '%s' seems to be unknown."), path.getPath().c_str()) + "\n"; + report += _("Please, report the following data to the ScummVM team along with name"); + report += "\n"; + report += _("of the game you tried to add and its version/language/etc.:"); + report += "\n"; for (SizeMD5Map::const_iterator file = filesSizeMD5.begin(); file != filesSizeMD5.end(); ++file) - printf(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5.c_str(), file->_value.size); + report += Common::String::format(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5.c_str(), file->_value.size); - printf("\n"); -} + report += "\n"; -static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams ¶ms); + g_system->logMessage(LogMessageType::kInfo, report.c_str()); +} -static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth, const char * const *directoryGlobs) { +void AdvancedMetaEngine::composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth) const { if (depth <= 0) return; if (fslist.empty()) return; - // First we compose a hashmap of all files in fslist. - // Includes nifty stuff like removing trailing dots and ignoring case. for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) { Common::FSList files; - if (!directoryGlobs) + if (!params.directoryGlobs) continue; bool matched = false; - for (const char * const *glob = directoryGlobs; *glob; glob++) + for (const char * const *glob = params.directoryGlobs; *glob; glob++) if (file->getName().matchString(*glob, true)) { matched = true; break; @@ -407,7 +361,7 @@ static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, if (!file->getChildren(files, Common::FSNode::kListAll)) continue; - composeFileHashMap(files, allFiles, depth - 1, directoryGlobs); + composeFileHashMap(files, allFiles, depth - 1); } Common::String tstr = file->getName(); @@ -420,7 +374,7 @@ static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, } } -static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String &extra) { +ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSList &fslist, Common::Language language, Common::Platform platform, const Common::String &extra) const { FileMap allFiles; SizeMD5Map filesSizeMD5; @@ -434,8 +388,7 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p debug(3, "Starting detection in dir '%s'", parent.getPath().c_str()); // First we compose a hashmap of all files in fslist. - // Includes nifty stuff like removing trailing dots and ignoring case. - composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth), params.directoryGlobs); + composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth)); // Check which files are included in some ADGameDescription *and* present // in fslist. Compute MD5s and file sizes for these files. @@ -453,16 +406,14 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p // file and as one with resource fork. if (g->flags & ADGF_MACRESFORK) { - Common::MacResManager *macResMan = new Common::MacResManager(); + Common::MacResManager macResMan; - if (macResMan->open(parent, fname)) { - tmp.md5 = macResMan->computeResForkMD5AsString(params.md5Bytes); - tmp.size = macResMan->getResForkDataSize(); + if (macResMan.open(parent, fname)) { + tmp.md5 = macResMan.computeResForkMD5AsString(params.md5Bytes); + tmp.size = macResMan.getResForkDataSize(); debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5.c_str()); filesSizeMD5[fname] = tmp; } - - delete macResMan; } else { if (allFiles.contains(fname)) { debug(3, "+ %s", fname.c_str()); @@ -575,19 +526,13 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p // Filename based fallback if (params.fileBasedFallback != 0) - matched = detectGameFilebased(allFiles, params); + matched = detectGameFilebased(allFiles); } return matched; } -/** - * Check for each ADFileBasedFallback record whether all files listed - * in it are present. If multiple pass this test, we pick the one with - * the maximal number of matching files. In case of a tie, the entry - * coming first in the list is chosen. - */ -static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams ¶ms) { +ADGameDescList AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles) const { const ADFileBasedFallback *ptr; const char* const* filenames; @@ -626,10 +571,14 @@ static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParam if (matchedDesc) { // We got a match matched.push_back(matchedDesc); if (params.flags & kADFlagPrintWarningOnFileBasedFallback) { - printf("Your game version has been detected using filename matching as a\n"); - printf("variant of %s.\n", matchedDesc->gameid); - printf("If this is an original and unmodified version, please report any\n"); - printf("information previously printed by ScummVM to the team.\n"); + Common::String report = Common::String::format(_("Your game version has been detected using " + "filename matching as a variant of %s."), matchedDesc->gameid); + report += "\n"; + report += _("If this is an original and unmodified version, please report any"); + report += "\n"; + report += _("information previously printed by ScummVM to the team."); + report += "\n"; + g_system->logMessage(LogMessageType::kInfo, report.c_str()); } } @@ -637,8 +586,38 @@ static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParam } GameList AdvancedMetaEngine::getSupportedGames() const { - return gameIDList(params); + if (params.singleid != NULL) { + GameList gl; + + const PlainGameDescriptor *g = params.gameDescriptors; + while (g->gameid) { + if (0 == scumm_stricmp(params.singleid, g->gameid)) { + gl.push_back(GameDescriptor(g->gameid, g->description)); + + return gl; + } + g++; + } + error("Engine %s doesn't have its singleid specified in ids list", params.singleid); + } + + return GameList(params.gameDescriptors); } + GameDescriptor AdvancedMetaEngine::findGame(const char *gameid) const { - return AdvancedDetector::findGameID(gameid, params.list, params.obsoleteList); + return AdvancedDetector::findGameID(gameid, params.gameDescriptors, params.obsoleteList); +} + +AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameDescriptors) { + params.descs = (const byte *)descs; + params.descItemSize = descItemSize; + params.md5Bytes = 5000; + params.gameDescriptors = gameDescriptors; + params.obsoleteList = NULL; + params.singleid = NULL; + params.fileBasedFallback = NULL; + params.flags = 0; + params.guioptions = Common::GUIO_NONE; + params.depth = 1; + params.directoryGlobs = NULL; } diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index 408c46556d..e5922bea4a 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -71,6 +71,11 @@ struct ADGameDescription { }; /** + * A list of pointers to ADGameDescription structs (or subclasses thereof). + */ +typedef Common::Array<const ADGameDescription*> ADGameDescList; + +/** * End marker for a table of ADGameDescription structs. Use this to * terminate a list to be passed to the AdvancedDetector API. */ @@ -148,7 +153,7 @@ struct ADParams { * A list of all gameids (and their corresponding descriptions) supported * by this engine. */ - const PlainGameDescriptor *list; + const PlainGameDescriptor *gameDescriptors; /** * Structure for autoupgrading obsolete targets (optional). @@ -214,7 +219,7 @@ namespace AdvancedDetector { */ GameDescriptor findGameID( const char *gameid, - const PlainGameDescriptor *list, + const PlainGameDescriptor *gameDescriptors, const ADObsoleteGameID *obsoleteList = 0 ); @@ -224,16 +229,26 @@ GameDescriptor findGameID( * A MetaEngine implementation based around the advanced detector code. */ class AdvancedMetaEngine : public MetaEngine { - const ADParams ¶ms; +protected: + ADParams params; public: AdvancedMetaEngine(const ADParams &dp) : params(dp) {} + AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameDescriptors); + /** + * Returns list of targets supported by the engine. + * Distinguishes engines with single ID + */ virtual GameList getSupportedGames() const; + virtual GameDescriptor findGame(const char *gameid) const; + virtual GameList detectGames(const Common::FSList &fslist) const; + virtual Common::Error createInstance(OSystem *syst, Engine **engine) const; - // To be provided by subclasses +protected: + // To be implemented by subclasses virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const = 0; /** @@ -244,6 +259,40 @@ public: virtual const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const { return 0; } + +protected: + typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap; + + /** + * Detect games in specified directory. + * Parameters language and platform are used to pass on values + * specified by the user. I.e. this is used to restrict search scope. + * + * @param fslist FSList to scan or NULL for scanning all specified + * default directories. + * @param language restrict results to specified language only + * @param platform restrict results to specified platform only + * @return list of ADGameDescription (or subclass) pointers corresponding to matched games + */ + ADGameDescList detectGame(const Common::FSList &fslist, Common::Language language, Common::Platform platform, const Common::String &extra) const; + + /** + * Check for each ADFileBasedFallback record whether all files listed + * in it are present. If multiple pass this test, we pick the one with + * the maximal number of matching files. In case of a tie, the entry + * coming first in the list is chosen. + */ + ADGameDescList detectGameFilebased(const FileMap &allFiles) const; + + void upgradeTargetIfNecessary() const; + + void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const; + + /** + * Compose a hashmap of all files in fslist. + * Includes nifty stuff like removing trailing dots and ignoring case. + */ + void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth) const; }; #endif diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 78316588b0..811a58f45d 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -131,46 +131,65 @@ void AgiEngine::processEvents() { switch (key = event.kbd.keycode) { case Common::KEYCODE_LEFT: case Common::KEYCODE_KP4: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP4) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_LEFT; break; case Common::KEYCODE_RIGHT: case Common::KEYCODE_KP6: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP6) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_RIGHT; break; case Common::KEYCODE_UP: case Common::KEYCODE_KP8: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP8) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_UP; break; case Common::KEYCODE_DOWN: case Common::KEYCODE_KP2: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP2) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_DOWN; break; case Common::KEYCODE_PAGEUP: case Common::KEYCODE_KP9: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP9) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_UP_RIGHT; break; case Common::KEYCODE_PAGEDOWN: case Common::KEYCODE_KP3: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP3) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_DOWN_RIGHT; break; case Common::KEYCODE_HOME: case Common::KEYCODE_KP7: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP7) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_UP_LEFT; break; case Common::KEYCODE_END: case Common::KEYCODE_KP1: - if (_allowSynthetic || !event.synthetic) + if (_predictiveDialogRunning && key == Common::KEYCODE_KP1) + key = event.kbd.ascii; + else if (_allowSynthetic || !event.synthetic) key = KEY_DOWN_LEFT; break; case Common::KEYCODE_KP5: - key = KEY_STATIONARY; + if (_predictiveDialogRunning) + key = event.kbd.ascii; + else + key = KEY_STATIONARY; break; case Common::KEYCODE_PLUS: key = '+'; diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index 22d8adf92d..b0e055edcc 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -129,31 +129,6 @@ static const PlainGameDescriptor agiGames[] = { #include "agi/detection_tables.h" -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Agi::gameDescriptions, - // Size of that superset structure - sizeof(Agi::AGIGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - agiGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "agi", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOSPEECH, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - using namespace Agi; class AgiMetaEngine : public AdvancedMetaEngine { @@ -161,7 +136,10 @@ class AgiMetaEngine : public AdvancedMetaEngine { mutable Common::String _extra; public: - AgiMetaEngine() : AdvancedMetaEngine(detectionParams) {} + AgiMetaEngine() : AdvancedMetaEngine(Agi::gameDescriptions, sizeof(Agi::AGIGameDescription), agiGames) { + params.singleid = "agi"; + params.guioptions = Common::GUIO_NOSPEECH; + } virtual const char *getName() const { return "AGI preAGI + v2 + v3"; diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index 80e89f410b..edfe83b1cb 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -190,7 +190,7 @@ bool AgiEngine::predictiveDialog() { bool needRefresh = true; - for (;;) { + while (!shouldQuit()) { if (needRefresh) { for (int i = 0; buttons[i]; i++) { int color1 = colors[i * 2]; @@ -573,8 +573,10 @@ bool AgiEngine::matchWord() { hi = line - 1; else if (cmpVal < 0) lo = line + 1; - else + else { hi = line; + break; + } } _currentWord.clear(); diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp index 6d64c29de9..3c8a3dfc8d 100644 --- a/engines/agi/sound_2gs.cpp +++ b/engines/agi/sound_2gs.cpp @@ -135,7 +135,7 @@ void SoundGen2GS::stop() { * Fill output buffer by advancing the generators for a 1/60th of a second. * @return Number of generated samples */ -uint32 SoundGen2GS::generateOutput() { +uint SoundGen2GS::generateOutput() { memset(_out, 0, _outSize * 2 * 2); if (!_playing || _playingSound == -1) diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp index 319b7049ed..fdebf16b1a 100644 --- a/engines/agi/sound_pcjr.cpp +++ b/engines/agi/sound_pcjr.cpp @@ -219,6 +219,7 @@ int SoundGenPCJr::volumeCalc(SndGenChan *chan) { // return 0 if it's passing more data // return -1 if it's passing nothing (end of data) int SoundGenPCJr::getNextNote(int ch, Tone *tone) { + ToneChan *tpcm; SndGenChan *chan; const byte *data; @@ -228,6 +229,7 @@ int SoundGenPCJr::getNextNote(int ch, Tone *tone) { if (!_vm->getflag(fSoundOn)) return -1; + tpcm = &_tchannel[ch]; chan = &_channel[ch]; if (!chan->avail) return -1; @@ -241,6 +243,9 @@ int SoundGenPCJr::getNextNote(int ch, Tone *tone) { // if it's 0 then it's not going to be played // if it's 0xFFFF then the channel data has finished. if ((chan->duration != 0) && (chan->duration != 0xFFFF)) { + tpcm->genTypePrev = -1; + tpcm->freqCountPrev = -1; + // only tone channels dissolve if ((ch != 3) && (_dissolveMethod != 0)) // != noise?? chan->dissolveCount = 0; diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index 629a5d63fc..dbd1743304 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -63,7 +63,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { {0, 0, Common::kPlatformUnknown} }; -static const PlainGameDescriptor simonGames[] = { +static const PlainGameDescriptor agosGames[] = { {"pn", "Personal Nightmare"}, {"elvira1", "Elvira - Mistress of the Dark"}, {"elvira2", "Elvira II - The Jaws of Cerberus"}, @@ -87,36 +87,16 @@ static const char *directoryGlobs[] = { 0 }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)AGOS::gameDescriptions, - // Size of that superset structure - sizeof(AGOS::AGOSGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - simonGames, - // Structure for autoupgrading obsolete targets - obsoleteGameIDsTable, - // Name of single gameid (optional) - 0, - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD, - // Maximum directory depth - 2, - // List of directory globs - directoryGlobs -}; - using namespace AGOS; class AgosMetaEngine : public AdvancedMetaEngine { public: - AgosMetaEngine() : AdvancedMetaEngine(detectionParams) {} + AgosMetaEngine() : AdvancedMetaEngine(AGOS::gameDescriptions, sizeof(AGOS::AGOSGameDescription), agosGames) { + params.obsoleteList = obsoleteGameIDsTable; + params.guioptions = Common::GUIO_NOLAUNCHLOAD; + params.depth = 2; + params.directoryGlobs = directoryGlobs; + } virtual const char *getName() const { return "AGOS"; diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index 738366124c..89c81c2599 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -60,34 +60,13 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { #include "cine/detection_tables.h" -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Cine::gameDescriptions, - // Size of that superset structure - sizeof(Cine::CINEGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - cineGames, - // Structure for autoupgrading obsolete targets - obsoleteGameIDsTable, - // Name of single gameid (optional) - "cine", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class CineMetaEngine : public AdvancedMetaEngine { public: - CineMetaEngine() : AdvancedMetaEngine(detectionParams) {} + CineMetaEngine() : AdvancedMetaEngine(Cine::gameDescriptions, sizeof(Cine::CINEGameDescription), cineGames) { + params.obsoleteList = obsoleteGameIDsTable; + params.singleid = "cine"; + params.guioptions = Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI; + } virtual const char *getName() const { return "Cine"; diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index 3bd0c1f76f..f6f8db4f3a 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -217,34 +217,12 @@ static const CRUISEGameDescription gameDescriptions[] = { } -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Cruise::gameDescriptions, - // Size of that superset structure - sizeof(Cruise::CRUISEGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - cruiseGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "cruise", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class CruiseMetaEngine : public AdvancedMetaEngine { public: - CruiseMetaEngine() : AdvancedMetaEngine(detectionParams) {} + CruiseMetaEngine() : AdvancedMetaEngine(Cruise::gameDescriptions, sizeof(Cruise::CRUISEGameDescription), cruiseGames) { + params.singleid = "cruise"; + params.guioptions = Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI; + } virtual const char *getName() const { return "CruisE"; diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp index d3483eb5a4..cf0413ffa9 100644 --- a/engines/draci/detection.cpp +++ b/engines/draci/detection.cpp @@ -83,34 +83,11 @@ const ADGameDescription gameDescriptions[] = { } // End of namespace Draci -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Draci::gameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - draciGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "draci", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class DraciMetaEngine : public AdvancedMetaEngine { public: - DraciMetaEngine() : AdvancedMetaEngine(detectionParams) {} + DraciMetaEngine() : AdvancedMetaEngine(Draci::gameDescriptions, sizeof(ADGameDescription), draciGames) { + params.singleid = "draci"; + } virtual const char *getName() const { return "Draci"; diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 5a8903db9d..9494bfa66b 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -266,34 +266,12 @@ static const DrasculaGameDescription gameDescriptions[] = { } // End of namespace Drascula -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Drascula::gameDescriptions, - // Size of that superset structure - sizeof(Drascula::DrasculaGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - drasculaGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "drascula", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class DrasculaMetaEngine : public AdvancedMetaEngine { public: - DrasculaMetaEngine() : AdvancedMetaEngine(detectionParams) {} + DrasculaMetaEngine() : AdvancedMetaEngine(Drascula::gameDescriptions, sizeof(Drascula::DrasculaGameDescription), drasculaGames) { + params.singleid = "drascula"; + params.guioptions = Common::GUIO_NOMIDI | Common::GUIO_NOLAUNCHLOAD; + } virtual const char *getName() const { return "Drascula"; diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index be44c05bfb..2ecd6b741e 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -86,34 +86,14 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { #include "gob/detection_tables.h" -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Gob::gameDescriptions, - // Size of that superset structure - sizeof(Gob::GOBGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - gobGames, - // Structure for autoupgrading obsolete targets - obsoleteGameIDsTable, - // Name of single gameid (optional) - "gob", - // List of files for file-based fallback detection (optional) - Gob::fileBased, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class GobMetaEngine : public AdvancedMetaEngine { public: - GobMetaEngine() : AdvancedMetaEngine(detectionParams) {} + GobMetaEngine() : AdvancedMetaEngine(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) { + params.obsoleteList = obsoleteGameIDsTable; + params.singleid = "gob"; + params.fileBasedFallback = Gob::fileBased; + params.guioptions = Common::GUIO_NOLAUNCHLOAD; + } virtual const char *getName() const { return "Gob"; diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index 0dd510abca..62ee65d74a 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -202,35 +202,13 @@ static const GroovieGameDescription gameDescriptions[] = { {AD_TABLE_END_MARKER, kGroovieT7G, 0} }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)gameDescriptions, - // Size of that superset structure - sizeof(GroovieGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - groovieGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "groovie", - // List of files for file-based fallback detection (optional) - 0, - // Flags - kADFlagUseExtraAsHint, - // Additional GUI options (for every game} - Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - - class GroovieMetaEngine : public AdvancedMetaEngine { public: - GroovieMetaEngine() : AdvancedMetaEngine(detectionParams) {} + GroovieMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(GroovieGameDescription), groovieGames) { + params.singleid = "groovie"; + params.flags = kADFlagUseExtraAsHint; + params.guioptions = Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX; + } const char *getName() const { return "Groovie"; diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 8b6ee2ca42..5f95de649a 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -336,11 +336,6 @@ bool GroovieEngine::hasFeature(EngineFeature f) const { (f == kSupportsLoadingDuringRuntime); } -void GroovieEngine::errorString(const char *buf_input, char *buf_output, int buf_output_size) { - //snprintf(buf_output, buf_output_size, "%s%s\n", _script.getContext().c_str(), buf_input); - snprintf(buf_output, buf_output_size, "%s", buf_input); -} - void GroovieEngine::syncSoundSettings() { Engine::syncSoundSettings(); diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index eb64cfc60a..df2f062757 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -91,7 +91,6 @@ protected: // Engine APIs Common::Error run(); - virtual void errorString(const char *buf_input, char *buf_output, int buf_output_size); virtual bool hasFeature(EngineFeature f) const; diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 9a3903e9dc..33fc986193 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -845,6 +845,9 @@ bool MusicPlayerIOS::load(uint32 fileref, bool loop) { if (loop) audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0); + // MIDI player handles volume reset on load, IOS player doesn't - force update here + updateVolume(); + // Play! _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_handle, audStream); return true; diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp index 05b43b7d3c..c26f04d6ee 100644 --- a/engines/groovie/resource.cpp +++ b/engines/groovie/resource.cpp @@ -169,7 +169,7 @@ bool ResMan_t7g::getResInfo(uint32 fileRef, ResInfo &resInfo) { error("Groovie::Resource: Invalid resource number: 0x%04X (%s)", resNum, rlFileName.c_str()); } - // Read the resource name (just for debugging purposes) + // Read the resource name char resname[13]; rlFile->read(resname, 12); resname[12] = 0; @@ -240,7 +240,7 @@ uint32 ResMan_v2::getRef(Common::String name, Common::String scriptname) { // Test whether it's the resource we're searching Common::String resname(readname, 18); if (resname.hasPrefix(name.c_str())) { - debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource %12s matches %s", readname, name.c_str()); + debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource %18s matches %s", readname, name.c_str()); found = true; } } @@ -279,10 +279,11 @@ bool ResMan_v2::getResInfo(uint32 fileRef, ResInfo &resInfo) { resInfo.size = rlFile.readUint32LE(); resInfo.gjd = rlFile.readUint16LE(); - // Read the resource name (just for debugging purposes) - char resname[12]; - rlFile.read(resname, 12); - debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %12s", resname); + // Read the resource name + char resname[19]; + resname[18] = 0; + rlFile.read(resname, 18); + debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %18s", resname); resInfo.filename = resname; // 6 padding bytes? (it looks like they're always 0) diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp index 25b8b16084..f70a21aa8f 100644 --- a/engines/hugo/detection.cpp +++ b/engines/hugo/detection.cpp @@ -131,34 +131,10 @@ static const HugoGameDescription gameDescriptions[] = { {AD_TABLE_END_MARKER, kGameTypeNone} }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)gameDescriptions, - // Size of that superset structure - sizeof(HugoGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - hugoGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - 0, - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class HugoMetaEngine : public AdvancedMetaEngine { public: - HugoMetaEngine() : AdvancedMetaEngine(detectionParams) {} + HugoMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(HugoGameDescription), hugoGames) { + } const char *getName() const { return "Hugo"; diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp index 6db2e45b0e..84bda3f3fd 100644 --- a/engines/kyra/animator_mr.cpp +++ b/engines/kyra/animator_mr.cpp @@ -449,11 +449,10 @@ void KyraEngine_MR::showIdleAnim() { "A", "R", "R", "FR", "FX", "FL", "L", "L" }; - char filename[14]; - snprintf(filename, 14, "MI0%s%.02d.EMC", facingTable[_mainCharacter.facing], _characterShapeFile); + Common::String filename = Common::String::format( "MI0%s%.02d.EMC", facingTable[_mainCharacter.facing], _characterShapeFile); - if (_res->exists(filename)) - runAnimationScript(filename, 1, 1, 1, 1); + if (_res->exists(filename.c_str())) + runAnimationScript(filename.c_str(), 1, 1, 1, 1); } _nextIdleType = !_nextIdleType; diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 47a086e08c..6589c2b45b 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -47,37 +47,15 @@ const char * const directoryGlobs[] = { 0 }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)adGameDescs, - // Size of that superset structure - sizeof(KYRAGameDescription), - // Number of bytes to compute MD5 sum for - 1024 * 1024, - // List of all engine targets - gameList, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - 0, - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 2, - // List of directory globs - directoryGlobs -}; - } // End of anonymous namespace class KyraMetaEngine : public AdvancedMetaEngine { public: - KyraMetaEngine() : AdvancedMetaEngine(detectionParams) {} - + KyraMetaEngine() : AdvancedMetaEngine(adGameDescs, sizeof(KYRAGameDescription), gameList) { + params.md5Bytes = 1024 * 1024; + params.depth = 2; + params.directoryGlobs = directoryGlobs; + } const char *getName() const { return "Kyra"; } diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h index 8a948eff00..47a3c4362a 100644 --- a/engines/kyra/detection_tables.h +++ b/engines/kyra/detection_tables.h @@ -47,6 +47,7 @@ namespace { #define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3) #define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL) +#define LOL_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_LOL) #define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL) #define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL) #define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL) @@ -1056,6 +1057,109 @@ const KYRAGameDescription adGameDescs[] = { LOL_CD_FLAGS }, + // Italian fan translation + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "898485c0eb7bb4403fdd63bf5191f37e", -1 }, + { 0, 0, 0, 0 } + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "898485c0eb7bb4403fdd63bf5191f37e", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "898485c0eb7bb4403fdd63bf5191f37e", -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "898485c0eb7bb4403fdd63bf5191f37e", -1 }, + { 0, 0, 0, 0 } + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "898485c0eb7bb4403fdd63bf5191f37e", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "898485c0eb7bb4403fdd63bf5191f37e", -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + { { "lol", @@ -1222,7 +1326,6 @@ const KYRAGameDescription adGameDescs[] = { LOL_KYRA2_DEMO_FLAGS }, #endif // ENABLE_LOL - { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) } }; diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index 4c4dc50503..fb11040168 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -2806,15 +2806,18 @@ int GUI_LoL::clickedOptionsMenu(Button *button) { case 0xfff3: _vm->_configVoice ^= 3; break; - case 0x4072: - char filename[13]; - snprintf(filename, sizeof(filename), "LEVEL%02d.%s", _vm->_currentLevel, _vm->_languageExt[_vm->_lang]); + case 0x4072: { + Common::String filename; + filename = Common::String::format("LEVEL%02d.%s", _vm->_currentLevel, _vm->_languageExt[_vm->_lang]); delete[] _vm->_levelLangFile; - _vm->_levelLangFile = _vm->resource()->fileData(filename, 0); - snprintf(filename, sizeof(filename), "LANDS.%s", _vm->_languageExt[_vm->_lang]); + _vm->_levelLangFile = _vm->resource()->fileData(filename.c_str(), 0); + filename = Common::String::format("LANDS.%s", _vm->_languageExt[_vm->_lang]); delete[] _vm->_landsFile; - _vm->_landsFile = _vm->resource()->fileData(filename, 0); + _vm->_landsFile = _vm->resource()->fileData(filename.c_str(), 0); _newMenu = _lastMenu; + } break; + default: + // TODO: Is there anything we should do if we hit this case? break; } diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index 25a77c6cc8..32eb02e06d 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -717,25 +717,25 @@ void KyraEngine_MR::showAlbum() { } void KyraEngine_MR::loadAlbumPage() { - char filename[16]; + Common::String filename; int num = _album.curPage / 2; if (num == 0) { - strcpy(filename, "ALBUM0.CPS"); + filename = "ALBUM0.CPS"; } else if (num >= 1 && num <= 6) { --num; num %= 2; - snprintf(filename, 16, "ALBUM%d.CPS", num+1); + filename = Common::String::format("ALBUM%d.CPS", num+1); } else { - strcpy(filename, "ALBUM3.CPS"); + filename = "ALBUM3.CPS"; } _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 4, Screen::CR_NO_P_CHECK); - _screen->loadBitmap(filename, 3, 3, 0); + _screen->loadBitmap(filename.c_str(), 3, 3, 0); } void KyraEngine_MR::loadAlbumPageWSA() { - char filename[16]; + Common::String filename; _album.leftPage.curFrame = 0; _album.leftPage.maxFrame = 0; @@ -746,14 +746,14 @@ void KyraEngine_MR::loadAlbumPageWSA() { _album.rightPage.wsa->close(); if (_album.curPage) { - snprintf(filename, 16, "PAGE%x.WSA", _album.curPage); - _album.leftPage.wsa->open(filename, 1, 0); + filename = Common::String::format("PAGE%x.WSA", _album.curPage); + _album.leftPage.wsa->open(filename.c_str(), 1, 0); _album.leftPage.maxFrame = _album.leftPage.wsa->frames()-1; } if (_album.curPage != 14) { - snprintf(filename, 16, "PAGE%x.WSA", _album.curPage+1); - _album.rightPage.wsa->open(filename, 1, 0); + filename = Common::String::format("PAGE%x.WSA", _album.curPage+1); + _album.rightPage.wsa->open(filename.c_str(), 1, 0); _album.rightPage.maxFrame = _album.leftPage.wsa->frames()-1; } } diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index b6388604f5..2cf2cb2c70 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -396,20 +396,20 @@ bool LoLEngine::launchObject(int objectType, Item item, int startX, int startY, return true; } -void LoLEngine::endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock) { +void LoLEngine::endObjectFlight(FlyingObject *t, int x, int y, int collisionObject) { int cx = x; int cy = y; uint16 block = calcBlockIndex(t->x, t->y); removeAssignedObjectFromBlock(&_levelBlockProperties[block], t->item); removeDrawObjectFromBlock(&_levelBlockProperties[block], t->item); - if (objectOnNextBlock == 1) { + if (collisionObject == 1) { cx = t->x; cy = t->y; } if (t->objectType == 0 || t->objectType == 1) { - objectFlightProcessHits(t, cx, cy, objectOnNextBlock); + objectFlightProcessHits(t, cx, cy, collisionObject); t->x = (cx & 0xffc0) | 0x40; t->y = (cy & 0xffc0) | 0x40; t->flyingHeight = 0; @@ -481,8 +481,24 @@ void LoLEngine::updateFlyingObject(FlyingObject *t) { int x = 0; int y = 0; getNextStepCoords(t->x, t->y, x, y, t->direction); - // WORKAROUND: The next line seems to be bugged in the original code. I have fixed it in a way that at least seems to work fine. - int objectOnNextBlock = checkBlockBeforeObjectPlacement(x, y, _itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000 ? 127 : 63, t->flags, t->wallFlags); + /* WORKAROUND: + Large fireballs cast by the "birds" in white tower level 2 and by the "wraith knights" in castle cimmeria + level 1 (or possible other objects with flag 0x4000) could not fly through corridors in ScummVM and would + be terminated prematurely. The original code (all versions) involuntarily circumvents this via a bug in the + next line of code. + The original checks for _itemProperties[t->item].flags instead of _itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags. + This leads to more or less unpredictable object widths. The large fireballs will usually get a width of 63 + instead of 256 making them work just fine in the original. + + I have fixed this by setting an object width of 63 of here. This produces results faithful to the original + at least. + + Other methods of working around this issue don't make too much sense. An object with a width of 256 + could never fly through corridors, since 256 is also the width of a block. Aligning the fireballs to the + middle of a block (or making the monsters align to the middle before casting them) wouldn't help here + (and wouldn't be faithful to the original either). + */ + int objectOnNextBlock = checkBlockBeforeObjectPlacement(x, y, /*_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000 ? 256 :*/ 63, t->flags, t->wallFlags); if (objectOnNextBlock) { endObjectFlight(t, x, y, objectOnNextBlock); } else { diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 4ce5c5b2cf..973ab25088 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -366,10 +366,9 @@ void KyraEngine_MR::uninitMainMenu() { void KyraEngine_MR::playVQA(const char *name) { VQAMovie vqa(this, _system); - char filename[20]; - snprintf(filename, sizeof(filename), "%s%d.VQA", name, _configVQAQuality); + Common::String filename = Common::String::format("%s%d.VQA", name, _configVQAQuality); - if (vqa.open(filename)) { + if (vqa.open(filename.c_str())) { for (int i = 0; i < 4; ++i) { if (i != _musicSoundChannel) _soundDigital->stopSound(i); @@ -444,12 +443,11 @@ void KyraEngine_MR::fadeOutMusic(int ticks) { void KyraEngine_MR::snd_playSoundEffect(int item, int volume) { if (_sfxFileMap[item*2+0] != 0xFF) { - char filename[16]; assert(_sfxFileMap[item*2+0] < _sfxFileListSize); - snprintf(filename, 16, "%s", _sfxFileList[_sfxFileMap[item*2+0]]); + Common::String filename = Common::String::format("%s", _sfxFileList[_sfxFileMap[item*2+0]]); uint8 priority = _sfxFileMap[item*2+1]; - _soundDigital->playSound(filename, priority, Audio::Mixer::kSFXSoundType, volume); + _soundDigital->playSound(filename.c_str(), priority, Audio::Mixer::kSFXSoundType, volume); } } @@ -458,11 +456,10 @@ void KyraEngine_MR::playVoice(int high, int low) { } void KyraEngine_MR::snd_playVoiceFile(int file) { - char filename[16]; - snprintf(filename, 16, "%.08u", (uint)file); + Common::String filename = Common::String::format("%.08u", (uint)file); if (speechEnabled()) - _voiceSoundChannel = _soundDigital->playSound(filename, 0xFE, Audio::Mixer::kSpeechSoundType, 255); + _voiceSoundChannel = _soundDigital->playSound(filename.c_str(), 0xFE, Audio::Mixer::kSpeechSoundType, 255); } bool KyraEngine_MR::snd_voiceIsPlaying() { @@ -1242,26 +1239,14 @@ void KyraEngine_MR::restoreGfxRect32x32(int x, int y) { #pragma mark - -char *KyraEngine_MR::appendLanguage(char *buf, int lang, int bufSize) { - assert(lang < _languageExtensionSize); - - const int size = Common::strlcat(buf, _languageExtension[lang], bufSize); - if (size >= bufSize) { - warning("buffer too small to append language extension"); - return 0; - } - - return buf; -} - int KyraEngine_MR::loadLanguageFile(const char *file, uint8 *&buffer) { delete[] buffer; buffer = 0; uint32 size = 0; - char nBuf[32]; - Common::strlcpy(nBuf, file, sizeof(nBuf)); - buffer = _res->fileData(appendLanguage(nBuf, _lang, sizeof(nBuf)), &size); + Common::String nBuf = file; + nBuf += _languageExtension[_lang]; + buffer = _res->fileData(nBuf.c_str(), &size); return buffer ? size : 0; } diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 0d9d66ce95..b762648d29 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -662,8 +662,6 @@ private: static const char *_languageExtension[]; static const int _languageExtensionSize; - char *appendLanguage(char *buf, int lang, int bufSize); - int loadLanguageFile(const char *file, uint8 *&buffer); }; diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index f108082e13..f79fabf9eb 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -93,15 +93,6 @@ Common::Error KyraEngine_v1::init() { syncSoundSettings(); if (!_flags.useDigSound) { - // In Kyra 1 users who have specified a default MT-32 device in the launcher settings - // will get MT-32 music, otherwise AdLib. In Kyra 2 and LoL users who have specified a - // default GM device in the launcher will get GM music, otherwise AdLib. Users who want - // MT-32 music in Kyra2 or LoL have to select this individually (since we assume that - // most users rather have a GM device than a MT-32 device). - // Users who want PC speaker sound always have to select this individually for all - // Kyra games. - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | ((_flags.gameID == GI_KYRA2 || _flags.gameID == GI_LOL) ? MDT_PREFER_GM : MDT_PREFER_MT32)); - if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) _sound = new SoundTowns(this, _mixer); @@ -114,43 +105,53 @@ Common::Error KyraEngine_v1::init() { _sound = new SoundTownsPC98_v2(this, _mixer); } else if (_flags.platform == Common::kPlatformAmiga) { _sound = new SoundAmiga(this, _mixer); - } else if (MidiDriver::getMusicType(dev) == MT_ADLIB) { - _sound = new SoundAdLibPC(this, _mixer); } else { - Sound::kType type; - const MusicType midiType = MidiDriver::getMusicType(dev); + // In Kyra 1 users who have specified a default MT-32 device in the launcher settings + // will get MT-32 music, otherwise AdLib. In Kyra 2 and LoL users who have specified a + // default GM device in the launcher will get GM music, otherwise AdLib. Users who want + // MT-32 music in Kyra2 or LoL have to select this individually (since we assume that + // most users rather have a GM device than a MT-32 device). + // Users who want PC speaker sound always have to select this individually for all + // Kyra games. + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | ((_flags.gameID == GI_KYRA2 || _flags.gameID == GI_LOL) ? MDT_PREFER_GM : MDT_PREFER_MT32)); + if (MidiDriver::getMusicType(dev) == MT_ADLIB) { + _sound = new SoundAdLibPC(this, _mixer); + } else { + Sound::kType type; + const MusicType midiType = MidiDriver::getMusicType(dev); - if (midiType == MT_PCSPK || midiType == MT_NULL) - type = Sound::kPCSpkr; - else if (midiType == MT_MT32 || ConfMan.getBool("native_mt32")) - type = Sound::kMidiMT32; - else - type = Sound::kMidiGM; + if (midiType == MT_PCSPK || midiType == MT_NULL) + type = Sound::kPCSpkr; + else if (midiType == MT_MT32 || ConfMan.getBool("native_mt32")) + type = Sound::kMidiMT32; + else + type = Sound::kMidiGM; - MidiDriver *driver = 0; + MidiDriver *driver = 0; - if (MidiDriver::getMusicType(dev) == MT_PCSPK) { - driver = new MidiDriver_PCSpeaker(_mixer); - } else { - driver = MidiDriver::createMidi(dev); - if (type == Sound::kMidiMT32) - driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - } + if (MidiDriver::getMusicType(dev) == MT_PCSPK) { + driver = new MidiDriver_PCSpeaker(_mixer); + } else { + driver = MidiDriver::createMidi(dev); + if (type == Sound::kMidiMT32) + driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + } - assert(driver); + assert(driver); - SoundMidiPC *soundMidiPc = new SoundMidiPC(this, _mixer, driver, type); - _sound = soundMidiPc; - assert(_sound); + SoundMidiPC *soundMidiPc = new SoundMidiPC(this, _mixer, driver, type); + _sound = soundMidiPc; + assert(_sound); - // Unlike some SCUMM games, it's not that the MIDI sounds are - // missing. It's just that at least at the time of writing they - // are decidedly inferior to the AdLib ones. - if (ConfMan.getBool("multi_midi")) { - SoundAdLibPC *adlib = new SoundAdLibPC(this, _mixer); - assert(adlib); + // Unlike some SCUMM games, it's not that the MIDI sounds are + // missing. It's just that at least at the time of writing they + // are decidedly inferior to the AdLib ones. + if (ConfMan.getBool("multi_midi")) { + SoundAdLibPC *adlib = new SoundAdLibPC(this, _mixer); + assert(adlib); - _sound = new MixedSoundDriver(this, _mixer, soundMidiPc, adlib); + _sound = new MixedSoundDriver(this, _mixer, soundMidiPc, adlib); + } } } diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index bb533b14a5..5b4f3385a4 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -99,7 +99,7 @@ class KyraMetaEngine; * - The Legend of Kyrandia (fully supported, except for Macintosh port, which lacks sound) * - (The) Hand of Fate (fully supported) * - Malcolm's Revenge (fully supported) - * - Lands of Lore: The Throne of Chaos (completable, still work in progress) + * - Lands of Lore: The Throne of Chaos (fully supported) */ namespace Kyra { @@ -418,7 +418,7 @@ protected: void loadGameStateCheck(int slot); virtual Common::Error loadGameState(int slot) = 0; - Common::Error saveGameState(int slot, const char *saveName) { return saveGameStateIntern(slot, saveName, 0); } + Common::Error saveGameState(int slot, const Common::String &desc) { return saveGameStateIntern(slot, desc.c_str(), 0); } virtual Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) = 0; Common::SeekableReadStream *openSaveForReading(const char *filename, SaveHeader &header); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 9b0ae173d5..c567cbb037 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -42,9 +42,13 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _gui = 0; _txt = 0; _tim = 0; - _animator = 0; - switch (_flags.lang) { + _lang = 0; + Common::Language lang = Common::parseLanguage(ConfMan.get("language")); + if (lang == _flags.fanLang && _flags.replacedLang != Common::UNK_LANG) + lang = _flags.replacedLang; + + switch (lang) { case Common::EN_ANY: case Common::EN_USA: case Common::EN_GRB: @@ -576,7 +580,6 @@ Common::Error LoLEngine::go() { _tim = new TIMInterpreter_LoL(this, _screen, _system); assert(_tim); - _animator = _tim->animator(); if (shouldQuit()) return Common::kNoError; @@ -613,11 +616,11 @@ void LoLEngine::preInit() { loadTalkFile(0); - char filename[32]; - snprintf(filename, sizeof(filename), "LANDS.%s", _languageExt[_lang]); - _res->exists(filename, true); + Common::String filename; + filename = Common::String::format("LANDS.%s", _languageExt[_lang]); + _res->exists(filename.c_str(), true); delete[] _landsFile; - _landsFile = _res->fileData(filename, 0); + _landsFile = _res->fileData(filename.c_str(), 0); loadItemIconShapes(); } @@ -1163,9 +1166,8 @@ void LoLEngine::loadCharFaceShapes(int charNum, int id) { if (id < 0) id = -id; - char file[13]; - snprintf(file, sizeof(file), "FACE%02d.SHP", id); - _screen->loadBitmap(file, 3, 3, 0); + Common::String file = Common::String::format("FACE%02d.SHP", id); + _screen->loadBitmap(file.c_str(), 3, 3, 0); const uint8 *p = _screen->getCPagePtr(3); for (int i = 0; i < 40; i++) { @@ -1811,29 +1813,26 @@ void LoLEngine::createTransparencyTables() { } void LoLEngine::updateSequenceBackgroundAnimations() { - if (_updateFlags & 8 || !_animator) + if (_updateFlags & 8 || !_tim) + return; + if (!_tim->animator()) return; for (int i = 0; i < 6; i++) - _animator->update(i); + _tim->animator()->update(i); } void LoLEngine::loadTalkFile(int index) { - char file[8]; - if (index == _curTlkFile) return; - if (_curTlkFile > 0 && index > 0) { - snprintf(file, sizeof(file), "%02d.TLK", _curTlkFile); - _res->unloadPakFile(file); - } + if (_curTlkFile > 0 && index > 0) + _res->unloadPakFile(Common::String::format("%02d.TLK", _curTlkFile)); if (index > 0) _curTlkFile = index; - snprintf(file, sizeof(file), "%02d.TLK", index); - _res->loadPakFile(file); + _res->loadPakFile(Common::String::format("%02d.TLK", index)); } int LoLEngine::characterSays(int track, int charId, bool redraw) { @@ -2702,12 +2701,11 @@ int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) { snd_playSoundEffect(155, -1); - char wsafile[13]; - snprintf(wsafile, 13, "mists%0d.wsa", spellLevel + 1); + Common::String wsafile = Common::String::format("mists%0d.wsa", spellLevel + 1); WSAMovie_v2 *mov = new WSAMovie_v2(this); - mov->open(wsafile, 1, 0); + mov->open(wsafile.c_str(), 1, 0); if (!mov->opened()) - error("Mist: Unable to load mists.wsa"); + error("Mist: Unable to load %s", wsafile.c_str()); snd_playSoundEffect(_mistAnimData[spellLevel].sound, -1); playSpellAnimation(mov, _mistAnimData[spellLevel].part1First, _mistAnimData[spellLevel].part1Last, 7, 112, 0, 0, 0, 0, 0, false); @@ -2720,7 +2718,7 @@ int LoLEngine::processMagicMistOfDoom(int charNum, int spellLevel) { _screen->copyPage(12, 0); updateDrawPage2(); - this->snd_playQueuedEffects(); + snd_playQueuedEffects(); return 1; } @@ -2734,12 +2732,11 @@ int LoLEngine::processMagicLightning(int charNum, int spellLevel) { _lightningDiv = _lightningProps[spellLevel].frameDiv; _lightningFirstSfx = 0; - char wsafile[13]; - snprintf(wsafile, 13, "litning%d.wsa", spellLevel + 1); + Common::String wsafile = Common::String::format("litning%d.wsa", spellLevel + 1); WSAMovie_v2 *mov = new WSAMovie_v2(this); - mov->open(wsafile, 1, 0); + mov->open(wsafile.c_str(), 1, 0); if (!mov->opened()) - error("Litning: Unable to load litning.wsa"); + error("Litning: Unable to load %s", wsafile.c_str()); for (int i = 0; i < 4; i++) playSpellAnimation(mov, 0, _lightningProps[spellLevel].lastFrame, 3, 93, 0, &LoLEngine::callbackProcessMagicLightning, 0, 0, 0, false); @@ -3139,11 +3136,10 @@ void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot) int vX = _updateSpellBookCoords[slot << 1] + 32; int vY = _updateSpellBookCoords[(slot << 1) + 1] + 5; - char wsaFile[13]; + Common::String wsaFile = Common::String::format("write%0d", spell); if (_flags.isTalkie) - snprintf(wsaFile, 13, "write%0d%c.wsa", spell, (_lang == 1) ? 'f' : (_lang == 0 ? 'e' : 'g')); - else - snprintf(wsaFile, 13, "write%0d.wsa", spell); + wsaFile += (_lang == 1) ? 'f' : (_lang == 0 ? 'e' : 'g'); + wsaFile += ".wsa"; snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1); snd_playSoundEffect(95, -1); @@ -3187,7 +3183,7 @@ void LoLEngine::transferSpellToScollAnimation(int charNum, int spell, int slot) playSpellAnimation(mov, 0, 6, 5, _updateSpellBookCoords[slot << 1], _updateSpellBookCoords[(slot << 1) + 1], 0, 0, 0, 0, false); mov->close(); - mov->open(wsaFile, 0, 0); + mov->open(wsaFile.c_str(), 0, 0); if (!mov->opened()) error("SpellBook: Unable to load spellbook anim"); snd_playSoundEffect(_updateSpellBookAnimData[(spell << 2) + 3], -1); @@ -4160,10 +4156,9 @@ void LoLEngine::loadMapLegendData(int level) { legendData[i * 6 + 5] = 0xffff; } - char file[13]; + Common::String file = Common::String::format("level%d.xxx", level); uint32 size = 0; - snprintf(file, 12, "level%d.xxx", level); - uint8 *data = _res->fileData(file, &size); + uint8 *data = _res->fileData(file.c_str(), &size); uint8 *pos = data; size = MIN<uint32>(size / 12, 32); @@ -4531,10 +4526,9 @@ void LoLEngine::generateTempData() { _lvlTempData[l]->monsters = new MonsterInPlay[30]; _lvlTempData[l]->flyingObjects = new FlyingObject[8]; - char filename[13]; - snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", _currentLevel); + Common::String filename = Common::String::format("LEVEL%d.CMZ", _currentLevel); - _screen->loadBitmap(filename, 15, 15, 0); + _screen->loadBitmap(filename.c_str(), 15, 15, 0); const uint8 *p = _screen->getCPagePtr(14); uint16 len = READ_LE_UINT16(p + 4); p += 6; diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index a815fa1a37..943bb7f8d5 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -315,7 +315,6 @@ private: GUI_LoL *_gui; TIMInterpreter *_tim; - TimAnimator *_animator; Common::Error init(); Common::Error go(); @@ -1215,7 +1214,7 @@ private: void setItemPosition(Item item, uint16 x, uint16 y, int flyingHeight, int b); void removeLevelItem(Item item, int block); bool launchObject(int objectType, Item item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c); - void endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock); + void endObjectFlight(FlyingObject *t, int x, int y, int collisionObject); void processObjectFlight(FlyingObject *t, int x, int y); void updateObjectFlightPosition(FlyingObject *t); void objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock); diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 305036fc51..165919dff2 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -67,18 +67,17 @@ void LoLEngine::loadLevel(int index) { loadLevelWallData(index, true); _loadLevelFlag = 1; - char filename[13]; - snprintf(filename, sizeof(filename), "LEVEL%d.INI", index); + Common::String filename = Common::String::format("LEVEL%d.INI", index); int f = _hasTempDataFlags & (1 << (index - 1)); - runInitScript(filename, f ? 0 : 1); + runInitScript(filename.c_str(), f ? 0 : 1); if (f) restoreBlockTempData(index); - snprintf(filename, sizeof(filename), "LEVEL%d.INF", index); - runInfScript(filename); + filename = Common::String::format("LEVEL%d.INF", index); + runInfScript(filename.c_str()); addLevelItems(); deleteMonstersFromBlock(_currentBlock); @@ -142,11 +141,10 @@ void LoLEngine::assignBlockObject(LevelBlockProperty *l, uint16 item) { } void LoLEngine::loadLevelWallData(int index, bool mapShapes) { - char filename[13]; - snprintf(filename, sizeof(filename), "LEVEL%d.WLL", index); + Common::String filename = Common::String::format("LEVEL%d.WLL", index); uint32 size; - uint8 *file = _res->fileData(filename, &size); + uint8 *file = _res->fileData(filename.c_str(), &size); uint16 c = READ_LE_UINT16(file); loadLevelShpDat(_levelShpList[c], _levelDatList[c], false); @@ -241,10 +239,9 @@ void LoLEngine::restoreBlockTempData(int index) { memcpy(_monsters, _lvlTempData[l]->monsters, sizeof(MonsterInPlay) * 30); memcpy(_flyingObjects, _lvlTempData[l]->flyingObjects, sizeof(FlyingObject) * 8); - char filename[13]; - snprintf(filename, sizeof(filename), "LEVEL%d.CMZ", index); + Common::String filename = Common::String::format("LEVEL%d.CMZ", index); - _screen->loadBitmap(filename, 3, 3, 0); + _screen->loadBitmap(filename.c_str(), 3, 3, 0); const uint8 *p = _screen->getCPagePtr(2); uint16 len = READ_LE_UINT16(p + 4); p += 6; @@ -366,13 +363,13 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight _lastSpecialColor = 0x44; } - char fname[13]; + Common::String fname; const uint8 *v = 0; int tlen = 0; if (_flags.use16ColorMode) { - snprintf(fname, sizeof(fname), "%s.VCF", _lastBlockDataFile); - _screen->loadBitmap(fname, 3, 3, 0); + fname = Common::String::format("%s.VCF", _lastBlockDataFile); + _screen->loadBitmap(fname.c_str(), 3, 3, 0); v = _screen->getCPagePtr(2); tlen = READ_LE_UINT16(v) << 5; v += 2; @@ -383,8 +380,8 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight memcpy(_vcfBlocks, v, tlen); } - snprintf(fname, sizeof(fname), "%s.VCN", _lastBlockDataFile); - _screen->loadBitmap(fname, 3, 3, 0); + fname = Common::String::format("%s.VCN", _lastBlockDataFile); + _screen->loadBitmap(fname.c_str(), 3, 3, 0); v = _screen->getCPagePtr(2); tlen = READ_LE_UINT16(v); v += 2; @@ -434,8 +431,8 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight memcpy(_vcnBlocks, v, vcnLen); v += vcnLen; - snprintf(fname, sizeof(fname), "%s.VMP", _lastBlockDataFile); - _screen->loadBitmap(fname, 3, 3, 0); + fname = Common::String::format("%s.VMP", _lastBlockDataFile); + _screen->loadBitmap(fname.c_str(), 3, 3, 0); v = _screen->getCPagePtr(2); if (vmpLen == -1) @@ -503,9 +500,7 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight generateBrightnessPalette(_screen->getPalette(0), _screen->getPalette(1), _brightness, _lampEffect); if (_flags.isTalkie) { - char tname[13]; - snprintf(tname, sizeof(tname), "LEVEL%.02d.TLC", _currentLevel); - Common::SeekableReadStream *s = _res->createReadStream(tname); + Common::SeekableReadStream *s = _res->createReadStream(Common::String::format("LEVEL%.02d.TLC", _currentLevel)); s->read(_transparencyTable1, 256); s->read(_transparencyTable2, 5120); delete s; @@ -1375,9 +1370,8 @@ void LoLEngine::processGasExplosion(int soundId) { if (dist) { WSAMovie_v2 *mov = new WSAMovie_v2(this); - char file[13]; - snprintf(file, 13, "gasexp%0d.wsa", dist); - mov->open(file, 1, 0); + Common::String file = Common::String::format("gasexp%0d.wsa", dist); + mov->open(file.c_str(), 1, 0); if (!mov->opened()) error("Gas: Unable to load gasexp.wsa"); diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 2261ef8389..695528b8d1 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -524,7 +524,7 @@ int LoLEngine::olol_initAnimStruct(EMCState *script) { int LoLEngine::olol_playAnimationPart(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAnimationPart(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); - _animator->playPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + _tim->animator()->playPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); return 1; } @@ -593,13 +593,13 @@ int LoLEngine::olol_clearDialogueField(EMCState *script) { int LoLEngine::olol_setupBackgroundAnimationPart(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setupBackgroundAnimationPart(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); - _animator->setupPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); + _tim->animator()->setupPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); return 0; } int LoLEngine::olol_startBackgroundAnimation(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_startBackgroundAnimation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - _animator->start(stackPos(0), stackPos(1)); + _tim->animator()->start(stackPos(0), stackPos(1)); return 1; } @@ -629,7 +629,7 @@ int LoLEngine::olol_loadBitmap(EMCState *script) { int LoLEngine::olol_stopBackgroundAnimation(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopBackgroundAnimation(%p) (%d)", (const void *)script, stackPos(0)); - _animator->stop(stackPos(0)); + _tim->animator()->stop(stackPos(0)); return 1; } @@ -1136,9 +1136,8 @@ int LoLEngine::olol_loadTimScript(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadTimScript(%p) (%d, %s)", (const void *)script, stackPos(0), stackPosString(1)); if (_activeTim[stackPos(0)]) return 1; - char file[13]; - snprintf(file, sizeof(file), "%s.TIM", stackPosString(1)); - _activeTim[stackPos(0)] = _tim->load(file, &_timIngameOpcodes); + Common::String file = Common::String::format("%s.TIM", stackPosString(1)); + _activeTim[stackPos(0)] = _tim->load(file.c_str(), &_timIngameOpcodes); return 1; } @@ -1185,10 +1184,9 @@ int LoLEngine::olol_giveItemToMonster(EMCState *script) { int LoLEngine::olol_loadLangFile(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadLangFile(%p) (%s)", (const void *)script, stackPosString(0)); - char filename[13]; - snprintf(filename, sizeof(filename), "%s.%s", stackPosString(0), _languageExt[_lang]); + Common::String filename = Common::String::format("%s.%s", stackPosString(0), _languageExt[_lang]); delete[] _levelLangFile; - _levelLangFile = _res->fileData(filename, 0); + _levelLangFile = _res->fileData(filename.c_str(), 0); return 1; } @@ -1440,7 +1438,10 @@ int LoLEngine::olol_playEndSequence(EMCState *script){ _screen->getPalette(1).clear(); showOutro(c, (_monsterDifficulty == 2)); - quitGame(); + // Don't call quitGame() on a RTL request (because this would + // make the next game launched from the launcher quit instantly. + if (!shouldQuit()) + quitGame(); return 0; } @@ -1983,7 +1984,7 @@ int LoLEngine::olol_removeInventoryItem(EMCState *script) { int LoLEngine::olol_getAnimationLastPart(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getAnimationLastPart(%p) (%d)", (const void *)script, stackPos(0)); - return _animator->resetLastPart(stackPos(0)); + return _tim->animator()->resetLastPart(stackPos(0)); } int LoLEngine::olol_assignSpecialGuiShape(EMCState *script) { @@ -2406,16 +2407,16 @@ int LoLEngine::tlol_processWsaFrame(const TIM *tim, const uint16 *param) { const int y2 = param[3]; const int factor = MAX<int>(0, (int16)param[4]); - const int x1 = _animator->getAnimX(animIndex); - const int y1 = _animator->getAnimY(animIndex); - const Movie *wsa = _animator->getWsaCPtr(animIndex); + const int x1 = _tim->animator()->getAnimX(animIndex); + const int y1 = _tim->animator()->getAnimY(animIndex); + const Movie *wsa = _tim->animator()->getWsaCPtr(animIndex); int w1 = wsa->width(); int h1 = wsa->height(); int w2 = (w1 * factor) / 100; int h2 = (h1 * factor) / 100; - _animator->displayFrame(animIndex, 2, frame); + _tim->animator()->displayFrame(animIndex, 2, frame); _screen->wsaFrameAnimationStep(x1, y1, x2, y2, w1, h1, w2, h2, 2, _flags.isDemo && _flags.platform != Common::kPlatformPC98 ? 0 : 8, 0); if (!_flags.isDemo && _flags.platform != Common::kPlatformPC98) _screen->checkedPageUpdate(8, 4); @@ -2584,13 +2585,13 @@ int LoLEngine::tlol_playSoundEffect(const TIM *tim, const uint16 *param) { int LoLEngine::tlol_startBackgroundAnimation(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_startBackgroundAnimation(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]); - _animator->start(param[0], param[1]); + _tim->animator()->start(param[0], param[1]); return 1; } int LoLEngine::tlol_stopBackgroundAnimation(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_stopBackgroundAnimation(%p, %p) (%d)", (const void *)tim, (const void *)param, param[0]); - _animator->stop(param[0]); + _tim->animator()->stop(param[0]); return 1; } @@ -2674,12 +2675,12 @@ int LoLEngine::tlol_displayAnimFrame(const TIM *tim, const uint16 *param) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_displayAnimFrame(%p, %p) (%d, %d)", (const void *)tim, (const void *)param, param[0], param[1]); const int animIndex = tim->wsa[param[0]].anim - 1; - const Movie *wsa = _animator->getWsaCPtr(animIndex); + const Movie *wsa = _tim->animator()->getWsaCPtr(animIndex); if (param[1] == 0xFFFF) { _screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK); } else { - _animator->displayFrame(animIndex, 2, param[1], 0); + _tim->animator()->displayFrame(animIndex, 2, param[1], 0); _screen->copyRegion(wsa->xAdd(), wsa->yAdd(), wsa->xAdd(), wsa->yAdd(), wsa->width(), wsa->height(), 2, 0); } diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 501ae2defd..6f0f0ab083 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -482,17 +482,16 @@ int TIMInterpreter::initAnimStruct(int index, const char *filename, int x, int y wsaOpenFlags = 1; } - char file[32]; - snprintf(file, 32, "%s.WSA", filename); + Common::String file = Common::String::format("%s.WSA", filename); - if (_vm->resource()->exists(file)) { + if (_vm->resource()->exists(file.c_str())) { if (isLoLDemo) wsa = new WSAMovie_v1(_vm); else wsa = new WSAMovie_v2(_vm); assert(wsa); - wsa->open(file, wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0); + wsa->open(file.c_str(), wsaOpenFlags, (index == 1) ? &_screen->getPalette(0) : 0); } if (wsa && wsa->opened()) { @@ -526,10 +525,10 @@ int TIMInterpreter::initAnimStruct(int index, const char *filename, int x, int y } if (wsaFlags & 4) { - snprintf(file, 32, "%s.CPS", filename); + file = Common::String::format("%s.CPS", filename); - if (_vm->resource()->exists(file)) { - _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0)); + if (_vm->resource()->exists(file.c_str())) { + _screen->loadBitmap(file.c_str(), 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK); if (_drawPage2) _screen->checkedPageUpdate(8, 4); @@ -550,10 +549,10 @@ int TIMInterpreter::initAnimStruct(int index, const char *filename, int x, int y _screen->updateScreen(); } - snprintf(file, 32, "%s.CPS", filename); + file = Common::String::format("%s.CPS", filename); - if (_vm->resource()->exists(file)) { - _screen->loadBitmap(file, 3, 3, &_screen->getPalette(0)); + if (_vm->resource()->exists(file.c_str())) { + _screen->loadBitmap(file.c_str(), 3, 3, &_screen->getPalette(0)); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, _drawPage2, Screen::CR_NO_P_CHECK); if (_drawPage2) _screen->checkedPageUpdate(8, 4); @@ -922,13 +921,12 @@ int TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, i if (wsaFlags & 8) wsaOpenFlags |= 1; - char file[32]; - snprintf(file, 32, "%s.WSA", filename); + Common::String file = Common::String::format("%s.WSA", filename); - if (_vm->resource()->exists(file)) { + if (_vm->resource()->exists(file.c_str())) { wsa = new WSAMovie_v2(_vm); assert(wsa); - wsa->open(file, wsaOpenFlags, &_screen->getPalette(3)); + wsa->open(file.c_str(), wsaOpenFlags, &_screen->getPalette(3)); } if (!_vm->_flags.use16ColorMode) { diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index d11403ad9f..01bf3c5e26 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -202,8 +202,7 @@ void LoLEngine::setupPrologueData(bool load) { void LoLEngine::showIntro() { _tim = new TIMInterpreter(this, _screen, _system); assert(_tim); - _animator = _tim->animator(); - + if (_flags.platform == Common::kPlatformPC98) showStarcraftLogo(); @@ -262,7 +261,6 @@ void LoLEngine::showIntro() { delete _tim; _tim = 0; - _animator = 0; _screen->fadePalette(_screen->getPalette(1), 30, 0); } @@ -270,7 +268,6 @@ void LoLEngine::showIntro() { int LoLEngine::chooseCharacter() { _tim = new TIMInterpreter(this, _screen, _system); assert(_tim); - _animator = _tim->animator(); _tim->setLangData("LOLINTRO.DIP"); @@ -309,9 +306,8 @@ int LoLEngine::chooseCharacter() { Screen::FontId old = _screen->setFont(Screen::FID_SJIS_FNT); for (int j = 0; j < 3; ++j) { - char buffer[3]; - snprintf(buffer, sizeof(buffer), "%2d", _charPreviews[i].attrib[j]); - _screen->printText(buffer, _charPosXPC98[i] + 16, 176 + j * 8, 0x81, 0x00); + Common::String attribString = Common::String::format("%2d", _charPreviews[i].attrib[j]); + _screen->printText(attribString.c_str(), _charPosXPC98[i] + 16, 176 + j * 8, 0x81, 0x00); } _screen->setFont(old); } @@ -387,7 +383,6 @@ int LoLEngine::chooseCharacter() { delete _tim; _tim = 0; - _animator = 0; return _charSelection; } @@ -1061,7 +1056,6 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { setupEpilogueData(true); TIMInterpreter *timBackUp = _tim; _tim = new TIMInterpreter(this, _screen, _system); - _animator = _tim->animator(); _screen->getPalette(0).clear(); _screen->setScreenPalette(_screen->getPalette(0)); @@ -1117,47 +1111,49 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { _screen->fadeToBlack(30); - showCredits(); + if (!shouldQuit()) + showCredits(); _eventList.clear(); + + if (!shouldQuit()) { + switch (character) { + case 0: + _screen->loadBitmap("KIERAN.CPS", 3, 3, &_screen->getPalette(0)); + break; - switch (character) { - case 0: - _screen->loadBitmap("KIERAN.CPS", 3, 3, &_screen->getPalette(0)); - break; - - case 1: - _screen->loadBitmap("AK'SHEL.CPS", 3, 3, &_screen->getPalette(0)); - break; + case 1: + _screen->loadBitmap("AK'SHEL.CPS", 3, 3, &_screen->getPalette(0)); + break; - case 2: - _screen->loadBitmap("MICHAEL.CPS", 3, 3, &_screen->getPalette(0)); - break; + case 2: + _screen->loadBitmap("MICHAEL.CPS", 3, 3, &_screen->getPalette(0)); + break; - case 3: - _screen->loadBitmap("CONRAD.CPS", 3, 3, &_screen->getPalette(0)); - break; + case 3: + _screen->loadBitmap("CONRAD.CPS", 3, 3, &_screen->getPalette(0)); + break; - default: - _screen->clearPage(3); - _screen->getPalette(0).clear(); - } + default: + _screen->clearPage(3); + _screen->getPalette(0).clear(); + } - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); - if (maxDifficulty && !_flags.use16ColorMode) - _tim->displayText(0x8000, 0, 0xDC); - _screen->updateScreen(); - _screen->fadePalette(_screen->getPalette(0), 30, 0); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); + if (maxDifficulty && !_flags.use16ColorMode) + _tim->displayText(0x8000, 0, 0xDC); + _screen->updateScreen(); + _screen->fadePalette(_screen->getPalette(0), 30, 0); - while (!checkInput(0) && !shouldQuit()) - delay(_tickLength); + while (!checkInput(0) && !shouldQuit()) + delay(_tickLength); - _screen->fadeToBlack(30); + _screen->fadeToBlack(30); + } _tim->clearLangData(); delete _tim; _tim = timBackUp; - _animator = 0; setupEpilogueData(false); } @@ -1245,7 +1241,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { int curShapeFile = 0; uint8 *shapes[12]; - memset(&shapes, 0, sizeof(shapes)); + memset(shapes, 0, sizeof(shapes)); loadOutroShapes(curShapeFile++, shapes); uint8 *monsterPal = 0; diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp index 95a632c08c..b2a9c2fd93 100644 --- a/engines/kyra/sound_lok.cpp +++ b/engines/kyra/sound_lok.cpp @@ -74,9 +74,8 @@ void KyraEngine_LoK::snd_playWanderScoreViaMap(int command, int restart) { } void KyraEngine_LoK::snd_playVoiceFile(int id) { - char vocFile[9]; - snprintf(vocFile, sizeof(vocFile), "%03d", id); - _speechPlayTime = _sound->voicePlay(vocFile, &_speechHandle); + Common::String vocFile = Common::String::format("%03d", id); + _speechPlayTime = _sound->voicePlay(vocFile.c_str(), &_speechHandle); } void KyraEngine_LoK::snd_voiceWaitForFinish(bool ingame) { diff --git a/engines/kyra/sound_lol.cpp b/engines/kyra/sound_lol.cpp index a7776f0ab6..7262635728 100644 --- a/engines/kyra/sound_lol.cpp +++ b/engines/kyra/sound_lol.cpp @@ -50,36 +50,34 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { _lastSpeaker = speaker; _nextSpeechId = _nextSpeaker = -1; - char pattern1[8]; - char pattern2[5]; - char file1[13]; - char file2[13]; - char file3[13]; - file3[0] = 0; + Common::String pattern1; + Common::String file1; + Common::String file2; + Common::String file3; SpeechList newSpeechList; - snprintf(pattern2, sizeof(pattern2), "%02d", id & 0x4000 ? 0 : _curTlkFile); + Common::String pattern2 = Common::String::format("%02d", id & 0x4000 ? 0 : _curTlkFile); if (id & 0x4000) { - snprintf(pattern1, sizeof(pattern1), "%03X", id & 0x3fff); + pattern1 = Common::String::format("%03X", id & 0x3fff); } else if (id < 1000) { - snprintf(pattern1, sizeof(pattern1), "%03d", id); + pattern1 = Common::String::format("%03d", id); } else { - snprintf(file3, sizeof(file3), "@%04d%c.%s", id - 1000, (char)speaker, pattern2); - if (_sound->isVoicePresent(file3)) - newSpeechList.push_back(_sound->getVoiceStream(file3)); + file3 = Common::String::format("@%04d%c.%s", id - 1000, (char)speaker, pattern2.c_str()); + if (_sound->isVoicePresent(file3.c_str())) + newSpeechList.push_back(_sound->getVoiceStream(file3.c_str())); } - if (!file3[0]) { + if (file3.empty()) { for (char i = 0; ; i++) { char symbol = '0' + i; - snprintf(file1, sizeof(file1), "%s%c%c.%s", pattern1, (char)speaker, symbol, pattern2); - snprintf(file2, sizeof(file2), "%s%c%c.%s", pattern1, '_', symbol, pattern2); - if (_sound->isVoicePresent(file1)) - newSpeechList.push_back(_sound->getVoiceStream(file1)); - else if (_sound->isVoicePresent(file2)) - newSpeechList.push_back(_sound->getVoiceStream(file2)); + file1 = Common::String::format("%s%c%c.%s", pattern1.c_str(), (char)speaker, symbol, pattern2.c_str()); + file2 = Common::String::format("%s%c%c.%s", pattern1.c_str(), '_', symbol, pattern2.c_str()); + if (_sound->isVoicePresent(file1.c_str())) + newSpeechList.push_back(_sound->getVoiceStream(file1.c_str())); + else if (_sound->isVoicePresent(file2.c_str())) + newSpeechList.push_back(_sound->getVoiceStream(file2.c_str())); else break; } @@ -260,9 +258,7 @@ void LoLEngine::snd_loadSoundFile(int track) { int t = (track - 250) * 3; if (_curMusicFileIndex != _musicTrackMap[t] || _curMusicFileExt != (char)_musicTrackMap[t + 1]) { snd_stopMusic(); - char filename[13]; - snprintf(filename, sizeof(filename), "LORE%02d%c", _musicTrackMap[t], (char)_musicTrackMap[t + 1]); - _sound->loadSoundFile(filename); + _sound->loadSoundFile(Common::String::format("LORE%02d%c", _musicTrackMap[t], (char)_musicTrackMap[t + 1])); _curMusicFileIndex = _musicTrackMap[t]; _curMusicFileExt = (char)_musicTrackMap[t + 1]; } else { diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 499cc6f301..d56abc5d47 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -38,7 +38,7 @@ namespace Kyra { -#define RESFILE_VERSION 73 +#define RESFILE_VERSION 74 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp index 393fa8d11f..4406f3ec41 100644 --- a/engines/kyra/text_hof.cpp +++ b/engines/kyra/text_hof.cpp @@ -436,15 +436,16 @@ void KyraEngine_HoF::updateDlgBuffer() { _npcTalkChpIndex = _currentChapter; _npcTalkDlgIndex = _mainCharacter.dlgIndex; - char filename[13]; - snprintf(filename, 13, "CH%.02d-S%.02d.DLG", _currentChapter, _npcTalkDlgIndex); + Common::String filename = Common::String::format("CH%.02d-S%.02d.DL", _currentChapter, _npcTalkDlgIndex); const char *suffix = _flags.isTalkie ? suffixTalkie : suffixTowns; if (_flags.platform != Common::kPlatformPC || _flags.isTalkie) - filename[11] = suffix[_lang]; + filename += suffix[_lang]; + else + filename += 'G'; delete[] _dlgBuffer; - _dlgBuffer = _res->fileData(filename, 0); + _dlgBuffer = _res->fileData(filename.c_str(), 0); } void KyraEngine_HoF::loadDlgHeader(int &csEntry, int &vocH, int &scIndex1, int &scIndex2) { diff --git a/engines/kyra/text_mr.cpp b/engines/kyra/text_mr.cpp index 2cb752fdb3..d690b70266 100644 --- a/engines/kyra/text_mr.cpp +++ b/engines/kyra/text_mr.cpp @@ -625,24 +625,20 @@ void KyraEngine_MR::malcolmSceneStartupChat() { } void KyraEngine_MR::updateDlgBuffer() { - char dlgFile[16]; - char cnvFile[16]; - if (_cnvFile) _cnvFile->seek(0, SEEK_SET); if (_curDlgIndex == _mainCharacter.dlgIndex && _curDlgChapter == _currentChapter && _curDlgLang == _lang) return; - snprintf(dlgFile, 16, "CH%.02d-S%.02d.", _currentChapter, _mainCharacter.dlgIndex); - appendLanguage(dlgFile, _lang, 16); - snprintf(cnvFile, 16, "CH%.02d-S%.02d.CNV", _currentChapter, _mainCharacter.dlgIndex); + Common::String dlgFile = Common::String::format("CH%.02d-S%.02d.%s", _currentChapter, _mainCharacter.dlgIndex, _languageExtension[_lang]); + Common::String cnvFile = Common::String::format("CH%.02d-S%.02d.CNV", _currentChapter, _mainCharacter.dlgIndex); delete _cnvFile; delete _dlgBuffer; - _res->exists(cnvFile, true); - _res->exists(dlgFile, true); + _res->exists(cnvFile.c_str(), true); + _res->exists(dlgFile.c_str(), true); _cnvFile = _res->createReadStream(cnvFile); _dlgBuffer = _res->createReadStream(dlgFile); assert(_cnvFile); diff --git a/engines/lastexpress/data/animation.cpp b/engines/lastexpress/data/animation.cpp index 8ce73993c3..1cbf7672d1 100644 --- a/engines/lastexpress/data/animation.cpp +++ b/engines/lastexpress/data/animation.cpp @@ -94,7 +94,7 @@ bool Animation::load(Common::SeekableReadStream *stream, int flag) { } _currentChunk = _chunks.begin(); _changed = false; - _startTime = g_engine->_system->getMillis(); + _startTime = g_system->getMillis(); return true; } @@ -110,7 +110,7 @@ bool Animation::process() { // - Re-implement to be closer to the original engine // - Add support for subtitles // - Use engine sound queue instead of our own appendable sound instance - int32 currentFrame = (g_engine->_system->getMillis() - _startTime) * 3 / 100; + int32 currentFrame = (g_system->getMillis() - _startTime) * 3 / 100; // Process all chunks until the current frame while (!_changed && _currentChunk != NULL && currentFrame > _currentChunk->frame && !hasEnded()) { @@ -180,7 +180,7 @@ bool Animation::process() { // Synchronize the audio by resetting the start time if (_currentChunk->frame == 0) - _startTime = g_engine->_system->getMillis(); + _startTime = g_system->getMillis(); break; case kChunkTypeAudioEnd: @@ -260,7 +260,8 @@ void Animation::processChunkAudio(Common::SeekableReadStream *in, const Chunk &c // TODO: this method will probably go away and be integrated in the main loop void Animation::play() { - while (!hasEnded() && !g_engine->getEventManager()->shouldQuit() && !g_engine->getEventManager()->shouldRTL()) { + Common::EventManager *eventMan = g_system->getEventManager(); + while (!hasEnded() && !Engine::shouldQuit()) { process(); if (_changed) { @@ -283,11 +284,11 @@ void Animation::play() { g_system->updateScreen(); //FIXME: implement subtitles - g_engine->_system->delayMillis(20); + g_system->delayMillis(20); // Handle right-click to interrupt animations Common::Event ev = Common::Event(); - while (g_engine->getEventManager()->pollEvent(ev)) { + while (eventMan->pollEvent(ev)) { if (ev.type == Common::EVENT_RBUTTONUP) { // Stop audio if (_audio) diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index e1bd9494a9..4b7c5f6a9a 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -865,7 +865,7 @@ bool Debugger::cmdBeetle(int argc, const char **argv) { askForRedraw(); redrawScreen(); - while (g_engine->getEventManager()->pollEvent(ev)) { + while (g_system->getEventManager()->pollEvent(ev)) { switch (ev.type) { default: diff --git a/engines/lastexpress/detection.cpp b/engines/lastexpress/detection.cpp index 7c7c6b0a36..bf575b63f8 100644 --- a/engines/lastexpress/detection.cpp +++ b/engines/lastexpress/detection.cpp @@ -21,6 +21,7 @@ */ #include "lastexpress/lastexpress.h" +#include "engines/advancedDetector.h" namespace LastExpress { @@ -176,35 +177,13 @@ static const ADGameDescription gameDescriptions[] = { AD_TABLE_END_MARKER }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)gameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - lastExpressGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "lastexpress", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class LastExpressMetaEngine : public AdvancedMetaEngine { public: - LastExpressMetaEngine() : AdvancedMetaEngine(detectionParams) {} + LastExpressMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(ADGameDescription), lastExpressGames) { + params.singleid = "lastexpress"; + params.guioptions = Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX; + } const char *getName() const { return "Lastexpress"; @@ -224,6 +203,10 @@ bool LastExpressMetaEngine::createInstance(OSystem *syst, Engine **engine, const return gd != 0; } +bool LastExpressEngine::isDemo() const { + return (bool)(_gameDescription->flags & ADGF_DEMO); +} + } // End of namespace LastExpress #if PLUGIN_ENABLED_DYNAMIC(LASTEXPRESS) diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index 63efd182a8..3f98ac79ea 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -699,7 +699,6 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, FlagType flag } void SoundManager::playSoundEvent(EntityIndex entity, byte action, byte a3) { - char filename[12]; int values[5]; if (getEntityData(entity)->car != getEntityData(kEntityPlayer)->car) @@ -842,7 +841,6 @@ void SoundManager::playSteam(CityIndex index) { void SoundManager::playFightSound(byte action, byte a4) { int _action = (int)action; - char filename[12]; int values[5]; switch (action) { diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp index 6fdd18413b..e162998719 100644 --- a/engines/lastexpress/lastexpress.cpp +++ b/engines/lastexpress/lastexpress.cpp @@ -37,6 +37,8 @@ #include "common/config-manager.h" #include "common/debug-channels.h" +#include "common/error.h" +#include "common/fs.h" #include "engines/util.h" diff --git a/engines/lastexpress/lastexpress.h b/engines/lastexpress/lastexpress.h index d78bba36f0..f8f38788a0 100644 --- a/engines/lastexpress/lastexpress.h +++ b/engines/lastexpress/lastexpress.h @@ -29,11 +29,12 @@ #include "common/random.h" #include "common/timer.h" -#include "engines/advancedDetector.h" #include "engines/engine.h" #include "graphics/pixelformat.h" +struct ADGameDescription; + /** * This is the namespace of the LastExpress engine. * @@ -101,7 +102,7 @@ public: void restoreEventHandlers(); void setEventHandlers(EventHandler::EventFunction *eventMouse, EventHandler::EventFunction *eventTick); - bool isDemo() const { return (bool)(_gameDescription->flags & ADGF_DEMO); } + bool isDemo() const; // Frame Counter uint32 getFrameCounter() { return _frameCounter; } diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp index ced0be0cfb..83ede92569 100644 --- a/engines/lure/detection.cpp +++ b/engines/lure/detection.cpp @@ -175,34 +175,14 @@ static const LureGameDescription gameDescriptions[] = { } // End of namespace Lure -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Lure::gameDescriptions, - // Size of that superset structure - sizeof(Lure::LureGameDescription), - // Number of bytes to compute MD5 sum for - 1024, - // List of all engine targets - lureGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "lure", - // List of files for file-based fallback detection (optional) - 0, - // Flags - kADFlagUseExtraAsHint, - // Additional GUI options (for every game} - Common::GUIO_NOSPEECH, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class LureMetaEngine : public AdvancedMetaEngine { public: - LureMetaEngine() : AdvancedMetaEngine(detectionParams) {} + LureMetaEngine() : AdvancedMetaEngine(Lure::gameDescriptions, sizeof(Lure::LureGameDescription), lureGames) { + params.md5Bytes = 1024; + params.singleid = "lure"; + params.flags = kADFlagUseExtraAsHint; + params.guioptions = Common::GUIO_NOSPEECH; + } virtual const char *getName() const { return "Lure"; diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp index 1aefe3d02d..bab17d9e1d 100644 --- a/engines/m4/detection.cpp +++ b/engines/m4/detection.cpp @@ -384,34 +384,14 @@ static const char *directoryGlobs[] = { 0 }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)M4::gameDescriptions, - // Size of that superset structure - sizeof(M4::M4GameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - m4Games, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "m4", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOMIDI, - // Maximum directory depth - 2, - // List of directory globs - directoryGlobs -}; - class M4MetaEngine : public AdvancedMetaEngine { public: - M4MetaEngine() : AdvancedMetaEngine(detectionParams) {} + M4MetaEngine() : AdvancedMetaEngine(M4::gameDescriptions, sizeof(M4::M4GameDescription), m4Games) { + params.singleid = "m4"; + params.guioptions = Common::GUIO_NOMIDI; + params.depth = 2; + params.directoryGlobs = directoryGlobs; + } virtual const char *getName() const { return "MADS/M4"; diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index 4576e2b5ce..a0576a458e 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -525,34 +525,11 @@ static MadeGameDescription g_fallbackDesc = { } // End of namespace Made -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Made::gameDescriptions, - // Size of that superset structure - sizeof(Made::MadeGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - madeGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "made", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class MadeMetaEngine : public AdvancedMetaEngine { public: - MadeMetaEngine() : AdvancedMetaEngine(detectionParams) {} + MadeMetaEngine() : AdvancedMetaEngine(Made::gameDescriptions, sizeof(Made::MadeGameDescription), madeGames) { + params.singleid = "made"; + } virtual const char *getName() const { return "MADE"; diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 6a73b28246..a7442729d2 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -158,35 +158,14 @@ static const char *directoryGlobs[] = { 0 }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Mohawk::gameDescriptions, - // Size of that superset structure - sizeof(Mohawk::MohawkGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - mohawkGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "mohawk", - // List of files for file-based fallback detection (optional) - Mohawk::fileBased, - // Flags - 0, - // Additional GUI options (for every game) - Common::GUIO_NONE, - // Maximum directory depth - 2, - // List of directory globs - directoryGlobs -}; - class MohawkMetaEngine : public AdvancedMetaEngine { public: - MohawkMetaEngine() : AdvancedMetaEngine(detectionParams) {} - + MohawkMetaEngine() : AdvancedMetaEngine(Mohawk::gameDescriptions, sizeof(Mohawk::MohawkGameDescription), mohawkGames) { + params.singleid = "mohawk"; + params.fileBasedFallback = Mohawk::fileBased; + params.depth = 2; + params.directoryGlobs = directoryGlobs; + } virtual const char *getName() const { return "Mohawk"; } diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index 5510643d04..df66c3dc1c 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -527,7 +527,7 @@ static const MohawkGameDescription gameDescriptions[] = { "harryhh", "", AD_ENTRY1("HHHB.LB", "267bb6e3c8f237ca98b02c07b9c4013f"), - Common::EN_ANY, + Common::EN_GRB, Common::kPlatformWindows, ADGF_NO_FLAGS, Common::GUIO_NONE @@ -573,6 +573,54 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + // From afholman in bug#3309308 + { + { + "harryhh", + "", + AD_ENTRY1("EnglishBO", "b63a7b67834de0cd4cdbf02cf40d8547"), + Common::EN_GRB, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "harryhh", + "", + AD_ENTRY1("GermanBO", "eb740102c1c8379c2c610cba14484ccb"), + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "harryhh", + "", + AD_ENTRY1("FrenchBO", "2118de914ab9eaec482c245c06145071"), + Common::FR_FRA, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + // Harry and the Haunted House 1.1 // From pacifist { @@ -866,6 +914,54 @@ static const MohawkGameDescription gameDescriptions[] = { "TORTOISE.EXE" }, + // From afholman in bug#3309308 + { + { + "tortoise", + "", + AD_ENTRY1("TORTB.LB", "83f6bfcf30c445d13e81e0faed9aa27b"), + Common::EN_GRB, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0, + }, + + // From afholman in bug#3309308 + { + { + "tortoise", + "", + AD_ENTRY1("TORTD.LB", "21761e7de4e5f12298f43fa17c00f3e1"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0, + }, + + // From afholman in bug#3309308 + { + { + "tortoise", + "", + AD_ENTRY1("TORTF.LB", "9693043df217ffc0667a1f45f2849aa7"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0, + }, + { { "tortoise", @@ -942,6 +1038,38 @@ static const MohawkGameDescription gameDescriptions[] = { "ARTHUR.EXE" }, + // From afholman in bug#3309308 + { + { + "arthur", + "", + AD_ENTRY1("BookOutline", "133750de1ceb9e7351599d79f99fee4d"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_LB_10, + "Arthur's Teacher Trouble" + }, + + // From darthbo in bug#3301791 + { + { + "arthur", + "", + AD_ENTRY1("PAGES.512", "cd995d20d0d7b4642476fd76044b4e5b"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_LB_10, + "ARTHUR.EXE" + }, + { { "arthur", @@ -1145,6 +1273,22 @@ static const MohawkGameDescription gameDescriptions[] = { "RUFF.EXE" }, + // From aluff in bug#3307785 + { + { + "ruff", + "", + AD_ENTRY1("BookOutline", "f625d4056c750b9aad6f94dd854f5abe"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + "Living Books Player" + }, + { { "ruff", @@ -1191,6 +1335,38 @@ static const MohawkGameDescription gameDescriptions[] = { "Living Books Player" }, + // From aluff in bug#3309981 + { + { + "newkid", + "", + AD_ENTRY1("NEWKID.512", "5135f24afa138ecdf5b52d955e9a9189"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + "NEWKID.EXE" + }, + + // From aluff in bug#3309981 + { + { + "newkid", + "", + AD_ENTRY1("BookOutline", "6aa7c4720b922f4164584956be5ba9e5"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + "Living Books Player" + }, + { { "newkid", @@ -1299,6 +1475,22 @@ static const MohawkGameDescription gameDescriptions[] = { "BIRTHDAY.EXE" }, + // From aluff in bug#3309936 + { + { + "arthurbday", + "", + AD_ENTRY1("BookOutline", "d631242b004720ecc615e4f855825860"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + "Living Books Player" + }, + { { "arthurbday", @@ -1375,6 +1567,102 @@ static const MohawkGameDescription gameDescriptions[] = { "Little Monster at School" }, + // From afholman in bug#3309308 + { + { + "lilmonster", + "", + AD_ENTRY1("lmasb.lb", "18a4e82f2c5cc30f7a2f9bd95e8c1364"), + Common::EN_GRB, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "lilmonster", + "", + AD_ENTRY1("lmasd.lb", "422b94c0e663305869cb2d2f1109a0bc"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "lilmonster", + "", + AD_ENTRY1("lmasf.lb", "8c22e79c97a86827d56b4c596066dcea"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "lilmonster", + "", + AD_ENTRY1("EnglishBO", "7aa2a1694255000b72ff0cc179f8059f"), + Common::EN_GRB, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "lilmonster", + "", + AD_ENTRY1("GermanBO", "ff7ac4b1b4f2ded71ff3650f383fea48"), + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "lilmonster", + "", + AD_ENTRY1("FrenchBO", "d13e5eae0f68cecc91a0dcfcceec7061"), + Common::FR_FRA, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + // From Scarlatti in bug #3275626 { { @@ -1686,6 +1974,38 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + // From aluff in bug#3306722 + { + { + "stellaluna", + "", + AD_ENTRY1("STELLA.LB", "ca8562a79f63485680e21191f5865fd7"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From aluff in bug#3306722 + { + { + "stellaluna", + "", + AD_ENTRY1("BookOutline", "7e931a455ac88557e04ca682579cd5a5"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + // Sheila Rae the Brave 1.0 // From pacifist { @@ -1703,6 +2023,118 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + // From aluff in bug#3309934 + { + { + "sheila", + "", + AD_ENTRY1("BookOutline", "961f0cf4de2fbaa1da8ce0011822cd38"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "sheila", + "", + AD_ENTRY1("SRAEB.LB", "4835612022c2ae1944bde453d3202803"), + Common::EN_GRB, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "sheila", + "", + AD_ENTRY1("SRAED.LB", "3f21183534d324cf3bb8464f9217712c"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "sheila", + "", + AD_ENTRY1("SRAEF.LB", "96b00fc4b44c0e881c674d4bae5aa79a"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "sheila", + "", + AD_ENTRY1("EnglishBO", "6d3ad5724f1729a1d96d812668770c2e"), + Common::EN_GRB, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "sheila", + "", + AD_ENTRY1("GermanBO", "af1dc5a8bc8da58310d17b72b657fc1f"), + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + + // From afholman in bug#3309308 + { + { + "sheila", + "", + AD_ENTRY1("FrenchBO", "62eefcb8424a5f9ba7db5af6f0421e58"), + Common::FR_FRA, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV2, + 0, + 0 + }, + { AD_TABLE_END_MARKER, 0, 0, 0 } }; diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index c3719bcd51..09f6fa5e2e 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -220,34 +220,11 @@ static const PARALLACTIONGameDescription gameDescriptions[] = { } -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Parallaction::gameDescriptions, - // Size of that superset structure - sizeof(Parallaction::PARALLACTIONGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - parallactionGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - 0, - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class ParallactionMetaEngine : public AdvancedMetaEngine { public: - ParallactionMetaEngine() : AdvancedMetaEngine(detectionParams) {} + ParallactionMetaEngine() : AdvancedMetaEngine(Parallaction::gameDescriptions, sizeof(Parallaction::PARALLACTIONGameDescription), parallactionGames) { + params.guioptions = Common::GUIO_NOLAUNCHLOAD; + } virtual const char *getName() const { return "Parallaction"; diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index 23bdc73666..ece90855b7 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -101,34 +101,12 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { #include "saga/detection_tables.h" -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Saga::gameDescriptions, - // Size of that superset structure - sizeof(Saga::SAGAGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - sagaGames, - // Structure for autoupgrading obsolete targets - obsoleteGameIDsTable, - // Name of single gameid (optional) - "saga", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class SagaMetaEngine : public AdvancedMetaEngine { public: - SagaMetaEngine() : AdvancedMetaEngine(detectionParams) {} + SagaMetaEngine() : AdvancedMetaEngine(Saga::gameDescriptions, sizeof(Saga::SAGAGameDescription), sagaGames) { + params.obsoleteList = obsoleteGameIDsTable; + params.singleid = "saga"; + } virtual const char *getName() const { return "SAGA [" diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index af945247ba..b1b5f81995 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -131,6 +131,8 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList)); DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias + DCmd_Register("saved_bits", WRAP_METHOD(Console, cmdSavedBits)); + DCmd_Register("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits)); // Segments DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias @@ -364,6 +366,8 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" undither - Enable/disable undithering\n"); DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n"); DebugPrintf(" animate_object_list / al - Shows the current list of objects in kAnimate's draw list\n"); + DebugPrintf(" saved_bits - List saved bits on the hunk\n"); + DebugPrintf(" show_saved_bits - Display saved bits\n"); DebugPrintf("\n"); DebugPrintf("Segments:\n"); DebugPrintf(" segment_table / segtable - Lists all segments\n"); @@ -1600,6 +1604,174 @@ bool Console::cmdWindowList(int argc, const char **argv) { return true; } + +bool Console::cmdSavedBits(int argc, const char **argv) { + SegManager *segman = _engine->_gamestate->_segMan; + SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK); + HunkTable* hunks = (HunkTable*)segman->getSegmentObj(id); + if (!hunks) { + DebugPrintf("No hunk segment found.\n"); + return true; + } + + Common::Array<reg_t> entries = hunks->listAllDeallocatable(id); + + for (uint i = 0; i < entries.size(); ++i) { + uint16 offset = entries[i].offset; + const Hunk& h = hunks->_table[offset]; + if (strcmp(h.type, "SaveBits()") == 0) { + byte* memoryPtr = (byte*)h.mem; + + if (memoryPtr) { + DebugPrintf("%04x:%04x:", PRINT_REG(entries[i])); + + Common::Rect rect; + byte mask; + assert(h.size >= sizeof(rect) + sizeof(mask)); + + memcpy((void *)&rect, memoryPtr, sizeof(rect)); + memcpy((void *)&mask, memoryPtr + sizeof(rect), sizeof(mask)); + + DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left, + rect.bottom, rect.right); + if (mask & GFX_SCREEN_MASK_VISUAL) + DebugPrintf(" visual"); + if (mask & GFX_SCREEN_MASK_PRIORITY) + DebugPrintf(" priority"); + if (mask & GFX_SCREEN_MASK_CONTROL) + DebugPrintf(" control"); + if (mask & GFX_SCREEN_MASK_DISPLAY) + DebugPrintf(" display"); + DebugPrintf("\n"); + } + } + } + + + return true; +} + +bool Console::cmdShowSavedBits(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Display saved bits.\n"); + DebugPrintf("Usage: %s <address>\n", argv[0]); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + reg_t memoryHandle = NULL_REG; + + if (parse_reg_t(_engine->_gamestate, argv[1], &memoryHandle, false)) { + DebugPrintf("Invalid address passed.\n"); + DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + return true; + } + + if (memoryHandle.isNull()) { + DebugPrintf("Invalid address.\n"); + return true; + } + + SegManager *segman = _engine->_gamestate->_segMan; + SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK); + HunkTable* hunks = (HunkTable*)segman->getSegmentObj(id); + if (!hunks) { + DebugPrintf("No hunk segment found.\n"); + return true; + } + + if (memoryHandle.segment != id || !hunks->isValidOffset(memoryHandle.offset)) { + DebugPrintf("Invalid address.\n"); + return true; + } + + const Hunk& h = hunks->_table[memoryHandle.offset]; + + if (strcmp(h.type, "SaveBits()") != 0) { + DebugPrintf("Invalid address.\n"); + return true; + } + + byte *memoryPtr = segman->getHunkPointer(memoryHandle); + + if (!memoryPtr) { + DebugPrintf("Invalid or freed bits.\n"); + return true; + } + + // Now we _finally_ know these are valid saved bits + + Common::Rect rect; + byte mask; + assert(h.size >= sizeof(rect) + sizeof(mask)); + + memcpy((void *)&rect, memoryPtr, sizeof(rect)); + memcpy((void *)&mask, memoryPtr + sizeof(rect), sizeof(mask)); + + Common::Point tl(rect.left, rect.top); + Common::Point tr(rect.right-1, rect.top); + Common::Point bl(rect.left, rect.bottom-1); + Common::Point br(rect.right-1, rect.bottom-1); + + DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left, + rect.bottom, rect.right); + if (mask & GFX_SCREEN_MASK_VISUAL) + DebugPrintf(" visual"); + if (mask & GFX_SCREEN_MASK_PRIORITY) + DebugPrintf(" priority"); + if (mask & GFX_SCREEN_MASK_CONTROL) + DebugPrintf(" control"); + if (mask & GFX_SCREEN_MASK_DISPLAY) + DebugPrintf(" display"); + DebugPrintf("\n"); + + if (!_engine->_gfxPaint16 || !_engine->_gfxScreen) + return true; + + // We backup all planes, and then flash the saved bits + // FIXME: This probably won't work well with hi-res games + + byte bakMask = GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY | GFX_SCREEN_MASK_CONTROL; + int bakSize = _engine->_gfxScreen->bitsGetDataSize(rect, bakMask); + reg_t bakScreen = segman->allocateHunkEntry("show_saved_bits backup", bakSize); + byte* bakMemory = segman->getHunkPointer(bakScreen); + assert(bakMemory); + _engine->_gfxScreen->bitsSave(rect, bakMask, bakMemory); + +#ifndef USE_TEXT_CONSOLE_FOR_DEBUGGER + // If a graphical debugger overlay is used, hide it here, so that the + // results can be drawn. + g_system->hideOverlay(); +#endif + + const int paintCount = 3; + for (int i = 0; i < paintCount; ++i) { + _engine->_gfxScreen->bitsRestore(memoryPtr); + _engine->_gfxScreen->drawLine(tl, tr, 0, 255, 255); + _engine->_gfxScreen->drawLine(tr, br, 0, 255, 255); + _engine->_gfxScreen->drawLine(br, bl, 0, 255, 255); + _engine->_gfxScreen->drawLine(bl, tl, 0, 255, 255); + _engine->_gfxScreen->copyRectToScreen(rect); + g_system->updateScreen(); + g_sci->sleep(500); + _engine->_gfxScreen->bitsRestore(bakMemory); + _engine->_gfxScreen->copyRectToScreen(rect); + g_system->updateScreen(); + if (i < paintCount - 1) + g_sci->sleep(500); + } + + _engine->_gfxPaint16->bitsFree(bakScreen); + +#ifndef USE_TEXT_CONSOLE_FOR_DEBUGGER + // Show the graphical debugger overlay + g_system->showOverlay(); +#endif + + return true; +} + + bool Console::cmdParseGrammar(int argc, const char **argv) { DebugPrintf("Parse grammar, in strict GNF:\n"); @@ -2782,7 +2954,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { uint16 argc2 = opparams[1]; if (kFuncNum == kernelFuncNum) { - DebugPrintf("Called from script %d, object %s, method %s(%d) with %d parameters\n", + DebugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n", itr->getNumber(), objName, _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), i, argc2); } @@ -2799,7 +2971,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { // Check for end of function/script if (offset >= script->getBufSize()) break; - if (opcode == op_ret)// && offset >= maxJmpOffset) + if (opcode == op_ret && offset >= maxJmpOffset) break; } // while (true) } // for (uint16 i = 0; i < obj->getMethodCount(); i++) diff --git a/engines/sci/console.h b/engines/sci/console.h index 1e2ebe4ba2..d943923ba1 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -94,6 +94,8 @@ private: bool cmdPlayVideo(int argc, const char **argv); bool cmdAnimateList(int argc, const char **argv); bool cmdWindowList(int argc, const char **argv); + bool cmdSavedBits(int argc, const char **argv); + bool cmdShowSavedBits(int argc, const char **argv); // Segments bool cmdPrintSegmentTable(int argc, const char **argv); bool cmdSegmentInfo(int argc, const char **argv); diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 100b71efa7..302ba13247 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -371,35 +371,11 @@ static ADGameDescription s_fallbackDesc = { static char s_fallbackGameIdBuf[256]; - -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Sci::SciGameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - s_sciGameTitles, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "sci", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class SciMetaEngine : public AdvancedMetaEngine { public: - SciMetaEngine() : AdvancedMetaEngine(detectionParams) {} + SciMetaEngine() : AdvancedMetaEngine(Sci::SciGameDescriptions, sizeof(ADGameDescription), s_sciGameTitles) { + params.singleid = "sci"; + } virtual const char *getName() const { return "SCI [SCI0, SCI01, SCI10, SCI11" diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index d56d8f03cd..def3879945 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -503,6 +503,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Eco Quest 2 - Spanish DOS Floppy (supplied by umbrio in bug report #3313962) + {"ecoquest2", "Floppy", { + {"resource.map", 0, "a6b271b934afa7e84d03816a4fefa67b", 5593}, + {"resource.000", 0, "1c4093f7248240329121fdf8c0d59152", 4209150}, + {"resource.msg", 0, "eff8be1925d42288de55e405983e9314", 117810}, + AD_LISTEND}, + Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Freddy Pharkas - English DOS demo (from FRG) // SCI interpreter version 1.001.069 {"freddypharkas", "Demo", { diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index ee88d8af15..e1e52215d2 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -100,12 +100,12 @@ enum { -reg_t file_open(EngineState *s, const char *filename, int mode, bool unwrapFilename) { +reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool unwrapFilename) { Common::String englishName = g_sci->getSciLanguageString(filename, K_LANG_ENGLISH); Common::String wrappedName = unwrapFilename ? g_sci->wrapFilename(englishName) : englishName; Common::SeekableReadStream *inFile = 0; Common::WriteStream *outFile = 0; - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); if (mode == _K_FILE_MODE_OPEN_OR_FAIL) { // Try to open file, abort if not possible @@ -178,7 +178,7 @@ reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { int mode = argv[1].toUint16(); debugC(kDebugLevelFile, "kFOpen(%s,0x%x)", name.c_str(), mode); - return file_open(s, name.c_str(), mode, true); + return file_open(s, name, mode, true); } static FileHandle *getFileFromHandle(EngineState *s, uint handle) { @@ -349,7 +349,7 @@ reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) { if (findSavegame(saves, savegameId) != -1) { // Confirmed that this id still lives... Common::String filename = g_sci->getSavegameName(savegameId); - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); saveFileMan->removeSavefile(filename); } break; @@ -410,7 +410,7 @@ static bool _savegame_sort_byDate(const SavegameDesc &l, const SavegameDesc &r) // Create a sorted array containing all found savedgames static void listSavegames(Common::Array<SavegameDesc> &saves) { - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); // Load all saves Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); @@ -637,14 +637,14 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { s->r_acc = NULL_REG; Common::String filename = g_sci->getSavegameName(savegameId); - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); Common::OutSaveFile *out; out = saveFileMan->openForSaving(filename); if (!out) { warning("Error opening savegame \"%s\" for writing", filename.c_str()); } else { - if (!gamestate_save(s, out, game_description.c_str(), version.c_str())) { + if (!gamestate_save(s, out, game_description, version)) { warning("Saving the game failed"); } else { s->r_acc = TRUE_REG; // save successful @@ -705,7 +705,7 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { s->r_acc = TRUE_REG; warning("Savegame ID %d not found", savegameId); } else { - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); Common::String filename = g_sci->getSavegameName(savegameId); Common::SeekableReadStream *in; @@ -792,7 +792,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { unwrapFilename = false; } - return file_open(s, name.c_str(), mode, unwrapFilename); + return file_open(s, name, mode, unwrapFilename); } reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { @@ -845,7 +845,7 @@ reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) { reg_t kFileIOUnlink(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); bool result; // SQ4 floppy prepends /\ to the filenames @@ -920,7 +920,7 @@ reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { } void DirSeeker::addAsVirtualFiles(Common::String title, Common::String fileMask) { - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); Common::StringArray foundFiles = saveFileMan->listSavefiles(fileMask); if (!foundFiles.empty()) { _files.push_back(title); @@ -984,7 +984,7 @@ reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager const Common::String wrappedMask = g_sci->wrapFilename(mask); // Obtain a list of all files matching the given mask - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); _files = saveFileMan->listSavefiles(wrappedMask); } @@ -1043,7 +1043,7 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) { exists = Common::File::exists(name); // Check for a savegame with the name - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); if (!exists) exists = !saveFileMan->listSavefiles(name).empty(); @@ -1083,7 +1083,7 @@ reg_t kFileIORename(EngineState *s, int argc, reg_t *argv) { // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 // returns -1 on fail. We just return -1 for all versions. - if (g_engine->getSaveFileManager()->renameSavefile(oldName, newName)) + if (g_sci->getSaveFileManager()->renameSavefile(oldName, newName)) return NULL_REG; else return SIGNAL_REG; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 16098ab275..957930784b 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -174,13 +174,15 @@ reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode break; case Script_SRelative: - if (opsize) - param_value = scr[retval.offset++]; + if (opsize) { + int8 offset = (int8)scr[retval.offset++]; + debugN(" %02x [%04x]", 0xff & offset, 0xffff & (retval.offset + offset)); + } else { - param_value = READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); + int16 offset = (int16)READ_SCI11ENDIAN_UINT16(&scr[retval.offset]); retval.offset += 2; + debugN(" %04x [%04x]", 0xffff & offset, 0xffff & (retval.offset + offset)); } - debugN(opsize ? " %02x [%04x]" : " %04x [%04x]", param_value, (0xffff) & (retval.offset + param_value)); break; case Script_End: diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index e094ed3bd7..3328f80de1 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -192,10 +192,10 @@ static kLanguage charToLanguage(const char c) { } } -Common::String SciEngine::getSciLanguageString(const char *str, kLanguage lang, kLanguage *lang2) const { +Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage lang, kLanguage *lang2) const { kLanguage secondLang = K_LANG_NONE; - const char *seeker = str; + const char *seeker = str.c_str(); while (*seeker) { if ((*seeker == '%') || (*seeker == '#')) { secondLang = charToLanguage(*(seeker + 1)); @@ -242,9 +242,9 @@ Common::String SciEngine::getSciLanguageString(const char *str, kLanguage lang, } if (seeker) - return Common::String(str, seeker - str); + return Common::String(str.c_str(), seeker - str.c_str()); else - return Common::String(str); + return str; } kLanguage SciEngine::getSciLanguage() { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 499574957e..1517355365 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -130,16 +130,16 @@ static reg_t read_var(EngineState *s, int type, int index) { if (solution.type == WORKAROUND_NONE) { #ifdef RELEASE_BUILD // If we are running an official ScummVM release -> fake 0 in unknown cases - warning("Uninitialized read for temp %d from method %s::%s (script %d, room %d, localCall %x)", - index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, - g_sci->getEngineState()->currentRoomNumber(), originReply.localCallOffset); + warning("Uninitialized read for temp %d from method %s::%s (room %d, script %d, localCall %x)", + index, originReply.objectName.c_str(), originReply.methodName.c_str(), s->currentRoomNumber(), + originReply.scriptNr, originReply.localCallOffset); s->variables[type][index] = NULL_REG; break; #else - error("Uninitialized read for temp %d from method %s::%s (script %d, room %d, localCall %x)", - index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, - g_sci->getEngineState()->currentRoomNumber(), originReply.localCallOffset); + error("Uninitialized read for temp %d from method %s::%s (room %d, script %d, localCall %x)", + index, originReply.objectName.c_str(), originReply.methodName.c_str(), s->currentRoomNumber(), + originReply.scriptNr, originReply.localCallOffset); #endif } assert(solution.type == WORKAROUND_FAKE); @@ -366,9 +366,9 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { switch (solution.type) { case WORKAROUND_NONE: kernel->signatureDebug(kernelCall.signature, argc, argv); - error("[VM] k%s[%x]: signature mismatch via method %s::%s (script %d, room %d, localCall 0x%x)", + error("[VM] k%s[%x]: signature mismatch via method %s::%s (room %d, script %d, localCall 0x%x)", kernelCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), - originReply.scriptNr, s->currentRoomNumber(), originReply.localCallOffset); + s->currentRoomNumber(), originReply.scriptNr, originReply.localCallOffset); break; case WORKAROUND_IGNORE: // don't do kernel call, leave acc alone return; @@ -418,13 +418,13 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { int callNameLen = strlen(kernelCall.name); if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) { const char *subCallName = kernelSubCall.name + callNameLen; - error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, room %d, localCall %x)", + error("[VM] k%s(%s): signature mismatch via method %s::%s (room %d, script %d, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), - originReply.scriptNr, s->currentRoomNumber(), originReply.localCallOffset); + s->currentRoomNumber(), originReply.scriptNr, originReply.localCallOffset); } - error("[VM] k%s: signature mismatch via method %s::%s (script %d, room %d, localCall %x)", + error("[VM] k%s: signature mismatch via method %s::%s (room %d, script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), - originReply.scriptNr, s->currentRoomNumber(), originReply.localCallOffset); + s->currentRoomNumber(), originReply.scriptNr, originReply.localCallOffset); break; } case WORKAROUND_IGNORE: // don't do kernel call, leave acc alone diff --git a/engines/sci/engine/vm_types.cpp b/engines/sci/engine/vm_types.cpp index 71a28a9761..e39c7708ad 100644 --- a/engines/sci/engine/vm_types.cpp +++ b/engines/sci/engine/vm_types.cpp @@ -32,9 +32,9 @@ reg_t reg_t::lookForWorkaround(const reg_t right) const { SciTrackOriginReply originReply; SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, arithmeticWorkarounds, &originReply); if (solution.type == WORKAROUND_NONE) - error("Invalid arithmetic operation (params: %04x:%04x and %04x:%04x) from method %s::%s (script %d, room %d, localCall %x)", + error("Invalid arithmetic operation (params: %04x:%04x and %04x:%04x) from method %s::%s (room %d, script %d, localCall %x)", PRINT_REG(*this), PRINT_REG(right), originReply.objectName.c_str(), - originReply.methodName.c_str(), originReply.scriptNr, g_sci->getEngineState()->currentRoomNumber(), + originReply.methodName.c_str(), g_sci->getEngineState()->currentRoomNumber(), originReply.scriptNr, originReply.localCallOffset); assert(solution.type == WORKAROUND_FAKE); return make_reg(0, solution.value); diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index fa25b02a8f..464b4d8d5b 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -34,6 +34,7 @@ namespace Sci { const SciWorkaroundEntry arithmeticWorkarounds[] = { { GID_CAMELOT, 92, 92, 0, "endingCartoon2", "changeState", 0x20d, 0, { WORKAROUND_FAKE, 0 } }, // op_lai: during the ending, sub gets called with no parameters, uses parameter 1 which is theGrail in this case - bug #3044734 { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xcc6, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when giving the papers to the customs officer, gets called against a pointer instead of a number - bug #3034464 + { GID_ECOQUEST2, 100, 0, 0, "Rain", "points", 0xce0, 0, { WORKAROUND_FAKE, 0 } }, // Same as above, for the Spanish version - bug #3313962 { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #3038913 { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) @@ -447,7 +448,7 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun workaround = workaroundList; while (workaround->methodName) { bool objectNameMatches = (workaround->objectName == NULL) || - (workaround->objectName == g_sci->getSciLanguageString(searchObjectName.c_str(), K_LANG_ENGLISH)); + (workaround->objectName == g_sci->getSciLanguageString(searchObjectName, K_LANG_ENGLISH)); // Special case: in the fanmade Russian translation of SQ4, all // of the object names have been deleted or renamed to Russian, @@ -460,7 +461,7 @@ SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroun && ((workaround->roomNr == -1) || (workaround->roomNr == curRoomNumber)) && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel)) && objectNameMatches - && workaround->methodName == g_sci->getSciLanguageString(curMethodName.c_str(), K_LANG_ENGLISH) + && workaround->methodName == g_sci->getSciLanguageString(curMethodName, K_LANG_ENGLISH) && workaround->localCallOffset == lastCall->debugLocalCallOffset && ((workaround->index == -1) || (workaround->index == index))) { // Workaround found diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index 1dbe279f8a..3183ffa2b9 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -84,7 +84,14 @@ reg_t GfxCompare::canBeHereCheckRectList(reg_t checkObject, const Common::Rect & curRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight)); curRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom)); // Check if curRect is within checkRect - if (checkRect.contains(curRect)) + // This behavior is slightly odd, but it's how the original SCI + // engine did it: a rect cannot be contained within itself + // (there is no equality). Do NOT change this to contains(), as + // it breaks KQ4 early (bug #3315639). + if (curRect.right > checkRect.left && + curRect.left < checkRect.right && + curRect.bottom > checkRect.top && + curRect.top < checkRect.bottom) return curObject; } } diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls.cpp index 0289735c0a..8d4712a969 100644 --- a/engines/sci/graphics/controls.cpp +++ b/engines/sci/graphics/controls.cpp @@ -329,7 +329,6 @@ void GfxControls::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, if (style & SCI_CONTROLS_STYLE_SELECTED) { _paint16->frameRect(rect); } - rect.grow(1); if (!getPicNotValid()) _paint16->bitsShow(rect); } else { diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 9d4ab3f589..913f680e99 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -423,7 +423,9 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) { default: while (itemIterator != itemEnd) { itemEntry = *itemIterator; - if ((itemEntry->keyPress == keyPress) && (itemEntry->keyModifier == keyModifier)) + if (itemEntry->keyPress == keyPress && + itemEntry->keyModifier == keyModifier && + itemEntry->enabled) break; itemIterator++; } diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index 6529a6ae64..ce69ba8922 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -330,7 +330,7 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos if (!_addToFlag && _resourceType != SCI_PICTURE_TYPE_SCI32) clearColor = _screen->getColorWhite(); - byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY; + byte drawMask = priority > 15 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY; ptr = celBitmap; ptr += skipCelBitmapPixels; diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 2446ea545e..4ab0b9719f 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -763,11 +763,14 @@ int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) { uint16 GfxScreen::getLowResScreenHeight() { // Some Mac SCI1/1.1 games only take up 190 rows and do not // have the menu bar. + // TODO: Verify that LSL1 and LSL5 use height 190 if (g_sci->getPlatform() == Common::kPlatformMacintosh) { switch (g_sci->getGameId()) { case GID_FREDDYPHARKAS: case GID_KQ5: case GID_KQ6: + case GID_LSL1: + case GID_LSL5: case GID_SQ1: return 190; default: diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 1256db8969..d047eb10a1 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -189,14 +189,6 @@ void GfxTransitions::doit(Common::Rect picRect) { // Now we do the actual transition to the new screen doTransition(_number, false); - if (picRect.bottom != _screen->getHeight()) { - // TODO: this is a workaround for lsl6 not showing menubar when playing - // There is some new code in the sierra sci in ShowPic that seems to do - // something similar to this - _screen->copyToScreen(); - g_system->updateScreen(); - } - _screen->_picNotValid = 0; } diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 5c8e9c3d2e..afb4c184e8 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -692,7 +692,7 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const const int16 celHeight = celInfo->height; const int16 celWidth = celInfo->width; const byte clearKey = celInfo->clearKey; - const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; + const byte drawMask = priority > 15 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; int x, y; if (_embeddedPal) @@ -753,7 +753,7 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const int16 celHeight = celInfo->height; const int16 celWidth = celInfo->width; const byte clearKey = celInfo->clearKey; - const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; + const byte drawMask = priority > 15 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; uint16 scalingX[640]; uint16 scalingY[480]; int16 scaledWidth, scaledHeight; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 77718e4b37..04ccbd97d2 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -290,7 +290,7 @@ public: void setSciLanguage(kLanguage lang); void setSciLanguage(); - Common::String getSciLanguageString(const char *str, kLanguage lang, kLanguage *lang2 = NULL) const; + Common::String getSciLanguageString(const Common::String &str, kLanguage lang, kLanguage *lang2 = NULL) const; // Check if vocabulary needs to get switched (in multilingual parser games) void checkVocabularySwitch(); diff --git a/engines/sci/sound/drivers/amigamac.cpp b/engines/sci/sound/drivers/amigamac.cpp index 158b4b08fb..1436ca45a7 100644 --- a/engines/sci/sound/drivers/amigamac.cpp +++ b/engines/sci/sound/drivers/amigamac.cpp @@ -24,6 +24,7 @@ #include "sci/sound/drivers/mididriver.h" #include "sci/resource.h" +#include "common/debug-channels.h" #include "common/file.h" #include "common/frac.h" #include "common/memstream.h" @@ -33,8 +34,6 @@ namespace Sci { -//#define DEBUG - class MidiDriver_AmigaMac : public MidiDriver_Emulated { public: enum { @@ -287,12 +286,10 @@ void MidiDriver_AmigaMac::playInstrument(int16 *dest, Voice *channel, int count) } void MidiDriver_AmigaMac::changeInstrument(int channel, int instrument) { -#ifdef DEBUG - if (_bank.instruments[instrument][0]) - debugN("Amiga/Mac driver: Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument].name, instrument); + if (((uint)instrument < _bank.instruments.size()) && (_bank.instruments[instrument].size() > 0)) + debugC(1, kDebugLevelSound, "Amiga/Mac driver: Setting channel %i to \"%s\" (%i)", channel, _bank.instruments[instrument].name, instrument); else - warning("Amiga/Mac driver: instrument %i does not exist (channel %i)", instrument, channel); -#endif + debugC(kDebugLevelSound, "Amiga/Mac driver: instrument %i does not exist (channel %i)", instrument, channel); _channels[channel].instrument = instrument; } @@ -325,9 +322,7 @@ void MidiDriver_AmigaMac::stopNote(int ch, int note) { break; if (channel == kChannels) { -#ifdef DEBUG - warning("Amiga/Mac driver: cannot stop note %i on channel %i", note, ch); -#endif + debugC(1, kDebugLevelSound, "Amiga/Mac driver: cannot stop note %i on channel %i", note, ch); return; } @@ -466,9 +461,9 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C instrument->fixedNote = 101; instrument->mode = header[33]; - instrument->transpose = (int8) header[34]; + instrument->transpose = (int8)header[34]; for (int i = 0; i < 4; i++) { - int length = (int8) header[49 + i]; + int length = (int8)header[49 + i]; if (length == 0 && i > 0) length = 256; @@ -488,15 +483,18 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C strncpy(instrument->name, (char *) header + 2, 29); instrument->name[29] = 0; -#ifdef DEBUG - debugN("Amiga/Mac driver: Reading instrument %i: \"%s\" (%i bytes)\n", - *id, instrument->name, size); - debugN(" Mode: %02x\n", instrument->mode); - debugN(" Looping: %s\n", instrument->mode & kModeLoop ? "on" : "off"); - debugN(" Pitch changes: %s\n", instrument->mode & kModePitch ? "on" : "off"); - debugN(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]); - debugN(" Segment offsets: 0 %i %i\n", loop_offset, (int32)READ_BE_UINT32(header + 43)); -#endif + if (DebugMan.isDebugChannelEnabled(kDebugLevelSound)) { + debug("Amiga/Mac driver: Reading instrument %i: \"%s\" (%i bytes)", + *id, instrument->name, size); + debugN(" Mode: %02x (", header[33]); + debugN("looping: %s, ", header[33] & kModeLoop ? "on" : "off"); + debug("pitch changes: %s)", header[33] & kModePitch ? "on" : "off"); + debug(" Transpose: %i", (int8)header[34]); + for (uint i = 0; i < 3; i++) + debug(" Segment %i: %i words @ offset %i", i, (int16)READ_BE_UINT16(header + 35 + 6 * i), (i == 0 ? 0 : (int32)READ_BE_UINT32(header + 31 + 6 * i))); + for (uint i = 0; i < 4; i++) + debug(" Envelope %i: period %i / delta %i / target %i", i, header[49 + i], (int8)header[53 + i], header[57 + i]); + } instrument->samples = (int8 *) malloc(size + 1); if (file.read(instrument->samples, size) < (unsigned int)size) { @@ -511,10 +509,8 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C if (instrument->mode & kModeLoop) { if (loop_offset + seg_size[1] > size) { -#ifdef DEBUG - warning("Amiga/Mac driver: looping samples extend %i bytes past end of sample block", - loop_offset + seg_size[1] - size); -#endif + debugC(kDebugLevelSound, "Amiga/Mac driver: looping samples extend %i bytes past end of sample block", + loop_offset + seg_size[1] - size); seg_size[1] = size - loop_offset; } @@ -675,15 +671,11 @@ void MidiDriver_AmigaMac::send(uint32 b) { break; case 0x0a: // pan // TODO -#ifdef DEBUG - warning("Amiga/Mac driver: ignoring pan 0x%02x event for channel %i", op2, channel); -#endif + debugC(1, kDebugLevelSound, "Amiga/Mac driver: ignoring pan 0x%02x event for channel %i", op2, channel); break; case 0x40: // hold // TODO -#ifdef DEBUG - warning("Amiga/Mac driver: ignoring hold 0x%02x event for channel %i", op2, channel); -#endif + debugC(1, kDebugLevelSound, "Amiga/Mac driver: ignoring hold 0x%02x event for channel %i", op2, channel); break; case 0x4b: // voice mapping break; @@ -768,9 +760,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) { _bank.size = READ_BE_UINT16(header + 38); strncpy(_bank.name, (char *) header + 8, 29); _bank.name[29] = 0; -#ifdef DEBUG - debugN("Amiga/Mac driver: Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name); -#endif + debugC(kDebugLevelSound, "Amiga/Mac driver: Reading %i instruments from bank \"%s\"", _bank.size, _bank.name); for (uint i = 0; i < _bank.size; i++) { int id; @@ -807,9 +797,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil _bank.size = 128; strncpy(_bank.name, (char *) header + 8, 29); _bank.name[29] = 0; -#ifdef DEBUG - debugN("Amiga/Mac driver: Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name); -#endif + debugC(kDebugLevelSound, "Amiga/Mac driver: Reading %i instruments from bank \"%s\"", _bank.size, _bank.name); Common::Array<uint32> instrumentOffsets; instrumentOffsets.resize(_bank.size); diff --git a/engines/scumm/gfx_towns.cpp b/engines/scumm/gfx_towns.cpp index 82bb32cdfb..10d6ee0082 100644 --- a/engines/scumm/gfx_towns.cpp +++ b/engines/scumm/gfx_towns.cpp @@ -248,7 +248,7 @@ void TownsScreen::setupLayer(int layer, int width, int height, int numCol, void l->palette = (uint8*)pal; if (l->palette && _bpp == 1) - warning("TownsScreen::setupLayer(): Layer palette usage requires 15 bit graphics setting.\nLayer palette will be ignored."); + warning("TownsScreen::setupLayer(): Layer palette usage requires 16 bit graphics setting.\nLayer palette will be ignored."); delete[] l->pixels; l->pixels = new uint8[l->pitch * l->height]; @@ -270,7 +270,8 @@ void TownsScreen::setupLayer(int layer, int width, int height, int numCol, void l->bltTmpPal = (l->bpp == 1 && _bpp == 2) ? new uint16[l->numCol] : 0; l->enabled = true; - l->onBottom = (!layer || !_layers[0].enabled); + _layers[0].onBottom = true; + _layers[1].onBottom = _layers[0].enabled ? false : true; l->ready = true; } @@ -420,10 +421,10 @@ void TownsScreen::toggleLayers(int flag) { if (flag < 0 || flag > 3) return; - for (int i = 0; i < 2; ++i) { - _layers[i].enabled = (flag & (i + 1)) ? true : false; - _layers[i].onBottom = (!i || !_layers[0].enabled); - } + _layers[0].enabled = (flag & 1) ? true : false; + _layers[0].onBottom = true; + _layers[1].enabled = (flag & 2) ? true : false; + _layers[1].onBottom = _layers[0].enabled ? false : true; _dirtyRects.clear(); _dirtyRects.push_back(Common::Rect(_width - 1, _height - 1)); @@ -458,12 +459,12 @@ void TownsScreen::updateOutputBuffer() { for (int y = r->top; y <= r->bottom; ++y) { if (l->bpp == _bpp && l->scaleW == 1 && l->onBottom) { - memcpy(dst, l->bltInternY[y] + l->bltInternX[r->left], (r->right + 1 - r->left) * _bpp); + memcpy(dst, &l->bltInternY[y][l->bltInternX[r->left]], (r->right + 1 - r->left) * _bpp); dst += _pitch; } else if (_bpp == 2) { for (int x = r->left; x <= r->right; ++x) { - uint8 *src = l->bltInternY[y] + l->bltInternX[x]; + uint8 *src = &l->bltInternY[y][l->bltInternX[x]]; if (l->bpp == 1) { uint8 col = *src; if (col || l->onBottom) { @@ -480,7 +481,7 @@ void TownsScreen::updateOutputBuffer() { } else { for (int x = r->left; x <= r->right; ++x) { - uint8 col = *(l->bltInternY[y] + l->bltInternX[x]); + uint8 col = l->bltInternY[y][l->bltInternX[x]]; if (col || l->onBottom) { if (l->numCol == 16) col = (col >> 4) & (col & 0x0f); diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 6b195bec84..4565bb9f26 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -171,7 +171,7 @@ bool MacResExtractor::extractResource(int id, CachedCursor *cc) { return false; // If we don't have a cursor palette, force monochrome cursors - bool forceMonochrome = !_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette); + bool forceMonochrome = !_vm->_system->hasFeature(OSystem::kFeatureCursorPalette); Graphics::MacCursor *macCursor = new Graphics::MacCursor(); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index c0c477a597..dd26e23b4d 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -162,7 +162,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _pauseDialog = NULL; _versionDialog = NULL; _fastMode = 0; - _actors = NULL; + _actors = _sortedActors = NULL; _arraySlot = NULL; _inventory = NULL; _newNames = NULL; @@ -584,9 +584,12 @@ ScummEngine::~ScummEngine() { _mixer->stopAll(); - for (int i = 0; i < _numActors; ++i) - delete _actors[i]; - delete[] _actors; + if (_actors) { + for (int i = 0; i < _numActors; ++i) + delete _actors[i]; + delete[] _actors; + } + delete[] _sortedActors; delete[] _2byteFontPtr; @@ -1361,6 +1364,7 @@ void ScummEngine::resetScumm() { #ifdef USE_RGB_COLOR if (_game.features & GF_16BIT_COLOR #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE + || _game.platform == Common::kPlatformFMTowns #endif ) @@ -1832,7 +1836,7 @@ void ScummEngine::setupMusic(int midi) { if (nativeMidiDriver != NULL && _native_mt32) nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && (midi & MDT_ADLIB); - if (_musicType == MDT_ADLIB || MDT_TOWNS || multi_midi) { + if (_musicType == MDT_ADLIB || _musicType == MDT_TOWNS || multi_midi) { adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB)); adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0); } diff --git a/engines/sword25/detection.cpp b/engines/sword25/detection.cpp index edb8c30545..c704b3e833 100644 --- a/engines/sword25/detection.cpp +++ b/engines/sword25/detection.cpp @@ -31,7 +31,7 @@ namespace Sword25 { uint32 Sword25Engine::getGameFlags() const { return _gameDescription->flags; } } -static const PlainGameDescriptor Sword25Game[] = { +static const PlainGameDescriptor sword25Game[] = { {"sword25", "Broken Sword 2.5"}, {0, 0} }; @@ -41,35 +41,13 @@ static const char *directoryGlobs[] = { 0 }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Sword25::gameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - Sword25Game, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - NULL, - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NOMIDI, - // Maximum directory depth - 2, - // List of directory globs - directoryGlobs -}; - class Sword25MetaEngine : public AdvancedMetaEngine { public: - Sword25MetaEngine() : AdvancedMetaEngine(detectionParams) {} - + Sword25MetaEngine() : AdvancedMetaEngine(Sword25::gameDescriptions, sizeof(ADGameDescription), sword25Game) { + params.guioptions = Common::GUIO_NOMIDI; + params.depth = 2; + params.directoryGlobs = directoryGlobs; + } virtual const char *getName() const { return "Sword25"; } diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp index be6d940d23..098bd2c6b9 100644 --- a/engines/sword25/fmv/theora_decoder.cpp +++ b/engines/sword25/fmv/theora_decoder.cpp @@ -479,12 +479,6 @@ void TheoraDecoder::reset() { if (_fileStream) _fileStream->seek(0); -#if ENABLE_THEORA_SEEKING - _videobufGranulePos = -1; - _audiobufGranulePos = 0; - _videobufTime = 0; -#endif - _audiobufFill = 0; _audiobufReady = false; diff --git a/engines/sword25/gfx/animationresource.cpp b/engines/sword25/gfx/animationresource.cpp index a9c9cf9c29..b9d70cf87b 100644 --- a/engines/sword25/gfx/animationresource.cpp +++ b/engines/sword25/gfx/animationresource.cpp @@ -38,11 +38,11 @@ namespace Sword25 { -namespace { -const int DEFAULT_FPS = 10; -const int MIN_FPS = 1; -const int MAX_FPS = 200; -} +enum { + DEFAULT_FPS = 10, + MIN_FPS = 1, + MAX_FPS = 200 +}; AnimationResource::AnimationResource(const Common::String &filename) : Resource(filename, Resource::TYPE_ANIMATION), @@ -112,8 +112,8 @@ bool AnimationResource::parseBooleanKey(Common::String s, bool &result) { bool AnimationResource::parserCallback_animation(ParserNode *node) { if (!parseIntegerKey(node->values["fps"], 1, &_FPS) || (_FPS < MIN_FPS) || (_FPS > MAX_FPS)) { - return parserError("Illegal or missing fps attribute in <animation> tag in \"%s\". Assuming default (\"%d\").", - getFileName().c_str(), DEFAULT_FPS); + return parserError(Common::String::format("Illegal or missing fps attribute in <animation> tag in \"%s\". Assuming default (\"%d\").", + getFileName().c_str(), DEFAULT_FPS)); } // Loop type value diff --git a/engines/sword25/gfx/animationresource.h b/engines/sword25/gfx/animationresource.h index 2a1e3ce882..70291f220e 100644 --- a/engines/sword25/gfx/animationresource.h +++ b/engines/sword25/gfx/animationresource.h @@ -48,36 +48,35 @@ public: AnimationResource(const Common::String &filename); virtual ~AnimationResource(); - virtual const Frame &getFrame(uint index) const { - assert(index < _frames.size()); + virtual const Frame &getFrame(uint index) const { return _frames[index]; } - virtual uint getFrameCount() const { + virtual uint getFrameCount() const { return _frames.size(); } - virtual void unlock() { + virtual void unlock() { release(); } - Animation::ANIMATION_TYPES getAnimationType() const { + Animation::ANIMATION_TYPES getAnimationType() const { return _animationType; } - int getFPS() const { + int getFPS() const { return _FPS; } - int getMillisPerFrame() const { + int getMillisPerFrame() const { return _millisPerFrame; } - bool isScalingAllowed() const { + bool isScalingAllowed() const { return _scalingAllowed; } - bool isAlphaAllowed() const { + bool isAlphaAllowed() const { return _alphaAllowed; } - bool isColorModulationAllowed() const { + bool isColorModulationAllowed() const { return _colorModulationAllowed; } - bool isValid() const { + bool isValid() const { return _valid; } diff --git a/engines/sword25/gfx/fontresource.cpp b/engines/sword25/gfx/fontresource.cpp index f99987fc91..7657abb5f2 100644 --- a/engines/sword25/gfx/fontresource.cpp +++ b/engines/sword25/gfx/fontresource.cpp @@ -115,23 +115,23 @@ bool FontResource::parserCallback_character(ParserNode *node) { int charCode, top, left, right, bottom; if (!parseIntegerKey(node->values["code"], 1, &charCode) || (charCode < 0) || (charCode >= 256)) { - return parserError("Illegal or missing code attribute in <character> tag in \"%s\".", getFileName().c_str()); + return parserError("Illegal or missing code attribute in <character> tag in '" + getFileName() + "'."); } if (!parseIntegerKey(node->values["top"], 1, &top) || (top < 0)) { - return parserError("Illegal or missing top attribute in <character> tag in \"%s\".", getFileName().c_str()); + return parserError("Illegal or missing top attribute in <character> tag in '" + getFileName() + "'."); } if (!parseIntegerKey(node->values["left"], 1, &left) || (left < 0)) { - return parserError("Illegal or missing left attribute in <character> tag in \"%s\".", getFileName().c_str()); + return parserError("Illegal or missing left attribute in <character> tag in '" + getFileName() + "'."); } if (!parseIntegerKey(node->values["right"], 1, &right) || (right < 0)) { - return parserError("Illegal or missing right attribute in <character> tag in \"%s\".", getFileName().c_str()); + return parserError("Illegal or missing right attribute in <character> tag in '" + getFileName() + "'."); } if (!parseIntegerKey(node->values["bottom"], 1, &bottom) || (bottom < 0)) { - return parserError("Illegal or missing bottom attribute in <character> tag in \"%s\".", getFileName().c_str()); + return parserError("Illegal or missing bottom attribute in <character> tag in '" + getFileName() + "'."); } - this->_characterRects[charCode] = Common::Rect(left, top, right, bottom); + _characterRects[charCode] = Common::Rect(left, top, right, bottom); return true; } diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp index 20622b2098..9244137c25 100644 --- a/engines/sword25/sfx/soundengine.cpp +++ b/engines/sword25/sfx/soundengine.cpp @@ -37,6 +37,7 @@ #include "audio/decoders/vorbis.h" #include "common/system.h" +#include "common/config-manager.h" namespace Sword25 { @@ -65,8 +66,6 @@ SoundEngine::SoundEngine(Kernel *pKernel) : ResourceService(pKernel) { } bool SoundEngine::init(uint sampleRate, uint channels) { - warning("STUB: SoundEngine::init(%d, %d)", sampleRate, channels); - return true; } @@ -74,12 +73,44 @@ void SoundEngine::update() { } void SoundEngine::setVolume(float volume, SOUND_TYPES type) { - warning("STUB: SoundEngine::setVolume(%f, %d)", volume, type); + int val = (int)(255 * volume); + + switch (type) { + case SoundEngine::MUSIC: + ConfMan.setInt("music_volume", val); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, val); + break; + case SoundEngine::SPEECH: + ConfMan.setInt("speech_volume", val); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, val); + break; + case SoundEngine::SFX: + ConfMan.setInt("sfx_volume", val); + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, val); + break; + default: + error("Unknown SOUND_TYPE"); + } } float SoundEngine::getVolume(SOUND_TYPES type) { - warning("STUB: SoundEngine::getVolume(%d)", type); - return 0; + int val = 0; + + switch (type) { + case SoundEngine::MUSIC: + val = ConfMan.getInt("music_volume"); + break; + case SoundEngine::SPEECH: + val = ConfMan.getInt("speech_volume"); + break; + case SoundEngine::SFX: + val = ConfMan.getInt("sfx_volume"); + break; + default: + error("Unknown SOUND_TYPE"); + } + + return (float)val / 255.0; } void SoundEngine::pauseAll() { @@ -95,11 +126,15 @@ void SoundEngine::resumeAll() { } void SoundEngine::pauseLayer(uint layer) { - warning("STUB: SoundEngine::pauseLayer(%d)", layer); + // Not used in the game + + warning("SoundEngine::pauseLayer(%d)", layer); } void SoundEngine::resumeLayer(uint layer) { - warning("STUB: SoundEngine::resumeLayer(%d)", layer); + // Not used in the game + + warning("SoundEngine::resumeLayer(%d)", layer); } SndHandle *SoundEngine::getHandle(uint *id) { @@ -207,7 +242,9 @@ void SoundEngine::stopSound(uint handle) { } bool SoundEngine::isSoundPaused(uint handle) { - warning("STUB: SoundEngine::isSoundPaused(%d)", handle); + // Not used in the game + + warning("SoundEngine::isSoundPaused(%d)", handle); return false; } @@ -221,20 +258,18 @@ bool SoundEngine::isSoundPlaying(uint handle) { } float SoundEngine::getSoundVolume(uint handle) { - warning("STUB: SoundEngine::getSoundVolume(%d)", handle); + debugC(1, kDebugSound, "SoundEngine::getSoundVolume(%d)", handle); - return 0; + return (float)_mixer->getChannelVolume(_handles[handle].handle) / 255.0; } float SoundEngine::getSoundPanning(uint handle) { - warning("STUB: SoundEngine::getSoundPanning(%d)", handle); + debugC(1, kDebugSound, "SoundEngine::getSoundPanning(%d)", handle); - return 0; + return (float)_mixer->getChannelBalance(_handles[handle].handle) / 127.0; } Resource *SoundEngine::loadResource(const Common::String &fileName) { - warning("STUB: SoundEngine::loadResource(%s)", fileName.c_str()); - return new SoundResource(fileName); } diff --git a/engines/sword25/util/lua/ldblib.cpp b/engines/sword25/util/lua/ldblib.cpp index b2e249e9b7..4d0333b46e 100644 --- a/engines/sword25/util/lua/ldblib.cpp +++ b/engines/sword25/util/lua/ldblib.cpp @@ -4,6 +4,10 @@ ** See Copyright Notice in lua.h */ +#define FORBIDDEN_SYMBOL_EXCEPTION_stdin +#define FORBIDDEN_SYMBOL_EXCEPTION_stderr +#define FORBIDDEN_SYMBOL_EXCEPTION_fputs +#define FORBIDDEN_SYMBOL_EXCEPTION_fgets #include <stdio.h> #include <stdlib.h> diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp index 5012e6af65..b684560bc7 100644 --- a/engines/teenagent/detection.cpp +++ b/engines/teenagent/detection.cpp @@ -79,37 +79,14 @@ static const ADGameDescription teenAgentGameDescriptions[] = { AD_TABLE_END_MARKER, }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)teenAgentGameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - teenAgentGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "teenagent", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 +enum { + MAX_SAVES = 20 }; -#define MAX_SAVES 20 - - class TeenAgentMetaEngine : public AdvancedMetaEngine { public: - TeenAgentMetaEngine() : AdvancedMetaEngine(detectionParams) { + TeenAgentMetaEngine() : AdvancedMetaEngine(teenAgentGameDescriptions, sizeof(ADGameDescription), teenAgentGames) { + params.singleid = "teenagent"; } virtual const char *getName() const { diff --git a/engines/testbed/config.cpp b/engines/testbed/config.cpp index 6adf82952f..6bd4c82b41 100644 --- a/engines/testbed/config.cpp +++ b/engines/testbed/config.cpp @@ -126,10 +126,13 @@ void TestbedOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ws = _testbedConfMan->getConfigWriteStream(); _testbedConfMan->writeTestbedConfigToStream(ws); delete ws; - default: - GUI::Dialog::handleCommand(sender, cmd, data); + break; + default: + break; } + + GUI::Dialog::handleCommand(sender, cmd, data); } void TestbedInteractionDialog::addText(uint w, uint h, const Common::String text, Graphics::TextAlign textAlign, uint xOffset, uint yPadding) { @@ -150,7 +153,7 @@ void TestbedInteractionDialog::addButton(uint w, uint h, const Common::String na _yOffset += h; } -void TestbedInteractionDialog::addList(uint x, uint y, uint w, uint h, Common::Array<Common::String> &strArray, GUI::ListWidget::ColorList *colors, uint yPadding) { +void TestbedInteractionDialog::addList(uint x, uint y, uint w, uint h, const Common::Array<Common::String> &strArray, GUI::ListWidget::ColorList *colors, uint yPadding) { _yOffset += yPadding; GUI::ListWidget *list = new GUI::ListWidget(this, x, y, w, h); list->setEditable(false); @@ -159,7 +162,7 @@ void TestbedInteractionDialog::addList(uint x, uint y, uint w, uint h, Common::A _yOffset += h; } -void TestbedInteractionDialog::addButtonXY(uint x, uint y, uint w, uint h, const Common::String name, uint32 cmd) { +void TestbedInteractionDialog::addButtonXY(uint x, uint /* y */, uint w, uint h, const Common::String name, uint32 cmd) { _buttonArray.push_back(new GUI::ButtonWidget(this, x, _yOffset, w, h, name, 0, cmd)); } @@ -174,7 +177,6 @@ void TestbedConfigManager::initDefaultConfiguration() { } void TestbedConfigManager::writeTestbedConfigToStream(Common::WriteStream *ws) { - Common::String wStr; for (Common::Array<Testsuite *>::const_iterator i = _testsuiteList.begin(); i < _testsuiteList.end(); i++) { _configFileInterface.setKey("this", (*i)->getName(), boolToString((*i)->isEnabled())); const Common::Array<Test *> &testList = (*i)->getTestList(); @@ -186,13 +188,13 @@ void TestbedConfigManager::writeTestbedConfigToStream(Common::WriteStream *ws) { ws->flush(); } -Common::SeekableReadStream *TestbedConfigManager::getConfigReadStream() { +Common::SeekableReadStream *TestbedConfigManager::getConfigReadStream() const { // Look for config file using SearchMan Common::SeekableReadStream *rs = SearchMan.createReadStreamForMember(_configFileName); return rs; } -Common::WriteStream *TestbedConfigManager::getConfigWriteStream() { +Common::WriteStream *TestbedConfigManager::getConfigWriteStream() const { // Look for config file in game-path const Common::String &path = ConfMan.get("path"); Common::WriteStream *ws; diff --git a/engines/testbed/config.h b/engines/testbed/config.h index c0df65ad32..fd5588aa31 100644 --- a/engines/testbed/config.h +++ b/engines/testbed/config.h @@ -50,8 +50,8 @@ public: ~TestbedConfigManager() {} void selectTestsuites(); void setConfigFile(const Common::String fName) { _configFileName = fName; } - Common::SeekableReadStream *getConfigReadStream(); - Common::WriteStream *getConfigWriteStream(); + Common::SeekableReadStream *getConfigReadStream() const; + Common::WriteStream *getConfigWriteStream() const; void writeTestbedConfigToStream(Common::WriteStream *ws); Testsuite *getTestsuiteByName(const Common::String &name); bool stringToBool(const Common::String str) { return str.equalsIgnoreCase("true") ? true : false; } @@ -119,7 +119,7 @@ public: void addButton(uint w, uint h, const Common::String name, uint32 cmd, uint xOffset = 0, uint yPadding = 8); void addButtonXY(uint x, uint y, uint w, uint h, const Common::String name, uint32 cmd); void addText(uint w, uint h, const Common::String text, Graphics::TextAlign textAlign, uint xOffset, uint yPadding = 8); - void addList(uint x, uint y, uint w, uint h, Common::Array<Common::String> &strArray, GUI::ListWidget::ColorList *colors = 0, uint yPadding = 8); + void addList(uint x, uint y, uint w, uint h, const Common::Array<Common::String> &strArray, GUI::ListWidget::ColorList *colors = 0, uint yPadding = 8); protected: Common::Array<GUI::ButtonWidget *> _buttonArray; uint _xOffset; diff --git a/engines/testbed/detection.cpp b/engines/testbed/detection.cpp index 91518b2b8e..2c3d5b43c5 100644 --- a/engines/testbed/detection.cpp +++ b/engines/testbed/detection.cpp @@ -45,34 +45,11 @@ static const ADGameDescription testbedDescriptions[] = { AD_TABLE_END_MARKER }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)testbedDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 512, - // List of all engine targets - testbed_setting, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "testbed", - // List of files for file-based fallback detection (optional) - 0, - // Flags - ADGF_NO_FLAGS, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class TestbedMetaEngine : public AdvancedMetaEngine { public: - TestbedMetaEngine() : AdvancedMetaEngine(detectionParams) { + TestbedMetaEngine() : AdvancedMetaEngine(testbedDescriptions, sizeof(ADGameDescription), testbed_setting) { + params.md5Bytes = 512; + params.singleid = "testbed"; } virtual const char *getName() const { @@ -83,7 +60,7 @@ public: return "Copyright (C) ScummVM"; } - virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription * /* desc */) const { // Instantiate Engine even if the game data is not found. *engine = new Testbed::TestbedEngine(syst); return true; diff --git a/engines/testbed/fs.cpp b/engines/testbed/fs.cpp index e2bedb1898..62ac616192 100644 --- a/engines/testbed/fs.cpp +++ b/engines/testbed/fs.cpp @@ -167,7 +167,7 @@ TestExitStatus FStests::testWriteFile() { return kTestPassed; } - return kTestFailed; + return kTestFailed; } @@ -189,7 +189,7 @@ FSTestSuite::FSTestSuite() { } void FSTestSuite::enable(bool flag) { - Testsuite::enable(ConfParams.isGameDataFound() & flag); + Testsuite::enable(ConfParams.isGameDataFound() ? flag : false); } } // End of namespace Testbed diff --git a/engines/testbed/graphics.cpp b/engines/testbed/graphics.cpp index b38b83f222..36ec726fc7 100644 --- a/engines/testbed/graphics.cpp +++ b/engines/testbed/graphics.cpp @@ -102,7 +102,7 @@ void GFXtests::initMousePalette() { CursorMan.replaceCursorPalette(palette, 0, 3); } -Common::Rect GFXtests::computeSize(Common::Rect &cursorRect, int scalingFactor, int cursorTargetScale) { +Common::Rect GFXtests::computeSize(const Common::Rect &cursorRect, int scalingFactor, int cursorTargetScale) { if (cursorTargetScale == 1 || scalingFactor == 1) { // Game data and cursor would be scaled equally. // so dimensions would be same. @@ -137,7 +137,7 @@ void GFXtests::HSVtoRGB(int &rComp, int &gComp, int &bComp, int hue, int sat, in float f, p, q, t; if (s == 0) { - r = g = b = v * 255; + rComp = gComp = bComp = (int)(v * 255); return; } @@ -186,7 +186,7 @@ void GFXtests::HSVtoRGB(int &rComp, int &gComp, int &bComp, int hue, int sat, in bComp = (int)(b * 255); } -Common::Rect GFXtests::drawCursor(bool cursorPaletteDisabled, const char *gfxModeName, int cursorTargetScale) { +Common::Rect GFXtests::drawCursor(bool cursorPaletteDisabled, int cursorTargetScale) { // Buffer initialized with yellow color byte buffer[500]; memset(buffer, 2, sizeof(buffer)); @@ -244,12 +244,12 @@ void rotatePalette(byte *palette, int size) { */ void GFXtests::setupMouseLoop(bool disableCursorPalette, const char *gfxModeName, int cursorTargetScale) { bool isFeaturePresent; - isFeaturePresent = g_system->hasFeature(OSystem::kFeatureCursorHasPalette); + isFeaturePresent = g_system->hasFeature(OSystem::kFeatureCursorPalette); Common::Rect cursorRect; if (isFeaturePresent) { - cursorRect = GFXtests::drawCursor(disableCursorPalette, gfxModeName, cursorTargetScale); + cursorRect = GFXtests::drawCursor(disableCursorPalette, cursorTargetScale); Common::EventManager *eventMan = g_system->getEventManager(); Common::Event event; @@ -741,7 +741,7 @@ TestExitStatus GFXtests::scaledCursors() { if (isAspectRatioCorrected) { info += "\nDisabling Aspect ratio correction, for letting cusors match exactly, will be restored after this test."; } - + if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("Info! Skipping test : Scaled Cursors\n"); return kTestSkipped; @@ -753,7 +753,7 @@ TestExitStatus GFXtests::scaledCursors() { } - if (isAspectRatioCorrected) { + if (isAspectRatioCorrected) { g_system->beginGFXTransaction(); g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, false); g_system->endGFXTransaction(); @@ -766,7 +766,7 @@ TestExitStatus GFXtests::scaledCursors() { // for every graphics mode display cursors for cursorTargetScale 1, 2 and 3 // Switch Graphics mode // FIXME: Crashes with "3x" mode now.: - + info = Common::String::format("Testing : Scaled cursors with GFX Mode %s\n", gfxMode->name); if (Testsuite::handleInteractiveInput(info, "OK", "Skip", kOptionRight)) { Testsuite::logPrintf("\tInfo! Skipping sub-test : Scaled Cursors :: GFX Mode %s\n", gfxMode->name); @@ -779,7 +779,7 @@ TestExitStatus GFXtests::scaledCursors() { Testsuite::logPrintf("Info! Explicit exit requested during scaling test, this test may be incomplete\n"); return kTestSkipped; } - + g_system->beginGFXTransaction(); bool isGFXModeSet = g_system->setGraphicsMode(gfxMode->id); @@ -807,7 +807,7 @@ TestExitStatus GFXtests::scaledCursors() { if (Testsuite::handleInteractiveInput(info, "Yes", "No", kOptionRight)) { Testsuite::logPrintf("\tInfo! Failed sub-test : Scaled Cursors :: GFX Mode %s\n", gfxMode->name); } - + if (Engine::shouldQuit()) { // Explicit exit requested Testsuite::logPrintf("Info! Explicit exit requested during scaling test, this test may be incomplete\n"); @@ -824,7 +824,7 @@ TestExitStatus GFXtests::scaledCursors() { if (isAspectRatioCorrected) { g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, true); } - + OSystem::TransactionError gfxError = g_system->endGFXTransaction(); if (gfxError != OSystem::kTransactionSuccess || !isGFXModeSet) { @@ -962,13 +962,14 @@ TestExitStatus GFXtests::paletteRotation() { Testsuite::logPrintf("Info! Skipping test : palette Rotation\n"); return kTestSkipped; } - Common::Point pt(0, 10); + Testsuite::clearEntireScreen(); // Use 256 colors byte palette[256 * 3] = {0}; int r, g, b; + r = g = b = 0; int colIndx; for (int i = 0; i < 256; i++) { @@ -1065,7 +1066,6 @@ TestExitStatus GFXtests::pixelFormats() { } Common::List<Graphics::PixelFormat> pfList = g_system->getSupportedFormats(); - Common::List<Graphics::PixelFormat>::const_iterator iter = pfList.begin(); int numFormatsTested = 0; int numPassed = 0; @@ -1073,7 +1073,7 @@ TestExitStatus GFXtests::pixelFormats() { Testsuite::logDetailedPrintf("Testing Pixel Formats. Size of list : %d\n", pfList.size()); - for (iter = pfList.begin(); iter != pfList.end(); iter++) { + for (Common::List<Graphics::PixelFormat>::const_iterator iter = pfList.begin(); iter != pfList.end(); iter++) { numFormatsTested++; if (iter->bytesPerPixel == 1) { // Palettes already tested diff --git a/engines/testbed/graphics.h b/engines/testbed/graphics.h index 7fa8f9d708..f3013fdf53 100644 --- a/engines/testbed/graphics.h +++ b/engines/testbed/graphics.h @@ -32,9 +32,9 @@ namespace GFXtests { void drawEllipse(int x, int y, int a, int b); void setupMouseLoop(bool disableCursorPalette = false, const char *gfxModeName = "", int cursorTargetScale = 1); void initMousePalette(); -Common::Rect computeSize(Common::Rect &cursorRect, int scalingFactor, int cursorTargetScale); +Common::Rect computeSize(const Common::Rect &cursorRect, int scalingFactor, int cursorTargetScale); void HSVtoRGB(int &rComp, int &gComp, int &bComp, int hue, int sat, int val); -Common::Rect drawCursor(bool cursorPaletteDisabled = false, const char *gfxModeName = "", int cursorTargetScale = 1); +Common::Rect drawCursor(bool cursorPaletteDisabled = false, int cursorTargetScale = 1); // will contain function declarations for GFX tests TestExitStatus cursorTrails(); diff --git a/engines/testbed/midi.cpp b/engines/testbed/midi.cpp index 54be866b4c..69d361b0d6 100644 --- a/engines/testbed/midi.cpp +++ b/engines/testbed/midi.cpp @@ -142,12 +142,12 @@ MidiTestSuite::MidiTestSuite() { // add some fallback test if filesystem loading failed Testsuite::logPrintf("Warning! Midi: Sound data file music.mid not found\n"); _isMidiDataFound = false; - enable(false); + MidiTestSuite::enable(false); } } void MidiTestSuite::enable(bool flag) { - Testsuite::enable(_isMidiDataFound & flag); + Testsuite::enable(_isMidiDataFound ? flag : false); } } diff --git a/engines/testbed/misc.cpp b/engines/testbed/misc.cpp index 35b3c6bfe2..034d3eb27e 100644 --- a/engines/testbed/misc.cpp +++ b/engines/testbed/misc.cpp @@ -24,13 +24,12 @@ namespace Testbed { -Common::String MiscTests::getHumanReadableFormat(TimeDate &td) { +Common::String MiscTests::getHumanReadableFormat(const TimeDate &td) { return Common::String::format("%d:%d:%d on %d/%d/%d (dd/mm/yyyy)", td.tm_hour, td.tm_min, td.tm_sec, td.tm_mday, td.tm_mon + 1, td.tm_year + 1900); } void MiscTests::timerCallback(void *arg) { // Increment arg which actually points to an int - // arg must point to a static data, threads otherwise have their own stack int &valToModify = *((int *) arg); valToModify = 999; // some arbitrary value } @@ -110,7 +109,7 @@ TestExitStatus MiscTests::testDateTime() { } TestExitStatus MiscTests::testTimers() { - static int valToModify = 0; + int valToModify = 0; if (g_system->getTimerManager()->installTimerProc(timerCallback, 100000, &valToModify)) { g_system->delayMillis(150); g_system->getTimerManager()->removeTimerProc(timerCallback); @@ -132,7 +131,7 @@ TestExitStatus MiscTests::testMutexes() { Testsuite::writeOnScreen("Installing mutex", Common::Point(0, 100)); } - static SharedVars sv = {1, 1, true, g_system->createMutex()}; + SharedVars sv = {1, 1, true, g_system->createMutex()}; if (g_system->getTimerManager()->installTimerProc(criticalSection, 100000, &sv)) { g_system->delayMillis(150); diff --git a/engines/testbed/misc.h b/engines/testbed/misc.h index 415fe82903..3f0772c6e5 100644 --- a/engines/testbed/misc.h +++ b/engines/testbed/misc.h @@ -40,7 +40,7 @@ namespace MiscTests { // Miscellaneous tests include testing datetime, timers and mutexes // Helper functions for Misc tests -Common::String getHumanReadableFormat(TimeDate &td); +Common::String getHumanReadableFormat(const TimeDate &td); void timerCallback(void *arg); void criticalSection(void *arg); diff --git a/engines/testbed/savegame.cpp b/engines/testbed/savegame.cpp index b19c8e3872..226e9880a6 100644 --- a/engines/testbed/savegame.cpp +++ b/engines/testbed/savegame.cpp @@ -133,11 +133,11 @@ TestExitStatus SaveGametests::testListingSavefile() { writeDataToFile("tBedSavefileToList.1", "Save me!"); writeDataToFile("tBedSavefileToList.2", "Save me!"); - Common::Error error = saveFileMan->getError(); + Common::Error err = saveFileMan->getError(); - if (error.getCode() != Common::kNoError) { + if (err.getCode() != Common::kNoError) { // Abort. Some Error in writing files - Testsuite::logDetailedPrintf("Error while creating savefiles: %s\n", error.getDesc().c_str()); + Testsuite::logDetailedPrintf("Error while creating savefiles: %s\n", err.getDesc().c_str()); return kTestFailed; } @@ -158,11 +158,9 @@ TestExitStatus SaveGametests::testListingSavefile() { } } return kTestPassed; - } else { - Testsuite::logDetailedPrintf("listing Savefiles failed!\n"); - return kTestFailed; } + Testsuite::logDetailedPrintf("listing Savefiles failed!\n"); return kTestFailed; } @@ -173,8 +171,8 @@ TestExitStatus SaveGametests::testErrorMessages() { // Try opening a non existing file readAndVerifyData("tBedSomeNonExistentSaveFile.0", "File doesn't exists!"); - Common::Error error = saveFileMan->getError(); - if (error.getCode() == Common::kNoError) { + Common::Error err = saveFileMan->getError(); + if (err.getCode() == Common::kNoError) { // blunder! how come? Testsuite::logDetailedPrintf("SaveFileMan.getError() failed\n"); return kTestFailed; diff --git a/engines/testbed/sound.h b/engines/testbed/sound.h index 76d0c7bb61..fea7d9d45b 100644 --- a/engines/testbed/sound.h +++ b/engines/testbed/sound.h @@ -69,10 +69,6 @@ public: const char *getDescription() const { return "Sound Subsystem"; } - -private: - bool _isTestDataFound; - }; } // End of namespace Testbed diff --git a/engines/testbed/testbed.cpp b/engines/testbed/testbed.cpp index 41a705e292..152764eb27 100644 --- a/engines/testbed/testbed.cpp +++ b/engines/testbed/testbed.cpp @@ -76,12 +76,16 @@ void TestbedExitDialog::init() { void TestbedExitDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) { switch (cmd) { + default: + break; + case kCmdRerunTestbed : ConfParams.setRerunFlag(true); cmd = GUI::kCloseCmd; - default: - GUI::Dialog::handleCommand(sender, cmd, data); + break; } + + GUI::Dialog::handleCommand(sender, cmd, data); } bool TestbedEngine::hasFeature(EngineFeature f) const { diff --git a/engines/testbed/testsuite.cpp b/engines/testbed/testsuite.cpp index 77211b3e64..655179aa74 100644 --- a/engines/testbed/testsuite.cpp +++ b/engines/testbed/testsuite.cpp @@ -113,7 +113,7 @@ bool Testsuite::handleInteractiveInput(const Common::String &textToDisplay, cons return prompt.runModal() == result ? true : false; } -void Testsuite::displayMessage(const Common::String &textToDisplay, const char *defaultButton, const char *altButton) { +void Testsuite::displayMessage(const Common::String &textToDisplay, const char *defaultButton) { GUI::MessageDialog prompt(textToDisplay, defaultButton); prompt.runModal(); } @@ -214,10 +214,11 @@ uint Testsuite::parseEvents() { return kSkipNext; } break; + case Common::EVENT_QUIT: case Common::EVENT_RTL: return kEngineQuit; - break; + default: break; } diff --git a/engines/testbed/testsuite.h b/engines/testbed/testsuite.h index 3a3a78b9bb..dc159ce25f 100644 --- a/engines/testbed/testsuite.h +++ b/engines/testbed/testsuite.h @@ -112,7 +112,7 @@ public: */ static bool handleInteractiveInput(const Common::String &textToDisplay, const char *opt1 = "Yes", const char *opt2 = "No", OptionSelected result = kOptionLeft); - static void displayMessage(const Common::String &textToDisplay, const char *defaultButton = "OK", const char *altButton = 0); + static void displayMessage(const Common::String &textToDisplay, const char *defaultButton = "OK"); static Common::Rect writeOnScreen(const Common::String &textToDisplay, const Common::Point &pt, bool flag = false); static void clearScreen(const Common::Rect &rect); static void clearEntireScreen() { @@ -145,7 +145,7 @@ public: static void logPrintf(const char *s, ...) GCC_PRINTF(1, 2); static void logDetailedPrintf(const char *s, ...) GCC_PRINTF(1, 2); - + // Progress bar (Information Display) related methods. /** * Display region is in the bottom. Probably 1/4th of the game screen. @@ -180,7 +180,7 @@ protected: bool _isTsEnabled; private: - + /** * Used from the code to decide if the engine needs to exit */ diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index 0f0e3cd1ef..59a567bc63 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -63,7 +63,7 @@ uint16 TinselEngine::getVersion() const { return _gameDescription->version; } -} +} // End of namespace Tinsel static const PlainGameDescriptor tinselGames[] = { {"tinsel", "Tinsel engine game"}, @@ -74,34 +74,11 @@ static const PlainGameDescriptor tinselGames[] = { #include "tinsel/detection_tables.h" -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Tinsel::gameDescriptions, - // Size of that superset structure - sizeof(Tinsel::TinselGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - tinselGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "tinsel", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - class TinselMetaEngine : public AdvancedMetaEngine { public: - TinselMetaEngine() : AdvancedMetaEngine(detectionParams) {} + TinselMetaEngine() : AdvancedMetaEngine(Tinsel::gameDescriptions, sizeof(Tinsel::TinselGameDescription), tinselGames) { + params.singleid = "tinsel"; + } virtual const char *getName() const { return "Tinsel"; @@ -265,7 +242,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList & if (testFile.open(allFiles[fname])) { tmp.size = (int32)testFile.size(); - tmp.md5 = computeStreamMD5AsString(testFile, detectionParams.md5Bytes); + tmp.md5 = computeStreamMD5AsString(testFile, params.md5Bytes); } else { tmp.size = -1; } @@ -285,7 +262,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList & bool fileMissing = false; - if ((detectionParams.flags & kADFlagUseExtraAsHint) && !extra.empty() && g->desc.extra != extra) + if ((params.flags & kADFlagUseExtraAsHint) && !extra.empty() && g->desc.extra != extra) continue; bool allFilesPresent = true; diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp index ae67d1900e..0bf3316209 100644 --- a/engines/toon/audio.cpp +++ b/engines/toon/audio.cpp @@ -232,8 +232,8 @@ AudioStreamInstance::AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer, _mixer = mixer; _compBuffer = NULL; _bufferOffset = 0; - _lastADPCMval1 = 0; - _lastADPCMval2 = 0; + _lastSample = 0; + _lastStepIndex = 0; _file = stream; _fadingIn = false; _fadingOut = false; @@ -307,8 +307,8 @@ bool AudioStreamInstance::readPacket() { if (_looping) { _file->seek(8); _currentReadSize = 8; - _lastADPCMval1 = 0; - _lastADPCMval2 = 0; + _lastSample = 0; + _lastStepIndex = 0; } else { _bufferSize = 0; stopNow(); @@ -342,52 +342,49 @@ bool AudioStreamInstance::readPacket() { void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize) { debugC(5, kDebugAudio, "decodeADPCM(comp, dest, %d)", packetSize); + // standard IMA ADPCM decoding int32 numSamples = 2 * packetSize; - int32 v18 = _lastADPCMval1; - int32 v19 = _lastADPCMval2; + int32 samp = _lastSample; + int32 stepIndex = _lastStepIndex; for (int32 i = 0; i < numSamples; i++) { uint8 comm = *comp; + bool isOddSample = (i & 1); - int32 v29 = i & 1; - int32 v30; - if (v29 == 0) - v30 = comm & 0xf; + uint8 code; + if (!isOddSample) + code = comm & 0xf; else - v30 = (comm & 0xf0) >> 4; + code = (comm & 0xf0) >> 4; - int32 v31 = v30 & 0x8; - int32 v32 = v30 & 0x7; - int32 v33 = Audio::Ima_ADPCMStream::_imaTable[v19]; - int32 v34 = v33 >> 3; - if (v32 & 4) - v34 += v33; + uint8 sample = code & 0x7; - if (v32 & 2) - v34 += v33 >> 1; + int32 step = Audio::Ima_ADPCMStream::_imaTable[stepIndex]; + int32 E = step >> 3; + if (sample & 4) + E += step; + if (sample & 2) + E += step >> 1; + if (sample & 1) + E += step >> 2; - if (v32 & 1) - v34 += v33 >> 2; + stepIndex += Audio::ADPCMStream::_stepAdjustTable[sample]; + stepIndex = CLIP<int32>(stepIndex, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1); - v19 += Audio::ADPCMStream::_stepAdjustTable[v32]; - v19 = CLIP<int32>(v19, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1); - - if (v31) - v18 -= v34; + if (code & 0x8) + samp -= E; else - v18 += v34; + samp += E; - if (v18 > 32767) - v18 = 32767; - else if (v18 < -32768) - v18 = -32768; + samp = CLIP<int32>(samp, -32768, 32767); - *dest = v18; - comp += v29; + *dest = samp; + if (isOddSample) + comp++; dest++; } - _lastADPCMval1 = v18; - _lastADPCMval2 = v19; + _lastSample = samp; + _lastStepIndex = stepIndex; } void AudioStreamInstance::play(bool fade, Audio::Mixer::SoundType soundType) { diff --git a/engines/toon/audio.h b/engines/toon/audio.h index 52ca21b075..61a534265e 100644 --- a/engines/toon/audio.h +++ b/engines/toon/audio.h @@ -84,8 +84,8 @@ protected: Audio::SoundHandle _handle; Audio::Mixer::SoundType _soundType; Audio::Mixer *_mixer; - int32 _lastADPCMval1; - int32 _lastADPCMval2; + int32 _lastSample; + int32 _lastStepIndex; bool _stopped; AudioManager *_man; int32 _totalSize; diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp index 1056f6ec0d..8ddfcd4fed 100644 --- a/engines/toon/detection.cpp +++ b/engines/toon/detection.cpp @@ -28,7 +28,7 @@ #include "graphics/thumbnail.h" #include "toon/toon.h" -static const PlainGameDescriptor ToonGames[] = { +static const PlainGameDescriptor toonGames[] = { { "toon", "Toonstruck" }, { 0, 0 } }; @@ -117,35 +117,14 @@ static const char * const directoryGlobs[] = { 0 }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Toon::gameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 5000, - // List of all engine targets - ToonGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "toon", - // List of files for file-based fallback detection (optional) - Toon::fileBasedFallback, - // Flags - 0, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 3, - // List of directory globs - directoryGlobs -}; - class ToonMetaEngine : public AdvancedMetaEngine { public: - ToonMetaEngine() : AdvancedMetaEngine(detectionParams) {} - + ToonMetaEngine() : AdvancedMetaEngine(Toon::gameDescriptions, sizeof(ADGameDescription), toonGames) { + params.singleid = "toon"; + params.fileBasedFallback = Toon::fileBasedFallback; + params.depth = 3; + params.directoryGlobs = directoryGlobs; + } virtual const char *getName() const { return "Toon"; } diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index 93da20fb47..0e0978b3d6 100644 --- a/engines/toon/toon.cpp +++ b/engines/toon/toon.cpp @@ -28,6 +28,7 @@ #include "common/savefile.h" #include "common/memstream.h" +#include "engines/advancedDetector.h" #include "engines/util.h" #include "graphics/palette.h" #include "graphics/surface.h" diff --git a/engines/toon/toon.h b/engines/toon/toon.h index 02828f26d1..65c6ba0234 100644 --- a/engines/toon/toon.h +++ b/engines/toon/toon.h @@ -23,7 +23,6 @@ #ifndef TOON_TOON_H #define TOON_TOON_H -#include "engines/advancedDetector.h" #include "engines/engine.h" #include "graphics/surface.h" #include "common/random.h" @@ -44,6 +43,8 @@ namespace Common { class MemoryWriteStreamDynamic; } +struct ADGameDescription; + #define TOON_DAT_VER_MAJ 0 // 1 byte #define TOON_DAT_VER_MIN 3 // 1 byte #define TOON_SAVEGAME_VERSION 4 diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index b7f9c092aa..3e324b5685 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -126,35 +126,16 @@ static const char *directoryGlobs[] = { 0 }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)Touche::gameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 4096, - // List of all engine targets - toucheGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "touche", - // List of files for file-based fallback detection (optional) - Touche::fileBasedFallback, - // Flags - kADFlagPrintWarningOnFileBasedFallback, - // Additional GUI options (for every game} - Common::GUIO_NONE, - // Maximum directory depth - 2, - // List of directory globs - directoryGlobs -}; - class ToucheMetaEngine : public AdvancedMetaEngine { public: - ToucheMetaEngine() : AdvancedMetaEngine(detectionParams) {} - + ToucheMetaEngine() : AdvancedMetaEngine(Touche::gameDescriptions, sizeof(ADGameDescription), toucheGames) { + params.md5Bytes = 4096; + params.singleid = "touche"; + params.fileBasedFallback = Touche::fileBasedFallback; + params.flags = kADFlagPrintWarningOnFileBasedFallback; + params.depth = 2; + params.directoryGlobs = directoryGlobs; + } virtual const char *getName() const { return "Touche"; } diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp index ae337765a2..ed2b03ebc4 100644 --- a/engines/tsage/core.cpp +++ b/engines/tsage/core.cpp @@ -521,24 +521,30 @@ void PlayerMover::pathfind(Common::Point *routeList, Common::Point srcPos, Commo break; } - int var6; - proc1(routeRegions, srcRegion, destRegion, var6); + bool tempVar; // This is used only as internal state for the function. + calculateRestOfRoute(routeRegions, srcRegion, destRegion, tempVar); + // Empty route? if (!routeRegions[0]) { regionIndexes.push_back(destRegion); continue; } - _globals->_walkRegions._field18[0]._pt1 = srcPos; - _globals->_walkRegions._field18[0]._pt2 = srcPos; - _globals->_walkRegions._field18[1]._pt1 = destPos; - _globals->_walkRegions._field18[1]._pt2 = destPos; + // field 0 holds the start, and field 1 holds the destination + WRField18 &currSrcField = _globals->_walkRegions._field18[0]; + WRField18 &currDestField = _globals->_walkRegions._field18[1]; + + currSrcField._pt1 = srcPos; + currSrcField._pt2 = srcPos; + currDestField._pt1 = destPos; + currDestField._pt2 = destPos; int tempList[REGION_LIST_SIZE]; tempList[0] = 0; int endIndex = 0; int idx = 1; + // Find the indexes for each entry in the found route. do { int breakEntry = routeRegions[idx]; int breakEntry2 = routeRegions[idx + 1]; @@ -556,49 +562,52 @@ void PlayerMover::pathfind(Common::Point *routeList, Common::Point srcPos, Commo tempList[idx] = 1; for (int listIndex = 1; listIndex <= endIndex; ++listIndex) { - int var10 = tempList[listIndex]; - int var12 = tempList[listIndex + 1]; + int thisIdx = tempList[listIndex]; + int nextIdx = tempList[listIndex + 1]; + + WRField18 &thisField = _globals->_walkRegions._field18[thisIdx]; + WRField18 &nextField = _globals->_walkRegions._field18[nextIdx]; - if (sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var12]._pt1, - _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2) && - sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var12]._pt2, - _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2)) + if (sub_F8E5_calculatePoint(currSrcField._pt1, nextField._pt1, + thisField._pt1, thisField._pt2) && + sub_F8E5_calculatePoint(currSrcField._pt1, nextField._pt2, + thisField._pt1, thisField._pt2)) continue; Common::Point tempPt; - if (sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[1]._pt1, - _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2, &tempPt)) { + if (sub_F8E5_calculatePoint(currSrcField._pt1, currDestField._pt1, + thisField._pt1, thisField._pt2, &tempPt)) { // Add point to the route list - _globals->_walkRegions._field18[0]._pt1 = tempPt; + currSrcField._pt1 = tempPt; *routeList++ = tempPt; } else { - int v16 = - (findDistance(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var10]._pt1) << 1) + - (findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[1]._pt1) << 1) + - findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var12]._pt1) + - findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var12]._pt2); - - int v1A = - (findDistance(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var10]._pt2) << 1) + - (findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[1]._pt2) << 1) + - findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[var12]._pt1) + - findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[var12]._pt2); - - if (v16 < v1A) { - checkMovement2(_globals->_walkRegions._field18[var10]._pt1, - _globals->_walkRegions._field18[var10]._pt2, 1, objPos); + int dist1 = + (findDistance(currSrcField._pt1, thisField._pt1) << 1) + + (findDistance(thisField._pt1, currDestField._pt1) << 1) + + findDistance(thisField._pt1, nextField._pt1) + + findDistance(thisField._pt1, nextField._pt2); + + int dist2 = + (findDistance(currSrcField._pt1, thisField._pt2) << 1) + + (findDistance(thisField._pt2, currDestField._pt2) << 1) + + findDistance(thisField._pt2, nextField._pt1) + + findDistance(thisField._pt2, nextField._pt2); + + // Do 1 step of movement, storing the new position in objPos. + if (dist1 < dist2) { + doStepsOfNpcMovement(thisField._pt1, thisField._pt2, 1, objPos); } else { - checkMovement2(_globals->_walkRegions._field18[var10]._pt2, - _globals->_walkRegions._field18[var10]._pt1, 1, objPos); + doStepsOfNpcMovement(thisField._pt2, thisField._pt1, 1, objPos); } - _globals->_walkRegions._field18[0]._pt1 = objPos; + // Update the current position. + currSrcField._pt1 = objPos; *routeList++ = objPos; } } // Add in the route entry - *routeList++ = _globals->_walkRegions._field18[1]._pt1; + *routeList++ = currDestField._pt1; } // Mark the end of the path @@ -746,7 +755,7 @@ int PlayerMover::checkMover(Common::Point &srcPos, const Common::Point &destPos) return regionIndex; } -void PlayerMover::checkMovement2(const Common::Point &srcPos, const Common::Point &destPos, int numSteps, Common::Point &ptOut) { +void PlayerMover::doStepsOfNpcMovement(const Common::Point &srcPos, const Common::Point &destPos, int numSteps, Common::Point &ptOut) { Common::Point objPos = _sceneObject->_position; _sceneObject->_position = srcPos; uint32 regionBitList = _sceneObject->_regionBitList; @@ -771,9 +780,10 @@ void PlayerMover::checkMovement2(const Common::Point &srcPos, const Common::Poin _sceneObject->_mover = this; } -int PlayerMover::proc1(int *routeList, int srcRegion, int destRegion, int &v) { +int PlayerMover::calculateRestOfRoute(int *routeList, int srcRegion, int destRegion, bool &foundRoute) { + // Make a copy of the provided route. The first entry is the size. int tempList[REGION_LIST_SIZE + 1]; - v = 0; + foundRoute = false; for (int idx = 0; idx <= *routeList; ++idx) tempList[idx] = routeList[idx]; @@ -791,24 +801,28 @@ int PlayerMover::proc1(int *routeList, int srcRegion, int destRegion, int &v) { WalkRegion &srcWalkRegion = _globals->_walkRegions[srcRegion]; int distance; if (!routeList[0]) { - // No route + // The route is empty (new route). distance = 0; } else { + // Find the distance from the last region in the route. WalkRegion ®ion = _globals->_walkRegions[routeList[*routeList]]; distance = findDistance(srcWalkRegion._pt, region._pt); } + // Add the srcRegion to the end of the route. tempList[++*tempList] = srcRegion; - int newIndex = *tempList; + int ourListSize = *tempList; if (srcRegion == destRegion) { - v = 1; - for (int idx = newIndex; idx <= *tempList; ++idx) { + // We made a route to the destination; copy that route and return. + foundRoute = true; + for (int idx = ourListSize; idx <= *tempList; ++idx) { routeList[idx] = tempList[idx]; ++*routeList; } return distance; } else { + // Find the first connected region leading to our destination. int foundIndex = 0; int idx = 0; int currDest; @@ -821,27 +835,32 @@ int PlayerMover::proc1(int *routeList, int srcRegion, int destRegion, int &v) { ++idx; } - int resultOffset = 31990; - while (((currDest = _globals->_walkRegions._idxList[srcWalkRegion._idxListIndex + foundIndex]) != 0) && (v == 0)) { - int newDistance = proc1(tempList, currDest, destRegion, v); + // Check every connected region until we find a route to the destination (or we have no more to check). + int bestDistance = 31990; + while (((currDest = _globals->_walkRegions._idxList[srcWalkRegion._idxListIndex + foundIndex]) != 0) && (!foundRoute)) { + int newDistance = calculateRestOfRoute(tempList, currDest, destRegion, foundRoute); - if ((newDistance <= resultOffset) || v) { - routeList[0] = newIndex - 1; + if ((newDistance <= bestDistance) || foundRoute) { + // We found a shorter possible route, or one leading to the destination. - for (int i = newIndex; i <= tempList[0]; ++i) { + // Overwrite the route with this new one. + routeList[0] = ourListSize - 1; + + for (int i = ourListSize; i <= tempList[0]; ++i) { routeList[i] = tempList[i]; ++routeList[0]; } - resultOffset = newDistance; + bestDistance = newDistance; } - tempList[0] = newIndex; + // Truncate our local list to the size it was before the call. + tempList[0] = ourListSize; ++foundIndex; } - v = 0; - return resultOffset + distance; + foundRoute = false; + return bestDistance + distance; } } @@ -855,71 +874,62 @@ int PlayerMover::findDistance(const Common::Point &pt1, const Common::Point &pt2 return (int)sqrt(xx + yy); } -bool PlayerMover::sub_F8E5(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3, +bool PlayerMover::sub_F8E5_calculatePoint(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3, const Common::Point &pt4, Common::Point *ptOut) { - double diff1 = pt2.x - pt1.x; - double diff2 = pt2.y - pt1.y; - double diff3 = pt4.x - pt3.x; - double diff4 = pt4.y - pt3.y; - double var10 = 0.0, var8 = 0.0; - double var18 = 0.0, var20 = 0.0; + double diffX1 = pt2.x - pt1.x; + double diffY1 = pt2.y - pt1.y; + double diffX2 = pt4.x - pt3.x; + double diffY2 = pt4.y - pt3.y; + double ratio1 = 0.0, ratio2 = 0.0; + double adjustedY1 = 0.0, adjustedY2 = 0.0; - if (diff1 != 0.0) { - var8 = diff2 / diff1; - var18 = pt1.y - (pt1.x * var8); + // Calculate the ratios between the X and Y points. + if (diffX1 != 0.0) { + ratio1 = diffY1 / diffX1; + adjustedY1 = pt1.y - (pt1.x * ratio1); } - if (diff3 != 0.0) { - var10 = diff4 / diff3; - var20 = pt3.y - (pt3.x * var10); + if (diffX2 != 0.0) { + ratio2 = diffY2 / diffX2; + adjustedY2 = pt3.y - (pt3.x * ratio2); } - if (var8 == var10) + if (ratio1 == ratio2) return false; - double var48, var50; - if (diff1 == 0) { - if (diff3 == 0) + double xPos, yPos; + if (diffX1 == 0) { + if (diffX2 == 0) return false; - var48 = pt1.x; - var50 = var10 * var48 + var20; + xPos = pt1.x; + yPos = ratio2 * xPos + adjustedY2; } else { - var48 = (diff3 == 0) ? pt3.x : (var20 - var18) / (var8 - var10); - var50 = var8 * var48 + var18; + xPos = (diffX2 == 0) ? pt3.x : (adjustedY2 - adjustedY1) / (ratio1 - ratio2); + yPos = ratio1 * xPos + adjustedY1; } - bool var52 = false, var56 = false, var54 = false, var58 = false; - Common::Point tempPt((int)(var48 + 0.5), (int)(var50 + 0.5)); + // This is our candidate point, which we must check for validity. + Common::Point tempPt((int)(xPos + 0.5), (int)(yPos + 0.5)); - if ((tempPt.x >= pt3.x) && (tempPt.x <= pt4.x)) - var56 = true; - else if ((tempPt.x >= pt4.x) && (tempPt.x <= pt3.x)) - var56 = true; - if (var56) { - if ((tempPt.y >= pt3.y) && (tempPt.y <= pt4.y)) - var58 = true; - else if ((tempPt.y >= pt4.y) && (tempPt.y <= pt3.y)) - var58 = true; - } - - if ((tempPt.x >= pt1.x) && (tempPt.x <= pt2.x)) - var52 = true; - else if ((tempPt.x >= pt2.x) && (tempPt.x <= pt1.x)) - var52 = true; - if (var52) { - if ((tempPt.y >= pt1.y) && (tempPt.y <= pt2.y)) - var54 = true; - else if ((tempPt.y >= pt2.y) && (tempPt.y <= pt1.y)) - var54 = true; - } + // Is tempPt inside the second bounds? + if (!((tempPt.x >= pt3.x) && (tempPt.x <= pt4.x))) + if (!((tempPt.x >= pt4.x) && (tempPt.x <= pt3.x))) + return false; + if (!((tempPt.y >= pt3.y) && (tempPt.y <= pt4.y))) + if (!((tempPt.y >= pt4.y) && (tempPt.y <= pt3.y))) + return false; - if (var52 && var54 && var56 && var58) { - if (ptOut) - *ptOut = tempPt; - return true; - } + // Is tempPt inside the first bounds? + if (!((tempPt.x >= pt1.x) && (tempPt.x <= pt2.x))) + if (!((tempPt.x >= pt2.x) && (tempPt.x <= pt1.x))) + return false; + if (!((tempPt.y >= pt1.y) && (tempPt.y <= pt2.y))) + if (!((tempPt.y >= pt2.y) && (tempPt.y <= pt1.y))) + return false; - return false; + if (ptOut) + *ptOut = tempPt; + return true; } /*--------------------------------------------------------------------------*/ @@ -1353,6 +1363,8 @@ void ScenePalette::changeBackground(const Rect &bounds, FadeMode fadeMode) { void ScenePalette::synchronize(Serializer &s) { if (s.getVersion() >= 2) SavedObject::synchronize(s); + if (s.getVersion() >= 5) + _listeners.synchronize(s); s.syncBytes(_palette, 256 * 3); s.syncAsSint32LE(_colors.foreground); @@ -2564,6 +2576,9 @@ void SceneText::synchronize(Serializer &s) { s.syncAsSint16LE(_color2); s.syncAsSint16LE(_color3); SYNC_ENUM(_textMode, TextAlign); + + if (s.getVersion() >= 5) + _textSurface.synchronize(s); } /*--------------------------------------------------------------------------*/ diff --git a/engines/tsage/core.h b/engines/tsage/core.h index 71130e5b0b..92907addbc 100644 --- a/engines/tsage/core.h +++ b/engines/tsage/core.h @@ -229,12 +229,12 @@ protected: int regionIndexOf(int xp, int yp) { return regionIndexOf(Common::Point(xp, yp)); } int findClosestRegion(Common::Point &pt, const Common::List<int> &indexList); int checkMover(Common::Point &srcPos, const Common::Point &destPos); - void checkMovement2(const Common::Point &pt1, const Common::Point &pt2, int numSteps, Common::Point &ptOut); - int proc1(int *routeList, int srcRegion, int destRegion, int &v); + void doStepsOfNpcMovement(const Common::Point &pt1, const Common::Point &pt2, int numSteps, Common::Point &ptOut); + int calculateRestOfRoute(int *routeList, int srcRegion, int destRegion, bool &foundRoute); static Common::Point *findLinePoint(RouteEnds *routeEnds, Common::Point *objPos, int length, Common::Point *outPos); static int findDistance(const Common::Point &pt1, const Common::Point &pt2); - static bool sub_F8E5(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3, + static bool sub_F8E5_calculatePoint(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3, const Common::Point &pt4, Common::Point *ptOut = NULL); public: Common::Point _finalDest; diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp index 20c2002257..e9e80312b9 100644 --- a/engines/tsage/detection.cpp +++ b/engines/tsage/detection.cpp @@ -66,25 +66,16 @@ static const PlainGameDescriptor tSageGameTitles[] = { #include "engines/tsage/detection_tables.h" -static const ADParams detectionParams = { - (const byte *)tSage::gameDescriptions, - sizeof(tSage::tSageGameDescription), - 0, - tSageGameTitles, - 0, - "tsage", - NULL, - 0, - Common::GUIO_NONE, - 0, - NULL +enum { + MAX_SAVES = 100 }; -#define MAX_SAVES 100 - class TSageMetaEngine : public AdvancedMetaEngine { public: - TSageMetaEngine() : AdvancedMetaEngine(detectionParams) { + TSageMetaEngine() : AdvancedMetaEngine(tSage::gameDescriptions, sizeof(tSage::tSageGameDescription), tSageGameTitles) { + params.md5Bytes = 5000; + params.singleid = "tsage"; + params.guioptions = Common::GUIO_NOSPEECH; } virtual const char *getName() const { diff --git a/engines/tsage/detection_tables.h b/engines/tsage/detection_tables.h index dc55f2a66d..fb97e40449 100644 --- a/engines/tsage/detection_tables.h +++ b/engines/tsage/detection_tables.h @@ -24,7 +24,7 @@ namespace tSage { static const tSageGameDescription gameDescriptions[] = { - // Ringworld English CD version + // Ringworld CD and First Wave versions { { "ring", @@ -38,26 +38,12 @@ static const tSageGameDescription gameDescriptions[] = { GType_Ringworld, GF_CD | GF_ALT_REGIONS }, - // Ringworld First Wave English CD version - { - { - "ring", - "CD", - AD_ENTRY1s("ring.rlb", "0a25b4ee58d44a54425c0b47e5096bbc", 37847618), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_Ringworld, - GF_CD | GF_ALT_REGIONS - }, // Ringworld English Floppy version { { "ring", "Floppy", - AD_ENTRY1s("ring.rlb", "61f78f68a56832ae95fe06748c403234", 8438770), + AD_ENTRY1s("ring.rlb", "7b7f0c5b37b58fa5ec06ebb2ca0d0d9d", 8438770), Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, @@ -71,7 +57,7 @@ static const tSageGameDescription gameDescriptions[] = { { "ring", "Floppy Demo", - AD_ENTRY1s("tsage.rlb", "bf4e8525d0cab84b08b57126092eeacd", 833453), + AD_ENTRY1s("tsage.rlb", "3b3604a97c06c91f3735d3e9d341f63f", 833453), Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, @@ -80,6 +66,8 @@ static const tSageGameDescription gameDescriptions[] = { GType_Ringworld, GF_FLOPPY | GF_DEMO }, +#if 0 + // FIXME: Compute new MD5s based on 5000 bytes instead of 0 (unlimited) // Ringworld English Floppy Demo #2 version { { @@ -94,13 +82,13 @@ static const tSageGameDescription gameDescriptions[] = { GType_Ringworld, GF_FLOPPY | GF_DEMO | GF_ALT_REGIONS }, - - // Blue Force + // FIXME: Compute new MD5s based on 5000 bytes instead of 0 (unlimited) + // Blue Force floppy { { "blueforce", - "", - AD_ENTRY1s("blue.rlb", "467da43c848cc0e800b547c59d84ccb1", 10032614), + "Floppy", + AD_ENTRY1s("blue.rlb", "17c3993415e8a2cf93040eef7e88ec93", 1156508), Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, @@ -109,12 +97,13 @@ static const tSageGameDescription gameDescriptions[] = { GType_BlueForce, GF_FLOPPY }, - // Blue Force floppy +#endif + // Blue Force { { "blueforce", - "Floppy", - AD_ENTRY1s("blue.rlb", "17c3993415e8a2cf93040eef7e88ec93", 1156508), + "", + AD_ENTRY1s("blue.rlb", "17eabb456cb1546c66baf1aff387ba6a", 10032614), Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, @@ -128,7 +117,7 @@ static const tSageGameDescription gameDescriptions[] = { { "blueforce", "CD", - AD_ENTRY1s("blue.rlb", "ac29f38184cb3b874ea18523059872ba", 63863322), + AD_ENTRY1s("blue.rlb", "99983f48cb218f1f3760cf2f9a7ef11d", 63863322), Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, diff --git a/engines/tsage/dialogs.cpp b/engines/tsage/dialogs.cpp index 759deebbef..c1bd1d027f 100644 --- a/engines/tsage/dialogs.cpp +++ b/engines/tsage/dialogs.cpp @@ -43,21 +43,20 @@ MessageDialog::MessageDialog(const Common::String &message, const Common::String const Common::String &btn2Message) : GfxDialog() { // Set up the message addElements(&_msg, &_btn1, NULL); - + _msg.set(message, 200, ALIGN_LEFT); - _btn1._bounds.moveTo(_msg._bounds.left, _msg._bounds.bottom + 2); + _msg._bounds.moveTo(0, 0); _defaultButton = &_btn1; // Set up the first button _btn1.setText(btn1Message); - _btn1._bounds.moveTo(_msg._bounds.right - _btn1._bounds.width(), _msg._bounds.bottom); + _btn1._bounds.moveTo(_msg._bounds.right - _btn1._bounds.width(), _msg._bounds.bottom + 2); if (!btn2Message.empty()) { // Set up the second button - _defaultButton = &_btn2; add(&_btn2); _btn2.setText(btn2Message); - _btn2._bounds.moveTo(_msg._bounds.right - _btn2._bounds.width(), _msg._bounds.bottom); + _btn2._bounds.moveTo(_msg._bounds.right - _btn2._bounds.width(), _msg._bounds.bottom + 2); _btn1._bounds.translate(-(_btn2._bounds.width() + 4), 0); } @@ -82,8 +81,9 @@ int MessageDialog::show2(const Common::String &message, const Common::String &bt MessageDialog *dlg = new MessageDialog(message, btn1Message, btn2Message); dlg->draw(); - GfxButton *selectedButton = dlg->execute(); - int result = (selectedButton == &dlg->_btn1) ? 0 : 1; + GfxButton *defaultButton = !btn2Message.empty() ? &dlg->_btn2 : &dlg->_btn1; + GfxButton *selectedButton = dlg->execute(defaultButton); + int result = (selectedButton == defaultButton) ? 1 : 0; delete dlg; return result; @@ -473,7 +473,7 @@ void InventoryDialog::execute() { g_system->updateScreen(); } if (_vm->getEventManager()->shouldQuit()) - return; + break; hiliteObj = NULL; if ((event.eventType == EVENT_BUTTON_DOWN) && !_bounds.contains(event.mousePos)) diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp index e889c56c4d..9df2a7ccd6 100644 --- a/engines/tsage/events.cpp +++ b/engines/tsage/events.cpp @@ -304,4 +304,14 @@ void EventsClass::delay(int numFrames) { _priorFrameTime = g_system->getMillis(); } +void EventsClass::listenerSynchronize(Serializer &s) { + s.syncAsUint32LE(_frameNumber); + s.syncAsUint32LE(_prevDelayFrame); + + if (s.getVersion() >= 5) { + s.syncAsSint16LE(_currentCursor); + s.syncAsSint16LE(_lastCursor); + } +} + } // end of namespace tSage diff --git a/engines/tsage/events.h b/engines/tsage/events.h index 9a7bdbe82c..a13455d378 100644 --- a/engines/tsage/events.h +++ b/engines/tsage/events.h @@ -98,11 +98,7 @@ public: uint32 getFrameNumber() const { return _frameNumber; } void delay(int numFrames); - virtual void listenerSynchronize(Serializer &s) { - s.syncAsUint32LE(_frameNumber); - s.syncAsUint32LE(_prevDelayFrame); - // TODO: Synchronize unknown stuff - } + virtual void listenerSynchronize(Serializer &s); }; } // End of namespace tSage diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp index e629396501..863f1458b1 100644 --- a/engines/tsage/globals.cpp +++ b/engines/tsage/globals.cpp @@ -50,33 +50,42 @@ static SavedObject *classFactoryProc(const Common::String &className) { /*--------------------------------------------------------------------------*/ -Globals::Globals() : - _dialogCenter(160, 140), - _gfxManagerInstance(_screenSurface), - _randomSource("tsage") { +Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface), + _randomSource("tsage"), _unkColor1(0), _unkColor2(255), _unkColor3(255) { reset(); _stripNum = 0; + _gfxEdgeAdjust = 3; if (_vm->getFeatures() & GF_DEMO) { _gfxFontNumber = 0; _gfxColors.background = 6; _gfxColors.foreground = 0; - _fontColors.background = 0; - _fontColors.foreground = 0; + _fontColors.background = 255; + _fontColors.foreground = 6; _dialogCenter.y = 80; + // Workaround in order to use later version of the engine + _unkColor1 = _gfxColors.foreground; + _unkColor2 = _gfxColors.foreground; + _unkColor3 = _gfxColors.foreground; } else if ((_vm->getGameID() == GType_Ringworld) && (_vm->getFeatures() & GF_CD)) { _gfxFontNumber = 50; _gfxColors.background = 53; _gfxColors.foreground = 0; _fontColors.background = 51; _fontColors.foreground = 54; - warning("TODO: Check the 3 additional colors"); + _unkColor1 = 18; + _unkColor2 = 18; + _unkColor3 = 18; } else { _gfxFontNumber = 50; _gfxColors.background = 53; _gfxColors.foreground = 18; _fontColors.background = 51; _fontColors.foreground = 54; + // Workaround in order to use later version of the engine + _unkColor1 = _gfxColors.foreground; + _unkColor2 = _gfxColors.foreground; + _unkColor3 = _gfxColors.foreground; } _screenSurface.setScreenSurface(); _gfxManagers.push_back(&_gfxManagerInstance); @@ -131,6 +140,12 @@ void Globals::synchronize(Serializer &s) { s.syncAsSint32LE(_gfxColors.foreground); s.syncAsSint32LE(_fontColors.background); s.syncAsSint32LE(_fontColors.foreground); + + if (s.getVersion() >= 4) { + s.syncAsByte(_unkColor1); + s.syncAsByte(_unkColor2); + s.syncAsByte(_unkColor3); + } s.syncAsSint16LE(_dialogCenter.x); s.syncAsSint16LE(_dialogCenter.y); _sceneListeners.synchronize(s); diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h index 6b3df587b6..8212387ed1 100644 --- a/engines/tsage/globals.h +++ b/engines/tsage/globals.h @@ -51,6 +51,7 @@ public: int _gfxFontNumber; GfxColors _gfxColors; GfxColors _fontColors; + byte _unkColor1, _unkColor2, _unkColor3; SoundManager _soundManager; Common::Point _dialogCenter; WalkRegions _walkRegions; @@ -67,6 +68,7 @@ public: SequenceManager _sequenceManager; Common::RandomSource _randomSource; int _stripNum; + int _gfxEdgeAdjust; public: Globals(); ~Globals(); diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp index cc11343c9c..25dc897ecd 100644 --- a/engines/tsage/graphics.cpp +++ b/engines/tsage/graphics.cpp @@ -304,6 +304,43 @@ void GfxSurface::unlockSurface() { } } +void GfxSurface::synchronize(Serializer &s) { + assert(!_lockSurfaceCtr); + assert(!_screenSurface); + + s.syncAsByte(_disableUpdates); + _bounds.synchronize(s); + s.syncAsSint16LE(_centroid.x); + s.syncAsSint16LE(_centroid.y); + s.syncAsSint16LE(_transColor); + + if (s.isSaving()) { + // Save contents of the surface + if (_customSurface) { + s.syncAsSint16LE(_customSurface->w); + s.syncAsSint16LE(_customSurface->h); + s.syncBytes((byte *)_customSurface->pixels, _customSurface->w * _customSurface->h); + } else { + int zero = 0; + s.syncAsSint16LE(zero); + s.syncAsSint16LE(zero); + } + } else { + int w, h; + s.syncAsSint16LE(w); + s.syncAsSint16LE(h); + + if ((w == 0) || (h == 0)) { + if (_customSurface) + delete _customSurface; + _customSurface = NULL; + } else { + create(w, h); + s.syncBytes((byte *)_customSurface->pixels, w * h); + } + } +} + /** * Fills a specified rectangle on the surface with the specified color * @@ -589,6 +626,9 @@ void GfxElement::setDefaults() { _fontNumber = _globals->_gfxFontNumber; _colors = _globals->_gfxColors; _fontColors = _globals->_fontColors; + _unkColor1 = _globals->_unkColor1; + _unkColor2 = _globals->_unkColor2; + _unkColor3 = _globals->_unkColor3; } /** @@ -602,7 +642,7 @@ void GfxElement::highlight() { // Scan through the contents of the element, switching any occurances of the foreground // color with the background color and vice versa Rect tempRect(_bounds); - tempRect.collapse(2, 2); + tempRect.collapse(_globals->_gfxEdgeAdjust - 1, _globals->_gfxEdgeAdjust - 1); for (int yp = tempRect.top; yp < tempRect.bottom; ++yp) { byte *lineP = (byte *)surface.getBasePtr(tempRect.left, yp); @@ -634,7 +674,7 @@ void GfxElement::drawFrame() { } Rect tempRect = _bounds; - tempRect.collapse(3, 3); + tempRect.collapse(_globals->_gfxEdgeAdjust, _globals->_gfxEdgeAdjust); tempRect.collapse(-1, -1); gfxManager.fillRect(tempRect, _colors.background); @@ -783,7 +823,10 @@ void GfxMessage::draw() { // Set the font and color gfxManager.setFillFlag(false); gfxManager._font.setFontNumber(_fontNumber); - gfxManager._font._colors.foreground = this->_colors.foreground; + + gfxManager._font._colors.foreground = this->_unkColor1; + gfxManager._font._colors2.background = this->_unkColor2; + gfxManager._font._colors2.foreground = this->_unkColor3; // Display the text gfxManager._font.writeLines(_message.c_str(), _bounds, _textAlign); @@ -803,8 +846,10 @@ void GfxButton::setDefaults() { gfxManager._font.getStringBounds(_message.c_str(), tempRect, 240); tempRect.right = ((tempRect.right + 15) / 16) * 16; - // Set the button bounds to a reduced area - tempRect.collapse(-3, -3); + // Set the button bounds + tempRect.collapse(-_globals->_gfxEdgeAdjust, -_globals->_gfxEdgeAdjust); + if (_vm->getFeatures() & GF_CD) + --tempRect.top; tempRect.moveTo(_bounds.left, _bounds.top); _bounds = tempRect; } @@ -820,11 +865,17 @@ void GfxButton::draw() { // Set the font and color gfxManager._font.setFontNumber(_fontNumber); - gfxManager._font._colors.foreground = this->_colors.foreground; + + // + gfxManager._font._colors.foreground = this->_unkColor1; + gfxManager._font._colors2.background = this->_unkColor2; + gfxManager._font._colors2.foreground = this->_unkColor3; // Display the button's text Rect tempRect(_bounds); - tempRect.collapse(3, 3); + tempRect.collapse(_globals->_gfxEdgeAdjust, _globals->_gfxEdgeAdjust); + if (_vm->getFeatures() & GF_CD) + ++tempRect.top; gfxManager._font.writeLines(_message.c_str(), tempRect, ALIGN_CENTER); gfxManager.unlockSurface(); @@ -885,7 +936,7 @@ void GfxDialog::setDefaults() { // Set the dialog boundaries _gfxManager._bounds = tempRect; - tempRect.collapse(-6, -6); + tempRect.collapse(-_globals->_gfxEdgeAdjust * 2, -_globals->_gfxEdgeAdjust * 2); _bounds = tempRect; } @@ -915,7 +966,7 @@ void GfxDialog::draw() { drawFrame(); // Reset the dialog's graphics manager to only draw within the dialog boundaries - tempRect.translate(6, 6); + tempRect.translate(_globals->_gfxEdgeAdjust * 2, _globals->_gfxEdgeAdjust * 2); _gfxManager._bounds = tempRect; // Draw each element in the dialog in order @@ -952,7 +1003,7 @@ void GfxDialog::addElements(GfxElement *ge, ...) { } void GfxDialog::setTopLeft(int xp, int yp) { - _bounds.moveTo(xp - 6, yp - 6); + _bounds.moveTo(xp - _globals->_gfxEdgeAdjust * 2, yp - _globals->_gfxEdgeAdjust * 2); } void GfxDialog::setCenter(int xp, int yp) { diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h index b269520039..e09e1093a3 100644 --- a/engines/tsage/graphics.h +++ b/engines/tsage/graphics.h @@ -91,6 +91,7 @@ public: void setScreenSurface(); Graphics::Surface lockSurface(); void unlockSurface(); + void synchronize(Serializer &s); void create(int width, int height); void setBounds(const Rect &bounds) { _bounds = bounds; } const Rect &getBounds() const { return _bounds; } @@ -176,6 +177,7 @@ public: uint16 _fontNumber; GfxColors _colors; GfxColors _fontColors; + byte _unkColor1, _unkColor2, _unkColor3; uint16 _keycode; public: GfxElement(); diff --git a/engines/tsage/ringworld_demo.cpp b/engines/tsage/ringworld_demo.cpp index 3ad414fa20..de8dbf8c12 100644 --- a/engines/tsage/ringworld_demo.cpp +++ b/engines/tsage/ringworld_demo.cpp @@ -40,17 +40,7 @@ Scene *RingworldDemoGame::createScene(int sceneNumber) { } void RingworldDemoGame::quitGame() { - _globals->_events.setCursor(CURSOR_ARROW); - MessageDialog *dlg = new MessageDialog(DEMO_EXIT_MSG, EXIT_BTN_STRING, DEMO_BTN_STRING); - dlg->draw(); - - GfxButton *selectedButton = dlg->execute(&dlg->_btn2); - bool exitFlag = selectedButton != &dlg->_btn2; - - delete dlg; - _globals->_events.hideCursor(); - - if (exitFlag) + if (MessageDialog::show(DEMO_EXIT_MSG, EXIT_BTN_STRING, DEMO_BTN_STRING) == 0) _vm->quitGame(); } diff --git a/engines/tsage/ringworld_scenes1.cpp b/engines/tsage/ringworld_scenes1.cpp index 82f0153d8f..6960788db3 100644 --- a/engines/tsage/ringworld_scenes1.cpp +++ b/engines/tsage/ringworld_scenes1.cpp @@ -3102,6 +3102,18 @@ void Scene6100::Action7::signal() { /*--------------------------------------------------------------------------*/ +void Scene6100::Object::synchronize(Serializer &s) { + SceneObject::synchronize(s); + + // Save the double fields of the FloatSet + s.syncBytes((byte *)&_floats._float1, sizeof(double)); + s.syncBytes((byte *)&_floats._float2, sizeof(double)); + s.syncBytes((byte *)&_floats._float3, sizeof(double)); + s.syncBytes((byte *)&_floats._float4, sizeof(double)); +} + +/*--------------------------------------------------------------------------*/ + void Scene6100::ProbeMover::dispatch() { Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; @@ -3123,14 +3135,43 @@ void Scene6100::Item1::doAction(int action) { /*--------------------------------------------------------------------------*/ +Scene6100::Scene6100(): Scene() { + _objList[0] = &_sunflower1; + _objList[1] = &_sunflower2; + _objList[2] = &_sunflower3; + _objList[3] = &_rocks; + + _speed = 30; + _fadePercent = 100; + _rocksCheck = false; + _hitCount = 0; + _turnAmount = 0; + _angle = 0; + _msgActive = false; + + _globals->_sceneHandler._delayTicks = 8; + + _globals->_player.disableControl(); + _globals->_events.setCursor(CURSOR_WALK); +} + +void Scene6100::synchronize(Serializer &s) { + Scene::synchronize(s); + + s.syncAsSint16LE(_speed); + s.syncAsSint16LE(_fadePercent); + s.syncAsByte(_rocksCheck); + s.syncAsByte(_msgActive); + s.syncAsSint16LE(_hitCount); + s.syncAsSint16LE(_turnAmount); + s.syncAsSint16LE(_angle); +} + void Scene6100::postInit(SceneObjectList *OwnerList) { loadScene(6100); Scene::postInit(); setZoomPercents(62, 2, 200, 425); - _globals->_sceneHandler._delayTicks = 8; - _globals->_player.disableControl(); - _globals->_events.setCursor(CURSOR_WALK); _stripManager.addSpeaker(&_speakerQR); _stripManager.addSpeaker(&_speakerSL); @@ -3178,11 +3219,6 @@ void Scene6100::postInit(SceneObjectList *OwnerList) { _probe._floats._float3 = 0.0; _probe.hide(); - _objList[0] = &_sunflower1; - _objList[1] = &_sunflower2; - _objList[2] = &_sunflower3; - _objList[3] = &_rocks; - int baseVal = 2000; for (int idx = 0; idx < 3; ++idx) { _objList[idx]->_floats._float1 = _globals->_randomSource.getRandomNumber(999); @@ -3201,14 +3237,6 @@ void Scene6100::postInit(SceneObjectList *OwnerList) { _objList[idx]->changeZoom(-1); } - _speed = 30; - _fadePercent = 100; - _rocksCheck = false; - _hitCount = 0; - _turnAmount = 0; - _angle = 0; - _msgActive = false; - setAction(&_action5); _globals->_scenePalette.addRotation(96, 143, -1); diff --git a/engines/tsage/ringworld_scenes1.h b/engines/tsage/ringworld_scenes1.h index 554b261f2c..abd765473c 100644 --- a/engines/tsage/ringworld_scenes1.h +++ b/engines/tsage/ringworld_scenes1.h @@ -483,6 +483,8 @@ class Scene6100 : public Scene { class Object : public SceneObject { public: FloatSet _floats; + + virtual void synchronize(Serializer &s); }; class ProbeMover : public NpcMover { public: @@ -519,6 +521,8 @@ public: Object *_objList[4]; bool _msgActive; + Scene6100(); + virtual void synchronize(Serializer &s); virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void remove(); virtual void process(Event &event); diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp index 56df32146a..522e40c236 100644 --- a/engines/tsage/saveload.cpp +++ b/engines/tsage/saveload.cpp @@ -206,7 +206,6 @@ Common::Error Saver::restore(int slot) { // Final post-restore notifications _macroRestoreFlag = false; _loadNotifiers.notify(false); - _globals->_events.setCursor(_globals->_player._uiEnabled ? CURSOR_WALK : CURSOR_NONE); return Common::kNoError; } diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h index 51b7696590..c1c2851f28 100644 --- a/engines/tsage/saveload.h +++ b/engines/tsage/saveload.h @@ -33,7 +33,7 @@ namespace tSage { typedef void (*SaveNotifierFn)(bool postFlag); -#define TSAGE_SAVEGAME_VERSION 3 +#define TSAGE_SAVEGAME_VERSION 5 class SavedObject; diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h index 563fdfcc21..5db45f24ab 100644 --- a/engines/tsage/tsage.h +++ b/engines/tsage/tsage.h @@ -23,7 +23,6 @@ #ifndef TSAGE_H #define TSAGE_H -#include "engines/advancedDetector.h" #include "engines/engine.h" #include "common/rect.h" #include "audio/mixer.h" diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index 31d9caef73..3eb3973371 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -102,31 +102,6 @@ static const ADGameDescription tuckerGameDescriptions[] = { AD_TABLE_END_MARKER }; -static const ADParams detectionParams = { - // Pointer to ADGameDescription or its superset structure - (const byte *)tuckerGameDescriptions, - // Size of that superset structure - sizeof(ADGameDescription), - // Number of bytes to compute MD5 sum for - 512, - // List of all engine targets - tuckerGames, - // Structure for autoupgrading obsolete targets - 0, - // Name of single gameid (optional) - "tucker", - // List of files for file-based fallback detection (optional) - 0, - // Flags - 0, - // Additional GUI options (for every game) - Common::GUIO_NONE, - // Maximum directory depth - 1, - // List of directory globs - 0 -}; - static const ADGameDescription tuckerDemoGameDescription = { "tucker", "Non-Interactive Demo", @@ -139,7 +114,9 @@ static const ADGameDescription tuckerDemoGameDescription = { class TuckerMetaEngine : public AdvancedMetaEngine { public: - TuckerMetaEngine() : AdvancedMetaEngine(detectionParams) { + TuckerMetaEngine() : AdvancedMetaEngine(tuckerGameDescriptions, sizeof(ADGameDescription), tuckerGames) { + params.md5Bytes = 512; + params.singleid = "tucker"; } virtual const char *getName() const { |