[Scummvm-git-logs] scummvm master -> 288d8a8a745388590dcd1374e5a337d715bedc59

sev- sev at scummvm.org
Tue May 12 08:34:07 UTC 2020


This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
e561e97023 WINTERMUTE: Add Foxtail Chapter 3 engine and detection
aecb03e69c WINTERMUTE: Use different opcodes for FoxTail 1.2.896
5ad57c94dd WINTERMUTE: Add extra keymaps for FoxTail 1.2.896
1b5cbe8c20 WINTERMUTE: Add keymapper_tables.h to POTFILES
2b34a9fbca WINTERMUTE: Add some small FoxTail-specific methods
55d443d824 WINTERMUTE: Patch text line height for FoxTail 1.2.896
fae360a50f WINTERMUTE: Extend crossfade & add MusicCrossfadeVolume() for FoxTail
bae13c1414 WINTERMUTE: Fix & extend string Split() for FoxTail
288d8a8a74 WINTERMUTE: Fix & extend non-package file access, add GetFiles() for FoxTail


Commit: e561e97023e2f5bd152040197e9cfca123ee44ad
    https://github.com/scummvm/scummvm/commit/e561e97023e2f5bd152040197e9cfca123ee44ad
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Add Foxtail Chapter 3 engine and detection

Changed paths:
    engines/wintermute/base/base_engine.h
    engines/wintermute/base/base_game.cpp
    engines/wintermute/detection_tables.h


diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
index 723bb1701f..02d4c9e74c 100644
--- a/engines/wintermute/base/base_engine.h
+++ b/engines/wintermute/base/base_engine.h
@@ -115,6 +115,7 @@ enum WMETargetExecutable {
 	FOXTAIL_1_2_304,
 	FOXTAIL_1_2_362,
 	FOXTAIL_1_2_527,
+	FOXTAIL_1_2_896,
 	FOXTAIL_LATEST_VERSION
 };
 
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index 341d65a571..b566f3127c 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -2664,6 +2664,8 @@ ScValue *BaseGame::scGetProperty(const Common::String &name) {
 			_scValue->setString("1.2.362");
 		} else if (BaseEngine::instance().getTargetExecutable() == FOXTAIL_1_2_527) {
 			_scValue->setString("1.2.527");
+		} else if (BaseEngine::instance().getTargetExecutable() == FOXTAIL_1_2_896) {
+			_scValue->setString("1.2.896");
 		} else {
 			_scValue->setString("UNKNOWN");
 		}
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index b568479241..a036b75a88 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -1031,6 +1031,46 @@ static const WMEGameDescription gameDescriptions[] = {
 	WME_WINENTRY("foxtail", "1.2.527.3391",
 		WME_ENTRY1s("data.dcp", "e5d06fa058cd9d6f20d6206356e5854d", 109503303), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_527),
 
+	// FoxTail 1.2.896.4370 (English)
+	WME_WINENTRY("foxtail", "1.2.896.4370",
+		WME_ENTRY1s("data.dcp", "cee21687240aa160b8ebf1e0cccaef59", 154006218), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4370 (German)
+	WME_WINENTRY("foxtail", "1.2.896.4370",
+		WME_ENTRY1s("data.dcp", "cee21687240aa160b8ebf1e0cccaef59", 154006218), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4370 (Polish)
+	WME_WINENTRY("foxtail", "1.2.896.4370",
+		WME_ENTRY1s("data.dcp", "cee21687240aa160b8ebf1e0cccaef59", 154006218), Common::PL_POL, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4370 (Russian)
+	WME_WINENTRY("foxtail", "1.2.896.4370",
+		WME_ENTRY1s("data.dcp", "cee21687240aa160b8ebf1e0cccaef59", 154006218), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4370 (Ukranian)
+	WME_WINENTRY("foxtail", "1.2.896.4370",
+		WME_ENTRY1s("data.dcp", "cee21687240aa160b8ebf1e0cccaef59", 154006218), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4371 (English)
+	WME_WINENTRY("foxtail", "1.2.896.4371",
+		WME_ENTRY1s("data.dcp", "ca9842a6461cc7b00e63b5bc11813971", 154006242), Common::EN_ANY, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4371 (German)
+	WME_WINENTRY("foxtail", "1.2.896.4371",
+		WME_ENTRY1s("data.dcp", "ca9842a6461cc7b00e63b5bc11813971", 154006242), Common::DE_DEU, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4371 (Polish)
+	WME_WINENTRY("foxtail", "1.2.896.4371",
+		WME_ENTRY1s("data.dcp", "ca9842a6461cc7b00e63b5bc11813971", 154006242), Common::PL_POL, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4371 (Russian)
+	WME_WINENTRY("foxtail", "1.2.896.4371",
+		WME_ENTRY1s("data.dcp", "ca9842a6461cc7b00e63b5bc11813971", 154006242), Common::RU_RUS, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
+	// FoxTail 1.2.896.4371 (Ukranian)
+	WME_WINENTRY("foxtail", "1.2.896.4371",
+		WME_ENTRY1s("data.dcp", "ca9842a6461cc7b00e63b5bc11813971", 154006242), Common::UA_UKR, ADGF_UNSTABLE, FOXTAIL_1_2_896),
+
 	// Framed (Beta)
 	WME_WINENTRY("framed", "Beta",
 		WME_ENTRY1s("data.dcp", "e7259fb36f2c6f9f28242291e0c3de98", 34690568), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, WME_1_8_11),


Commit: aecb03e69c3c241351af5ec51d5057a17ac49c35
    https://github.com/scummvm/scummvm/commit/aecb03e69c3c241351af5ec51d5057a17ac49c35
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Use different opcodes for FoxTail 1.2.896

Changed paths:
    engines/wintermute/base/scriptables/script.cpp
    engines/wintermute/base/scriptables/script.h


diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp
index b2685a0280..05934db961 100644
--- a/engines/wintermute/base/scriptables/script.cpp
+++ b/engines/wintermute/base/scriptables/script.cpp
@@ -98,6 +98,10 @@ ScScript::ScScript(BaseGame *inGame, ScEngine *engine) : BaseClass(inGame) {
 	_parentScript = nullptr;
 
 	_tracingMode = false;
+
+#ifdef ENABLE_FOXTAIL
+	_needAltOpcodes = BaseEngine::instance().isFoxTail(FOXTAIL_1_2_896, FOXTAIL_LATEST_VERSION);	
+#endif
 }
 
 
@@ -512,6 +516,74 @@ char *ScScript::getString() {
 	return ret;
 }
 
+#ifdef ENABLE_FOXTAIL
+//////////////////////////////////////////////////////////////////////////
+// FoxTail 1.2.896 is using unusual opcodes table, let's map them here
+// NOTE: Those opcodes are never used at FoxTail 1.2.896.4370:
+//   II_CMP_STRICT_EQ
+//   II_CMP_STRICT_NE
+//   II_DEF_CONST_VAR
+//   II_DBG_LINE
+//   II_PUSH_VAR_THIS
+//////////////////////////////////////////////////////////////////////////
+uint32 ScScript::decodeAltOpcodes(uint32 inst) {
+	if (inst > 46) {
+		return (uint32)(-1);
+	}
+
+	uint32 foxtail_1_2_896_mapping[] = {
+		II_CMP_LE,
+		II_JMP,
+		II_POP_REG1,
+		II_PUSH_BOOL,
+		II_MODULO,
+		II_POP_EMPTY,
+		II_CALL_BY_EXP,
+		II_CMP_L,
+		II_PUSH_FLOAT,
+		II_NOT,
+		II_PUSH_THIS,
+		II_PUSH_BY_EXP,
+		II_PUSH_THIS_FROM_STACK,
+		II_CMP_G,
+		II_DEF_GLOB_VAR,
+		II_PUSH_STRING,
+		II_PUSH_REG1,
+		II_DEF_VAR,
+		/* unused */ (uint32)(-1),
+		II_RET_EVENT,
+		II_PUSH_VAR_REF,
+		II_CMP_NE,
+		/* unused */ II_DBG_LINE,
+		II_OR,
+		II_POP_VAR,
+		II_AND,
+		II_EXTERNAL_CALL,
+		II_CORRECT_STACK,
+		II_RET,
+		II_DIV,
+		II_PUSH_VAR,
+		II_SUB,
+		II_CALL,
+		II_CREATE_OBJECT,
+		II_MUL,
+		II_POP_BY_EXP,
+		/*unused */ (uint32)(-1),
+		II_PUSH_NULL,
+		II_JMP_FALSE,
+		II_ADD,
+		II_CMP_GE,
+		/* unused */ (uint32)(-1),
+		/* unused */ (uint32)(-1),
+		II_PUSH_INT,
+		II_CMP_EQ,
+		II_POP_THIS,
+		II_SCOPE
+	};
+
+	return foxtail_1_2_896_mapping[inst];
+}
+#endif
 
 //////////////////////////////////////////////////////////////////////////
 bool ScScript::executeInstruction() {
@@ -528,6 +600,12 @@ bool ScScript::executeInstruction() {
 
 	uint32 inst = getDWORD();
 
+#ifdef ENABLE_FOXTAIL
+	if (_needAltOpcodes) {
+		inst = decodeAltOpcodes(inst);
+	}
+#endif
+
 	preInstHook(inst);
 
 	switch (inst) {
@@ -1315,6 +1393,9 @@ bool ScScript::persist(BasePersistenceManager *persistMgr) {
 
 	if (!persistMgr->getIsSaving()) {
 		_tracingMode = false;
+#ifdef ENABLE_FOXTAIL
+		_needAltOpcodes = BaseEngine::instance().isFoxTail(FOXTAIL_1_2_896, FOXTAIL_LATEST_VERSION);	
+#endif
 	}
 
 	return STATUS_OK;
diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h
index 91e31340c3..52afc36a47 100644
--- a/engines/wintermute/base/scriptables/script.h
+++ b/engines/wintermute/base/scriptables/script.h
@@ -167,6 +167,11 @@ private:
 
 	virtual void preInstHook(uint32 inst);
 	virtual void postInstHook(uint32 inst);
+
+#ifdef ENABLE_FOXTAIL
+	bool _needAltOpcodes;
+	uint32 decodeAltOpcodes(uint32 inst);
+#endif
 };
 
 } // End of namespace Wintermute


Commit: 5ad57c94dd5cb4133ec332762a919f42428c82b9
    https://github.com/scummvm/scummvm/commit/5ad57c94dd5cb4133ec332762a919f42428c82b9
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Add extra keymaps for FoxTail 1.2.896

Changed paths:
    engines/wintermute/keymapper_tables.h


diff --git a/engines/wintermute/keymapper_tables.h b/engines/wintermute/keymapper_tables.h
index 66154104cc..033f162eef 100644
--- a/engines/wintermute/keymapper_tables.h
+++ b/engines/wintermute/keymapper_tables.h
@@ -669,6 +669,58 @@ inline Common::KeymapArray getWintermuteKeymaps(const char *target, const Common
 			//TODO: extra joy control, e.g. "JOY_R+JOY_B"
 			gameKeyMap->addAction(act);
 		}
+
+		if (extra.hasPrefix("1.2.896.")) {
+			act = new Action("CREDIT", _("Show game credits"));
+			act->setKeyEvent(KEYCODE_F1);
+			act->addDefaultInputMapping("F1"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("MPLAY", _("Play selected music record"));
+			act->setKeyEvent(KEYCODE_F4);
+			act->addDefaultInputMapping("F4"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("MNEXT", _("Select next music record"));
+			act->setKeyEvent(KeyState(KEYCODE_TAB, ASCII_TAB));
+			act->addDefaultInputMapping("TAB"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("NOTE1", _("Play note 1: A"));
+			act->setKeyEvent(KeyState(KEYCODE_d, 'd'));
+			act->addDefaultInputMapping("d"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("NOTE2", _("Play note 2: F#"));
+			act->setKeyEvent(KeyState(KEYCODE_f, 'f'));
+			act->addDefaultInputMapping("f"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("NOTE3", _("Play note 3: D#"));
+			act->setKeyEvent(KeyState(KEYCODE_g, 'g'));
+			act->addDefaultInputMapping("g"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("NOTE4", _("Play note 4: C#"));
+			act->setKeyEvent(KeyState(KEYCODE_h, 'h'));
+			act->addDefaultInputMapping("h"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("NOTE5", _("Play note 5: E"));
+			act->setKeyEvent(KeyState(KEYCODE_j, 'j'));
+			act->addDefaultInputMapping("j"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("NOTE6", _("Play note 6: G#"));
+			act->setKeyEvent(KeyState(KEYCODE_k, 'k'));
+			act->addDefaultInputMapping("k"); // original keyboard
+			gameKeyMap->addAction(act);
+
+			act = new Action("NOTE7", _("Play note 7: B"));
+			act->setKeyEvent(KeyState(KEYCODE_l, 'l'));
+			act->addDefaultInputMapping("l"); // original keyboard
+			gameKeyMap->addAction(act);
+		}
 	} else if (gameId == "ghostsheet") {
 		act = new Action("HINT", _("Show hints"));
 		act->setKeyEvent(KeyState(KEYCODE_TAB, ASCII_TAB));


Commit: 1b5cbe8c20447b5d38ac9a7af9cf749aa9819fc9
    https://github.com/scummvm/scummvm/commit/1b5cbe8c20447b5d38ac9a7af9cf749aa9819fc9
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Add keymapper_tables.h to POTFILES

Changed paths:
    engines/wintermute/POTFILES


diff --git a/engines/wintermute/POTFILES b/engines/wintermute/POTFILES
index 79f5c5dfed..f3100a904d 100644
--- a/engines/wintermute/POTFILES
+++ b/engines/wintermute/POTFILES
@@ -1,2 +1,3 @@
 engines/wintermute/detection.cpp
 engines/wintermute/wintermute.cpp
+keymapper_tables.h
\ No newline at end of file


Commit: 2b34a9fbcafdcbe169a6ace144c86ff4a69f9aba
    https://github.com/scummvm/scummvm/commit/2b34a9fbcafdcbe169a6ace144c86ff4a69f9aba
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Add some small FoxTail-specific methods

Changed paths:
    engines/wintermute/base/base_game.cpp
    engines/wintermute/base/base_object.cpp
    engines/wintermute/base/scriptables/script_ext_date.cpp
    engines/wintermute/ui/ui_button.cpp


diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index b566f3127c..b350358207 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -1432,6 +1432,19 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
 
 		return STATUS_OK;
 	}
+
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] ValidSaveSlotVersion
+	// Checks if given slot stores game state of compatible game version
+	// This version always returs true
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "ValidSaveSlotVersion") == 0) {
+		stack->correctParams(1);
+		/* int slot = */ stack->pop()->getInt();
+		// do nothing
+		stack->pushBool(true);
+		return STATUS_OK;
+	}
 #endif
 
 	//////////////////////////////////////////////////////////////////////////
@@ -3359,6 +3372,27 @@ bool BaseGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack
 	}
 
 #ifdef ENABLE_FOXTAIL
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] IsNumber
+	// Used at kalimba.script to check if string token is a number
+	// If true is returned, then ToInt() is called for same parameter
+	// ToInt(string) implementation is using atoi(), so let's use it here too
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "IsNumber") == 0) {
+		stack->correctParams(1);
+		ScValue *val = stack->pop();
+		
+		bool result = false;
+		if (val->isInt() || val->isFloat()) {
+			result = true;
+		} else if (val->isString()) {
+			const char *str = val->getString();
+			result = (atoi(str) != 0) || (strcmp(str, "0") == 0);
+		}
+
+		stack->pushBool(result);
+	}
+
 	//////////////////////////////////////////////////////////////////////////
 	// [FoxTail] Split
 	// Returns array of words of a string, using another as a delimeter
@@ -3394,6 +3428,29 @@ bool BaseGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack
 
 		delete[] copy;
 	}
+
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] Trim / lTrim / rTrim
+	// Removes whitespaces from a string from the left & right
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "Trim") == 0 || strcmp(name, "lTrim") == 0 || strcmp(name, "rTrim") == 0) {
+		stack->correctParams(1);
+		const char *str = stack->pop()->getString();
+		char *copy = new char[strlen(str) + 1];
+		strcpy(copy, str); 
+
+		char *ptr = copy;
+		if (strcmp(name, "rTrim") != 0) {
+			ptr = Common::ltrim(ptr);
+		}
+		if (strcmp(name, "lTrim") != 0) {
+			ptr = Common::rtrim(ptr);
+		}
+
+		stack->pushString(ptr);
+
+		delete[] copy;
+	}
 #endif
 
 	//////////////////////////////////////////////////////////////////////////
diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp
index 8f3cfa67f1..855f68d178 100644
--- a/engines/wintermute/base/base_object.cpp
+++ b/engines/wintermute/base/base_object.cpp
@@ -479,6 +479,23 @@ bool BaseObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta
 		return STATUS_OK;
 	}
 
+#ifdef ENABLE_FOXTAIL
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] GetSoundFilename
+	// Used to save/restore ambient sounds
+	// Should contain '\\' character, because Split("\\") is called on result 
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "GetSoundFilename") == 0) {
+		stack->correctParams(0);
+
+		if (!_sFX) {
+			stack->pushNULL();
+		} else {
+			stack->pushString(_sFX->getFilename());
+		}
+		return STATUS_OK;
+	}
+#endif
 
 	//////////////////////////////////////////////////////////////////////////
 	// SoundFXNone
diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp
index 89cdcde0af..c53fd4ea11 100644
--- a/engines/wintermute/base/scriptables/script_ext_date.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_date.cpp
@@ -90,6 +90,17 @@ bool SXDate::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
 		stack->pushInt(_tm.tm_mon + 1);
 		return STATUS_OK;
 	}
+#ifdef ENABLE_FOXTAIL
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] GetDay
+	// date.GetDate() was renamed to date.GetDay() in FoxTail 1.2.896 engine
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "GetDay") == 0) {
+		stack->correctParams(0);
+		stack->pushInt(_tm.tm_mday);
+		return STATUS_OK;
+	}
+#endif
 	//////////////////////////////////////////////////////////////////////////
 	// GetDate
 	//////////////////////////////////////////////////////////////////////////
