[Scummvm-git-logs] scummvm master -> de5fbf9b008710d75aa1dc9923b4806318de6608
neuromancer
noreply at scummvm.org
Sun Apr 30 18:30:57 UTC 2023
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
c4a0d162fb FREESCAPE: refactored conditional handling to make it work with castle
de5fbf9b00 FREESCAPE: added support for using different languages in castle (DOS)
Commit: c4a0d162fb117c5e28c86c62070dd31f468b22d8
https://github.com/scummvm/scummvm/commit/c4a0d162fb117c5e28c86c62070dd31f468b22d8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-04-30T20:30:41+02:00
Commit Message:
FREESCAPE: refactored conditional handling to make it work with castle
Changed paths:
engines/freescape/freescape.h
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/8bitDetokeniser.h
engines/freescape/language/instruction.cpp
engines/freescape/language/token.h
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 385745bb4db..2bf19ab76ef 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -281,6 +281,7 @@ public:
void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer);
// Instructions
+ bool checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated);
bool checkIfGreaterOrEqual(FCLInstruction &instruction);
void executeIncrementVariable(FCLInstruction &instruction);
void executeDecrementVariable(FCLInstruction &instruction);
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 37b76ab9854..775140d972a 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -33,7 +33,7 @@ uint8 k8bitMaxVariable = 64;
uint8 k8bitMaxShield = 64;
uint8 k8bitMaxEnergy = 64;
-Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool enableActivated) {
+Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool multipleConditionals) {
Common::String detokenisedStream;
Common::Array<uint8>::size_type bytePointer = 0;
Common::Array<uint8>::size_type sizeOfTokenisedContent = tokenisedCondition.size();
@@ -56,28 +56,30 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
if (sizeOfTokenisedContent > 0)
detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
- Token::Type newConditional = Token::UNKNOWN;
- Token::Type oldConditional = Token::UNKNOWN;
+ uint16 newConditional = 0;
+ uint16 oldConditional = 0;
while (bytePointer < sizeOfTokenisedContent) {
// get the conditional type of the next operation
- uint8 conditionalByte = tokenisedCondition[bytePointer];
-
- if ((conditionalByte & 0xc0) && enableActivated) {
- newConditional = Token::ACTIVATEDQ;
- } else if (conditionalByte & 0x80)
- newConditional = Token::SHOTQ;
- else if (conditionalByte & 0x40)
- newConditional = Token::TIMERQ;
+ uint8 conditionalByte = tokenisedCondition[bytePointer] & 0xc0;
+ //detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", conditionalByte);
+ newConditional = 0;
+
+ if (conditionalByte == 0x40)
+ newConditional = kConditionalTimeout;
+ else if (conditionalByte == 0x80)
+ newConditional = kConditionalShot;
+ else if (conditionalByte == 0xc0)
+ newConditional = kConditionalActivated;
else
- newConditional = Token::COLLIDEDQ;
+ newConditional = kConditionalCollided;
// if the conditional type has changed then end the old conditional,
// if we were in one, and begin a new one
if (bytePointer == 0 || newConditional != oldConditional) {
oldConditional = newConditional;
FCLInstruction branch;
- branch = FCLInstruction(oldConditional);
+ branch = FCLInstruction(Token::CONDITIONAL);
if (bytePointer > 0) {
detokenisedStream += "ENDIF\n";
@@ -86,18 +88,23 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
}
branch.setBranches(conditionalInstructions, nullptr);
+ branch.setSource(oldConditional); // conditional flag
instructions.push_back(branch);
- if (oldConditional == Token::SHOTQ)
- detokenisedStream += "IF SHOT? THEN\n";
- else if (oldConditional == Token::TIMERQ)
- detokenisedStream += "IF TIMER? THEN\n";
- else if (oldConditional == Token::COLLIDEDQ)
- detokenisedStream += "IF COLLIDED? THEN\n";
- else if (oldConditional == Token::ACTIVATEDQ)
- detokenisedStream += "IF ACTIVATED? THEN\n";
+ detokenisedStream += "IF ";
+
+ if (oldConditional & kConditionalShot)
+ detokenisedStream += "SHOT? ";
+ else if (oldConditional & kConditionalTimeout)
+ detokenisedStream += "TIMER? ";
+ else if (oldConditional & kConditionalCollided)
+ detokenisedStream += "COLLIDED? ";
+ else if (oldConditional & kConditionalActivated)
+ detokenisedStream += "ACTIVATED? ";
else
error("Invalid conditional: %x", oldConditional);
+
+ detokenisedStream += "THEN\n";
}
// get the actual operation
diff --git a/engines/freescape/language/8bitDetokeniser.h b/engines/freescape/language/8bitDetokeniser.h
index 08326c2d5c9..8ba7c11a3f0 100644
--- a/engines/freescape/language/8bitDetokeniser.h
+++ b/engines/freescape/language/8bitDetokeniser.h
@@ -36,6 +36,13 @@ enum {
k8bitVariableEnergyDrillerJet = 57
};
+enum {
+ kConditionalShot = 1 << 0,
+ kConditionalTimeout = 1 << 1,
+ kConditionalCollided = 1 << 2,
+ kConditionalActivated = 1 << 3,
+};
+
extern uint8 k8bitMaxVariable;
extern uint8 k8bitMaxShield;
extern uint8 k8bitMaxEnergy;
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index b27b8bbffc9..da9ed9ba5d4 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -148,31 +148,13 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
debugC(1, kFreescapeDebugCode, "Executing NOP at ip: %d", ip);
break;
- case Token::ACTIVATEDQ:
- if (shot) // TODO: implement interaction
+ case Token::CONDITIONAL:
+ if (checkConditional(instruction, shot, collided, timer, false)) // TODO: implement interaction
executeCode(*instruction._thenInstructions, shot, collided, timer);
// else branch is always empty
assert(instruction._elseInstructions == nullptr);
break;
- case Token::COLLIDEDQ:
- if (collided)
- executeCode(*instruction._thenInstructions, shot, collided, timer);
- // else branch is always empty
- assert(instruction._elseInstructions == nullptr);
- break;
- case Token::SHOTQ:
- if (shot)
- executeCode(*instruction._thenInstructions, shot, collided, timer);
- // else branch is always empty
- assert(instruction._elseInstructions == nullptr);
- break;
- case Token::TIMERQ:
- if (timer)
- executeCode(*instruction._thenInstructions, shot, collided, timer);
- // else branch is always empty
- assert(instruction._elseInstructions == nullptr);
- break;
case Token::VARNOTEQ:
if (executeEndIfNotEqual(instruction))
ip = codeSize;
@@ -355,6 +337,23 @@ bool FreescapeEngine::executeEndIfVisibilityIsEqual(FCLInstruction &instruction)
return (obj->isInvisible() == (value != 0));
}
+bool FreescapeEngine::checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated) {
+ uint16 conditional = instruction._source;
+ bool result = false;
+
+ if (conditional & kConditionalShot)
+ result |= shot;
+ if (conditional & kConditionalTimeout)
+ result |= timer;
+ if (conditional & kConditionalCollided)
+ result |= collided;
+ if (conditional & kConditionalActivated)
+ result |= activated;
+
+ debugC(1, kFreescapeDebugCode, "Check if conditional %x is true: %d!", conditional, result);
+ return result;
+}
+
bool FreescapeEngine::checkIfGreaterOrEqual(FCLInstruction &instruction) {
uint16 variable = instruction._source;
uint16 value = instruction._destination;
diff --git a/engines/freescape/language/token.h b/engines/freescape/language/token.h
index d108d93d780..a99d777b8bd 100644
--- a/engines/freescape/language/token.h
+++ b/engines/freescape/language/token.h
@@ -30,12 +30,11 @@ namespace Freescape {
struct Token {
public:
enum Type {
- ACTIVATEDQ,
ADDVAR,
AGAIN,
AND,
ANDV,
- COLLIDEDQ,
+ CONDITIONAL,
DELAY,
DESTROY,
DESTROYEDQ,
@@ -67,7 +66,6 @@ public:
SCREEN,
SOUND,
SETVAR,
- SHOTQ,
START,
STARTANIM,
STOPANIM,
@@ -75,7 +73,6 @@ public:
SUBVAR,
SYNCSND,
THEN,
- TIMERQ,
TOGVIS,
TRIGANIM,
UPDATEI,
Commit: de5fbf9b008710d75aa1dc9923b4806318de6608
https://github.com/scummvm/scummvm/commit/de5fbf9b008710d75aa1dc9923b4806318de6608
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-04-30T20:30:41+02:00
Commit Message:
FREESCAPE: added support for using different languages in castle (DOS)
Changed paths:
engines/freescape/detection.cpp
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 032e9bf425d..097a5e98d48 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -346,7 +346,7 @@ static const ADGameDescription gameDescriptions[] = {
{"CMH.EXE", 0, "1f3b67e649e718e239ebfd7c56e96d47", 63040},
AD_LISTEND
},
- Common::EN_ANY,
+ Common::UNK_LANG,
Common::kPlatformDOS,
ADGF_UNSTABLE,
GUIO1(GUIO_NOMIDI)
@@ -619,6 +619,19 @@ public:
const DebugChannelDef *getDebugChannels() const override {
return debugFlagList;
}
+ DetectedGame toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo) const override;
};
+DetectedGame FreescapeMetaEngineDetection::toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo) const {
+ DetectedGame game = AdvancedMetaEngineDetection::toDetectedGame(adGame);
+
+ // The AdvancedDetector model only allows specifying a single supported game language.
+ if (game.gameId == "castlemaster" && game.language == Common::UNK_LANG) {
+ game.appendGUIOptions(Common::getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
+ game.appendGUIOptions(Common::getGameGUIOptionsDescriptionLanguage(Common::FR_FRA));
+ game.appendGUIOptions(Common::getGameGUIOptionsDescriptionLanguage(Common::DE_DEU));
+ }
+ return game;
+}
+
REGISTER_PLUGIN_STATIC(FREESCAPE_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, FreescapeMetaEngineDetection);
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 007ba3d185f..351b96692db 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -60,6 +60,8 @@ FreescapeEngine::FreescapeEngine(OSystem *syst, const ADGameDescription *gd)
_variant = gd->flags;
+ _language = Common::parseLanguage(ConfMan.get("language"));
+
if (!Common::parseBool(ConfMan.get("prerecorded_sounds"), _usePrerecordedSounds))
error("Failed to parse bool from prerecorded_sounds option");
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 2bf19ab76ef..66d56c02e82 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -95,6 +95,7 @@ public:
// Game selection
uint32 _variant;
+ Common::Language _language;
bool isDriller() { return _targetName.hasPrefix("driller") || _targetName.hasPrefix("spacestationoblivion"); }
bool isDark() { return _targetName.hasPrefix("darkside"); }
bool isEclipse() { return _targetName.hasPrefix("totaleclipse"); }
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 7943c1a7578..c5747264ea2 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -143,7 +143,23 @@ void CastleEngine::loadAssetsDOSFullGame() {
_border->setPalette((byte *)&kCastleBorderDOSPalette, 0, 16);
file.close();
- stream = decryptFile("CMLE");
+ switch (_language) {
+ case Common::ES_ESP:
+ stream = decryptFile("CMLS");
+ break;
+ case Common::FR_FRA:
+ stream = decryptFile("CMLF");
+ break;
+ case Common::DE_DEU:
+ stream = decryptFile("CMLG");
+ break;
+ case Common::EN_ANY:
+ stream = decryptFile("CMLE");
+ break;
+ default:
+ error("Invalid or unsupported language: %x", _language);
+ }
+
loadMessagesVariableSize(stream, 0x11, 164);
delete stream;
More information about the Scummvm-git-logs
mailing list