[Scummvm-git-logs] scummvm master -> e7aac61340935b930cf9b8d50a85d51d8e7303cd
aquadran
noreply at scummvm.org
Fri Aug 15 12:57:42 UTC 2025
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
e7aac61340 WINTERMUTE: Added W/A for 'Face Noir' in game mini puzzle
Commit: e7aac61340935b930cf9b8d50a85d51d8e7303cd
https://github.com/scummvm/scummvm/commit/e7aac61340935b930cf9b8d50a85d51d8e7303cd
Author: PaweÅ KoÅodziejski (aquadran at gmail.com)
Date: 2025-08-15T14:57:20+02:00
Commit Message:
WINTERMUTE: Added W/A for 'Face Noir' in game mini puzzle
Changed paths:
engines/wintermute/base/scriptables/script.cpp
engines/wintermute/base/scriptables/script.h
engines/wintermute/base/scriptables/script_value.cpp
engines/wintermute/base/scriptables/script_value.h
engines/wintermute/debugger/watch_instance.cpp
diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp
index e125826ae07..b91bc9d01b1 100644
--- a/engines/wintermute/base/scriptables/script.cpp
+++ b/engines/wintermute/base/scriptables/script.cpp
@@ -107,6 +107,10 @@ ScScript::ScScript(BaseGame *inGame, ScEngine *engine) : BaseClass(inGame) {
#ifdef ENABLE_FOXTAIL
initOpcodesType();
#endif
+ // W/A for 'Face Noir' game. See comment in script_value.cpp
+ if (BaseEngine::instance().getGameId() == "facenoir") {
+ _enableFloatCompareWA = true;
+ }
}
@@ -1019,7 +1023,7 @@ bool ScScript::executeInstruction() {
}
*/
- _operand->setBool(ScValue::compare(op1, op2) == 0);
+ _operand->setBool(ScValue::compare(op1, op2, _enableFloatCompareWA) == 0);
_stack->push(_operand);
break;
@@ -1043,7 +1047,7 @@ bool ScScript::executeInstruction() {
}
*/
- _operand->setBool(ScValue::compare(op1, op2) != 0);
+ _operand->setBool(ScValue::compare(op1, op2, _enableFloatCompareWA) != 0);
_stack->push(_operand);
break;
@@ -1058,7 +1062,7 @@ bool ScScript::executeInstruction() {
else _operand->setBool(op1->getInt() < op2->getInt());
*/
- _operand->setBool(ScValue::compare(op1, op2) < 0);
+ _operand->setBool(ScValue::compare(op1, op2, _enableFloatCompareWA) < 0);
_stack->push(_operand);
break;
@@ -1073,7 +1077,7 @@ bool ScScript::executeInstruction() {
else _operand->setBool(op1->getInt() > op2->getInt());
*/
- _operand->setBool(ScValue::compare(op1, op2) > 0);
+ _operand->setBool(ScValue::compare(op1, op2, _enableFloatCompareWA) > 0);
_stack->push(_operand);
break;
@@ -1088,7 +1092,7 @@ bool ScScript::executeInstruction() {
else _operand->setBool(op1->getInt() <= op2->getInt());
*/
- _operand->setBool(ScValue::compare(op1, op2) <= 0);
+ _operand->setBool(ScValue::compare(op1, op2, _enableFloatCompareWA) <= 0);
_stack->push(_operand);
break;
@@ -1103,7 +1107,7 @@ bool ScScript::executeInstruction() {
else _operand->setBool(op1->getInt() >= op2->getInt());
*/
- _operand->setBool(ScValue::compare(op1, op2) >= 0);
+ _operand->setBool(ScValue::compare(op1, op2, _enableFloatCompareWA) >= 0);
_stack->push(_operand);
break;
@@ -1112,7 +1116,7 @@ bool ScScript::executeInstruction() {
op1 = _stack->pop();
//_operand->setBool(op1->getType()==op2->getType() && op1->getFloat()==op2->getFloat());
- _operand->setBool(ScValue::compareStrict(op1, op2) == 0);
+ _operand->setBool(ScValue::compareStrict(op1, op2, _enableFloatCompareWA) == 0);
_stack->push(_operand);
break;
@@ -1122,7 +1126,7 @@ bool ScScript::executeInstruction() {
op1 = _stack->pop();
//_operand->setBool(op1->getType()!=op2->getType() || op1->getFloat()!=op2->getFloat());
- _operand->setBool(ScValue::compareStrict(op1, op2) != 0);
+ _operand->setBool(ScValue::compareStrict(op1, op2, _enableFloatCompareWA) != 0);
_stack->push(_operand);
break;
@@ -1352,6 +1356,12 @@ bool ScScript::persist(BasePersistenceManager *persistMgr) {
#ifdef ENABLE_FOXTAIL
initOpcodesType();
#endif
+ // W/A for 'Face Noir' game. See comment in script_value.cpp
+ if (BaseEngine::instance().getGameId() == "facenoir") {
+ _enableFloatCompareWA = true;
+ } else {
+ _enableFloatCompareWA = false;
+ }
}
return STATUS_OK;
diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h
index ae175191b0e..a48b57e68f1 100644
--- a/engines/wintermute/base/scriptables/script.h
+++ b/engines/wintermute/base/scriptables/script.h
@@ -168,6 +168,8 @@ private:
void initOpcodesType();
uint32 decodeAltOpcodes(uint32 inst);
#endif
+
+ bool _enableFloatCompareWA{};
};
} // End of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp
index 6e356914fce..62b5a0220ea 100644
--- a/engines/wintermute/base/scriptables/script_value.cpp
+++ b/engines/wintermute/base/scriptables/script_value.cpp
@@ -892,7 +892,7 @@ bool ScValue::saveAsText(BaseDynamicBuffer *buffer, int indent) {
//////////////////////////////////////////////////////////////////////////
// -1 ... left is less, 0 ... equals, 1 ... left is greater
-int ScValue::compare(ScValue *val1, ScValue *val2) {
+int ScValue::compare(ScValue *val1, ScValue *val2, bool enableFloatCompareWA) {
// both natives?
if (val1->isNative() && val2->isNative()) {
// same class?
@@ -925,12 +925,32 @@ int ScValue::compare(ScValue *val1, ScValue *val2) {
// one of them is float?
if (val1->isFloat() || val2->isFloat()) {
- if (val1->getFloat() < val2->getFloat()) {
- return -1;
- } else if (val1->getFloat() > val2->getFloat()) {
- return 1;
+ if (enableFloatCompareWA) {
+ // W/A:
+ // The engine uses double precision for script values,
+ // while other parts use single precision.
+ // Conversion between them may not always be exactly
+ // the same across platforms.
+ // Some games maye rely on the higher precision of doubles.
+ // As a result, calculated values may not match the
+ // expectations of the game scripts.
+ // The solution is to cast to single precision before comparison.
+ // This helps fix the in-game 'Face Noir' mini puzzle.
+ if ((float)val1->getFloat() < (float)val2->getFloat()) {
+ return -1;
+ } else if ((float)val1->getFloat() > (float)val2->getFloat()) {
+ return 1;
+ } else {
+ return 0;
+ }
} else {
- return 0;
+ if (val1->getFloat() < val2->getFloat()) {
+ return -1;
+ } else if (val1->getFloat() > val2->getFloat()) {
+ return 1;
+ } else {
+ return 0;
+ }
}
}
@@ -946,11 +966,11 @@ int ScValue::compare(ScValue *val1, ScValue *val2) {
//////////////////////////////////////////////////////////////////////////
-int ScValue::compareStrict(ScValue *val1, ScValue *val2) {
+int ScValue::compareStrict(ScValue *val1, ScValue *val2, bool enableFloatCompareWA) {
if (val1->getTypeTolerant() != val2->getTypeTolerant()) {
return -1;
} else {
- return ScValue::compare(val1, val2);
+ return ScValue::compare(val1, val2, enableFloatCompareWA);
}
}
diff --git a/engines/wintermute/base/scriptables/script_value.h b/engines/wintermute/base/scriptables/script_value.h
index e4074e977e7..0cd9cea58c7 100644
--- a/engines/wintermute/base/scriptables/script_value.h
+++ b/engines/wintermute/base/scriptables/script_value.h
@@ -41,8 +41,8 @@ class BaseScriptable;
class ScValue : public BaseClass {
public:
- static int compare(ScValue *val1, ScValue *val2);
- static int compareStrict(ScValue *val1, ScValue *val2);
+ static int compare(ScValue *val1, ScValue *val2, bool enableFloatCompareWA);
+ static int compareStrict(ScValue *val1, ScValue *val2, bool enableFloatCompareWA);
TValType getTypeTolerant();
void cleanup(bool ignoreNatives = false);
DECLARE_PERSISTENT(ScValue, BaseClass)
diff --git a/engines/wintermute/debugger/watch_instance.cpp b/engines/wintermute/debugger/watch_instance.cpp
index e4d1f74be5f..7a83e1360d5 100644
--- a/engines/wintermute/debugger/watch_instance.cpp
+++ b/engines/wintermute/debugger/watch_instance.cpp
@@ -38,10 +38,7 @@ void WatchInstance::evaluate() {
// ^^ This here is NULL by default
}
ScValue* currentValue = _script->resolveName(_watch->getSymbol());
- if(ScValue::compare(
- currentValue,
- _lastValue
- )) {
+ if(ScValue::compare(currentValue, _lastValue, false)) {
_lastValue->copy(currentValue);
_watch->trigger(this);
}
More information about the Scummvm-git-logs
mailing list