diff --git a/engines/wintermute/ui/ui_button.cpp b/engines/wintermute/ui/ui_button.cpp
index 2e41e1432e..eaa853e37b 100644
--- a/engines/wintermute/ui/ui_button.cpp
+++ b/engines/wintermute/ui/ui_button.cpp
@@ -872,6 +872,21 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
 		return STATUS_OK;
 	}
 
+#ifdef ENABLE_FOXTAIL
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] HeightToFit
+	// Used to autofit widget's height to it's content
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "HeightToFit") == 0) {
+		stack->correctParams(0);
+
+		correctSize();
+
+		stack->pushNULL();
+		return STATUS_OK;
+	}
+#endif
+
 	//////////////////////////////////////////////////////////////////////////
 	// SetDisabledImage
 	//////////////////////////////////////////////////////////////////////////


Commit: 55d443d824c443798397bc6e6c0b2ec4bedbcfae
    https://github.com/scummvm/scummvm/commit/55d443d824c443798397bc6e6c0b2ec4bedbcfae
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Patch text line height for FoxTail 1.2.896

Changed paths:
    engines/wintermute/base/font/base_font_truetype.cpp


diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index cf79f3bbbc..6a5605feaa 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -32,6 +32,7 @@
 #include "engines/wintermute/base/gfx/base_surface.h"
 #include "engines/wintermute/base/base_parser.h"
 #include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_engine.h"
 #include "engines/wintermute/base/base_file_manager.h"
 #include "engines/wintermute/utils/utils.h"
 #include "engines/wintermute/wintermute.h"
