[Scummvm-git-logs] scummvm master -> 06e1446d5e76bd394ea0c6e5bd35cab10c7e06fa
npjg
noreply at scummvm.org
Sat May 10 21:25:50 UTC 2025
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
100e7267a3 MEDIASTATION: Give datum types correct names
b53def9abf MEDIASTATION: Use stream methods to read typed fields
a43e097df1 MEDIASTATION: Simplify Boot stream parsing
1e76610489 MEDIASTATION: Correctly implement collection methods
a5c12ca646 MEDIASTATION: Make the screen asset actually an asset
06e1446d5e MEDIASTATION: Use one hashmap for event handlers
Commit: 100e7267a3e7dd40d8a87d2b7f674dee333b6a71
https://github.com/scummvm/scummvm/commit/100e7267a3e7dd40d8a87d2b7f674dee333b6a71
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-05-10T17:15:44-04:00
Commit Message:
MEDIASTATION: Give datum types correct names
Changed paths:
engines/mediastation/assetheader.cpp
engines/mediastation/assets/sprite.cpp
engines/mediastation/bitmap.cpp
engines/mediastation/boot.cpp
engines/mediastation/context.cpp
engines/mediastation/datum.cpp
engines/mediastation/datum.h
engines/mediastation/mediascript/codechunk.cpp
diff --git a/engines/mediastation/assetheader.cpp b/engines/mediastation/assetheader.cpp
index c808d1a34c5..2d866cd05e8 100644
--- a/engines/mediastation/assetheader.cpp
+++ b/engines/mediastation/assetheader.cpp
@@ -167,29 +167,29 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
// - They might be in the same RIFF subfile as this header,
// - They might be in a different RIFF subfile in the same CXT file,
// - They might be in a different CXT file entirely.
- _chunkReference = Datum(chunk, kDatumTypeReference).u.i;
+ _chunkReference = Datum(chunk, kDatumTypeChunkReference).u.i;
break;
}
case kAssetHeaderMovieAudioChunkReference: {
- _audioChunkReference = Datum(chunk, kDatumTypeReference).u.i;
+ _audioChunkReference = Datum(chunk, kDatumTypeChunkReference).u.i;
break;
}
case kAssetHeaderMovieAnimationChunkReference: {
- _animationChunkReference = Datum(chunk, kDatumTypeReference).u.i;
+ _animationChunkReference = Datum(chunk, kDatumTypeChunkReference).u.i;
break;
}
case kAssetHeaderBoundingBox: {
- _boundingBox = Datum(chunk, kDatumTypeBoundingBox).u.bbox;
+ _boundingBox = Datum(chunk, kDatumTypeRect).u.bbox;
break;
}
case kAssetHeaderMouseActiveArea: {
- uint16 total_points = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint16 total_points = Datum(chunk, kDatumTypeUint16).u.i;
for (int i = 0; i < total_points; i++) {
- Common::Point *point = Datum(chunk, kDatumTypePoint2).u.point;
+ Common::Point *point = Datum(chunk, kDatumTypePoint).u.point;
_mouseActiveArea.push_back(point);
}
break;
@@ -226,7 +226,7 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
}
case kAssetHeaderFrameRate: {
- _frameRate = static_cast<uint32>(Datum(chunk, kDatumTypeFloat64_2).u.f);
+ _frameRate = static_cast<uint32>(Datum(chunk, kDatumTypeDouble).u.f);
break;
}
@@ -279,17 +279,17 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
}
case kAssetHeaderStartPoint: {
- _startPoint = Datum(chunk, kDatumTypePoint2).u.point;
+ _startPoint = Datum(chunk, kDatumTypePoint).u.point;
break;
}
case kAssetHeaderEndPoint: {
- _endPoint = Datum(chunk, kDatumTypePoint2).u.point;
+ _endPoint = Datum(chunk, kDatumTypePoint).u.point;
break;
}
case kAssetHeaderStepRate: {
- double _stepRateFloat = Datum(chunk, kDatumTypeFloat64_2).u.f;
+ double _stepRateFloat = Datum(chunk, kDatumTypeDouble).u.f;
// This should always be an integer anyway,
// so we'll cast away any fractional part.
_stepRate = static_cast<uint32>(_stepRateFloat);
@@ -373,7 +373,7 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
}
AssetHeaderSectionType AssetHeader::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16_1);
+ Datum datum = Datum(chunk, kDatumTypeUint16);
AssetHeaderSectionType sectionType = static_cast<AssetHeaderSectionType>(datum.u.i);
return sectionType;
}
diff --git a/engines/mediastation/assets/sprite.cpp b/engines/mediastation/assets/sprite.cpp
index 6528a0c7826..9911e83c231 100644
--- a/engines/mediastation/assets/sprite.cpp
+++ b/engines/mediastation/assets/sprite.cpp
@@ -29,7 +29,7 @@ namespace MediaStation {
SpriteFrameHeader::SpriteFrameHeader(Chunk &chunk) : BitmapHeader(chunk) {
_index = Datum(chunk).u.i;
debugC(5, kDebugLoading, "SpriteFrameHeader::SpriteFrameHeader(): _index = 0x%x (@0x%llx)", _index, static_cast<long long int>(chunk.pos()));
- _boundingBox = Datum(chunk, kDatumTypePoint2).u.point;
+ _boundingBox = Datum(chunk, kDatumTypePoint).u.point;
debugC(5, kDebugLoading, "SpriteFrameHeader::SpriteFrameHeader(): _boundingBox (@0x%llx)", static_cast<long long int>(chunk.pos()));
}
diff --git a/engines/mediastation/bitmap.cpp b/engines/mediastation/bitmap.cpp
index dd5ec9e044f..37153b32821 100644
--- a/engines/mediastation/bitmap.cpp
+++ b/engines/mediastation/bitmap.cpp
@@ -26,16 +26,16 @@
namespace MediaStation {
BitmapHeader::BitmapHeader(Chunk &chunk) {
- uint headerSizeInBytes = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint headerSizeInBytes = Datum(chunk, kDatumTypeUint16).u.i;
debugC(5, kDebugLoading, "BitmapHeader::BitmapHeader(): headerSize = 0x%x", headerSizeInBytes);
_dimensions = Datum(chunk).u.point;
- _compressionType = static_cast<BitmapCompressionType>(Datum(chunk, kDatumTypeUint16_1).u.i);
+ _compressionType = static_cast<BitmapCompressionType>(Datum(chunk, kDatumTypeUint16).u.i);
debugC(5, kDebugLoading, "BitmapHeader::BitmapHeader(): _compressionType = 0x%x", static_cast<uint>(_compressionType));
// TODO: Figure out what this is.
// This has something to do with the width of the bitmap but is always
// a few pixels off from the width. And in rare cases it seems to be
// the true width!
- unk2 = Datum(chunk, kDatumTypeUint16_1).u.i;
+ unk2 = Datum(chunk, kDatumTypeUint16).u.i;
}
BitmapHeader::~BitmapHeader() {
diff --git a/engines/mediastation/boot.cpp b/engines/mediastation/boot.cpp
index 8e7aa9c16d0..7100cbbe7a8 100644
--- a/engines/mediastation/boot.cpp
+++ b/engines/mediastation/boot.cpp
@@ -27,9 +27,9 @@ namespace MediaStation {
#pragma region VersionInfo
VersionInfo::VersionInfo(Chunk &chunk) {
- _majorVersion = Datum(chunk, kDatumTypeUint16_1).u.i;
- _minorVersion = Datum(chunk, kDatumTypeUint16_1).u.i;
- _revision = Datum(chunk, kDatumTypeUint16_1).u.i;
+ _majorVersion = Datum(chunk, kDatumTypeUint16).u.i;
+ _minorVersion = Datum(chunk, kDatumTypeUint16).u.i;
+ _revision = Datum(chunk, kDatumTypeUint16).u.i;
string = Datum(chunk, kDatumTypeString).u.string;
}
@@ -108,7 +108,7 @@ ContextDeclaration::ContextDeclaration(Chunk &chunk) {
}
ContextDeclarationSectionType ContextDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16_1);
+ Datum datum = Datum(chunk, kDatumTypeUint16);
ContextDeclarationSectionType sectionType = static_cast<ContextDeclarationSectionType>(datum.u.i);
return sectionType;
}
@@ -133,13 +133,13 @@ UnknownDeclaration::UnknownDeclaration(Chunk &chunk) {
sectionType = getSectionType(chunk);
if (kUnknownDeclarationUnk1 == sectionType) {
- _unk = Datum(chunk, kDatumTypeUint16_1).u.i;
+ _unk = Datum(chunk, kDatumTypeUint16).u.i;
} else {
error("UnknownDeclaration(): Expected section type UNK_1, got 0x%x", static_cast<uint>(sectionType));
}
sectionType = getSectionType(chunk);
if (kUnknownDeclarationUnk2 == sectionType) {
- uint16 repeatedUnk = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint16 repeatedUnk = Datum(chunk, kDatumTypeUint16).u.i;
if (repeatedUnk != _unk) {
warning("UnknownDeclaration(): Expected unknown values to match, but 0x%x != 0x%x", _unk, repeatedUnk);
}
@@ -149,7 +149,7 @@ UnknownDeclaration::UnknownDeclaration(Chunk &chunk) {
}
UnknownDeclarationSectionType UnknownDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16_1);
+ Datum datum = Datum(chunk, kDatumTypeUint16);
UnknownDeclarationSectionType sectionType = static_cast<UnknownDeclarationSectionType>(datum.u.i);
return sectionType;
}
@@ -170,7 +170,7 @@ FileDeclaration::FileDeclaration(Chunk &chunk) {
// Read the file ID.
sectionType = getSectionType(chunk);
if (kFileDeclarationFileId == sectionType) {
- _id = Datum(chunk, kDatumTypeUint16_1).u.i;
+ _id = Datum(chunk, kDatumTypeUint16).u.i;
} else {
error("FileDeclaration(): Expected section type FILE_ID, got 0x%x", static_cast<uint>(sectionType));
}
@@ -178,7 +178,7 @@ FileDeclaration::FileDeclaration(Chunk &chunk) {
// Read the intended file location.
sectionType = getSectionType(chunk);
if (kFileDeclarationFileNameAndType == sectionType) {
- Datum datum = Datum(chunk, kDatumTypeUint16_1);
+ Datum datum = Datum(chunk, kDatumTypeUint16);
// TODO: Verify we actually read a valid enum member.
_intendedLocation = static_cast<IntendedFileLocation>(datum.u.i);
} else {
@@ -192,7 +192,7 @@ FileDeclaration::FileDeclaration(Chunk &chunk) {
}
FileDeclarationSectionType FileDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16_1);
+ Datum datum = Datum(chunk, kDatumTypeUint16);
FileDeclarationSectionType sectionType = static_cast<FileDeclarationSectionType>(datum.u.i);
return sectionType;
}
@@ -218,7 +218,7 @@ SubfileDeclaration::SubfileDeclaration(Chunk &chunk) {
// Read the asset ID.
sectionType = getSectionType(chunk);
if (kSubfileDeclarationAssetId == sectionType) {
- _assetId = Datum(chunk, kDatumTypeUint16_1).u.i;
+ _assetId = Datum(chunk, kDatumTypeUint16).u.i;
} else {
error("SubfileDeclaration(): Expected section type ASSET_ID, got 0x%x", static_cast<uint>(sectionType));
}
@@ -226,7 +226,7 @@ SubfileDeclaration::SubfileDeclaration(Chunk &chunk) {
// Read the file ID.
sectionType = getSectionType(chunk);
if (kSubfileDeclarationFileId == sectionType) {
- _fileId = Datum(chunk, kDatumTypeUint16_1).u.i;
+ _fileId = Datum(chunk, kDatumTypeUint16).u.i;
} else {
error("SubfileDeclaration(): Expected section type FILE_ID, got 0x%x", static_cast<uint>(sectionType));
}
@@ -234,14 +234,14 @@ SubfileDeclaration::SubfileDeclaration(Chunk &chunk) {
// Read the start offset from the absolute start of the file.
sectionType = getSectionType(chunk);
if (kSubfileDeclarationStartOffset == sectionType) {
- _startOffsetInFile = Datum(chunk, kDatumTypeUint32_1).u.i;
+ _startOffsetInFile = Datum(chunk, kDatumTypeUint32).u.i;
} else {
error("SubfileDeclaration(): Expected section type START_OFFSET, got 0x%x", static_cast<uint>(sectionType));
}
}
SubfileDeclarationSectionType SubfileDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16_1);
+ Datum datum = Datum(chunk, kDatumTypeUint16);
SubfileDeclarationSectionType sectionType = static_cast<SubfileDeclarationSectionType>(datum.u.i);
return sectionType;
}
@@ -249,9 +249,9 @@ SubfileDeclarationSectionType SubfileDeclaration::getSectionType(Chunk &chunk) {
#pragma region CursorDeclaration
CursorDeclaration::CursorDeclaration(Chunk& chunk) {
- uint16 unk1 = Datum(chunk, kDatumTypeUint16_1).u.i; // Always 0x0001
- _id = Datum(chunk, kDatumTypeUint16_1).u.i;
- _unk = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint16 unk1 = Datum(chunk, kDatumTypeUint16).u.i; // Always 0x0001
+ _id = Datum(chunk, kDatumTypeUint16).u.i;
+ _unk = Datum(chunk, kDatumTypeUint16).u.i;
_name = Datum(chunk, kDatumTypeFilename).u.string;
debugC(5, kDebugLoading, " - CursorDeclaration(): unk1 = 0x%x, id = 0x%x, unk = 0x%x, name = %s", unk1, _id, _unk, _name->c_str());
}
@@ -276,7 +276,7 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
Subfile subfile = getNextSubfile();
Chunk chunk = subfile.nextChunk();
- uint32 beforeSectionTypeUnk = Datum(chunk, kDatumTypeUint16_1).u.i; // Usually 0x0001
+ uint32 beforeSectionTypeUnk = Datum(chunk, kDatumTypeUint16).u.i; // Usually 0x0001
debugC(5, kDebugLoading, "Boot::Boot(): unk1 = 0x%x", beforeSectionTypeUnk);
BootSectionType sectionType = getSectionType(chunk);
@@ -419,7 +419,7 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
}
BootSectionType Boot::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16_1);
+ Datum datum = Datum(chunk, kDatumTypeUint16);
BootSectionType sectionType = static_cast<BootSectionType>(datum.u.i);
return sectionType;
}
diff --git a/engines/mediastation/context.cpp b/engines/mediastation/context.cpp
index 86f88d43ab8..dfe0af50948 100644
--- a/engines/mediastation/context.cpp
+++ b/engines/mediastation/context.cpp
@@ -160,20 +160,20 @@ void Context::registerActiveAssets() {
}
void Context::readParametersSection(Chunk &chunk) {
- _fileNumber = Datum(chunk, kDatumTypeUint16_1).u.i;
+ _fileNumber = Datum(chunk, kDatumTypeUint16).u.i;
- ContextParametersSectionType sectionType = static_cast<ContextParametersSectionType>(Datum(chunk, kDatumTypeUint16_1).u.i);
+ ContextParametersSectionType sectionType = static_cast<ContextParametersSectionType>(Datum(chunk, kDatumTypeUint16).u.i);
while (sectionType != kContextParametersEmptySection) {
debugC(5, kDebugLoading, "ContextParameters::ContextParameters: sectionType = 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
switch (sectionType) {
case kContextParametersName: {
- uint repeatedFileNumber = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint repeatedFileNumber = Datum(chunk, kDatumTypeUint16).u.i;
if (repeatedFileNumber != _fileNumber) {
warning("ContextParameters::ContextParameters(): Repeated file number didn't match: %d != %d", repeatedFileNumber, _fileNumber);
}
_contextName = Datum(chunk, kDatumTypeString).u.string;
- uint endingFlag = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint endingFlag = Datum(chunk, kDatumTypeUint16).u.i;
if (endingFlag != 0) {
warning("ContextParameters::ContextParameters(): Got non-zero ending flag 0x%x", endingFlag);
}
@@ -200,12 +200,12 @@ void Context::readParametersSection(Chunk &chunk) {
error("ContextParameters::ContextParameters(): Unknown section type 0x%x", static_cast<uint>(sectionType));
}
- sectionType = static_cast<ContextParametersSectionType>(Datum(chunk, kDatumTypeUint16_1).u.i);
+ sectionType = static_cast<ContextParametersSectionType>(Datum(chunk, kDatumTypeUint16).u.i);
}
}
void Context::readVariable(Chunk &chunk) {
- uint repeatedFileNumber = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint repeatedFileNumber = Datum(chunk, kDatumTypeUint16).u.i;
if (repeatedFileNumber != _fileNumber) {
warning("Context::readVariable(): Repeated file number didn't match: %d != %d", repeatedFileNumber, _fileNumber);
}
@@ -234,7 +234,7 @@ void Context::readNewStyleHeaderSections(Subfile &subfile, Chunk &chunk) {
while (moreSectionsToRead) {
// Verify this chunk is a header.
// TODO: What are the situations when it's not?
- uint16 sectionType = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint16 sectionType = Datum(chunk, kDatumTypeUint16).u.i;
debugC(5, kDebugLoading, "Context::readNewStyleHeaderSections(): sectionType = 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
bool chunkIsHeader = (sectionType == 0x000d);
if (!chunkIsHeader) {
@@ -291,7 +291,7 @@ void Context::readAssetFromLaterSubfile(Subfile &subfile) {
}
bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
- uint16 sectionType = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint16 sectionType = Datum(chunk, kDatumTypeUint16).u.i;
debugC(5, kDebugLoading, "Context::readHeaderSection(): sectionType = 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
switch (sectionType) {
case kContextParametersSection: {
@@ -318,7 +318,7 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
delete[] buffer;
debugC(5, kDebugLoading, "Context::readHeaderSection(): Read palette");
// This is likely just an ending flag that we expect to be zero.
- uint endingFlag = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint endingFlag = Datum(chunk, kDatumTypeUint16).u.i;
if (endingFlag != 0) {
warning("Context::readHeaderSection(): Got non-zero ending flag 0x%x", endingFlag);
}
diff --git a/engines/mediastation/datum.cpp b/engines/mediastation/datum.cpp
index 9dd46ad28f2..a2b0bf97fba 100644
--- a/engines/mediastation/datum.cpp
+++ b/engines/mediastation/datum.cpp
@@ -25,7 +25,7 @@
namespace MediaStation {
Datum::Datum() {
- t = kDatumTypeInvalid;
+ t = kDatumTypeEmpty;
u.i = 0;
}
@@ -47,43 +47,43 @@ void Datum::readWithType(Common::SeekableReadStream &chunk) {
if (kDatumTypeUint8 == t) {
u.i = chunk.readByte();
- } else if (kDatumTypeUint16_1 == t || kDatumTypeUint16_2 == t) {
+ } else if (kDatumTypeUint16 == t || kDatumTypeVersion == t) {
u.i = chunk.readUint16LE();
- } else if (kDatumTypeInt16_1 == t || kDatumTypeInt16_2 == t) {
+ } else if (kDatumTypeInt16 == t || kDatumTypeGraphicUnit == t) {
u.i = chunk.readSint16LE();
- } else if (kDatumTypeUint32_1 == t || kDatumTypeUint32_2 == t) {
+ } else if (kDatumTypeUint32 == t || kDatumTypeInt32 == t) {
u.i = chunk.readUint32LE();
- } else if (kDatumTypeFloat64_1 == t || kDatumTypeFloat64_2 == t) {
+ } else if (kDatumTypeTime == t || kDatumTypeDouble == t) {
u.f = chunk.readDoubleLE();
} else if (kDatumTypeString == t || kDatumTypeFilename == t) {
// TODO: This copies the string. Can we read it directly from the chunk?
- int size = Datum(chunk, kDatumTypeUint32_1).u.i;
+ int size = Datum(chunk, kDatumTypeUint32).u.i;
char *buffer = new char[size + 1];
chunk.read(buffer, size);
buffer[size] = '\0';
u.string = new Common::String(buffer);
delete[] buffer;
- } else if (kDatumTypePoint1 == t || kDatumTypePoint2 == t) {
- uint16 x = Datum(chunk, kDatumTypeInt16_2).u.i;
- uint16 y = Datum(chunk, kDatumTypeInt16_2).u.i;
+ } else if (kDatumTypeGraphicSize == t || kDatumTypePoint == t) {
+ uint16 x = Datum(chunk, kDatumTypeGraphicUnit).u.i;
+ uint16 y = Datum(chunk, kDatumTypeGraphicUnit).u.i;
u.point = new Common::Point(x, y);
- } else if (kDatumTypeBoundingBox == t) {
- Common::Point *leftTop = Datum(chunk, kDatumTypePoint2).u.point;
- Common::Point *dimensions = Datum(chunk, kDatumTypePoint1).u.point;
+ } else if (kDatumTypeRect == t) {
+ Common::Point *leftTop = Datum(chunk, kDatumTypePoint).u.point;
+ Common::Point *dimensions = Datum(chunk, kDatumTypeGraphicSize).u.point;
u.bbox = new Common::Rect(*leftTop, dimensions->x, dimensions->y);
delete leftTop;
delete dimensions;
} else if (kDatumTypePolygon == t) {
- uint16 totalPoints = Datum(chunk, kDatumTypeUint16_1).u.i;
+ uint16 totalPoints = Datum(chunk, kDatumTypeUint16).u.i;
for (int i = 0; i < totalPoints; i++) {
- Common::Point *point = Datum(chunk, kDatumTypePoint1).u.point;
+ Common::Point *point = Datum(chunk, kDatumTypeGraphicSize).u.point;
u.polygon->push_back(point);
}
@@ -91,7 +91,7 @@ void Datum::readWithType(Common::SeekableReadStream &chunk) {
u.palette = new unsigned char[0x300];
chunk.read(u.palette, 0x300);
- } else if (kDatumTypeReference == t) {
+ } else if (kDatumTypeChunkReference == t) {
u.chunkRef = chunk.readUint32BE();
} else {
diff --git a/engines/mediastation/datum.h b/engines/mediastation/datum.h
index 55dc6d025f1..a5b303c43bf 100644
--- a/engines/mediastation/datum.h
+++ b/engines/mediastation/datum.h
@@ -32,31 +32,26 @@
namespace MediaStation {
enum DatumType {
- // This type isn't a type we see in data files; it is just a
- // default initialization value.
- kDatumTypeInvalid = 0x0000,
-
- kDatumTypeUint8 = 0x0002,
- // TODO: Understand why there are different (u)int16 type codes.
- kDatumTypeUint16_1 = 0x0003,
- kDatumTypeUint16_2 = 0x0013,
- kDatumTypeInt16_1 = 0x0006,
- kDatumTypeInt16_2 = 0x0010,
- // TODO: Understand why there are two different uint32 type codes.
- kDatumTypeUint32_1 = 0x0004,
- kDatumTypeUint32_2 = 0x0007,
- // TODO: Understand why there are two different float64 type codes.
- kDatumTypeFloat64_1 = 0x0011,
- kDatumTypeFloat64_2 = 0x0009,
- kDatumTypeString = 0x0012,
- kDatumTypeFilename = 0x000a,
- kDatumTypePoint1 = 0x000f,
- kDatumTypePoint2 = 0x000e,
- kDatumTypeBoundingBox = 0x000d,
- kDatumTypePolygon = 0x001d,
- // These are other types.
- kDatumTypePalette = 0x05aa,
- kDatumTypeReference = 0x001b
+ kDatumTypeEmpty = 0x00,
+ kDatumTypeUint8 = 0x02,
+ kDatumTypeUint16 = 0x03,
+ kDatumTypeUint32 = 0x04,
+ kDatumTypeInt8 = 0x05,
+ kDatumTypeInt16 = 0x06,
+ kDatumTypeInt32 = 0x07,
+ kDatumTypeFloat = 0x08,
+ kDatumTypeDouble = 0x09,
+ kDatumTypeFilename = 0x0a,
+ kDatumTypeRect = 0x0d,
+ kDatumTypePoint = 0x0e,
+ kDatumTypeGraphicSize = 0x0f,
+ kDatumTypeGraphicUnit = 0x10,
+ kDatumTypeTime = 0x11,
+ kDatumTypeString = 0x12,
+ kDatumTypeVersion = 0x13,
+ kDatumTypeChunkReference = 0x1b,
+ kDatumTypePolygon = 0x1d,
+ kDatumTypePalette = 0x05aa
};
// It is the caller's responsibility to delete any heap items
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 5a065d1ba9f..5c95b000f77 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -30,13 +30,13 @@
namespace MediaStation {
CodeChunk::CodeChunk(Common::SeekableReadStream &chunk) {
- uint lengthInBytes = Datum(chunk, kDatumTypeUint32_1).u.i;
+ uint lengthInBytes = Datum(chunk, kDatumTypeUint32).u.i;
debugC(5, kDebugLoading, "CodeChunk::CodeChunk(): Length 0x%x (@0x%llx)", lengthInBytes, static_cast<long long int>(chunk.pos()));
_bytecode = chunk.readStream(lengthInBytes);
}
ScriptValue CodeChunk::executeNextBlock() {
- uint blockSize = Datum(*_bytecode, kDatumTypeUint32_1).u.i;
+ uint blockSize = Datum(*_bytecode, kDatumTypeUint32).u.i;
uint startingPos = _bytecode->pos();
ScriptValue returnValue;
@@ -57,7 +57,7 @@ ScriptValue CodeChunk::executeNextBlock() {
}
void CodeChunk::skipNextBlock() {
- uint lengthInBytes = Datum(*_bytecode, kDatumTypeUint32_1).u.i;
+ uint lengthInBytes = Datum(*_bytecode, kDatumTypeUint32).u.i;
_bytecode->skip(lengthInBytes);
}
@@ -219,7 +219,7 @@ ScriptValue CodeChunk::evaluateValue() {
case kOperandTypeString: {
// This is indeed a raw string, not a string wrapped in a datum!
- uint size = Datum(*_bytecode, kDatumTypeUint16_1).u.i;
+ uint size = Datum(*_bytecode, kDatumTypeUint16).u.i;
Common::String string = _bytecode->readString('\0', size);
debugC(5, kDebugScript, "%s ", string.c_str());
returnValue.setToString(string);
Commit: b53def9abf0674100d0f6bda253837b049542d72
https://github.com/scummvm/scummvm/commit/b53def9abf0674100d0f6bda253837b049542d72
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-05-10T17:24:32-04:00
Commit Message:
MEDIASTATION: Use stream methods to read typed fields
Instead of Datum class, which is now removed.
Changed paths:
R engines/mediastation/datum.cpp
R engines/mediastation/datum.h
engines/mediastation/asset.cpp
engines/mediastation/asset.h
engines/mediastation/assetheader.cpp
engines/mediastation/assetheader.h
engines/mediastation/assets/font.cpp
engines/mediastation/assets/hotspot.cpp
engines/mediastation/assets/image.cpp
engines/mediastation/assets/movie.cpp
engines/mediastation/assets/sprite.cpp
engines/mediastation/assets/sprite.h
engines/mediastation/assets/text.cpp
engines/mediastation/assets/text.h
engines/mediastation/bitmap.cpp
engines/mediastation/bitmap.h
engines/mediastation/boot.cpp
engines/mediastation/boot.h
engines/mediastation/context.cpp
engines/mediastation/context.h
engines/mediastation/datafile.cpp
engines/mediastation/datafile.h
engines/mediastation/mediascript/codechunk.cpp
engines/mediastation/mediascript/codechunk.h
engines/mediastation/mediascript/collection.cpp
engines/mediastation/mediascript/collection.h
engines/mediastation/mediascript/eventhandler.cpp
engines/mediastation/mediascript/eventhandler.h
engines/mediastation/mediascript/function.cpp
engines/mediastation/mediascript/scriptvalue.cpp
engines/mediastation/mediascript/scriptvalue.h
engines/mediastation/mediastation.cpp
engines/mediastation/module.mk
diff --git a/engines/mediastation/asset.cpp b/engines/mediastation/asset.cpp
index 04a3f5d3c54..a08f0a3d96e 100644
--- a/engines/mediastation/asset.cpp
+++ b/engines/mediastation/asset.cpp
@@ -46,7 +46,7 @@ int Asset::zIndex() const {
return _header->_zIndex;
}
-Common::Rect *Asset::getBbox() {
+Common::Rect Asset::getBbox() const {
return _header->_boundingBox;
}
diff --git a/engines/mediastation/asset.h b/engines/mediastation/asset.h
index 1aa756333ec..9d84f597ecb 100644
--- a/engines/mediastation/asset.h
+++ b/engines/mediastation/asset.h
@@ -71,10 +71,10 @@ public:
AssetType type() const;
int zIndex() const;
+ Common::Rect getBbox() const;
AssetHeader *getHeader() const {
return _header;
}
- Common::Rect *getBbox();
protected:
AssetHeader *_header = nullptr;
diff --git a/engines/mediastation/assetheader.cpp b/engines/mediastation/assetheader.cpp
index 2d866cd05e8..6e9d8f87185 100644
--- a/engines/mediastation/assetheader.cpp
+++ b/engines/mediastation/assetheader.cpp
@@ -19,39 +19,27 @@
*
*/
-#include "mediastation/datum.h"
#include "mediastation/assetheader.h"
#include "mediastation/debugchannels.h"
namespace MediaStation {
AssetHeader::AssetHeader(Chunk &chunk) {
- // I arbitrarily chose the bitmap as the default union member,
- // but they are all pointers so it doesn't matter.
- _fileNumber = Datum(chunk).u.i;
- // TODO: Cast to an asset type.
- _type = static_cast<AssetType>(Datum(chunk).u.i);
- _id = Datum(chunk).u.i;
+ _fileNumber = chunk.readTypedUint16();
+ _type = static_cast<AssetType>(chunk.readTypedUint16());
+ _id = chunk.readTypedUint16();
debugC(4, kDebugLoading, "AssetHeader::AssetHeader(): _type = 0x%x, _id = 0x%x (@0x%llx)", static_cast<uint>(_type), _id, static_cast<long long int>(chunk.pos()));
- AssetHeaderSectionType sectionType = getSectionType(chunk);
+ AssetHeaderSectionType sectionType = static_cast<AssetHeaderSectionType>(chunk.readTypedUint16());
bool moreSectionsToRead = (kAssetHeaderEmptySection != sectionType);
while (moreSectionsToRead) {
readSection(sectionType, chunk);
- sectionType = getSectionType(chunk);
+ sectionType = static_cast<AssetHeaderSectionType>(chunk.readTypedUint16());
moreSectionsToRead = (kAssetHeaderEmptySection != sectionType);
}
}
AssetHeader::~AssetHeader() {
- delete _boundingBox;
- _boundingBox = nullptr;
-
- for (Common::Point *point : _mouseActiveArea) {
- delete point;
- }
- _mouseActiveArea.clear();
-
for (auto it = _eventHandlers.begin(); it != _eventHandlers.end(); ++it) {
delete it->_value;
}
@@ -79,18 +67,6 @@ AssetHeader::~AssetHeader() {
delete _palette;
_palette = nullptr;
-
- delete _name;
- _name = nullptr;
-
- delete _startPoint;
- _startPoint = nullptr;
-
- delete _endPoint;
- _endPoint = nullptr;
-
- delete _text;
- _text = nullptr;
}
void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk) {
@@ -146,14 +122,14 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
}
case kAssetHeaderStageId: {
- _stageId = Datum(chunk).u.i;
+ _stageId = chunk.readTypedUint16();
break;
}
case kAssetHeaderAssetId: {
// We already have this asset's ID, so we will just verify it is the same
// as the ID we have already read.
- uint32 duplicateAssetId = Datum(chunk).u.i;
+ uint32 duplicateAssetId = chunk.readTypedUint16();
if (duplicateAssetId != _id) {
warning("AssetHeader::readSection(): AssetHeader ID %d does not match original asset ID %d", duplicateAssetId, _id);
}
@@ -167,87 +143,87 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
// - They might be in the same RIFF subfile as this header,
// - They might be in a different RIFF subfile in the same CXT file,
// - They might be in a different CXT file entirely.
- _chunkReference = Datum(chunk, kDatumTypeChunkReference).u.i;
+ _chunkReference = chunk.readTypedChunkReference();
break;
}
case kAssetHeaderMovieAudioChunkReference: {
- _audioChunkReference = Datum(chunk, kDatumTypeChunkReference).u.i;
+ _audioChunkReference = chunk.readTypedChunkReference();
break;
}
case kAssetHeaderMovieAnimationChunkReference: {
- _animationChunkReference = Datum(chunk, kDatumTypeChunkReference).u.i;
+ _animationChunkReference = chunk.readTypedChunkReference();
break;
}
case kAssetHeaderBoundingBox: {
- _boundingBox = Datum(chunk, kDatumTypeRect).u.bbox;
+ _boundingBox = chunk.readTypedRect();
break;
}
case kAssetHeaderMouseActiveArea: {
- uint16 total_points = Datum(chunk, kDatumTypeUint16).u.i;
+ uint16 total_points = chunk.readTypedUint16();
for (int i = 0; i < total_points; i++) {
- Common::Point *point = Datum(chunk, kDatumTypePoint).u.point;
+ Common::Point point = chunk.readTypedPoint();
_mouseActiveArea.push_back(point);
}
break;
}
case kAssetHeaderZIndex: {
- _zIndex = Datum(chunk).u.i;
+ _zIndex = chunk.readTypedGraphicUnit();
break;
}
case kAssetHeaderAssetReference: {
- _assetReference = Datum(chunk).u.i;
+ _assetReference = chunk.readTypedUint16();
break;
}
case kAssetHeaderStartup: {
- _startup = Datum(chunk).u.i;
+ _startup = chunk.readTypedByte();
break;
}
case kAssetHeaderTransparency: {
- _transparency = Datum(chunk).u.i;
+ _transparency = chunk.readTypedByte();
break;
}
case kAssetHeaderHasOwnSubfile: {
- _hasOwnSubfile = Datum(chunk).u.i;
+ _hasOwnSubfile = chunk.readTypedByte();
break;
}
case kAssetHeaderCursorResourceId: {
- _cursorResourceId = Datum(chunk).u.i;
+ _cursorResourceId = chunk.readTypedUint16();
break;
}
case kAssetHeaderFrameRate: {
- _frameRate = static_cast<uint32>(Datum(chunk, kDatumTypeDouble).u.f);
+ _frameRate = static_cast<uint32>(chunk.readTypedDouble());
break;
}
case kAssetHeaderLoadType: {
- _loadType = Datum(chunk).u.i;
+ _loadType = chunk.readTypedByte();
break;
}
case kAssetHeaderSoundInfo: {
- _chunkCount = Datum(chunk).u.i;
- _rate = Datum(chunk).u.i;
+ _chunkCount = chunk.readTypedUint16();
+ _rate = chunk.readTypedUint32();
break;
}
case kAssetHeaderMovieLoadType: {
- _loadType = Datum(chunk).u.i;
+ _loadType = chunk.readTypedByte();
break;
}
case kAssetHeaderGetOffstageEvents: {
- _getOffstageEvents = Datum(chunk).u.i;
+ _getOffstageEvents = chunk.readTypedByte();
break;
}
@@ -263,33 +239,33 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
}
case kAssetHeaderDissolveFactor: {
- _dissolveFactor = Datum(chunk).u.i;
+ _dissolveFactor = chunk.readTypedDouble();
break;
}
case kAssetHeaderSoundEncoding1:
case kAssetHeaderSoundEncoding2: {
- _soundEncoding = static_cast<SoundEncoding>(Datum(chunk).u.i);
+ _soundEncoding = static_cast<SoundEncoding>(chunk.readTypedUint16());
break;
}
case kAssetHeaderSpriteChunkCount: {
- _chunkCount = Datum(chunk).u.i;
+ _chunkCount = chunk.readTypedUint16();
break;
}
case kAssetHeaderStartPoint: {
- _startPoint = Datum(chunk, kDatumTypePoint).u.point;
+ _startPoint = chunk.readTypedPoint();
break;
}
case kAssetHeaderEndPoint: {
- _endPoint = Datum(chunk, kDatumTypePoint).u.point;
+ _endPoint = chunk.readTypedPoint();
break;
}
case kAssetHeaderStepRate: {
- double _stepRateFloat = Datum(chunk, kDatumTypeDouble).u.f;
+ double _stepRateFloat = chunk.readTypedDouble();
// This should always be an integer anyway,
// so we'll cast away any fractional part.
_stepRate = static_cast<uint32>(_stepRateFloat);
@@ -299,62 +275,62 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
case kAssetHeaderDuration: {
// These are stored in the file as fractional seconds,
// but we want milliseconds.
- _duration = (uint32)(Datum(chunk).u.f * 1000);
+ _duration = (uint32)(chunk.readTypedTime() * 1000);
break;
}
case kAssetHeaderX: {
- _x = Datum(chunk).u.i;
+ _x = chunk.readTypedUint16();
break;
}
case kAssetHeaderY: {
- _y = Datum(chunk).u.i;
+ _y = chunk.readTypedUint16();
break;
}
case kAssetHeaderEditable: {
- _editable = Datum(chunk).u.i;
+ _editable = chunk.readTypedByte();
break;
}
case kAssetHeaderFontId: {
- _fontAssetId = Datum(chunk).u.i;
+ _fontAssetId = chunk.readTypedUint16();
break;
}
case kAssetHeaderTextMaxLength: {
- _maxTextLength = Datum(chunk).u.i;
+ _maxTextLength = chunk.readTypedUint16();
break;
}
case kAssetHeaderInitialText: {
- _text = Datum(chunk).u.string;
+ _text = chunk.readTypedString();
break;
}
case kAssetHeaderTextJustification: {
- _justification = static_cast<TextJustification>(Datum(chunk).u.i);
+ _justification = static_cast<TextJustification>(chunk.readTypedUint16());
break;
}
case kAssetHeaderTextPosition: {
- _position = static_cast<TextPosition>(Datum(chunk).u.i);
+ _position = static_cast<TextPosition>(chunk.readTypedUint16());
break;
}
case kAssetHeaderTextCharacterClass: {
CharacterClass characterClass;
- characterClass.firstAsciiCode = Datum(chunk).u.i;
- characterClass.lastAsciiCode = Datum(chunk).u.i;
+ characterClass.firstAsciiCode = chunk.readTypedUint16();
+ characterClass.lastAsciiCode = chunk.readTypedUint16();
_acceptedInput.push_back(characterClass);
break;
}
case kAssetHeaderSpriteFrameMapping: {
- uint32 externalFrameId = Datum(chunk).u.i;
- uint32 internalFrameId = Datum(chunk).u.i;
- uint32 unk1 = Datum(chunk).u.i;
+ uint32 externalFrameId = chunk.readTypedUint16();
+ uint32 internalFrameId = chunk.readTypedUint16();
+ uint32 unk1 = chunk.readTypedUint16();
if (unk1 != internalFrameId) {
warning("AssetHeader::readSection(): Repeated internalFrameId doesn't match");
}
@@ -363,7 +339,7 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
}
case kAssetHeaderPathTotalSteps: {
- _totalSteps = Datum(chunk).u.i;
+ _totalSteps = chunk.readTypedUint16();
break;
}
@@ -372,10 +348,4 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
}
}
-AssetHeaderSectionType AssetHeader::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16);
- AssetHeaderSectionType sectionType = static_cast<AssetHeaderSectionType>(datum.u.i);
- return sectionType;
-}
-
} // end of namespace MediaStation
diff --git a/engines/mediastation/assetheader.h b/engines/mediastation/assetheader.h
index b8f327fbd55..958f4d8d27f 100644
--- a/engines/mediastation/assetheader.h
+++ b/engines/mediastation/assetheader.h
@@ -172,8 +172,8 @@ public:
// These two are only used in movies.
ChunkReference _audioChunkReference = 0;
ChunkReference _animationChunkReference = 0;
- Common::Rect *_boundingBox = nullptr;
- Common::Array<Common::Point *> _mouseActiveArea;
+ Common::Rect _boundingBox;
+ Common::Array<Common::Point> _mouseActiveArea;
int _zIndex = 0;
uint32 _assetReference = 0;
uint32 _startup = 0;
@@ -188,7 +188,7 @@ public:
bool _getOffstageEvents = 0;
uint32 _x = 0; // Image only.
uint32 _y = 0; // Image only.
- Common::String *_name = nullptr;
+ Common::String _name;
uint32 _stageId = 0;
SoundEncoding _soundEncoding;
uint32 _chunkCount = 0;
@@ -196,8 +196,8 @@ public:
// PATH FIELDS.
uint32 _dissolveFactor = 0;
- Common::Point *_startPoint = nullptr;
- Common::Point *_endPoint = nullptr;
+ Common::Point _startPoint;
+ Common::Point _endPoint;
uint32 _stepRate = 0;
uint32 _duration = 0;
uint _totalSteps = 0;
@@ -210,7 +210,7 @@ public:
Common::Array<EventHandler *> _loadCompleteHandlers;
// TEXT FIELDS.
- Common::String *_text = nullptr;
+ Common::String _text;
uint _maxTextLength = 0;
uint _fontAssetId = 0;
TextJustification _justification;
@@ -219,7 +219,6 @@ public:
private:
void readSection(AssetHeaderSectionType sectionType, Chunk &chunk);
- AssetHeaderSectionType getSectionType(Chunk &chunk);
};
} // End of namespace MediaStation
diff --git a/engines/mediastation/assets/font.cpp b/engines/mediastation/assets/font.cpp
index a9f71e1c0be..a185a375f11 100644
--- a/engines/mediastation/assets/font.cpp
+++ b/engines/mediastation/assets/font.cpp
@@ -43,9 +43,9 @@ ScriptValue Font::callMethod(BuiltInMethod methodId, Common::Array<ScriptValue>
void Font::readChunk(Chunk &chunk) {
debugC(5, kDebugLoading, "Font::readChunk(): Reading font glyph (@0x%llx)", static_cast<long long int>(chunk.pos()));
- uint asciiCode = Datum(chunk).u.i;
- int unk1 = Datum(chunk).u.i;
- int unk2 = Datum(chunk).u.i;
+ uint asciiCode = chunk.readTypedUint16();
+ int unk1 = chunk.readTypedUint16();
+ int unk2 = chunk.readTypedUint16();
BitmapHeader *header = new BitmapHeader(chunk);
FontGlyph *glyph = new FontGlyph(chunk, asciiCode, unk1, unk2, header);
if (_glyphs.getValOrDefault(asciiCode) != nullptr) {
diff --git a/engines/mediastation/assets/hotspot.cpp b/engines/mediastation/assets/hotspot.cpp
index da02b85261f..7f7a50dbfa7 100644
--- a/engines/mediastation/assets/hotspot.cpp
+++ b/engines/mediastation/assets/hotspot.cpp
@@ -32,7 +32,7 @@ Hotspot::Hotspot(AssetHeader *header) : Asset(header) {
bool Hotspot::isInside(const Common::Point &pointToCheck) {
// No sense checking the polygon if we're not even in the bbox.
- if (!_header->_boundingBox->contains(pointToCheck)) {
+ if (!_header->_boundingBox.contains(pointToCheck)) {
return false;
}
@@ -43,14 +43,14 @@ bool Hotspot::isInside(const Common::Point &pointToCheck) {
// Polygon intersection code adapted from HADESCH engine, might need more
// refinement once more testing is possible.
- Common::Point point = pointToCheck - Common::Point(_header->_boundingBox->left, _header->_boundingBox->top);
+ Common::Point point = pointToCheck - Common::Point(_header->_boundingBox.left, _header->_boundingBox.top);
int rcross = 0; // Number of right-side overlaps
// Each edge is checked whether it cuts the outgoing stream from the point
- Common::Array<Common::Point *> _polygon = _header->_mouseActiveArea;
+ Common::Array<Common::Point> _polygon = _header->_mouseActiveArea;
for (unsigned i = 0; i < _polygon.size(); i++) {
- const Common::Point &edgeStart = *_polygon[i];
- const Common::Point &edgeEnd = *_polygon[(i + 1) % _polygon.size()];
+ const Common::Point &edgeStart = _polygon[i];
+ const Common::Point &edgeEnd = _polygon[(i + 1) % _polygon.size()];
// A vertex is a point? Then it lies on one edge of the polygon
if (point == edgeStart)
diff --git a/engines/mediastation/assets/image.cpp b/engines/mediastation/assets/image.cpp
index 942ef1b2686..54771709580 100644
--- a/engines/mediastation/assets/image.cpp
+++ b/engines/mediastation/assets/image.cpp
@@ -118,7 +118,7 @@ void Image::spatialHide() {
}
Common::Point Image::getLeftTop() {
- return Common::Point(_header->_x + _header->_boundingBox->left + _xAdjust, _header->_y + _header->_boundingBox->top + _yAdjust);
+ 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/movie.cpp b/engines/mediastation/assets/movie.cpp
index e0f50bac700..65c2daf8f4a 100644
--- a/engines/mediastation/assets/movie.cpp
+++ b/engines/mediastation/assets/movie.cpp
@@ -24,46 +24,45 @@
#include "mediastation/mediastation.h"
#include "mediastation/assets/movie.h"
-#include "mediastation/datum.h"
#include "mediastation/debugchannels.h"
namespace MediaStation {
MovieFrameHeader::MovieFrameHeader(Chunk &chunk) : BitmapHeader(chunk) {
- _index = Datum(chunk).u.i;
+ _index = chunk.readTypedUint32();
debugC(5, kDebugLoading, "MovieFrameHeader::MovieFrameHeader(): _index = 0x%x (@0x%llx)", _index, static_cast<long long int>(chunk.pos()));
- _keyframeEndInMilliseconds = Datum(chunk).u.i;
+ _keyframeEndInMilliseconds = chunk.readTypedUint32();
}
MovieFrameFooter::MovieFrameFooter(Chunk &chunk) {
- _unk1 = Datum(chunk).u.i;
- _unk2 = Datum(chunk).u.i;
- if (g_engine->isFirstGenerationEngine()) { // TODO: Add the version number check.
- _startInMilliseconds = Datum(chunk).u.i;
- _endInMilliseconds = Datum(chunk).u.i;
- _left = Datum(chunk).u.i;
- _top = Datum(chunk).u.i;
- _unk3 = Datum(chunk).u.i;
- _unk4 = Datum(chunk).u.i;
- _index = Datum(chunk).u.i;
+ _unk1 = chunk.readTypedUint16();
+ _unk2 = chunk.readTypedUint32();
+ if (g_engine->isFirstGenerationEngine()) {
+ _startInMilliseconds = chunk.readTypedUint32();
+ _endInMilliseconds = chunk.readTypedUint32();
+ _left = chunk.readTypedUint16();
+ _top = chunk.readTypedUint16();
+ _unk3 = chunk.readTypedUint16();
+ _unk4 = chunk.readTypedUint16();
+ _index = chunk.readTypedUint16();
} else {
- _unk4 = Datum(chunk).u.i;
- _startInMilliseconds = Datum(chunk).u.i;
- _endInMilliseconds = Datum(chunk).u.i;
- _left = Datum(chunk).u.i;
- _top = Datum(chunk).u.i;
- _zIndex = Datum(chunk).u.i;
+ _unk4 = chunk.readTypedUint16();
+ _startInMilliseconds = chunk.readTypedUint32();
+ _endInMilliseconds = chunk.readTypedUint32();
+ _left = chunk.readTypedUint16();
+ _top = chunk.readTypedUint16();
+ _zIndex = chunk.readTypedSint16();
// This represents the difference between the left coordinate of the
// keyframe (if applicable) and the left coordinate of this frame. Zero
// if there is no keyframe.
- _diffBetweenKeyframeAndFrameX = Datum(chunk).u.i;
+ _diffBetweenKeyframeAndFrameX = chunk.readTypedSint16();
// This represents the difference between the top coordinate of the
// keyframe (if applicable) and the top coordinate of this frame. Zero
// if there is no keyframe.
- _diffBetweenKeyframeAndFrameY = Datum(chunk).u.i;
- _index = Datum(chunk).u.i;
- _keyframeIndex = Datum(chunk).u.i;
- _unk9 = Datum(chunk).u.i;
+ _diffBetweenKeyframeAndFrameY = chunk.readTypedSint16();
+ _index = chunk.readTypedUint32();
+ _keyframeIndex = chunk.readTypedUint32();
+ _unk9 = chunk.readTypedByte();
debugC(5, kDebugLoading, "MovieFrameFooter::MovieFrameFooter(): _startInMilliseconds = %d, _endInMilliseconds = %d, _left = %d, _top = %d, _index = %d, _keyframeIndex = %d (@0x%llx)",
_startInMilliseconds, _endInMilliseconds, _left, _top, _index, _keyframeIndex, static_cast<long long int>(chunk.pos()));
debugC(5, kDebugLoading, "MovieFrameFooter::MovieFrameFooter(): _zIndex = %d, _diffBetweenKeyframeAndFrameX = %d, _diffBetweenKeyframeAndFrameY = %d, _unk4 = %d, _unk9 = %d",
@@ -244,7 +243,7 @@ ScriptValue Movie::callMethod(BuiltInMethod methodId, Common::Array<ScriptValue>
case kXPositionMethod: {
assert(args.empty());
- double left = static_cast<double>(_header->_boundingBox->left);
+ double left = static_cast<double>(_header->_boundingBox.left);
returnValue.setToFloat(left);
return returnValue;
@@ -252,7 +251,7 @@ ScriptValue Movie::callMethod(BuiltInMethod methodId, Common::Array<ScriptValue>
case kYPositionMethod: {
assert(args.empty());
- double top = static_cast<double>(_header->_boundingBox->top);
+ double top = static_cast<double>(_header->_boundingBox.top);
returnValue.setToFloat(top);
return returnValue;
}
@@ -382,14 +381,14 @@ void Movie::spatialCenterMoveTo(int x, int y) {
}
// Calculate the center of the movie, and update location.
- int frameWidth = _header->_boundingBox->width();
- int frameHeight = _header->_boundingBox->height();
+ int frameWidth = _header->_boundingBox.width();
+ int frameHeight = _header->_boundingBox.height();
int centerX = x - frameWidth / 2;
int centerY = y - frameHeight / 2;
debugC(5, kDebugScript, "Movie::callMethod(): (%d) Moving movie center to (%d, %d)", _header->_id, x, y);
// Unlike the sprites, movie bounding boxes must be moved too.
- _header->_boundingBox->moveTo(centerX, centerY);
+ _header->_boundingBox.moveTo(centerX, centerY);
// Mark the new location dirty.
for (MovieFrame *frame : _framesOnScreen) {
@@ -408,7 +407,7 @@ void Movie::spatialMoveTo(int x, int y) {
// Update the location and mark the new location dirty.
debugC(5, kDebugGraphics, "Movie::callMethod(): (%d) Moving movie to (%d, %d)", _header->_id, x, y);
// Unlike the sprites, movie bounding boxes must be moved too.
- _header->_boundingBox->moveTo(x, y);
+ _header->_boundingBox.moveTo(x, y);
for (MovieFrame *frame : _framesOnScreen) {
Common::Rect bbox = getFrameBoundingBox(frame);
@@ -518,7 +517,7 @@ void Movie::redraw(Common::Rect &rect) {
Common::Rect areaToRedraw = bbox.findIntersectingRect(rect);
if (!areaToRedraw.isEmpty()) {
Common::Point originOnScreen(areaToRedraw.left, areaToRedraw.top);
- areaToRedraw.translate(-frame->left() - _header->_boundingBox->left, -frame->top() - _header->_boundingBox->top);
+ areaToRedraw.translate(-frame->left() - _header->_boundingBox.left, -frame->top() - _header->_boundingBox.top);
areaToRedraw.clip(Common::Rect(0, 0, frame->width(), frame->height()));
g_engine->_screen->simpleBlitFrom(frame->_surface, areaToRedraw, originOnScreen);
}
@@ -527,13 +526,13 @@ void Movie::redraw(Common::Rect &rect) {
Common::Rect Movie::getFrameBoundingBox(MovieFrame *frame) {
Common::Rect bbox = frame->boundingBox();
- bbox.translate(_header->_boundingBox->left, _header->_boundingBox->top);
+ bbox.translate(_header->_boundingBox.left, _header->_boundingBox.top);
return bbox;
}
void Movie::readChunk(Chunk &chunk) {
// Individual chunks are "stills" and are stored in the first subfile.
- uint sectionType = Datum(chunk).u.i;
+ uint sectionType = chunk.readTypedUint16();
switch ((MovieSectionType)sectionType) {
case kMovieFrameSection: {
debugC(5, kDebugLoading, "Movie::readStill(): Reading frame");
@@ -557,20 +556,18 @@ void Movie::readChunk(Chunk &chunk) {
void Movie::readSubfile(Subfile &subfile, Chunk &chunk) {
// READ THE METADATA FOR THE WHOLE MOVIE.
- uint expectedRootSectionType = Datum(chunk).u.i;
+ uint expectedRootSectionType = chunk.readTypedUint16();
debugC(5, kDebugLoading, "Movie::readSubfile(): sectionType = 0x%x (@0x%llx)", static_cast<uint>(expectedRootSectionType), static_cast<long long int>(chunk.pos()));
if (kMovieRootSection != (MovieSectionType)expectedRootSectionType) {
error("Expected ROOT section type, got 0x%x", expectedRootSectionType);
}
- uint chunkCount = Datum(chunk).u.i;
- debugC(5, kDebugLoading, "Movie::readSubfile(): chunkCount = 0x%x (@0x%llx)", chunkCount, static_cast<long long int>(chunk.pos()));
-
- uint dataStartOffset = Datum(chunk).u.i;
- debugC(5, kDebugLoading, "Movie::readSubfile(): dataStartOffset = 0x%x (@0x%llx)", dataStartOffset, static_cast<long long int>(chunk.pos()));
+ uint chunkCount = chunk.readTypedUint16();
+ double unk1 = chunk.readTypedDouble();
+ debugC(5, kDebugLoading, "Movie::readSubfile(): chunkCount = 0x%x, unk1 = %f (@0x%llx)", chunkCount, unk1, static_cast<long long int>(chunk.pos()));
Common::Array<uint> chunkLengths;
for (uint i = 0; i < chunkCount; i++) {
- uint chunkLength = Datum(chunk).u.i;
+ uint chunkLength = chunk.readTypedUint32();
debugC(5, kDebugLoading, "Movie::readSubfile(): chunkLength = 0x%x (@0x%llx)", chunkLength, static_cast<long long int>(chunk.pos()));
chunkLengths.push_back(chunkLength);
}
@@ -587,7 +584,7 @@ void Movie::readSubfile(Subfile &subfile, Chunk &chunk) {
warning("Movie::readSubfile(): (Frameset %d of %d) No animation chunks found (@0x%llx)", i, chunkCount, static_cast<long long int>(chunk.pos()));
}
while (isAnimationChunk) {
- uint sectionType = Datum(chunk).u.i;
+ uint sectionType = chunk.readTypedUint16();
debugC(5, kDebugLoading, "Movie::readSubfile(): sectionType = 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
switch (MovieSectionType(sectionType)) {
case kMovieFrameSection: {
diff --git a/engines/mediastation/assets/sprite.cpp b/engines/mediastation/assets/sprite.cpp
index 9911e83c231..9d6cd5530c7 100644
--- a/engines/mediastation/assets/sprite.cpp
+++ b/engines/mediastation/assets/sprite.cpp
@@ -19,7 +19,6 @@
*
*/
-#include "mediastation/datum.h"
#include "mediastation/assets/sprite.h"
#include "mediastation/debugchannels.h"
#include "mediastation/mediastation.h"
@@ -27,17 +26,12 @@
namespace MediaStation {
SpriteFrameHeader::SpriteFrameHeader(Chunk &chunk) : BitmapHeader(chunk) {
- _index = Datum(chunk).u.i;
+ _index = chunk.readTypedUint16();
debugC(5, kDebugLoading, "SpriteFrameHeader::SpriteFrameHeader(): _index = 0x%x (@0x%llx)", _index, static_cast<long long int>(chunk.pos()));
- _boundingBox = Datum(chunk, kDatumTypePoint).u.point;
+ _boundingBox = chunk.readTypedPoint();
debugC(5, kDebugLoading, "SpriteFrameHeader::SpriteFrameHeader(): _boundingBox (@0x%llx)", static_cast<long long int>(chunk.pos()));
}
-SpriteFrameHeader::~SpriteFrameHeader() {
- delete _boundingBox;
- _boundingBox = nullptr;
-}
-
SpriteFrame::SpriteFrame(Chunk &chunk, SpriteFrameHeader *header) : Bitmap(chunk, header) {
_bitmapHeader = header;
}
@@ -47,11 +41,11 @@ SpriteFrame::~SpriteFrame() {
}
uint32 SpriteFrame::left() {
- return _bitmapHeader->_boundingBox->x;
+ return _bitmapHeader->_boundingBox.x;
}
uint32 SpriteFrame::top() {
- return _bitmapHeader->_boundingBox->y;
+ return _bitmapHeader->_boundingBox.y;
}
Common::Point SpriteFrame::topLeft() {
@@ -325,7 +319,7 @@ 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 - _xAdjust, -_activeFrame->top() - _header->_boundingBox->top - _yAdjust);
+ 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);
}
@@ -348,7 +342,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 + _xAdjust, _header->_boundingBox->top + _yAdjust);
+ 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 2715ac12140..d90b8506349 100644
--- a/engines/mediastation/assets/sprite.h
+++ b/engines/mediastation/assets/sprite.h
@@ -37,10 +37,9 @@ namespace MediaStation {
class SpriteFrameHeader : public BitmapHeader {
public:
SpriteFrameHeader(Chunk &chunk);
- virtual ~SpriteFrameHeader() override;
uint _index;
- Common::Point *_boundingBox;
+ Common::Point _boundingBox;
};
class SpriteFrame : public Bitmap {
diff --git a/engines/mediastation/assets/text.cpp b/engines/mediastation/assets/text.cpp
index 16df7642ba3..2b7ef861b01 100644
--- a/engines/mediastation/assets/text.cpp
+++ b/engines/mediastation/assets/text.cpp
@@ -56,11 +56,11 @@ ScriptValue Text::callMethod(BuiltInMethod methodId, Common::Array<ScriptValue>
}
}
-Common::String *Text::text() const {
+Common::String Text::text() const {
return _header->_text;
}
-void Text::setText(Common::String *text) {
+void Text::setText(Common::String text) {
error("Text::setText(): Setting text not implemented yet");
}
diff --git a/engines/mediastation/assets/text.h b/engines/mediastation/assets/text.h
index 49e4065483c..5ba2f9be7a8 100644
--- a/engines/mediastation/assets/text.h
+++ b/engines/mediastation/assets/text.h
@@ -39,8 +39,8 @@ public:
private:
// Method implementations.
- Common::String *text() const;
- void setText(Common::String *text);
+ Common::String text() const;
+ void setText(Common::String text);
};
} // End of namespace MediaStation
diff --git a/engines/mediastation/bitmap.cpp b/engines/mediastation/bitmap.cpp
index 37153b32821..3d0f1f889ee 100644
--- a/engines/mediastation/bitmap.cpp
+++ b/engines/mediastation/bitmap.cpp
@@ -19,28 +19,22 @@
*
*/
-#include "mediastation/datum.h"
#include "mediastation/bitmap.h"
#include "mediastation/debugchannels.h"
namespace MediaStation {
BitmapHeader::BitmapHeader(Chunk &chunk) {
- uint headerSizeInBytes = Datum(chunk, kDatumTypeUint16).u.i;
+ uint headerSizeInBytes = chunk.readTypedUint16();
debugC(5, kDebugLoading, "BitmapHeader::BitmapHeader(): headerSize = 0x%x", headerSizeInBytes);
- _dimensions = Datum(chunk).u.point;
- _compressionType = static_cast<BitmapCompressionType>(Datum(chunk, kDatumTypeUint16).u.i);
+ _dimensions = chunk.readTypedGraphicSize();
+ _compressionType = static_cast<BitmapCompressionType>(chunk.readTypedUint16());
debugC(5, kDebugLoading, "BitmapHeader::BitmapHeader(): _compressionType = 0x%x", static_cast<uint>(_compressionType));
// TODO: Figure out what this is.
// This has something to do with the width of the bitmap but is always
// a few pixels off from the width. And in rare cases it seems to be
// the true width!
- unk2 = Datum(chunk, kDatumTypeUint16).u.i;
-}
-
-BitmapHeader::~BitmapHeader() {
- delete _dimensions;
- _dimensions = nullptr;
+ unk2 = chunk.readTypedUint16();
}
bool BitmapHeader::isCompressed() {
@@ -50,8 +44,8 @@ bool BitmapHeader::isCompressed() {
Bitmap::Bitmap(Chunk &chunk, BitmapHeader *bitmapHeader) :
_bitmapHeader(bitmapHeader) {
// The header must be constructed beforehand.
- uint16 width = _bitmapHeader->_dimensions->x;
- uint16 height = _bitmapHeader->_dimensions->y;
+ uint16 width = _bitmapHeader->_dimensions.x;
+ uint16 height = _bitmapHeader->_dimensions.y;
_surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
_surface.setTransparentColor(0);
uint8 *pixels = (uint8 *)_surface.getPixels();
@@ -77,11 +71,11 @@ Bitmap::~Bitmap() {
}
uint16 Bitmap::width() {
- return _bitmapHeader->_dimensions->x;
+ return _bitmapHeader->_dimensions.x;
}
uint16 Bitmap::height() {
- return _bitmapHeader->_dimensions->y;
+ return _bitmapHeader->_dimensions.y;
}
void Bitmap::decompress(Chunk &chunk) {
diff --git a/engines/mediastation/bitmap.h b/engines/mediastation/bitmap.h
index 0691ba8a539..a1cb1add861 100644
--- a/engines/mediastation/bitmap.h
+++ b/engines/mediastation/bitmap.h
@@ -40,11 +40,10 @@ enum BitmapCompressionType {
class BitmapHeader {
public:
BitmapHeader(Chunk &chunk);
- virtual ~BitmapHeader();
bool isCompressed();
- Common::Point *_dimensions = nullptr;
+ Common::Point _dimensions;
BitmapCompressionType _compressionType;
uint unk2;
};
diff --git a/engines/mediastation/boot.cpp b/engines/mediastation/boot.cpp
index 7100cbbe7a8..55acbfe80f0 100644
--- a/engines/mediastation/boot.cpp
+++ b/engines/mediastation/boot.cpp
@@ -20,26 +20,10 @@
*/
#include "mediastation/boot.h"
-#include "mediastation/datum.h"
#include "mediastation/debugchannels.h"
namespace MediaStation {
-#pragma region VersionInfo
-VersionInfo::VersionInfo(Chunk &chunk) {
- _majorVersion = Datum(chunk, kDatumTypeUint16).u.i;
- _minorVersion = Datum(chunk, kDatumTypeUint16).u.i;
- _revision = Datum(chunk, kDatumTypeUint16).u.i;
- string = Datum(chunk, kDatumTypeString).u.string;
-}
-
-VersionInfo::~VersionInfo() {
- if (string != nullptr) {
- delete string;
- }
-}
-#pragma endregion
-
#pragma region ContextDeclaration
ContextDeclaration::ContextDeclaration(Chunk &chunk) {
// Make sure this declaration isn't empty.
@@ -56,7 +40,7 @@ ContextDeclaration::ContextDeclaration(Chunk &chunk) {
// Read the file number.
sectionType = getSectionType(chunk);
if (kContextDeclarationFileNumber1 == sectionType) {
- _fileNumber = Datum(chunk).u.i;
+ _fileNumber = chunk.readTypedUint16();
} else {
error("ContextDeclaration(): Expected section type FILE_NUMBER_1, got 0x%x", static_cast<uint>(sectionType));
}
@@ -64,7 +48,7 @@ ContextDeclaration::ContextDeclaration(Chunk &chunk) {
// Is it just for data integrity, or is there some other reason?
sectionType = getSectionType(chunk);
if (kContextDeclarationFileNumber2 == sectionType) {
- uint32 repeatedFileNumber = Datum(chunk).u.i;
+ uint32 repeatedFileNumber = chunk.readTypedUint16();
if (repeatedFileNumber != _fileNumber) {
warning("ContextDeclaration(): Expected file numbers to match, but 0x%d != 0x%d", _fileNumber, repeatedFileNumber);
}
@@ -81,7 +65,7 @@ ContextDeclaration::ContextDeclaration(Chunk &chunk) {
int rewindOffset = chunk.pos();
sectionType = getSectionType(chunk);
if (kContextDeclarationName == sectionType) {
- _contextName = Datum(chunk, kDatumTypeString).u.string;
+ _contextName = chunk.readTypedString();
} else {
// There is no context name.
// We have instead read into the next declaration, so let's undo that.
@@ -99,7 +83,7 @@ ContextDeclaration::ContextDeclaration(Chunk &chunk) {
int rewindOffset = 0;
sectionType = getSectionType(chunk);
while (kContextDeclarationFileReference == sectionType) {
- int fileReference = Datum(chunk).u.i;
+ int fileReference = chunk.readTypedUint16();
_fileReferences.push_back(fileReference);
rewindOffset = chunk.pos();
sectionType = getSectionType(chunk);
@@ -108,14 +92,7 @@ ContextDeclaration::ContextDeclaration(Chunk &chunk) {
}
ContextDeclarationSectionType ContextDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16);
- ContextDeclarationSectionType sectionType = static_cast<ContextDeclarationSectionType>(datum.u.i);
- return sectionType;
-}
-
-ContextDeclaration::~ContextDeclaration() {
- delete _contextName;
- _contextName = nullptr;
+ return static_cast<ContextDeclarationSectionType>(chunk.readTypedUint16());
}
#pragma endregion
@@ -133,13 +110,13 @@ UnknownDeclaration::UnknownDeclaration(Chunk &chunk) {
sectionType = getSectionType(chunk);
if (kUnknownDeclarationUnk1 == sectionType) {
- _unk = Datum(chunk, kDatumTypeUint16).u.i;
+ _unk = chunk.readTypedUint16();
} else {
error("UnknownDeclaration(): Expected section type UNK_1, got 0x%x", static_cast<uint>(sectionType));
}
sectionType = getSectionType(chunk);
if (kUnknownDeclarationUnk2 == sectionType) {
- uint16 repeatedUnk = Datum(chunk, kDatumTypeUint16).u.i;
+ uint16 repeatedUnk = chunk.readTypedUint16();
if (repeatedUnk != _unk) {
warning("UnknownDeclaration(): Expected unknown values to match, but 0x%x != 0x%x", _unk, repeatedUnk);
}
@@ -149,9 +126,7 @@ UnknownDeclaration::UnknownDeclaration(Chunk &chunk) {
}
UnknownDeclarationSectionType UnknownDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16);
- UnknownDeclarationSectionType sectionType = static_cast<UnknownDeclarationSectionType>(datum.u.i);
- return sectionType;
+ return static_cast<UnknownDeclarationSectionType>(chunk.readTypedUint16());
}
#pragma endregion
@@ -170,7 +145,7 @@ FileDeclaration::FileDeclaration(Chunk &chunk) {
// Read the file ID.
sectionType = getSectionType(chunk);
if (kFileDeclarationFileId == sectionType) {
- _id = Datum(chunk, kDatumTypeUint16).u.i;
+ _id = chunk.readTypedUint16();
} else {
error("FileDeclaration(): Expected section type FILE_ID, got 0x%x", static_cast<uint>(sectionType));
}
@@ -178,9 +153,7 @@ FileDeclaration::FileDeclaration(Chunk &chunk) {
// Read the intended file location.
sectionType = getSectionType(chunk);
if (kFileDeclarationFileNameAndType == sectionType) {
- Datum datum = Datum(chunk, kDatumTypeUint16);
- // TODO: Verify we actually read a valid enum member.
- _intendedLocation = static_cast<IntendedFileLocation>(datum.u.i);
+ _intendedLocation = static_cast<IntendedFileLocation>(chunk.readTypedUint16());
} else {
error("FileDeclaration(): Expected section type FILE_NAME_AND_TYPE, got 0x%x", static_cast<uint>(sectionType));
}
@@ -188,18 +161,11 @@ FileDeclaration::FileDeclaration(Chunk &chunk) {
// Since the platforms that Media Station originally targeted were case-insensitive,
// the case of these filenames might not match the case of the files actually in
// the directory. All files should be matched case-insensitively.
- _name = Datum(chunk, kDatumTypeFilename).u.string;
+ _name = chunk.readTypedFilename();
}
FileDeclarationSectionType FileDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16);
- FileDeclarationSectionType sectionType = static_cast<FileDeclarationSectionType>(datum.u.i);
- return sectionType;
-}
-
-FileDeclaration::~FileDeclaration() {
- delete _name;
- _name = nullptr;
+ return static_cast<FileDeclarationSectionType>(chunk.readTypedUint16());
}
#pragma endregion
@@ -218,7 +184,7 @@ SubfileDeclaration::SubfileDeclaration(Chunk &chunk) {
// Read the asset ID.
sectionType = getSectionType(chunk);
if (kSubfileDeclarationAssetId == sectionType) {
- _assetId = Datum(chunk, kDatumTypeUint16).u.i;
+ _assetId = chunk.readTypedUint16();
} else {
error("SubfileDeclaration(): Expected section type ASSET_ID, got 0x%x", static_cast<uint>(sectionType));
}
@@ -226,7 +192,7 @@ SubfileDeclaration::SubfileDeclaration(Chunk &chunk) {
// Read the file ID.
sectionType = getSectionType(chunk);
if (kSubfileDeclarationFileId == sectionType) {
- _fileId = Datum(chunk, kDatumTypeUint16).u.i;
+ _fileId = chunk.readTypedUint16();
} else {
error("SubfileDeclaration(): Expected section type FILE_ID, got 0x%x", static_cast<uint>(sectionType));
}
@@ -234,40 +200,24 @@ SubfileDeclaration::SubfileDeclaration(Chunk &chunk) {
// Read the start offset from the absolute start of the file.
sectionType = getSectionType(chunk);
if (kSubfileDeclarationStartOffset == sectionType) {
- _startOffsetInFile = Datum(chunk, kDatumTypeUint32).u.i;
+ _startOffsetInFile = chunk.readTypedUint32();
} else {
error("SubfileDeclaration(): Expected section type START_OFFSET, got 0x%x", static_cast<uint>(sectionType));
}
}
SubfileDeclarationSectionType SubfileDeclaration::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16);
- SubfileDeclarationSectionType sectionType = static_cast<SubfileDeclarationSectionType>(datum.u.i);
- return sectionType;
+ return static_cast<SubfileDeclarationSectionType>(chunk.readTypedUint16());
}
#pragma endregion
#pragma region CursorDeclaration
CursorDeclaration::CursorDeclaration(Chunk& chunk) {
- uint16 unk1 = Datum(chunk, kDatumTypeUint16).u.i; // Always 0x0001
- _id = Datum(chunk, kDatumTypeUint16).u.i;
- _unk = Datum(chunk, kDatumTypeUint16).u.i;
- _name = Datum(chunk, kDatumTypeFilename).u.string;
- debugC(5, kDebugLoading, " - CursorDeclaration(): unk1 = 0x%x, id = 0x%x, unk = 0x%x, name = %s", unk1, _id, _unk, _name->c_str());
-}
-
-CursorDeclaration::~CursorDeclaration() {
- delete _name;
- _name = nullptr;
-}
-#pragma endregion
-
-#pragma region Engine Resource Declaration
-EngineResourceDeclaration::EngineResourceDeclaration(Common::String *resourceName, int resourceId) : _resourceName(resourceName), _resourceId(resourceId) {}
-
-EngineResourceDeclaration::~EngineResourceDeclaration() {
- delete _resourceName;
- _resourceName = nullptr;
+ uint16 unk1 = chunk.readTypedUint16(); // Always 0x0001
+ _id = chunk.readTypedUint16();
+ _unk = chunk.readTypedUint16();
+ _name = chunk.readTypedFilename();
+ debugC(5, kDebugLoading, " - CursorDeclaration(): unk1 = 0x%x, id = 0x%x, unk = 0x%x, name = %s", unk1, _id, _unk, _name.c_str());
}
#pragma endregion
@@ -276,7 +226,7 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
Subfile subfile = getNextSubfile();
Chunk chunk = subfile.nextChunk();
- uint32 beforeSectionTypeUnk = Datum(chunk, kDatumTypeUint16).u.i; // Usually 0x0001
+ uint32 beforeSectionTypeUnk = chunk.readTypedUint16(); // Usually 0x0001
debugC(5, kDebugLoading, "Boot::Boot(): unk1 = 0x%x", beforeSectionTypeUnk);
BootSectionType sectionType = getSectionType(chunk);
@@ -285,36 +235,36 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
debugC(5, kDebugLoading, "Boot::Boot(): sectionType = 0x%x", static_cast<uint>(sectionType));
switch (sectionType) {
case kBootVersionInformation: {
- _gameTitle = Datum(chunk, kDatumTypeString).u.string;
- debugC(5, kDebugLoading, " - gameTitle = %s", _gameTitle->c_str());
- uint32 unk = chunk.readUint16LE();
- debugC(5, kDebugLoading, " - unk = 0x%x", unk);
- _versionInfo = new VersionInfo(chunk);
- debugC(5, kDebugLoading, " - versionInfo = %d.%d.%d (%s)", _versionInfo->_majorVersion, _versionInfo->_minorVersion, _versionInfo->_revision, _versionInfo->string->c_str());
- _sourceString = Datum(chunk, kDatumTypeString).u.string;
- debugC(5, kDebugLoading, " - sourceString = %s", _sourceString->c_str());
+ _gameTitle = chunk.readTypedString();
+ debugC(5, kDebugLoading, " - gameTitle = %s", _gameTitle.c_str());
+ _versionInfo = chunk.readTypedVersion();
+ _engineInfo = chunk.readTypedString();
+ debugC(5, kDebugLoading, " - versionInfo = %d.%d.%d (%s)",
+ _versionInfo.major, _versionInfo.minor, _versionInfo.patch, _engineInfo.c_str());
+ _sourceString = chunk.readTypedString();
+ debugC(5, kDebugLoading, " - sourceString = %s", _sourceString.c_str());
break;
}
case kBootUnk1:
case kBootUnk2:
case kBootUnk3: {
- uint32 unk = Datum(chunk).u.i;
+ uint unk = chunk.readTypedUint16();
debugC(5, kDebugLoading, " - unk = 0x%x", unk);
break;
}
case kBootUnk4: {
- double unk = Datum(chunk).u.f;
+ double unk = chunk.readTypedTime();
debugC(5, kDebugLoading, " - unk = %f", unk);
break;
}
case kBootEngineResource: {
- Common::String *resourceName = Datum(chunk, kDatumTypeString).u.string;
+ Common::String resourceName = chunk.readTypedString();
sectionType = getSectionType(chunk);
if (sectionType == kBootEngineResourceId) {
- int resourceId = Datum(chunk).u.i;
+ int resourceId = chunk.readTypedUint16();
EngineResourceDeclaration *resourceDeclaration = new EngineResourceDeclaration(resourceName, resourceId);
_engineResourceDeclarations.setVal(resourceId, resourceDeclaration);
} else {
@@ -385,26 +335,26 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
}
case kBootEntryScreen: {
- _entryContextId = Datum(chunk).u.i;
+ _entryContextId = chunk.readTypedUint16();
debugC(5, kDebugLoading, " - _entryContextId = %d", _entryContextId);
break;
}
case kBootAllowMultipleSounds: {
- _allowMultipleSounds = (Datum(chunk).u.i == 1);
+ _allowMultipleSounds = (chunk.readTypedByte() == 1);
debugC(5, kDebugLoading, " - _allowMultipleSounds = %d", _allowMultipleSounds);
break;
}
case kBootAllowMultipleStreams: {
- _allowMultipleStreams = (Datum(chunk).u.i == 1);
+ _allowMultipleStreams = (chunk.readTypedByte() == 1);
debugC(5, kDebugLoading, " - _allowMultipleStreams = %d", _allowMultipleStreams);
break;
}
case kBootUnk5: {
- uint32 unk1 = Datum(chunk).u.i;
- uint32 unk2 = Datum(chunk).u.i;
+ uint32 unk1 = chunk.readTypedUint16();
+ uint32 unk2 = chunk.readTypedUint16();
debugC(5, kDebugLoading, " - unk1 = 0x%x, unk2 = 0x%x", unk1, unk2);
break;
}
@@ -419,21 +369,10 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
}
BootSectionType Boot::getSectionType(Chunk &chunk) {
- Datum datum = Datum(chunk, kDatumTypeUint16);
- BootSectionType sectionType = static_cast<BootSectionType>(datum.u.i);
- return sectionType;
+ return static_cast<BootSectionType>(chunk.readTypedUint16());
}
Boot::~Boot() {
- delete _gameTitle;
- _gameTitle = nullptr;
-
- delete _versionInfo;
- _versionInfo = nullptr;
-
- delete _sourceString;
- _sourceString = nullptr;
-
for (auto it = _contextDeclarations.begin(); it != _contextDeclarations.end(); ++it) {
delete it->_value;
}
diff --git a/engines/mediastation/boot.h b/engines/mediastation/boot.h
index bd9ff4f23b8..47a79d7c5a6 100644
--- a/engines/mediastation/boot.h
+++ b/engines/mediastation/boot.h
@@ -31,27 +31,6 @@
namespace MediaStation {
-// Contains information about the engine (also called
-// "title compiler") used in this particular game.
-// Engine version information is not present in early games.
-class VersionInfo {
-public:
- VersionInfo(Chunk &chunk);
- ~VersionInfo();
-
- // The version number of this engine,
- // in the form 4.0r8 (major . minor r revision).
- uint32 _majorVersion = 0;
- uint32 _minorVersion = 0;
- uint32 _revision = 0;
-
- // A textual description of this engine.
- // Example: "Title Compiler T4.0r8 built Feb 13 1998 10:16:52"
- // ^^^^^^^^^^^^^^ ^^^^^
- // | Engine name | Version number
- Common::String *string = nullptr;
-};
-
enum ContextDeclarationSectionType {
kContextDeclarationEmptySection = 0x0000,
kContextDeclarationPlaceholder = 0x0003,
@@ -64,11 +43,10 @@ enum ContextDeclarationSectionType {
class ContextDeclaration {
public:
ContextDeclaration(Chunk &chunk);
- ~ContextDeclaration();
Common::Array<uint32> _fileReferences;
uint32 _fileNumber = 0;
- Common::String *_contextName = nullptr;
+ Common::String _contextName;
// Signal that there are no more declarations to read.
bool _isLast = false;
@@ -115,11 +93,10 @@ enum IntendedFileLocation {
class FileDeclaration {
public:
FileDeclaration(Chunk &chunk);
- ~FileDeclaration();
uint32 _id = 0;
IntendedFileLocation _intendedLocation;
- Common::String *_name = nullptr;
+ Common::String _name;
// Signal that there are no more declarations to read.
bool _isLast = false;
@@ -152,20 +129,18 @@ private:
class CursorDeclaration {
public:
CursorDeclaration(Chunk &chunk);
- ~CursorDeclaration();
uint16 _id = 0;
uint16 _unk = 0;
- Common::String *_name = nullptr;
+ Common::String _name;
};
class EngineResourceDeclaration {
public:
- Common::String *_resourceName = nullptr;
+ Common::String _resourceName;
int _resourceId = 0;
- EngineResourceDeclaration(Common::String *resourceName, int resourceId);
- ~EngineResourceDeclaration();
+ EngineResourceDeclaration(Common::String resourceName, int resourceId) : _resourceName(resourceName), _resourceId(resourceId) {};
};
enum BootSectionType {
@@ -194,9 +169,10 @@ private:
BootSectionType getSectionType(Chunk &chunk);
public:
- Common::String *_gameTitle = nullptr;
- VersionInfo *_versionInfo = nullptr;
- Common::String *_sourceString = nullptr;
+ Common::String _gameTitle;
+ VersionInfo _versionInfo;
+ Common::String _engineInfo;
+ Common::String _sourceString;
Common::HashMap<uint32, ContextDeclaration *> _contextDeclarations;
Common::Array<UnknownDeclaration *> _unknownDeclarations;
Common::HashMap<uint32, FileDeclaration *> _fileDeclarations;
diff --git a/engines/mediastation/context.cpp b/engines/mediastation/context.cpp
index dfe0af50948..b21843b1202 100644
--- a/engines/mediastation/context.cpp
+++ b/engines/mediastation/context.cpp
@@ -21,7 +21,6 @@
#include "mediastation/mediastation.h"
#include "mediastation/context.h"
-#include "mediastation/datum.h"
#include "mediastation/debugchannels.h"
#include "mediastation/bitmap.h"
@@ -114,9 +113,6 @@ Context::~Context() {
delete _palette;
_palette = nullptr;
- delete _contextName;
- _contextName = nullptr;
-
for (auto it = _assets.begin(); it != _assets.end(); ++it) {
delete it->_value;
}
@@ -160,20 +156,20 @@ void Context::registerActiveAssets() {
}
void Context::readParametersSection(Chunk &chunk) {
- _fileNumber = Datum(chunk, kDatumTypeUint16).u.i;
+ _fileNumber = chunk.readTypedUint16();
- ContextParametersSectionType sectionType = static_cast<ContextParametersSectionType>(Datum(chunk, kDatumTypeUint16).u.i);
+ ContextParametersSectionType sectionType = static_cast<ContextParametersSectionType>(chunk.readTypedUint16());
while (sectionType != kContextParametersEmptySection) {
debugC(5, kDebugLoading, "ContextParameters::ContextParameters: sectionType = 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
switch (sectionType) {
case kContextParametersName: {
- uint repeatedFileNumber = Datum(chunk, kDatumTypeUint16).u.i;
+ uint repeatedFileNumber = chunk.readTypedUint16();
if (repeatedFileNumber != _fileNumber) {
warning("ContextParameters::ContextParameters(): Repeated file number didn't match: %d != %d", repeatedFileNumber, _fileNumber);
}
- _contextName = Datum(chunk, kDatumTypeString).u.string;
+ _contextName = chunk.readTypedString();
- uint endingFlag = Datum(chunk, kDatumTypeUint16).u.i;
+ uint endingFlag = chunk.readTypedUint16();
if (endingFlag != 0) {
warning("ContextParameters::ContextParameters(): Got non-zero ending flag 0x%x", endingFlag);
}
@@ -200,17 +196,17 @@ void Context::readParametersSection(Chunk &chunk) {
error("ContextParameters::ContextParameters(): Unknown section type 0x%x", static_cast<uint>(sectionType));
}
- sectionType = static_cast<ContextParametersSectionType>(Datum(chunk, kDatumTypeUint16).u.i);
+ sectionType = static_cast<ContextParametersSectionType>(chunk.readTypedUint16());
}
}
void Context::readVariable(Chunk &chunk) {
- uint repeatedFileNumber = Datum(chunk, kDatumTypeUint16).u.i;
+ uint repeatedFileNumber = chunk.readTypedUint16();
if (repeatedFileNumber != _fileNumber) {
warning("Context::readVariable(): Repeated file number didn't match: %d != %d", repeatedFileNumber, _fileNumber);
}
- uint id = Datum(chunk).u.i;
+ uint id = chunk.readTypedUint16();
if (g_engine->getVariable(id) != nullptr) {
error("Context::readVariable(): Global variable %d already exists", id);
}
@@ -234,7 +230,7 @@ void Context::readNewStyleHeaderSections(Subfile &subfile, Chunk &chunk) {
while (moreSectionsToRead) {
// Verify this chunk is a header.
// TODO: What are the situations when it's not?
- uint16 sectionType = Datum(chunk, kDatumTypeUint16).u.i;
+ uint16 sectionType = chunk.readTypedUint16();
debugC(5, kDebugLoading, "Context::readNewStyleHeaderSections(): sectionType = 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
bool chunkIsHeader = (sectionType == 0x000d);
if (!chunkIsHeader) {
@@ -291,7 +287,7 @@ void Context::readAssetFromLaterSubfile(Subfile &subfile) {
}
bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
- uint16 sectionType = Datum(chunk, kDatumTypeUint16).u.i;
+ uint16 sectionType = chunk.readTypedUint16();
debugC(5, kDebugLoading, "Context::readHeaderSection(): sectionType = 0x%x (@0x%llx)", static_cast<uint>(sectionType), static_cast<long long int>(chunk.pos()));
switch (sectionType) {
case kContextParametersSection: {
@@ -318,7 +314,7 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
delete[] buffer;
debugC(5, kDebugLoading, "Context::readHeaderSection(): Read palette");
// This is likely just an ending flag that we expect to be zero.
- uint endingFlag = Datum(chunk, kDatumTypeUint16).u.i;
+ uint endingFlag = chunk.readTypedUint16();
if (endingFlag != 0) {
warning("Context::readHeaderSection(): Got non-zero ending flag 0x%x", endingFlag);
}
@@ -398,7 +394,7 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
_assetsByChunkReference.setVal(header->_animationChunkReference, asset);
}
// TODO: This datum only appears sometimes.
- uint unk2 = Datum(chunk).u.i;
+ uint unk2 = chunk.readTypedUint16();
debugC(5, kDebugLoading, "Context::readHeaderSection(): Got unknown value at end of asset header section 0x%x", unk2);
break;
}
@@ -407,7 +403,7 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
Function *function = new Function(chunk);
_functions.setVal(function->_id, function);
if (!g_engine->isFirstGenerationEngine()) {
- uint endingFlag = Datum(chunk).u.i;
+ uint endingFlag = chunk.readTypedUint16();
if (endingFlag != 0) {
warning("Context::readHeaderSection(): Got non-zero ending flag 0x%x in function section", endingFlag);
}
@@ -416,8 +412,8 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
}
case kContextUnkAtEndSection: {
- int unk1 = Datum(chunk).u.i;
- int unk2 = Datum(chunk).u.i;
+ int unk1 = chunk.readTypedUint16();
+ int unk2 = chunk.readTypedUint16();
debugC(5, kDebugLoading, "Context::readHeaderSection(): unk1 = %d, unk2 = %d", unk1, unk2);
return false;
}
diff --git a/engines/mediastation/context.h b/engines/mediastation/context.h
index 0334138b259..649baa8e831 100644
--- a/engines/mediastation/context.h
+++ b/engines/mediastation/context.h
@@ -77,7 +77,7 @@ private:
// as it appears in the filename. For instance, the context in
// "100.cxt" would have file number 100.
uint _fileNumber = 0;
- Common::String *_contextName = nullptr;
+ Common::String _contextName;
Common::HashMap<uint, Asset *> _assets;
Common::HashMap<uint, Function *> _functions;
diff --git a/engines/mediastation/datafile.cpp b/engines/mediastation/datafile.cpp
index 5e739126c0b..15ca2230751 100644
--- a/engines/mediastation/datafile.cpp
+++ b/engines/mediastation/datafile.cpp
@@ -24,6 +24,121 @@
namespace MediaStation {
+void ParameterReadStream::readAndVerifyType(DatumType type) {
+ DatumType actualType = static_cast<DatumType>(readUint16LE());
+ if (actualType != type) {
+ error("Expected datum type %d, got %d (@0x%llx)", type, actualType, static_cast<long long int>(pos()));
+ }
+}
+
+byte ParameterReadStream::readTypedByte() {
+ readAndVerifyType(kDatumTypeUint8);
+ return readByte();
+}
+
+uint16 ParameterReadStream::readTypedUint16() {
+ readAndVerifyType(kDatumTypeUint16);
+ return readUint16LE();
+}
+
+uint32 ParameterReadStream::readTypedUint32() {
+ readAndVerifyType(kDatumTypeUint32);
+ return readUint32LE();
+}
+
+int8 ParameterReadStream::readTypedSByte() {
+ readAndVerifyType(kDatumTypeInt8);
+ return readSByte();
+}
+
+int16 ParameterReadStream::readTypedSint16() {
+ readAndVerifyType(kDatumTypeInt16);
+ return readSint16LE();
+}
+
+int32 ParameterReadStream::readTypedSint32() {
+ readAndVerifyType(kDatumTypeInt32);
+ return readSint32LE();
+}
+
+float ParameterReadStream::readTypedFloat() {
+ readAndVerifyType(kDatumTypeFloat);
+ return readFloatLE();
+}
+
+double ParameterReadStream::readTypedDouble() {
+ readAndVerifyType(kDatumTypeDouble);
+ return readDoubleLE();
+}
+
+Common::String ParameterReadStream::readTypedFilename() {
+ readAndVerifyType(kDatumTypeFilename);
+ uint size = readTypedUint32();
+ return readString('\0', size);
+}
+
+Common::Rect ParameterReadStream::readTypedRect() {
+ readAndVerifyType(kDatumTypeRect);
+ Common::Point leftTop = readTypedPoint();
+ Common::Point dimensions = readTypedGraphicSize();
+ return Common::Rect(leftTop, dimensions.x, dimensions.y);
+}
+
+Common::Point ParameterReadStream::readTypedPoint() {
+ readAndVerifyType(kDatumTypePoint);
+ int16 x = readTypedGraphicUnit();
+ int16 y = readTypedGraphicUnit();
+ return Common::Point(x, y);
+}
+
+Common::Point ParameterReadStream::readTypedGraphicSize() {
+ readAndVerifyType(kDatumTypeGraphicSize);
+ int16 width = readTypedGraphicUnit();
+ int16 height = readTypedGraphicUnit();
+ return Common::Point(width, height);
+}
+
+int16 ParameterReadStream::readTypedGraphicUnit() {
+ readAndVerifyType(kDatumTypeGraphicUnit);
+ return readSint16LE();
+}
+
+double ParameterReadStream::readTypedTime() {
+ readAndVerifyType(kDatumTypeTime);
+ return readDoubleLE();
+}
+
+Common::String ParameterReadStream::readTypedString() {
+ readAndVerifyType(kDatumTypeString);
+ uint size = readTypedUint32();
+ return readString('\0', size);
+}
+
+VersionInfo ParameterReadStream::readTypedVersion() {
+ readAndVerifyType(kDatumTypeVersion);
+ VersionInfo version;
+ version.major = readTypedUint16();
+ version.minor = readTypedUint16();
+ version.patch = readTypedUint16();
+ return version;
+}
+
+uint32 ParameterReadStream::readTypedChunkReference() {
+ readAndVerifyType(kDatumTypeChunkReference);
+ // This one is always BE.
+ return readUint32BE();
+}
+
+Polygon ParameterReadStream::readTypedPolygon() {
+ Polygon polygon;
+ uint totalPoints = readTypedUint16();
+ for (uint i = 0; i < totalPoints; ++i) {
+ Common::Point point = readTypedGraphicSize();
+ polygon.push_back(point);
+ }
+ return polygon;
+}
+
Chunk::Chunk(Common::SeekableReadStream *stream) : _parentStream(stream) {
_id = _parentStream->readUint32BE();
_length = _parentStream->readUint32LE();
diff --git a/engines/mediastation/datafile.h b/engines/mediastation/datafile.h
index 98c7f6a2424..33d3c4c272a 100644
--- a/engines/mediastation/datafile.h
+++ b/engines/mediastation/datafile.h
@@ -25,9 +25,21 @@
#include "common/file.h"
#include "common/stream.h"
#include "common/path.h"
+#include "common/rect.h"
+#include "common/str.h"
namespace MediaStation {
+// The version number of this engine,
+// in the form 4.0r8 (major . minor r revision).
+struct VersionInfo {
+ uint16 major = 0;
+ uint16 minor = 0;
+ uint16 patch = 0;
+};
+
+typedef Common::Array<Common::Point> Polygon;
+
// A Media Station datafile consists of one or more RIFF-style "subfiles". Aside
// from some oddness at the start of the subfile, each subfile is basically
// standard sequence of chunks inside a LIST chunk, like you'd see in any RIFF
@@ -36,7 +48,62 @@ namespace MediaStation {
// - a000, where 000 is a string that represents a 3-digit hexadecimal number.
// Indicates a chunk that contains actor data (sounds and bitmaps).
-class Chunk : public Common::SeekableReadStream {
+enum DatumType {
+ kDatumTypeEmpty = 0x00,
+ kDatumTypeUint8 = 0x02,
+ kDatumTypeUint16 = 0x03,
+ kDatumTypeUint32 = 0x04,
+ kDatumTypeInt8 = 0x05,
+ kDatumTypeInt16 = 0x06,
+ kDatumTypeInt32 = 0x07,
+ kDatumTypeFloat = 0x08,
+ kDatumTypeDouble = 0x09,
+ kDatumTypeFilename = 0x0a,
+ kDatumTypeRect = 0x0d,
+ kDatumTypePoint = 0x0e,
+ kDatumTypeGraphicSize = 0x0f,
+ kDatumTypeGraphicUnit = 0x10,
+ kDatumTypeTime = 0x11,
+ kDatumTypeString = 0x12,
+ kDatumTypeVersion = 0x13,
+ kDatumTypeChunkReference = 0x1b,
+ kDatumTypePolygon = 0x1d,
+ kDatumTypePalette = 0x05aa
+};
+
+class ParameterReadStream : public Common::SeekableReadStream {
+public:
+ // Data files are internally little-endian, even on game versions targeting
+ // big-endian systems. The original engine has code for swapping byte order
+ // at runtime when needed. All of these internally assume the data files are
+ // stored little-endian on disk.
+ byte readTypedByte();
+ uint16 readTypedUint16();
+ uint32 readTypedUint32();
+ int8 readTypedSByte();
+ int16 readTypedSint16();
+ int32 readTypedSint32();
+ float readTypedFloat();
+ double readTypedDouble();
+ Common::String readTypedFilename();
+ Common::Rect readTypedRect();
+ Common::Point readTypedPoint();
+ Common::Point readTypedGraphicSize();
+ int16 readTypedGraphicUnit();
+ double readTypedTime();
+ Common::String readTypedString();
+ VersionInfo readTypedVersion();
+ uint32 readTypedChunkReference();
+ Polygon readTypedPolygon();
+ // PALETTE:
+ // u.palette = new unsigned char[0x300];
+ // chunk.read(u.palette, 0x300);
+
+private:
+ void readAndVerifyType(DatumType type);
+};
+
+class Chunk : public ParameterReadStream {
public:
Chunk() = default;
Chunk(Common::SeekableReadStream *stream);
diff --git a/engines/mediastation/datum.cpp b/engines/mediastation/datum.cpp
deleted file mode 100644
index a2b0bf97fba..00000000000
--- a/engines/mediastation/datum.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "mediastation/datum.h"
-#include "mediastation/debugchannels.h"
-
-namespace MediaStation {
-
-Datum::Datum() {
- t = kDatumTypeEmpty;
- u.i = 0;
-}
-
-Datum::Datum(Common::SeekableReadStream &chunk) {
- t = static_cast<DatumType>(chunk.readUint16LE());
- readWithType(chunk);
-}
-
-Datum::Datum(Common::SeekableReadStream &chunk, DatumType expectedType) {
- t = static_cast<DatumType>(chunk.readUint16LE());
- if (t != expectedType) {
- error("Datum::Datum(): Expected datum type 0x%x, got 0x%x (@0x%llx)", expectedType, t, static_cast<long long int>(chunk.pos()));
- }
- readWithType(chunk);
-}
-
-void Datum::readWithType(Common::SeekableReadStream &chunk) {
- debugC(9, kDebugLoading, "Datum::Datum(): Type 0x%x (@0x%llx)", static_cast<uint>(t), static_cast<long long int>(chunk.pos()));
- if (kDatumTypeUint8 == t) {
- u.i = chunk.readByte();
-
- } else if (kDatumTypeUint16 == t || kDatumTypeVersion == t) {
- u.i = chunk.readUint16LE();
-
- } else if (kDatumTypeInt16 == t || kDatumTypeGraphicUnit == t) {
- u.i = chunk.readSint16LE();
-
- } else if (kDatumTypeUint32 == t || kDatumTypeInt32 == t) {
- u.i = chunk.readUint32LE();
-
- } else if (kDatumTypeTime == t || kDatumTypeDouble == t) {
- u.f = chunk.readDoubleLE();
-
- } else if (kDatumTypeString == t || kDatumTypeFilename == t) {
- // TODO: This copies the string. Can we read it directly from the chunk?
- int size = Datum(chunk, kDatumTypeUint32).u.i;
- char *buffer = new char[size + 1];
- chunk.read(buffer, size);
- buffer[size] = '\0';
- u.string = new Common::String(buffer);
- delete[] buffer;
-
- } else if (kDatumTypeGraphicSize == t || kDatumTypePoint == t) {
- uint16 x = Datum(chunk, kDatumTypeGraphicUnit).u.i;
- uint16 y = Datum(chunk, kDatumTypeGraphicUnit).u.i;
- u.point = new Common::Point(x, y);
-
- } else if (kDatumTypeRect == t) {
- Common::Point *leftTop = Datum(chunk, kDatumTypePoint).u.point;
- Common::Point *dimensions = Datum(chunk, kDatumTypeGraphicSize).u.point;
- u.bbox = new Common::Rect(*leftTop, dimensions->x, dimensions->y);
- delete leftTop;
- delete dimensions;
-
- } else if (kDatumTypePolygon == t) {
- uint16 totalPoints = Datum(chunk, kDatumTypeUint16).u.i;
- for (int i = 0; i < totalPoints; i++) {
- Common::Point *point = Datum(chunk, kDatumTypeGraphicSize).u.point;
- u.polygon->push_back(point);
- }
-
- } else if (kDatumTypePalette == t) {
- u.palette = new unsigned char[0x300];
- chunk.read(u.palette, 0x300);
-
- } else if (kDatumTypeChunkReference == t) {
- u.chunkRef = chunk.readUint32BE();
-
- } else {
- error("Unknown datum type: 0x%x (@0x%llx)", static_cast<uint>(t), static_cast<long long int>(chunk.pos()));
- }
-}
-
-} // End of namespace MediaStation
diff --git a/engines/mediastation/datum.h b/engines/mediastation/datum.h
deleted file mode 100644
index a5b303c43bf..00000000000
--- a/engines/mediastation/datum.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef MEDIASTATION_DATUM_H
-#define MEDIASTATION_DATUM_H
-
-#include "common/str.h"
-#include "common/array.h"
-#include "common/rect.h"
-#include "common/stream.h"
-
-#include "mediastation/datafile.h"
-
-namespace MediaStation {
-
-enum DatumType {
- kDatumTypeEmpty = 0x00,
- kDatumTypeUint8 = 0x02,
- kDatumTypeUint16 = 0x03,
- kDatumTypeUint32 = 0x04,
- kDatumTypeInt8 = 0x05,
- kDatumTypeInt16 = 0x06,
- kDatumTypeInt32 = 0x07,
- kDatumTypeFloat = 0x08,
- kDatumTypeDouble = 0x09,
- kDatumTypeFilename = 0x0a,
- kDatumTypeRect = 0x0d,
- kDatumTypePoint = 0x0e,
- kDatumTypeGraphicSize = 0x0f,
- kDatumTypeGraphicUnit = 0x10,
- kDatumTypeTime = 0x11,
- kDatumTypeString = 0x12,
- kDatumTypeVersion = 0x13,
- kDatumTypeChunkReference = 0x1b,
- kDatumTypePolygon = 0x1d,
- kDatumTypePalette = 0x05aa
-};
-
-// It is the caller's responsibility to delete any heap items
-// that are created as part of a datum. The datum is really
-// just a container.
-class Datum {
-public:
- DatumType t;
- union {
- int i;
- double f;
- uint32 chunkRef;
- Common::String *string;
- Common::Array<Common::Point *> *polygon;
- Common::Point *point;
- Common::Rect *bbox;
- unsigned char *palette;
- } u;
-
- Datum();
- Datum(Common::SeekableReadStream &chunk);
- Datum(Common::SeekableReadStream &chunk, DatumType expectedType);
-
-private:
- void readWithType(Common::SeekableReadStream &chunk);
-};
-
-} // End of namespace MediaStation
-
-#endif
diff --git a/engines/mediastation/mediascript/codechunk.cpp b/engines/mediastation/mediascript/codechunk.cpp
index 5c95b000f77..08ae09347ad 100644
--- a/engines/mediastation/mediascript/codechunk.cpp
+++ b/engines/mediastation/mediascript/codechunk.cpp
@@ -24,26 +24,25 @@
#include "mediastation/mediastation.h"
#include "mediastation/mediascript/codechunk.h"
#include "mediastation/mediascript/collection.h"
-#include "mediastation/datum.h"
#include "mediastation/debugchannels.h"
namespace MediaStation {
-CodeChunk::CodeChunk(Common::SeekableReadStream &chunk) {
- uint lengthInBytes = Datum(chunk, kDatumTypeUint32).u.i;
+CodeChunk::CodeChunk(Chunk &chunk) {
+ uint lengthInBytes = chunk.readTypedUint32();
debugC(5, kDebugLoading, "CodeChunk::CodeChunk(): Length 0x%x (@0x%llx)", lengthInBytes, static_cast<long long int>(chunk.pos()));
- _bytecode = chunk.readStream(lengthInBytes);
+ _bytecode = static_cast<ParameterReadStream *>(chunk.readStream(lengthInBytes));
}
ScriptValue CodeChunk::executeNextBlock() {
- uint blockSize = Datum(*_bytecode, kDatumTypeUint32).u.i;
+ uint blockSize = _bytecode->readTypedUint32();
uint startingPos = _bytecode->pos();
ScriptValue returnValue;
- ExpressionType expressionType = static_cast<ExpressionType>(Datum(*_bytecode).u.i);
+ ExpressionType expressionType = static_cast<ExpressionType>(_bytecode->readTypedUint16());
while (expressionType != kExpressionTypeEmpty && !_returnImmediately) {
returnValue = evaluateExpression(expressionType);
- expressionType = static_cast<ExpressionType>(Datum(*_bytecode).u.i);
+ expressionType = static_cast<ExpressionType>(_bytecode->readTypedUint16());
}
// Verify we consumed the right number of script bytes.
@@ -57,7 +56,7 @@ ScriptValue CodeChunk::executeNextBlock() {
}
void CodeChunk::skipNextBlock() {
- uint lengthInBytes = Datum(*_bytecode, kDatumTypeUint32).u.i;
+ uint lengthInBytes = _bytecode->readTypedUint32();
_bytecode->skip(lengthInBytes);
}
@@ -77,7 +76,7 @@ ScriptValue CodeChunk::execute(Common::Array<ScriptValue> *args) {
}
ScriptValue CodeChunk::evaluateExpression() {
- ExpressionType expressionType = static_cast<ExpressionType>(Datum(*_bytecode).u.i);
+ ExpressionType expressionType = static_cast<ExpressionType>(_bytecode->readTypedUint16());
ScriptValue returnValue = evaluateExpression(expressionType);
return returnValue;
}
@@ -110,7 +109,7 @@ ScriptValue CodeChunk::evaluateExpression(ExpressionType expressionType) {
}
ScriptValue CodeChunk::evaluateOperation() {
- Opcode opcode = static_cast<Opcode>(Datum(*_bytecode).u.i);
+ Opcode opcode = static_cast<Opcode>(_bytecode->readTypedUint16());
debugCN(5, kDebugScript, "%s ", opcodeToStr(opcode));
ScriptValue returnValue;
@@ -187,13 +186,13 @@ ScriptValue CodeChunk::evaluateOperation() {
}
ScriptValue CodeChunk::evaluateValue() {
- OperandType operandType = static_cast<OperandType>(Datum(*_bytecode).u.i);
+ OperandType operandType = static_cast<OperandType>(_bytecode->readTypedUint16());
debugCN(5, kDebugScript, "%s ", operandTypeToStr(operandType));
ScriptValue returnValue;
switch (operandType) {
case kOperandTypeBool: {
- int b = Datum(*_bytecode).u.i;
+ int b = _bytecode->readTypedByte();
if (b != 0 && b != 1) {
error("Got invalid literal bool value %d", b);
}
@@ -203,14 +202,14 @@ ScriptValue CodeChunk::evaluateValue() {
}
case kOperandTypeFloat: {
- double f = Datum(*_bytecode).u.f;
+ double f = _bytecode->readTypedDouble();
debugC(5, kDebugScript, "%f ", f);
returnValue.setToFloat(f);
return returnValue;
}
case kOperandTypeInt: {
- int i = Datum(*_bytecode).u.i;
+ int i = _bytecode->readTypedSint32();
debugC(5, kDebugScript, "%d ", i);
// Ints are stored internally as doubles.
returnValue.setToFloat(static_cast<double>(i));
@@ -219,7 +218,7 @@ ScriptValue CodeChunk::evaluateValue() {
case kOperandTypeString: {
// This is indeed a raw string, not a string wrapped in a datum!
- uint size = Datum(*_bytecode, kDatumTypeUint16).u.i;
+ uint size = _bytecode->readTypedUint16();
Common::String string = _bytecode->readString('\0', size);
debugC(5, kDebugScript, "%s ", string.c_str());
returnValue.setToString(string);
@@ -227,21 +226,21 @@ ScriptValue CodeChunk::evaluateValue() {
}
case kOperandTypeParamToken: {
- uint literal = Datum(*_bytecode).u.i;
+ uint literal = _bytecode->readTypedUint16();
debugC(5, kDebugScript, "%d ", literal);
returnValue.setToParamToken(literal);
return returnValue;
}
case kOperandTypeAssetId: {
- uint assetId = Datum(*_bytecode).u.i;
+ uint assetId = _bytecode->readTypedUint16();
debugC(5, kDebugScript, "%d ", assetId);
returnValue.setToAssetId(assetId);
return returnValue;
}
case kOperandTypeTime: {
- double d = Datum(*_bytecode).u.f;
+ double d = _bytecode->readTypedTime();
debugC(5, kDebugScript, "%f ", d);
returnValue.setToTime(d);
return returnValue;
@@ -253,14 +252,14 @@ ScriptValue CodeChunk::evaluateValue() {
}
case kOperandTypeFunctionId: {
- uint functionId = Datum(*_bytecode).u.i;
+ uint functionId = _bytecode->readTypedUint16();
debugC(5, kDebugScript, "%d ", functionId);
returnValue.setToFunctionId(functionId);
return returnValue;
}
case kOperandTypeMethodId: {
- BuiltInMethod methodId = static_cast<BuiltInMethod>(Datum(*_bytecode).u.i);
+ BuiltInMethod methodId = static_cast<BuiltInMethod>(_bytecode->readTypedUint16());
debugC(5, kDebugScript, "%s ", builtInMethodToStr(methodId));
returnValue.setToMethodId(methodId);
return returnValue;
@@ -277,8 +276,8 @@ ScriptValue CodeChunk::evaluateVariable() {
}
ScriptValue *CodeChunk::readAndReturnVariable() {
- uint id = Datum(*_bytecode).u.i;
- VariableScope scope = static_cast<VariableScope>(Datum(*_bytecode).u.i);
+ uint id = _bytecode->readTypedUint16();
+ VariableScope scope = static_cast<VariableScope>(_bytecode->readTypedUint16());
debugC(5, kDebugScript, "%d (%s)", id, variableScopeToStr(scope));
ScriptValue returnValue;
@@ -444,12 +443,12 @@ ScriptValue CodeChunk::evaluateUnaryOperation() {
ScriptValue CodeChunk::evaluateFunctionCall(bool isIndirect) {
uint functionId, paramCount = 0;
if (isIndirect) {
- paramCount = Datum(*_bytecode).u.i;
+ paramCount = _bytecode->readTypedUint16();
ScriptValue value = evaluateExpression();
functionId = value.asFunctionId();
} else {
- functionId = Datum(*_bytecode).u.i;
- paramCount = Datum(*_bytecode).u.i;
+ functionId = _bytecode->readTypedUint16();
+ paramCount = _bytecode->readTypedUint16();
}
return evaluateFunctionCall(functionId, paramCount);
@@ -484,12 +483,12 @@ ScriptValue CodeChunk::evaluateMethodCall(bool isIndirect) {
BuiltInMethod method;
uint paramCount = 0;
if (isIndirect) {
- paramCount = Datum(*_bytecode).u.i;
+ paramCount = _bytecode->readTypedUint16();
ScriptValue value = evaluateExpression();
method = value.asMethodId();
} else {
- method = static_cast<BuiltInMethod>(Datum(*_bytecode).u.i);
- paramCount = Datum(*_bytecode).u.i;
+ method = static_cast<BuiltInMethod>(_bytecode->readTypedUint16());
+ paramCount = _bytecode->readTypedUint16();
}
return evaluateMethodCall(method, paramCount);
@@ -552,7 +551,7 @@ ScriptValue CodeChunk::evaluateMethodCall(BuiltInMethod method, uint paramCount)
}
void CodeChunk::evaluateDeclareLocals() {
- uint localVariableCount = Datum(*_bytecode).u.i;
+ uint localVariableCount = _bytecode->readTypedUint16();
if (localVariableCount <= 0) {
error("Got non-positive local variable count");
}
diff --git a/engines/mediastation/mediascript/codechunk.h b/engines/mediastation/mediascript/codechunk.h
index 3d6b593ca67..cc0798d56c0 100644
--- a/engines/mediastation/mediascript/codechunk.h
+++ b/engines/mediastation/mediascript/codechunk.h
@@ -23,7 +23,6 @@
#define MEDIASTATION_MEDIASCRIPT_CODECHUNK_H
#include "common/array.h"
-#include "common/stream.h"
#include "mediastation/datafile.h"
#include "mediastation/mediascript/scriptvalue.h"
@@ -33,7 +32,7 @@ namespace MediaStation {
class CodeChunk {
public:
- CodeChunk(Common::SeekableReadStream &chunk);
+ CodeChunk(Chunk &chunk);
~CodeChunk();
ScriptValue executeNextBlock();
@@ -68,7 +67,7 @@ private:
bool _returnImmediately = false;
Common::Array<ScriptValue> _locals;
Common::Array<ScriptValue> *_args = nullptr;
- Common::SeekableReadStream *_bytecode = nullptr;
+ ParameterReadStream *_bytecode = nullptr;
};
} // End of namespace MediaStation
diff --git a/engines/mediastation/mediascript/collection.cpp b/engines/mediastation/mediascript/collection.cpp
index 3f586f0f15d..bcb27940ac7 100644
--- a/engines/mediastation/mediascript/collection.cpp
+++ b/engines/mediastation/mediascript/collection.cpp
@@ -23,7 +23,6 @@
#include "mediastation/mediascript/collection.h"
#include "mediastation/mediascript/scriptvalue.h"
#include "mediastation/mediascript/codechunk.h"
-#include "mediastation/datum.h"
#include "mediastation/debugchannels.h"
namespace MediaStation {
diff --git a/engines/mediastation/mediascript/collection.h b/engines/mediastation/mediascript/collection.h
index 8788b08d9d9..632597fc03a 100644
--- a/engines/mediastation/mediascript/collection.h
+++ b/engines/mediastation/mediascript/collection.h
@@ -27,7 +27,6 @@
#include "common/array.h"
#include "mediastation/datafile.h"
-#include "mediastation/datum.h"
#include "mediastation/mediascript/scriptconstants.h"
namespace MediaStation {
diff --git a/engines/mediastation/mediascript/eventhandler.cpp b/engines/mediastation/mediascript/eventhandler.cpp
index 0c73d969b77..fa9fbbb9e68 100644
--- a/engines/mediastation/mediascript/eventhandler.cpp
+++ b/engines/mediastation/mediascript/eventhandler.cpp
@@ -25,7 +25,7 @@
namespace MediaStation {
EventHandler::EventHandler(Chunk &chunk) {
- _type = static_cast<EventType>(Datum(chunk).u.i);
+ _type = static_cast<EventType>(chunk.readTypedUint16());
debugC(5, kDebugLoading, "EventHandler::EventHandler(): Type %s (%d) (@0x%llx)",
eventTypeToStr(_type), static_cast<uint>(_type), static_cast<long long int>(chunk.pos()));
diff --git a/engines/mediastation/mediascript/eventhandler.h b/engines/mediastation/mediascript/eventhandler.h
index a72f7004af7..00a6c352f4c 100644
--- a/engines/mediastation/mediascript/eventhandler.h
+++ b/engines/mediastation/mediascript/eventhandler.h
@@ -25,7 +25,6 @@
#include "common/str.h"
#include "mediastation/datafile.h"
-#include "mediastation/datum.h"
#include "mediastation/mediascript/codechunk.h"
#include "mediastation/mediascript/scriptconstants.h"
diff --git a/engines/mediastation/mediascript/function.cpp b/engines/mediastation/mediascript/function.cpp
index 558fb165d0e..89570482602 100644
--- a/engines/mediastation/mediascript/function.cpp
+++ b/engines/mediastation/mediascript/function.cpp
@@ -19,18 +19,17 @@
*
*/
-#include "mediastation/datum.h"
#include "mediastation/mediascript/function.h"
#include "mediastation/debugchannels.h"
namespace MediaStation {
Function::Function(Chunk &chunk) {
- _fileId = Datum(chunk).u.i;
+ _fileId = chunk.readTypedUint16();
// In PROFILE._ST (only present in some titles), the function ID is reported
// with 19900 added, so function 100 would be reported as 20000. But in
// bytecode, the zero-based ID is used, so that's what we'll store here.
- _id = Datum(chunk).u.i;
+ _id = chunk.readTypedUint16();
_code = new CodeChunk(chunk);
}
diff --git a/engines/mediastation/mediascript/scriptvalue.cpp b/engines/mediastation/mediascript/scriptvalue.cpp
index 6e411caf0b6..d7ff04710b4 100644
--- a/engines/mediastation/mediascript/scriptvalue.cpp
+++ b/engines/mediastation/mediascript/scriptvalue.cpp
@@ -19,27 +19,26 @@
*
*/
-#include "mediastation/datum.h"
#include "mediastation/mediascript/scriptvalue.h"
#include "mediastation/mediascript/function.h"
namespace MediaStation {
-ScriptValue::ScriptValue(Common::SeekableReadStream *stream) {
- _type = static_cast<ScriptValueType>(Datum(*stream).u.i);
+ScriptValue::ScriptValue(ParameterReadStream *stream) {
+ _type = static_cast<ScriptValueType>(stream->readTypedByte());
switch (_type) {
case kScriptValueTypeEmpty:
break;
case kScriptValueTypeFloat: {
- double d = Datum(*stream).u.f;
+ double d = stream->readTypedDouble();
setToFloat(d);
break;
}
case kScriptValueTypeBool: {
- uint rawValue = Datum(*stream, kDatumTypeUint8).u.i;
+ uint rawValue = stream->readTypedByte();
if (rawValue != 0 && rawValue != 1) {
error("Got invalid literal bool value %d", rawValue);
}
@@ -48,32 +47,32 @@ ScriptValue::ScriptValue(Common::SeekableReadStream *stream) {
}
case kScriptValueTypeTime: {
- double d = Datum(*stream).u.f;
+ double d = stream->readTypedTime();
setToFloat(d);
break;
}
case kScriptValueTypeParamToken: {
- uint paramToken = Datum(*stream).u.i;
+ uint paramToken = stream->readTypedUint16();
setToParamToken(paramToken);
break;
}
case kScriptValueTypeAssetId: {
- uint assetId = Datum(*stream).u.i;
+ uint assetId = stream->readTypedUint16();
setToAssetId(assetId);
break;
}
case kScriptValueTypeString: {
- uint size = Datum(*stream).u.i;
+ uint size = stream->readTypedUint16();
Common::String string = stream->readString('\0', size);
setToString(string);
break;
}
case kScriptValueTypeCollection: {
- uint totalItems = Datum(*stream).u.i;
+ uint totalItems = stream->readTypedUint16();
Common::SharedPtr<Collection> collection(new Collection);
for (uint i = 0; i < totalItems; i++) {
ScriptValue collectionValue = ScriptValue(stream);
@@ -84,13 +83,13 @@ ScriptValue::ScriptValue(Common::SeekableReadStream *stream) {
}
case kScriptValueTypeFunctionId: {
- uint functionId = Datum(*stream).u.i;
+ uint functionId = stream->readTypedUint16();
setToFunctionId(functionId);
break;
}
case kScriptValueTypeMethodId: {
- BuiltInMethod methodId = static_cast<BuiltInMethod>(Datum(*stream).u.i);
+ BuiltInMethod methodId = static_cast<BuiltInMethod>(stream->readTypedUint16());
setToMethodId(methodId);
break;
}
diff --git a/engines/mediastation/mediascript/scriptvalue.h b/engines/mediastation/mediascript/scriptvalue.h
index abbd5da6711..75c70f6368c 100644
--- a/engines/mediastation/mediascript/scriptvalue.h
+++ b/engines/mediastation/mediascript/scriptvalue.h
@@ -24,8 +24,8 @@
#include "common/ptr.h"
#include "common/str.h"
-#include "common/stream.h"
+#include "mediastation/datafile.h"
#include "mediastation/mediascript/scriptconstants.h"
#include "mediastation/mediascript/collection.h"
@@ -36,7 +36,7 @@ class Asset;
class ScriptValue {
public:
ScriptValue() : _type(kScriptValueTypeEmpty) {}
- ScriptValue(Common::SeekableReadStream *stream);
+ ScriptValue(ParameterReadStream *stream);
ScriptValueType getType() const { return _type; }
diff --git a/engines/mediastation/mediastation.cpp b/engines/mediastation/mediastation.cpp
index 5f22fe6ea7c..92c29af6236 100644
--- a/engines/mediastation/mediastation.cpp
+++ b/engines/mediastation/mediastation.cpp
@@ -125,7 +125,7 @@ bool MediaStationEngine::isFirstGenerationEngine() {
if (_boot == nullptr) {
error("Attempted to get engine version before BOOT.STM was read");
} else {
- return (_boot->_versionInfo == nullptr);
+ return (_boot->_versionInfo.major == 0);
}
}
@@ -264,7 +264,7 @@ void MediaStationEngine::setCursor(uint id) {
if (cursorDeclaration == nullptr) {
error("MediaStationEngine::setCursor(): Cursor %d not declared", id);
}
- _cursor->setCursor(*cursorDeclaration->_name);
+ _cursor->setCursor(cursorDeclaration->_name);
}
}
@@ -303,9 +303,9 @@ void MediaStationEngine::redraw() {
for (Common::Rect dirtyRect : _dirtyRects) {
for (Asset *asset : _assetsPlaying) {
- Common::Rect *bbox = asset->getBbox();
- if (bbox != nullptr) {
- if (dirtyRect.intersects(*bbox)) {
+ Common::Rect bbox = asset->getBbox();
+ if (!bbox.isEmpty()) {
+ if (dirtyRect.intersects(bbox)) {
asset->redraw(dirtyRect);
}
}
@@ -347,7 +347,7 @@ Context *MediaStationEngine::loadContext(uint32 contextId) {
warning("MediaStationEngine::loadContext(): Couldn't find file declaration with ID 0x%x", fileId);
return nullptr;
}
- Common::Path entryCxtFilepath(*fileDeclaration->_name);
+ Common::Path entryCxtFilepath(fileDeclaration->_name);
// Load any child contexts before we actually load this one. The child
// contexts must be unloaded explicitly later.
diff --git a/engines/mediastation/module.mk b/engines/mediastation/module.mk
index da72f49bc9a..8c43dddd48c 100644
--- a/engines/mediastation/module.mk
+++ b/engines/mediastation/module.mk
@@ -20,7 +20,6 @@ MODULE_OBJS = \
context.o \
cursors.o \
datafile.o \
- datum.o \
mediascript/codechunk.o \
mediascript/collection.o \
mediascript/eventhandler.o \
Commit: a43e097df18780d696d26e83e58c849534c5abc8
https://github.com/scummvm/scummvm/commit/a43e097df18780d696d26e83e58c849534c5abc8
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-05-10T17:25:03-04:00
Commit Message:
MEDIASTATION: Simplify Boot stream parsing
Changed paths:
engines/mediastation/boot.cpp
engines/mediastation/boot.h
engines/mediastation/mediastation.cpp
diff --git a/engines/mediastation/boot.cpp b/engines/mediastation/boot.cpp
index 55acbfe80f0..fb767591453 100644
--- a/engines/mediastation/boot.cpp
+++ b/engines/mediastation/boot.cpp
@@ -26,65 +26,35 @@ namespace MediaStation {
#pragma region ContextDeclaration
ContextDeclaration::ContextDeclaration(Chunk &chunk) {
- // Make sure this declaration isn't empty.
+ // Read the file number.
ContextDeclarationSectionType sectionType = getSectionType(chunk);
- if (kContextDeclarationEmptySection == sectionType) {
- _isLast = true;
- return;
- } else {
- // There may be more declarations in the stream.
- _isLast = false;
+ if (kContextDeclarationContextId != sectionType) {
+ error("Got unexpected section type %d", static_cast<uint>(sectionType));
}
+ _contextId = chunk.readTypedUint16();
- if (kContextDeclarationPlaceholder == sectionType) {
- // Read the file number.
- sectionType = getSectionType(chunk);
- if (kContextDeclarationFileNumber1 == sectionType) {
- _fileNumber = chunk.readTypedUint16();
- } else {
- error("ContextDeclaration(): Expected section type FILE_NUMBER_1, got 0x%x", static_cast<uint>(sectionType));
- }
- // I don't know why the file number is always repeated.
- // Is it just for data integrity, or is there some other reason?
- sectionType = getSectionType(chunk);
- if (kContextDeclarationFileNumber2 == sectionType) {
- uint32 repeatedFileNumber = chunk.readTypedUint16();
- if (repeatedFileNumber != _fileNumber) {
- warning("ContextDeclaration(): Expected file numbers to match, but 0x%d != 0x%d", _fileNumber, repeatedFileNumber);
- }
- } else {
- error("ContextDeclaration(): Expected section type FILE_NUMBER_2, got 0x%x", static_cast<uint>(sectionType));
- }
+ sectionType = getSectionType(chunk);
+ if (kContextDeclarationStreamId != sectionType) {
+ error("Got unexpected section type %d", static_cast<uint>(sectionType));
+ }
+ _streamId = chunk.readTypedUint16();
- // Read the context name.
- // Only some titles have context names, and unfortunately we can't
- // determine which just by relying on the title compiler version
- // number.
- // TODO: Find a better way to read the context name without relying
- // on reading and rewinding.
- int rewindOffset = chunk.pos();
+ // Read the context name. Only some titles have context names,
+ // and unfortunately we can't determine which just by relying
+ // on the title compiler version number.
+ sectionType = getSectionType(chunk);
+ if (kContextDeclarationName == sectionType) {
+ _name = chunk.readTypedString();
sectionType = getSectionType(chunk);
- if (kContextDeclarationName == sectionType) {
- _contextName = chunk.readTypedString();
- } else {
- // There is no context name.
- // We have instead read into the next declaration, so let's undo that.
- chunk.seek(rewindOffset);
- }
- } else if (kContextDeclarationEmptySection == sectionType) {
- _isLast = true;
- } else {
- error("ContextDeclaration::ContextDeclaration(): Unknown section type 0x%x", static_cast<uint>(sectionType));
}
- // Read the file references.
- // We don't know how many file references there are beforehand, so we'll
- // just read until we get something else.
- int rewindOffset = 0;
- sectionType = getSectionType(chunk);
- while (kContextDeclarationFileReference == sectionType) {
+ // Read the parent context IDs. We don't know how many file
+ // references there are beforehand, so we'll just read until
+ // we get something else.
+ uint rewindOffset = chunk.pos();
+ while (kContextDeclarationParentContextId == sectionType) {
int fileReference = chunk.readTypedUint16();
- _fileReferences.push_back(fileReference);
+ _parentContextIds.push_back(fileReference);
rewindOffset = chunk.pos();
sectionType = getSectionType(chunk);
}
@@ -96,67 +66,42 @@ ContextDeclarationSectionType ContextDeclaration::getSectionType(Chunk &chunk) {
}
#pragma endregion
-#pragma region UnknownDeclaration
-UnknownDeclaration::UnknownDeclaration(Chunk &chunk) {
+#pragma region ScreenDeclaration
+ScreenDeclaration::ScreenDeclaration(Chunk &chunk) {
// Make sure this declaration isn't empty.
- UnknownDeclarationSectionType sectionType = getSectionType(chunk);
- if (kUnknownDeclarationEmptySection == sectionType) {
- _isLast = true;
- return;
- } else {
- // There may be more declarations in the stream.
- _isLast = false;
+ ScreenDeclarationSectionType sectionType = getSectionType(chunk);
+ if (kScreenDeclarationAssetId != sectionType) {
+ error("Got unexpected section type %d", static_cast<uint>(sectionType));
}
+ _assetId = chunk.readTypedUint16();
sectionType = getSectionType(chunk);
- if (kUnknownDeclarationUnk1 == sectionType) {
- _unk = chunk.readTypedUint16();
- } else {
- error("UnknownDeclaration(): Expected section type UNK_1, got 0x%x", static_cast<uint>(sectionType));
- }
- sectionType = getSectionType(chunk);
- if (kUnknownDeclarationUnk2 == sectionType) {
- uint16 repeatedUnk = chunk.readTypedUint16();
- if (repeatedUnk != _unk) {
- warning("UnknownDeclaration(): Expected unknown values to match, but 0x%x != 0x%x", _unk, repeatedUnk);
- }
- } else {
- error("UnknownDeclaration(): Expected section type UNK_2, got 0x%x", static_cast<uint>(sectionType));
+ if (kScreenDeclarationScreenId != sectionType) {
+ error("Got unexpected section type %d", static_cast<uint>(sectionType));
}
+ _screenId = chunk.readTypedUint16();
}
-UnknownDeclarationSectionType UnknownDeclaration::getSectionType(Chunk &chunk) {
- return static_cast<UnknownDeclarationSectionType>(chunk.readTypedUint16());
+ScreenDeclarationSectionType ScreenDeclaration::getSectionType(Chunk &chunk) {
+ return static_cast<ScreenDeclarationSectionType>(chunk.readTypedUint16());
}
#pragma endregion
#pragma region FileDeclaration
FileDeclaration::FileDeclaration(Chunk &chunk) {
- // Make sure this declaration isn't empty.
- FileDeclarationSectionType sectionType = getSectionType(chunk);
- if (kFileDeclarationEmptySection == sectionType) {
- _isLast = true;
- return;
- } else {
- // There may be more declarations in the stream.
- _isLast = false;
- }
-
// Read the file ID.
- sectionType = getSectionType(chunk);
- if (kFileDeclarationFileId == sectionType) {
- _id = chunk.readTypedUint16();
- } else {
- error("FileDeclaration(): Expected section type FILE_ID, got 0x%x", static_cast<uint>(sectionType));
+ FileDeclarationSectionType sectionType = getSectionType(chunk);
+ if (kFileDeclarationFileId != sectionType) {
+ error("Got unexpected section type %d", static_cast<uint>(sectionType));
}
+ _id = chunk.readTypedUint16();
// Read the intended file location.
sectionType = getSectionType(chunk);
- if (kFileDeclarationFileNameAndType == sectionType) {
- _intendedLocation = static_cast<IntendedFileLocation>(chunk.readTypedUint16());
- } else {
- error("FileDeclaration(): Expected section type FILE_NAME_AND_TYPE, got 0x%x", static_cast<uint>(sectionType));
+ if (kFileDeclarationFileNameAndType != sectionType) {
+ error("Got unexpected section type %d", static_cast<uint>(sectionType));
}
+ _intendedLocation = static_cast<IntendedFileLocation>(chunk.readTypedUint16());
// Since the platforms that Media Station originally targeted were case-insensitive,
// the case of these filenames might not match the case of the files actually in
@@ -171,39 +116,26 @@ FileDeclarationSectionType FileDeclaration::getSectionType(Chunk &chunk) {
#pragma region SubfileDeclaration
SubfileDeclaration::SubfileDeclaration(Chunk &chunk) {
- // Make sure this declaration isn't empty.
- SubfileDeclarationSectionType sectionType = getSectionType(chunk);
- if (kSubfileDeclarationEmptySection == sectionType) {
- _isLast = true;
- return;
- } else {
- // There may be more declarations in the stream.
- _isLast = false;
- }
-
// Read the asset ID.
- sectionType = getSectionType(chunk);
- if (kSubfileDeclarationAssetId == sectionType) {
- _assetId = chunk.readTypedUint16();
- } else {
- error("SubfileDeclaration(): Expected section type ASSET_ID, got 0x%x", static_cast<uint>(sectionType));
+ SubfileDeclarationSectionType sectionType = getSectionType(chunk);
+ if (kSubfileDeclarationAssetId != sectionType) {
+ error("Got unexpected section type %d", static_cast<uint>(sectionType));
}
+ _assetId = chunk.readTypedUint16();
// Read the file ID.
sectionType = getSectionType(chunk);
- if (kSubfileDeclarationFileId == sectionType) {
- _fileId = chunk.readTypedUint16();
- } else {
+ if (kSubfileDeclarationFileId != sectionType) {
error("SubfileDeclaration(): Expected section type FILE_ID, got 0x%x", static_cast<uint>(sectionType));
}
+ _fileId = chunk.readTypedUint16();
// Read the start offset from the absolute start of the file.
sectionType = getSectionType(chunk);
- if (kSubfileDeclarationStartOffset == sectionType) {
- _startOffsetInFile = chunk.readTypedUint32();
- } else {
+ if (kSubfileDeclarationStartOffset != sectionType) {
error("SubfileDeclaration(): Expected section type START_OFFSET, got 0x%x", static_cast<uint>(sectionType));
}
+ _startOffsetInFile = chunk.readTypedUint32();
}
SubfileDeclarationSectionType SubfileDeclaration::getSectionType(Chunk &chunk) {
@@ -265,7 +197,7 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
sectionType = getSectionType(chunk);
if (sectionType == kBootEngineResourceId) {
int resourceId = chunk.readTypedUint16();
- EngineResourceDeclaration *resourceDeclaration = new EngineResourceDeclaration(resourceName, resourceId);
+ EngineResourceDeclaration resourceDeclaration = EngineResourceDeclaration(resourceName, resourceId);
_engineResourceDeclarations.setVal(resourceId, resourceDeclaration);
} else {
error("Boot::Boot(): Got section type 0x%x when expecting ENGINE_RESOURCE_ID", static_cast<uint>(sectionType));
@@ -274,56 +206,48 @@ Boot::Boot(const Common::Path &path) : Datafile(path){
}
case kBootContextDeclaration: {
- ContextDeclaration *contextDeclaration = new ContextDeclaration(chunk);
- while (!contextDeclaration->_isLast) {
- _contextDeclarations.setVal(contextDeclaration->_fileNumber, contextDeclaration);
- contextDeclaration = new ContextDeclaration(chunk);
+ uint flag = chunk.readTypedUint16();
+ while (flag != 0) {
+ ContextDeclaration contextDeclaration = ContextDeclaration(chunk);
+ _contextDeclarations.setVal(contextDeclaration._contextId, contextDeclaration);
+ flag = chunk.readTypedUint16();
}
- // The very last declaration is just an empty flag, so delete it
- // since it's not put in the map.
- delete contextDeclaration;
break;
}
- case kBootUnknownDeclaration: {
- UnknownDeclaration *unknownDeclaration = new UnknownDeclaration(chunk);
- while (!unknownDeclaration->_isLast) {
- _unknownDeclarations.push_back(unknownDeclaration);
- unknownDeclaration = new UnknownDeclaration(chunk);
+ case kBootScreenDeclaration: {
+ uint flag = chunk.readTypedUint16();
+ while (flag != 0) {
+ ScreenDeclaration screenDeclaration = ScreenDeclaration(chunk);
+ _screenDeclarations.setVal(screenDeclaration._assetId, screenDeclaration);
+ flag = chunk.readTypedUint16();
}
- // The very last declaration is just an empty flag, so delete it
- // since it's not put in the map.
- delete unknownDeclaration;
break;
}
case kBootFileDeclaration: {
- FileDeclaration *fileDeclaration = new FileDeclaration(chunk);
- while (!fileDeclaration->_isLast) {
- _fileDeclarations.setVal(fileDeclaration->_id, fileDeclaration);
- fileDeclaration = new FileDeclaration(chunk);
- }
- // The very last declaration is just an empty flag, so delete it
- // since it's not put in the map.
- delete fileDeclaration;
+ uint flag = chunk.readTypedUint16();
+ while (flag != 0) {
+ FileDeclaration fileDeclaration = FileDeclaration(chunk);
+ _fileDeclarations.setVal(fileDeclaration._id, fileDeclaration);
+ flag = chunk.readTypedUint16();
+ };
break;
}
case kBootSubfileDeclaration: {
- SubfileDeclaration *subfileDeclaration = new SubfileDeclaration(chunk);
- while (!subfileDeclaration->_isLast) {
- _subfileDeclarations.setVal(subfileDeclaration->_assetId, subfileDeclaration);
- subfileDeclaration = new SubfileDeclaration(chunk);
+ uint flag = chunk.readTypedUint16();
+ while (flag != 0) {
+ SubfileDeclaration subfileDeclaration = SubfileDeclaration(chunk);
+ _subfileDeclarations.setVal(subfileDeclaration._assetId, subfileDeclaration);
+ flag = chunk.readTypedUint16();
}
- // The very last declaration is just an empty flag, so delete it
- // since it's not put in the map.
- delete subfileDeclaration;
break;
}
case kBootCursorDeclaration: {
- CursorDeclaration *cursorDeclaration = new CursorDeclaration(chunk);
- _cursorDeclarations.setVal(cursorDeclaration->_id, cursorDeclaration);
+ CursorDeclaration cursorDeclaration = CursorDeclaration(chunk);
+ _cursorDeclarations.setVal(cursorDeclaration._id, cursorDeclaration);
break;
}
@@ -373,34 +297,11 @@ BootSectionType Boot::getSectionType(Chunk &chunk) {
}
Boot::~Boot() {
- for (auto it = _contextDeclarations.begin(); it != _contextDeclarations.end(); ++it) {
- delete it->_value;
- }
_contextDeclarations.clear();
-
- for (auto it = _subfileDeclarations.begin(); it != _subfileDeclarations.end(); ++it) {
- delete it->_value;
- }
_subfileDeclarations.clear();
-
- for (auto it = _cursorDeclarations.begin(); it != _cursorDeclarations.end(); ++it) {
- delete it->_value;
- }
_cursorDeclarations.clear();
-
- for (auto it = _engineResourceDeclarations.begin(); it != _engineResourceDeclarations.end(); ++it) {
- delete it->_value;
- }
_engineResourceDeclarations.clear();
-
- for (auto unknownDeclaration : _unknownDeclarations) {
- delete unknownDeclaration;
- }
- _unknownDeclarations.clear();
-
- for (auto it = _fileDeclarations.begin(); it != _fileDeclarations.end(); ++it) {
- delete it->_value;
- }
+ _screenDeclarations.clear();
_fileDeclarations.clear();
}
#pragma endregion
diff --git a/engines/mediastation/boot.h b/engines/mediastation/boot.h
index 47a79d7c5a6..f77332bbdb9 100644
--- a/engines/mediastation/boot.h
+++ b/engines/mediastation/boot.h
@@ -34,42 +34,42 @@ namespace MediaStation {
enum ContextDeclarationSectionType {
kContextDeclarationEmptySection = 0x0000,
kContextDeclarationPlaceholder = 0x0003,
- kContextDeclarationFileNumber1 = 0x0004,
- kContextDeclarationFileNumber2 = 0x0005,
- kContextDeclarationFileReference = 0x0006,
+ kContextDeclarationContextId = 0x0004,
+ kContextDeclarationStreamId = 0x0005,
+ kContextDeclarationParentContextId = 0x0006,
kContextDeclarationName = 0x0bb8
};
class ContextDeclaration {
public:
ContextDeclaration(Chunk &chunk);
+ ContextDeclaration() {};
- Common::Array<uint32> _fileReferences;
- uint32 _fileNumber = 0;
- Common::String _contextName;
- // Signal that there are no more declarations to read.
- bool _isLast = false;
+ uint _contextId = 0;
+ uint _streamId = 0;
+ Common::String _name;
+ Common::Array<uint> _parentContextIds;
private:
ContextDeclarationSectionType getSectionType(Chunk &chunk);
};
-enum UnknownDeclarationSectionType {
- kUnknownDeclarationEmptySection = 0x0000,
- kUnknownDeclarationUnk1 = 0x0009,
- kUnknownDeclarationUnk2 = 0x0004
+enum ScreenDeclarationSectionType {
+ kScreenDeclarationEmpty = 0x0000,
+ kScreenDeclarationAssetId = 0x0009,
+ kScreenDeclarationScreenId = 0x0004
};
-class UnknownDeclaration {
+class ScreenDeclaration {
public:
- uint16 _unk = 0;
- // Signal that there are no more declarations to read.
- bool _isLast = false;
+ ScreenDeclaration(Chunk &chunk);
+ ScreenDeclaration() {};
- UnknownDeclaration(Chunk &chunk);
+ uint _assetId = 0;
+ uint _screenId = 0;
private:
- UnknownDeclarationSectionType getSectionType(Chunk& chunk);
+ ScreenDeclarationSectionType getSectionType(Chunk& chunk);
};
enum FileDeclarationSectionType {
@@ -81,6 +81,7 @@ enum FileDeclarationSectionType {
// Indicates where a file is intended to be stored.
// NOTE: This might not be correct and this might be a more general "file type".
enum IntendedFileLocation {
+ kFileLocationEmpty = 0x0000,
// Usually all files that have numbers remain on the CD-ROM.
kFileIntendedOnCdRom = 0x0007,
// These UNKs only appear in George Shrinks.
@@ -93,12 +94,11 @@ enum IntendedFileLocation {
class FileDeclaration {
public:
FileDeclaration(Chunk &chunk);
+ FileDeclaration() {};
- uint32 _id = 0;
- IntendedFileLocation _intendedLocation;
+ uint _id = 0;
+ IntendedFileLocation _intendedLocation = kFileLocationEmpty;
Common::String _name;
- // Signal that there are no more declarations to read.
- bool _isLast = false;
private:
FileDeclarationSectionType getSectionType(Chunk &chunk);
@@ -114,12 +114,11 @@ enum SubfileDeclarationSectionType {
class SubfileDeclaration {
public:
SubfileDeclaration(Chunk &chunk);
+ SubfileDeclaration() {};
- uint16 _assetId = 0;
- uint16 _fileId = 0;
- uint32 _startOffsetInFile = 0;
- // Signal that there are no more context declarations to read.
- bool _isLast = false;
+ uint _assetId = 0;
+ uint _fileId = 0;
+ uint _startOffsetInFile = 0;
private:
SubfileDeclarationSectionType getSectionType(Chunk &chunk);
@@ -129,18 +128,20 @@ private:
class CursorDeclaration {
public:
CursorDeclaration(Chunk &chunk);
+ CursorDeclaration() {};
- uint16 _id = 0;
- uint16 _unk = 0;
+ uint _id = 0;
+ uint _unk = 0;
Common::String _name;
};
class EngineResourceDeclaration {
public:
- Common::String _resourceName;
- int _resourceId = 0;
+ EngineResourceDeclaration(Common::String resourceName, int resourceId) : _name(resourceName), _id(resourceId) {};
+ EngineResourceDeclaration() {};
- EngineResourceDeclaration(Common::String resourceName, int resourceId) : _resourceName(resourceName), _resourceId(resourceId) {};
+ Common::String _name;
+ int _id = 0;
};
enum BootSectionType {
@@ -153,7 +154,7 @@ enum BootSectionType {
kBootUnk3 = 0x0193,
kBootEngineResource = 0x0bba,
kBootEngineResourceId = 0x0bbb,
- kBootUnknownDeclaration = 0x0007,
+ kBootScreenDeclaration = 0x0007,
kBootFileDeclaration = 0x000a,
kBootSubfileDeclaration = 0x000b,
kBootUnk5 = 0x000c,
@@ -173,12 +174,12 @@ public:
VersionInfo _versionInfo;
Common::String _engineInfo;
Common::String _sourceString;
- Common::HashMap<uint32, ContextDeclaration *> _contextDeclarations;
- Common::Array<UnknownDeclaration *> _unknownDeclarations;
- Common::HashMap<uint32, FileDeclaration *> _fileDeclarations;
- Common::HashMap<uint32, SubfileDeclaration *> _subfileDeclarations;
- Common::HashMap<uint32, CursorDeclaration *> _cursorDeclarations;
- Common::HashMap<uint32, EngineResourceDeclaration *> _engineResourceDeclarations;
+ Common::HashMap<uint32, ContextDeclaration> _contextDeclarations;
+ Common::HashMap<uint32, ScreenDeclaration> _screenDeclarations;
+ Common::HashMap<uint32, FileDeclaration> _fileDeclarations;
+ Common::HashMap<uint32, SubfileDeclaration> _subfileDeclarations;
+ Common::HashMap<uint32, CursorDeclaration> _cursorDeclarations;
+ Common::HashMap<uint32, EngineResourceDeclaration> _engineResourceDeclarations;
uint32 _entryContextId = 0;
bool _allowMultipleSounds = false;
diff --git a/engines/mediastation/mediastation.cpp b/engines/mediastation/mediastation.cpp
index 92c29af6236..aebaa7b6355 100644
--- a/engines/mediastation/mediastation.cpp
+++ b/engines/mediastation/mediastation.cpp
@@ -260,11 +260,8 @@ void MediaStationEngine::setCursor(uint id) {
// that's a lookup into BOOT.STM, which gives actual name the name of the
// resource in the executable.
if (id != 0) {
- CursorDeclaration *cursorDeclaration = _boot->_cursorDeclarations.getValOrDefault(id);
- if (cursorDeclaration == nullptr) {
- error("MediaStationEngine::setCursor(): Cursor %d not declared", id);
- }
- _cursor->setCursor(cursorDeclaration->_name);
+ const CursorDeclaration &cursorDeclaration = _boot->_cursorDeclarations.getVal(id);
+ _cursor->setCursor(cursorDeclaration._name);
}
}
@@ -328,31 +325,23 @@ Context *MediaStationEngine::loadContext(uint32 contextId) {
}
// Get the file ID.
- SubfileDeclaration *subfileDeclaration = _boot->_subfileDeclarations.getValOrDefault(contextId);
- if (subfileDeclaration == nullptr) {
- error("MediaStationEngine::loadContext(): Couldn't find subfile declaration with ID %d", contextId);
- return nullptr;
- }
+ const SubfileDeclaration &subfileDeclaration = _boot->_subfileDeclarations.getVal(contextId);
// There are other assets in a subfile too, so we need to make sure we're
// referencing the screen asset, at the start of the file.
- if (subfileDeclaration->_startOffsetInFile != 16) {
+ if (subfileDeclaration._startOffsetInFile != 16) {
warning("MediaStationEngine::loadContext(): Requested ID wasn't for a context.");
return nullptr;
}
- uint32 fileId = subfileDeclaration->_fileId;
+ uint fileId = subfileDeclaration._fileId;
// Get the filename.
- FileDeclaration *fileDeclaration = _boot->_fileDeclarations.getValOrDefault(fileId);
- if (fileDeclaration == nullptr) {
- warning("MediaStationEngine::loadContext(): Couldn't find file declaration with ID 0x%x", fileId);
- return nullptr;
- }
- Common::Path entryCxtFilepath(fileDeclaration->_name);
+ const FileDeclaration &fileDeclaration = _boot->_fileDeclarations.getVal(fileId);
+ Common::Path entryCxtFilepath(fileDeclaration._name);
// Load any child contexts before we actually load this one. The child
// contexts must be unloaded explicitly later.
- ContextDeclaration *contextDeclaration = _boot->_contextDeclarations.getValOrDefault(contextId);
- for (uint32 childContextId : contextDeclaration->_fileReferences) {
+ ContextDeclaration contextDeclaration = _boot->_contextDeclarations.getVal(contextId);
+ for (uint childContextId : contextDeclaration._parentContextIds) {
// The root context is referred to by an ID of 0, regardless of what its
// actual ID is. The root context is already always loaded.
if (childContextId != 0) {
@@ -469,8 +458,8 @@ void MediaStationEngine::releaseContext(uint32 contextId) {
// Make sure nothing is still using this context.
for (auto it = _loadedContexts.begin(); it != _loadedContexts.end(); ++it) {
uint id = it->_key;
- ContextDeclaration *contextDeclaration = _boot->_contextDeclarations.getValOrDefault(id);
- for (uint32 childContextId : contextDeclaration->_fileReferences) {
+ ContextDeclaration contextDeclaration = _boot->_contextDeclarations.getVal(id);
+ for (uint32 childContextId : contextDeclaration._parentContextIds) {
if (childContextId == contextId) {
return;
}
Commit: 1e76610489d1644179994bfd86daf3613ad21bc1
https://github.com/scummvm/scummvm/commit/1e76610489d1644179994bfd86daf3613ad21bc1
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-05-10T17:25:03-04:00
Commit Message:
MEDIASTATION: Correctly implement collection methods
Changed paths:
engines/mediastation/mediascript/collection.cpp
engines/mediastation/mediascript/collection.h
engines/mediastation/mediascript/scriptconstants.cpp
engines/mediastation/mediascript/scriptconstants.h
engines/mediastation/mediascript/scriptvalue.cpp
engines/mediastation/mediascript/scriptvalue.h
diff --git a/engines/mediastation/mediascript/collection.cpp b/engines/mediastation/mediascript/collection.cpp
index bcb27940ac7..c78219e899b 100644
--- a/engines/mediastation/mediascript/collection.cpp
+++ b/engines/mediastation/mediascript/collection.cpp
@@ -29,105 +29,145 @@ namespace MediaStation {
ScriptValue Collection::callMethod(BuiltInMethod method, Common::Array<ScriptValue> &args) {
ScriptValue returnValue;
-
switch (method) {
- case kIsEmptyMethod: {
- returnValue.setToBool(empty());
- return returnValue;
- }
-
- case kAppendMethod: {
- for (ScriptValue arg : args) {
- push_back(arg);
+ case kAppendMethod:
+ for (ScriptValue value : args) {
+ push_back(value);
}
- return returnValue;
- }
+ break;
- case kDeleteFirstMethod: {
- returnValue = remove_at(0);
- return returnValue;
- }
+ case kApplyMethod:
+ apply(args);
+ break;
- case kDeleteAtMethod: {
- // Find the item in the collection, then remove and return it.
- assert(args.size() == 1);
- for (uint i = 0; i < size(); i++) {
- if (args[0] == operator[](i)) {
- returnValue = remove_at(i);
- return returnValue;
- }
- }
+ case kCountMethod:
+ assert(args.empty());
+ returnValue.setToFloat(size());
+ break;
- // The item wasn't found.
- return returnValue;
- }
+ case kDeleteFirstMethod:
+ assert(args.empty());
+ returnValue = remove_at(0);
+ break;
- case kCountMethod: {
- double size = static_cast<double>(this->size());
- returnValue.setToFloat(size);
- return returnValue;
- }
+ case kDeleteLastMethod:
+ assert(args.empty());
+ returnValue = remove_at(size() - 1);
+ break;
+
+ case kEmptyMethod:
+ assert(args.empty());
+ clear();
+ break;
case kGetAtMethod: {
assert(args.size() == 1);
uint index = static_cast<uint>(args[0].asFloat());
returnValue = operator[](index);
- return returnValue;
+ break;
}
- case kSendMethod: {
- // Call a method on each item in the collection.
- BuiltInMethod methodToSend = static_cast<BuiltInMethod>(args[0].asMethodId());
- Common::Array<ScriptValue> sendArgs;
- for (uint i = 0; i < size(); i++) {
- ScriptValue self = operator[](i);
-
- uint assetId = self.asAssetId();
- Asset *selfAsset = g_engine->getAssetById(assetId);
- if (selfAsset != nullptr) {
- Common::Array<ScriptValue> emptyArgs;
- returnValue = selfAsset->callMethod(methodToSend, emptyArgs);
- }
- }
- return returnValue;
- }
+ case kIsEmptyMethod:
+ assert(args.empty());
+ returnValue.setToBool(empty());
+ break;
+
+ case kJumbleMethod:
+ assert(args.empty());
+ jumble();
+ break;
case kSeekMethod: {
- // Find the item in the collection if it exists.
assert(args.size() == 1);
- for (uint i = 0; i < size(); i++) {
- if (args[0] == operator[](i)) {
- return operator[](i);
- }
- }
+ int index = seek(args[0]);
+ returnValue.setToFloat(index);
+ break;
+ }
+
+ case kSendMethod:
+ send(args);
+ break;
- // The item wasn't found.
- returnValue.setToFloat(-1.0);
- return returnValue;
+ case kDeleteAtMethod: {
+ assert(args.size() == 1);
+ uint index = static_cast<uint>(args[0].asFloat());
+ returnValue = remove_at(index);
+ break;
}
- case kJumbleMethod: {
- // Scramble the items in the collection.
- for (uint i = size() - 1; i > 0; --i) {
- uint j = g_engine->_randomSource.getRandomNumber(size() - 1);
- SWAP(operator[](i), operator[](j));
- }
- return returnValue;
+ case kInsertAtMethod: {
+ assert(args.size() == 2);
+ uint index = static_cast<uint>(args[1].asFloat());
+ insert_at(index, args[0]);
+ break;
}
- case kSortMethod: {
+ case kReplaceAtMethod: {
+ assert(args.size() == 2);
+ uint index = static_cast<uint>(args[1].asFloat());
+ operator[](index) = args[0];
+ break;
+ }
+
+ case kPrependListMethod:
+ insert_at(0, args);
+ break;
+
+ case kSortMethod:
assert(args.empty());
Common::sort(begin(), end());
- return returnValue;
+ break;
+
+ default:
+ error("Attempt to call unimplemented method %s (%d)", builtInMethodToStr(method), static_cast<uint>(method));
}
+ return returnValue;
+}
- case kEmptyMethod: {
- clear();
- return returnValue;
+void Collection::apply(const Common::Array<ScriptValue> &args) {
+ // Calls a function with each element of the collection as the first arg.
+ Common::Array<ScriptValue> argsToApply = args;
+ uint functionId = args[0].asFunctionId();
+ for (const ScriptValue &item : *this) {
+ argsToApply[0] = item;
+ // TODO: Need to create and call FunctionManager.
+ warning("Applying function %d not implemented", functionId);
}
+}
- default:
- error("Collection::callMethod(): Attempt to call unimplemented method %s (%d)", builtInMethodToStr(method), static_cast<uint>(method));
+void Collection::send(const Common::Array<ScriptValue> &args) {
+ Common::Array<ScriptValue> argsToSend(args.size() - 1);
+ if (argsToSend.size() > 0) {
+ for (uint i = 1; i < args.size(); i++) {
+ argsToSend[i - 1] = args[i];
+ }
+ }
+
+ BuiltInMethod methodToSend = static_cast<BuiltInMethod>(args[0].asMethodId());
+ Common::Array<ScriptValue> sendArgs;
+ for (const ScriptValue &item : *this) {
+ uint assetId = item.asAssetId();
+ Asset *targetAsset = g_engine->getAssetById(assetId);
+ if (targetAsset != nullptr) {
+ targetAsset->callMethod(methodToSend, argsToSend);
+ }
+ }
+}
+
+int Collection::seek(const ScriptValue &item) {
+ // Search from back to front.
+ for (int i = size() - 1; i >= 0; i--) {
+ if (item == operator[](i)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void Collection::jumble() {
+ for (uint i = size() - 1; i > 0; --i) {
+ uint j = g_engine->_randomSource.getRandomNumber(size() - 1);
+ SWAP(operator[](i), operator[](j));
}
}
diff --git a/engines/mediastation/mediascript/collection.h b/engines/mediastation/mediascript/collection.h
index 632597fc03a..950b7b7f662 100644
--- a/engines/mediastation/mediascript/collection.h
+++ b/engines/mediastation/mediascript/collection.h
@@ -36,6 +36,12 @@ class ScriptValue;
class Collection : public Common::Array<ScriptValue> {
public:
ScriptValue callMethod(BuiltInMethod method, Common::Array<ScriptValue> &args);
+
+private:
+ void apply(const Common::Array<ScriptValue> &values);
+ void send(const Common::Array<ScriptValue> &values);
+ int seek(const ScriptValue &itemToFind);
+ void jumble();
};
} // End of namespace MediaStation
diff --git a/engines/mediastation/mediascript/scriptconstants.cpp b/engines/mediastation/mediascript/scriptconstants.cpp
index f2ff59527e7..62616d2f6cd 100644
--- a/engines/mediastation/mediascript/scriptconstants.cpp
+++ b/engines/mediastation/mediascript/scriptconstants.cpp
@@ -207,28 +207,38 @@ const char *builtInMethodToStr(BuiltInMethod method) {
return "SetText";
case kSetMaximumTextLengthMethod:
return "SetMaximumTextLength";
- case kIsEmptyMethod:
- return "IsEmpty";
- case kEmptyMethod:
- return "Empty";
case kAppendMethod:
return "Append";
- case kGetAtMethod:
- return "GetAt";
+ case kApplyMethod:
+ return "Apply";
case kCountMethod:
return "Count";
- case kSendMethod:
- return "Send";
+ case kDeleteFirstMethod:
+ return "DeleteFirst";
+ case kDeleteLastMethod:
+ return "DeleteLast";
+ case kEmptyMethod:
+ return "Empty";
+ case kGetAtMethod:
+ return "GetAt";
+ case kIsEmptyMethod:
+ return "IsEmpty";
+ case kJumbleMethod:
+ return "Jumble";
case kSeekMethod:
return "Seek";
- case kSortMethod:
- return "Sort";
+ case kSendMethod:
+ return "Send";
case kDeleteAtMethod:
return "DeleteAt";
- case kJumbleMethod:
- return "Jumble";
- case kDeleteFirstMethod:
- return "DeleteFirst";
+ case kInsertAtMethod:
+ return "InsertAt";
+ case kReplaceAtMethod:
+ return "ReplaceAt";
+ case kPrependListMethod:
+ return "PrependList";
+ case kSortMethod:
+ return "Sort";
case kOpenLensMethod:
return "OpenLens";
case kCloseLensMethod:
diff --git a/engines/mediastation/mediascript/scriptconstants.h b/engines/mediastation/mediascript/scriptconstants.h
index 7a0b94f0d40..edd8d86ce63 100644
--- a/engines/mediastation/mediascript/scriptconstants.h
+++ b/engines/mediastation/mediascript/scriptconstants.h
@@ -147,22 +147,23 @@ enum BuiltInMethod {
kSetMaximumTextLengthMethod = 293, // PARAM: 1
// COLLECTION METHODS.
- // These aren't assets but arrays used in Media Script.
- kIsEmptyMethod = 254, // PARAMS: 0
- kEmptyMethod = 252, // PARAMS: 0
+ // These are arrays used in Media Script.
kAppendMethod = 247, // PARAMS: 1+
- kGetAtMethod = 253, // PARAMS: 1
+ kApplyMethod = 248, // PARAMS: 1+
kCountMethod = 249, // PARAMS: 0
- // Looks like this lets you call a method on all the items in a collection.
- // Examples look like : var_7be1_collect_shapes.send(spatialHide);
- kSendMethod = 257, // PARAMS: 1+. Looks like the first param is the function,
- // Seeking seems to be finding the index where a certain item is.
- // and the next params are any arguments you want to send.
+ kDeleteFirstMethod = 250, // PARAMS: 0
+ kDeleteLastMethod = 251, // PARAMS: 0
+ kEmptyMethod = 252, // PARAMS: 0
+ kGetAtMethod = 253, // PARAMS: 1
+ kIsEmptyMethod = 254, // PARAMS: 0
+ kJumbleMethod = 255, // PARAMS: 0
kSeekMethod = 256, // PARAMS: 1
- kSortMethod = 266, // PARAMS: 0
+ kSendMethod = 257, // PARAMS: 1+
kDeleteAtMethod = 258, // PARAMS: 1
- kJumbleMethod = 255, // PARAMS: 0
- kDeleteFirstMethod = 250, // PARAMS: 0
+ kInsertAtMethod = 259, // PARAMS: 2
+ kReplaceAtMethod = 260, // PARAMS: 2
+ kPrependListMethod = 261, // PARAMS: 1+
+ kSortMethod = 266, // PARAMS: 0
// PRINTER METHODS.
kOpenLensMethod = 346, // PARAMS: 0
diff --git a/engines/mediastation/mediascript/scriptvalue.cpp b/engines/mediastation/mediascript/scriptvalue.cpp
index d7ff04710b4..bbfcef64734 100644
--- a/engines/mediastation/mediascript/scriptvalue.cpp
+++ b/engines/mediastation/mediascript/scriptvalue.cpp
@@ -99,6 +99,14 @@ ScriptValue::ScriptValue(ParameterReadStream *stream) {
}
}
+void ScriptValue::setToFloat(uint i) {
+ setToFloat(static_cast<double>(i));
+}
+
+void ScriptValue::setToFloat(int i) {
+ setToFloat(static_cast<double>(i));
+}
+
void ScriptValue::setToFloat(double d) {
_type = kScriptValueTypeFloat;
_u.d = d;
diff --git a/engines/mediastation/mediascript/scriptvalue.h b/engines/mediastation/mediascript/scriptvalue.h
index 75c70f6368c..9d7b7ae1485 100644
--- a/engines/mediastation/mediascript/scriptvalue.h
+++ b/engines/mediastation/mediascript/scriptvalue.h
@@ -40,8 +40,11 @@ public:
ScriptValueType getType() const { return _type; }
+ void setToFloat(uint i);
+ void setToFloat(int i);
void setToFloat(double d);
double asFloat() const;
+ int asIntFromFloat() const;
void setToBool(bool b);
bool asBool() const;
Commit: a5c12ca646c6ee7ebbeffe336c062557e2ab664d
https://github.com/scummvm/scummvm/commit/a5c12ca646c6ee7ebbeffe336c062557e2ab664d
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-05-10T17:25:03-04:00
Commit Message:
MEDIASTATION: Make the screen asset actually an asset
Changed paths:
engines/mediastation/context.cpp
engines/mediastation/context.h
engines/mediastation/mediastation.cpp
diff --git a/engines/mediastation/context.cpp b/engines/mediastation/context.cpp
index b21843b1202..4857e95593d 100644
--- a/engines/mediastation/context.cpp
+++ b/engines/mediastation/context.cpp
@@ -363,7 +363,7 @@ bool Context::readHeaderSection(Subfile &subfile, Chunk &chunk) {
case kAssetTypeScreen:
asset = new Screen(header);
- _screenAsset = header;
+ _screenAsset = asset;
break;
case kAssetTypeFont:
diff --git a/engines/mediastation/context.h b/engines/mediastation/context.h
index 649baa8e831..a7ed7e62853 100644
--- a/engines/mediastation/context.h
+++ b/engines/mediastation/context.h
@@ -62,9 +62,7 @@ public:
uint32 _subfileCount;
uint32 _fileSize;
Graphics::Palette *_palette = nullptr;
- // TODO: Eliminate this screenAsset because the screen that this context
- // represents is now an asset in itself.
- AssetHeader *_screenAsset = nullptr;
+ Asset *_screenAsset = nullptr;
Asset *getAssetById(uint assetId);
Asset *getAssetByChunkReference(uint chunkReference);
diff --git a/engines/mediastation/mediastation.cpp b/engines/mediastation/mediastation.cpp
index aebaa7b6355..47c5cffb6f4 100644
--- a/engines/mediastation/mediastation.cpp
+++ b/engines/mediastation/mediastation.cpp
@@ -279,7 +279,7 @@ void MediaStationEngine::refreshActiveHotspot() {
hotspot->runEventHandlerIfExists(kMouseEnteredEvent);
} else {
// There is no hotspot, so set the default cursor for this screen instead.
- setCursor(_currentContext->_screenAsset->_cursorResourceId);
+ setCursor(_currentContext->_screenAsset->getHeader()->_cursorResourceId);
}
}
@@ -417,15 +417,8 @@ ScriptValue MediaStationEngine::callMethod(BuiltInMethod methodId, Common::Array
void MediaStationEngine::doBranchToScreen() {
if (_currentContext != nullptr) {
- EventHandler *exitEvent = _currentContext->_screenAsset->_eventHandlers.getValOrDefault(kExitEvent);
- if (exitEvent != nullptr) {
- debugC(5, kDebugScript, "Executing context exit event handler");
- exitEvent->execute(_currentContext->_screenAsset->_id);
- } else {
- debugC(5, kDebugScript, "No context exit event handler");
- }
-
- releaseContext(_currentContext->_screenAsset->_id);
+ _currentContext->_screenAsset->runEventHandlerIfExists(kExitEvent);
+ releaseContext(_currentContext->_screenAsset->getHeader()->_id);
}
Context *context = loadContext(_requestedScreenBranchId);
@@ -434,15 +427,7 @@ void MediaStationEngine::doBranchToScreen() {
_currentHotspot = nullptr;
if (context->_screenAsset != nullptr) {
- // TODO: Make the screen an asset just like everything else so we can
- // run event handlers with runEventHandlerIfExists.
- EventHandler *entryEvent = context->_screenAsset->_eventHandlers.getValOrDefault(MediaStation::kEntryEvent);
- if (entryEvent != nullptr) {
- debugC(5, kDebugScript, "Executing context entry event handler");
- entryEvent->execute(context->_screenAsset->_id);
- } else {
- debugC(5, kDebugScript, "No context entry event handler");
- }
+ context->_screenAsset->runEventHandlerIfExists(kEntryEvent);
}
_requestedScreenBranchId = 0;
Commit: 06e1446d5e76bd394ea0c6e5bd35cab10c7e06fa
https://github.com/scummvm/scummvm/commit/06e1446d5e76bd394ea0c6e5bd35cab10c7e06fa
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2025-05-10T17:25:03-04:00
Commit Message:
MEDIASTATION: Use one hashmap for event handlers
Changed paths:
engines/mediastation/asset.cpp
engines/mediastation/asset.h
engines/mediastation/assetheader.cpp
engines/mediastation/assetheader.h
engines/mediastation/assets/sprite.cpp
engines/mediastation/assets/timer.cpp
engines/mediastation/mediascript/eventhandler.h
engines/mediastation/mediastation.cpp
diff --git a/engines/mediastation/asset.cpp b/engines/mediastation/asset.cpp
index a08f0a3d96e..24cb7a0e2e4 100644
--- a/engines/mediastation/asset.cpp
+++ b/engines/mediastation/asset.cpp
@@ -71,7 +71,8 @@ void Asset::processTimeEventHandlers() {
// TODO: Replace with a queue.
uint currentTime = g_system->getMillis();
- for (EventHandler *timeEvent : _header->_timeHandlers) {
+ const Common::Array<EventHandler *> &_timeHandlers = _header->_eventHandlers.getValOrDefault(kTimerEvent);
+ for (EventHandler *timeEvent : _timeHandlers) {
// Indeed float, not time.
double timeEventInFractionalSeconds = timeEvent->_argumentValue.asFloat();
uint timeEventInMilliseconds = timeEventInFractionalSeconds * 1000;
@@ -85,24 +86,29 @@ void Asset::processTimeEventHandlers() {
_lastProcessedTime = currentTime - _startTime;
}
-void Asset::runEventHandlerIfExists(EventType eventType) {
- EventHandler *eventHandler = _header->_eventHandlers.getValOrDefault(eventType);
- if (eventHandler != nullptr) {
- debugC(5, kDebugScript, "Executing handler for event type %s on asset %d", eventTypeToStr(eventType), _header->_id);
- eventHandler->execute(_header->_id);
- } else {
- debugC(5, kDebugScript, "No event handler for event type %s on asset %d", eventTypeToStr(eventType), _header->_id);
+void Asset::runEventHandlerIfExists(EventType eventType, const ScriptValue &arg) {
+ const Common::Array<EventHandler *> &_eventHandlers = _header->_eventHandlers.getValOrDefault(eventType);
+ for (EventHandler *eventHandler : _eventHandlers) {
+ const ScriptValue &argToCheck = eventHandler->_argumentValue;
+
+ if (arg.getType() != argToCheck.getType()) {
+ warning("Got event handler arg type %s, expected %s",
+ scriptValueTypeToStr(arg.getType()), scriptValueTypeToStr(argToCheck.getType()));
+ continue;
+ }
+
+ if (arg == argToCheck) {
+ debugC(5, kDebugScript, "Executing handler for event type %s on asset %d", eventTypeToStr(eventType), _header->_id);
+ eventHandler->execute(_header->_id);
+ return;
+ }
}
+ debugC(5, kDebugScript, "No event handler for event type %s on asset %d", eventTypeToStr(eventType), _header->_id);
}
-void Asset::runKeyDownEventHandlerIfExists(Common::KeyState keyState) {
- EventHandler *keyDownEvent = _header->_keyDownHandlers.getValOrDefault(keyState.ascii);
- if (keyDownEvent != nullptr) {
- debugC(5, kDebugScript, "Executing keydown event handler for ASCII code %d on asset %d", keyState.ascii, _header->_id);
- keyDownEvent->execute(_header->_id);
- } else {
- debugC(5, kDebugScript, "No keydown event handler for ASCII code %d on asset %d", keyState.ascii, _header->_id);
- }
+void Asset::runEventHandlerIfExists(EventType eventType) {
+ ScriptValue scriptValue;
+ runEventHandlerIfExists(eventType, scriptValue);
}
} // End of namespace MediaStation
diff --git a/engines/mediastation/asset.h b/engines/mediastation/asset.h
index 9d84f597ecb..98e63689450 100644
--- a/engines/mediastation/asset.h
+++ b/engines/mediastation/asset.h
@@ -66,8 +66,8 @@ public:
void setInactive();
void setActive();
void processTimeEventHandlers();
+ void runEventHandlerIfExists(EventType eventType, const ScriptValue &arg);
void runEventHandlerIfExists(EventType eventType);
- void runKeyDownEventHandlerIfExists(Common::KeyState keyState);
AssetType type() const;
int zIndex() const;
diff --git a/engines/mediastation/assetheader.cpp b/engines/mediastation/assetheader.cpp
index 6e9d8f87185..8e741d44d41 100644
--- a/engines/mediastation/assetheader.cpp
+++ b/engines/mediastation/assetheader.cpp
@@ -41,30 +41,12 @@ AssetHeader::AssetHeader(Chunk &chunk) {
AssetHeader::~AssetHeader() {
for (auto it = _eventHandlers.begin(); it != _eventHandlers.end(); ++it) {
- delete it->_value;
+ for (EventHandler *eventHandler : it->_value) {
+ delete eventHandler;
+ }
}
_eventHandlers.clear();
- for (EventHandler *timeHandler : _timeHandlers) {
- delete timeHandler;
- }
- _timeHandlers.clear();
-
- for (auto it = _keyDownHandlers.begin(); it != _keyDownHandlers.end(); ++it) {
- delete it->_value;
- }
- _keyDownHandlers.clear();
-
- for (EventHandler *inputHandler : _inputHandlers) {
- delete inputHandler;
- }
- _inputHandlers.clear();
-
- for (EventHandler *loadCompleteHandler : _loadCompleteHandlers) {
- delete loadCompleteHandler;
- }
- _loadCompleteHandlers.clear();
-
delete _palette;
_palette = nullptr;
}
@@ -78,46 +60,16 @@ void AssetHeader::readSection(AssetHeaderSectionType sectionType, Chunk& chunk)
case kAssetHeaderEventHandler: {
EventHandler *eventHandler = new EventHandler(chunk);
- switch (eventHandler->_type) {
- case kTimerEvent: {
- _timeHandlers.push_back(eventHandler);
- break;
- }
+ Common::Array<EventHandler *> &eventHandlersForType = _eventHandlers.getOrCreateVal(eventHandler->_type);
- case kKeyDownEvent: {
- if (eventHandler->_argumentValue.getType() != kScriptValueTypeFloat) {
- error("Keydown event handler doesn't have correct argument type");
+ // This is not a hashmap because we don't want to have to hash ScriptValues.
+ for (EventHandler *existingEventHandler : eventHandlersForType) {
+ if (existingEventHandler->_argumentValue == eventHandler->_argumentValue) {
+ error("AssetHeader::readSection(): Event handler for %s (%s) already exists",
+ eventTypeToStr(eventHandler->_type), eventHandler->getDebugHeader().c_str());
}
- uint asciiCode = static_cast<uint>(eventHandler->_argumentValue.asFloat());
- _keyDownHandlers.setVal(asciiCode, eventHandler);
- break;
- }
-
- case kInputEvent: {
- _inputHandlers.push_back(eventHandler);
- break;
- }
-
- case kLoadCompleteEvent: {
- _loadCompleteHandlers.push_back(eventHandler);
- break;
- }
-
- default: {
- if (eventHandler->_argumentValue.getType() != kScriptValueTypeEmpty && \
- eventHandler->_argumentValue.getType() != kScriptValueTypeParamToken) {
- error("AssetHeader::readSection(): Event handler of type %s has a non-null argument type %s",
- eventTypeToStr(eventHandler->_type), scriptValueTypeToStr(eventHandler->_argumentValue.getType()));
- }
-
- if (_eventHandlers.contains(eventHandler->_type)) {
- error("AssetHeader::readSection(): Event handler type %s already exists", eventTypeToStr(eventHandler->_type));
- } else {
- _eventHandlers.setVal(eventHandler->_type, eventHandler);
- }
- break;
- }
}
+ eventHandlersForType.push_back(eventHandler);
break;
}
diff --git a/engines/mediastation/assetheader.h b/engines/mediastation/assetheader.h
index 958f4d8d27f..af077b20a30 100644
--- a/engines/mediastation/assetheader.h
+++ b/engines/mediastation/assetheader.h
@@ -203,11 +203,7 @@ public:
uint _totalSteps = 0;
// EVENT HANDLER FIELDS.
- Common::HashMap<uint, EventHandler *> _eventHandlers;
- Common::Array<EventHandler *> _timeHandlers;
- Common::HashMap<uint, EventHandler *> _keyDownHandlers;
- Common::Array<EventHandler *> _inputHandlers;
- Common::Array<EventHandler *> _loadCompleteHandlers;
+ Common::HashMap<uint, Common::Array<EventHandler *>> _eventHandlers;
// TEXT FIELDS.
Common::String _text;
diff --git a/engines/mediastation/assets/sprite.cpp b/engines/mediastation/assets/sprite.cpp
index 9d6cd5530c7..ec2b9dd652e 100644
--- a/engines/mediastation/assets/sprite.cpp
+++ b/engines/mediastation/assets/sprite.cpp
@@ -306,7 +306,10 @@ void Sprite::updateFrameState() {
_currentFrameIndex = 0;
_nextFrameTime = 0;
- runEventHandlerIfExists(kSpriteMovieEndEvent);
+ ScriptValue defaultSpriteClip;
+ const uint DEFAULT_SPRITE_CLIP_ID = 1200;
+ defaultSpriteClip.setToParamToken(DEFAULT_SPRITE_CLIP_ID);
+ runEventHandlerIfExists(kSpriteMovieEndEvent, defaultSpriteClip);
}
}
diff --git a/engines/mediastation/assets/timer.cpp b/engines/mediastation/assets/timer.cpp
index 5f04ad08e01..38a9c0debc2 100644
--- a/engines/mediastation/assets/timer.cpp
+++ b/engines/mediastation/assets/timer.cpp
@@ -68,7 +68,8 @@ void Timer::timePlay() {
// TODO: Is there a better way to find out what the max time is? Do we have to look
// through each of the timer event handlers to figure it out?
_duration = 0;
- for (EventHandler *timeEvent : _header->_timeHandlers) {
+ const Common::Array<EventHandler *> &_timeHandlers = _header->_eventHandlers.getValOrDefault(kTimerEvent);
+ for (EventHandler *timeEvent : _timeHandlers) {
// Indeed float, not time.
double timeEventInFractionalSeconds = timeEvent->_argumentValue.asFloat();
uint timeEventInMilliseconds = timeEventInFractionalSeconds * 1000;
diff --git a/engines/mediastation/mediascript/eventhandler.h b/engines/mediastation/mediascript/eventhandler.h
index 00a6c352f4c..843a008e790 100644
--- a/engines/mediastation/mediascript/eventhandler.h
+++ b/engines/mediastation/mediascript/eventhandler.h
@@ -36,12 +36,11 @@ public:
~EventHandler();
ScriptValue execute(uint assetId);
+ Common::String getDebugHeader();
EventType _type;
ScriptValue _argumentValue;
private:
- Common::String getDebugHeader();
-
CodeChunk *_code = nullptr;
};
diff --git a/engines/mediastation/mediastation.cpp b/engines/mediastation/mediastation.cpp
index 47c5cffb6f4..5bfe0511b8f 100644
--- a/engines/mediastation/mediastation.cpp
+++ b/engines/mediastation/mediastation.cpp
@@ -227,7 +227,9 @@ void MediaStationEngine::processEvents() {
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);
+ ScriptValue keyCode;
+ keyCode.setToFloat(_event.kbd.ascii);
+ hotspot->runEventHandlerIfExists(kKeyDownEvent, keyCode);
}
break;
}
More information about the Scummvm-git-logs
mailing list