[Scummvm-git-logs] scummvm master -> 9d717b633d7bf0c2c3b8846b5ef5d51a2474788b
npjg
noreply at scummvm.org
Thu Mar 13 23:18:28 UTC 2025
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
19e086fb0c MEDIASTATION: Implement sprite frame mapping field
5e51f63e86 MEDIASTATION: Show first sprite frames properly
09bbc7e798 MEDIASTATION: Let sprites & images move under script control
3421caee82 MEDIASTATION: Make local script vars accessible to sub-chunks
c3b9cad220 MEDIASTATION: Fix hotspot refresh recursion in scripts
4d620f729a MEDIASTATION: Stub another transition type
9d717b633d MEDIASTATION: Support referencing functions in variables
Commit: 19e086fb0cfbc151dc49466615fc7bbd43c579d5
https://github.com/scummvm/scummvm/commit/19e086fb0cfbc151dc49466615fc7bbd43c579d5
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-03-13T18:54:02-04:00
Commit Message:
MEDIASTATION: Implement sprite frame mapping field
This allows scripts to manually set a frame in the sprite.
Changed paths:
engines/mediastation/assetheader.cpp
engines/mediastation/assetheader.h
engines/mediastation/assets/sprite.cpp
engines/mediastation/mediascript/scriptconstants.cpp
engines/mediastation/mediascript/scriptconstants.h
diff --git a/engines/mediastation/assetheader.cpp b/engines/mediastation/assetheader.cpp
index ce6be09a3ce..2af6e18635e 100644
--- a/engines/mediastation/assetheader.cpp
+++ b/engines/mediastation/assetheader.cpp
@@ -354,6 +354,17 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
break;
}
+ case kAssetHeaderSpriteFrameMapping: {
+ uint32 externalFrameId = Datum(chunk).u.i;
+ uint32 internalFrameId = Datum(chunk).u.i;
+ uint32 unk1 = Datum(chunk).u.i;
+ if (unk1 != internalFrameId) {
+ warning("AssetHeader::readSection(): Repeated internalFrameId doesn't match");
+ }
+ _spriteFrameMapping.setVal(externalFrameId, internalFrameId);
+ break;
+ }
+
default:
error("AssetHeader::readSection(): Unknown section type 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
}
diff --git a/engines/mediastation/assetheader.h b/engines/mediastation/assetheader.h
index 9d184948d2f..29cbbbce553 100644
--- a/engines/mediastation/assetheader.h
+++ b/engines/mediastation/assetheader.h
@@ -131,7 +131,10 @@ enum AssetHeaderSectionType {
kAssetHeaderTextPosition = 0x25f,
kAssetHeaderTextUnk1 = 0x262,
kAssetHeaderTextUnk2 = 0x263,
- kAssetHeaderTextCharacterClass = 0x0266
+ kAssetHeaderTextCharacterClass = 0x0266,
+
+ // SPRITE FIELDS.
+ kAssetHeaderSpriteFrameMapping = 0x03e9
};
enum TextJustification {
@@ -189,6 +192,7 @@ public:
uint32 _stageId = 0;
SoundEncoding _soundEncoding;
uint32 _chunkCount = 0;
+ Common::HashMap<uint32, uint32> _spriteFrameMapping;
// PATH FIELDS.
uint32 _dissolveFactor = 0;
diff --git a/engines/mediastation/assets/sprite.cpp b/engines/mediastation/assets/sprite.cpp
index 533ef3011be..751f643f34d 100644
--- a/engines/mediastation/assets/sprite.cpp
+++ b/engines/mediastation/assets/sprite.cpp
@@ -122,6 +122,14 @@ Operand Sprite::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args)
return Operand();
}
+ case kSetSpriteFrameByIdMethod: {
+ assert(args.size() == 1);
+ uint32 externalFrameId = args[0].getInteger();
+ uint32 internalFrameId = _header->_spriteFrameMapping.getVal(externalFrameId);
+ showFrame(_frames[internalFrameId]);
+ return Operand();
+ }
+
case kIsPlayingMethod: {
Operand returnValue(kOperandTypeLiteral1);
returnValue.putInteger(static_cast<int>(_isPlaying));
diff --git a/engines/mediastation/mediascript/scriptconstants.cpp b/engines/mediastation/mediascript/scriptconstants.cpp
index ee6e91000c9..7446848e9e8 100644
--- a/engines/mediastation/mediascript/scriptconstants.cpp
+++ b/engines/mediastation/mediascript/scriptconstants.cpp
@@ -161,6 +161,8 @@ const char *builtInMethodToStr(BuiltInMethod method) {
return "IsVisible";
case kMovieResetMethod:
return "MovieReset";
+ case kSetSpriteFrameByIdMethod:
+ return "SetSpriteFrameById";
case kSetCurrentClipMethod:
return "SetCurrentClip";
case kSetWorldSpaceExtentMethod:
diff --git a/engines/mediastation/mediascript/scriptconstants.h b/engines/mediastation/mediascript/scriptconstants.h
index 0228a2f047f..d03d5672fb1 100644
--- a/engines/mediastation/mediascript/scriptconstants.h
+++ b/engines/mediastation/mediascript/scriptconstants.h
@@ -113,6 +113,7 @@ enum BuiltInMethod {
// SPRITE METHODS.
kMovieResetMethod = 219, // PARAMS: 0
+ kSetSpriteFrameByIdMethod = 220, // PARAMS: 1
kSetCurrentClipMethod = 221, // PARAMS: 0-1
// STAGE METHODS.
Commit: 5e51f63e86e28d467ddb4b1b493fecd853ba84f5
https://github.com/scummvm/scummvm/commit/5e51f63e86e28d467ddb4b1b493fecd853ba84f5
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-03-13T18:54:02-04:00
Commit Message:
MEDIASTATION: Show first sprite frames properly
Changed paths:
engines/mediastation/assets/sprite.cpp
engines/mediastation/assets/sprite.h
diff --git a/engines/mediastation/assets/sprite.cpp b/engines/mediastation/assets/sprite.cpp
index 751f643f34d..df7b17ae181 100644
--- a/engines/mediastation/assets/sprite.cpp
+++ b/engines/mediastation/assets/sprite.cpp
@@ -70,6 +70,7 @@ Sprite::Sprite(AssetHeader *header) : Asset(header) {
if (header->_startup == kAssetStartupActive) {
setActive();
_isShowing = true;
+ _showFirstFrame = true;
}
}
@@ -117,7 +118,10 @@ Operand Sprite::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args)
}
case kSetCurrentClipMethod: {
- assert(args.empty());
+ assert(args.size() <= 1);
+ if (args.size() == 1 && args[0].getInteger() != 0) {
+ error("Sprite::callMethod(): (%d) setClip() called with unhandled arg: %d", _header->_id, args[0].getInteger());
+ }
setCurrentClip();
return Operand();
}
@@ -236,6 +240,12 @@ void Sprite::readChunk(Chunk &chunk) {
}
void Sprite::updateFrameState() {
+ if (_showFirstFrame) {
+ showFrame(_frames[0]);
+ _showFirstFrame = false;
+ return;
+ }
+
if (!_isActive) {
return;
}
diff --git a/engines/mediastation/assets/sprite.h b/engines/mediastation/assets/sprite.h
index 9156a5919fe..196bf7762d8 100644
--- a/engines/mediastation/assets/sprite.h
+++ b/engines/mediastation/assets/sprite.h
@@ -76,6 +76,7 @@ public:
private:
Common::Array<SpriteFrame *> _frames;
SpriteFrame *_activeFrame = nullptr;
+ bool _showFirstFrame = true;
bool _isShowing = false;
bool _isPlaying = false;
uint _currentFrameIndex = 0;
Commit: 09bbc7e7982c21df82004df380f3f77b4d5f3a72
https://github.com/scummvm/scummvm/commit/09bbc7e7982c21df82004df380f3f77b4d5f3a72
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-03-13T18:54:03-04:00
Commit Message:
MEDIASTATION: Let sprites & images move under script control
Changed paths:
engines/mediastation/assets/hotspot.cpp
engines/mediastation/assets/image.cpp
engines/mediastation/assets/image.h
engines/mediastation/assets/sprite.cpp
engines/mediastation/assets/sprite.h
engines/mediastation/mediastation.cpp
engines/mediastation/mediastation.h
diff --git a/engines/mediastation/assets/hotspot.cpp b/engines/mediastation/assets/hotspot.cpp
index 87b66f3c4f5..f0ae58cd367 100644
--- a/engines/mediastation/assets/hotspot.cpp
+++ b/engines/mediastation/assets/hotspot.cpp
@@ -92,6 +92,18 @@ Operand Hotspot::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args
return returnValue;
}
+ case kTriggerAbsXPositionMethod: {
+ Operand returnValue(kOperandTypeLiteral1);
+ returnValue.putInteger(g_engine->_mousePos.x);
+ return returnValue;
+ }
+
+ case kTriggerAbsYPositionMethod: {
+ Operand returnValue(kOperandTypeLiteral1);
+ returnValue.putInteger(g_engine->_mousePos.y);
+ return returnValue;
+ }
+
default:
error("Hotspot::callMethod(): Got unimplemented method ID %s (%d)", builtInMethodToStr(methodId), static_cast<uint>(methodId));
}
diff --git a/engines/mediastation/assets/image.cpp b/engines/mediastation/assets/image.cpp
index c5fc1e302d9..869f73c9dd8 100644
--- a/engines/mediastation/assets/image.cpp
+++ b/engines/mediastation/assets/image.cpp
@@ -60,6 +60,27 @@ Operand Image::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args)
return Operand();
}
+ case kSpatialMoveToMethod: {
+ assert(args.size() == 2);
+
+ // Mark the previous location dirty.
+ Common::Rect bbox(getLeftTop(), _bitmap->width(), _bitmap->height());
+ g_engine->_dirtyRects.push_back(bbox);
+
+ // Update location and mark new location dirty.
+ int newXAdjust = args[0].getInteger();
+ int newYAdjust = args[1].getInteger();
+ if (_xAdjust != newXAdjust || _yAdjust != newYAdjust) {
+ _xAdjust = newXAdjust;
+ _yAdjust = newYAdjust;
+
+ bbox = Common::Rect(getLeftTop(), _bitmap->width(), _bitmap->height());
+ g_engine->_dirtyRects.push_back(bbox);
+ }
+
+ return Operand();
+ }
+
default:
error("Image::callMethod(): Got unimplemented method ID %s (%d)", builtInMethodToStr(methodId), static_cast<uint>(methodId));
}
@@ -76,6 +97,7 @@ void Image::redraw(Common::Rect &rect) {
if (!areaToRedraw.isEmpty()) {
Common::Point originOnScreen(areaToRedraw.left, areaToRedraw.top);
areaToRedraw.translate(-leftTop.x, -leftTop.y);
+ areaToRedraw.clip(Common::Rect(0, 0, _bitmap->width(), _bitmap->height()));
g_engine->_screen->simpleBlitFrom(_bitmap->_surface, areaToRedraw, originOnScreen);
}
}
@@ -94,7 +116,7 @@ void Image::spatialHide() {
}
Common::Point Image::getLeftTop() {
- return Common::Point(_header->_x + _header->_boundingBox->left, _header->_y + _header->_boundingBox->top);
+ return Common::Point(_header->_x + _header->_boundingBox->left + _xAdjust, _header->_y + _header->_boundingBox->top + _yAdjust);
}
void Image::readChunk(Chunk &chunk) {
diff --git a/engines/mediastation/assets/image.h b/engines/mediastation/assets/image.h
index 41185b4a765..4f4d502c785 100644
--- a/engines/mediastation/assets/image.h
+++ b/engines/mediastation/assets/image.h
@@ -46,6 +46,8 @@ public:
private:
Bitmap *_bitmap = nullptr;
+ int _xAdjust = 0;
+ int _yAdjust = 0;
// Script method implementations.
void spatialShow();
diff --git a/engines/mediastation/assets/sprite.cpp b/engines/mediastation/assets/sprite.cpp
index df7b17ae181..c3af44070a9 100644
--- a/engines/mediastation/assets/sprite.cpp
+++ b/engines/mediastation/assets/sprite.cpp
@@ -140,6 +140,29 @@ Operand Sprite::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args)
return returnValue;
}
+ case kSpatialMoveToMethod: {
+ assert(args.size() == 2);
+
+ // Mark the previous location dirty.
+ if (_activeFrame != nullptr) {
+ g_engine->_dirtyRects.push_back(getActiveFrameBoundingBox());
+ }
+
+ // Update the location and mark the new location dirty.
+ int newXAdjust = args[0].getInteger();
+ int newYAdjust = args[1].getInteger();
+ if (_xAdjust != newXAdjust || _yAdjust != newYAdjust) {
+ debugC(5, kDebugGraphics, "Sprite::callMethod(): (%d) Moving sprite to (%d, %d)", _header->_id, newXAdjust, newYAdjust);
+ _xAdjust = newXAdjust;
+ _yAdjust = newYAdjust;
+ if (_activeFrame != nullptr) {
+ g_engine->_dirtyRects.push_back(getActiveFrameBoundingBox());
+ }
+ }
+
+ return Operand();
+ }
+
default:
error("Sprite::callMethod(): Got unimplemented method ID %s (%d)", builtInMethodToStr(methodId), static_cast<uint>(methodId));
}
@@ -301,7 +324,8 @@ void Sprite::redraw(Common::Rect &rect) {
Common::Rect areaToRedraw = bbox.findIntersectingRect(rect);
if (!areaToRedraw.isEmpty()) {
Common::Point originOnScreen(areaToRedraw.left, areaToRedraw.top);
- areaToRedraw.translate(-_activeFrame->left() - _header->_boundingBox->left, -_activeFrame->top() - _header->_boundingBox->top);
+ areaToRedraw.translate(-_activeFrame->left() - _header->_boundingBox->left - _xAdjust, -_activeFrame->top() - _header->_boundingBox->top - _yAdjust);
+ areaToRedraw.clip(Common::Rect(0, 0, _activeFrame->width(), _activeFrame->height()));
g_engine->_screen->simpleBlitFrom(_activeFrame->_surface, areaToRedraw, originOnScreen);
}
}
@@ -323,7 +347,7 @@ Common::Rect Sprite::getActiveFrameBoundingBox() {
// The frame dimensions are relative to those of the sprite movie.
// So we must get the absolute coordinates.
Common::Rect bbox = _activeFrame->boundingBox();
- bbox.translate(_header->_boundingBox->left, _header->_boundingBox->top);
+ bbox.translate(_header->_boundingBox->left + _xAdjust, _header->_boundingBox->top + _yAdjust);
return bbox;
}
diff --git a/engines/mediastation/assets/sprite.h b/engines/mediastation/assets/sprite.h
index 196bf7762d8..1999ae819f5 100644
--- a/engines/mediastation/assets/sprite.h
+++ b/engines/mediastation/assets/sprite.h
@@ -82,6 +82,9 @@ private:
uint _currentFrameIndex = 0;
uint _nextFrameTime = 0;
+ int _xAdjust = 0;
+ int _yAdjust = 0;
+
// Method implementations.
void spatialShow();
void spatialHide();
diff --git a/engines/mediastation/mediastation.cpp b/engines/mediastation/mediastation.cpp
index 35b5289efd1..b84cbe56c80 100644
--- a/engines/mediastation/mediastation.cpp
+++ b/engines/mediastation/mediastation.cpp
@@ -200,14 +200,14 @@ void MediaStationEngine::processEvents() {
}
case Common::EVENT_MOUSEMOVE: {
+ _mousePos = g_system->getEventManager()->getMousePos();
refreshActiveHotspot();
break;
}
case Common::EVENT_KEYDOWN: {
// Even though this is a keydown event, we need to look at the mouse position.
- Common::Point mousePos = g_system->getEventManager()->getMousePos();
- Asset *hotspot = findAssetToAcceptMouseEvents(mousePos);
+ Asset *hotspot = findAssetToAcceptMouseEvents();
if (hotspot != nullptr) {
debugC(1, kDebugEvents, "EVENT_KEYDOWN (%d): Sent to hotspot %d", _event.kbd.ascii, hotspot->getHeader()->_id);
hotspot->runKeyDownEventHandlerIfExists(_event.kbd);
@@ -216,9 +216,9 @@ void MediaStationEngine::processEvents() {
}
case Common::EVENT_LBUTTONDOWN: {
- Asset *hotspot = findAssetToAcceptMouseEvents(_event.mouse);
+ Asset *hotspot = findAssetToAcceptMouseEvents();
if (hotspot != nullptr) {
- debugC(1, kDebugEvents, "EVENT_LBUTTONDOWN (%d, %d): Sent to hotspot %d", _event.mouse.x, _event.mouse.y, hotspot->getHeader()->_id);
+ debugC(1, kDebugEvents, "EVENT_LBUTTONDOWN (%d, %d): Sent to hotspot %d", _mousePos.x, _mousePos.y, hotspot->getHeader()->_id);
hotspot->runEventHandlerIfExists(kMouseDownEvent);
}
break;
@@ -252,15 +252,15 @@ void MediaStationEngine::setCursor(uint id) {
}
void MediaStationEngine::refreshActiveHotspot() {
- Asset *hotspot = findAssetToAcceptMouseEvents(_eventMan->getMousePos());
+ Asset *hotspot = findAssetToAcceptMouseEvents();
if (hotspot != _currentHotspot) {
if (_currentHotspot != nullptr) {
_currentHotspot->runEventHandlerIfExists(kMouseExitedEvent);
- debugC(5, kDebugEvents, "EVENT_MOUSEMOVE (%d, %d): Exited hotspot %d", _event.mouse.x, _event.mouse.y, _currentHotspot->getHeader()->_id);
+ debugC(5, kDebugEvents, "refreshActiveHotspot(): (%d, %d): Exited hotspot %d", _mousePos.x, _mousePos.y, _currentHotspot->getHeader()->_id);
}
_currentHotspot = hotspot;
if (hotspot != nullptr) {
- debugC(5, kDebugEvents, "EVENT_MOUSEMOVE (%d, %d): Entered hotspot %d", _event.mouse.x, _event.mouse.y, hotspot->getHeader()->_id);
+ debugC(5, kDebugEvents, "refreshActiveHotspot(): (%d, %d): Entered hotspot %d", _mousePos.x, _mousePos.y, hotspot->getHeader()->_id);
setCursor(hotspot->getHeader()->_cursorResourceId);
hotspot->runEventHandlerIfExists(kMouseEnteredEvent);
} else {
@@ -270,7 +270,7 @@ void MediaStationEngine::refreshActiveHotspot() {
}
if (hotspot != nullptr) {
- debugC(5, kDebugEvents, "EVENT_MOUSEMOVE (%d, %d): Sent to hotspot %d", _event.mouse.x, _event.mouse.y, hotspot->getHeader()->_id);
+ debugC(5, kDebugEvents, "refreshActiveHotspot(): (%d, %d): Sent to hotspot %d", _mousePos.x, _mousePos.y, hotspot->getHeader()->_id);
hotspot->runEventHandlerIfExists(kMouseMovedEvent);
}
}
@@ -463,7 +463,7 @@ void MediaStationEngine::releaseContext(uint32 contextId) {
_loadedContexts.erase(contextId);
}
-Asset *MediaStationEngine::findAssetToAcceptMouseEvents(Common::Point point) {
+Asset *MediaStationEngine::findAssetToAcceptMouseEvents() {
Asset *intersectingAsset = nullptr;
// The z-indices seem to be reversed, so the highest z-index number is
// actually the lowest asset.
@@ -471,7 +471,8 @@ Asset *MediaStationEngine::findAssetToAcceptMouseEvents(Common::Point point) {
for (Asset *asset : _assetsPlaying) {
if (asset->type() == kAssetTypeHotspot) {
- if (asset->isActive() && static_cast<Hotspot *>(asset)->isInside(point)) {
+ debugC(5, kDebugGraphics, "findAssetToAcceptMouseEvents(): Hotspot %d (z-index %d)", asset->getHeader()->_id, asset->zIndex());
+ if (asset->isActive() && static_cast<Hotspot *>(asset)->isInside(_mousePos)) {
if (asset->zIndex() < lowestZIndex) {
lowestZIndex = asset->zIndex();
intersectingAsset = asset;
diff --git a/engines/mediastation/mediastation.h b/engines/mediastation/mediastation.h
index 563f11d7b16..bc8dc9ef299 100644
--- a/engines/mediastation/mediastation.h
+++ b/engines/mediastation/mediastation.h
@@ -93,6 +93,7 @@ public:
Graphics::Screen *_screen = nullptr;
Context *_currentContext = nullptr;
+ Common::Point _mousePos;
Common::Array<Common::Rect> _dirtyRects;
// All Media Station titles run at 640x480.
@@ -124,7 +125,7 @@ private:
Context *loadContext(uint32 contextId);
void setPaletteFromHeader(AssetHeader *header);
void releaseContext(uint32 contextId);
- Asset *findAssetToAcceptMouseEvents(Common::Point point);
+ Asset *findAssetToAcceptMouseEvents();
void effectTransition(Common::Array<Operand> &args);
};
Commit: 3421caee82e1b1cd89ed5ee6bc81d68459f74d3b
https://github.com/scummvm/scummvm/commit/3421caee82e1b1cd89ed5ee6bc81d68459f74d3b
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-03-13T18:54:03-04:00
Commit Message:
MEDIASTATION: Make local script vars accessible to sub-chunks
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
engines/mediastation/mediascript/codechunk.h
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index cc853b295ed..252e9d7702d 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -29,13 +29,14 @@
namespace MediaStation {
-CodeChunk::CodeChunk(Common::SeekableReadStream &chunk) : _args(nullptr) {
+CodeChunk::CodeChunk(Common::SeekableReadStream &chunk) {
uint lengthInBytes = Datum(chunk, kDatumTypeUint32_1).u.i;
debugC(5, kDebugLoading, "CodeChunk::CodeChunk(): Length 0x%x (@0x%llx)", lengthInBytes, static_cast<long long int>(chunk.pos()));
_bytecode = chunk.readStream(lengthInBytes);
}
-Operand CodeChunk::execute(Common::Array<Operand> *args) {
+Operand CodeChunk::execute(Common::Array<Operand> *args, Common::Array<Operand> *locals) {
+ _locals = locals;
_args = args;
Operand returnValue;
while (_bytecode->pos() < _bytecode->size()) {
@@ -51,6 +52,12 @@ Operand CodeChunk::execute(Common::Array<Operand> *args) {
// We don't own the args, so we will prevent a potentially out-of-scope
// variable from being re-accessed.
_args = nullptr;
+
+ if (_weOwnLocals) {
+ delete _locals;
+ }
+ _locals = nullptr;
+
return returnValue;
}
@@ -129,7 +136,9 @@ Operand CodeChunk::executeNextStatement() {
case kOpcodeDeclareVariables: {
uint32 localVariableCount = Datum(*_bytecode).u.i;
debugC(5, kDebugScript, "%d", localVariableCount);
- _locals.resize(localVariableCount);
+ assert(_locals == nullptr);
+ _locals = new Common::Array<Operand>(localVariableCount);
+ _weOwnLocals = true;
return Operand();
}
@@ -176,11 +185,9 @@ Operand CodeChunk::executeNextStatement() {
// 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(_args);
+ ifBlock.execute(_args, _locals);
} else {
- elseBlock.execute(_args);
+ elseBlock.execute(_args, _locals);
}
// If blocks themselves shouldn't return anything.
@@ -415,7 +422,7 @@ Operand CodeChunk::getVariable(uint32 id, VariableScope scope) {
case kVariableScopeLocal: {
uint index = id - 1;
- return _locals.operator[](index);
+ return _locals->operator[](index);
}
case kVariableScopeParameter: {
@@ -444,7 +451,7 @@ void CodeChunk::putVariable(uint32 id, VariableScope scope, Operand value) {
case kVariableScopeLocal: {
uint index = id - 1;
- _locals[index] = value;
+ _locals->operator[](index) = value;
break;
}
@@ -503,6 +510,11 @@ CodeChunk::~CodeChunk() {
// We don't own the args, so we don't need to delete it.
_args = nullptr;
+ if (_weOwnLocals) {
+ delete _locals;
+ }
+ _locals = nullptr;
+
delete _bytecode;
_bytecode = nullptr;
}
diff --git a/engines/mediastation/mediascript/codechunk.h b/engines/mediastation/mediascript/codechunk.h
index b9b8155842e..c38ff104ba8 100644
--- a/engines/mediastation/mediascript/codechunk.h
+++ b/engines/mediastation/mediascript/codechunk.h
@@ -37,7 +37,7 @@ public:
CodeChunk(Common::SeekableReadStream &chunk);
~CodeChunk();
- Operand execute(Common::Array<Operand> *args = nullptr);
+ Operand execute(Common::Array<Operand> *args = nullptr, Common::Array<Operand> *locals = nullptr);
private:
Operand executeNextStatement();
@@ -45,9 +45,10 @@ private:
Operand getVariable(uint32 id, VariableScope scope);
void putVariable(uint32 id, VariableScope scope, Operand value);
- Common::Array<Operand> _locals;
- Common::Array<Operand> *_args;
- Common::SeekableReadStream *_bytecode;
+ bool _weOwnLocals = false;
+ Common::Array<Operand> *_locals = nullptr;
+ Common::Array<Operand> *_args = nullptr;
+ Common::SeekableReadStream *_bytecode = nullptr;
};
} // End of namespace MediaStation
Commit: c3b9cad220afbf0a78af839d343cbe5b46d076ae
https://github.com/scummvm/scummvm/commit/c3b9cad220afbf0a78af839d343cbe5b46d076ae
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-03-13T18:54:03-04:00
Commit Message:
MEDIASTATION: Fix hotspot refresh recursion in scripts
Changed paths:
engines/mediastation/assets/hotspot.cpp
engines/mediastation/mediastation.cpp
engines/mediastation/mediastation.h
diff --git a/engines/mediastation/assets/hotspot.cpp b/engines/mediastation/assets/hotspot.cpp
index f0ae58cd367..d0a2a0a169c 100644
--- a/engines/mediastation/assets/hotspot.cpp
+++ b/engines/mediastation/assets/hotspot.cpp
@@ -74,14 +74,14 @@ Operand Hotspot::callMethod(BuiltInMethod methodId, Common::Array<Operand> &args
assert(args.empty());
_isActive = true;
g_engine->addPlayingAsset(this);
- g_engine->refreshActiveHotspot();
+ g_engine->_needsHotspotRefresh = true;
return Operand();
}
case kMouseDeactivateMethod: {
assert(args.empty());
_isActive = false;
- g_engine->refreshActiveHotspot();
+ g_engine->_needsHotspotRefresh = true;
return Operand();
}
diff --git a/engines/mediastation/mediastation.cpp b/engines/mediastation/mediastation.cpp
index b84cbe56c80..28bff731ab3 100644
--- a/engines/mediastation/mediastation.cpp
+++ b/engines/mediastation/mediastation.cpp
@@ -171,6 +171,11 @@ Common::Error MediaStationEngine::run() {
break;
}
+ if (_needsHotspotRefresh) {
+ refreshActiveHotspot();
+ _needsHotspotRefresh = false;
+ }
+
if (!(*it)->isActive()) {
it = _assetsPlaying.erase(it);
} else {
@@ -201,7 +206,7 @@ void MediaStationEngine::processEvents() {
case Common::EVENT_MOUSEMOVE: {
_mousePos = g_system->getEventManager()->getMousePos();
- refreshActiveHotspot();
+ _needsHotspotRefresh = true;
break;
}
diff --git a/engines/mediastation/mediastation.h b/engines/mediastation/mediastation.h
index bc8dc9ef299..dcc9b02c145 100644
--- a/engines/mediastation/mediastation.h
+++ b/engines/mediastation/mediastation.h
@@ -95,6 +95,7 @@ public:
Common::Point _mousePos;
Common::Array<Common::Rect> _dirtyRects;
+ bool _needsHotspotRefresh = false;
// All Media Station titles run at 640x480.
const uint16 SCREEN_WIDTH = 640;
Commit: 4d620f729a8c3ee1f3f90c27dcdada8a816eeb77
https://github.com/scummvm/scummvm/commit/4d620f729a8c3ee1f3f90c27dcdada8a816eeb77
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-03-13T18:54:03-04:00
Commit Message:
MEDIASTATION: Stub another transition type
And downgrade unknown transition types to warnings, rather than errors.
Changed paths:
engines/mediastation/transitions.cpp
diff --git a/engines/mediastation/transitions.cpp b/engines/mediastation/transitions.cpp
index afa2381774f..267e7066806 100644
--- a/engines/mediastation/transitions.cpp
+++ b/engines/mediastation/transitions.cpp
@@ -33,7 +33,8 @@ enum TransitionType {
kTransitionSetToPercentOfPalette = 306,
kTransitionFadeToPaletteObject = 307,
kTransitionSetToPaletteObject = 308,
- kTransitionSetToPercentOfPaletteObject = 309
+ kTransitionSetToPercentOfPaletteObject = 309,
+ kTransitionCircleOut = 328
};
void MediaStationEngine::effectTransition(Common::Array<Operand> &args) {
@@ -84,8 +85,13 @@ void MediaStationEngine::effectTransition(Common::Array<Operand> &args) {
break;
}
+ case kTransitionCircleOut: {
+ warning("MediaStationEngine::effectTransition(): Circle out transition not implemented");
+ break;
+ }
+
default:
- error("MediaStationEngine::effectTransition(): Got unknown transition type %d", static_cast<uint>(transitionType));
+ warning("MediaStationEngine::effectTransition(): Got unknown transition type %d", static_cast<uint>(transitionType));
}
}
Commit: 9d717b633d7bf0c2c3b8846b5ef5d51a2474788b
https://github.com/scummvm/scummvm/commit/9d717b633d7bf0c2c3b8846b5ef5d51a2474788b
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-03-13T18:54:03-04:00
Commit Message:
MEDIASTATION: Support referencing functions in variables
Changed paths:
engines/mediastation/mediascript/codechunk.cpp
engines/mediastation/mediascript/codechunk.h
engines/mediastation/mediascript/operand.cpp
engines/mediastation/mediascript/scriptconstants.cpp
engines/mediastation/mediascript/scriptconstants.h
engines/mediastation/mediascript/variable.cpp
engines/mediastation/mediascript/variable.h
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 252e9d7702d..159bbadd095 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -88,29 +88,11 @@ Operand CodeChunk::executeNextStatement() {
return Operand();
}
- case kOpcodeCallRoutine: {
+ case kOpcodeCallFunction: {
uint functionId = Datum(*_bytecode).u.i;
uint32 parameterCount = Datum(*_bytecode).u.i;
- Common::Array<Operand> args;
debugC(5, kDebugScript, "%d (%d params)", functionId, parameterCount);
- for (uint i = 0; i < parameterCount; i++) {
- debugCN(5, kDebugScript, " Param %d: ", i);
- Operand arg = executeNextStatement();
- args.push_back(arg);
- }
-
- Operand returnValue;
- Function *function = g_engine->getFunctionById(functionId);
- if (function != nullptr) {
- // This is a title-defined function.
- returnValue = function->execute(args);
- } else {
- // This is a function built in (and global to) the engine.
- BuiltInFunction builtInFunctionId = static_cast<BuiltInFunction>(functionId);
- debugC(5, kDebugScript, " Function Name: %s ", builtInFunctionToStr(builtInFunctionId));
- returnValue = g_engine->callBuiltInFunction(builtInFunctionId, args);
- }
- return returnValue;
+ return callFunction(functionId, parameterCount);
}
case kOpcodeCallMethod: {
@@ -336,6 +318,15 @@ Operand CodeChunk::executeNextStatement() {
return value;
}
+ case kOpcodeCallFunctionInVariable: {
+ uint parameterCount = Datum(*_bytecode).u.i;
+ Operand variable = executeNextStatement();
+ uint functionId = variable.getFunctionId();
+ debugC(5, kDebugScript, "Variable %d [function %d] (%d params)", variable.getVariable()->_id, functionId, parameterCount);
+
+ return callFunction(functionId, parameterCount);
+ }
+
default:
error("CodeChunk::getNextStatement(): Got unimplemented opcode %s (%d)", opcodeToStr(opcode), static_cast<uint>(opcode));
}
@@ -379,7 +370,7 @@ Operand CodeChunk::executeNextStatement() {
}
case kOperandTypeString: {
- // This is indeed a raw string anot not a string wrapped in a datum!
+ // This is indeed a raw string, not a string wrapped in a datum!
// TODO: This copies the string. Can we read it directly from the chunk?
int size = Datum(*_bytecode, kDatumTypeUint16_1).u.i;
char *buffer = new char[size + 1];
@@ -411,6 +402,29 @@ Operand CodeChunk::executeNextStatement() {
}
}
+Operand CodeChunk::callFunction(uint functionId, uint parameterCount) {
+ Common::Array<Operand> args;
+ for (uint i = 0; i < parameterCount; i++) {
+ debugCN(5, kDebugScript, " Param %d: ", i);
+ Operand arg = executeNextStatement();
+ args.push_back(arg);
+ }
+
+ Operand returnValue;
+ Function *function = g_engine->getFunctionById(functionId);
+ if (function != nullptr) {
+ // This is a title-defined function.
+ returnValue = function->execute(args);
+ } else {
+ // This is a function built in (and global to) the engine.
+ BuiltInFunction builtInFunctionId = static_cast<BuiltInFunction>(functionId);
+ debugC(5, kDebugScript, " Function Name: %s ", builtInFunctionToStr(builtInFunctionId));
+ returnValue = g_engine->callBuiltInFunction(builtInFunctionId, args);
+ }
+
+ return returnValue;
+}
+
Operand CodeChunk::getVariable(uint32 id, VariableScope scope) {
switch (scope) {
case kVariableScopeGlobal: {
diff --git a/engines/mediastation/mediascript/codechunk.h b/engines/mediastation/mediascript/codechunk.h
index c38ff104ba8..79031b17797 100644
--- a/engines/mediastation/mediascript/codechunk.h
+++ b/engines/mediastation/mediascript/codechunk.h
@@ -42,6 +42,7 @@ public:
private:
Operand executeNextStatement();
Operand callBuiltInMethod(BuiltInMethod method, Operand self, Common::Array<Operand> &args);
+ Operand callFunction(uint functionId, uint parameterCount);
Operand getVariable(uint32 id, VariableScope scope);
void putVariable(uint32 id, VariableScope scope, Operand value);
diff --git a/engines/mediastation/mediascript/operand.cpp b/engines/mediastation/mediascript/operand.cpp
index 1f65dcf33b1..afe0c331fd9 100644
--- a/engines/mediastation/mediascript/operand.cpp
+++ b/engines/mediastation/mediascript/operand.cpp
@@ -181,6 +181,11 @@ uint Operand::getFunctionId() {
return _u.functionId;
}
+ case kOperandTypeVariableDeclaration: {
+ assert(_u.variable->_type == kVariableTypeFunction);
+ return _u.variable->_value.functionId;
+ }
+
default:
error("Operand::getFunction(): Attempt to get function ID from operand type %s (%d)",
operandTypeToStr(_type), static_cast<uint>(_type));
diff --git a/engines/mediastation/mediascript/scriptconstants.cpp b/engines/mediastation/mediascript/scriptconstants.cpp
index 7446848e9e8..be272355817 100644
--- a/engines/mediastation/mediascript/scriptconstants.cpp
+++ b/engines/mediastation/mediascript/scriptconstants.cpp
@@ -74,8 +74,8 @@ const char *opcodeToStr(Opcode opcode) {
return "%";
case kOpcodeNegate:
return "-";
- case kOpcodeCallRoutine:
- return "CallRoutine";
+ case kOpcodeCallFunction:
+ return "CallFunction";
case kOpcodeCallMethod:
return "CallMethod";
case kOpcodeDeclareVariables:
@@ -84,6 +84,8 @@ const char *opcodeToStr(Opcode opcode) {
return "Return";
case kOpcodeUnk1:
return "UNKNOWN (Unk1)";
+ case kOpcodeCallFunctionInVariable:
+ return "CallFunctionInVariable";
case kOpcodeWhile:
return "While";
default:
@@ -332,6 +334,8 @@ const char *operandTypeToStr(OperandType type) {
return "Collection";
case kOperandTypeFunction:
return "Function";
+ case kOperandTypeMethod:
+ return "Method";
default:
return "UNKNOWN";
}
@@ -341,6 +345,8 @@ const char *variableTypeToStr(VariableType type) {
switch (type) {
case kVariableTypeEmpty:
return "Empty";
+ case kVariableTypeFunction:
+ return "Function";
case kVariableTypeCollection:
return "Collection";
case kVariableTypeString:
diff --git a/engines/mediastation/mediascript/scriptconstants.h b/engines/mediastation/mediascript/scriptconstants.h
index d03d5672fb1..6f3d27f5b2f 100644
--- a/engines/mediastation/mediascript/scriptconstants.h
+++ b/engines/mediastation/mediascript/scriptconstants.h
@@ -50,7 +50,7 @@ enum Opcode {
kOpcodeDivide = 216,
kOpcodeModulo = 217,
kOpcodeNegate = 218,
- kOpcodeCallRoutine = 219,
+ kOpcodeCallFunction = 219,
kOpcodeCallMethod = 220,
// This seems to appear at the start of a function to declare the number of
// local variables used in the function. It seems to be the `Declare`
@@ -60,7 +60,8 @@ enum Opcode {
kOpcodeDeclareVariables = 221,
kOpcodeWhile = 224,
kOpcodeReturn = 222,
- kOpcodeUnk1 = 223
+ kOpcodeUnk1 = 223,
+ kOpcodeCallFunctionInVariable = 225
};
const char *opcodeToStr(Opcode opcode);
@@ -248,8 +249,9 @@ enum OperandType {
kOperandTypeDollarSignVariable = 155,
kOperandTypeAssetId = 156,
kOperandTypeVariableDeclaration = 158,
- kOperandTypeCollection = 159,
- kOperandTypeFunction = 160
+ kOperandTypeFunction = 159,
+ kOperandTypeMethod = 160,
+ kOperandTypeCollection = 161
};
const char *operandTypeToStr(OperandType type);
@@ -257,6 +259,7 @@ enum VariableType {
// This is an invalid type used for initialization only.
kVariableTypeEmpty = 0x0000,
+ kVariableTypeFunction = 0x0008,
kVariableTypeCollection = 0x0007,
kVariableTypeString = 0x0006,
kVariableTypeAssetId = 0x0005,
diff --git a/engines/mediastation/mediascript/variable.cpp b/engines/mediastation/mediascript/variable.cpp
index 1778105a702..c515993b22b 100644
--- a/engines/mediastation/mediascript/variable.cpp
+++ b/engines/mediastation/mediascript/variable.cpp
@@ -227,6 +227,12 @@ void Variable::putValue(Operand value) {
break;
}
+ case kOperandTypeFunction: {
+ _type = kVariableTypeFunction;
+ _value.functionId = value.getFunctionId();
+ break;
+ }
+
default:
error("Variable::putValue(): Assigning an unknown operand type %s (%d) to a variable not supported",
operandTypeToStr(value.getType()), static_cast<uint>(value.getType()));
diff --git a/engines/mediastation/mediascript/variable.h b/engines/mediastation/mediascript/variable.h
index f11e5367b33..a27d66c1c6f 100644
--- a/engines/mediastation/mediascript/variable.h
+++ b/engines/mediastation/mediascript/variable.h
@@ -45,6 +45,7 @@ public:
union {
Common::String *string;
Collection *collection;
+ uint functionId;
int i;
double d;
uint assetId;
More information about the Scummvm-git-logs
mailing list