@@ -615,6 +616,11 @@ bool BaseFontTT::initFont() {
 		warning("BaseFontTT::InitFont - Couldn't load font: %s", _fontFile);
 	}
 	_lineHeight = _font->getFontHeight();
+#ifdef ENABLE_FOXTAIL
+	if (BaseEngine::instance().isFoxTail(FOXTAIL_1_2_896, FOXTAIL_LATEST_VERSION)) {
+		_lineHeight -= 1;
+	}
+#endif
 	return STATUS_OK;
 }
 


Commit: fae360a50f10932d6d095f559d8ca0d83e1cb3aa
    https://github.com/scummvm/scummvm/commit/fae360a50f10932d6d095f559d8ca0d83e1cb3aa
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Extend crossfade & add MusicCrossfadeVolume() for FoxTail

Changed paths:
    engines/wintermute/base/base_game_music.cpp
    engines/wintermute/base/base_game_music.h


diff --git a/engines/wintermute/base/base_game_music.cpp b/engines/wintermute/base/base_game_music.cpp
index fee7c7be2d..29040e8788 100644
--- a/engines/wintermute/base/base_game_music.cpp
+++ b/engines/wintermute/base/base_game_music.cpp
@@ -49,6 +49,8 @@ BaseGameMusic::BaseGameMusic(BaseGame *gameRef) : _gameRef(gameRef) {
 	_musicCrossfadeChannel1 = -1;
 	_musicCrossfadeChannel2 = -1;
 	_musicCrossfadeSwap = false;
+	_musicCrossfadeVolume1 = 0;
+	_musicCrossfadeVolume2 = 100;
 }
 
 void BaseGameMusic::cleanup() {
@@ -152,8 +154,6 @@ bool BaseGameMusic::setMusicStartTime(int channel, uint32 time) {
 
 //////////////////////////////////////////////////////////////////////////
 bool BaseGameMusic::updateMusicCrossfade() {
-	/* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */
-
 	if (!_musicCrossfadeRunning) {
 		return STATUS_OK;
 	}
@@ -181,13 +181,22 @@ bool BaseGameMusic::updateMusicCrossfade() {
 
 	if (currentTime >= _musicCrossfadeLength) {
 		_musicCrossfadeRunning = false;
-		//_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol);
-		_music[_musicCrossfadeChannel2]->setVolumePercent(100);
 
-		_music[_musicCrossfadeChannel1]->stop();
-		//_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol);
-		_music[_musicCrossfadeChannel1]->setVolumePercent(100);
+		if (_musicCrossfadeVolume2 == 0) {
+			_music[_musicCrossfadeChannel2]->stop();
+			_music[_musicCrossfadeChannel2]->setVolumePercent(100);
+		} else {
+			_music[_musicCrossfadeChannel2]->setVolumePercent(_musicCrossfadeVolume2);
+		}
 
+		if (_musicCrossfadeChannel1 != _musicCrossfadeChannel2) {
+			if (_musicCrossfadeVolume1 == 0) {
+				_music[_musicCrossfadeChannel1]->stop();
+				_music[_musicCrossfadeChannel1]->setVolumePercent(100);
+			} else {
+				_music[_musicCrossfadeChannel1]->setVolumePercent(_musicCrossfadeVolume1);
+			}
+		}
 
 		if (_musicCrossfadeSwap) {
 			// swap channels
@@ -201,12 +210,15 @@ bool BaseGameMusic::updateMusicCrossfade() {
 			_musicStartTime[_musicCrossfadeChannel2] = dummyInt;
 		}
 	} else {
-		//_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol - (float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
-		//_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
-		_music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f));
-		_music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f));
-
-		//_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume());
+		float progress = (float)currentTime / (float)_musicCrossfadeLength;
+		int volumeDelta = (int)((_musicCrossfadeVolume1 - _musicCrossfadeVolume2)*progress);
+		_music[_musicCrossfadeChannel2]->setVolumePercent(_musicCrossfadeVolume1 - volumeDelta);
+		BaseEngine::LOG(0, "Setting music channel %d volume to %d", _musicCrossfadeChannel2, _musicCrossfadeVolume1 - volumeDelta);
+
+		if (_musicCrossfadeChannel1 != _musicCrossfadeChannel2) {
+			_music[_musicCrossfadeChannel1]->setVolumePercent(_musicCrossfadeVolume2 + volumeDelta);
+			BaseEngine::LOG(0, "Setting music channel %d volume to %d", _musicCrossfadeChannel1, _musicCrossfadeVolume2 + volumeDelta);
+		}
 	}
 
 	return STATUS_OK;
@@ -227,6 +239,12 @@ bool BaseGameMusic::persistCrossfadeSettings(BasePersistenceManager *persistMgr)
 	persistMgr->transferSint32(TMEMBER(_musicCrossfadeChannel1));
 	persistMgr->transferSint32(TMEMBER(_musicCrossfadeChannel2));
 	persistMgr->transferBool(TMEMBER(_musicCrossfadeSwap));
+
+	// let's keep savegame compatibility for the price of small possibility of wrong volume at game load
+	if (!persistMgr->getIsSaving()) {
+		_musicCrossfadeVolume1 = 0;
+		_musicCrossfadeVolume2 = 100;
+	}
 	return true;
 }
 
