diff options
Diffstat (limited to 'engines/wintermute')
30 files changed, 1274 insertions, 447 deletions
diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp index 75e7c45d7e..a598581632 100644 --- a/engines/wintermute/ad/ad_actor.cpp +++ b/engines/wintermute/ad/ad_actor.cpp @@ -34,6 +34,7 @@ #include "engines/wintermute/ad/ad_waypoint_group.h" #include "engines/wintermute/ad/ad_path.h" #include "engines/wintermute/ad/ad_sentence.h" +#include "engines/wintermute/base/base_frame.h" #include "engines/wintermute/base/base_parser.h" #include "engines/wintermute/base/sound/base_sound.h" #include "engines/wintermute/base/base_region.h" @@ -919,7 +920,7 @@ void AdActor::getNextStep() { ////////////////////////////////////////////////////////////////////////// void AdActor::initLine(const BasePoint &startPt, const BasePoint &endPt) { - _pFCount = MAX((abs(endPt.x - startPt.x)) , (abs(endPt.y - startPt.y))); + _pFCount = MAX((abs(endPt.x - startPt.x)), (abs(endPt.y - startPt.y))); _pFStepX = (double)(endPt.x - startPt.x) / _pFCount; _pFStepY = (double)(endPt.y - startPt.y) / _pFCount; @@ -1022,6 +1023,55 @@ bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] StopWalking + // Used to stop Leah in one scene only at rabbit_run.script in action() + // Let's just call turnTo() for current direction to finalize movement + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StopWalking") == 0) { + stack->correctParams(0); + turnTo(_dir); + stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] SetSpeedWalkAnim + // Used to set Leah speed at leah.script in SetSpeed() + // Modifies walking animations interframe delays + // Takes integer parameter: + // 10 on state.ultra_super_mega_fast_walk cheat code + // 40 on "Fast" settings + // 70 on "Normal" settings + // 90 on "Slow" settings + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetSpeedWalkAnim") == 0) { + stack->correctParams(1); + int speedWalk = stack->pop()->getInt(); + for (uint32 dir = 0; dir < NUM_DIRECTIONS; dir++) { + AdSpriteSet *anim = getAnimByName(_walkAnimName); + if (anim != nullptr) { + BaseSprite *item = anim->getSprite((TDirection)dir); + if (item != nullptr) { + for (uint32 i = 0; i < item->_frames.size(); i++) { + BaseFrame *frame = item->_frames[i]; + if (frame != nullptr) { + frame->_delay = speedWalk; + } + } + } + } + } + stack->pushNULL(); + + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // MergeAnims ////////////////////////////////////////////////////////////////////////// diff --git a/engines/wintermute/ad/ad_entity.cpp b/engines/wintermute/ad/ad_entity.cpp index 7a4df6c114..ea7c46c5ac 100644 --- a/engines/wintermute/ad/ad_entity.cpp +++ b/engines/wintermute/ad/ad_entity.cpp @@ -34,6 +34,7 @@ #include "engines/wintermute/ad/ad_sentence.h" #include "engines/wintermute/base/base_active_rect.h" #include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/base/base_file_manager.h" #include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/base_parser.h" @@ -67,6 +68,10 @@ AdEntity::AdEntity(BaseGame *inGame) : AdTalkHolder(inGame) { _walkToX = _walkToY = 0; _walkToDir = DI_NONE; +#ifdef ENABLE_FOXTAIL + _hintX = _hintY = -1; +#endif + _theora = nullptr; } @@ -98,6 +103,16 @@ const char *AdEntity::getItemName() const { return _item; } +#ifdef ENABLE_FOXTAIL +int32 AdEntity::getHintX() const { + return _hintX; +} + +int32 AdEntity::getHintY() const { + return _hintY; +} +#endif + ////////////////////////////////////////////////////////////////////////// bool AdEntity::loadFile(const char *filename) { char *buffer = (char *)BaseFileManager::getEngineInstance()->readWholeFile(filename); @@ -164,6 +179,10 @@ TOKEN_DEF(WALK_TO_X) TOKEN_DEF(WALK_TO_Y) TOKEN_DEF(WALK_TO_DIR) TOKEN_DEF(SAVE_STATE) +#ifdef ENABLE_FOXTAIL +TOKEN_DEF(HINT_X) +TOKEN_DEF(HINT_Y) +#endif TOKEN_DEF_END ////////////////////////////////////////////////////////////////////////// bool AdEntity::loadBuffer(char *buffer, bool complete) { @@ -210,6 +229,10 @@ bool AdEntity::loadBuffer(char *buffer, bool complete) { TOKEN_TABLE(WALK_TO_Y) TOKEN_TABLE(WALK_TO_DIR) TOKEN_TABLE(SAVE_STATE) +#ifdef ENABLE_FOXTAIL + TOKEN_TABLE(HINT_X) + TOKEN_TABLE(HINT_Y) +#endif TOKEN_TABLE_END char *params; @@ -487,6 +510,14 @@ bool AdEntity::loadBuffer(char *buffer, bool complete) { i = DI_NONE; } _walkToDir = (TDirection)i; +#ifdef ENABLE_FOXTAIL + case TOKEN_HINT_X: + parser.scanStr(params, "%d", &_hintX); + break; + case TOKEN_HINT_Y: + parser.scanStr(params, "%d", &_hintY); + break; +#endif } break; @@ -900,6 +931,24 @@ ScValue *AdEntity::scGetProperty(const Common::String &name) { return _scValue; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] HintX + ////////////////////////////////////////////////////////////////////////// + else if (name == "HintX") { + _scValue->setInt(_hintX); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] HintY + ////////////////////////////////////////////////////////////////////////// + else if (name == "HintY") { + _scValue->setInt(_hintY); + return _scValue; + } +#endif + ////////////////////////////////////////////////////////////////////////// // WalkToDirection ////////////////////////////////////////////////////////////////////////// @@ -951,6 +1000,24 @@ bool AdEntity::scSetProperty(const char *name, ScValue *value) { return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] HintX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "HintX") == 0) { + _hintX = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HintY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "HintY") == 0) { + _hintY = value->getInt(); + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // WalkToDirection ////////////////////////////////////////////////////////////////////////// @@ -1012,6 +1079,11 @@ bool AdEntity::saveAsText(BaseDynamicBuffer *buffer, int indent) { buffer->putTextIndent(indent + 2, "WALK_TO_DIR=%d\n", (int)_walkToDir); } +#ifdef ENABLE_FOXTAIL + buffer->putTextIndent(indent + 2, "HINT_X=%d\n", _hintX); + buffer->putTextIndent(indent + 2, "HINT_Y=%d\n", _hintY); +#endif + for (uint32 i = 0; i < _scripts.size(); i++) { buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); } @@ -1108,6 +1180,13 @@ bool AdEntity::persist(BasePersistenceManager *persistMgr) { persistMgr->transferPtr(TMEMBER_PTR(_theora)); +#ifdef ENABLE_FOXTAIL + if (BaseEngine::instance().isFoxTail(FOXTAIL_1_2_527, FOXTAIL_LATEST_VERSION)) { + persistMgr->transferSint32(TMEMBER(_hintX)); + persistMgr->transferSint32(TMEMBER(_hintY)); + } +#endif + return STATUS_OK; } diff --git a/engines/wintermute/ad/ad_entity.h b/engines/wintermute/ad/ad_entity.h index 678608af36..5407093915 100644 --- a/engines/wintermute/ad/ad_entity.h +++ b/engines/wintermute/ad/ad_entity.h @@ -55,6 +55,11 @@ public: TDirection getWalkToDir() const; const char* getItemName() const; +#ifdef ENABLE_FOXTAIL + int32 getHintX() const; + int32 getHintY() const; +#endif + // scripting interface virtual ScValue *scGetProperty(const Common::String &name) override; virtual bool scSetProperty(const char *name, ScValue *value) override; @@ -67,6 +72,11 @@ private: TDirection _walkToDir; char *_item; TEntityType _subtype; + +#ifdef ENABLE_FOXTAIL + int32 _hintX; + int32 _hintY; +#endif }; } // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_game.cpp b/engines/wintermute/ad/ad_game.cpp index dff0216c10..a6730feecd 100644 --- a/engines/wintermute/ad/ad_game.cpp +++ b/engines/wintermute/ad/ad_game.cpp @@ -873,6 +873,19 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] SetInventoryBoxHideSelected + // Used while changing cursor type at some included script + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetInventoryBoxHideSelected") == 0) { + stack->correctParams(1); + _inventoryBox->_hideSelected = stack->pop()->getBool(false); + stack->pushNULL(); + return STATUS_OK; + } +#endif else { return BaseGame::scCallMethod(script, stack, thisStack, name); diff --git a/engines/wintermute/ad/ad_item.cpp b/engines/wintermute/ad/ad_item.cpp index b414fbdadf..cebc6980d9 100644 --- a/engines/wintermute/ad/ad_item.cpp +++ b/engines/wintermute/ad/ad_item.cpp @@ -535,6 +535,23 @@ bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] RemoveNormalCursor + // Used while changing cursor type at some included script + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RemoveNormalCursor") == 0) { + stack->correctParams(0); + + delete _cursorNormal; + _cursorNormal = nullptr; + + stack->pushNULL(); + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // GetNormalCursor ////////////////////////////////////////////////////////////////////////// @@ -584,6 +601,23 @@ bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] RemoveHoverCursor + // Used while changing cursor type at some included script + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RemoveHoverCursor") == 0) { + stack->correctParams(0); + + delete _cursorHover; + _cursorHover = nullptr; + + stack->pushNULL(); + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // GetHoverCursor ////////////////////////////////////////////////////////////////////////// diff --git a/engines/wintermute/ad/ad_response_box.cpp b/engines/wintermute/ad/ad_response_box.cpp index fc8e778f37..bd4ae50eab 100644 --- a/engines/wintermute/ad/ad_response_box.cpp +++ b/engines/wintermute/ad/ad_response_box.cpp @@ -29,6 +29,7 @@ #include "engines/wintermute/ad/ad_game.h" #include "engines/wintermute/ad/ad_response.h" #include "engines/wintermute/ad/ad_response_box.h" +#include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/base/base_dynamic_buffer.h" #include "engines/wintermute/base/base_file_manager.h" #include "engines/wintermute/base/base_parser.h" @@ -190,6 +191,18 @@ bool AdResponseBox::createButtons() { btn->setWidth(width); } } + +#ifdef ENABLE_FOXTAIL + if (BaseEngine::instance().isFoxTail()) { + btn->addScript("interface/scripts/dialogue_button.script"); + btn->setWidth(120); + if (_fontHover == nullptr) { + btn->setFontHover(btn->getFont()); + btn->setFontPress(btn->getFontHover()); + } + } +#endif + btn->setName("response"); btn->correctSize(); @@ -500,6 +513,22 @@ bool AdResponseBox::display() { // prepare response buttons bool scrollNeeded = false; for (i = _scrollOffset; i < _respButtons.size(); i++) { + +#ifdef ENABLE_FOXTAIL + // FoxTail's "HORIZONTAL=TRUE" display boxes are actual 2x3 display boxes + // Tests show that this hack was removed in FOXTAIL_1_2_362 + if (_horizontal && BaseEngine::instance().isFoxTail(FOXTAIL_OLDEST_VERSION, FOXTAIL_1_2_304)) { + if (i >= _scrollOffset + 6) { + scrollNeeded = true; + break; + } + _respButtons[i]->setVisible(true); + _respButtons[i]->_posX = 55 + 120 * (i / 3); + _respButtons[i]->_posY = 100 + 10 * (i % 3); + continue; + } +#endif + if ((_horizontal && xxx + _respButtons[i]->getWidth() > rect.right) || (!_horizontal && yyy + _respButtons[i]->getHeight() > rect.bottom)) { diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h index a8770f6168..14a14a3c19 100644 --- a/engines/wintermute/base/base_engine.h +++ b/engines/wintermute/base/base_engine.h @@ -84,7 +84,14 @@ enum WMETargetExecutable { WME_1_9_2, // DEAD:CODE 2010 WME_1_9_3, // DEAD:CODE 2012, released as "1.10.1 beta" WME_LITE, - LATEST_VERSION + LATEST_VERSION, + FOXTAIL_OLDEST_VERSION, + FOXTAIL_1_2_227, + FOXTAIL_1_2_230, + FOXTAIL_1_2_304, + FOXTAIL_1_2_362, + FOXTAIL_1_2_527, + FOXTAIL_LATEST_VERSION }; class BaseFileManager; @@ -129,6 +136,12 @@ public: WMETargetExecutable getTargetExecutable() const { return _targetExecutable; } + static bool isFoxTailCheck(WMETargetExecutable t, WMETargetExecutable v1=FOXTAIL_OLDEST_VERSION, WMETargetExecutable v2=FOXTAIL_LATEST_VERSION) { + return t >= v1 && t <= v2; + } + bool isFoxTail(WMETargetExecutable v1=FOXTAIL_OLDEST_VERSION, WMETargetExecutable v2=FOXTAIL_LATEST_VERSION) const { + return isFoxTailCheck(_targetExecutable, v1, v2); + } }; } // End of namespace Wintermute diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp index dad8b43d65..6102c10725 100644 --- a/engines/wintermute/base/base_file_manager.cpp +++ b/engines/wintermute/base/base_file_manager.cpp @@ -300,7 +300,7 @@ bool BaseFileManager::registerPackages() { } } debugC(kWintermuteDebugFileAccess, "Registering %s %s", fileIt->getPath().c_str(), fileIt->getName().c_str()); - registerPackage((*fileIt), "", searchSignature); + registerPackage((*fileIt), fileName, searchSignature); } } @@ -311,7 +311,8 @@ bool BaseFileManager::registerPackages() { bool BaseFileManager::registerPackage(Common::FSNode file, const Common::String &filename, bool searchSignature) { PackageSet *pack = new PackageSet(file, filename, searchSignature); - _packages.add(file.getName(), pack, pack->getPriority() , true); + _packages.add(filename, pack, pack->getPriority() , true); + _versions[filename] = pack->getVersion(); return STATUS_OK; } @@ -348,6 +349,16 @@ Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &f return file; } +////////////////////////////////////////////////////////////////////////// +uint32 BaseFileManager::getPackageVersion(const Common::String &filename) { + Common::HashMap<Common::String, uint32>::iterator it = _versions.find(filename); + if (it != _versions.end()) { + return it->_value; + } + return 0; +} + +////////////////////////////////////////////////////////////////////////// bool BaseFileManager::hasFile(const Common::String &filename) { if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) { BasePersistenceManager pm(BaseEngine::instance().getGameTargetName()); diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h index 85181f1f58..397e38cc3d 100644 --- a/engines/wintermute/base/base_file_manager.h +++ b/engines/wintermute/base/base_file_manager.h @@ -46,6 +46,7 @@ public: Common::SeekableReadStream *openFile(const Common::String &filename, bool absPathWarning = true, bool keepTrackOf = true); Common::WriteStream *openFileForWrite(const Common::String &filename); byte *readWholeFile(const Common::String &filename, uint32 *size = nullptr, bool mustExist = true); + uint32 getPackageVersion(const Common::String &filename); BaseFileManager(Common::Language lang, bool detectionMode = false); virtual ~BaseFileManager(); @@ -72,6 +73,8 @@ private: Common::Array<Common::SeekableReadStream *> _openFiles; Common::Language _language; Common::Archive *_resources; + Common::HashMap<Common::String, uint32> _versions; + // This class is intentionally not a subclass of Base, as it needs to be used by // the detector too, without launching the entire engine: }; diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp index a821234ba0..6aa9785d84 100644 --- a/engines/wintermute/base/base_frame.cpp +++ b/engines/wintermute/base/base_frame.cpp @@ -174,7 +174,7 @@ bool BaseFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { int r = 255, g = 255, b = 255; int ar = 255, ag = 255, ab = 255, alpha = 255; int hotspotX = 0, hotspotY = 0; - bool custoTrans = false; + bool customTrans = false; bool editorSelected = false; bool is2DOnly = false; bool is3DOnly = false; @@ -196,7 +196,7 @@ bool BaseFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { case TOKEN_TRANSPARENT: parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - custoTrans = true; + customTrans = true; break; case TOKEN_RECT: @@ -310,7 +310,7 @@ bool BaseFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { BaseSubFrame *sub = new BaseSubFrame(_gameRef); if (surface_file != nullptr) { - if (custoTrans) { + if (customTrans) { sub->setSurface(surface_file, false, r, g, b, lifeTime, keepLoaded); } else { sub->setSurface(surface_file, true, 0, 0, 0, lifeTime, keepLoaded); @@ -323,7 +323,7 @@ bool BaseFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { } sub->_alpha = BYTETORGBA(ar, ag, ab, alpha); - if (custoTrans) { + if (customTrans) { sub->_transparent = BYTETORGBA(r, g, b, 0xFF); } } diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp index a06511f3ea..f5caaa8d2e 100644 --- a/engines/wintermute/base/base_game.cpp +++ b/engines/wintermute/base/base_game.cpp @@ -48,6 +48,7 @@ #include "engines/wintermute/base/base_surface_storage.h" #include "engines/wintermute/base/saveload.h" #include "engines/wintermute/base/save_thumb_helper.h" +#include "engines/wintermute/base/scriptables/script_ext_array.h" #include "engines/wintermute/base/scriptables/script_value.h" #include "engines/wintermute/base/scriptables/script_engine.h" #include "engines/wintermute/base/scriptables/script_stack.h" @@ -1259,6 +1260,21 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] RegistryFlush + // Return value is never used + // Used at SaveGameSettings() and Game.RegistryFlush() + // Called after a series of RegWriteNumber calls + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RegistryFlush") == 0) { + stack->correctParams(0); + ConfMan.flushToDisk(); + stack->pushNULL(); + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // RegWriteNumber ////////////////////////////////////////////////////////////////////////// @@ -1362,13 +1378,54 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack else if (strcmp(name, "GetSaveSlotDescription") == 0) { stack->correctParams(1); int slot = stack->pop()->getInt(); - char desc[512]; - desc[0] = '\0'; - SaveLoad::getSaveSlotDescription(slot, desc); - stack->pushString(desc); + Common::String desc = SaveLoad::getSaveSlotDescription(slot); + stack->pushString(desc.c_str()); return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GetSaveSlotDescriptionTimestamp + // Return struct with "Description" and "Timestamp" fields in 1.2.362- + // Return array with "Description" and "Timestamp" items in 1.2.527+ + // Timestamps should be comparable types + // Used to sort saved games by timestamps at save.script & load.script + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetSaveSlotDescriptionTimestamp") == 0) { + stack->correctParams(1); + int slot = stack->pop()->getInt(); + + TimeDate time; + SaveLoad::getSaveSlotTimestamp(slot, &time); + stack->pushInt(time.tm_sec); + stack->pushInt(time.tm_min); + stack->pushInt(time.tm_hour); + stack->pushInt(time.tm_mday); + stack->pushInt(time.tm_mon + 1); + stack->pushInt(time.tm_year + 1900); + stack->pushInt(6); + BaseScriptable *date = makeSXDate(_gameRef, stack); + stack->pushNative(date, false); + + Common::String desc = SaveLoad::getSaveSlotDescription(slot); + stack->pushString(desc.c_str()); + + BaseScriptable *obj; + if (BaseEngine::instance().isFoxTail(FOXTAIL_1_2_527, FOXTAIL_LATEST_VERSION)) { + stack->pushInt(2); + obj = makeSXArray(_gameRef, stack); + } else { + stack->pushInt(0); + obj = makeSXObject(_gameRef, stack); + obj->scSetProperty("Description", stack->pop()); + obj->scSetProperty("Timestamp", stack->pop()); + } + stack->pushNative(obj, false); + + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // EmptySaveSlot ////////////////////////////////////////////////////////////////////////// @@ -1941,6 +1998,96 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GetScreenType + // Returns 0 on fullscreen and 1 on window + // Used to init and update controls at options.script and methods.script + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetScreenType") == 0) { + stack->correctParams(0); + int type = !g_system->getFeatureState(OSystem::kFeatureFullscreenMode); + stack->pushInt(type); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GetScreenMode + // Returns integer to be used as a pixelization mode multiplier + // (e.g. it returns 2 for 640x360, 3 for 960x540, etc...) + // Used to init and update controls at options.script and methods.script + // This implementation always return 2 to fake window size of 2*320 x 2*180 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetScreenMode") == 0) { + stack->correctParams(0); + stack->pushInt(2); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GetDesktopDisplayMode + // Return struct with "w" and "h" fields in 1.2.362- + // Return array with "w" and "h" items in 1.2.527+ + // Used to init and update controls at options.script and methods.script + // w,h of actual desktop size expected to calcucate maximum available size + // Available screen modes are calcucated as 2...N, N*320<w and N*180<h + // This implementation fakes available size as 2*320 x 2*180 only + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetDesktopDisplayMode") == 0) { + stack->correctParams(0); + stack->pushInt(2 * 180 + 1); + stack->pushInt(2 * 320 + 1); + + BaseScriptable *obj; + if (BaseEngine::instance().isFoxTail(FOXTAIL_1_2_527, FOXTAIL_LATEST_VERSION)) { + stack->pushInt(2); + obj = makeSXArray(_gameRef, stack); + } else { + stack->pushInt(0); + obj = makeSXObject(_gameRef, stack); + obj->scSetProperty("w", stack->pop()); + obj->scSetProperty("h", stack->pop()); + } + stack->pushNative(obj, false); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] SetScreenTypeMode + // This implementation ignores mode, toggles screen type only + // Used to change screen type&mode at options.script and methods.script + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetScreenTypeMode") == 0) { + stack->correctParams(2); + int type = stack->pop()->getInt(); + stack->pop()->getInt(); //mode is unused + g_system->beginGFXTransaction(); + g_system->setFeatureState(OSystem::kFeatureFullscreenMode, !type); + g_system->endGFXTransaction(); + stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] ChangeWindowGrab + // Used at game.script on "Keypress" event on F11 + // Readme of FoxTail says: "F11 - free the mouse pointer from the window" + // This implementation does nothing + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ChangeWindowGrab") == 0) { + stack->correctParams(0); + stack->pushNULL(); + + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // ShowStatusLine ////////////////////////////////////////////////////////////////////////// @@ -2329,6 +2476,123 @@ ScValue *BaseGame::scGetProperty(const Common::String &name) { return _scValue; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] SystemLanguage (RO) + // Returns Steam API language name string + ////////////////////////////////////////////////////////////////////////// + else if (name == "SystemLanguage") { + switch (Common::parseLanguage(ConfMan.get("language"))) { + case Common::CZ_CZE: + _scValue->setString("czech"); + break; + case Common::DA_DAN: + _scValue->setString("danish"); + break; + case Common::DE_DEU: + _scValue->setString("german"); + break; + case Common::ES_ESP: + _scValue->setString("spanish"); + break; + case Common::FI_FIN: + _scValue->setString("finnish"); + break; + case Common::FR_FRA: + _scValue->setString("french"); + break; + case Common::GR_GRE: + _scValue->setString("greek"); + break; + case Common::HU_HUN: + _scValue->setString("hungarian"); + break; + case Common::IT_ITA: + _scValue->setString("italian"); + break; + case Common::JA_JPN: + _scValue->setString("japanese"); + break; + case Common::KO_KOR: + _scValue->setString("koreana"); + break; + case Common::NB_NOR: + _scValue->setString("norwegian"); + break; + case Common::NL_NLD: + _scValue->setString("dutch"); + break; + case Common::PT_BRA: + _scValue->setString("brazilian"); + break; + case Common::PT_POR: + _scValue->setString("portuguese"); + break; + case Common::PL_POL: + _scValue->setString("polish"); + break; + case Common::RU_RUS: + _scValue->setString("russian"); + break; + case Common::SE_SWE: + _scValue->setString("swedish"); + break; + case Common::UA_UKR: + _scValue->setString("ukrainian"); + break; + case Common::ZH_CNA: + _scValue->setString("schinese"); + break; + case Common::ZH_TWN: + _scValue->setString("tchinese"); + break; + default: + _scValue->setString("english"); + break; + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] BuildVersion (RO) + // Used to display full game version at options.script in UpdateControls() + // Returns FoxTail engine version number as a dotted string + ////////////////////////////////////////////////////////////////////////// + else if (name == "BuildVersion") { + if (BaseEngine::instance().getTargetExecutable() == FOXTAIL_1_2_227) { + _scValue->setString("1.2.227"); + } else if (BaseEngine::instance().getTargetExecutable() == FOXTAIL_1_2_230) { + _scValue->setString("1.2.230"); + } else if (BaseEngine::instance().getTargetExecutable() == FOXTAIL_1_2_304) { + _scValue->setString("1.2.304"); + } else if (BaseEngine::instance().getTargetExecutable() == FOXTAIL_1_2_362) { + _scValue->setString("1.2.362"); + } else if (BaseEngine::instance().getTargetExecutable() == FOXTAIL_1_2_527) { + _scValue->setString("1.2.527"); + } else { + _scValue->setString("UNKNOWN"); + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GameVersion (RO) + // Used to display full game version at options.script in UpdateControls() + // Returns FoxTail version number as a string + ////////////////////////////////////////////////////////////////////////// + else if (name == "GameVersion") { + uint32 gameVersion = 0; + BaseFileManager *fileManager = BaseEngine::instance().getFileManager(); + if (fileManager) { + gameVersion = fileManager->getPackageVersion("data.dcp"); + } + char tmp[16]; + sprintf(tmp,"%u",gameVersion); + _scValue->setString(tmp); + return _scValue; + } +#endif + ////////////////////////////////////////////////////////////////////////// // Platform (RO) ////////////////////////////////////////////////////////////////////////// @@ -2997,6 +3261,44 @@ bool BaseGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack stack->pushBool(val); } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] Split + // Returns array of words of a string, using another as a delimeter + // Used to split strings by 1 character delimeter in various scripts + // All the delimeters ever used in FoxTail are: " ", "@", "#", "$", "&" + // So, this implementation takes 1st char of delimeter string only + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Split") == 0) { + stack->correctParams(2); + const char *str = stack->pop()->getString(); + const char sep = stack->pop()->getString()[0]; + size_t size = strlen(str) + 1; + + // There is no way to makeSXArray() with exactly 1 given element + // That's why we are creating empty Array and SXArray::push() later + stack->pushInt(0); + BaseScriptable *arr = makeSXArray(_gameRef, stack); + + // Iterating string copy, replacing delimeter with '\0' and pushing matches + char *copy = new char[size]; + strcpy(copy, str); + char *begin = copy; + for (char *it = copy; it < copy + size; it++) { + if (*it == sep || *it == '\0') { + *it = '\0'; + stack->pushString(begin); + ((SXArray *)arr)->push(stack->pop()); + begin = it + 1; + } + } + + stack->pushNative(arr, false); + + delete[] copy; + } +#endif + ////////////////////////////////////////////////////////////////////////// // failure else { diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp index 13b753a7d6..502577c656 100644 --- a/engines/wintermute/base/base_keyboard_state.cpp +++ b/engines/wintermute/base/base_keyboard_state.cpp @@ -39,8 +39,207 @@ namespace Wintermute { IMPLEMENT_PERSISTENT(BaseKeyboardState, false) +// Used in WME 1.x +// See "MSDN: Virtual-Key Codes" for more details on original WME keycodes +const keyCodeMapping wmeOriginalMapping[] = { + { Common::KEYCODE_BACKSPACE, 8 }, + { Common::KEYCODE_TAB, 9 }, + { Common::KEYCODE_RETURN, 13 }, + { Common::KEYCODE_CAPSLOCK, 20 }, + { Common::KEYCODE_ESCAPE, 27 }, + { Common::KEYCODE_SPACE, 32 }, + + { Common::KEYCODE_PAUSE, 19 }, + { Common::KEYCODE_PAGEUP, 33 }, + { Common::KEYCODE_PAGEDOWN, 34 }, + { Common::KEYCODE_END, 35 }, + { Common::KEYCODE_HOME, 36 }, + { Common::KEYCODE_LEFT, 37 }, + { Common::KEYCODE_UP, 38 }, + { Common::KEYCODE_RIGHT, 39 }, + { Common::KEYCODE_DOWN, 40 }, + { Common::KEYCODE_PRINT, 42 }, + { Common::KEYCODE_INSERT, 45 }, + { Common::KEYCODE_DELETE, 46 }, + { Common::KEYCODE_SCROLLOCK, 145 }, + + { Common::KEYCODE_0, 48 }, + { Common::KEYCODE_1, 49 }, + { Common::KEYCODE_2, 50 }, + { Common::KEYCODE_3, 51 }, + { Common::KEYCODE_4, 52 }, + { Common::KEYCODE_5, 53 }, + { Common::KEYCODE_6, 54 }, + { Common::KEYCODE_7, 55 }, + { Common::KEYCODE_8, 56 }, + { Common::KEYCODE_9, 57 }, + + { Common::KEYCODE_a, 65 }, + { Common::KEYCODE_b, 66 }, + { Common::KEYCODE_c, 67 }, + { Common::KEYCODE_d, 68 }, + { Common::KEYCODE_e, 69 }, + { Common::KEYCODE_f, 70 }, + { Common::KEYCODE_g, 71 }, + { Common::KEYCODE_h, 72 }, + { Common::KEYCODE_i, 73 }, + { Common::KEYCODE_j, 74 }, + { Common::KEYCODE_k, 75 }, + { Common::KEYCODE_l, 76 }, + { Common::KEYCODE_m, 77 }, + { Common::KEYCODE_n, 78 }, + { Common::KEYCODE_o, 79 }, + { Common::KEYCODE_p, 80 }, + { Common::KEYCODE_q, 81 }, + { Common::KEYCODE_r, 82 }, + { Common::KEYCODE_s, 83 }, + { Common::KEYCODE_t, 84 }, + { Common::KEYCODE_u, 85 }, + { Common::KEYCODE_v, 86 }, + { Common::KEYCODE_w, 87 }, + { Common::KEYCODE_x, 88 }, + { Common::KEYCODE_y, 89 }, + { Common::KEYCODE_z, 90 }, + + { Common::KEYCODE_CLEAR, 12 }, + { Common::KEYCODE_KP_ENTER, 13 }, + { Common::KEYCODE_KP0, 96 }, + { Common::KEYCODE_KP1, 97 }, + { Common::KEYCODE_KP2, 98 }, + { Common::KEYCODE_KP3, 99 }, + { Common::KEYCODE_KP4, 100 }, + { Common::KEYCODE_KP5, 101 }, + { Common::KEYCODE_KP6, 102 }, + { Common::KEYCODE_KP7, 103 }, + { Common::KEYCODE_KP8, 104 }, + { Common::KEYCODE_KP9, 105 }, + { Common::KEYCODE_KP_MULTIPLY, 106 }, + { Common::KEYCODE_KP_PLUS, 107 }, + { Common::KEYCODE_KP_MINUS, 109 }, + { Common::KEYCODE_KP_PERIOD, 110 }, + { Common::KEYCODE_KP_DIVIDE, 111 }, + { Common::KEYCODE_NUMLOCK, 144 }, + + { Common::KEYCODE_F1, 112 }, + { Common::KEYCODE_F2, 113 }, + { Common::KEYCODE_F3, 114 }, + { Common::KEYCODE_F4, 115 }, + { Common::KEYCODE_F5, 116 }, + { Common::KEYCODE_F6, 117 }, + { Common::KEYCODE_F7, 118 }, + { Common::KEYCODE_F8, 119 }, + { Common::KEYCODE_F9, 120 }, + { Common::KEYCODE_F10, 121 }, + { Common::KEYCODE_F11, 122 }, + { Common::KEYCODE_F12, 123 }, + + { Common::KEYCODE_INVALID, 0 } +}; + +// Used in WME Lite & FoxTail +// See "SDL_Keycode" for more details on new WME keycodes +const keyCodeMapping wmeSdlMapping[] = { + { Common::KEYCODE_BACKSPACE, 8 }, + { Common::KEYCODE_TAB, 9 }, + { Common::KEYCODE_RETURN, 13 }, + { Common::KEYCODE_ESCAPE, 27 }, + { Common::KEYCODE_SPACE, 32 }, + { Common::KEYCODE_CAPSLOCK, 1073741881 }, + + { Common::KEYCODE_DELETE, 127 }, + { Common::KEYCODE_PRINT, 1073741894 }, + { Common::KEYCODE_SCROLLOCK, 1073741895 }, + { Common::KEYCODE_PAUSE, 1073741896 }, + { Common::KEYCODE_INSERT, 1073741897 }, + { Common::KEYCODE_HOME, 1073741898 }, + { Common::KEYCODE_PAGEUP, 1073741899 }, + { Common::KEYCODE_END, 1073741901 }, + { Common::KEYCODE_PAGEDOWN, 1073741902 }, + { Common::KEYCODE_RIGHT, 1073741903 }, + { Common::KEYCODE_LEFT, 1073741904 }, + { Common::KEYCODE_DOWN, 1073741905 }, + { Common::KEYCODE_UP, 1073741906 }, + + { Common::KEYCODE_0, 48 }, + { Common::KEYCODE_1, 49 }, + { Common::KEYCODE_2, 50 }, + { Common::KEYCODE_3, 51 }, + { Common::KEYCODE_4, 52 }, + { Common::KEYCODE_5, 53 }, + { Common::KEYCODE_6, 54 }, + { Common::KEYCODE_7, 55 }, + { Common::KEYCODE_8, 56 }, + { Common::KEYCODE_9, 57 }, + + { Common::KEYCODE_a, 97 }, + { Common::KEYCODE_b, 98 }, + { Common::KEYCODE_c, 99 }, + { Common::KEYCODE_d, 100 }, + { Common::KEYCODE_e, 101 }, + { Common::KEYCODE_f, 102 }, + { Common::KEYCODE_g, 103 }, + { Common::KEYCODE_h, 104 }, + { Common::KEYCODE_i, 105 }, + { Common::KEYCODE_j, 106 }, + { Common::KEYCODE_k, 107 }, + { Common::KEYCODE_l, 108 }, + { Common::KEYCODE_m, 109 }, + { Common::KEYCODE_n, 110 }, + { Common::KEYCODE_o, 111 }, + { Common::KEYCODE_p, 112 }, + { Common::KEYCODE_q, 113 }, + { Common::KEYCODE_r, 114 }, + { Common::KEYCODE_s, 115 }, + { Common::KEYCODE_t, 116 }, + { Common::KEYCODE_u, 117 }, + { Common::KEYCODE_v, 118 }, + { Common::KEYCODE_w, 119 }, + { Common::KEYCODE_x, 120 }, + { Common::KEYCODE_y, 121 }, + { Common::KEYCODE_z, 122 }, + + { Common::KEYCODE_KP_ENTER, 13 }, + { Common::KEYCODE_NUMLOCK, 1073741907 }, + { Common::KEYCODE_KP_DIVIDE, 1073741908 }, + { Common::KEYCODE_KP_MULTIPLY, 1073741909 }, + { Common::KEYCODE_KP_MINUS, 1073741910 }, + { Common::KEYCODE_KP_PLUS, 1073741911 }, + { Common::KEYCODE_KP1, 1073741913 }, + { Common::KEYCODE_KP2, 1073741914 }, + { Common::KEYCODE_KP3, 1073741915 }, + { Common::KEYCODE_KP4, 1073741916 }, + { Common::KEYCODE_KP5, 1073741917 }, + { Common::KEYCODE_KP6, 1073741918 }, + { Common::KEYCODE_KP7, 1073741919 }, + { Common::KEYCODE_KP8, 1073741920 }, + { Common::KEYCODE_KP9, 1073741921 }, + { Common::KEYCODE_KP0, 1073741922 }, + { Common::KEYCODE_KP_PERIOD, 1073741923 }, + { Common::KEYCODE_CLEAR, 1073741980 }, + + { Common::KEYCODE_F1, 1073741882 }, + { Common::KEYCODE_F2, 1073741883 }, + { Common::KEYCODE_F3, 1073741884 }, + { Common::KEYCODE_F4, 1073741885 }, + { Common::KEYCODE_F5, 1073741886 }, + { Common::KEYCODE_F6, 1073741887 }, + { Common::KEYCODE_F7, 1073741888 }, + { Common::KEYCODE_F8, 1073741889 }, + { Common::KEYCODE_F9, 1073741890 }, + { Common::KEYCODE_F10, 1073741891 }, + { Common::KEYCODE_F11, 1073741892 }, + { Common::KEYCODE_F12, 1073741893 }, + + { Common::KEYCODE_INVALID, 0 } +}; + ////////////////////////////////////////////////////////////////////////// BaseKeyboardState::BaseKeyboardState(BaseGame *inGame) : BaseScriptable(inGame) { + init(); +} + +////////////////////////////////////////////////////////////////////////// +void BaseKeyboardState::init() { _currentPrintable = false; _currentCharCode = 0; _currentKeyData = 0; @@ -53,6 +252,14 @@ BaseKeyboardState::BaseKeyboardState(BaseGame *inGame) : BaseScriptable(inGame) for (int i = 0; i < KEYSTATES_ARRAY_SIZE; i++) { _keyStates[i] = false; } + + if (BaseEngine::instance().getTargetExecutable() < WME_LITE) { + _mapping = wmeOriginalMapping; + _mappingSize = ARRAYSIZE(wmeOriginalMapping); + } else { + _mapping = wmeSdlMapping; + _mappingSize = ARRAYSIZE(wmeSdlMapping); + } } ////////////////////////////////////////////////////////////////////////// @@ -108,8 +315,18 @@ bool BaseKeyboardState::scCallMethod(ScScript *script, ScStack *stack, ScStack * // For letters, single keycode is used for upper and lower case // This mean that IsKeyDown(65) is true for both 'a' and Shift+'a' - // See "MSDN: Virtual-Key Codes" for more details on original WME keycodes - vKeyCode = vKeyToKeyCode(val->getInt()); + vKeyCode = Common::KEYCODE_INVALID; + uint32 temp = (uint32)val->getInt(); + + for (uint32 i = 0; i < _mappingSize; i++) { + if (_mapping[i].engineKeycode == temp) { + vKeyCode = _mapping[i].commonKeycode; + } + } + + if (vKeyCode == Common::KEYCODE_INVALID) { + warning("Unknown VKEY: %d", temp); + } } bool isDown = _keyStates[vKeyCode]; @@ -231,6 +448,11 @@ bool BaseKeyboardState::readKey(Common::Event *event) { else if (code >= Common::KEYCODE_SPACE && code < Common::KEYCODE_DELETE) { _currentCharCode = event->kbd.ascii; _currentPrintable = true; +#ifdef ENABLE_FOXTAIL + if (BaseEngine::instance().isFoxTail()) { + _currentCharCode = tolower(_currentCharCode); + } +#endif } // use ASCII value for numpad '/', '*', '-', '+' @@ -246,22 +468,28 @@ bool BaseKeyboardState::readKey(Common::Event *event) { _currentPrintable = true; } - // use keyCodeToVKey mapping for all other events - // in WME 1.x some of those keys are printable - else if (BaseEngine::instance().getTargetExecutable() < WME_LITE) { - _currentCharCode = keyCodeToVKey(event); - _currentPrintable = code == Common::KEYCODE_BACKSPACE || - code == Common::KEYCODE_TAB || - code == Common::KEYCODE_RETURN || - code == Common::KEYCODE_KP_ENTER || - code == Common::KEYCODE_ESCAPE; - } - - // use keyCodeToVKey mapping for all other events - // in WME_LITE all of those key are not printable + // use _mapping for all other events else { - _currentCharCode = keyCodeToVKey(event); - _currentPrintable = false; + _currentCharCode = 0; + for (uint32 i = 0; i < _mappingSize; i++) { + if (_mapping[i].commonKeycode == event->kbd.keycode) { + _currentCharCode = _mapping[i].engineKeycode; + } + } + + if (!_currentCharCode && (event->kbd.flags & Common::KBD_NON_STICKY) == 0) { + warning("Key pressed (%d '%c') is not recognized, ASCII returned (%d '%c').", event->kbd.keycode, event->kbd.keycode, event->kbd.ascii, event->kbd.ascii); + } + + if (BaseEngine::instance().getTargetExecutable() < WME_LITE) { + _currentPrintable = code == Common::KEYCODE_BACKSPACE || + code == Common::KEYCODE_TAB || + code == Common::KEYCODE_RETURN || + code == Common::KEYCODE_KP_ENTER || + code == Common::KEYCODE_ESCAPE; + } else { + _currentPrintable = false; + } } _currentControl = isControlDown(); @@ -285,10 +513,7 @@ bool BaseKeyboardState::persist(BasePersistenceManager *persistMgr) { persistMgr->transferBool(TMEMBER(_currentShift)); if (!persistMgr->getIsSaving()) { - _keyStates = new uint8[323]; // Hardcoded size for the common/keyboard.h enum - for (int i = 0; i < 323; i++) { - _keyStates[i] = false; - } + init(); } return STATUS_OK; @@ -317,342 +542,4 @@ bool BaseKeyboardState::isCurrentPrintable() const { return _currentPrintable; } -////////////////////////////////////////////////////////////////////////// -enum VKeyCodes { - kVkBack = 8, //printable - kVkTab = 9, //printable - kVkClear = 12, - kVkReturn = 13, //printable - kVkPause = 19, - kVkCapital = 20, - kVkEscape = 27, //printable - kVkSpace = 32, //printable - - kVkPrior = 33, - kVkNext = 34, - kVkEnd = 35, - kVkHome = 36, - kVkLeft = 37, - kVkUp = 38, - kVkRight = 39, - kVkDown = 40, - kVkPrint = 42, - kVkInsert = 45, - kVkDelete = 46, - - kVkA = 65, //printable - kVkB = 66, //printable - kVkC = 67, //printable - kVkD = 68, //printable - kVkE = 69, //printable - kVkF = 70, //printable - kVkG = 71, //printable - kVkH = 72, //printable - kVkI = 73, //printable - kVkJ = 74, //printable - kVkK = 75, //printable - kVkL = 76, //printable - kVkM = 77, //printable - kVkN = 78, //printable - kVkO = 79, //printable - kVkP = 80, //printable - kVkQ = 81, //printable - kVkR = 82, //printable - kVkS = 83, //printable - kVkT = 84, //printable - kVkU = 85, //printable - kVkV = 86, //printable - kVkW = 87, //printable - kVkX = 88, //printable - kVkY = 89, //printable - kVkZ = 90, //printable - - kVkNumpad0 = 96, //printable - kVkNumpad1 = 97, //printable - kVkNumpad2 = 98, //printable - kVkNumpad3 = 99, //printable - kVkNumpad4 = 100, //printable - kVkNumpad5 = 101, //printable - kVkNumpad6 = 102, //printable - kVkNumpad7 = 103, //printable - kVkNumpad8 = 104, //printable - kVkNumpad9 = 105, //printable - kVkMultiply = 106, //printable - kVkAdd = 107, //printable - kVkSeparator = 108, //printable - kVkSubtract = 109, //printable - kVkDecimal = 110, //printable - kVkDivide = 111, //printable - - kVkF1 = 112, - kVkF2 = 113, - kVkF3 = 114, - kVkF4 = 115, - kVkF5 = 116, - kVkF6 = 117, - kVkF7 = 118, - kVkF8 = 119, - kVkF9 = 120, - kVkF10 = 121, - kVkF11 = 122, - kVkF12 = 123, - - kVkNumLock = 144, - kVkScroll = 145 - - //TODO: shift, ctrl, menu, etc... -}; - -////////////////////////////////////////////////////////////////////////// -uint32 BaseKeyboardState::keyCodeToVKey(Common::Event *event) { - switch (event->kbd.keycode) { - case Common::KEYCODE_BACKSPACE: - return kVkBack; - case Common::KEYCODE_TAB: - return kVkTab; - case Common::KEYCODE_CLEAR: - case Common::KEYCODE_KP5: - return kVkClear; - case Common::KEYCODE_RETURN: - case Common::KEYCODE_KP_ENTER: - return kVkReturn; - case Common::KEYCODE_PAUSE: - return kVkPause; - case Common::KEYCODE_CAPSLOCK: - return kVkCapital; - case Common::KEYCODE_ESCAPE: - return kVkEscape; - case Common::KEYCODE_KP9: - case Common::KEYCODE_PAGEUP: - return kVkPrior; - case Common::KEYCODE_KP3: - case Common::KEYCODE_PAGEDOWN: - return kVkNext; - case Common::KEYCODE_END: - case Common::KEYCODE_KP1: - return kVkEnd; - case Common::KEYCODE_HOME: - case Common::KEYCODE_KP7: - return kVkHome; - case Common::KEYCODE_LEFT: - case Common::KEYCODE_KP4: - return kVkLeft; - case Common::KEYCODE_RIGHT: - case Common::KEYCODE_KP6: - return kVkRight; - case Common::KEYCODE_UP: - case Common::KEYCODE_KP8: - return kVkUp; - case Common::KEYCODE_DOWN: - case Common::KEYCODE_KP2: - return kVkDown; - case Common::KEYCODE_PRINT: - return kVkPrint; - case Common::KEYCODE_INSERT: - case Common::KEYCODE_KP0: - return kVkInsert; - case Common::KEYCODE_DELETE: - case Common::KEYCODE_KP_PERIOD: - return kVkDelete; - case Common::KEYCODE_F1: - return kVkF1; - case Common::KEYCODE_F2: - return kVkF2; - case Common::KEYCODE_F3: - return kVkF3; - case Common::KEYCODE_F4: - return kVkF4; - case Common::KEYCODE_F5: - return kVkF5; - case Common::KEYCODE_F6: - return kVkF6; - case Common::KEYCODE_F7: - return kVkF7; - case Common::KEYCODE_F8: - return kVkF8; - case Common::KEYCODE_F9: - return kVkF9; - case Common::KEYCODE_F10: - return kVkF10; - case Common::KEYCODE_F11: - return kVkF11; - case Common::KEYCODE_F12: - return kVkF12; - case Common::KEYCODE_NUMLOCK: - return kVkNumLock; - case Common::KEYCODE_SCROLLOCK: - return kVkScroll; - default: - // check if any non-sticky keys were used, otherwise key is unknown to us - if ((event->kbd.flags & Common::KBD_NON_STICKY) == 0) { - warning("Key pressed is not recognized, ASCII returned (%d '%c').", event->kbd.keycode, event->kbd.keycode); - } - // return ASCII if no match, since it could be used for typing - return event->kbd.ascii; - break; - } - -} - -////////////////////////////////////////////////////////////////////////// -Common::KeyCode BaseKeyboardState::vKeyToKeyCode(uint32 vkey) { - switch (vkey) { - case kVkBack: - return Common::KEYCODE_BACKSPACE; - case kVkTab: - return Common::KEYCODE_TAB; - case kVkClear: - return Common::KEYCODE_CLEAR; - case kVkReturn: - return Common::KEYCODE_RETURN; - case kVkPause: - return Common::KEYCODE_PAUSE; - case kVkCapital: - return Common::KEYCODE_CAPSLOCK; - case kVkEscape: - return Common::KEYCODE_ESCAPE; - case kVkSpace: - return Common::KEYCODE_SPACE; - case kVkPrior: - return Common::KEYCODE_PAGEUP; - case kVkNext: - return Common::KEYCODE_PAGEDOWN; - case kVkHome: - return Common::KEYCODE_HOME; - case kVkEnd: - return Common::KEYCODE_END; - case kVkLeft: - return Common::KEYCODE_LEFT; - case kVkRight: - return Common::KEYCODE_RIGHT; - case kVkUp: - return Common::KEYCODE_UP; - case kVkDown: - return Common::KEYCODE_DOWN; - case kVkPrint: - return Common::KEYCODE_PRINT; - case kVkInsert: - return Common::KEYCODE_INSERT; - case kVkDelete: - return Common::KEYCODE_DELETE; - case kVkA: - return Common::KEYCODE_a; - case kVkB: - return Common::KEYCODE_b; - case kVkC: - return Common::KEYCODE_c; - case kVkD: - return Common::KEYCODE_d; - case kVkE: - return Common::KEYCODE_e; - case kVkF: - return Common::KEYCODE_f; - case kVkG: - return Common::KEYCODE_g; - case kVkH: - return Common::KEYCODE_h; - case kVkI: - return Common::KEYCODE_i; - case kVkJ: - return Common::KEYCODE_j; - case kVkK: - return Common::KEYCODE_k; - case kVkL: - return Common::KEYCODE_l; - case kVkM: - return Common::KEYCODE_m; - case kVkN: - return Common::KEYCODE_n; - case kVkO: - return Common::KEYCODE_o; - case kVkP: - return Common::KEYCODE_p; - case kVkQ: - return Common::KEYCODE_q; - case kVkR: - return Common::KEYCODE_r; - case kVkS: - return Common::KEYCODE_s; - case kVkT: - return Common::KEYCODE_t; - case kVkU: - return Common::KEYCODE_u; - case kVkV: - return Common::KEYCODE_v; - case kVkW: - return Common::KEYCODE_w; - case kVkX: - return Common::KEYCODE_x; - case kVkY: - return Common::KEYCODE_y; - case kVkZ: - return Common::KEYCODE_z; - case kVkNumpad0: - return Common::KEYCODE_KP0; - case kVkNumpad1: - return Common::KEYCODE_KP1; - case kVkNumpad2: - return Common::KEYCODE_KP2; - case kVkNumpad3: - return Common::KEYCODE_KP3; - case kVkNumpad4: - return Common::KEYCODE_KP4; - case kVkNumpad5: - return Common::KEYCODE_KP5; - case kVkNumpad6: - return Common::KEYCODE_KP6; - case kVkNumpad7: - return Common::KEYCODE_KP7; - case kVkNumpad8: - return Common::KEYCODE_KP8; - case kVkNumpad9: - return Common::KEYCODE_KP9; - case kVkMultiply: - return Common::KEYCODE_KP_MULTIPLY; - case kVkAdd: - return Common::KEYCODE_KP_PLUS; - case kVkSeparator: - return Common::KEYCODE_KP_EQUALS; - case kVkSubtract: - return Common::KEYCODE_KP_MINUS; - case kVkDecimal: - return Common::KEYCODE_KP_PERIOD; - case kVkDivide: - return Common::KEYCODE_KP_DIVIDE; - case kVkF1: - return Common::KEYCODE_F1; - case kVkF2: - return Common::KEYCODE_F2; - case kVkF3: - return Common::KEYCODE_F3; - case kVkF4: - return Common::KEYCODE_F4; - case kVkF5: - return Common::KEYCODE_F5; - case kVkF6: - return Common::KEYCODE_F6; - case kVkF7: - return Common::KEYCODE_F7; - case kVkF8: - return Common::KEYCODE_F8; - case kVkF9: - return Common::KEYCODE_F9; - case kVkF10: - return Common::KEYCODE_F10; - case kVkF11: - return Common::KEYCODE_F11; - case kVkF12: - return Common::KEYCODE_F12; - case kVkNumLock: - return Common::KEYCODE_NUMLOCK; - case kVkScroll: - return Common::KEYCODE_SCROLLOCK; - default: - warning("Unknown VKEY: %d", vkey); - return (Common::KeyCode)(vkey < KEYSTATES_ARRAY_SIZE ? vkey : 0); - break; - } - -} - } // End of namespace Wintermute diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h index 32680b34c1..b2f7f781ea 100644 --- a/engines/wintermute/base/base_keyboard_state.h +++ b/engines/wintermute/base/base_keyboard_state.h @@ -37,6 +37,11 @@ namespace Wintermute { +struct keyCodeMapping { + Common::KeyCode commonKeycode; + uint32 engineKeycode; +}; + class BaseKeyboardState : public BaseScriptable { public: DECLARE_PERSISTENT(BaseKeyboardState, BaseScriptable) @@ -58,6 +63,8 @@ public: virtual const char *scToString(); private: + void init(); + bool _currentPrintable; uint32 _currentKeyData; uint32 _currentCharCode; @@ -67,8 +74,9 @@ private: bool _currentControl; uint8 *_keyStates; - uint32 keyCodeToVKey(Common::Event *event); //TODO, add more mappings - Common::KeyCode vKeyToKeyCode(uint32 vkey); //TODO, reimplement using ScummVM-backend + + const keyCodeMapping *_mapping; + uint32 _mappingSize; }; } // End of namespace Wintermute diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h index 760b45c907..e8ca663cb7 100644 --- a/engines/wintermute/base/base_persistence_manager.h +++ b/engines/wintermute/base/base_persistence_manager.h @@ -69,6 +69,7 @@ public: uint32 _offset; bool getIsSaving() { return _saving; } + TimeDate getSavedTimestamp() { return _savedTimestamp; } uint32 _richBufferSize; byte *_richBuffer; diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp index e8e62fb6bc..039e481fe3 100644 --- a/engines/wintermute/base/base_sub_frame.cpp +++ b/engines/wintermute/base/base_sub_frame.cpp @@ -119,7 +119,7 @@ bool BaseSubFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { Rect32 rect; int r = 255, g = 255, b = 255; int ar = 255, ag = 255, ab = 255, alpha = 255; - bool custoTrans = false; + bool customTrans = false; rect.setEmpty(); char *surfaceFile = nullptr; @@ -134,7 +134,7 @@ bool BaseSubFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { case TOKEN_TRANSPARENT: parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - custoTrans = true; + customTrans = true; break; case TOKEN_RECT: @@ -191,7 +191,7 @@ bool BaseSubFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { } if (surfaceFile != nullptr) { - if (custoTrans) { + if (customTrans) { setSurface(surfaceFile, false, r, g, b, lifeTime, keepLoaded); } else { setSurface(surfaceFile, true, 0, 0, 0, lifeTime, keepLoaded); @@ -199,7 +199,7 @@ bool BaseSubFrame::loadBuffer(char *buffer, int lifeTime, bool keepLoaded) { } _alpha = BYTETORGBA(ar, ag, ab, alpha); - if (custoTrans) { + if (customTrans) { _transparent = BYTETORGBA(r, g, b, 0xFF); } @@ -434,6 +434,57 @@ bool BaseSubFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisS return STATUS_OK; } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GetHeight + // Used to find sprite center at methods.script in fix_offset() + // Return value is integer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHeight") == 0) { + stack->correctParams(0); + if (_surface) { + stack->pushInt(_surface->getHeight()); + } else { + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GetWidth + // Used to find sprite center at methods.script in fix_offset() + // Return value is integer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetWidth") == 0) { + stack->correctParams(0); + if (_surface) { + stack->pushInt(_surface->getWidth()); + } else { + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] GetPixelAt + // Used for dynamic light at mixing.script in make_RGB() and make_HSV() + // Return value is passed to Game.GetRValue(), Game.GetGValue(), etc... + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetPixelAt") == 0) { + stack->correctParams(2); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + byte r, g, b, a; + if (_surface && _surface->getPixel(x, y, &r, &g, &b, &a)) { + uint32 pixel = BYTETORGBA(r, g, b, a); + stack->pushInt(pixel); + } else { + stack->pushNULL(); + } + return STATUS_OK; + } +#endif + ////////////////////////////////////////////////////////////////////////// // SetImage ////////////////////////////////////////////////////////////////////////// diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp index 2ed27e2c32..3d67d02774 100644 --- a/engines/wintermute/base/file/base_package.cpp +++ b/engines/wintermute/base/file/base_package.cpp @@ -142,6 +142,8 @@ PackageSet::PackageSet(Common::FSNode file, const Common::String &filename, bool debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, " Warning: package file '%s' is outdated.", filename.c_str()); } _priority = hdr._priority; + _version = hdr._gameVersion; + // new in v2 if (hdr._packageVersion == PACKAGE_VERSION) { uint32 dirOffset; diff --git a/engines/wintermute/base/file/base_package.h b/engines/wintermute/base/file/base_package.h index 35976eb47b..578dc789fa 100644 --- a/engines/wintermute/base/file/base_package.h +++ b/engines/wintermute/base/file/base_package.h @@ -78,8 +78,11 @@ public: virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; int getPriority() const { return _priority; } + uint32 getVersion() const { return _version; } + private: byte _priority; + uint32 _version; Common::Array<BasePackage *> _packages; Common::HashMap<Common::String, Common::ArchiveMemberPtr> _files; Common::HashMap<Common::String, Common::ArchiveMemberPtr>::iterator _filesIter; diff --git a/engines/wintermute/base/font/base_font_bitmap.cpp b/engines/wintermute/base/font/base_font_bitmap.cpp index c33b48d085..0c3c0ae97d 100644 --- a/engines/wintermute/base/font/base_font_bitmap.cpp +++ b/engines/wintermute/base/font/base_font_bitmap.cpp @@ -28,6 +28,7 @@ #include "engines/wintermute/base/font/base_font_bitmap.h" #include "engines/wintermute/utils/string_util.h" +#include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/base/base_parser.h" #include "engines/wintermute/base/base_frame.h" #include "engines/wintermute/base/gfx/base_surface.h" @@ -141,6 +142,9 @@ int BaseFontBitmap::textHeightDraw(const byte *text, int x, int y, int width, TT bool done = false; bool newLine = false; bool longLine = false; +#ifdef ENABLE_FOXTAIL + bool minimizeSpacing = BaseEngine::instance().isFoxTail(); +#endif if (draw) { _gameRef->_renderer->startSpriteBatch(); @@ -211,6 +215,11 @@ int BaseFontBitmap::textHeightDraw(const byte *text, int x, int y, int width, TT startX += getCharWidth(str[i]); } y += _tileHeight; +#ifdef ENABLE_FOXTAIL + if (minimizeSpacing) { + y -= 3; + } +#endif last_end = end; if (longLine) { end--; @@ -264,7 +273,7 @@ void BaseFontBitmap::drawChar(byte c, int x, int y) { } } if (!handled && _subframe) { - _subframe->_surface->displayTrans(x, y, rect); + _subframe->_surface->displayTrans(x, y, rect, _subframe->_alpha); } } @@ -308,6 +317,9 @@ TOKEN_DEF(EDITOR_PROPERTY) TOKEN_DEF(SPRITE) TOKEN_DEF(WIDTHS_FRAME) TOKEN_DEF(PAINT_WHOLE_CELL) +#ifdef ENABLE_FOXTAIL +TOKEN_DEF(COLOR) +#endif TOKEN_DEF_END ////////////////////////////////////////////////////////////////////// bool BaseFontBitmap::loadBuffer(char *buffer) { @@ -328,6 +340,9 @@ bool BaseFontBitmap::loadBuffer(char *buffer) { TOKEN_TABLE(SPRITE) TOKEN_TABLE(WIDTHS_FRAME) TOKEN_TABLE(PAINT_WHOLE_CELL) +#ifdef ENABLE_FOXTAIL + TOKEN_TABLE(COLOR) +#endif TOKEN_TABLE_END char *params; @@ -345,7 +360,11 @@ bool BaseFontBitmap::loadBuffer(char *buffer) { int lastWidth = 0; int i; int r = 255, g = 255, b = 255; - bool custoTrans = false; + bool customTrans = false; +#ifdef ENABLE_FOXTAIL + int ar = 255, ag = 255, ab = 255; + bool customAlpha = false; +#endif char *surfaceFile = nullptr; char *spriteFile = nullptr; @@ -366,8 +385,15 @@ bool BaseFontBitmap::loadBuffer(char *buffer) { case TOKEN_TRANSPARENT: parser.scanStr(params, "%d,%d,%d", &r, &g, &b); - custoTrans = true; + customTrans = true; + break; + +#ifdef ENABLE_FOXTAIL + case TOKEN_COLOR: + parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab); + customAlpha = true; break; +#endif case TOKEN_WIDTHS: parser.scanStr(params, "%D", widths, &num); @@ -441,11 +467,16 @@ bool BaseFontBitmap::loadBuffer(char *buffer) { if (surfaceFile != nullptr && !_sprite) { _subframe = new BaseSubFrame(_gameRef); - if (custoTrans) { + if (customTrans) { _subframe->setSurface(surfaceFile, false, r, g, b); } else { _subframe->setSurface(surfaceFile); } +#ifdef ENABLE_FOXTAIL + if (customAlpha) { + _subframe->_alpha = BYTETORGBA(ar, ag, ab, 255); + } +#endif } @@ -489,6 +520,14 @@ bool BaseFontBitmap::loadBuffer(char *buffer) { } } +#ifdef ENABLE_FOXTAIL + if (BaseEngine::instance().isFoxTail()) { + for (i = lastWidth; i < NUM_CHARACTERS; i++) { + _widths[i]--; + } + } +#endif + return STATUS_OK; } diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp index 0f33fc2c43..b60a4d4b38 100644 --- a/engines/wintermute/base/gfx/base_renderer.cpp +++ b/engines/wintermute/base/gfx/base_renderer.cpp @@ -32,6 +32,7 @@ #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/base_sub_frame.h" #include "engines/wintermute/base/base_region.h" +#include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/platform_osystem.h" #include "engines/wintermute/base/base_persistence_manager.h" @@ -372,6 +373,26 @@ bool BaseRenderer::displayIndicator() { if (!_indicatorDisplay || !_indicatorProgress) { return STATUS_OK; } + +#ifdef ENABLE_FOXTAIL + if (BaseEngine::instance().isFoxTail()) { + _hasDrawnSaveLoadImage = false; + fill(0, 0, 0); + displaySaveloadLines(); + displaySaveloadImage(); + forcedFlip(); + return STATUS_OK; + } +#endif + + displaySaveloadImage(); + displaySaveloadLines(); + indicatorFlip(); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::displaySaveloadImage() { if (_saveLoadImage && !_hasDrawnSaveLoadImage) { Rect32 rc; rc.setRect(0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight()); @@ -384,6 +405,11 @@ bool BaseRenderer::displayIndicator() { _hasDrawnSaveLoadImage = true; } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool BaseRenderer::displaySaveloadLines() { if ((!_indicatorDisplay && _indicatorWidth <= 0) || _indicatorHeight <= 0) { return STATUS_OK; } @@ -395,9 +421,6 @@ bool BaseRenderer::displayIndicator() { setup2D(); _indicatorWidthDrawn = curWidth; - if (_indicatorWidthDrawn) { - indicatorFlip(); - } return STATUS_OK; } diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h index 6b1a4f97f4..981171b78b 100644 --- a/engines/wintermute/base/gfx/base_renderer.h +++ b/engines/wintermute/base/gfx/base_renderer.h @@ -116,6 +116,7 @@ public: * essentially, just copies the region defined by the _indicator-variables. */ virtual bool indicatorFlip() = 0; + virtual bool forcedFlip() = 0; virtual void initLoop(); virtual bool setup2D(bool force = false); virtual bool setupLines(); @@ -223,6 +224,8 @@ protected: Rect32 _monitorRect; private: Common::Array<BaseActiveRect *> _rectList; + bool displaySaveloadImage(); + bool displaySaveloadLines(); }; BaseRenderer *makeOSystemRenderer(BaseGame *inGame); // Implemented in BRenderSDL.cpp diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index 7692bc6c48..cfa43adb17 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -146,7 +146,15 @@ bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) { } bool BaseRenderOSystem::indicatorFlip() { - g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight); + if (_indicatorWidthDrawn > 0 && _indicatorHeight > 0) { + g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight); + g_system->updateScreen(); + } + return STATUS_OK; +} + +bool BaseRenderOSystem::forcedFlip() { + g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); g_system->updateScreen(); return STATUS_OK; } diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index 47099046e9..11987e55e5 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -69,6 +69,7 @@ public: bool initRenderer(int width, int height, bool windowed) override; bool flip() override; virtual bool indicatorFlip(); + virtual bool forcedFlip(); bool fill(byte r, byte g, byte b, Common::Rect *rect = nullptr) override; Graphics::PixelFormat getPixelFormat() const override; void fade(uint16 alpha) override; diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index 9fbbe1d498..950cabf28c 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -81,6 +81,17 @@ public: } return _height; } + bool getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a) override { + if (!_loaded) { + finishLoad(); + } + if (_surface) { + uint32 pixel = getPixelAt(_surface, x, y); + _surface->format.colorToARGB(pixel, *a, *r, *g, *b); + return STATUS_OK; + } + return STATUS_FAILED; + } Graphics::AlphaType getAlphaType() const { return _alphaType; } private: diff --git a/engines/wintermute/base/saveload.cpp b/engines/wintermute/base/saveload.cpp index 6299cf6e01..1549eac7a8 100644 --- a/engines/wintermute/base/saveload.cpp +++ b/engines/wintermute/base/saveload.cpp @@ -159,31 +159,35 @@ void SaveLoad::afterLoadScript(void *script, void *data) { } Common::String SaveLoad::getSaveSlotFilename(int slot) { + Common::String filename; BasePersistenceManager *pm = new BasePersistenceManager(); - Common::String filename = pm->getFilenameForSlot(slot); - delete pm; + if (pm) { + filename = pm->getFilenameForSlot(slot); + delete pm; + } debugC(kWintermuteDebugSaveGame, "getSaveSlotFileName(%d) = %s", slot, filename.c_str()); return filename; } -bool SaveLoad::getSaveSlotDescription(int slot, char *buffer) { - buffer[0] = '\0'; - +Common::String SaveLoad::getSaveSlotDescription(int slot) { + Common::String description; Common::String filename = getSaveSlotFilename(slot); BasePersistenceManager *pm = new BasePersistenceManager(); - if (!pm) { - return false; + if ((pm->initLoad(filename))) { + description = pm->_savedDescription; } + delete pm; + return description; +} - if (!(pm->initLoad(filename))) { - delete pm; - return false; +void SaveLoad::getSaveSlotTimestamp(int slot, TimeDate *time) { + memset(time, 0, sizeof(TimeDate)); + Common::String filename = getSaveSlotFilename(slot); + BasePersistenceManager *pm = new BasePersistenceManager(); + if ((pm->initLoad(filename))) { + *time = pm->getSavedTimestamp(); } - - strcpy(buffer, pm->_savedDescription); delete pm; - - return true; } bool SaveLoad::isSaveSlotUsed(int slot) { diff --git a/engines/wintermute/base/saveload.h b/engines/wintermute/base/saveload.h index 31f5841f41..295d19d543 100644 --- a/engines/wintermute/base/saveload.h +++ b/engines/wintermute/base/saveload.h @@ -37,7 +37,8 @@ class SaveLoad { public: static bool emptySaveSlot(int slot); static bool isSaveSlotUsed(int slot); - static bool getSaveSlotDescription(int slot, char *buffer); + static Common::String getSaveSlotDescription(int slot); + static void getSaveSlotTimestamp(int slot, TimeDate *time); static Common::String getSaveSlotFilename(int slot); static bool loadGame(const Common::String &filename, BaseGame *gameRef); diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp index c13310255d..856584fe72 100644 --- a/engines/wintermute/base/scriptables/script.cpp +++ b/engines/wintermute/base/scriptables/script.cpp @@ -29,6 +29,7 @@ #include "engines/wintermute/base/scriptables/script_value.h" #include "engines/wintermute/base/scriptables/script.h" #include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_engine.h" #include "engines/wintermute/base/scriptables/script_engine.h" #include "engines/wintermute/base/scriptables/script_stack.h" #include "common/memstream.h" @@ -618,8 +619,14 @@ bool ScScript::executeInstruction() { _state = SCRIPT_WAITING_SCRIPT; _waitScript->copyParameters(_stack); } +#ifdef ENABLE_FOXTAIL + } else if (BaseEngine::instance().isFoxTail() && strcmp(methodName, "LoadItems") == 0 && strcmp(_threadEvent,"AfterLoad") == 0) { + _stack->correctParams(0); + _gameRef->LOG(0, "Method '%s' is called in unbreakable mode of '%s' event and was ignored", methodName, _threadEvent); + _stack->pushNULL(); +#endif } else { - // can call methods in unbreakable mode + // cannot call methods in unbreakable mode _stack->correctParams(0); runtimeError("Cannot call method '%s'. Ignored.", methodName); _stack->pushNULL(); diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp index 7431029cbf..05effd991e 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.cpp +++ b/engines/wintermute/base/scriptables/script_ext_array.cpp @@ -118,8 +118,7 @@ bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, ////////////////////////////////////////////////////////////////////////// // Pop ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Pop") == 0) { - + else if (strcmp(name, "Pop") == 0) { stack->correctParams(0); if (_length > 0) { @@ -133,7 +132,36 @@ bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, } return STATUS_OK; - } else { + } + +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] Delete + // Removes item from array by index, shifting other elements + // Used to shuffle arrays and delete found items in various scripts + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Delete") == 0) { + stack->correctParams(1); + + int shiftPoint = stack->pop()->getInt(0); + char paramNameFrom[20]; + char paramNameTo[20]; + + for (int i = shiftPoint; i < _length - 1 ; i++) { + sprintf(paramNameFrom, "%d", i + 1); + sprintf(paramNameTo, "%d", i); + _values->setProp(paramNameTo, _values->getProp(paramNameFrom), false); + } + _values->deleteProp(paramNameFrom); + _length--; + stack->pushNULL(); + + return STATUS_OK; + } +#endif + + else { return STATUS_FAILED; } } diff --git a/engines/wintermute/configure.engine b/engines/wintermute/configure.engine index 68049684a3..c825845f50 100644 --- a/engines/wintermute/configure.engine +++ b/engines/wintermute/configure.engine @@ -1,3 +1,4 @@ # This file is included from the main "configure" script # add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] -add_engine wintermute "Wintermute" yes "" "" "zlib 16bit highres jpeg png" +add_engine wintermute "Wintermute" yes "foxtail" "" "zlib 16bit highres jpeg png" +add_engine foxtail "FoxTail" yes diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h index 36280574ef..f9d8df081c 100644 --- a/engines/wintermute/detection_tables.h +++ b/engines/wintermute/detection_tables.h @@ -74,6 +74,7 @@ static const PlainGameDescriptor wintermuteGames[] = { {"goldencalf", "The Golden Calf"}, {"hamlet", "Hamlet or the last game without MMORPG features, shaders and product placement"}, {"helga", "Helga Deep In Trouble"}, + {"hor", "Hor"}, {"jamesperis", "James Peris: No License Nor Control"}, {"knossos", "K'NOSSOS"}, {"kulivocko", "Kulivocko"}, @@ -734,61 +735,242 @@ static const WMEGameDescription gameDescriptions[] = { WME_WINENTRY("four", "", WME_ENTRY1s("data.dcp", "ec05cd5e37c9a524053b8859635a4234", 62599855), Common::EN_ANY, ADGF_UNSTABLE, WME_1_9_1), - // FoxTail (Steam, Feb 26th 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "651ae5b062073021edaca7e1de131eec", 59357572), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1291 (English) + WME_WINENTRY("foxtail", "1.2.230.1291", + WME_ENTRY1s("data.dcp", "651ae5b062073021edaca7e1de131eec", 59357572), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 1th 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "03ed77b1ac8b94bbd0247324a41621ad", 59357623), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1291 (German) + WME_WINENTRY("foxtail", "1.2.230.1291", + WME_ENTRY1s("data.dcp", "651ae5b062073021edaca7e1de131eec", 59357572), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 2th A 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "d7287c49210c7c9f9376327c6e224c7b", 59383312), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1291 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1291", + WME_ENTRY1s("data.dcp", "651ae5b062073021edaca7e1de131eec", 59357572), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 2th B 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "434c4f598582a569972acd4d700a44e5", 59383416), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1291 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1291", + WME_ENTRY1s("data.dcp", "651ae5b062073021edaca7e1de131eec", 59357572), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 3th A 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "5aa16c180998f1816a734c58a01ab8b1", 59383306), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1303 (English) + WME_WINENTRY("foxtail", "1.2.230.1303", + WME_ENTRY1s("data.dcp", "03ed77b1ac8b94bbd0247324a41621ad", 59357623), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 3th B 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "363856606d19fb7e0e3a0a67737697fa", 59382887), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1303 (German) + WME_WINENTRY("foxtail", "1.2.230.1303", + WME_ENTRY1s("data.dcp", "03ed77b1ac8b94bbd0247324a41621ad", 59357623), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 3th C 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "bbab16777c4bc979c5f773e12b804a63", 59151985), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1303 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1303", + WME_ENTRY1s("data.dcp", "03ed77b1ac8b94bbd0247324a41621ad", 59357623), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 3th D 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "22e5f634742956b6f4087459a9c8acf4", 59151985), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1303 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1303", + WME_ENTRY1s("data.dcp", "03ed77b1ac8b94bbd0247324a41621ad", 59357623), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 20th 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "32fd78f0b1509863f2e91bc7afc633ff", 59630008), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1313 (English) + WME_WINENTRY("foxtail", "1.2.230.1313", + WME_ENTRY1s("data.dcp", "d7287c49210c7c9f9376327c6e224c7b", 59383312), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, May 30th 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "ca1b0379c8f0dffd3bf8b95e91379b2c", 70132635), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1313 (German) + WME_WINENTRY("foxtail", "1.2.230.1313", + WME_ENTRY1s("data.dcp", "d7287c49210c7c9f9376327c6e224c7b", 59383312), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, May 31th 2018, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "2c4c744ff103f4fc6e770515e2da8b16", 70124937), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1313 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1313", + WME_ENTRY1s("data.dcp", "d7287c49210c7c9f9376327c6e224c7b", 59383312), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Jan 17th 2019, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "e0177c5752d067a3e473b86ad40d57c3", 109502449), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1313 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1313", + WME_ENTRY1s("data.dcp", "d7287c49210c7c9f9376327c6e224c7b", 59383312), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Feb 22th 2019, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "a940ffa1b4347588d13e4a9756bb0bbd", 109503345), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1315 (English) + WME_WINENTRY("foxtail", "1.2.230.1315", + WME_ENTRY1s("data.dcp", "434c4f598582a569972acd4d700a44e5", 59383416), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), - // FoxTail (Steam, Mar 22th 2019, Windows/Linux/Mac) - WME_WINENTRY("foxtail", "", - WME_ENTRY1s("data.dcp", "e5d06fa058cd9d6f20d6206356e5854d", 109503303), Common::EN_ANY, ADGF_UNSTABLE, WME_LITE), + // FoxTail 1.2.230.1315 (German) + WME_WINENTRY("foxtail", "1.2.230.1315", + WME_ENTRY1s("data.dcp", "434c4f598582a569972acd4d700a44e5", 59383416), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1315 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1315", + WME_ENTRY1s("data.dcp", "434c4f598582a569972acd4d700a44e5", 59383416), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1315 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1315", + WME_ENTRY1s("data.dcp", "434c4f598582a569972acd4d700a44e5", 59383416), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1316 (English) + WME_WINENTRY("foxtail", "1.2.230.1316", + WME_ENTRY1s("data.dcp", "5aa16c180998f1816a734c58a01ab8b1", 59383306), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1316 (German) + WME_WINENTRY("foxtail", "1.2.230.1316", + WME_ENTRY1s("data.dcp", "5aa16c180998f1816a734c58a01ab8b1", 59383306), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1316 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1316", + WME_ENTRY1s("data.dcp", "5aa16c180998f1816a734c58a01ab8b1", 59383306), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1316 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1316", + WME_ENTRY1s("data.dcp", "5aa16c180998f1816a734c58a01ab8b1", 59383306), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1318 (English) + WME_WINENTRY("foxtail", "1.2.230.1318", + WME_ENTRY1s("data.dcp", "363856606d19fb7e0e3a0a67737697fa", 59382887), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1318 (German) + WME_WINENTRY("foxtail", "1.2.230.1318", + WME_ENTRY1s("data.dcp", "363856606d19fb7e0e3a0a67737697fa", 59382887), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1318 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1318", + WME_ENTRY1s("data.dcp", "363856606d19fb7e0e3a0a67737697fa", 59382887), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1318 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1318", + WME_ENTRY1s("data.dcp", "363856606d19fb7e0e3a0a67737697fa", 59382887), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1321 (English) + WME_WINENTRY("foxtail", "1.2.230.1321", + WME_ENTRY1s("data.dcp", "bbab16777c4bc979c5f773e12b804a63", 59151985), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1321 (German) + WME_WINENTRY("foxtail", "1.2.230.1321", + WME_ENTRY1s("data.dcp", "bbab16777c4bc979c5f773e12b804a63", 59151985), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1321 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1321", + WME_ENTRY1s("data.dcp", "bbab16777c4bc979c5f773e12b804a63", 59151985), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1321 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1321", + WME_ENTRY1s("data.dcp", "bbab16777c4bc979c5f773e12b804a63", 59151985), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1322 (English) + // not a mistake, data.dcp for 1.2.230.1321 and 1.2.230.1322 have same byte size + WME_WINENTRY("foxtail", "1.2.230.1322", + WME_ENTRY1s("data.dcp", "22e5f634742956b6f4087459a9c8acf4", 59151985), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1322 (German) + WME_WINENTRY("foxtail", "1.2.230.1322", + WME_ENTRY1s("data.dcp", "22e5f634742956b6f4087459a9c8acf4", 59151985), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1322 (Russian) + WME_WINENTRY("foxtail", "1.2.230.1322", + WME_ENTRY1s("data.dcp", "22e5f634742956b6f4087459a9c8acf4", 59151985), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.230.1322 (Ukranian) + WME_WINENTRY("foxtail", "1.2.230.1322", + WME_ENTRY1s("data.dcp", "22e5f634742956b6f4087459a9c8acf4", 59151985), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_230), + + // FoxTail 1.2.304.1571 (English) + WME_WINENTRY("foxtail", "1.2.304.1571", + WME_ENTRY1s("data.dcp", "32fd78f0b1509863f2e91bc7afc633ff", 59630008), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_304), + + // FoxTail 1.2.304.1571 (German) + WME_WINENTRY("foxtail", "1.2.304.1571", + WME_ENTRY1s("data.dcp", "32fd78f0b1509863f2e91bc7afc633ff", 59630008), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_304), + + // FoxTail 1.2.304.1571 (Russian) + WME_WINENTRY("foxtail", "1.2.304.1571", + WME_ENTRY1s("data.dcp", "32fd78f0b1509863f2e91bc7afc633ff", 59630008), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_304), + + // FoxTail 1.2.304.1571 (Ukranian) + WME_WINENTRY("foxtail", "1.2.304.1571", + WME_ENTRY1s("data.dcp", "32fd78f0b1509863f2e91bc7afc633ff", 59630008), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_304), + + // FoxTail 1.2.362.2039 (English) + WME_WINENTRY("foxtail", "1.2.362.2039", + WME_ENTRY1s("data.dcp", "ca1b0379c8f0dffd3bf8b95e91379b2c", 70132635), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.362.2039 (German) + WME_WINENTRY("foxtail", "1.2.362.2039", + WME_ENTRY1s("data.dcp", "ca1b0379c8f0dffd3bf8b95e91379b2c", 70132635), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.362.2039 (Russian) + WME_WINENTRY("foxtail", "1.2.362.2039", + WME_ENTRY1s("data.dcp", "ca1b0379c8f0dffd3bf8b95e91379b2c", 70132635), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.362.2039 (Ukranian) + WME_WINENTRY("foxtail", "1.2.362.2039", + WME_ENTRY1s("data.dcp", "ca1b0379c8f0dffd3bf8b95e91379b2c", 70132635), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.362.2047 (English) + WME_WINENTRY("foxtail", "1.2.362.2047", + WME_ENTRY1s("data.dcp", "2c4c744ff103f4fc6e770515e2da8b16", 70124937), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.362.2047 (German) + WME_WINENTRY("foxtail", "1.2.362.2047", + WME_ENTRY1s("data.dcp", "2c4c744ff103f4fc6e770515e2da8b16", 70124937), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.362.2047 (Russian) + WME_WINENTRY("foxtail", "1.2.362.2047", + WME_ENTRY1s("data.dcp", "2c4c744ff103f4fc6e770515e2da8b16", 70124937), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.362.2047 (Ukranian) + WME_WINENTRY("foxtail", "1.2.362.2047", + WME_ENTRY1s("data.dcp", "2c4c744ff103f4fc6e770515e2da8b16", 70124937), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_362), + + // FoxTail 1.2.527.3377 (English) + WME_WINENTRY("foxtail", "1.2.527.3377", + WME_ENTRY1s("data.dcp", "e0177c5752d067a3e473b86ad40d57c3", 109502449), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3377 (German) + WME_WINENTRY("foxtail", "1.2.527.3377", + WME_ENTRY1s("data.dcp", "e0177c5752d067a3e473b86ad40d57c3", 109502449), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3377 (Polish) + WME_WINENTRY("foxtail", "1.2.527.3377", + WME_ENTRY1s("data.dcp", "e0177c5752d067a3e473b86ad40d57c3", 109502449), Common::PL_POL, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3377 (Russian) + WME_WINENTRY("foxtail", "1.2.527.3377", + WME_ENTRY1s("data.dcp", "e0177c5752d067a3e473b86ad40d57c3", 109502449), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3377 (Ukranian) + WME_WINENTRY("foxtail", "1.2.527.3377", + WME_ENTRY1s("data.dcp", "e0177c5752d067a3e473b86ad40d57c3", 109502449), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3389 (English) + WME_WINENTRY("foxtail", "1.2.527.3389", + WME_ENTRY1s("data.dcp", "a940ffa1b4347588d13e4a9756bb0bbd", 109503345), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3389 (German) + WME_WINENTRY("foxtail", "1.2.527.3389", + WME_ENTRY1s("data.dcp", "a940ffa1b4347588d13e4a9756bb0bbd", 109503345), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3389 (Polish) + WME_WINENTRY("foxtail", "1.2.527.3389", + WME_ENTRY1s("data.dcp", "a940ffa1b4347588d13e4a9756bb0bbd", 109503345), Common::PL_POL, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3389 (Russian) + WME_WINENTRY("foxtail", "1.2.527.3389", + WME_ENTRY1s("data.dcp", "a940ffa1b4347588d13e4a9756bb0bbd", 109503345), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3389 (Ukranian) + WME_WINENTRY("foxtail", "1.2.527.3389", + WME_ENTRY1s("data.dcp", "a940ffa1b4347588d13e4a9756bb0bbd", 109503345), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3391 (English) + WME_WINENTRY("foxtail", "1.2.527.3391", + WME_ENTRY1s("data.dcp", "e5d06fa058cd9d6f20d6206356e5854d", 109503303), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3391 (German) + WME_WINENTRY("foxtail", "1.2.527.3391", + WME_ENTRY1s("data.dcp", "e5d06fa058cd9d6f20d6206356e5854d", 109503303), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3391 (Polish) + WME_WINENTRY("foxtail", "1.2.527.3391", + WME_ENTRY1s("data.dcp", "e5d06fa058cd9d6f20d6206356e5854d", 109503303), Common::PL_POL, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3391 (Russian) + WME_WINENTRY("foxtail", "1.2.527.3391", + WME_ENTRY1s("data.dcp", "e5d06fa058cd9d6f20d6206356e5854d", 109503303), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_527), + + // FoxTail 1.2.527.3391 (Ukranian) + WME_WINENTRY("foxtail", "1.2.527.3391", + WME_ENTRY1s("data.dcp", "e5d06fa058cd9d6f20d6206356e5854d", 109503303), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_527), // Framed (Beta) WME_WINENTRY("framed", "Beta", @@ -887,6 +1069,14 @@ static const WMEGameDescription gameDescriptions[] = { WME_ENTRY2s("english.dcp", "b3a93e678f0ef97200f691cd1724643f", 135864, "data.dcp", "45134ed93bc391edf148b79cdcbf2a09", 154266028), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, WME_1_9_3), + // Hor v1.0 + WME_WINENTRY("hor", "1.0", + WME_ENTRY1s("data.dcp", "ae94007f25a21143c028c1b7807dd907", 15077486), Common::UNK_LANG, ADGF_UNSTABLE, WME_1_9_3), + + // Hor v1.3 + WME_WINENTRY("hor", "1.3", + WME_ENTRY1s("data.dcp", "37b0abeb8651b82b9e6327bd10a18185", 15077486), Common::UNK_LANG, ADGF_UNSTABLE, WME_1_9_3), + // James Peris: No License Nor Control (English) WME_WINENTRY("jamesperis", "Version 1.5", WME_ENTRY1s("data.dcp", "f5635080b65aaf75c3676ce0cd46460b", 225294032), Common::EN_ANY, ADGF_UNSTABLE, WME_1_9_1), diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp index 7ee28f0fe2..dec2025346 100644 --- a/engines/wintermute/wintermute.cpp +++ b/engines/wintermute/wintermute.cpp @@ -115,6 +115,10 @@ Common::Error WintermuteEngine::run() { Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0); if (_gameDescription->adDesc.flags & GF_LOWSPEC_ASSETS) { initGraphics(320, 240, &format); +#ifdef ENABLE_FOXTAIL + } else if (BaseEngine::isFoxTailCheck(_gameDescription->targetExecutable)) { + initGraphics(640, 360, &format); +#endif } else { initGraphics(800, 600, &format); } @@ -158,6 +162,17 @@ int WintermuteEngine::init() { } #endif + // check dependencies for games with FoxTail subengine + #if not defined(ENABLE_FOXTAIL) + if (BaseEngine::isFoxTailCheck(_gameDescription->targetExecutable)) { + GUI::MessageDialog dialog(_("This game requires the FoxTail subengine, which is not compiled in.")); + dialog.runModal(); + delete _game; + _game = nullptr; + return false; + } + #endif + Common::ArchiveMemberList actors3d; if (BaseEngine::instance().getFileManager()->listMatchingMembers(actors3d, "*.act3d")) { GUI::MessageDialog dialog( |