[Scummvm-git-logs] scummvm master -> 9be5eda0cb9b5693b5f80f12fea50c8ed86f7926
npjg
noreply at scummvm.org
Sun Jan 12 02:24:46 UTC 2025
This automated email contains information about 13 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
79e443c9bd MEDIASTATION: Stub out text hide/show methods
27ffa9c6c9 MEDIASTATION: Remove now-irrelevant comment
90201d267d MEDIASTATION: Add basic if/else branching
3449bd24dd MEDIASTATION: Implement way to get an Operand out of variables
75ab2558bf MEDIASTATION: Remove unused forward declaration
6b493efa04 MEDIASTATION: Upgrade finding an unknown variable type to an error
e626719453 MEDIASTATION: Implement equality testing between operands.
81dda73b58 MEDIASTATION: Stub out mystery IBM/Crayola "drawing" function
edce7ea0e3 MEDIASTATION: Implement >= operator for operands
fd4d85ecd0 MEDIASTATION: Provide a more descriptive error message if we get an empty operand
6b8e9a6703 MEDIASTATION: Make script debug output a bit more understandable
aa26a6a3d9 MEDIASTATION: Implement Image spatialShow script method
9be5eda0cb MEDIASTATION: Implement better interface for getting assets across contexts.
Commit: 79e443c9bd67c9352963ff0bdbbfa56913790970
https://github.com/scummvm/scummvm/commit/79e443c9bd67c9352963ff0bdbbfa56913790970
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T15:23:42-05:00
Commit Message:
MEDIASTATION: Stub out text hide/show methods
Changed paths:
engines/mediastation/assets/text.cpp
diff --git a/engines/mediastation/assets/text.cpp b/engines/mediastation/assets/text.cpp
index d82996a8466..bfdc51b1855 100644
--- a/engines/mediastation/assets/text.cpp
+++ b/engines/mediastation/assets/text.cpp
@@ -35,6 +35,20 @@ Operand Text::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args) {
error("Text::callMethod(): getText() method not implemented yet");
}
+ case kSpatialShowMethod: {
+ assert(args.empty());
+ _isActive = true;
+ warning("Text::callMethod(): spatialShow method not implemented yet");
+ return Operand();
+ }
+
+ case kSpatialHideMethod: {
+ assert(args.empty());
+ _isActive = false;
+ warning("Text::callMethod(): spatialHide method not implemented yet");
+ return Operand();
+ }
+
default: {
error("Got unimplemented method ID %d", methodId);
}
Commit: 27ffa9c6c9dc6b615f922d5fda8421d06e40b4dd
https://github.com/scummvm/scummvm/commit/27ffa9c6c9dc6b615f922d5fda8421d06e40b4dd
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T15:24:35-05:00
Commit Message:
MEDIASTATION: Remove now-irrelevant comment
The problem I was writing about in the comment has since been somewhat addressed.
Changed paths:
engines/mediastation/contextparameters.cpp
diff --git a/engines/mediastation/contextparameters.cpp b/engines/mediastation/contextparameters.cpp
index a691a4df5ea..0434e3dd6d2 100644
--- a/engines/mediastation/contextparameters.cpp
+++ b/engines/mediastation/contextparameters.cpp
@@ -57,8 +57,6 @@ ContextParameters::ContextParameters(Chunk &chunk) : _contextName(nullptr) {
if (repeatedFileNumber != _fileNumber) {
warning("ContextParameters::ContextParameters(): Repeated file number didn't match: %d != %d", repeatedFileNumber, _fileNumber);
}
- // The trouble here is converting the variable to an operand.
- // They are two totally separate types!
Variable *variable = new Variable(chunk);
Operand operand;
if (g_engine->_variables.contains(variable->_id)) {
Commit: 90201d267d890a462a166c4bd2d579cc56f06800
https://github.com/scummvm/scummvm/commit/90201d267d890a462a166c4bd2d579cc56f06800
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T16:43:49-05:00
Commit Message:
MEDIASTATION: Add basic if/else branching
The major item incomplete here is that the if and else code chunks don't get the local variables or parameters from the function-level code chunk. But this at least lets the conditional blocks execute.
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index c998cb6b49a..461d3aad906 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -142,6 +142,25 @@ Operand CodeChunk::executeNextStatement() {
return value;
}
+ case kOpcodeIfElse: {
+ Operand condition = executeNextStatement();
+ CodeChunk ifBlock(*_bytecode);
+ CodeChunk elseBlock(*_bytecode);
+ // Doesn't seem like there is a real bool type for values,
+ // ao just get an integer.
+ if (condition.getInteger()) {
+ // TODO: If locals are modified in here, they won't be
+ // propagated up since it's its own code chunk.
+ ifBlock.execute();
+ } else {
+ elseBlock.execute();
+ }
+
+ // If blocks themselves shouldn't return anything.
+ return Operand();
+ }
+
+
default: {
error("CodeChunk::getNextStatement(): Got unknown opcode 0x%x (%d)", opcode, opcode);
}
Commit: 3449bd24dd76a001f6e090d239b3af404d9b3c0a
https://github.com/scummvm/scummvm/commit/3449bd24dd76a001f6e090d239b3af404d9b3c0a
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T17:01:19-05:00
Commit Message:
MEDIASTATION: Implement way to get an Operand out of variables
Changed paths:
engines/mediastation/mediascript/variable.cpp
engines/mediastation/mediascript/variable.h
diff --git a/engines/mediastation/mediascript/variable.cpp b/engines/mediastation/mediascript/variable.cpp
index b7dbc685d2a..334bf7525b5 100644
--- a/engines/mediastation/mediascript/variable.cpp
+++ b/engines/mediastation/mediascript/variable.cpp
@@ -114,6 +114,51 @@ Variable::~Variable() {
}
}
+Operand Variable::getValue() {
+ switch (_type) {
+ case kVariableTypeEmpty: {
+ error("Variable::getValue(): Attempt to get value from an empty variable");
+ }
+
+ case kVariableTypeCollection: {
+ // TODO: Determine if any scripts actually try to do this.
+ error("Variable::getValue(): Returning a collection is not implemented");
+ break;
+ }
+
+ case kVariableTypeString: {
+ Operand returnValue(kOperandTypeString);
+ returnValue.putString(_value.string);
+ return returnValue;
+ }
+
+ case kVariableTypeAssetId: {
+ Operand returnValue(kOperandTypeAssetId);
+ returnValue.putAsset(_value.assetId);
+ return returnValue;
+ }
+
+ case kVariableTypeBoolean: {
+ // TODO: Is this value type correct?
+ // Shouldn't matter too much, though, since it's still an integer type.
+ Operand returnValue(kOperandTypeLiteral1);
+ returnValue.putInteger(_value.b);
+ return returnValue;
+ }
+
+ case kVariableTypeLiteral: {
+ // Shouldn't matter too much, though, since it's still an integer type.
+ Operand returnValue(kOperandTypeLiteral1);
+ returnValue.putInteger(_value.datum->u.i);
+ return returnValue;
+ }
+
+ default: {
+ error("Variable::getValue(): Attempt to get value from unknown variable type 0x%x", static_cast<uint>(_type));
+ }
+ }
+}
+
Operand Variable::callMethod(BuiltInMethod method, Common::Array<Operand> &args) {
switch (_type) {
case kVariableTypeAssetId: {
diff --git a/engines/mediastation/mediascript/variable.h b/engines/mediastation/mediascript/variable.h
index ad60098a04f..725ad02b621 100644
--- a/engines/mediastation/mediascript/variable.h
+++ b/engines/mediastation/mediascript/variable.h
@@ -71,6 +71,8 @@ public:
Variable();
Variable(Chunk &chunk, bool readId = true);
+
+ Operand getValue();
Operand callMethod(BuiltInMethod method, Common::Array<Operand> &args);
~Variable();
};
Commit: 75ab2558bfec37afad2db8520236b2500e8c6fed
https://github.com/scummvm/scummvm/commit/75ab2558bfec37afad2db8520236b2500e8c6fed
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T17:03:08-05:00
Commit Message:
MEDIASTATION: Remove unused forward declaration
Changed paths:
engines/mediastation/mediascript/operand.h
diff --git a/engines/mediastation/mediascript/operand.h b/engines/mediastation/mediascript/operand.h
index 8e97ad69246..05351681906 100644
--- a/engines/mediastation/mediascript/operand.h
+++ b/engines/mediastation/mediascript/operand.h
@@ -28,7 +28,6 @@
namespace MediaStation {
-class Function;
class Asset;
enum OperandType {
Commit: 6b493efa04824d5d004675fea2549f35733dcc58
https://github.com/scummvm/scummvm/commit/6b493efa04824d5d004675fea2549f35733dcc58
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T17:05:44-05:00
Commit Message:
MEDIASTATION: Upgrade finding an unknown variable type to an error
I am pretty confident all the variable types are found now, so I anything else popping up likely indicates a bug.
Changed paths:
engines/mediastation/mediascript/variable.cpp
diff --git a/engines/mediastation/mediascript/variable.cpp b/engines/mediastation/mediascript/variable.cpp
index 334bf7525b5..7b6c6809707 100644
--- a/engines/mediastation/mediascript/variable.cpp
+++ b/engines/mediastation/mediascript/variable.cpp
@@ -79,7 +79,7 @@ Variable::Variable(Chunk &chunk, bool readId) {
}
default: {
- warning("Variable::Variable(): Got unknown variable value type 0x%x", static_cast<uint>(_type));
+ error("Variable::Variable(): Got unknown variable value type 0x%x", static_cast<uint>(_type));
_value.datum = new Datum(chunk);
}
}
Commit: e626719453e7fdc9055be194cb6a22ba3c105fd5
https://github.com/scummvm/scummvm/commit/e626719453e7fdc9055be194cb6a22ba3c105fd5
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T17:09:28-05:00
Commit Message:
MEDIASTATION: Implement equality testing between operands.
Also imlemented here is a getLiteralValue method that dereferences and variable reference, so we can do equality and other comparisons directly.
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
engines/mediastation/mediascript/operand.cpp
engines/mediastation/mediascript/operand.h
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 461d3aad906..0018e4c77d8 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -160,6 +160,16 @@ Operand CodeChunk::executeNextStatement() {
return Operand();
}
+ case kOpcodeEquals: {
+ Operand value1 = executeNextStatement();
+ Operand value2 = executeNextStatement();
+
+ // TODO: Confirm this is the correct value type?
+ Operand returnValue(kOperandTypeLiteral1);
+ bool equal = (value1 == value2);
+ returnValue.putInteger(static_cast<uint>(equal));
+ return returnValue;
+ }
default: {
error("CodeChunk::getNextStatement(): Got unknown opcode 0x%x (%d)", opcode, opcode);
diff --git a/engines/mediastation/mediascript/operand.cpp b/engines/mediastation/mediascript/operand.cpp
index 92112b09937..7a29bd3a105 100644
--- a/engines/mediastation/mediascript/operand.cpp
+++ b/engines/mediastation/mediascript/operand.cpp
@@ -244,6 +244,39 @@ uint32 Operand::getAssetId() {
}
}
+Operand Operand::getLiteralValue() {
+ // This function dereferences any variable to get the actual
+ // "direct" value (a literal asset ID or otherwise).
+ if (_type == kOperandTypeVariableDeclaration) {
+ return _u.variable->getValue();
+ } else {
+ return *this;
+ }
+}
+
+bool Operand::operator==(Operand &other) {
+ Operand lhs = getLiteralValue();
+ Operand rhs = getLiteralValue();
+ // TODO: Maybe some better type checking here. If the types being compared end up being incompatible, the respective get
+ // method on the rhs will raise the error. But better might be checking
+ // both before we try getting values to report a more descriptive error.
+ switch (lhs.getType()) {
+ case kOperandTypeLiteral1:
+ case kOperandTypeLiteral2:
+ return lhs.getInteger() == rhs.getInteger();
+
+ case kOperandTypeFloat1:
+ case kOperandTypeFloat2:
+ return lhs.getDouble() == rhs.getDouble();
+
+ case kOperandTypeString:
+ return *lhs.getString() == *rhs.getString();
+
+ default:
+ error("Operand::operator==(): Unsupported operand types %d and %d", static_cast<uint>(lhs.getType()), static_cast<uint>(rhs.getType()));
+ }
+}
+
Operand Operand::operator-(const Operand &other) const {
Operand returnValue;
if (this->_type == kOperandTypeLiteral1 && other._type == kOperandTypeLiteral1) {
diff --git a/engines/mediastation/mediascript/operand.h b/engines/mediastation/mediascript/operand.h
index 05351681906..b511d9dfb34 100644
--- a/engines/mediastation/mediascript/operand.h
+++ b/engines/mediastation/mediascript/operand.h
@@ -78,6 +78,9 @@ public:
Asset *getAsset();
uint32 getAssetId();
+ Operand getLiteralValue();
+
+ bool operator==(Operand &other);
Operand operator-(const Operand &other) const;
private:
Commit: 81dda73b58dea6b09f3a069267e9ecd2f277ded7
https://github.com/scummvm/scummvm/commit/81dda73b58dea6b09f3a069267e9ecd2f277ded7
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T17:48:00-05:00
Commit Message:
MEDIASTATION: Stub out mystery IBM/Crayola "drawing" function
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 0018e4c77d8..c2529c189eb 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -368,6 +368,14 @@ Operand CodeChunk::callBuiltInFunction(BuiltInFunction id, Common::Array<Operand
break;
}
+ case kDrawingFunction: {
+ // Not entirely sure what this function does, but it seems like a way to
+ // call into some drawing functions built into the IBM/Crayola executable.
+ warning("CodeChunk::callBuiltInFunction(): Built-in drawing function not implemented");
+ return Operand();
+ break;
+ }
+
default: {
error("CodeChunk::callBuiltInFunction(): Got unknown built-in function ID %d", id);
}
Commit: edce7ea0e3f1035d39ce5f03f81c56fae8bae2ae
https://github.com/scummvm/scummvm/commit/edce7ea0e3f1035d39ce5f03f81c56fae8bae2ae
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T17:53:09-05:00
Commit Message:
MEDIASTATION: Implement >= operator for operands
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
engines/mediastation/mediascript/operand.cpp
engines/mediastation/mediascript/operand.h
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index c2529c189eb..9ecca5454de 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -171,6 +171,17 @@ Operand CodeChunk::executeNextStatement() {
return returnValue;
}
+ case kOpcodeGreaterThanOrEqualTo: {
+ Operand value1 = executeNextStatement();
+ Operand value2 = executeNextStatement();
+
+ // TODO: Confirm this is the correct value type?
+ Operand returnValue(kOperandTypeLiteral1);
+ bool greaterThanOrEqualTo = value1 >= value2;
+ returnValue.putInteger(static_cast<uint>(greaterThanOrEqualTo));
+ return returnValue;
+ }
+
default: {
error("CodeChunk::getNextStatement(): Got unknown opcode 0x%x (%d)", opcode, opcode);
}
diff --git a/engines/mediastation/mediascript/operand.cpp b/engines/mediastation/mediascript/operand.cpp
index 7a29bd3a105..97019cec655 100644
--- a/engines/mediastation/mediascript/operand.cpp
+++ b/engines/mediastation/mediascript/operand.cpp
@@ -277,6 +277,25 @@ bool Operand::operator==(Operand &other) {
}
}
+bool Operand::operator>=(Operand &other) {
+ Operand lhs = getLiteralValue();
+ Operand rhs = getLiteralValue();
+ // If the types being compared end up being incompatible, the respective get
+ // method on the rhs will raise the error.
+ switch (lhs.getType()) {
+ case kOperandTypeLiteral1:
+ case kOperandTypeLiteral2:
+ return lhs.getInteger() >= rhs.getInteger();
+
+ case kOperandTypeFloat1:
+ case kOperandTypeFloat2:
+ return lhs.getDouble() >= rhs.getDouble();
+
+ default:
+ error("Operand::operator>=(): Unsupported operand types %d and %d", static_cast<uint>(lhs.getType()), static_cast<uint>(rhs.getType()));
+ }
+}
+
Operand Operand::operator-(const Operand &other) const {
Operand returnValue;
if (this->_type == kOperandTypeLiteral1 && other._type == kOperandTypeLiteral1) {
diff --git a/engines/mediastation/mediascript/operand.h b/engines/mediastation/mediascript/operand.h
index b511d9dfb34..a833258afcc 100644
--- a/engines/mediastation/mediascript/operand.h
+++ b/engines/mediastation/mediascript/operand.h
@@ -81,6 +81,7 @@ public:
Operand getLiteralValue();
bool operator==(Operand &other);
+ bool operator>=(Operand &other);
Operand operator-(const Operand &other) const;
private:
Commit: fd4d85ecd07afdcfb2100fea981d484cb5f9cba9
https://github.com/scummvm/scummvm/commit/fd4d85ecd07afdcfb2100fea981d484cb5f9cba9
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T18:12:15-05:00
Commit Message:
MEDIASTATION: Provide a more descriptive error message if we get an empty operand
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 9ecca5454de..468f8b7dc46 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -295,6 +295,11 @@ void CodeChunk::putVariable(uint32 id, VariableScope scope, Operand value) {
}
switch (value.getType()) {
+ case kOperandTypeEmpty: {
+ error("CodeChunk::putVariable(): Cannot assign an empty operand to a variable");
+ break;
+ }
+
case kOperandTypeLiteral1:
case kOperandTypeLiteral2: {
variable->_value.i = value.getInteger();
Commit: 6b8e9a67033bb7d972c93716c0a957e8ce6b241d
https://github.com/scummvm/scummvm/commit/6b8e9a67033bb7d972c93716c0a957e8ce6b241d
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T18:17:52-05:00
Commit Message:
MEDIASTATION: Make script debug output a bit more understandable
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 468f8b7dc46..1087ed46c75 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -59,7 +59,7 @@ Operand CodeChunk::executeNextStatement() {
}
InstructionType instructionType = InstructionType(Datum(*_bytecode).u.i);
- debugC(8, kDebugScript, " instructionType = %d", static_cast<uint>(instructionType));
+ debugC(9, kDebugScript, " instructionType = %d", static_cast<uint>(instructionType));
switch (instructionType) {
case kInstructionTypeEmpty: {
return Operand();
@@ -191,12 +191,12 @@ Operand CodeChunk::executeNextStatement() {
case kInstructionTypeOperand: {
OperandType operandType = static_cast<OperandType>(Datum(*_bytecode).u.i);
- debugC(8, kDebugScript, " *** Operand %d ***", static_cast<uint>(operandType));
Operand operand(operandType);
switch (operandType) {
// TODO: Add clearer debugging printouts for these.
case kOperandTypeAssetId: {
uint32 assetId = Datum(*_bytecode).u.i;
+ debugC(8, kDebugScript, " Asset ID: %d", assetId);
operand.putAsset(assetId);
return operand;
}
@@ -205,6 +205,7 @@ Operand CodeChunk::executeNextStatement() {
case kOperandTypeLiteral2:
case kOperandTypeDollarSignVariable: {
int literal = Datum(*_bytecode).u.i;
+ debugC(8, kDebugScript, " Literal: %d", literal);
operand.putInteger(literal);
return operand;
}
@@ -212,12 +213,14 @@ Operand CodeChunk::executeNextStatement() {
case kOperandTypeFloat1:
case kOperandTypeFloat2: {
double d = Datum(*_bytecode).u.f;
+ debugC(8, kDebugScript, " Float: %f", d);
operand.putDouble(d);
return operand;
}
case kOperandTypeFunction: {
uint functionId = Datum(*_bytecode).u.i;
+ debugC(8, kDebugScript, " Function ID: %d", functionId);
operand.putFunction(functionId);
return operand;
}
@@ -230,6 +233,7 @@ Operand CodeChunk::executeNextStatement() {
_bytecode->read(buffer, size);
buffer[size] = '\0';
Common::String *string = new Common::String(buffer);
+ debugC(8, kDebugScript, " String: %s", string->c_str());
operand.putString(string);
delete[] buffer;
return operand;
Commit: aa26a6a3d9aae8969281425fde77449ca3696841
https://github.com/scummvm/scummvm/commit/aa26a6a3d9aae8969281425fde77449ca3696841
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T18:18:42-05:00
Commit Message:
MEDIASTATION: Implement Image spatialShow script method
Changed paths:
engines/mediastation/assets/image.cpp
diff --git a/engines/mediastation/assets/image.cpp b/engines/mediastation/assets/image.cpp
index 24eee8c5ef0..86b232f9d2e 100644
--- a/engines/mediastation/assets/image.cpp
+++ b/engines/mediastation/assets/image.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "mediastation/mediastation.h"
#include "mediastation/assets/image.h"
namespace MediaStation {
@@ -30,10 +31,16 @@ Image::~Image() {
Operand Image::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args) {
switch (methodId) {
- // TODO: Add methods here.
+ case kSpatialShowMethod: {
+ assert(args.empty());
+ _isActive = true;
+ g_engine->addPlayingAsset(this);
+ return Operand();
+ break;
+ }
default: {
- error("Got unimplemented method ID %d", methodId);
+ error("Image::callMethod(): Got unimplemented method ID %d", methodId);
}
}
}
Commit: 9be5eda0cb9b5693b5f80f12fea50c8ed86f7926
https://github.com/scummvm/scummvm/commit/9be5eda0cb9b5693b5f80f12fea50c8ed86f7926
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-01-11T21:16:39-05:00
Commit Message:
MEDIASTATION: Implement better interface for getting assets across contexts.
In several titles, there are assets loaded from multiple contexts
at once, with contexts being loaded and unloaded. This change doesn't
keep a global list of loaded assets, but instead looks in each
context when it needs to find an asset. This is also likely closer
to the behavior of the original, though the original also used the
information in BOOT.STM to find assets in contexts that aren't
currently loaded, which we aren't doing currently.
Changed paths:
engines/mediastation/context.cpp
engines/mediastation/context.h
engines/mediastation/mediascript/codechunk.cpp
engines/mediastation/mediascript/operand.cpp
engines/mediastation/mediastation.cpp
engines/mediastation/mediastation.h
diff --git a/engines/mediastation/context.cpp b/engines/mediastation/context.cpp
index 0036136929e..9fe96471398 100644
--- a/engines/mediastation/context.cpp
+++ b/engines/mediastation/context.cpp
@@ -77,6 +77,19 @@ Context::~Context() {
_parameters = nullptr;
}
+Asset *Context::getAssetById(uint assetId) {
+ return _assets.getValOrDefault(assetId);
+}
+
+Asset *Context::getAssetByChunkReference(uint chunkReference) {
+ return _assetsByChunkReference.getValOrDefault(chunkReference);
+}
+
+
+Function *Context::getFunctionById(uint functionId) {
+ return _functions.getValOrDefault(functionId);
+}
+
bool Context::readPreamble() {
uint16 signature = _stream->readUint16LE();
if (signature != 0x4949) { // "II"
@@ -138,9 +151,14 @@ void Context::readAssetInFirstSubfile(Chunk &chunk) {
}
// TODO: Make sure this is not an asset link.
- Asset *asset = g_engine->_assetsByChunkReference.getValOrDefault(chunk._id);
+ Asset *asset = getAssetByChunkReference(chunk._id);
if (asset == nullptr) {
- error("Context::readAssetInFirstSubfile(): Asset for chunk \"%s\" (0x%x) does not exist or has not been read yet in this title. (@0x%llx)", tag2str(chunk._id), chunk._id, static_cast<long long int>(chunk.pos()));
+ // We should only need to look in the global scope when there is an
+ // install cache (INSTALL.CXT).
+ asset = g_engine->getAssetByChunkReference(chunk._id);
+ if (asset == nullptr) {
+ error("Context::readAssetInFirstSubfile(): Asset for chunk \"%s\" (0x%x) does not exist or has not been read yet in this title. (@0x%llx)", tag2str(chunk._id), chunk._id, static_cast<long long int>(chunk.pos()));
+ }
}
debugC(5, kDebugLoading, "\nContext::readAssetInFirstSubfile(): Got asset with chunk ID %s in first subfile (type: 0x%x) (@0x%llx)", tag2str(chunk._id), static_cast<uint>(asset->type()), static_cast<long long int>(chunk.pos()));
asset->readChunk(chunk);
@@ -148,9 +166,14 @@ void Context::readAssetInFirstSubfile(Chunk &chunk) {
void Context::readAssetFromLaterSubfile(Subfile &subfile) {
Chunk chunk = subfile.nextChunk();
- Asset *asset = g_engine->_assetsByChunkReference.getValOrDefault(chunk._id);
+ Asset *asset = getAssetByChunkReference(chunk._id);
if (asset == nullptr) {
- error("Context::readAssetFromLaterSubfile(): Asset for chunk \"%s\" (0x%x) does not exist or has not been read yet in this title. (@0x%llx)", tag2str(chunk._id), chunk._id, static_cast<long long int>(chunk.pos()));
+ // We should only need to look in the global scope when there is an
+ // install cache (INSTALL.CXT).
+ asset = g_engine->getAssetByChunkReference(chunk._id);
+ if (asset == nullptr) {
+ error("Context::readAssetFromLaterSubfile(): Asset for chunk \"%s\" (0x%x) does not exist or has not been read yet in this title. (@0x%llx)", tag2str(chunk._id), chunk._id, static_cast<long long int>(chunk.pos()));
+ }
}
debugC(5, kDebugLoading, "\nContext::readAssetFromLaterSubfile(): Got asset with chunk ID %s in later subfile (type: 0x%x) (@0x%llx)", tag2str(chunk._id), asset->type(), static_cast<long long int>(chunk.pos()));
asset->readSubfile(subfile, chunk);
@@ -250,20 +273,20 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
error("Context::readHeaderSection(): No class for asset type 0x%x (@0x%llx)", static_cast<uint>(header->_type), static_cast<long long int>(chunk.pos()));
}
- if (g_engine->_assets.contains(header->_id)) {
+ if (g_engine->getAssetById(header->_id)) {
error("Context::readHeaderSection(): Asset with ID 0x%d was already defined in this title", header->_id);
}
- g_engine->_assets.setVal(header->_id, asset);
+ _assets.setVal(header->_id, asset);
if (header->_chunkReference != 0) {
debugC(5, kDebugLoading, "Context::readHeaderSection(): Storing asset with chunk ID \"%s\" (0x%x)", tag2str(header->_chunkReference), header->_chunkReference);
- g_engine->_assetsByChunkReference.setVal(header->_chunkReference, asset);
+ _assetsByChunkReference.setVal(header->_chunkReference, asset);
}
// TODO: Store the movie chunk references better.
if (header->_audioChunkReference != 0) {
- g_engine->_assetsByChunkReference.setVal(header->_audioChunkReference, asset);
+ _assetsByChunkReference.setVal(header->_audioChunkReference, asset);
}
if (header->_animationChunkReference != 0) {
- g_engine->_assetsByChunkReference.setVal(header->_animationChunkReference, asset);
+ _assetsByChunkReference.setVal(header->_animationChunkReference, asset);
}
// TODO: This datum only appears sometimes.
uint unk2 = Datum(chunk).u.i;
@@ -273,7 +296,7 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
case kContextFunctionSection: {
Function *function = new Function(chunk);
- g_engine->_functions.setVal(function->_id, function);
+ _functions.setVal(function->_id, function);
if (!g_engine->isFirstGenerationEngine()) {
uint endingFlag = Datum(chunk).u.i;
if (endingFlag != 0) {
diff --git a/engines/mediastation/context.h b/engines/mediastation/context.h
index fb7093513c4..71a4e20b834 100644
--- a/engines/mediastation/context.h
+++ b/engines/mediastation/context.h
@@ -57,7 +57,15 @@ public:
// represents is now an asset in itself.
AssetHeader *_screenAsset = nullptr;
+ Asset *getAssetById(uint assetId);
+ Asset *getAssetByChunkReference(uint chunkReference);
+ Function *getFunctionById(uint functionId);
+
private:
+ Common::HashMap<uint, Asset *> _assets;
+ Common::HashMap<uint, Function *> _functions;
+ Common::HashMap<uint, Asset *> _assetsByChunkReference;
+
void readOldStyleHeaderSections(Subfile &subfile, Chunk &chunk);
void readNewStyleHeaderSections(Subfile &subfile, Chunk &chunk);
bool readHeaderSection(Subfile &subfile, Chunk &chunk);
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 1087ed46c75..170c77d8de9 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -92,7 +92,7 @@ Operand CodeChunk::executeNextStatement() {
// Call the routine.
debugC(5, kDebugScript, "SCRIPT: [ %d ]( %d args )", functionId, parameterCount);
Operand returnValue;
- Function *function = g_engine->_functions.getValOrDefault(functionId);
+ Function *function = g_engine->getFunctionById(functionId);
if (function != nullptr) {
// This is a title-defined function.
returnValue = function->execute(args);
diff --git a/engines/mediastation/mediascript/operand.cpp b/engines/mediastation/mediascript/operand.cpp
index 97019cec655..eef15c218e4 100644
--- a/engines/mediastation/mediascript/operand.cpp
+++ b/engines/mediastation/mediascript/operand.cpp
@@ -212,13 +212,13 @@ Asset *Operand::getAsset() {
if (_u.assetId == 0) {
return nullptr;
} else {
- return g_engine->_assets.getVal(_u.assetId);
+ return g_engine->getAssetById(_u.assetId);
}
}
case kOperandTypeVariableDeclaration: {
assert(_u.variable->_type == kVariableTypeAssetId);
- return g_engine->_assets.getVal(_u.variable->_value.assetId);
+ return g_engine->getAssetById(_u.variable->_value.assetId);
}
default: {
diff --git a/engines/mediastation/mediastation.cpp b/engines/mediastation/mediastation.cpp
index cf57eea4954..dc66ad89c01 100644
--- a/engines/mediastation/mediastation.cpp
+++ b/engines/mediastation/mediastation.cpp
@@ -63,24 +63,45 @@ MediaStationEngine::~MediaStationEngine() {
delete _boot;
_boot = nullptr;
- for (auto it = _assets.begin(); it != _assets.end(); ++it) {
+ for (auto it = _loadedContexts.begin(); it != _loadedContexts.end(); ++it) {
delete it->_value;
}
- _assets.clear();
- _assetsByChunkReference.clear();
-
- for (auto it = _functions.begin(); it != _functions.end(); ++it) {
- delete it->_value;
- }
- _functions.clear();
+ _loadedContexts.clear();
for (auto it = _variables.begin(); it != _variables.end(); ++it) {
delete it->_value;
}
_variables.clear();
+}
+
+Asset *MediaStationEngine::getAssetById(uint assetId) {
+ for (auto it = _loadedContexts.begin(); it != _loadedContexts.end(); ++it) {
+ Asset *asset = it->_value->getAssetById(assetId);
+ if (asset != nullptr) {
+ return asset;
+ }
+ }
+ return nullptr;
+}
+
+Asset *MediaStationEngine::getAssetByChunkReference(uint chunkReference) {
+ for (auto it = _loadedContexts.begin(); it != _loadedContexts.end(); ++it) {
+ Asset *asset = it->_value->getAssetByChunkReference(chunkReference);
+ if (asset != nullptr) {
+ return asset;
+ }
+ }
+ return nullptr;
+}
- delete _root;
- _root = nullptr;
+Function *MediaStationEngine::getFunctionById(uint functionId) {
+ for (auto it = _loadedContexts.begin(); it != _loadedContexts.end(); ++it) {
+ Function *function = it->_value->getFunctionById(functionId);
+ if (function != nullptr) {
+ return function;
+ }
+ }
+ return nullptr;
}
uint32 MediaStationEngine::getFeatures() const {
@@ -116,7 +137,7 @@ Common::Error MediaStationEngine::run() {
//Context *root = nullptr;
uint32 rootContextId = _boot->getRootContextId();
if (rootContextId != 0) {
- _root = loadContext(rootContextId);
+ loadContext(rootContextId);
} else {
warning("MediaStation::run(): Title has no root context");
}
@@ -210,6 +231,11 @@ Context *MediaStationEngine::loadContext(uint32 contextId) {
error("Cannot load contexts before BOOT.STM is read");
}
+ if (_loadedContexts.contains(contextId)) {
+ warning("MediaStationEngine::loadContext(): Context 0x%x already loaded, returning existing context", contextId);
+ return _loadedContexts.getVal(contextId);
+ }
+
// GET THE FILE ID.
SubfileDeclaration *subfileDeclaration = _boot->_subfileDeclarations.getValOrDefault(contextId);
if (subfileDeclaration == nullptr) {
@@ -234,8 +260,7 @@ Context *MediaStationEngine::loadContext(uint32 contextId) {
// LOAD THE CONTEXT.
Common::Path entryCxtFilepath = Common::Path(*fileName);
Context *context = new Context(entryCxtFilepath);
-
- // SET THE VARIABLES.
+ _loadedContexts.setVal(contextId, context);
return context;
}
@@ -294,7 +319,6 @@ void MediaStationEngine::branchToScreen(uint32 contextId) {
debugC(5, kDebugScript, "No context entry event handler");
}
}
- _currentContext = context;
}
Asset *MediaStationEngine::findAssetToAcceptMouseEvents(Common::Point point) {
@@ -303,8 +327,7 @@ Asset *MediaStationEngine::findAssetToAcceptMouseEvents(Common::Point point) {
// actually the lowest asset.
int lowestZIndex = INT_MAX;
- for (auto it = _assets.begin(); it != _assets.end(); ++it) {
- Asset *asset = it->_value;
+ for (Asset *asset : _assetsPlaying) {
// TODO: Currently only hotspots are found, but other asset types can
// likely get mouse events too.
if (asset->type() == kAssetTypeHotspot) {
@@ -325,7 +348,6 @@ Asset *MediaStationEngine::findAssetToAcceptMouseEvents(Common::Point point) {
}
}
}
-
return intersectingAsset;
}
diff --git a/engines/mediastation/mediastation.h b/engines/mediastation/mediastation.h
index 3b972d25ac5..ffda09b0b01 100644
--- a/engines/mediastation/mediastation.h
+++ b/engines/mediastation/mediastation.h
@@ -76,12 +76,13 @@ public:
void setPalette(Asset *palette);
void addPlayingAsset(Asset *assetToAdd);
+ Asset *getAssetById(uint assetId);
+ Asset *getAssetByChunkReference(uint chunkReference);
+ Function *getFunctionById(uint functionId);
+
Operand callMethod(BuiltInMethod methodId, Common::Array<Operand> &args);
- Common::HashMap<uint, Asset *> _assets;
- Common::HashMap<uint, Function *> _functions;
Common::HashMap<uint32, Variable *> _variables;
- Common::HashMap<uint, Asset *> _assetsByChunkReference;
- Context *_currentContext = nullptr;
+
Graphics::Screen *_screen = nullptr;
Audio::Mixer *_mixer = nullptr;
@@ -99,7 +100,7 @@ private:
Common::RandomSource _randomSource;
Boot *_boot = nullptr;
Common::Array<Asset *> _assetsPlaying;
- Context *_root = nullptr;
+ Common::HashMap<uint, Context *> _loadedContexts;
Context *loadContext(uint32 contextId);
void setPaletteFromHeader(AssetHeader *header);
More information about the Scummvm-git-logs
mailing list