@@ -472,6 +490,8 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
 		_musicCrossfadeStartTime = _gameRef->getLiveTimer()->getTime();
 		_musicCrossfadeChannel1 = channel1;
 		_musicCrossfadeChannel2 = channel2;
+		_musicCrossfadeVolume1 = 0;
+		_musicCrossfadeVolume2 = 100;
 		_musicCrossfadeLength = fadeLength;
 		_musicCrossfadeSwap = swap;
 
@@ -481,6 +501,38 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
 		return STATUS_OK;
 	}
 
+#ifdef ENABLE_FOXTAIL
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] MusicCrossfadeVolume
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "MusicCrossfadeVolume") == 0) {
+		stack->correctParams(4);
+		int channel = stack->pop()->getInt(0);
+		int volume1 = stack->pop()->getInt(0);
+		int volume2 = stack->pop()->getInt(0);
+		uint32 fadeLength = (uint32)stack->pop()->getInt(0);
+
+		if (_musicCrossfadeRunning) {
+			script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress.");
+			stack->pushBool(false);
+			return STATUS_OK;
+		}
+
+		_musicCrossfadeStartTime = _gameRef->getLiveTimer()->getTime();
+		_musicCrossfadeChannel1 = channel;
+		_musicCrossfadeChannel2 = channel;
+		_musicCrossfadeVolume1 = volume1;
+		_musicCrossfadeVolume2 = volume2;
+		_musicCrossfadeLength = fadeLength;
+		_musicCrossfadeSwap = false;
+
+		_musicCrossfadeRunning = true;
+
+		stack->pushBool(true);
+		return STATUS_OK;
+	}
+#endif
+
 	//////////////////////////////////////////////////////////////////////////
 	// GetSoundLength
 	//////////////////////////////////////////////////////////////////////////
