[Scummvm-git-logs] scummvm master -> 69d0293172d30588184ac69e2a8f0e37753ec99c
elasota
noreply at scummvm.org
Sat Oct 28 15:46:01 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:
69d0293172 MTROPOLIS: Add support for 'Unit Re-Booted'
Commit: 69d0293172d30588184ac69e2a8f0e37753ec99c
https://github.com/scummvm/scummvm/commit/69d0293172d30588184ac69e2a8f0e37753ec99c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2023-10-28T11:45:58-04:00
Commit Message:
MTROPOLIS: Add support for 'Unit Re-Booted'
This is not much of a game, but uses some variants of the data format which are
nice to support and should help with future projects.
Changed paths:
engines/mtropolis/boot.cpp
engines/mtropolis/data.cpp
engines/mtropolis/data.h
engines/mtropolis/detection.cpp
engines/mtropolis/detection.h
engines/mtropolis/detection_tables.h
engines/mtropolis/elements.cpp
engines/mtropolis/miniscript.cpp
engines/mtropolis/mtropolis.cpp
engines/mtropolis/plugin/standard_data.cpp
engines/mtropolis/runtime.cpp
engines/mtropolis/runtime.h
diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index e9220f17a8a..380ab5169f0 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -1025,6 +1025,20 @@ const ManifestFile sttgsDemoWinFiles[] = {
{nullptr, MTFT_AUTO}
};
+const ManifestFile unitWinFiles[] = {
+ {"UNIT32.EXE", MTFT_PLAYER},
+ {"DATA.MFX", MTFT_MAIN},
+ {"CURSORS.C32", MTFT_EXTENSION},
+ {"BASIC.X32", MTFT_SPECIAL},
+ {"EXTRAS.R32", MTFT_SPECIAL},
+ {nullptr, MTFT_AUTO}
+};
+
+const char *unitWinDirectories[] = {
+ "MPLUGINS",
+ nullptr
+};
+
const Game games[] = {
// Obsidian - Retail - Macintosh - English
{
@@ -1210,6 +1224,14 @@ const Game games[] = {
nullptr,
GameDataHandlerFactory<STTGSGameDataHandler>::create
},
+ // Unit: Rebooted
+ {
+ MTBOOT_UNIT_REBOOTED_WIN,
+ unitWinFiles,
+ unitWinDirectories,
+ nullptr,
+ GameDataHandlerFactory<STTGSGameDataHandler>::create
+ },
};
} // End of namespace Games
diff --git a/engines/mtropolis/data.cpp b/engines/mtropolis/data.cpp
index 72db1a11257..c1258808d1b 100644
--- a/engines/mtropolis/data.cpp
+++ b/engines/mtropolis/data.cpp
@@ -157,8 +157,10 @@ bool isAsset(DataObjectType type) {
} // End of namespace DataObjectTypes
-DataReader::DataReader(int64 globalPosition, Common::SeekableReadStreamEndian &stream, ProjectFormat projectFormat)
- : _globalPosition(globalPosition), _stream(stream), _projectFormat(projectFormat), _permitDamagedStrings(false) {
+DataReader::DataReader(int64 globalPosition, Common::SeekableReadStreamEndian &stream, ProjectFormat projectFormat,
+ ProjectEngineVersion projectEngineVersion)
+ : _globalPosition(globalPosition), _stream(stream), _projectFormat(projectFormat), _permitDamagedStrings(false),
+ _projectEngineVersion(projectEngineVersion) {
}
bool DataReader::readU8(uint8 &value) {
@@ -303,10 +305,18 @@ ProjectFormat DataReader::getProjectFormat() const {
return _projectFormat;
}
+ProjectEngineVersion DataReader::getProjectEngineVersion() const {
+ return _projectEngineVersion;
+}
+
bool DataReader::isBigEndian() const {
return _stream.isBE();
}
+bool DataReader::isV2Project() const {
+ return _projectEngineVersion == kProjectEngineVersion2;
+}
+
void DataReader::setPermitDamagedStrings(bool permit) {
_permitDamagedStrings = permit;
}
@@ -443,7 +453,7 @@ bool InternalTypeTaggedValue::load(DataReader &reader) {
Common::MemoryReadStreamEndian contentsStream(contents, sizeof(contents), reader.isBigEndian());
- DataReader valueReader(valueGlobalPos, contentsStream, reader.getProjectFormat());
+ DataReader valueReader(valueGlobalPos, contentsStream, reader.getProjectFormat(), reader.getProjectEngineVersion());
switch (type) {
case kNull:
@@ -731,7 +741,7 @@ PresentationSettings::PresentationSettings()
}
DataReadErrorCode PresentationSettings::load(DataReader &reader) {
- if (_revision != 2)
+ if (_revision != 2 && _revision != 3)
return kDataReadErrorUnsupportedRevision;
if (!reader.readU32(persistFlags) ||
@@ -798,6 +808,34 @@ DataReadErrorCode Unknown19::load(DataReader &reader) {
if (!reader.readU32(persistFlags) || !reader.readU32(sizeIncludingTag) || !reader.readBytes(unknown1))
return kDataReadErrorReadFailed;
+ if (sizeIncludingTag != 16)
+ return kDataReadErrorUnrecognized;
+
+ return kDataReadErrorNone;
+}
+
+Unknown2B::Unknown2B() : persistFlags(0), sizeIncludingTag(0) {
+}
+
+DataReadErrorCode Unknown2B::load(DataReader &reader) {
+ if (_revision != 1)
+ return kDataReadErrorUnsupportedRevision;
+
+ if (!reader.readU32(persistFlags) || !reader.readU32(sizeIncludingTag))
+ return kDataReadErrorReadFailed;
+
+ if (sizeIncludingTag > 100000)
+ return kDataReadErrorUnrecognized;
+
+ // So far read type (4) + revision (2) + persist (4) + size (4) = 14 bytes
+ uint8 *buf = static_cast<uint8 *>(malloc(sizeIncludingTag - 14));
+ if (!reader.read(buf, sizeIncludingTag - 14))
+ return kDataReadErrorReadFailed;
+
+ // TODO: Use this data.
+
+ free(buf);
+
return kDataReadErrorNone;
}
@@ -1002,13 +1040,16 @@ GlobalObjectInfo::GlobalObjectInfo()
}
DataReadErrorCode GlobalObjectInfo::load(DataReader &reader) {
- if (_revision != 0)
+ if (_revision != 0 && _revision != 1)
return kDataReadErrorUnsupportedRevision;
if (!reader.readU32(persistFlags) || !reader.readU32(sizeIncludingTag) || !reader.readU16(numGlobalModifiers)
|| !reader.readBytes(unknown1))
return kDataReadErrorReadFailed;
+ if (sizeIncludingTag != 20)
+ return kDataReadErrorUnrecognized;
+
return kDataReadErrorNone;
}
@@ -1112,7 +1153,7 @@ BehaviorModifier::BehaviorModifier()
}
DataReadErrorCode BehaviorModifier::load(DataReader& reader) {
- if (_revision != 1)
+ if (_revision != 1 && _revision != 2)
return kDataReadErrorUnsupportedRevision;
if (!reader.readU32(modifierFlags) || !reader.readU32(sizeIncludingTag)
@@ -1122,6 +1163,9 @@ DataReadErrorCode BehaviorModifier::load(DataReader& reader) {
|| !reader.readU16(lengthOfName) || !reader.readU16(numChildren))
return kDataReadErrorReadFailed;
+ if (_revision == 2 && !reader.readU32(unknown8))
+ return kDataReadErrorReadFailed;
+
if (lengthOfName > 0 && !reader.readTerminatedStr(name, lengthOfName))
return kDataReadErrorReadFailed;
@@ -1142,7 +1186,8 @@ MiniscriptProgram::Attribute::Attribute()
MiniscriptProgram::MiniscriptProgram()
: unknown1(0), sizeOfInstructions(0), numOfInstructions(0), numLocalRefs(0), numAttributes(0),
- projectFormat(kProjectFormatUnknown), isBigEndian(false) {
+ projectFormat(kProjectFormatUnknown), isBigEndian(false),
+ projectEngineVersion(kProjectEngineVersionUnknown) {
}
bool MiniscriptProgram::load(DataReader &reader) {
@@ -1186,7 +1231,8 @@ bool MiniscriptProgram::load(DataReader &reader) {
}
TypicalModifierHeader::TypicalModifierHeader()
- : modifierFlags(0), sizeIncludingTag(0), guid(0), unknown3{0, 0, 0, 0, 0, 0}, unknown4(0), lengthOfName(0) {
+ : modifierFlags(0), sizeIncludingTag(0), guid(0), unknown3{0, 0, 0, 0, 0, 0}, unknown4(0),
+ unknown5(0), lengthOfName(0) {
}
bool TypicalModifierHeader::load(DataReader& reader) {
@@ -1195,6 +1241,9 @@ bool TypicalModifierHeader::load(DataReader& reader) {
|| !reader.readU16(lengthOfName))
return false;
+ if (reader.isV2Project() && !reader.readU32(unknown5))
+ return false;
+
if (lengthOfName > 0 && !reader.readTerminatedStr(name, lengthOfName))
return false;
@@ -1206,7 +1255,7 @@ MiniscriptModifier::MiniscriptModifier()
}
DataReadErrorCode MiniscriptModifier::load(DataReader &reader) {
- if (_revision != 1003)
+ if (_revision != 1003 && _revision != 2003)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !enableWhen.load(reader) || !reader.readBytes(unknown6) || !reader.readU8(unknown7) || !program.load(reader))
@@ -1271,7 +1320,7 @@ MessengerModifier::MessengerModifier()
}
DataReadErrorCode MessengerModifier::load(DataReader &reader) {
- if (_revision != 1002)
+ if (_revision != 1002 && _revision != 2002)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader))
@@ -1315,17 +1364,23 @@ AliasModifier::AliasModifier()
}
DataReadErrorCode AliasModifier::load(DataReader& reader) {
- if (_revision > 2)
+ if (_revision > 2 && _revision != 4)
return kDataReadErrorUnsupportedRevision;
if (!reader.readU32(modifierFlags)
|| !reader.readU32(sizeIncludingTag)
|| !reader.readU16(aliasIndexPlusOne)
|| !reader.readU32(unknown1)
- || !reader.readU32(unknown2)
- || !reader.readU16(lengthOfName)
- || !editorLayoutPosition.load(reader))
+ || !reader.readU32(unknown2))
+ return kDataReadErrorReadFailed;
+
+ if (_revision <= 2 && (!reader.readU16(lengthOfName)
+ || !editorLayoutPosition.load(reader)))
+ return kDataReadErrorReadFailed;
+ else if (_revision == 4 && !editorLayoutPosition.load(reader)) {
+ // v4 puts the name len just before it.
return kDataReadErrorReadFailed;
+ }
if (_revision >= 2) {
haveGUID = true;
@@ -1336,6 +1391,13 @@ DataReadErrorCode AliasModifier::load(DataReader& reader) {
guid = 0;
}
+ if (_revision == 4) {
+ uint32 nameLen = 0;
+ if (!reader.readU32(nameLen))
+ return kDataReadErrorReadFailed;
+ lengthOfName = static_cast<uint16>(nameLen);
+ }
+
if (!reader.readTerminatedStr(name, lengthOfName))
return kDataReadErrorReadFailed;
@@ -1347,7 +1409,7 @@ ChangeSceneModifier::ChangeSceneModifier()
}
DataReadErrorCode ChangeSceneModifier::load(DataReader &reader) {
- if (_revision != 1001)
+ if (_revision != 1001 && _revision != 2001)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !reader.readU32(changeSceneFlags) || !executeWhen.load(reader)
@@ -1599,7 +1661,7 @@ TimerMessengerModifier::TimerMessengerModifier()
}
DataReadErrorCode TimerMessengerModifier::load(DataReader &reader) {
- if (_revision != 1002)
+ if (_revision != 1002 && _revision != 2002)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader))
@@ -1665,7 +1727,7 @@ KeyboardMessengerModifier::KeyboardMessengerModifier()
}
DataReadErrorCode KeyboardMessengerModifier::load(DataReader &reader) {
- if (_revision != 1003)
+ if (_revision != 1003 && _revision != 2003)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !reader.readU32(messageFlagsAndKeyStates) || !reader.readU16(unknown2)
@@ -1706,7 +1768,7 @@ GraphicModifier::GraphicModifier()
}
DataReadErrorCode GraphicModifier::load(DataReader &reader) {
- if (_revision != 1001)
+ if (_revision != 1001 && _revision != 2001)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !reader.readU16(unknown1) || !applyWhen.load(reader)
@@ -1833,7 +1895,7 @@ IntegerVariableModifier::IntegerVariableModifier() : unknown1{0, 0, 0, 0}, value
}
DataReadErrorCode IntegerVariableModifier::load(DataReader &reader) {
- if (_revision != 1000)
+ if (_revision != 1000 && _revision != 2000)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !reader.readBytes(unknown1) || !reader.readS32(value))
@@ -1846,7 +1908,7 @@ IntegerRangeVariableModifier::IntegerRangeVariableModifier() : unknown1{0, 0, 0,
}
DataReadErrorCode IntegerRangeVariableModifier::load(DataReader &reader) {
- if (_revision != 1000)
+ if (_revision != 1000 && _revision != 2000)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !reader.readBytes(unknown1) || !range.load(reader))
@@ -1859,7 +1921,7 @@ VectorVariableModifier::VectorVariableModifier() : unknown1{0, 0, 0, 0} {
}
DataReadErrorCode VectorVariableModifier::load(DataReader &reader) {
- if (_revision != 1000)
+ if (_revision != 1000 && _revision != 2000)
return kDataReadErrorUnsupportedRevision;
if (!modHeader.load(reader) || !reader.readBytes(unknown1) || !this->vector.load(reader))
@@ -1930,7 +1992,7 @@ PlugInModifier::PlugInModifier()
}
DataReadErrorCode PlugInModifier::load(DataReader &reader) {
- if (_revision != 1001)
+ if (_revision != 1001 && _revision != 2001)
return kDataReadErrorUnsupportedRevision;
if (!reader.readU32(modifierFlags) || !reader.readU32(codedSize) || !reader.read(modifierName, 16)
@@ -2170,7 +2232,7 @@ ImageAsset::ImageAsset()
}
DataReadErrorCode ImageAsset::load(DataReader &reader) {
- if (_revision != 1)
+ if (_revision != 1 && _revision != 2)
return kDataReadErrorUnsupportedRevision;
if (!reader.readU32(persistFlags) || !reader.readU32(unknown1) || !reader.readBytes(unknown2)
@@ -2430,6 +2492,9 @@ DataReadErrorCode loadDataObject(const PlugInModifierRegistry ®istry, DataRea
case DataObjectTypes::kUnknown19:
dataObject = new Unknown19();
break;
+ case DataObjectTypes::kUnknown2B:
+ dataObject = new Unknown2B();
+ break;
case DataObjectTypes::kProjectStructuralDef:
dataObject = new ProjectStructuralDef();
break;
@@ -2627,7 +2692,7 @@ DataReadErrorCode loadDataObject(const PlugInModifierRegistry ®istry, DataRea
Common::SharedPtr<DataObject> sharedPtr(dataObject);
DataReadErrorCode errorCode = dataObject->load(static_cast<DataObjectTypes::DataObjectType>(type), revision, reader);
if (errorCode != kDataReadErrorNone) {
- warning("Data object type 0x%x failed to load", static_cast<int>(type));
+ warning("Data object type 0x%x failed to load (err %d)", static_cast<int>(type), static_cast<int>(errorCode));
outObject.reset();
return errorCode;
}
diff --git a/engines/mtropolis/data.h b/engines/mtropolis/data.h
index a678bdb3649..7f68e638701 100644
--- a/engines/mtropolis/data.h
+++ b/engines/mtropolis/data.h
@@ -54,6 +54,12 @@ enum ProjectFormat {
kProjectFormatNeutral,
};
+enum ProjectEngineVersion {
+ kProjectEngineVersionUnknown,
+ kProjectEngineVersion1,
+ kProjectEngineVersion2,
+};
+
enum DataReadErrorCode {
kDataReadErrorNone = 0,
@@ -88,6 +94,7 @@ enum DataObjectType : uint {
kAssetCatalog = 0xd,
kGlobalObjectInfo = 0x17,
kUnknown19 = 0x19,
+ kUnknown2B = 0x2b,
kProjectStructuralDef = 0x2,
kSectionStructuralDef = 0x3,
@@ -174,7 +181,7 @@ namespace StructuralFlags {
class DataReader {
public:
- DataReader(int64 globalPosition, Common::SeekableReadStreamEndian &stream, ProjectFormat projectFormat);
+ DataReader(int64 globalPosition, Common::SeekableReadStreamEndian &stream, ProjectFormat projectFormat, ProjectEngineVersion projectEngineVersion);
bool readU8(uint8 &value);
bool readU16(uint16 &value);
@@ -208,7 +215,9 @@ public:
inline int64 tellGlobal() const { return _globalPosition + tell(); }
ProjectFormat getProjectFormat() const;
+ ProjectEngineVersion getProjectEngineVersion() const;
bool isBigEndian() const;
+ bool isV2Project() const;
void setPermitDamagedStrings(bool permit);
@@ -217,6 +226,7 @@ private:
Common::SeekableReadStreamEndian &_stream;
ProjectFormat _projectFormat;
+ ProjectEngineVersion _projectEngineVersion;
int64 _globalPosition;
bool _permitDamagedStrings;
@@ -541,6 +551,16 @@ protected:
DataReadErrorCode load(DataReader &reader) override;
};
+struct Unknown2B : public DataObject {
+ Unknown2B();
+
+ uint32 persistFlags;
+ uint32 sizeIncludingTag;
+
+protected:
+ DataReadErrorCode load(DataReader &reader) override;
+};
+
struct StructuralDef : public DataObject {
StructuralDef();
@@ -883,6 +903,7 @@ struct BehaviorModifier : public DataObject {
uint32 unknown4;
uint16 unknown5;
uint32 unknown6;
+ uint32 unknown8; // revision 2 only.
Point editorLayoutPosition;
uint16 lengthOfName;
uint16 numChildren;
@@ -930,6 +951,7 @@ struct MiniscriptProgram {
Common::Array<Attribute> attributes;
ProjectFormat projectFormat;
+ ProjectEngineVersion projectEngineVersion;
bool isBigEndian;
bool load(DataReader &reader);
@@ -944,6 +966,7 @@ struct TypicalModifierHeader {
uint32 guid;
uint8 unknown3[6];
uint32 unknown4;
+ uint32 unknown5; // V2 header only
Point editorLayoutPosition;
uint16 lengthOfName;
diff --git a/engines/mtropolis/detection.cpp b/engines/mtropolis/detection.cpp
index 54c19bbf7c9..fb6f0113f5b 100644
--- a/engines/mtropolis/detection.cpp
+++ b/engines/mtropolis/detection.cpp
@@ -34,6 +34,7 @@ static const PlainGameDescriptor mTropolisGames[] = {
{"albert3", "Uncle Albert's Mysterious Island"},
{"spqr", "SPQR: The Empire's Darkest Hour"},
{"sttgs", "Star Trek: The Game Show"},
+ {"unit", "Unit: Re-Booted"},
{nullptr, nullptr}
};
diff --git a/engines/mtropolis/detection.h b/engines/mtropolis/detection.h
index 507c8e6743e..9818a3ea0b7 100644
--- a/engines/mtropolis/detection.h
+++ b/engines/mtropolis/detection.h
@@ -35,6 +35,7 @@ enum MTropolisGameID {
GID_ALBERT3 = 5,
GID_SPQR = 6,
GID_STTGS = 7,
+ GID_UNIT = 8,
};
// Boot IDs - These can be shared across different variants if the file list and other properties are identical.
@@ -68,6 +69,8 @@ enum MTropolisGameBootID {
MTBOOT_SPQR_RETAIL_MAC,
MTBOOT_STTGS_DEMO_WIN,
+
+ MTBOOT_UNIT_REBOOTED_WIN,
};
enum MTGameFlag {
diff --git a/engines/mtropolis/detection_tables.h b/engines/mtropolis/detection_tables.h
index e31ec9460f7..141dd6ceae7 100644
--- a/engines/mtropolis/detection_tables.h
+++ b/engines/mtropolis/detection_tables.h
@@ -666,6 +666,25 @@ static const MTropolisGameDescription gameDescriptions[] = {
MTBOOT_STTGS_DEMO_WIN,
},
+ { // Unit: Rebooted (Music Videos)
+ {
+ "unit",
+ "",
+ {
+ // { "UNIT32.EXE", 0, "c23dccd2b7a525a9f7bb8505f7c7f2d4", 1085952 },
+ { "DATA.MFX", 0, "9a3a0c2f11173c7af3f16d42a2b7c1b7", 194625739 },
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ GID_UNIT,
+ 0,
+ MTBOOT_UNIT_REBOOTED_WIN,
+ },
+
{ AD_TABLE_END_MARKER, 0, 0, MTBOOT_INVALID }
};
diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index ecba035daf5..9bbb185ec36 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -536,6 +536,10 @@ bool MovieElement::readAttribute(MiniscriptThread *thread, DynamicValue &result,
result.setInt(_currentTimestamp);
return true;
}
+ if (attrib == "timescale") {
+ result.setInt(_timeScale);
+ return true;
+ }
return VisualElement::readAttribute(thread, result, attrib);
}
@@ -633,13 +637,21 @@ void MovieElement::activate() {
}
Video::QuickTimeDecoder *qtDecoder = new Video::QuickTimeDecoder();
- qtDecoder->setChunkBeginOffset(movieAsset->getMovieDataPos());
qtDecoder->setVolume(_volume * 255 / 100);
_videoDecoder.reset(qtDecoder);
_damagedFrames = movieAsset->getDamagedFrames();
- Common::SafeSeekableSubReadStream *movieDataStream = new Common::SafeSeekableSubReadStream(stream, movieAsset->getMovieDataPos(), movieAsset->getMovieDataPos() + movieAsset->getMovieDataSize(), DisposeAfterUse::NO);
+ Common::SafeSeekableSubReadStream *movieDataStream;
+
+ if (movieAsset->getMovieDataSize() > 0) {
+ qtDecoder->setChunkBeginOffset(movieAsset->getMoovAtomPos());
+ movieDataStream = new Common::SafeSeekableSubReadStream(stream, movieAsset->getMovieDataPos(), movieAsset->getMovieDataPos() + movieAsset->getMovieDataSize(), DisposeAfterUse::NO);
+ } else {
+ // If no data size, the movie data is all over the file and the MOOV atom may be after it.
+ movieDataStream = new Common::SafeSeekableSubReadStream(stream, 0, stream->size(), DisposeAfterUse::NO);
+ movieDataStream->seek(movieAsset->getMoovAtomPos());
+ }
if (!_videoDecoder->loadStream(movieDataStream))
_videoDecoder.reset();
diff --git a/engines/mtropolis/miniscript.cpp b/engines/mtropolis/miniscript.cpp
index 50a2afa3dc5..bafba72ef7d 100644
--- a/engines/mtropolis/miniscript.cpp
+++ b/engines/mtropolis/miniscript.cpp
@@ -380,7 +380,7 @@ bool MiniscriptParser::parse(const Data::MiniscriptProgram &program, Common::Sha
}
Common::MemoryReadStreamEndian stream(&program.bytecode[0], program.bytecode.size(), program.isBigEndian);
- Data::DataReader reader(0, stream, program.projectFormat);
+ Data::DataReader reader(0, stream, program.projectFormat, program.projectEngineVersion);
Common::Array<InstructionData> rawInstructions;
rawInstructions.resize(program.numOfInstructions);
@@ -450,7 +450,7 @@ bool MiniscriptParser::parse(const Data::MiniscriptProgram &program, Common::Sha
dataLoc = &rawInstruction.contents[0];
Common::MemoryReadStreamEndian instrContentsStream(static_cast<const byte *>(dataLoc), rawInstruction.contents.size(), reader.isBigEndian());
- Data::DataReader instrContentsReader(0, instrContentsStream, reader.getProjectFormat());
+ Data::DataReader instrContentsReader(0, instrContentsStream, reader.getProjectFormat(), reader.getProjectEngineVersion());
if (!rawInstruction.instrFactory->create(&programData[baseOffset + rawInstruction.pdPosition], rawInstruction.flags, instrContentsReader, miniscriptInstructions[i], parserFeedback)) {
// Destroy any already-created instructions
diff --git a/engines/mtropolis/mtropolis.cpp b/engines/mtropolis/mtropolis.cpp
index 494584397df..99475c22d29 100644
--- a/engines/mtropolis/mtropolis.cpp
+++ b/engines/mtropolis/mtropolis.cpp
@@ -161,22 +161,23 @@ Common::Error MTropolisEngine::run() {
preferredHeight = 360;
HackSuites::addObsidianImprovedWidescreen(*_gameDescription, _runtime->getHacks());
}
- }
-
- if (_gameDescription->gameID == GID_MTI) {
+ } else if (_gameDescription->gameID == GID_MTI) {
preferredWidth = 640;
preferredHeight = 480;
preferredColorDepthMode = kColorDepthMode8Bit;
enhancedColorDepthMode = kColorDepthMode32Bit;
HackSuites::addMTIQuirks(*_gameDescription, _runtime->getHacks());
- }
-
- if (_gameDescription->gameID == GID_SPQR) {
+ } else if (_gameDescription->gameID == GID_SPQR) {
preferredWidth = 640;
preferredHeight = 480;
preferredColorDepthMode = kColorDepthMode8Bit;
enhancedColorDepthMode = kColorDepthMode32Bit;
+ } else if (_gameDescription->gameID == GID_UNIT) {
+ preferredWidth = 640;
+ preferredHeight = 480;
+ preferredColorDepthMode = kColorDepthMode32Bit;
+ enhancedColorDepthMode = kColorDepthMode32Bit;
}
if (ConfMan.getBool("mtropolis_mod_minimum_transition_duration"))
diff --git a/engines/mtropolis/plugin/standard_data.cpp b/engines/mtropolis/plugin/standard_data.cpp
index 1cb6038ed0f..b7ee40404a5 100644
--- a/engines/mtropolis/plugin/standard_data.cpp
+++ b/engines/mtropolis/plugin/standard_data.cpp
@@ -32,7 +32,7 @@ CursorModifier::CursorModifier() : haveRemoveWhen(false) {
}
DataReadErrorCode CursorModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
- if (prefix.plugInRevision != 0 && prefix.plugInRevision != 1)
+ if (prefix.plugInRevision != 0 && prefix.plugInRevision != 1 && prefix.plugInRevision != 2)
return kDataReadErrorUnsupportedRevision;
if (!applyWhen.load(reader))
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index 6c6dfb4a53a..48882b93779 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -6971,6 +6971,7 @@ void Project::loadFromDescription(const ProjectDescription &desc, const Hacks &h
const Data::PlugInModifierRegistry &plugInDataLoaderRegistry = _plugInRegistry.getDataLoaderRegistry();
size_t numSegments = desc.getSegments().size();
+ debug(1, "Loading %d segments", (int)numSegments);
_segments.resize(numSegments);
for (size_t i = 0; i < numSegments; i++) {
@@ -6992,15 +6993,24 @@ void Project::loadFromDescription(const ProjectDescription &desc, const Hacks &h
_isBigEndian = true;
_projectFormat = Data::kProjectFormatMacintosh;
} else {
- error("Unrecognized project segment header");
+ warning("Unrecognized project segment header (startValue: %d)", startValue);
+ _projectFormat = Data::kProjectFormatWindows;
}
Common::SeekableSubReadStreamEndian stream(baseStream, 2, baseStream->size(), _isBigEndian);
- if (stream.readUint32() != 0xaa55a5a5 || stream.readUint32() != 0 || stream.readUint32() != 14) {
- error("Unrecognized project segment header");
+ const uint32 magic = stream.readUint32();
+ const uint32 hdr1 = stream.readUint32();
+ const uint32 hdr2 = stream.readUint32();
+ if (magic != 0xaa55a5a5 || (hdr1 != 0 && hdr1 != 0x2000000) || hdr2 != 14) {
+ error("Unrecognized project segment header (%x, %x, %d)", magic, hdr1, hdr2);
}
- Data::DataReader reader(2, stream, _projectFormat);
+ if (hdr1 == 0)
+ _projectEngineVersion = Data::kProjectEngineVersion1;
+ else
+ _projectEngineVersion = Data::kProjectEngineVersion2;
+
+ Data::DataReader reader(2, stream, _projectFormat, _projectEngineVersion);
Common::SharedPtr<Data::DataObject> dataObject;
Data::loadDataObject(_plugInRegistry.getDataLoaderRegistry(), reader, dataObject);
@@ -7027,11 +7037,11 @@ void Project::loadFromDescription(const ProjectDescription &desc, const Hacks &h
StreamDesc &streamDesc = _streams[i];
const Data::ProjectCatalog::StreamDesc &srcStream = catalog->streams[i];
- if (!strcmp(srcStream.streamType, "assetStream"))
+ if (!strcmp(srcStream.streamType, "assetStream") || !strcmp(srcStream.streamType, "assetstream"))
streamDesc.streamType = kStreamTypeAsset;
- else if (!strcmp(srcStream.streamType, "bootStream"))
+ else if (!strcmp(srcStream.streamType, "bootStream") || !strcmp(srcStream.streamType, "bootstream"))
streamDesc.streamType = kStreamTypeBoot;
- else if (!strcmp(srcStream.streamType, "sceneStream"))
+ else if (!strcmp(srcStream.streamType, "sceneStream") || !strcmp(srcStream.streamType, "scenestream"))
streamDesc.streamType = kStreamTypeScene;
else
streamDesc.streamType = kStreamTypeUnknown;
@@ -7075,7 +7085,7 @@ void Project::loadSceneFromStream(const Common::SharedPtr<Structural> &scene, ui
openSegmentStream(segmentIndex);
Common::SeekableSubReadStreamEndian stream(_segments[segmentIndex].weakStream, streamDesc.pos, streamDesc.pos + streamDesc.size, _isBigEndian);
- Data::DataReader reader(streamDesc.pos, stream, _projectFormat);
+ Data::DataReader reader(streamDesc.pos, stream, _projectFormat, _projectEngineVersion);
if (getRuntime()->getHacks().mtiHispaniolaDamagedStringHack && scene->getName() == "C01b : Main Deck Helm Kidnap")
reader.setPermitDamagedStrings(true);
@@ -7203,7 +7213,7 @@ void Project::forceLoadAsset(uint32 assetID, Common::Array<Common::SharedPtr<Ass
openSegmentStream(segmentIndex);
Common::SeekableSubReadStreamEndian stream(_segments[segmentIndex].weakStream, streamDesc.pos, streamDesc.pos + streamDesc.size, _isBigEndian);
- Data::DataReader reader(streamDesc.pos, stream, _projectFormat);
+ Data::DataReader reader(streamDesc.pos, stream, _projectFormat, _projectEngineVersion);
const Data::PlugInModifierRegistry &plugInDataLoaderRegistry = _plugInRegistry.getDataLoaderRegistry();
@@ -7363,7 +7373,7 @@ void Project::loadBootStream(size_t streamIndex, const Hacks &hacks) {
openSegmentStream(segmentIndex);
Common::SeekableSubReadStreamEndian stream(_segments[segmentIndex].weakStream, streamDesc.pos, streamDesc.pos + streamDesc.size, _isBigEndian);
- Data::DataReader reader(streamDesc.pos, stream, _projectFormat);
+ Data::DataReader reader(streamDesc.pos, stream, _projectFormat, _projectEngineVersion);
ChildLoaderStack loaderStack;
AssetDefLoaderContext assetDefLoader;
@@ -7423,6 +7433,7 @@ void Project::loadBootStream(size_t streamIndex, const Hacks &hacks) {
} break;
case Data::DataObjectTypes::kStreamHeader:
case Data::DataObjectTypes::kUnknown19:
+ case Data::DataObjectTypes::kUnknown2B:
// Ignore
break;
default:
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 9c5c7e1b650..7213f761aaf 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -2522,6 +2522,7 @@ private:
Common::Array<LabelTree> _labelTree;
Common::Array<LabelSuperGroup> _labelSuperGroups;
Data::ProjectFormat _projectFormat;
+ Data::ProjectEngineVersion _projectEngineVersion;
bool _isBigEndian;
Common::Array<AssetDesc *> _assetsByID;
More information about the Scummvm-git-logs
mailing list