[Scummvm-git-logs] scummvm master -> 029b6738cbab7bdb176a6b99db2b3df173200d87
elasota
noreply at scummvm.org
Tue Jan 24 06:35:49 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
029b6738cb MTROPOLIS: Add support for assigning sound assets and loading assets from other streams.
Commit: 029b6738cbab7bdb176a6b99db2b3df173200d87
https://github.com/scummvm/scummvm/commit/029b6738cbab7bdb176a6b99db2b3df173200d87
Author: elasota (ejlasota at gmail.com)
Date: 2023-01-23T23:06:49-05:00
Commit Message:
MTROPOLIS: Add support for assigning sound assets and loading assets from other streams.
Changed paths:
engines/mtropolis/data.cpp
engines/mtropolis/data.h
engines/mtropolis/elements.cpp
engines/mtropolis/elements.h
engines/mtropolis/hacks.cpp
engines/mtropolis/hacks.h
engines/mtropolis/runtime.cpp
engines/mtropolis/runtime.h
diff --git a/engines/mtropolis/data.cpp b/engines/mtropolis/data.cpp
index 60816e2ace2..aebe8d02650 100644
--- a/engines/mtropolis/data.cpp
+++ b/engines/mtropolis/data.cpp
@@ -740,7 +740,7 @@ DataReadErrorCode PresentationSettings::load(DataReader &reader) {
AssetCatalog::AssetInfoRev4Fields::AssetInfoRev4Fields() : assetType(0), flags2(0) {
}
-AssetCatalog::AssetInfo::AssetInfo() : flags1(0), nameLength(0), alwaysZero(0), unknown1(0), filePosition(0) {
+AssetCatalog::AssetInfo::AssetInfo() : flags1(0), nameLength(0), alwaysZero(0), streamID(0), filePosition(0) {
}
AssetCatalog::AssetCatalog() : persistFlags(0), totalNameSizePlus22(0), unknown1{0, 0, 0, 0}, numAssets(0), haveRev4Fields(false) {
@@ -762,7 +762,7 @@ DataReadErrorCode AssetCatalog::load(DataReader& reader) {
for (size_t i = 0; i < numAssets; i++) {
AssetInfo &asset = assets[i];
- if (!reader.readU32(asset.flags1) || !reader.readU16(asset.nameLength) || !reader.readU16(asset.alwaysZero) || !reader.readU32(asset.unknown1) || !reader.readU32(asset.filePosition))
+ if (!reader.readU32(asset.flags1) || !reader.readU16(asset.nameLength) || !reader.readU16(asset.alwaysZero) || !reader.readU32(asset.streamID) || !reader.readU32(asset.filePosition))
return kDataReadErrorReadFailed;
if (_revision >= 4) {
diff --git a/engines/mtropolis/data.h b/engines/mtropolis/data.h
index 71be2bccefc..e6e6303e1b7 100644
--- a/engines/mtropolis/data.h
+++ b/engines/mtropolis/data.h
@@ -502,7 +502,7 @@ struct AssetCatalog : public DataObject {
uint32 flags1;
uint16 nameLength;
uint16 alwaysZero;
- uint32 unknown1; // Possibly scene ID
+ uint32 streamID;
uint32 filePosition; // Contains a static value in Obsidian
AssetInfoRev4Fields rev4Fields;
diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index 35a9fc02ef9..92d1f2cf890 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -2122,6 +2122,9 @@ MiniscriptInstructionOutcome SoundElement::writeRefAttribute(MiniscriptThread *t
} else if (attrib == "balance") {
DynamicValueWriteFuncHelper<SoundElement, &SoundElement::scriptSetBalance, true>::create(this, writeProxy);
return kMiniscriptInstructionOutcomeContinue;
+ } else if (attrib == "asset") {
+ DynamicValueWriteFuncHelper<SoundElement, &SoundElement::scriptSetAsset, true>::create(this, writeProxy);
+ return kMiniscriptInstructionOutcomeContinue;
}
return NonVisualElement::writeRefAttribute(thread, writeProxy, attrib);
@@ -2333,6 +2336,53 @@ MiniscriptInstructionOutcome SoundElement::scriptSetBalance(MiniscriptThread *th
return kMiniscriptInstructionOutcomeContinue;
}
+MiniscriptInstructionOutcome SoundElement::scriptSetAsset(MiniscriptThread *thread, const DynamicValue &value) {
+ DynamicValue derefValue = value.dereference();
+
+ if (derefValue.getType() != DynamicValueTypes::kString) {
+ thread->error("Tried to set a sound element's asset to something that wasn't a string");
+ return kMiniscriptInstructionOutcomeFailed;
+ }
+
+ stopPlayer();
+
+ Project *project = thread->getRuntime()->getProject();
+
+ uint32 assetID = 0;
+ if (!project->getAssetIDByName(derefValue.getString(), assetID)) {
+ warning("Sound element references asset '%s' but the asset ID couldn't be resolved", derefValue.getString().c_str());
+ return kMiniscriptInstructionOutcomeFailed;
+ }
+
+ Common::Array<Common::SharedPtr<Asset> > forceLoadedAssets;
+
+ Common::SharedPtr<Asset> asset = project->getAssetByID(assetID).lock();
+
+ if (!asset) {
+ if (thread->getRuntime()->getHacks().allowAssetsFromOtherScenes) {
+ project->forceLoadAsset(assetID, forceLoadedAssets);
+ asset = project->getAssetByID(assetID).lock();
+ }
+ }
+
+ if (!asset) {
+ warning("Sound element references asset '%s' but the asset isn't loaded!", derefValue.getString().c_str());
+ return kMiniscriptInstructionOutcomeFailed;
+ }
+
+ if (asset->getAssetType() != kAssetTypeAudio) {
+ warning("Sound element assigned an asset that isn't audio");
+ return kMiniscriptInstructionOutcomeFailed;
+ }
+
+ _cachedAudio = static_cast<AudioAsset *>(asset.get())->loadAndCacheAudio(getRuntime());
+ _metadata = static_cast<AudioAsset *>(asset.get())->getMetadata();
+ _assetID = asset->getAssetID();
+
+ return kMiniscriptInstructionOutcomeContinue;
+
+}
+
void SoundElement::setLoop(bool loop) {
_loop = loop;
}
diff --git a/engines/mtropolis/elements.h b/engines/mtropolis/elements.h
index e07dee2a7a4..de89d55721d 100644
--- a/engines/mtropolis/elements.h
+++ b/engines/mtropolis/elements.h
@@ -391,6 +391,7 @@ private:
MiniscriptInstructionOutcome scriptSetLoop(MiniscriptThread *thread, const DynamicValue &value);
MiniscriptInstructionOutcome scriptSetVolume(MiniscriptThread *thread, const DynamicValue &value);
MiniscriptInstructionOutcome scriptSetBalance(MiniscriptThread *thread, const DynamicValue &value);
+ MiniscriptInstructionOutcome scriptSetAsset(MiniscriptThread *thread, const DynamicValue &value);
struct StartPlayingTaskData {
StartPlayingTaskData() : runtime(nullptr) {}
diff --git a/engines/mtropolis/hacks.cpp b/engines/mtropolis/hacks.cpp
index 980ef54a45c..1bcf01908f0 100644
--- a/engines/mtropolis/hacks.cpp
+++ b/engines/mtropolis/hacks.cpp
@@ -41,6 +41,7 @@ Hacks::Hacks() {
midiVolumeScale = 256;
minTransitionDuration = 0;
ignoreMToonMaintainRateFlag = false;
+ allowAssetsFromOtherScenes = false;
mtiVariableReferencesHack = false;
mtiSceneReturnHack = false;
}
@@ -1031,6 +1032,9 @@ void addMTIQuirks(const MTropolisGameDescription &desc, Hacks &hacks) {
// Given that the flag should not be set, we ignore the flag.
hacks.ignoreMToonMaintainRateFlag = true;
+ // Needed for piano, the sound assets are in B10 : Notes but the piano is in B10 : Piano
+ hacks.allowAssetsFromOtherScenes = true;
+
// MTI initializes variables in a way that doesn't seem to match mTropolis behavior in any explicable way:
//
// For example, 0010cb0e "Scene Started => init Benbow" looks like this internally, decompiled:
diff --git a/engines/mtropolis/hacks.h b/engines/mtropolis/hacks.h
index 57ce41b65b4..b1751c7a2a8 100644
--- a/engines/mtropolis/hacks.h
+++ b/engines/mtropolis/hacks.h
@@ -51,6 +51,7 @@ struct Hacks {
bool ignoreMismatchedProjectNameInObjectLookups;
bool removeQuickTimeEdits;
bool ignoreMToonMaintainRateFlag;
+ bool allowAssetsFromOtherScenes;
bool mtiVariableReferencesHack;
bool mtiSceneReturnHack;
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index 1bf6bb88f23..476bb7a6bb8 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -7143,6 +7143,60 @@ Common::WeakPtr<Asset> Project::getAssetByID(uint32 assetID) const {
return desc->asset;
}
+void Project::forceLoadAsset(uint32 assetID, Common::Array<Common::SharedPtr<Asset> > &outHoldAssets) {
+ AssetDesc *assetDesc = _assetsByID[assetID];
+ uint32 streamID = assetDesc->streamID;
+
+ size_t streamIndex = streamID - 1;
+
+ const StreamDesc &streamDesc = _streams[streamIndex];
+ uint segmentIndex = streamDesc.segmentIndex;
+
+ openSegmentStream(segmentIndex);
+
+ Common::SeekableSubReadStreamEndian stream(_segments[segmentIndex].weakStream, streamDesc.pos, streamDesc.pos + streamDesc.size, _isBigEndian);
+ Data::DataReader reader(streamDesc.pos, stream, _projectFormat);
+
+ const Data::PlugInModifierRegistry &plugInDataLoaderRegistry = _plugInRegistry.getDataLoaderRegistry();
+
+ reader.seek(assetDesc->filePosition - streamDesc.pos);
+
+ Common::SharedPtr<Data::DataObject> dataObject;
+ Data::loadDataObject(plugInDataLoaderRegistry, reader, dataObject);
+
+ if (!dataObject) {
+ error("Failed to force-load asset data object");
+ }
+
+ Data::DataObjectTypes::DataObjectType dataObjectType = dataObject->getType();
+
+ if (!Data::DataObjectTypes::isAsset(dataObjectType)) {
+ error("Failed to force-load asset, the data object at the expected position wasn't an asset");
+ }
+
+ AssetDefLoaderContext assetDefLoader;
+ loadAssetDef(streamIndex, assetDefLoader, *dataObject.get());
+
+ assignAssets(assetDefLoader.assets, getRuntime()->getHacks());
+
+ outHoldAssets = Common::move(assetDefLoader.assets);
+}
+
+bool Project::getAssetIDByName(const Common::String &assetName, uint32 &outAssetID) const {
+ for (uint32 assetID = 0; assetID < _assetsByID.size(); assetID++) {
+ const AssetDesc *assetDesc = _assetsByID[assetID];
+ if (!assetDesc)
+ continue;
+
+ if (caseInsensitiveEqual(assetName, assetDesc->name)) {
+ outAssetID = assetID;
+ return true;
+ }
+ }
+
+ return false;
+}
+
size_t Project::getSegmentForStreamIndex(size_t streamIndex) const {
return _streams[streamIndex].segmentIndex;
}
@@ -7385,6 +7439,9 @@ void Project::loadAssetCatalog(const Data::AssetCatalog &assetCatalog) {
else
assetDesc.typeCode = 0;
+ assetDesc.streamID = assetInfo.streamID;
+ assetDesc.filePosition = assetInfo.filePosition;
+
_assetsByID[assetDesc.id] = &assetDesc;
if (!assetDesc.name.empty())
_assetNameToID[assetDesc.name] = assetDesc.id;
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 3977e97ed43..1e492ec6468 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -2391,6 +2391,9 @@ public:
Common::String getAssetNameByID(uint32 assetID) const;
Common::WeakPtr<Asset> getAssetByID(uint32 assetID) const;
+ bool getAssetIDByName(const Common::String &assetName, uint32 &outAssetID) const;
+ void forceLoadAsset(uint32 assetID, Common::Array<Common::SharedPtr<Asset> > &outHoldAssets);
+
size_t getSegmentForStreamIndex(size_t streamIndex) const;
void openSegmentStream(int segmentIndex);
void closeSegmentStream(int segmentIndex);
@@ -2467,6 +2470,8 @@ private:
AssetDesc();
uint32 typeCode;
+ uint32 streamID;
+ uint32 filePosition;
size_t id;
Common::String name;
More information about the Scummvm-git-logs
mailing list