diff --git a/engines/wintermute/base/base_game_music.h b/engines/wintermute/base/base_game_music.h
index 1e786dbb2b..7fa364ad47 100644
--- a/engines/wintermute/base/base_game_music.h
+++ b/engines/wintermute/base/base_game_music.h
@@ -66,6 +66,8 @@ private:
 	uint32 _musicCrossfadeLength;
 	int32 _musicCrossfadeChannel1;
 	int32 _musicCrossfadeChannel2;
+	int32 _musicCrossfadeVolume1;
+	int32 _musicCrossfadeVolume2;
 };
 
 } // End of namespace Wintermute


Commit: bae13c14143cecda542e4c6214f56e46c6790ce4
    https://github.com/scummvm/scummvm/commit/bae13c14143cecda542e4c6214f56e46c6790ce4
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Fix & extend string Split() for FoxTail

Changed paths:
    engines/wintermute/base/base_game.cpp


diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index b350358207..f5af3b803e 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -3396,15 +3396,19 @@ bool BaseGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack
 	//////////////////////////////////////////////////////////////////////////
 	// [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
+	// Used to split strings by 1-2 characters delimeter in various scripts
+	// All the delimeters ever used in FoxTail are:
+	//   " ", "@", "#", "$", "&", ",", "\\", "@h", "@i", "@p", "@s"
 	//////////////////////////////////////////////////////////////////////////
 	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;
+		Common::String sep = stack->pop()->getString();
+		uint32 size = strlen(str) + 1;
+
+		// Let's make copies before modifying stack
+		char *copy = new char[size];
+		strcpy(copy, str);
 
 		// There is no way to makeSXArray() with exactly 1 given element
 		// That's why we are creating empty Array and SXArray::push() later
@@ -3412,15 +3416,17 @@ bool BaseGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack
 		BaseScriptable *arr = makeSXArray(_gameRef, stack);
 
 		// Iterating string copy, replacing delimeter with '\0' and pushing matches
-		char *copy = new char[size];
-		strcpy(copy, str);
+		// Only non-empty matches should be pushed
 		char *begin = copy;
 		for (char *it = copy; it < copy + size; it++) {
-			if (*it == sep || *it == '\0') {
+			if (strncmp(it, sep.c_str(), sep.size()) == 0 || *it == '\0') {
 				*it = '\0';
-				stack->pushString(begin);
-				((SXArray *)arr)->push(stack->pop());
-				begin = it + 1;
+				if (it != begin) {
+					stack->pushString(begin);
+					((SXArray *)arr)->push(stack->pop());
+				}
+				begin = it + sep.size();
+				it = begin - 1;
 			}
 		}
 


Commit: 288d8a8a745388590dcd1374e5a337d715bedc59
    https://github.com/scummvm/scummvm/commit/288d8a8a745388590dcd1374e5a337d715bedc59
Author: lolbot-iichan (lolbot_iichan at mail.ru)
Date: 2020-05-12T10:33:58+02:00

Commit Message:
WINTERMUTE: Fix & extend non-package file access, add GetFiles() for FoxTail

Changed paths:
    engines/wintermute/base/base_file_manager.cpp
    engines/wintermute/base/base_file_manager.h
    engines/wintermute/base/base_game.cpp
    engines/wintermute/base/file/base_disk_file.cpp
    engines/wintermute/base/file/base_disk_file.h
    engines/wintermute/base/file/base_savefile_manager_file.cpp
    engines/wintermute/base/file/base_savefile_manager_file.h
    engines/wintermute/wintermute.cpp


diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp
index 09c04e0c50..f99977a31e 100644
--- a/engines/wintermute/base/base_file_manager.cpp
+++ b/engines/wintermute/base/base_file_manager.cpp
@@ -395,10 +395,24 @@ bool BaseFileManager::hasFile(const Common::String &filename) {
 	return false;
 }
 
-int BaseFileManager::listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern) {
+//////////////////////////////////////////////////////////////////////////
+int BaseFileManager::listMatchingPackageMembers(Common::ArchiveMemberList &list, const Common::String &pattern) {
 	return _packages.listMatchingMembers(list, pattern);
 }
 
+//////////////////////////////////////////////////////////////////////////
+int BaseFileManager::listMatchingFiles(Common::StringArray &list, const Common::String &pattern) {
+	list = sfmFileList(pattern);
+	
+	Common::ArchiveMemberList files;
+	listMatchingDiskFileMembers(files, pattern);
+	for (Common::ArchiveMemberList::const_iterator it = files.begin(); it != files.end(); ++it) {
+		list.push_back((*it)->getName());
+	}
+		
+	return list.size();
+}
+
 //////////////////////////////////////////////////////////////////////////
 Common::SeekableReadStream *BaseFileManager::openFile(const Common::String &filename, bool absPathWarning, bool keepTrackOf) {
 	if (strcmp(filename.c_str(), "") == 0) {
diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h
index 397e38cc3d..de4f761a93 100644
--- a/engines/wintermute/base/base_file_manager.h
+++ b/engines/wintermute/base/base_file_manager.h
@@ -31,6 +31,7 @@
 
 #include "common/archive.h"
 #include "common/str.h"
+#include "common/str-array.h"
 #include "common/fs.h"
 #include "common/file.h"
 #include "common/language.h"
@@ -42,7 +43,8 @@ public:
 
 	bool closeFile(Common::SeekableReadStream *File);
 	bool hasFile(const Common::String &filename);
-	int listMatchingMembers(Common::ArchiveMemberList &list, const Common::String &pattern);
+	int listMatchingPackageMembers(Common::ArchiveMemberList &list, const Common::String &pattern);
+	int listMatchingFiles(Common::StringArray &list, const Common::String &pattern);
 	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);
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index f5af3b803e..6c1faaa237 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -2194,6 +2194,32 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
 
 		return STATUS_OK;
 	}
+
+	//////////////////////////////////////////////////////////////////////////
+	// [FoxTail] GetFiles
+	// Used at kalimba.script on F9 keypress to reload list of available music
+	// Known params: "*.mb"
+	// Original implementation does not seem to look up at DCP packages
+	// This implementation looks up at savegame storage and for actual files 
+	// Return value expected to be an Array of Strings
+	//////////////////////////////////////////////////////////////////////////
+	else if (strcmp(name, "GetFiles") == 0) {
+		stack->correctParams(1);
+		const char *pattern = stack->pop()->getString();
+
+		Common::StringArray fnames;
+		BaseFileManager::getEngineInstance()->listMatchingFiles(fnames, pattern);
+		
+		stack->pushInt(0);
+		BaseScriptable *arr = makeSXArray(_gameRef, stack);
+		for (uint32 i = 0; i < fnames.size(); i++) {
+			stack->pushString(fnames[i].c_str());
+			((SXArray *)arr)->push(stack->pop());
+		}
+
+ 		stack->pushNative(arr, false);
+ 		return STATUS_OK;
+	}
 #endif
 
 	//////////////////////////////////////////////////////////////////////////
diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp
index 4e26ec8920..6b77d79801 100644
--- a/engines/wintermute/base/file/base_disk_file.cpp
+++ b/engines/wintermute/base/file/base_disk_file.cpp
@@ -61,8 +61,8 @@ static Common::FSNode getNodeForRelativePath(const Common::String &filename) {
 	}
 
 	// Relative path:
-	if (filename.contains('\\')) {
-		Common::StringTokenizer path(filename, "\\");
+	if (filename.contains('/')) {
+		Common::StringTokenizer path(filename, "/");
 
 		// Start traversing relative to the game-data-dir
 		const Common::FSNode gameDataDir(ConfMan.get("path"));
@@ -70,7 +70,7 @@ static Common::FSNode getNodeForRelativePath(const Common::String &filename) {
 
 		// Parse all path-elements
 		while (!path.empty()) {
-			// Get the next path-component by slicing on '\\'
+			// Get the next path-component by slicing on '/'
 			Common::String pathPart = path.nextToken();
 			// Get the next FSNode in the chain, if it exists as a child from the previous.
 			curNode = curNode.getChild(pathPart);
@@ -109,6 +109,11 @@ bool diskFileExists(const Common::String &filename) {
 	return false;
 }
 
+
+int listMatchingDiskFileMembers(Common::ArchiveMemberList &list, const Common::String &pattern) {
+	return Common::FSDirectory(ConfMan.get("path")).listMatchingMembers(list, pattern);
+}
+			
 Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
 	uint32 prefixSize = 0;
 	Common::SeekableReadStream *file = nullptr;
diff --git a/engines/wintermute/base/file/base_disk_file.h b/engines/wintermute/base/file/base_disk_file.h
index f20629f7ec..cd6645f1d4 100644
--- a/engines/wintermute/base/file/base_disk_file.h
+++ b/engines/wintermute/base/file/base_disk_file.h
@@ -29,12 +29,14 @@
 #ifndef WINTERMUTE_BASE_DISKFILE_H
 #define WINTERMUTE_BASE_DISKFILE_H
 
+#include "common/archive.h"
 #include "common/stream.h"
 
 namespace Wintermute {
 
 Common::SeekableReadStream *openDiskFile(const Common::String &filename);
 bool diskFileExists(const Common::String &filename);
+int listMatchingDiskFileMembers(Common::ArchiveMemberList &list, const Common::String &pattern);
 
 } // End of namespace Wintermute
 
diff --git a/engines/wintermute/base/file/base_savefile_manager_file.cpp b/engines/wintermute/base/file/base_savefile_manager_file.cpp
index d76053f58f..3e45fd0da2 100644
--- a/engines/wintermute/base/file/base_savefile_manager_file.cpp
+++ b/engines/wintermute/base/file/base_savefile_manager_file.cpp
@@ -42,6 +42,9 @@ Common::String makeSfmFilename(const Common::String &filename) {
 			smFilename.setChar('_', i);
 		}
 	}
+	while (smFilename.hasPrefix("._")) {
+		smFilename = smFilename.substr(2);
+	}
 	return BaseEngine::instance().getGameTargetName() + "." + smFilename;
 }
 
@@ -60,4 +63,14 @@ Common::WriteStream *openSfmFileForWrite(const Common::String &filename) {
 	return g_system->getSavefileManager()->openForSaving(smFilename, false);
 }
 
+Common::StringArray sfmFileList(const Common::String &mask) {
+	Common::String prefix = BaseEngine::instance().getGameTargetName() + ".";
+	Common::String smMask = makeSfmFilename(mask);
+	Common::StringArray array = g_system->getSavefileManager()->listSavefiles(smMask);
+	for (uint32 i = 0; i < array.size(); i++) {
+		array[i] = array[i].substr(prefix.size());
+	}
+	return array;
+}
+
 } // End of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_savefile_manager_file.h b/engines/wintermute/base/file/base_savefile_manager_file.h
index 2b129cf39a..99307aeab8 100644
--- a/engines/wintermute/base/file/base_savefile_manager_file.h
+++ b/engines/wintermute/base/file/base_savefile_manager_file.h
@@ -29,6 +29,7 @@
 #ifndef WINTERMUTE_BASE_SAVEFILEMANAGERFILE_H
 #define WINTERMUTE_BASE_SAVEFILEMANAGERFILE_H
 
+#include "common/str-array.h"
 #include "common/stream.h"
 
 namespace Wintermute {
@@ -36,6 +37,7 @@ namespace Wintermute {
 Common::SeekableReadStream *openSfmFile(const Common::String &filename);
 Common::WriteStream *openSfmFileForWrite(const Common::String &filename);
 bool sfmFileExists(const Common::String &filename);
+Common::StringArray sfmFileList(const Common::String &mask);
 
 } // End of namespace Wintermute
 
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index c41c559cc4..b3ea5f5593 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -184,7 +184,7 @@ int WintermuteEngine::init() {
 	#endif
 
 	Common::ArchiveMemberList actors3d;
-	if (BaseEngine::instance().getFileManager()->listMatchingMembers(actors3d, "*.act3d")) {
+	if (BaseEngine::instance().getFileManager()->listMatchingPackageMembers(actors3d, "*.act3d")) {
 		GUI::MessageDialog dialog(
 				_("This game requires 3D characters support, which is out of ScummVM's scope."),
 				_("Start anyway"),




More information about the Scummvm-git-logs mailing list