[Scummvm-git-logs] scummvm master -> a9432dcce69bdf414a9e5ff53f730b8b391f6228
sev-
noreply at scummvm.org
Mon Jul 7 09:42:22 UTC 2025
This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
283e0ad643 DIRECTOR: Write cast config chunk to file
70c02643dc DIRECTOR: Save CASt resources as it is (default)
28bcf5cf14 DIRECTOR: Write CASt and CLUT resources in PaletteCastMember
593191968f DIRECTOR: Write Cast Config and CASt Resources
080edb9cbd DIRECTOR: Write TextCastMember 'STXT' resource
dc9f94b541 DIRECTOR: Move writeCAStResource() to base class CastMember
c49b627c2d DIRECTOR: saveInfoEntries(), helper dumpFile() and kDebugSaving
96d3dbc710 DIRECTOR: Write 'CASt' resources for all Cast Members
83534578a9 DIRECTOR: Minor adjustments in writing 'CASt' Resources
85c7db7a60 DIRECTOR: Fix chechsum calculation mistake
a9432dcce6 DIRECTOR: Minor Formatting Changes
Commit: 283e0ad643938067f7e27c0ed8036f7a7e878e1e
https://github.com/scummvm/scummvm/commit/283e0ad643938067f7e27c0ed8036f7a7e878e1e
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Write cast config chunk to file
Remove the chunk.h file
There is no apparent reason to store the config chunk data into
a separate struct. Directly store the data in the Cast class and
save it from there.
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/movie.cpp
engines/director/movie.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 1ab1822b5f9..8f2fc653386 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -318,20 +318,21 @@ bool Cast::loadConfig() {
if (stream->size() > 36) {
stream->seek(36); // Seek to version
_version = stream->readSint16(); // Read version for post-D3
+ _directorVersion = _version;
stream->seek(0); // Seek to start of stream
}
- uint16 len = stream->readUint16();
- uint16 fileVersion = stream->readUint16(); // TODO: very high fileVersion means protected
+ _len = stream->readUint16();
+ _fileVersion = stream->readUint16(); // TODO: very high fileVersion means protected
if (stream->size() <= 36)
- _version = fileVersion; // Checking if we have already read the version
+ _version = _fileVersion; // Checking if we have already read the version
uint humanVer = humanVersion(_version);
- Common::Rect checkRect = Movie::readRect(*stream);
+ _checkRect = Movie::readRect(*stream);
if (!g_director->_fixStageSize)
- _movieRect = checkRect;
+ _movieRect = _checkRect;
else
_movieRect = g_director->_fixStageRect;
@@ -341,11 +342,11 @@ bool Cast::loadConfig() {
// D3 and below use this, override for D4 and over
// actual framerates are, on average: { 3.75, 4, 4.35, 4.65, 5, 5.5, 6, 6.6, 7.5, 8.5, 10, 12, 20, 30, 60 }
Common::Array<int> frameRates = { 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 10, 12, 15, 20, 30, 60 };
- byte readRate = stream->readByte();
- if (readRate <= 0xF) {
- _frameRate = frameRates[readRate];
+ _readRate = stream->readByte();
+ if (_readRate <= 0xF) {
+ _frameRate = frameRates[_readRate];
} else {
- switch (readRate) {
+ switch (_readRate) {
// rate when set via the tempo channel
// these rates are the actual framerates
case 0x10:
@@ -362,29 +363,30 @@ bool Cast::loadConfig() {
_frameRate = 3;
break;
default:
- warning("BUILDBOT: Cast::loadConfig: unhandled framerate: %i", readRate);
- _frameRate = readRate;
+ warning("BUILDBOT: Cast::loadConfig: unhandled framerate: %i", _readRate);
+ _frameRate = _readRate;
}
}
- byte lightswitch = stream->readByte();
- int16 unk1 = stream->readSint16();
+ _lightswitch = stream->readByte();
+
+ _unk1 = stream->readSint16();
// Warning for post-D7 movies (unk1 is stageColorG and stageColorB post-D7)
if (humanVer >= 700)
- warning("STUB: Cast::loadConfig: 16 bit unk1 read instead of two 8 bit stageColorG and stageColorB. Read value: %04x", unk1);
+ warning("STUB: Cast::loadConfig: 16 bit unk1 read instead of two 8 bit stageColorG and stageColorB. Read value: %04x", _unk1);
- uint16 commentFont = stream->readUint16();
- uint16 commentSize = stream->readUint16();
- uint16 commentStyle = stream->readUint16();
+ _commentFont = stream->readUint16();
+ _commentSize = stream->readUint16();
+ _commentStyle = stream->readUint16();
_stageColor = stream->readUint16();
// Warning for post-D7 movies (stageColor is isStageColorRGB and stageColorR post-D7)
if (humanVer >= 700)
warning("STUB: Cast::loadConfig: 16 bit stageColor read instead of two 8 bit isStageColorRGB and stageColorR. Read value: %04x", _stageColor);
- uint16 bitdepth = stream->readUint16();
+ _bitdepth = stream->readUint16();
// byte color = stream.readByte(); // boolean, color = 1, B/W = 0
// uint16 stageColorR = stream.readUint16();
@@ -392,73 +394,69 @@ bool Cast::loadConfig() {
// uint16 stageColorB = stream.readUint16();
debugC(1, kDebugLoading, "Cast::loadConfig(): len: %d, fileVersion: %d, light: %d, unk: %d, font: %d, size: %d"
- ", style: %d", len, fileVersion, lightswitch, unk1, commentFont, commentSize, commentStyle);
+ ", style: %d", _len, _fileVersion, _lightswitch, _unk1, _commentFont, _commentSize, _commentStyle);
debugC(1, kDebugLoading, "Cast::loadConfig(): stagecolor: %d, depth: %d",
- _stageColor, bitdepth);
+ _stageColor, _bitdepth);
if (debugChannelSet(1, kDebugLoading))
_movieRect.debugPrint(1, "Cast::loadConfig(): Movie rect: ");
// Fields required for checksum calculation
- uint8 field17 = 0, field18 = 0;
- int16 field21 = 0;
- int32 field19 = 0, field22 = 0, field23 = 0;
-
// D3 fields - Macromedia did not increment the fileVersion from D2 to D3
// so we just have to check if there are more bytes to read.
if (stream->pos() < stream->size()) {
//reading these fields for the sake of checksum calculation
- field17 = stream->readByte();
- field18 = stream->readByte();
- field19 = stream->readSint32();
+ _field17 = stream->readByte();
+ _field18 = stream->readByte();
+ _field19 = stream->readSint32();
- /* _version = */ stream->readUint16();
+ _directorVersion = stream->readUint16();
- field21 = stream->readSint16();
- field22 = stream->readSint32();
- field23 = stream->readSint32();
+ _field21 = stream->readSint16();
+ _field22 = stream->readSint32();
+ _field23 = stream->readSint32();
}
debugC(1, kDebugLoading, "Cast::loadConfig(): directorVersion: %d", humanVer);
if (_version >= kFileVer400) {
- int32 field24 = stream->readSint32();
- int8 field25 = stream->readSByte();
- /* int8 field26 = */ stream->readSByte();
+ _field24 = stream->readSint32();
+ _field25 = stream->readSByte();
+ _field26 = stream->readSByte();
_frameRate = stream->readSint16();
- uint16 platform = stream->readUint16();
- _platform = platformFromID(platform);
+ _platformID = stream->readUint16();
+ _platform = platformFromID(_platformID);
- int16 protection = stream->readSint16();
- _isProtected = (protection % 23) == 0;
- /* int32 field29 = */ stream->readSint32();
- uint32 checksum = stream->readUint32();
+ _protection = stream->readSint16();
+ _isProtected = (_protection % 23) == 0;
+ _field29 = stream->readSint32();
+ _checksum = stream->readUint32();
//Calculation and verification of checksum
- uint32 check = len + 1;
- check *= fileVersion + 2;
- check /= checkRect.top + 3;
- check *= checkRect.left + 4;
- check /= checkRect.bottom + 5;
- check *= checkRect.right + 6;
+ uint32 check = _len + 1;
+ check *= _fileVersion + 2;
+ check /= _checkRect.top + 3;
+ check *= _checkRect.left + 4;
+ check /= _checkRect.bottom + 5;
+ check *= _checkRect.right + 6;
check -= _castArrayStart + 7;
check *= _castArrayEnd + 8;
- check -= (int8)readRate + 9;
- check -= lightswitch + 10;
+ check -= (int8)_readRate + 9;
+ check -= _lightswitch + 10;
if (humanVer < 700)
- check += unk1 + 11;
+ check += _unk1 + 11;
else
warning("STUB: skipped using stageColorG, stageColorB for post-D7 movie in checksum calulation");
- check *= commentFont + 12;
- check += commentSize + 13;
+ check *= _commentFont + 12;
+ check += _commentSize + 13;
if (humanVer < 800)
- check *= (uint8)((commentStyle >> 8) & 0xFF) + 14;
+ check *= (uint8)((_commentStyle >> 8) & 0xFF) + 14;
else
- check *= commentStyle + 14;
+ check *= _commentStyle + 14;
if (humanVer < 700)
check += _stageColor + 15;
@@ -466,26 +464,26 @@ bool Cast::loadConfig() {
check += (uint8)(_stageColor & 0xFF) + 15; // Taking lower 8 bits to take into account stageColorR
- check += bitdepth + 16;
- check += field17 + 17;
- check *= field18 + 18;
- check += field19 + 19;
+ check += _bitdepth + 16;
+ check += _field17 + 17;
+ check *= _field18 + 18;
+ check += _field19 + 19;
check *= _version + 20;
- check += field21 + 21;
- check += field22 + 22;
- check += field23 + 23;
- check += field24 + 24;
- check *= field25 + 25;
+ check += _field21 + 21;
+ check += _field22 + 22;
+ check += _field23 + 23;
+ check += _field24 + 24;
+ check *= _field25 + 25;
check += _frameRate + 26;
- check *= platform + 27;
- check *= (protection * 0xE06) + 0xFF450000u;
+ check *= _platform + 27;
+ check *= (_protection * 0xE06) + 0xFF450000u;
check ^= MKTAG('r', 'a', 'l', 'f');
- if (check != checksum)
- warning("BUILDBOT: The checksum for this VWCF resource is incorrect. Got %04x, but expected %04x", check, checksum);
+ if (check != _checksum)
+ warning("BUILDBOT: The checksum for this VWCF resource is incorrect. Got %04x, but expected %04x", check, _checksum);
if (_version >= kFileVer400 && _version < kFileVer500) {
- /* int16 field30 = */ stream->readSint16();
+ _field30 = stream->readSint16();
_defaultPalette.member = stream->readSint16();
// In this header value, the first builtin palette starts at 0 and
@@ -496,7 +494,7 @@ bool Cast::loadConfig() {
_defaultPalette.member -= 1;
else
_defaultPalette.castLib = DEFAULT_CAST_LIB;
- for (int i = 0; i < 0x08; i++) {
+ for (int i = 0; i < 0x08; i++){
stream->readByte();
}
} else if (_version >= kFileVer500 && _version < kFileVer600) {
@@ -524,6 +522,75 @@ bool Cast::loadConfig() {
return true;
}
+void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
+ if (_version < kFileVer400) {
+ error("Cast::saveConfig called on a pre-D4 Director movie");
+ }
+
+ writeStream->seek(offset); // This will allow us to write cast config at any offset
+ // These offsets are only for Director Version 4 to Director version 6
+ // offsets
+ writeStream->writeUint16LE(_len); // 0
+ writeStream->writeUint16LE(_fileVersion); // 2
+
+ Movie::writeRect(writeStream, _checkRect); // 4, 6, 8, 10
+
+ writeStream->writeUint16LE(_castArrayStart); // 12
+ writeStream->writeUint16LE(_castArrayEnd); // 14
+
+ writeStream->writeByte(_readRate); // 16
+ writeStream->writeByte(_lightswitch); // 17
+ writeStream->writeSint16LE(_unk1); // 18
+
+ writeStream->writeUint16LE(_commentFont); // 20
+ writeStream->writeUint16LE(_commentSize); // 22
+ writeStream->writeUint16LE(_commentStyle); // 24
+ writeStream->writeUint16LE(_stageColor); // 26
+
+ writeStream->writeUint16LE(_bitdepth); // 28
+
+ writeStream->writeByte(_field17); // 29
+ writeStream->writeByte(_field18); // 30
+ writeStream->writeSint32LE(_field19); // 34
+
+ writeStream->writeUint16LE(_directorVersion); // 36
+
+ writeStream->writeUint16LE(_field21); // 38
+ writeStream->writeUint32LE(_field22); // 40
+ writeStream->writeUint32LE(_field23); // 44
+
+ writeStream->writeSint32LE(_field24); // 48
+ writeStream->writeSByte(_field25); // 52
+ writeStream->writeSByte(_field26); // 53
+
+ writeStream->writeSint16LE(_frameRate); // 54
+ writeStream->writeUint16LE(_platform); // 56
+ writeStream->writeSint16LE(_protection); // 58
+ writeStream->writeSint32LE(_field29); // 60
+
+ // Currently a stub
+ uint32 checksum = computeChecksum();
+ writeStream->writeUint32LE(checksum); // 64
+
+ if (_version >= kFileVer400 && _version < kFileVer500) {
+ writeStream->writeSint16LE(_field30); // 68
+
+ // This loop isn't writing meaningful data currently
+ // But it is possible that this data might be needed
+ for (int i = 0; i < 0x08; i++) {
+ writeStream->writeByte(0); // 70, 71, 72, 73, 74, 75, 76, 77
+ }
+ } else if (_version >= kFileVer500 && _version < kFileVer600) {
+ for (int i = 0; i < 0x08; i++) {
+ writeStream->writeByte(0); // 68, 69, 70, 71, 72, 73, 74, 75
+ }
+
+ writeStream->writeSint16LE(_defaultPalette.castLib); // 76
+ writeStream->writeSint16LE(_defaultPalette.member); // 77
+ }
+
+}
+
void Cast::loadCast() {
Common::SeekableReadStreamEndian *r = nullptr;
@@ -714,6 +781,15 @@ void Cast::loadCast() {
}
+void Cast::saveCast(Common::MemoryWriteStream *writeStream, uint32 offset) {
+
+}
+
+uint32 Cast::computeChecksum() {
+ warning("STUB::ConfigChunk::computeChecksum() is not implemented yet");
+ return 0;
+}
+
Common::String Cast::getLinkedPath(int castId) {
if (!_castsInfo.contains(castId))
return Common::String();
diff --git a/engines/director/cast.h b/engines/director/cast.h
index f4a80f2b123..2a96b597f3d 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -26,6 +26,7 @@
namespace Common {
class ReadStreamEndian;
+ class MemoryWriteStream;
struct Rect;
class SeekableReadStreamEndian;
}
@@ -55,6 +56,7 @@ class ShapeCastMember;
class TextCastMember;
class PaletteCastMember;
class SoundCastMember;
+struct ConfigChunk;
typedef Common::HashMap<byte, byte> CharMap;
typedef Common::HashMap<uint16, uint16> FontSizeMap;
@@ -104,6 +106,9 @@ public:
void loadExternalSound(Common::SeekableReadStreamEndian &stream);
void loadSord(Common::SeekableReadStreamEndian &stream);
+ void saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset);
+ void saveCast(Common::MemoryWriteStream *writeStream, uint32 offset);
+
int getCastSize();
int getCastMaxID();
int getNextUnusedID();
@@ -142,6 +147,8 @@ private:
bool readFXmpLine(Common::SeekableReadStreamEndian &stream);
void loadVWTL(Common::SeekableReadStreamEndian &stream);
+ uint32 computeChecksum();
+
public:
Archive *_castArchive;
uint16 _version;
@@ -163,19 +170,61 @@ public:
Common::HashMap<uint, const RTE1 *> _loadedRTE1s;
Common::HashMap<uint, const RTE2 *> _loadedRTE2s;
uint16 _castIDoffset;
- uint16 _castArrayStart;
- uint16 _castArrayEnd;
Common::Rect _movieRect;
- uint16 _stageColor;
CastMemberID _defaultPalette;
- int16 _frameRate;
TilePatternEntry _tiles[kNumBuiltinTiles];
LingoArchive *_lingoArchive;
LingoDec::ScriptContext *_lingodec = nullptr;
LingoDec::ChunkResolver *_chunkResolver = nullptr;
+
+ /* Data to be saved */
+ /* 0 */ uint16 _len;
+ /* 2 */ uint16 _fileVersion;
+ /* 4, 6, 8, 10 */ Common::Rect _checkRect;
+ /* 12 */ uint16 _castArrayStart;
+ /* 14 */ uint16 _castArrayEnd;
+ /* 16 */ byte _readRate;
+ /* 17 */ byte _lightswitch;
+
+ // Director 6 and below
+ /* 18 */ int16 _unk1; // Mentioned in ProjectorRays as preD7field11
+
+ // Director 7 and above
+ // Currently not supporting Director 7
+ // /* 18 */ int8 D7stageColorG;
+ // /* 19 */ int8 D7stageColorB;
+
+ /* 20 */ uint16 _commentFont;
+ /* 22 */ uint16 _commentSize;
+ /* 24 */ uint16 _commentStyle;
+
+ // Director 6 and below
+ /* 26 */ uint16 _stageColor;
+ // Director 7 and above
+ // Currently not supporting Director 7
+ // /* 26 */ uint8 D7stageColorIsRGB;
+ // /* 27 */ uint8 D7stageColorR;
+
+ /* 28 */ uint16 _bitdepth;
+ /* 30 */ uint8 _field17;
+ /* 31 */ uint8 _field18;
+ /* 32 */ int32 _field19;
+ /* 36 */ int16 _directorVersion;
+ /* 38 */ int16 _field21;
+ /* 40 */ int32 _field22;
+ /* 44 */ int32 _field23;
+ /* 48 */ int32 _field24;
+ /* 52 */ int8 _field25;
+ /* 53 */ uint8 _field26;
+ /* 54 */ int16 _frameRate;
+ /* 56 */ int16 _platformID;
+ /* 58 */ int16 _protection;
+ /* 60 */ int32 _field29;
+ /* 64 */ uint32 _checksum;
+ /* 68 */ uint16 _field30; // Marked as remnants in ProjectorRays
private:
DirectorEngine *_vm;
@@ -192,6 +241,7 @@ private:
Common::HashMap<uint16, CastMemberInfo *> _castsInfo;
Common::HashMap<Common::String, int, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _castsNames;
Common::HashMap<uint16, int> _castsScriptIds;
+
};
} // End of namespace Director
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 048b04f5974..45b50f5c6d1 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -284,6 +284,13 @@ Common::Rect Movie::readRect(Common::ReadStreamEndian &stream) {
return rect;
}
+void Movie::writeRect(Common::MemoryWriteStream *writeStream, Common::Rect rect) {
+ writeStream->writeSint16LE(rect.top);
+ writeStream->writeSint16LE(rect.left);
+ writeStream->writeSint16LE(rect.bottom);
+ writeStream->writeSint16LE(rect.right);
+}
+
InfoEntries Movie::loadInfoEntries(Common::SeekableReadStreamEndian &stream, uint16 version) {
uint32 offset = stream.pos();
offset += stream.readUint32();
diff --git a/engines/director/movie.h b/engines/director/movie.h
index ab1c961fd48..8b23aa995cb 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -29,6 +29,7 @@ namespace Common {
struct Event;
class ReadStreamEndian;
class SeekableReadStreamEndian;
+class MemoryWriteStream;
}
namespace Director {
@@ -91,6 +92,8 @@ public:
static Common::Rect readRect(Common::ReadStreamEndian &stream);
static InfoEntries loadInfoEntries(Common::SeekableReadStreamEndian &stream, uint16 version);
+ static void writeRect(Common::MemoryWriteStream *writeStream, Common::Rect rect);
+
void loadCastLibMapping(Common::SeekableReadStreamEndian &stream);
bool loadArchive();
void setArchive(Archive *archive);
Commit: 70c02643dcfe6b26541cf38a4be5b83045a55c83
https://github.com/scummvm/scummvm/commit/70c02643dcfe6b26541cf38a4be5b83045a55c83
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Save CASt resources as it is (default)
Part of saving Director movies project
Function writeToFile() in the Base class CastMember
While saving cast members as 'CASt' resources if they are unmodified
write them verbatim as the original with recalculated offset
Use this default method for all unchanged castmembers
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 8f2fc653386..c117e4647f0 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -779,10 +779,32 @@ void Cast::loadCast() {
debugC(4, kDebugLoading, "'SCRF' resource skipped");
}
+ saveCast(nullptr, 0);
+
}
void Cast::saveCast(Common::MemoryWriteStream *writeStream, uint32 offset) {
+ // This offset is at which we will start writing our 'CASt' resources
+ // In the original file, all the 'CASt' resources don't necessarily appear side by side
+ // But in our written file they will be
+ writeStream->seek(offset);
+
+ Common::Array<uint16> cast = _castArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't'));
+
+ for (auto &castID : cast) {
+ Resource res = _castArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), castID);
+ uint16 id = res.castId + _castArrayStart;
+ // FIXME: This is wrong, we need to write cast members even if they are not handled/loaded
+ // We are currently ignoring cast members that we do not understand (e.g. kCastPicture)
+ // They need to be handled by the default handler, which will write them as they were
+ if (!_loadedCast->contains(castID)) {
+ continue;
+ }
+
+ CastMember *target = _loadedCast->getVal(id);
+ target->writeToFile(writeStream, offset, _version, castID);
+ }
}
uint32 Cast::computeChecksum() {
@@ -1020,7 +1042,7 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
stream.hexdump(stream.size());
uint32 castDataSize, castInfoSize, castType, castDataSizeToRead, castDataOffset, castInfoOffset;
- byte flags1 = 0, unk1 = 0, unk2 = 0, unk3 = 0;
+ byte flags1 = -1, unk1 = 0, unk2 = 0, unk3 = 0;
// D2-3 cast members should be loaded in loadCastDataVWCR
#if 0
@@ -1060,7 +1082,7 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
error("Cast::loadCastData: unsupported Director version (%d)", _version);
}
- debugC(3, kDebugLoading, "Cast::loadCastData(): CASt: id: %d type: %x castDataSize: %d castInfoSize: %d (%x) unk1: %d unk2: %d unk3: %d",
+ debug("Cast::loadCastData(): CASt: id: %d type: %x castDataSize: %d castInfoSize: %d (%x) unk1: %d unk2: %d unk3: %d",
id, castType, castDataSize, castInfoSize, castInfoSize, unk1, unk2, unk3);
// read the cast member itself
@@ -1135,6 +1157,10 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
break;
}
if (target) {
+ target->_castDataSize = castDataSize;
+ target->_castInfoSize = castInfoSize;
+ target->_castType = castType;
+ target->_flags1 = flags1;
setCastMember(id, target);
}
if (castStream.eos()) {
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 2a96b597f3d..258a51b76f1 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -108,6 +108,7 @@ public:
void saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset);
void saveCast(Common::MemoryWriteStream *writeStream, uint32 offset);
+ void saveCastData();
int getCastSize();
int getCastMaxID();
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 4dbdd345d19..dedd1fcfc9b 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -20,6 +20,10 @@
*/
#include "common/events.h"
+#include "common/substream.h"
+#include "common/macresman.h"
+#include "common/memstream.h"
+
#include "director/director.h"
#include "director/cast.h"
#include "director/castmember/castmember.h"
@@ -303,4 +307,63 @@ void CastMember::unload() {
_loaded = false;
}
+// Default implementation to write the cast members as they are
+void CastMember::writeToFile(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castID) {
+ writeStream->seek(offset);
+ writeStream->writeUint16LE(MKTAG('C', 'A', 'S', 't'));
+
+ uint32 castDataToWrite = getDataSize();
+ uint32 castInfoToWrite = getInfoSize();
+ uint32 castDataOffset = 0;
+ uint32 castInfoOffset = 0;
+ Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), castID);
+
+ if (version >= kFileVer400 && version < kFileVer500) {
+ writeStream->writeUint16LE(castDataToWrite);
+ writeStream->writeUint32LE(castInfoToWrite);
+ castDataOffset += 6;
+
+ writeStream->writeUint32LE(_castType);
+ castDataToWrite -= 1;
+
+ if (_flags1 != -1) {
+ writeStream->writeByte(_flags1);
+ castDataToWrite -= 1;
+ castDataOffset += 1;
+ }
+ } else if (version >= kFileVer500 && version < kFileVer600) {
+ writeStream->writeUint32LE(_castType);
+ writeStream->writeUint32LE(getInfoSize());
+ writeStream->writeUint32LE(getDataSize());
+ }
+
+
+ byte *data = (byte *)calloc(castDataToWrite, 1);
+ byte *info = (byte *)calloc(castInfoToWrite, 1);
+ stream->seek(castDataOffset, SEEK_CUR);
+ stream->read(data, castDataToWrite);
+ stream->read(info, castInfoToWrite);
+
+ Common::MemoryReadStreamEndian *dataStream = new Common::MemoryReadStreamEndian(data, castDataToWrite, stream->isBE());
+ Common::MemoryReadStreamEndian *infoStream = new Common::MemoryReadStreamEndian(info, castInfoToWrite, stream->isBE());
+
+ if (version >= kFileVer400 && version < kFileVer500) {
+ writeStream->writeStream(dataStream);
+ writeStream->writeStream(infoStream);
+ } else if (version >= kFileVer500 && version < kFileVer600) {
+ writeStream->writeStream(infoStream);
+ writeStream->writeStream(dataStream);
+ }
+}
+
+uint32 CastMember::getDataSize() {
+ debug("CastMember::getDataSize(): Defualt implementation of cast member data size, returning original size.");
+ return _castDataSize;
+}
+
+uint32 CastMember::getInfoSize() {
+ debug("CastMember::getInfoSize(): Defualt implementation of cast member info size, returning original size.");
+ return _castInfoSize;
+}
+
} // End of namespace Director
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index 76afa109adf..bd4914064a0 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -36,6 +36,7 @@ class MacWidget;
namespace Common {
class SeekableReadStream;
class SeekableReadStreamEndian;
+class MemoryWriteStream;
}
namespace Director {
@@ -100,6 +101,10 @@ public:
virtual CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) { return bbox.contains(pos) ? kCollisionYes : kCollisionNo; }
+ virtual void writeToFile(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castID);
+ virtual uint32 getDataSize();
+ virtual uint32 getInfoSize();
+
CastType _type;
Common::Rect _initialRect;
Common::Rect _boundingRect;
@@ -109,7 +114,12 @@ public:
bool _erase;
int _purgePriority;
uint32 _size;
- uint8 _flags1;
+
+ /* Data fields used when saving the Cast Member */
+ uint32 _castDataSize;
+ uint32 _castInfoSize;
+ uint32 _castType;
+ byte _flags1;
protected:
Cast *_cast;
Commit: 28bcf5cf145ddafb481d3be7331c041d31b2b8c3
https://github.com/scummvm/scummvm/commit/28bcf5cf145ddafb481d3be7331c041d31b2b8c3
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Write CASt and CLUT resources in PaletteCastMember
Write the Info in the cast resource when writing the CASt resource
Write the Palette data as a CLUT resource
Changed paths:
engines/director/archive.cpp
engines/director/cast.cpp
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
engines/director/castmember/palette.cpp
engines/director/castmember/palette.h
engines/director/stxt.cpp
engines/director/stxt.h
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 7737cefd52c..f014c37bbd2 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -1173,7 +1173,7 @@ bool RIFXArchive::writeToFile(Common::Path path) {
// Don't need to allocate this much size in case 'junk' and 'free' resources are ignored
// Or might need to allocate even more size if extra chunks are written
- dumpData = (byte *)malloc(_size);
+ dumpData = (byte *)calloc(_size, sizeof(byte));
Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, _size);
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index c117e4647f0..76dfba1717d 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -779,31 +779,34 @@ void Cast::loadCast() {
debugC(4, kDebugLoading, "'SCRF' resource skipped");
}
- saveCast(nullptr, 0);
+ // saveCast(nullptr, 0);
}
void Cast::saveCast(Common::MemoryWriteStream *writeStream, uint32 offset) {
// This offset is at which we will start writing our 'CASt' resources
// In the original file, all the 'CASt' resources don't necessarily appear side by side
- // But in our written file they will be
writeStream->seek(offset);
Common::Array<uint16> cast = _castArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't'));
+ uint32 sizeWritten = 0;
- for (auto &castID : cast) {
- Resource res = _castArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), castID);
+ for (auto &it : cast) {
+ writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
+ writeStream->seek(4, SEEK_CUR);
+
+ Resource res = _castArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), it);
uint16 id = res.castId + _castArrayStart;
// FIXME: This is wrong, we need to write cast members even if they are not handled/loaded
// We are currently ignoring cast members that we do not understand (e.g. kCastPicture)
// They need to be handled by the default handler, which will write them as they were
- if (!_loadedCast->contains(castID)) {
+ if (!_loadedCast->contains(id)) {
continue;
}
CastMember *target = _loadedCast->getVal(id);
- target->writeToFile(writeStream, offset, _version, castID);
+ sizeWritten += target->writeCAStResource(writeStream, offset + sizeWritten, _version);
}
}
@@ -1042,7 +1045,8 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
stream.hexdump(stream.size());
uint32 castDataSize, castInfoSize, castType, castDataSizeToRead, castDataOffset, castInfoOffset;
- byte flags1 = -1, unk1 = 0, unk2 = 0, unk3 = 0;
+ uint8 flags1 = -1;
+ byte unk1 = 0, unk2 = 0, unk3 = 0;
// D2-3 cast members should be loaded in loadCastDataVWCR
#if 0
@@ -1437,6 +1441,15 @@ void Cast::loadCastInfo(Common::SeekableReadStreamEndian &stream, uint16 id) {
Common::MemoryReadStreamEndian *entryStream;
CastMember *member = _loadedCast->getVal(id);
+ // We need this data while saving the cast information back
+ // Is it possible that the count changes?
+ ci->unk1 = castInfo.unk1;
+ ci->unk2 = castInfo.unk2;
+ ci->count = castInfo.strings.size();
+
+ // If possible, we won't store flags
+ ci->flags = castInfo.flags;
+
// We have here variable number of strings. Thus, instead of
// adding tons of ifs, we use this switch()
switch (castInfo.strings.size()) {
@@ -1447,42 +1460,49 @@ void Cast::loadCastInfo(Common::SeekableReadStreamEndian &stream, uint16 id) {
if (castInfo.strings[14].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 14, id);
Common::hexdump(castInfo.strings[14].data, castInfo.strings[14].len);
+ ci->unknownString7 = castInfo.strings[14].readString();
}
// fallthrough
case 14:
if (castInfo.strings[13].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 13, id);
Common::hexdump(castInfo.strings[13].data, castInfo.strings[13].len);
+ ci->unknownString6 = castInfo.strings[13].readString();
}
// fallthrough
case 13:
if (castInfo.strings[12].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 12, id);
Common::hexdump(castInfo.strings[12].data, castInfo.strings[12].len);
+ ci->unknownString5 = castInfo.strings[12].readString();
}
// fallthrough
case 12:
if (castInfo.strings[11].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 11, id);
Common::hexdump(castInfo.strings[11].data, castInfo.strings[11].len);
+ ci->unknownString4 = castInfo.strings[11].readString();
}
// fallthrough
case 11:
if (castInfo.strings[10].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 11, id);
Common::hexdump(castInfo.strings[10].data, castInfo.strings[10].len);
+ ci->unknownString3 = castInfo.strings[10].readString();
}
// fallthrough
case 10:
if (castInfo.strings[9].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 10, id);
Common::hexdump(castInfo.strings[9].data, castInfo.strings[9].len);
+ ci->unknownString2 = castInfo.strings[9].readString();
}
// fallthrough
case 9:
if (castInfo.strings[8].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 9, id);
Common::hexdump(castInfo.strings[8].data, castInfo.strings[8].len);
+ ci->unknownString1 = castInfo.strings[8].readString();
}
// fallthrough
case 8:
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index dedd1fcfc9b..78f7758b85f 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -26,6 +26,7 @@
#include "director/director.h"
#include "director/cast.h"
+#include "director/movie.h"
#include "director/castmember/castmember.h"
#include "director/lingo/lingo-the.h"
@@ -307,16 +308,25 @@ void CastMember::unload() {
_loaded = false;
}
-// Default implementation to write the cast members as they are
-void CastMember::writeToFile(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castID) {
+// Default implementation to write the 'CASt' resources as they are
+// Cast members have two types of "information", one is _data_ and the other is _info_
+// _data_ is the actual "data" (e.g. the pixel image data of a bitmap, sound data of a sound cast member)
+// Whereas _info_ is metadata (size, name, flags, etc.)
+// Some castmembers have their _data_ as well as _info_ in this very 'CASt' resource, e.g. TextCastMember
+// Whereas some other have their _info_ in a 'CASt' resource and _data_ in a dedicated resource (e.g. PaletteCastMember has 'CLUT' resource)
+uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version) {
writeStream->seek(offset);
+ uint32 startPos = writeStream->pos();
+
writeStream->writeUint16LE(MKTAG('C', 'A', 'S', 't'));
uint32 castDataToWrite = getDataSize();
uint32 castInfoToWrite = getInfoSize();
uint32 castDataOffset = 0;
uint32 castInfoOffset = 0;
- Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), castID);
+
+ // We'll need the original resource stream if there is no change in the castmember
+ Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), _castId);
if (version >= kFileVer400 && version < kFileVer500) {
writeStream->writeUint16LE(castDataToWrite);
@@ -337,16 +347,19 @@ void CastMember::writeToFile(Common::MemoryWriteStream *writeStream, uint32 offs
writeStream->writeUint32LE(getDataSize());
}
-
+ // CastDataToWrite could be 0
byte *data = (byte *)calloc(castDataToWrite, 1);
byte *info = (byte *)calloc(castInfoToWrite, 1);
- stream->seek(castDataOffset, SEEK_CUR);
+ stream->seek(castDataOffset);
stream->read(data, castDataToWrite);
+
+ stream->seek(castInfoOffset);
stream->read(info, castInfoToWrite);
Common::MemoryReadStreamEndian *dataStream = new Common::MemoryReadStreamEndian(data, castDataToWrite, stream->isBE());
Common::MemoryReadStreamEndian *infoStream = new Common::MemoryReadStreamEndian(info, castInfoToWrite, stream->isBE());
+ // They just arbitrarily changed the order for D5? Why? Although we don't necessarily have to follow that
if (version >= kFileVer400 && version < kFileVer500) {
writeStream->writeStream(dataStream);
writeStream->writeStream(infoStream);
@@ -354,6 +367,200 @@ void CastMember::writeToFile(Common::MemoryWriteStream *writeStream, uint32 offs
writeStream->writeStream(infoStream);
writeStream->writeStream(dataStream);
}
+
+ return writeStream->pos() - startPos;
+}
+
+void CastMemberInfo::writeCastMemberInfo(Common::MemoryWriteStream *writeStream) {
+ writeStream->writeUint32LE(20); // The offset post-d4 movies is always 20
+ writeStream->writeUint32LE(unk1);
+ writeStream->writeUint32LE(unk2);
+ writeStream->writeUint32LE(flags); // Possibly no need to save
+
+ writeStream->writeUint32LE(scriptId);
+ writeStream->writeUint16LE(count);
+
+ uint32 length = 0;
+ writeStream->writeUint32LE(length);
+
+ // The structure of the CastMemberInfo is as follows:
+ // First some headers: offset, unkonwns and flags, and then a count of strings to be read
+ // (These strings contain properties of the cast member like filename, script attached to it, name, etc.)
+ // After the header, we have the lengths of the strings
+ for (int i = 1; i <= count; i++) {
+ switch (i) {
+ default:
+ debug("writeCastMemberInfo:: extra strings found, ignoring");
+ break;
+
+ case 1:
+ length += script.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 2:
+ length += name.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 3:
+ length += directory.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 4:
+ length += fileName.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 5:
+ length += type.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 6:
+ if (scriptEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 7:
+ if (scriptStyle.fontId) {
+ length += 20; // The length of FontStyle
+ writeStream->writeUint32LE(length);
+ }
+ break;
+
+ case 8:
+ if (textEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 9:
+ length += unknownString1.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 10:
+ length += unknownString2.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 11:
+ length += unknownString3.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 12:
+ length += unknownString4.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 13:
+ length += unknownString5.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 14:
+ length += unknownString6.size();
+ writeStream->writeUint32LE(length);
+ break;
+
+ case 15:
+ length += unknownString7.size();
+ writeStream->writeUint32LE(length);
+ break;
+ }
+ }
+
+ for (int i = 1; i <= count; i++) {
+ switch (i) {
+ default:
+ debug("writeCastMemberInfo::extra strings found, ignoring");
+ break;
+
+ case 1:
+ writeStream->writeString(script);
+ break;
+
+ case 2:
+ writeStream->writeString(directory);
+ break;
+
+ case 3:
+ writeStream->writeString(directory);
+ break;
+
+ case 4:
+ writeStream->writeString(fileName);
+ break;
+
+ case 5:
+ writeStream->writeString(type);
+ break;
+
+ case 6:
+ // Need a better check to see if script edit info is valid
+ if (scriptEditInfo.version) {
+ Movie::writeRect(writeStream, scriptEditInfo.rect);
+ writeStream->writeUint32LE(scriptEditInfo.selStart);
+ writeStream->writeUint32LE(scriptEditInfo.selEnd);
+ writeStream->writeByte(scriptEditInfo.version);
+ writeStream->writeByte(scriptEditInfo.rulerFlag);
+ }
+ break;
+
+ case 7:
+ // Need a better check to see if scriptStyle is valid
+ if (scriptStyle.fontId) {
+ writeStream->writeUint16LE(1); // FIXME: For CastMembers, the count is 1, observed value, need to validate
+ scriptStyle.write(writeStream);
+ }
+ break;
+
+ case 8:
+ // Need a better check to see if text edit info is valid
+ if (textEditInfo.version) {
+ Movie::writeRect(writeStream, textEditInfo.rect);
+ writeStream->writeUint32LE(textEditInfo.selStart);
+ writeStream->writeUint32LE(textEditInfo.selEnd);
+ writeStream->writeByte(textEditInfo.version);
+ writeStream->writeByte(textEditInfo.rulerFlag);
+ }
+ break;
+
+ case 9:
+ writeStream->writeString(unknownString1);
+ break;
+
+ case 10:
+ writeStream->writeString(unknownString2);
+ break;
+
+ case 11:
+ writeStream->writeString(unknownString3);
+ break;
+
+ case 12:
+ writeStream->writeString(unknownString4);
+ break;
+
+ case 13:
+ writeStream->writeString(unknownString5);
+ break;
+
+ case 14:
+ writeStream->writeString(unknownString6);
+ break;
+
+ case 15:
+ writeStream->writeString(unknownString7);
+ break;
+ }
+ }
}
uint32 CastMember::getDataSize() {
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index bd4914064a0..e3d1ab4c5bd 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -101,7 +101,7 @@ public:
virtual CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) { return bbox.contains(pos) ? kCollisionYes : kCollisionNo; }
- virtual void writeToFile(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castID);
+ virtual uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version);
virtual uint32 getDataSize();
virtual uint32 getInfoSize();
@@ -119,7 +119,7 @@ public:
uint32 _castDataSize;
uint32 _castInfoSize;
uint32 _castType;
- byte _flags1;
+ uint8 _flags1;
protected:
Cast *_cast;
@@ -141,6 +141,10 @@ struct EditInfo {
};
struct CastMemberInfo {
+ uint32 unk1;
+ uint32 unk2;
+ uint32 flags;
+ uint16 count;
bool autoHilite;
uint32 scriptId;
Common::String script;
@@ -154,7 +158,18 @@ struct CastMemberInfo {
Common::String modifiedBy;
Common::String comments;
+ // There just has to be a better solution
+ // It is not rare to find these strings in the CastMemberInfo
+ Common::String unknownString1;
+ Common::String unknownString2;
+ Common::String unknownString3;
+ Common::String unknownString4;
+ Common::String unknownString5;
+ Common::String unknownString6;
+ Common::String unknownString7;
+
CastMemberInfo() : autoHilite(false), scriptId(0) {}
+ void writeCastMemberInfo(Common::MemoryWriteStream *writeStream);
};
} // End of namespace Director
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index 9f9ae4fbacb..ee3f5a84a7c 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -19,10 +19,15 @@
*
*/
+#include "common/substream.h"
+#include "common/macresman.h"
+#include "common/memstream.h"
+
#include "director/director.h"
#include "director/cast.h"
#include "director/castmember/palette.h"
+
namespace Director {
PaletteCastMember::PaletteCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version)
@@ -131,4 +136,75 @@ void PaletteCastMember::unload() {
// No unload necessary.
}
+uint32 PaletteCastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version) {
+ uint64 startingPos = writeStream->pos();
+
+ uint32 castDataToWrite = getDataSize();
+ uint32 castInfoToWrite = getInfoSize();
+ uint32 castDataOffset = 0;
+
+ if (version >= kFileVer400 && version < kFileVer500) {
+ writeStream->writeUint16LE(castDataToWrite);
+ writeStream->writeUint32LE(castInfoToWrite);
+ castDataOffset += 6;
+
+ writeStream->writeUint32LE(_castType);
+ castDataToWrite -= 1;
+
+ if (_flags1 != -1) {
+ writeStream->writeByte(_flags1);
+ castDataToWrite -= 1;
+ castDataOffset += 1;
+ }
+ } else if (version >= kFileVer500 && version < kFileVer600) {
+ writeStream->writeUint32LE(_castType);
+ writeStream->writeUint32LE(getInfoSize());
+ writeStream->writeUint32LE(getDataSize());
+ }
+
+ CastMemberInfo *ci = _cast->getCastMemberInfo(_castId);
+
+ ci->writeCastMemberInfo(writeStream);
+
+ // For cast members with dedicated resrouces for data, the castDataToWrite is zero
+ // So for Palette Cast Member, the castDataToWrite is zero
+ // if (castDataToWrite > 0) {
+ // writeDataInfo();
+ // }
+
+ return writeStream->pos() - startingPos;
}
+
+void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset) {
+ writeStream->seek(offset);
+ writeStream->writeUint32LE(MKTAG('C', 'L', 'U', 'T'));
+ writeStream->seek(4, SEEK_CUR);
+
+ const byte *pal = _palette->palette;
+
+ for (int i = 0; i < _palette->length; i++) {
+ writeStream->writeByte(pal[3 * i]);
+ writeStream->seek(1, SEEK_CUR);
+
+ writeStream->writeByte(pal[3 * i + 1]);
+ writeStream->seek(1, SEEK_CUR);
+
+ writeStream->writeByte(pal[3 * i + 2]);
+ writeStream->seek(1, SEEK_CUR);
+ }
+}
+
+uint32 PaletteCastMember::getInfoSize() {
+ // Need to find a way to find the info size
+ return 0;
+}
+uint32 PaletteCastMember::getDataSize() {
+ if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ return 0;
+ } else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ // Observed value, need to verify
+ return 4;
+ }
+}
+
+} // End of namespace Director
diff --git a/engines/director/castmember/palette.h b/engines/director/castmember/palette.h
index 66db897c0bf..1d0afc23ee2 100644
--- a/engines/director/castmember/palette.h
+++ b/engines/director/castmember/palette.h
@@ -43,6 +43,10 @@ public:
void load() override;
void unload() override;
+ uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version) override;
+ void writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset);
+ uint32 getInfoSize() override;
+ uint32 getDataSize() override;
PaletteV4 *_palette;
};
diff --git a/engines/director/stxt.cpp b/engines/director/stxt.cpp
index c679e27ea79..278a3ee9555 100644
--- a/engines/director/stxt.cpp
+++ b/engines/director/stxt.cpp
@@ -19,6 +19,8 @@
*
*/
+#include "common/macresman.h"
+#include "common/memstream.h"
#include "common/substream.h"
#include "director/director.h"
@@ -150,4 +152,19 @@ void FontStyle::read(Common::ReadStreamEndian &stream, Cast *cast) {
formatStartOffset, originalHeight, height, ascent, originalFontId, fontId, textSlant, fontSize, r, g, b);
}
+void FontStyle::write(Common::MemoryWriteStream *writeStream) {
+ writeStream->writeUint32LE(formatStartOffset);
+ writeStream->writeUint16LE(height);
+ writeStream->writeUint16LE(ascent);
+ writeStream->writeUint16LE(fontId);
+
+ writeStream->writeByte(textSlant);
+ writeStream->seek(1, SEEK_CUR); // padding
+ writeStream->writeUint16LE(fontSize);
+
+ writeStream->writeUint16LE(r);
+ writeStream->writeUint16LE(g);
+ writeStream->writeUint16LE(b);
+}
+
} // End of namespace Director
diff --git a/engines/director/stxt.h b/engines/director/stxt.h
index 27ee69d5977..d245617b841 100644
--- a/engines/director/stxt.h
+++ b/engines/director/stxt.h
@@ -24,6 +24,7 @@
namespace Common {
class ReadStreamEndian;
+class MemoryWriteStream;
}
namespace Director {
@@ -44,6 +45,7 @@ struct FontStyle {
FontStyle();
void read(Common::ReadStreamEndian &textStream, Cast *cast);
+ void write(Common::MemoryWriteStream *writeStream);
};
class Stxt {
Commit: 593191968f1add8f2293820e4ee5055c02470549
https://github.com/scummvm/scummvm/commit/593191968f1add8f2293820e4ee5055c02470549
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Write Cast Config and CASt Resources
Correctly write the Cast config resource 'VWCF'
Correctly write the Cast member resource 'CASt' as they are
Correctly write the Cast Info in the 'CASt' resource
Correctly write custom Palette Cast member 'CASt' resource
Correctly write custom Palette Cast member data 'CLUT' resource
Changed paths:
engines/director/archive.cpp
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
engines/director/castmember/palette.cpp
engines/director/castmember/palette.h
engines/director/movie.cpp
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index f014c37bbd2..c28db0cfa44 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -1231,7 +1231,9 @@ bool RIFXArchive::writeToFile(Common::Path path) {
it->tag != MKTAG('m', 'm', 'a', 'p') &&
it->tag != MKTAG('K', 'E', 'Y', '*')
) {
- writeStream->seek(it->offset + 8);
+ writeStream->seek(it->offset);
+ writeStream->writeUint32LE(it->tag);
+ writeStream->writeUint32LE(it->size);
writeStream->writeStream(getResource(it->tag, it->index));
}
}
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 76dfba1717d..661d6234756 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -518,6 +518,29 @@ bool Cast::loadConfig() {
_vm->setVersion(humanVer);
}
+ uint32 castSize = stream->size() + 8;
+ byte *dumpData = nullptr;
+ dumpData = (byte *)calloc(castSize, sizeof(byte));
+
+ Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
+
+ saveConfig(writeStream, 0);
+ Common::DumpFile out;
+ char buf[256];
+ Common::sprintf_s(buf, "./dumps/%d-%s-%s", 0, tag2str(MKTAG('V', 'W', 'C', 'F')), "WrittenConfig");
+
+ // Write the movie out, stored in dumpData
+ if (out.open(buf, true)) {
+ out.write(dumpData, castSize);
+ out.flush();
+ out.close();
+ debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
+ } else {
+ warning("RIFXArchive::writeStream: Error saving the file %s", buf);
+ }
+ free(dumpData);
+ delete writeStream;
+
delete stream;
return true;
}
@@ -778,36 +801,269 @@ void Cast::loadCast() {
if (_castArchive->hasResource(MKTAG('S', 'C', 'R', 'F'), -1)) {
debugC(4, kDebugLoading, "'SCRF' resource skipped");
}
-
- // saveCast(nullptr, 0);
-
+
+ if (debugChannelSet(7, kDebugLoading)) {
+ debug("Cast::saveCast: Saving the Cast resources in ./dumps");
+ saveCast();
+ }
}
-void Cast::saveCast(Common::MemoryWriteStream *writeStream, uint32 offset) {
+void Cast::saveCast() {
// This offset is at which we will start writing our 'CASt' resources
// In the original file, all the 'CASt' resources don't necessarily appear side by side
- writeStream->seek(offset);
-
+ // writeStream->seek(offset);
+
Common::Array<uint16> cast = _castArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't'));
- uint32 sizeWritten = 0;
+ // Okay, this is going to cause confusion
+ // In the director movie archive, each CASt resource is given an ID, Not sure how this ID is assigned
+ // but it is present in the keytable and is loaded while reading the keytable in RIFXArchive::readKeyTable();
+ // The castId on the other hand present in the Resource struct is assigned by ScummVM Director in RIFXArchive::readCast()
+ // It is basically the index at which it occurs in the CAS* resource
+ // So, RIFXArchive::getResourceDetail will return the list of IDs present in the keytable
+ // Whereas, in the _loadedCast, the key of these Cast members is given by castId
for (auto &it : cast) {
- writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
- writeStream->seek(4, SEEK_CUR);
-
Resource res = _castArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), it);
uint16 id = res.castId + _castArrayStart;
+ uint32 castSize = 0;
+
+ if (_loadedCast->contains(id)) {
+ CastMember *target = _loadedCast->getVal(id);
+ castSize = target->getCastResourceSize(_version) + 8;
+ } else {
+ castSize = _castArchive->getResourceSize(MKTAG('C', 'A', 'S', 't'), it) + 8;
+ }
+
+ byte *dumpData = nullptr;
+ dumpData = (byte *)calloc(castSize, sizeof(byte));
+
+ Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
- // FIXME: This is wrong, we need to write cast members even if they are not handled/loaded
- // We are currently ignoring cast members that we do not understand (e.g. kCastPicture)
- // They need to be handled by the default handler, which will write them as they were
if (!_loadedCast->contains(id)) {
- continue;
+ Common::SeekableReadStreamEndian *stream = getResource(MKTAG('C', 'A', 'S', 't'), it);
+ writeStream->writeStream(stream);
+ } else {
+ CastMember *target = _loadedCast->getVal(id);
+ target->writeCAStResource(writeStream, 0, _version, it);
+ }
+
+ Common::DumpFile out;
+ char buf[256];
+ Common::sprintf_s(buf, "./dumps/%d-%s-%s", it, tag2str(res.tag), "WrittenCAStResource");
+
+ // Write the movie out, stored in dumpData
+ if (out.open(buf, true)) {
+ out.write(dumpData, castSize);
+ out.flush();
+ out.close();
+ debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
+ } else {
+ warning("RIFXArchive::writeStream: Error saving the file %s", buf);
}
+ free(dumpData);
+ delete writeStream;
+ }
- CastMember *target = _loadedCast->getVal(id);
- sizeWritten += target->writeCAStResource(writeStream, offset + sizeWritten, _version);
- }
+}
+
+void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId) {
+ if (!_castsInfo.contains(castId)) {
+ return;
+ }
+ CastMemberInfo *ci = _castsInfo[castId];
+
+ writeStream->writeUint32BE(20); // The offset post-d4 movies is always 20
+ writeStream->writeUint32BE(ci->unk1);
+ writeStream->writeUint32BE(ci->unk2);
+ writeStream->writeUint32BE(ci->flags); // Possibly no need to save
+
+ writeStream->writeUint32BE(ci->scriptId);
+
+ writeStream->writeUint16BE(ci->count);
+
+ uint32 length = 0;
+ writeStream->writeUint32BE(length);
+
+ // The structure of the CastMemberInfo is as follows:
+ // First some headers: offset, unkonwns and flags, and then a count of strings to be read
+ // (These strings contain properties of the cast member like filename, script attached to it, name, etc.)
+ // After the header, we have the next data is the lengths of the strings,
+ // The first int is 0, the second int is 0 + length of the first string, the third int is 0 + length of first string + length of second string and so on
+ // After the lengths of the strings are the actual strings
+ for (int i = 1; i <= ci->count; i++) {
+ switch (i) {
+ default:
+ debug("writeCastMemberInfo:: extra strings found, ignoring");
+ break;
+
+ case 1:
+ length += ci->script.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 2:
+ length += ci->name.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 3:
+ length += ci->directory.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 4:
+ length += ci->fileName.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 5:
+ length += ci->type.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 6:
+ if (ci->scriptEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 7:
+ if (ci->scriptStyle.fontId) {
+ length += 20; // The length of FontStyle
+ writeStream->writeUint32BE(length);
+ }
+ break;
+
+ case 8:
+ if (ci->textEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 9:
+ length += ci->unknownString1.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 10:
+ length += ci->unknownString2.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 11:
+ length += ci->unknownString3.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 12:
+ length += ci->unknownString4.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 13:
+ length += ci->unknownString5.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 14:
+ length += ci->unknownString6.size();
+ writeStream->writeUint32BE(length);
+ break;
+
+ case 15:
+ length += ci->unknownString7.size();
+ writeStream->writeUint32BE(length);
+ break;
+ }
+ }
+
+ for (int i = 1; i <= ci->count; i++) {
+ switch (i) {
+ default:
+ debug("writeCastMemberInfo::extra strings found, ignoring");
+ break;
+
+ case 1:
+ writeStream->writeString(ci->script);
+ break;
+
+ case 2:
+ writeStream->writeString(ci->name);
+ break;
+
+ case 3:
+ writeStream->writeString(ci->directory);
+ break;
+
+ case 4:
+ writeStream->writeString(ci->fileName);
+ break;
+
+ case 5:
+ writeStream->writeString(ci->type);
+ break;
+
+ case 6:
+ // Need a better check to see if script edit info is valid
+ if (ci->scriptEditInfo.version) {
+ Movie::writeRect(writeStream, ci->scriptEditInfo.rect);
+ writeStream->writeUint32BE(ci->scriptEditInfo.selStart);
+ writeStream->writeUint32BE(ci->scriptEditInfo.selEnd);
+ writeStream->writeByte(ci->scriptEditInfo.version);
+ writeStream->writeByte(ci->scriptEditInfo.rulerFlag);
+ }
+ break;
+
+ case 7:
+ // Need a better check to see if scriptStyle is valid
+ if (ci->scriptStyle.fontId) {
+ writeStream->writeUint16LE(1); // FIXME: For CastMembers, the count is 1, observed value, need to validate
+ ci->scriptStyle.write(writeStream);
+ }
+ break;
+
+ case 8:
+ // Need a better check to see if text edit info is valid
+ if (ci->textEditInfo.version) {
+ Movie::writeRect(writeStream, ci->textEditInfo.rect);
+ writeStream->writeUint32BE(ci->textEditInfo.selStart);
+ writeStream->writeUint32BE(ci->textEditInfo.selEnd);
+ writeStream->writeByte(ci->textEditInfo.version);
+ writeStream->writeByte(ci->textEditInfo.rulerFlag);
+ }
+ break;
+
+ case 9:
+ writeStream->writeString(ci->unknownString1);
+ break;
+
+ case 10:
+ writeStream->writeString(ci->unknownString2);
+ break;
+
+ case 11:
+ writeStream->writeString(ci->unknownString3);
+ break;
+
+ case 12:
+ writeStream->writeString(ci->unknownString4);
+ break;
+
+ case 13:
+ writeStream->writeString(ci->unknownString5);
+ break;
+
+ case 14:
+ writeStream->writeString(ci->unknownString6);
+ break;
+
+ case 15:
+ writeStream->writeString(ci->unknownString7);
+ break;
+ }
+ }
}
uint32 Cast::computeChecksum() {
@@ -1028,6 +1284,8 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
// IDs are stored as relative to the start of the cast array.
id += _castArrayStart;
+ uint32 size = stream.size() + 8;
+
// D4+ variant
if (stream.size() == 0)
return;
@@ -1045,7 +1303,7 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
stream.hexdump(stream.size());
uint32 castDataSize, castInfoSize, castType, castDataSizeToRead, castDataOffset, castInfoOffset;
- uint8 flags1 = -1;
+ uint8 flags1 = 0xFF;
byte unk1 = 0, unk2 = 0, unk3 = 0;
// D2-3 cast members should be loaded in loadCastDataVWCR
@@ -1161,6 +1419,7 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
break;
}
if (target) {
+ target->_castResourceSize = size;
target->_castDataSize = castDataSize;
target->_castInfoSize = castInfoSize;
target->_castType = castType;
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 258a51b76f1..338a4782eac 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -107,8 +107,9 @@ public:
void loadSord(Common::SeekableReadStreamEndian &stream);
void saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset);
- void saveCast(Common::MemoryWriteStream *writeStream, uint32 offset);
+ void saveCast();
void saveCastData();
+ void writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId);
int getCastSize();
int getCastMaxID();
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 78f7758b85f..81d2d88eb58 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -314,263 +314,34 @@ void CastMember::unload() {
// Whereas _info_ is metadata (size, name, flags, etc.)
// Some castmembers have their _data_ as well as _info_ in this very 'CASt' resource, e.g. TextCastMember
// Whereas some other have their _info_ in a 'CASt' resource and _data_ in a dedicated resource (e.g. PaletteCastMember has 'CLUT' resource)
-uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version) {
- writeStream->seek(offset);
- uint32 startPos = writeStream->pos();
-
- writeStream->writeUint16LE(MKTAG('C', 'A', 'S', 't'));
-
- uint32 castDataToWrite = getDataSize();
- uint32 castInfoToWrite = getInfoSize();
- uint32 castDataOffset = 0;
- uint32 castInfoOffset = 0;
-
+uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castIndex) {
// We'll need the original resource stream if there is no change in the castmember
- Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), _castId);
-
- if (version >= kFileVer400 && version < kFileVer500) {
- writeStream->writeUint16LE(castDataToWrite);
- writeStream->writeUint32LE(castInfoToWrite);
- castDataOffset += 6;
-
- writeStream->writeUint32LE(_castType);
- castDataToWrite -= 1;
-
- if (_flags1 != -1) {
- writeStream->writeByte(_flags1);
- castDataToWrite -= 1;
- castDataOffset += 1;
- }
- } else if (version >= kFileVer500 && version < kFileVer600) {
- writeStream->writeUint32LE(_castType);
- writeStream->writeUint32LE(getInfoSize());
- writeStream->writeUint32LE(getDataSize());
- }
-
- // CastDataToWrite could be 0
- byte *data = (byte *)calloc(castDataToWrite, 1);
- byte *info = (byte *)calloc(castInfoToWrite, 1);
- stream->seek(castDataOffset);
- stream->read(data, castDataToWrite);
-
- stream->seek(castInfoOffset);
- stream->read(info, castInfoToWrite);
-
- Common::MemoryReadStreamEndian *dataStream = new Common::MemoryReadStreamEndian(data, castDataToWrite, stream->isBE());
- Common::MemoryReadStreamEndian *infoStream = new Common::MemoryReadStreamEndian(info, castInfoToWrite, stream->isBE());
+ Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), castIndex);
+ uint32 size = stream->size();
- // They just arbitrarily changed the order for D5? Why? Although we don't necessarily have to follow that
- if (version >= kFileVer400 && version < kFileVer500) {
- writeStream->writeStream(dataStream);
- writeStream->writeStream(infoStream);
- } else if (version >= kFileVer500 && version < kFileVer600) {
- writeStream->writeStream(infoStream);
- writeStream->writeStream(dataStream);
- }
-
- return writeStream->pos() - startPos;
-}
-
-void CastMemberInfo::writeCastMemberInfo(Common::MemoryWriteStream *writeStream) {
- writeStream->writeUint32LE(20); // The offset post-d4 movies is always 20
- writeStream->writeUint32LE(unk1);
- writeStream->writeUint32LE(unk2);
- writeStream->writeUint32LE(flags); // Possibly no need to save
-
- writeStream->writeUint32LE(scriptId);
- writeStream->writeUint16LE(count);
-
- uint32 length = 0;
- writeStream->writeUint32LE(length);
-
- // The structure of the CastMemberInfo is as follows:
- // First some headers: offset, unkonwns and flags, and then a count of strings to be read
- // (These strings contain properties of the cast member like filename, script attached to it, name, etc.)
- // After the header, we have the lengths of the strings
- for (int i = 1; i <= count; i++) {
- switch (i) {
- default:
- debug("writeCastMemberInfo:: extra strings found, ignoring");
- break;
-
- case 1:
- length += script.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 2:
- length += name.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 3:
- length += directory.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 4:
- length += fileName.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 5:
- length += type.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 6:
- if (scriptEditInfo.version) {
- length += 18; // The length of an edit info
- }
- writeStream->writeUint32LE(length);
- break;
-
- case 7:
- if (scriptStyle.fontId) {
- length += 20; // The length of FontStyle
- writeStream->writeUint32LE(length);
- }
- break;
-
- case 8:
- if (textEditInfo.version) {
- length += 18; // The length of an edit info
- }
- writeStream->writeUint32LE(length);
- break;
-
- case 9:
- length += unknownString1.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 10:
- length += unknownString2.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 11:
- length += unknownString3.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 12:
- length += unknownString4.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 13:
- length += unknownString5.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 14:
- length += unknownString6.size();
- writeStream->writeUint32LE(length);
- break;
-
- case 15:
- length += unknownString7.size();
- writeStream->writeUint32LE(length);
- break;
- }
- }
-
- for (int i = 1; i <= count; i++) {
- switch (i) {
- default:
- debug("writeCastMemberInfo::extra strings found, ignoring");
- break;
-
- case 1:
- writeStream->writeString(script);
- break;
-
- case 2:
- writeStream->writeString(directory);
- break;
-
- case 3:
- writeStream->writeString(directory);
- break;
-
- case 4:
- writeStream->writeString(fileName);
- break;
-
- case 5:
- writeStream->writeString(type);
- break;
-
- case 6:
- // Need a better check to see if script edit info is valid
- if (scriptEditInfo.version) {
- Movie::writeRect(writeStream, scriptEditInfo.rect);
- writeStream->writeUint32LE(scriptEditInfo.selStart);
- writeStream->writeUint32LE(scriptEditInfo.selEnd);
- writeStream->writeByte(scriptEditInfo.version);
- writeStream->writeByte(scriptEditInfo.rulerFlag);
- }
- break;
-
- case 7:
- // Need a better check to see if scriptStyle is valid
- if (scriptStyle.fontId) {
- writeStream->writeUint16LE(1); // FIXME: For CastMembers, the count is 1, observed value, need to validate
- scriptStyle.write(writeStream);
- }
- break;
-
- case 8:
- // Need a better check to see if text edit info is valid
- if (textEditInfo.version) {
- Movie::writeRect(writeStream, textEditInfo.rect);
- writeStream->writeUint32LE(textEditInfo.selStart);
- writeStream->writeUint32LE(textEditInfo.selEnd);
- writeStream->writeByte(textEditInfo.version);
- writeStream->writeByte(textEditInfo.rulerFlag);
- }
- break;
-
- case 9:
- writeStream->writeString(unknownString1);
- break;
-
- case 10:
- writeStream->writeString(unknownString2);
- break;
-
- case 11:
- writeStream->writeString(unknownString3);
- break;
-
- case 12:
- writeStream->writeString(unknownString4);
- break;
-
- case 13:
- writeStream->writeString(unknownString5);
- break;
+ writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
+ writeStream->writeUint32LE(size);
- case 14:
- writeStream->writeString(unknownString6);
- break;
-
- case 15:
- writeStream->writeString(unknownString7);
- break;
- }
- }
+ writeStream->writeStream(stream);
+ return size + 8;
}
+// This is the data that is inside the 'CASt' resource
uint32 CastMember::getDataSize() {
- debug("CastMember::getDataSize(): Defualt implementation of cast member data size, returning original size.");
+ debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size, returning original size.");
return _castDataSize;
}
+// This is the info that is inside the 'CASt' resource
uint32 CastMember::getInfoSize() {
- debug("CastMember::getInfoSize(): Defualt implementation of cast member info size, returning original size.");
+ debug("CastMember::getInfoSize(): Defualt implementation of 'CASt' resource info size, returning original size.");
return _castInfoSize;
}
+// getCastResourceSize only returns the size of the resource without the header
+uint32 CastMember::getCastResourceSize(uint32 version) {
+ debug("CastMember::getInfoSize(): Defualt implementation of 'CASt' resource size, returning original size.");
+ return _castResourceSize;
+}
+
} // End of namespace Director
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index e3d1ab4c5bd..e5768fc24f4 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -101,9 +101,10 @@ public:
virtual CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) { return bbox.contains(pos) ? kCollisionYes : kCollisionNo; }
- virtual uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version);
+ virtual uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castId);
virtual uint32 getDataSize();
virtual uint32 getInfoSize();
+ virtual uint32 getCastResourceSize(uint32 version);
CastType _type;
Common::Rect _initialRect;
@@ -118,6 +119,7 @@ public:
/* Data fields used when saving the Cast Member */
uint32 _castDataSize;
uint32 _castInfoSize;
+ uint32 _castResourceSize;
uint32 _castType;
uint8 _flags1;
@@ -169,7 +171,6 @@ struct CastMemberInfo {
Common::String unknownString7;
CastMemberInfo() : autoHilite(false), scriptId(0) {}
- void writeCastMemberInfo(Common::MemoryWriteStream *writeStream);
};
} // End of namespace Director
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index ee3f5a84a7c..1a509794cea 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -32,6 +32,8 @@ namespace Director {
PaletteCastMember::PaletteCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version)
: CastMember(cast, castId, stream) {
+ debug("In Palette Cast Member: stream: size: %d", stream.size());
+ stream.hexdump(stream.size());
_type = kCastPalette;
_palette = nullptr;
}
@@ -136,75 +138,207 @@ void PaletteCastMember::unload() {
// No unload necessary.
}
-uint32 PaletteCastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version) {
- uint64 startingPos = writeStream->pos();
+uint32 PaletteCastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 id) {
+ uint32 castResourceSize = getCastResourceSize(version);
+
+ writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
+ writeStream->writeUint32LE(castResourceSize); // this is excluding the 'CASt' header and the size itself (- 8 bytes)
uint32 castDataToWrite = getDataSize();
uint32 castInfoToWrite = getInfoSize();
- uint32 castDataOffset = 0;
if (version >= kFileVer400 && version < kFileVer500) {
- writeStream->writeUint16LE(castDataToWrite);
- writeStream->writeUint32LE(castInfoToWrite);
- castDataOffset += 6;
-
- writeStream->writeUint32LE(_castType);
- castDataToWrite -= 1;
+ writeStream->writeUint16BE(castDataToWrite);
+ writeStream->writeUint32BE(castInfoToWrite);
+ writeStream->writeByte(_castType);
- if (_flags1 != -1) {
+ if (_flags1 != 0xFF) {
writeStream->writeByte(_flags1);
- castDataToWrite -= 1;
- castDataOffset += 1;
+ }
+
+ // For cast members with dedicated resrouces for data, the castDataToWrite is zero
+ // So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
+ if (castDataToWrite) {
+ writePaletteData(writeStream, writeStream->pos());
+ }
+
+ if (castInfoToWrite) {
+ _cast->writeCastInfo(writeStream, _castId);
}
} else if (version >= kFileVer500 && version < kFileVer600) {
- writeStream->writeUint32LE(_castType);
- writeStream->writeUint32LE(getInfoSize());
- writeStream->writeUint32LE(getDataSize());
- }
-
- CastMemberInfo *ci = _cast->getCastMemberInfo(_castId);
+ writeStream->writeUint32BE(_castType);
+ writeStream->writeUint32BE(castInfoToWrite);
+ writeStream->writeUint32BE(castDataToWrite);
+
+ if (castInfoToWrite) {
+ _cast->writeCastInfo(writeStream, _castId);
+ }
- ci->writeCastMemberInfo(writeStream);
+ // For cast members with dedicated resrouces for data, the castDataToWrite is zero
+ // So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
+ if (castDataToWrite) {
+ writePaletteData(writeStream, writeStream->pos());
+ }
+ }
- // For cast members with dedicated resrouces for data, the castDataToWrite is zero
- // So for Palette Cast Member, the castDataToWrite is zero
- // if (castDataToWrite > 0) {
- // writeDataInfo();
- // }
+ writePaletteData(nullptr, 0);
- return writeStream->pos() - startingPos;
+ return castResourceSize + 8;
}
void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset) {
- writeStream->seek(offset);
+ uint32 castSize = getPaletteDataSize() + 8;
+ byte *dumpData = nullptr;
+ dumpData = (byte *)calloc(castSize, sizeof(byte));
+
+ writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
+
+ // writeStream->seek(offset);
writeStream->writeUint32LE(MKTAG('C', 'L', 'U', 'T'));
- writeStream->seek(4, SEEK_CUR);
+ writeStream->writeUint32LE(getPaletteDataSize());
const byte *pal = _palette->palette;
for (int i = 0; i < _palette->length; i++) {
writeStream->writeByte(pal[3 * i]);
- writeStream->seek(1, SEEK_CUR);
+ writeStream->writeByte(pal[3 * i]);
writeStream->writeByte(pal[3 * i + 1]);
- writeStream->seek(1, SEEK_CUR);
+ writeStream->writeByte(pal[3 * i + 1]);
writeStream->writeByte(pal[3 * i + 2]);
- writeStream->seek(1, SEEK_CUR);
+ writeStream->writeByte(pal[3 * i + 2]);
}
+
+ Common::DumpFile out;
+ char buf[256];
+ Common::sprintf_s(buf, "./dumps/%d-%s-%s", 0, tag2str(MKTAG('C', 'L', 'U', 'T')), "WrittenPalette");
+
+ // Write the movie out, stored in dumpData
+ if (out.open(buf, true)) {
+ out.write(dumpData, castSize);
+ out.flush();
+ out.close();
+ debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
+ } else {
+ warning("RIFXArchive::writeStream: Error saving the file %s", buf);
+ }
+ free(dumpData);
+ delete writeStream;
}
+// This function is called three separate times
+// first when writing this 'CASt' resource in memory map (in getCastResourceSize())
+// second when writing the 'CASt' resource itself (in getCastResourceSize())
+// and thirdly when we're writing the info size in the 'CASt' resource
+// All three times, it returns the same value, this could be more efficient
uint32 PaletteCastMember::getInfoSize() {
- // Need to find a way to find the info size
- return 0;
+ CastMemberInfo *ci = _cast->getCastMemberInfo(_castId);
+ if (!ci) {
+ return 0;
+ }
+
+ uint32 length = 0;
+
+ switch (ci->count) {
+ default:
+ debug("writeCastMemberInfo:: extra strings found, ignoring");
+ break;
+ case 15:
+ length += ci->unknownString7.size();
+ // fallthrough
+ case 14:
+ length += ci->unknownString6.size();
+ // fallthrough
+ case 13:
+ length += ci->unknownString5.size();
+ // fallthrough
+ case 12:
+ length += ci->unknownString4.size();
+ // fallthrough
+ case 11:
+ length += ci->unknownString3.size();
+ // fallthrough
+ case 10:
+ length += ci->unknownString2.size();
+ // fallthrough
+ case 9:
+ length += ci->unknownString1.size();
+ // fallthrough
+ case 8:
+ if (ci->textEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ // fallthrough
+ case 7:
+ if (ci->scriptStyle.fontId) {
+ length += 20; // The length of FontStyle
+ }
+ // fallthrough
+ case 6:
+ if (ci->scriptEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ // fallthrough
+ case 5:
+ length += ci->type.size();
+ // fallthrough
+ case 4:
+ length += ci->fileName.size();
+ // fallthrough
+ case 3:
+ length += ci->directory.size();
+ // fallthrough
+ case 2:
+ length += ci->name.size();
+ debug("at 2: length = %d, name: %s", ci->name.size(), ci->name.c_str());
+ // fallthrough
+ case 1:
+ length += ci->script.size();
+ debug("at 1: length = %d", ci->name.size());
+ // fallthrough
+ case 0:
+ break;
+ }
+
+ debug("Header size = 20, length: %d, ci->count: %d, (ci->count + 1) * 4: %d", length, ci->count, (ci->count + 1) *4);
+ // The header + total length of the strings + number of length entries for the strings
+ return 22 + length + (ci->count + 1) * 4;
}
+
uint32 PaletteCastMember::getDataSize() {
if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
return 0;
} else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- // Observed value, need to verify
- return 4;
+ if (_flags1 != 0xFF) {
+ return 3;
+ } else {
+ return 4;
+ }
}
+ return 0;
+}
+
+uint32 PaletteCastMember::getCastResourceSize(uint32 version) {
+ uint32 headerSize = 0;
+
+ if (version >= kFileVer400 && version < kFileVer500) {
+ headerSize = 9;
+ if (_flags1 != 0xFF) {
+ headerSize += 1;
+ }
+ } else if (version >= kFileVer500 && version < kFileVer600) {
+ headerSize = 12;
+ }
+
+ return headerSize + getInfoSize() + getDataSize();
+}
+
+uint32 PaletteCastMember::getPaletteDataSize() {
+ // This is the actual Palette data, in the 'CLUT' resource
+ // PaletteCastMembers data stored in the 'CLUT' resource does not change in size (may change in content) (need to verify)
+ // Hence their original size can be written
+ return _palette->length * 6;
}
} // End of namespace Director
diff --git a/engines/director/castmember/palette.h b/engines/director/castmember/palette.h
index 1d0afc23ee2..9f07d118011 100644
--- a/engines/director/castmember/palette.h
+++ b/engines/director/castmember/palette.h
@@ -43,10 +43,16 @@ public:
void load() override;
void unload() override;
- uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version) override;
+ uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castId) override;
void writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset);
- uint32 getInfoSize() override;
- uint32 getDataSize() override;
+
+ /* All three of following are part of 'CASt' Resource */
+ uint32 getInfoSize() override; // This is the size of the info in the 'CASt' resource
+ uint32 getDataSize() override; // This is the size of the data in the 'CASt' resource
+ uint32 getCastResourceSize(uint32 version) override; // This is the size of the entire 'CASt' resource
+
+ uint32 getPaletteDataSize();
+
PaletteV4 *_palette;
};
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 45b50f5c6d1..0c80af28a22 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -285,10 +285,10 @@ Common::Rect Movie::readRect(Common::ReadStreamEndian &stream) {
}
void Movie::writeRect(Common::MemoryWriteStream *writeStream, Common::Rect rect) {
- writeStream->writeSint16LE(rect.top);
- writeStream->writeSint16LE(rect.left);
- writeStream->writeSint16LE(rect.bottom);
- writeStream->writeSint16LE(rect.right);
+ writeStream->writeSint16BE(rect.top);
+ writeStream->writeSint16BE(rect.left);
+ writeStream->writeSint16BE(rect.bottom);
+ writeStream->writeSint16BE(rect.right);
}
InfoEntries Movie::loadInfoEntries(Common::SeekableReadStreamEndian &stream, uint16 version) {
Commit: 080edb9cbdbb496964cf348d607f4bcaa63bfe7d
https://github.com/scummvm/scummvm/commit/080edb9cbdbb496964cf348d607f4bcaa63bfe7d
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Write TextCastMember 'STXT' resource
Currently only encoding the text in MacRoman formatting
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember/palette.cpp
engines/director/castmember/text.cpp
engines/director/castmember/text.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 661d6234756..24ba96c4219 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -736,8 +736,7 @@ void Cast::loadCast() {
debugC(2, kDebugLoading, "****** Loading %d STXT resources", stxt.size());
for (auto &iterator : stxt) {
- _loadedStxts.setVal(iterator - _castIDoffset,
- new Stxt(this, *(r = _castArchive->getResource(MKTAG('S','T','X','T'), iterator))));
+ _loadedStxts.setVal(iterator - _castIDoffset, new Stxt(this, *(r = _castArchive->getResource(MKTAG('S','T','X','T'), iterator))));
debugC(3, kDebugText, "STXT: id %d", iterator - _castIDoffset);
delete r;
@@ -1066,6 +1065,85 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
}
}
+// This function is called three separate times
+// first when writing this 'CASt' resource in memory map (in getCastResourceSize())
+// second when writing the 'CASt' resource itself (in getCastResourceSize())
+// and thirdly when we're writing the info size in the 'CASt' resource
+// All three times, it returns the same value, this could be more efficient
+uint32 Cast::getCastInfoSize(uint32 castId) {
+ CastMemberInfo *ci = getCastMemberInfo(castId);
+ if (!ci) {
+ return 0;
+ }
+
+ uint32 length = 0;
+
+ switch (ci->count) {
+ default:
+ debug("writeCastMemberInfo:: extra strings found, ignoring");
+ break;
+ case 15:
+ length += ci->unknownString7.size();
+ // fallthrough
+ case 14:
+ length += ci->unknownString6.size();
+ // fallthrough
+ case 13:
+ length += ci->unknownString5.size();
+ // fallthrough
+ case 12:
+ length += ci->unknownString4.size();
+ // fallthrough
+ case 11:
+ length += ci->unknownString3.size();
+ // fallthrough
+ case 10:
+ length += ci->unknownString2.size();
+ // fallthrough
+ case 9:
+ length += ci->unknownString1.size();
+ // fallthrough
+ case 8:
+ if (ci->textEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ // fallthrough
+ case 7:
+ if (ci->scriptStyle.fontId) {
+ length += 20; // The length of FontStyle
+ }
+ // fallthrough
+ case 6:
+ if (ci->scriptEditInfo.version) {
+ length += 18; // The length of an edit info
+ }
+ // fallthrough
+ case 5:
+ length += ci->type.size();
+ // fallthrough
+ case 4:
+ length += ci->fileName.size();
+ // fallthrough
+ case 3:
+ length += ci->directory.size();
+ // fallthrough
+ case 2:
+ length += ci->name.size();
+ debug("at 2: length = %d, name: %s", ci->name.size(), ci->name.c_str());
+ // fallthrough
+ case 1:
+ length += ci->script.size();
+ debug("at 1: length = %d", ci->name.size());
+ // fallthrough
+ case 0:
+ break;
+ }
+
+ debug("Header size = 20, length: %d, ci->count: %d, (ci->count + 1) * 4: %d", length, ci->count, (ci->count + 1) *4);
+ // The header + total length of the strings + number of length entries for the strings
+ return 22 + length + (ci->count + 1) * 4;
+}
+
uint32 Cast::computeChecksum() {
warning("STUB::ConfigChunk::computeChecksum() is not implemented yet");
return 0;
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 338a4782eac..fcef398e706 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -110,6 +110,7 @@ public:
void saveCast();
void saveCastData();
void writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId);
+ uint32 getCastInfoSize(uint32 castId);
int getCastSize();
int getCastMaxID();
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index 1a509794cea..7d95d08b68b 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -32,7 +32,6 @@ namespace Director {
PaletteCastMember::PaletteCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version)
: CastMember(cast, castId, stream) {
- debug("In Palette Cast Member: stream: size: %d", stream.size());
stream.hexdump(stream.size());
_type = kCastPalette;
_palette = nullptr;
@@ -159,7 +158,7 @@ uint32 PaletteCastMember::writeCAStResource(Common::MemoryWriteStream *writeStre
// For cast members with dedicated resrouces for data, the castDataToWrite is zero
// So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
if (castDataToWrite) {
- writePaletteData(writeStream, writeStream->pos());
+ // writeCastData(writeStream, writeStream->pos());
}
if (castInfoToWrite) {
@@ -177,7 +176,7 @@ uint32 PaletteCastMember::writeCAStResource(Common::MemoryWriteStream *writeStre
// For cast members with dedicated resrouces for data, the castDataToWrite is zero
// So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
if (castDataToWrite) {
- writePaletteData(writeStream, writeStream->pos());
+ // writeCastData();
}
}
@@ -212,7 +211,7 @@ void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream,
Common::DumpFile out;
char buf[256];
- Common::sprintf_s(buf, "./dumps/%d-%s-%s", 0, tag2str(MKTAG('C', 'L', 'U', 'T')), "WrittenPalette");
+ Common::sprintf_s(buf, "./dumps/%d-%s-%s", _castId, tag2str(MKTAG('C', 'L', 'U', 'T')), "WrittenPalette");
// Write the movie out, stored in dumpData
if (out.open(buf, true)) {
@@ -227,83 +226,8 @@ void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream,
delete writeStream;
}
-// This function is called three separate times
-// first when writing this 'CASt' resource in memory map (in getCastResourceSize())
-// second when writing the 'CASt' resource itself (in getCastResourceSize())
-// and thirdly when we're writing the info size in the 'CASt' resource
-// All three times, it returns the same value, this could be more efficient
uint32 PaletteCastMember::getInfoSize() {
- CastMemberInfo *ci = _cast->getCastMemberInfo(_castId);
- if (!ci) {
- return 0;
- }
-
- uint32 length = 0;
-
- switch (ci->count) {
- default:
- debug("writeCastMemberInfo:: extra strings found, ignoring");
- break;
- case 15:
- length += ci->unknownString7.size();
- // fallthrough
- case 14:
- length += ci->unknownString6.size();
- // fallthrough
- case 13:
- length += ci->unknownString5.size();
- // fallthrough
- case 12:
- length += ci->unknownString4.size();
- // fallthrough
- case 11:
- length += ci->unknownString3.size();
- // fallthrough
- case 10:
- length += ci->unknownString2.size();
- // fallthrough
- case 9:
- length += ci->unknownString1.size();
- // fallthrough
- case 8:
- if (ci->textEditInfo.version) {
- length += 18; // The length of an edit info
- }
- // fallthrough
- case 7:
- if (ci->scriptStyle.fontId) {
- length += 20; // The length of FontStyle
- }
- // fallthrough
- case 6:
- if (ci->scriptEditInfo.version) {
- length += 18; // The length of an edit info
- }
- // fallthrough
- case 5:
- length += ci->type.size();
- // fallthrough
- case 4:
- length += ci->fileName.size();
- // fallthrough
- case 3:
- length += ci->directory.size();
- // fallthrough
- case 2:
- length += ci->name.size();
- debug("at 2: length = %d, name: %s", ci->name.size(), ci->name.c_str());
- // fallthrough
- case 1:
- length += ci->script.size();
- debug("at 1: length = %d", ci->name.size());
- // fallthrough
- case 0:
- break;
- }
-
- debug("Header size = 20, length: %d, ci->count: %d, (ci->count + 1) * 4: %d", length, ci->count, (ci->count + 1) *4);
- // The header + total length of the strings + number of length entries for the strings
- return 22 + length + (ci->count + 1) * 4;
+ return _cast->getCastInfoSize(_castId);
}
uint32 PaletteCastMember::getDataSize() {
@@ -338,6 +262,7 @@ uint32 PaletteCastMember::getPaletteDataSize() {
// This is the actual Palette data, in the 'CLUT' resource
// PaletteCastMembers data stored in the 'CLUT' resource does not change in size (may change in content) (need to verify)
// Hence their original size can be written
+ // This is the length of the 'CLUT' resource without the header and size
return _palette->length * 6;
}
diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index 4da9ee5eb11..9054e6ca796 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -20,6 +20,9 @@
*/
#include "common/events.h"
+#include "common/substream.h"
+#include "common/macresman.h"
+#include "common/memstream.h"
#include "graphics/macgui/macbutton.h"
#include "graphics/macgui/macwindow.h"
@@ -259,6 +262,8 @@ void TextCastMember::setForeColor(uint32 fgCol, int start, int end) {
void TextCastMember::importStxt(const Stxt *stxt) {
_fontId = stxt->_style.fontId;
+ _height = stxt->_style.height;
+ _ascent = stxt->_style.ascent;
_textSlant = stxt->_style.textSlant;
_fontSize = stxt->_style.fontSize;
_fgpalinfo1 = stxt->_style.r;
@@ -944,4 +949,158 @@ bool TextCastMember::setChunkField(int field, int start, int end, const Datum &d
return false;
}
+uint32 TextCastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castIndex) {
+ uint32 castResourceSize = getCastResourceSize(version);
+
+ writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
+ writeStream->writeUint32LE(castResourceSize); // this is excluding the 'CASt' header and the size itself (- 8 bytes)
+
+ uint32 castDataToWrite = getDataSize();
+ uint32 castInfoToWrite = getInfoSize();
+
+ if (version >= kFileVer400 && version < kFileVer500) {
+ writeStream->writeUint16BE(castDataToWrite);
+ writeStream->writeUint32BE(castInfoToWrite);
+ writeStream->writeByte(_castType);
+
+ if (_flags1 != 0xFF) { // In case of TextCastMember, this should be true
+ writeStream->writeByte(_flags1);
+ }
+
+ // For cast members with dedicated resources for data, the castDataToWrite is zero
+ // So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
+ if (castDataToWrite) {
+ }
+
+ if (castInfoToWrite) {
+ _cast->writeCastInfo(writeStream, _castId);
+ }
+ } else if (version >= kFileVer500 && version < kFileVer600) {
+ writeStream->writeUint32BE(_castType);
+ writeStream->writeUint32BE(castInfoToWrite);
+ writeStream->writeUint32BE(castDataToWrite);
+
+ if (castInfoToWrite) {
+ _cast->writeCastInfo(writeStream, _castId);
+ }
+
+ // For cast members with dedicated resrouces for data, the castDataToWrite is zero
+ // So for Text Cast Member, the castDataToWrite is not zero
+ // Its metadata is stored in this 'CASt' resource but it also has an child 'STXT' resource
+ if (castDataToWrite) {
+ writeCastData(writeStream, writeStream->pos());
+ }
+ }
+ load();
+ writeSTXTResource(nullptr, 0);
+ return castResourceSize + 8;
+}
+
+void TextCastMember::writeCastData(Common::MemoryWriteStream *writeStream, uint64 offset) {
+ writeStream->seek(offset);
+
+ writeStream->writeByte(_borderSize);
+ writeStream->writeByte(_gutterSize);
+ writeStream->writeByte(_boxShadow);
+ writeStream->writeByte(_textType);
+ writeStream->writeByte(_textAlign);
+ writeStream->writeSint16LE(_textAlign);
+ writeStream->writeUint16LE(_bgpalinfo1);
+ writeStream->writeUint16LE(_bgpalinfo2);
+ writeStream->writeUint16LE(_bgpalinfo3);
+ writeStream->writeUint16LE(_scroll);
+
+ Movie::writeRect(writeStream, _initialRect);
+ writeStream->writeUint16LE(_maxHeight);
+ writeStream->writeByte(_textShadow);
+ writeStream->writeByte(_textFlags);
+
+ writeStream->writeUint16LE(_textHeight);
+
+ if (_type == kCastButton) {
+ writeStream->writeUint16LE(_buttonType + 1);
+ }
}
+
+uint32 TextCastMember::getInfoSize() {
+ return _cast->getCastInfoSize(_castId);
+}
+
+uint32 TextCastMember::getDataSize() {
+ // Need to verify if this changes, current observation: it doesn't
+ return (_type == kCastButton) ? 31 : 29;
+}
+
+uint32 TextCastMember::getCastResourceSize(uint32 version) {
+ uint32 headerSize = 0;
+
+ if (version >= kFileVer400 && version < kFileVer500) {
+ headerSize = 9;
+ if (_flags1 != 0xFF) {
+ headerSize += 1;
+ }
+ } else if (version >= kFileVer500 && version < kFileVer600) {
+ headerSize = 12;
+ }
+
+ return headerSize + getInfoSize() + getDataSize();
+}
+
+uint32 TextCastMember::writeSTXTResource(Common::MemoryWriteStream *writeStream, uint32 offset) {
+ uint32 castSize = getSTXTResourceSize() + 10;
+ byte *dumpData = nullptr;
+ dumpData = (byte *)calloc(castSize, sizeof(byte));
+
+ writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
+
+ writeStream->seek(offset);
+
+ writeStream->writeUint32BE(MKTAG('S', 'T', 'X', 'T'));
+ writeStream->writeUint32BE(getSTXTResourceSize() + 8); // Size of the STXT resource without the header and size
+
+ writeStream->writeUint32BE(12); // This is the offset, if it's not 12, we throw an error and exit ScummVM
+ writeStream->writeUint32BE(_ptext.size());
+ // Encode only in one format, original may be encoded in multiple formats
+ // Size of one Font Style is 20 + The number of encodings takes 2 bytes
+ writeStream->writeUint32BE(20 + 2);
+ writeStream->writeString(_ptext.encode(Common::kMacRoman)); // Currently using MacRoman encoding only, may change later to include others
+
+ writeStream->writeUint16BE(1); // Only one formatting: MacRoman
+
+ writeStream->writeUint32BE(0); // FontStyle::formatStartOffset
+ writeStream->writeUint16BE(_height); // FontStyle::height // Apparently height doesn't matter
+ writeStream->writeUint16BE(_ascent); // FontStyle::ascent // And neither does ascent
+
+ writeStream->writeUint16BE(_fontId); // FontStyle::fontId
+ writeStream->writeByte(_textSlant); // FontStyle::textSlant
+ writeStream->writeByte(0); // padding
+ writeStream->writeUint16BE(_fontSize); // FontStyle::fontSize
+
+ writeStream->writeUint16BE(_fgpalinfo1); // FontStyle:r
+ writeStream->writeUint16BE(_fgpalinfo2); // FontStyle:g
+ writeStream->writeUint16BE(_fgpalinfo3); // FontStyle:b
+
+ Common::DumpFile out;
+ char buf[256];
+ Common::sprintf_s(buf, "./dumps/%d-%s-%s", _castId, tag2str(MKTAG('S', 'T', 'X', 'T')), "WrittenSTXTResource");
+
+ // Write the movie out, stored in dumpData
+ if (out.open(buf, true)) {
+ out.write(dumpData, castSize);
+ out.flush();
+ out.close();
+ debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
+ } else {
+ warning("RIFXArchive::writeStream: Error saving the file %s", buf);
+ }
+ free(dumpData);
+ delete writeStream;
+ return getSTXTResourceSize() + 8;
+}
+
+uint32 TextCastMember::getSTXTResourceSize() {
+ // Header (offset, string length, data length) + text string + data (FontStyle)
+ return 12 + _ptext.size() + 22;
+}
+
+} // End of namespace Director
diff --git a/engines/director/castmember/text.h b/engines/director/castmember/text.h
index 21319deaf7a..960b201f5c6 100644
--- a/engines/director/castmember/text.h
+++ b/engines/director/castmember/text.h
@@ -92,6 +92,16 @@ public:
void load() override;
void unload() override;
+ uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castId) override;
+ void writeCastData(Common::MemoryWriteStream *writeStream, uint64 offset);
+ uint32 writeSTXTResource(Common::MemoryWriteStream *writeStream, uint32 offset);
+
+ /* All three of following are part of 'CASt' Resource */
+ uint32 getInfoSize() override; // This is the size of the info in the 'CASt' resource
+ uint32 getDataSize() override; // This is the size of the data in the 'CASt' resource
+ uint32 getCastResourceSize(uint32 version) override; // This is the size of the entire 'CASt' resource
+ uint32 getSTXTResourceSize();
+
uint8 _borderSize;
uint8 _gutterSize;
uint8 _boxShadow;
@@ -99,6 +109,8 @@ public:
uint16 _textHeight;
uint32 _fontId;
+ uint16 _height;
+ uint16 _ascent;
uint16 _fontSize;
TextType _textType;
TextAlignType _textAlign;
Commit: dc9f94b541f86ebdd34e5bafa8e125ce5446ff2f
https://github.com/scummvm/scummvm/commit/dc9f94b541f86ebdd34e5bafa8e125ce5446ff2f
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Move writeCAStResource() to base class CastMember
The CASt resource differs in individual CastMembers only at data
The rest is common for each CastMember hence move the writing function
to base class and only handle the data writing in individual
CastMembers
Changed paths:
engines/director/archive.cpp
engines/director/cast.cpp
engines/director/castmember/bitmap.cpp
engines/director/castmember/bitmap.h
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
engines/director/castmember/palette.cpp
engines/director/castmember/palette.h
engines/director/castmember/text.cpp
engines/director/castmember/text.h
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index c28db0cfa44..9ad99e4fe5d 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -1210,7 +1210,9 @@ bool RIFXArchive::writeToFile(Common::Path path) {
int32 keyTag = MKTAG('K', 'E', 'Y', '*');
if (hasResource(keyTag, -1)) {
uint16 firstID = getResourceIDList(keyTag)[0];
- uint32 offset = getOffset(keyTag, firstID) + 8; // The +8 is consistent with RIFXArchive::getResource()
+ // The +8 is consistent with RIFXArchive::getResource()
+ // The +8 is to ignore the resource tag (e.g. 'KEY*') and the size entry
+ uint32 offset = getOffset(keyTag, firstID) + 8;
writeKeyTable(writeStream, offset);
}
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 24ba96c4219..e4a01c91a0b 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -828,8 +828,12 @@ void Cast::saveCast() {
if (_loadedCast->contains(id)) {
CastMember *target = _loadedCast->getVal(id);
- castSize = target->getCastResourceSize(_version) + 8;
+ // To make it consistent with how the data is stored originally, getResourceSize returns
+ // the size excluding 'CASt' header and the entry for size itself. Adding 8 to compensate for that
+ castSize = target->getCastResourceSize() + 8;
} else {
+ // The size stored in the memory map (_resources array), as well as the resource itself is the size
+ // excluding the 'CASt' header and the entry of size itself. Adding 8 to compensate for that
castSize = _castArchive->getResourceSize(MKTAG('C', 'A', 'S', 't'), it) + 8;
}
@@ -843,7 +847,18 @@ void Cast::saveCast() {
writeStream->writeStream(stream);
} else {
CastMember *target = _loadedCast->getVal(id);
- target->writeCAStResource(writeStream, 0, _version, it);
+
+ switch (target->_type) {
+ case (kCastPalette):
+ case (kCastBitmap):
+ case (kCastText):
+ case (kCastButton):
+ target->writeCAStResource(writeStream, 0);
+ break;
+ default:
+ target->writeCAStResource(writeStream, 0, it);
+ break;
+ }
}
Common::DumpFile out;
@@ -878,7 +893,7 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
writeStream->writeUint32BE(ci->scriptId);
- writeStream->writeUint16BE(ci->count);
+ writeStream->writeUint16BE(ci->count); // count of strings in the info
uint32 length = 0;
writeStream->writeUint32BE(length);
@@ -1362,8 +1377,6 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
// IDs are stored as relative to the start of the cast array.
id += _castArrayStart;
- uint32 size = stream.size() + 8;
-
// D4+ variant
if (stream.size() == 0)
return;
@@ -1497,10 +1510,7 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
break;
}
if (target) {
- target->_castResourceSize = size;
target->_castDataSize = castDataSize;
- target->_castInfoSize = castInfoSize;
- target->_castType = castType;
target->_flags1 = flags1;
setCastMember(id, target);
}
diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index 2b625c9f0fb..87e9e0fd6b6 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -21,6 +21,9 @@
#include "common/config-manager.h"
#include "common/macresman.h"
+#include "common/substream.h"
+#include "common/macresman.h"
+#include "common/memstream.h"
#include "graphics/surface.h"
#include "graphics/macgui/macwidget.h"
#include "image/bmp.h"
@@ -973,4 +976,32 @@ bool BitmapCastMember::setField(int field, const Datum &d) {
return CastMember::setField(field, d);
}
+uint32 BitmapCastMember::getCastDataSize() {
+ uint32 dataSize = 22;
+
+ if (_bitsPerPixel != 0) {
+ dataSize += 6;
+ if (_cast->_version >= kFileVer500) {
+ dataSize += 2;
+ }
+
+ if (_clut.member != 0) {
+ dataSize += 16;
+ }
+ }
+ return dataSize;
+}
+
+void BitmapCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ writeStream->writeUint32LE(_pitch);
+
+ Movie::writeRect(writeStream, _initialRect);
+ Movie::writeRect(writeStream, _boundingRect);
+
+ writeStream->writeUint16LE(_regY);
+ writeStream->writeUint16LE(_regX);
+
+}
+
} // End of namespace Director
+
\ No newline at end of file
diff --git a/engines/director/castmember/bitmap.h b/engines/director/castmember/bitmap.h
index 2538b7e67e6..5487cf62638 100644
--- a/engines/director/castmember/bitmap.h
+++ b/engines/director/castmember/bitmap.h
@@ -64,6 +64,10 @@ public:
CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
+
+ uint32 getCastDataSize() override; // This is the size of the data in the 'CASt' resource
+
Picture *_picture = nullptr;
Graphics::Surface *_ditheredImg;
Graphics::Surface *_matte;
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 81d2d88eb58..1215b91a045 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -314,7 +314,8 @@ void CastMember::unload() {
// Whereas _info_ is metadata (size, name, flags, etc.)
// Some castmembers have their _data_ as well as _info_ in this very 'CASt' resource, e.g. TextCastMember
// Whereas some other have their _info_ in a 'CASt' resource and _data_ in a dedicated resource (e.g. PaletteCastMember has 'CLUT' resource)
-uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castIndex) {
+
+uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 castIndex) {
// We'll need the original resource stream if there is no change in the castmember
Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), castIndex);
uint32 size = stream->size();
@@ -326,22 +327,90 @@ uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uin
return size + 8;
}
+uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset) {
+ uint32 castResourceSize = getCastResourceSize();
+
+ writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
+ writeStream->writeUint32LE(castResourceSize); // this is excluding the 'CASt' header and the size itself (- 8 bytes)
+
+ uint32 castDataToWrite = getCastDataSize();
+ uint32 castInfoToWrite = getCastInfoSize();
+
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ writeStream->writeUint16BE(castDataToWrite);
+ writeStream->writeUint32BE(castInfoToWrite);
+ writeStream->writeByte((uint8)_type);
+ castDataToWrite -= 1;
+
+ if (_flags1 != 0xFF) { // In case of TextCastMember, this should be true
+ writeStream->writeByte(_flags1);
+ castDataToWrite -= 1;
+ }
+
+ // For cast members with dedicated resources for data, the castDataToWrite is zero
+ if (castDataToWrite) {
+ writeCastData(writeStream);
+ }
+
+ if (castInfoToWrite) {
+ _cast->writeCastInfo(writeStream, _castId);
+ }
+ } else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ writeStream->writeUint32BE((uint32)_type);
+ writeStream->writeUint32BE(castInfoToWrite);
+ writeStream->writeUint32BE(castDataToWrite);
+
+ if (castInfoToWrite) {
+ _cast->writeCastInfo(writeStream, _castId);
+ }
+
+ // For cast members with dedicated resrouces for data, the castDataToWrite is zero
+ if (castDataToWrite) {
+ writeCastData(writeStream);
+ }
+ }
+ return 0;
+}
+
// This is the data that is inside the 'CASt' resource
-uint32 CastMember::getDataSize() {
- debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size, returning original size.");
+uint32 CastMember::getCastDataSize() {
+ debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size, this is not supposed to be called");
return _castDataSize;
}
+void CastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data, this is not supposed to be called");
+
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ if (_flags1 != 0xFF) {
+ writeStream->write(0, _castDataSize - 2);
+ } else {
+ writeStream->write(0, _castDataSize - 1);
+ }
+ } else {
+ writeStream->write(0, _castDataSize);
+ }
+}
+
// This is the info that is inside the 'CASt' resource
-uint32 CastMember::getInfoSize() {
- debug("CastMember::getInfoSize(): Defualt implementation of 'CASt' resource info size, returning original size.");
- return _castInfoSize;
+uint32 CastMember::getCastInfoSize() {
+ return _cast->getCastInfoSize(_castId);
}
// getCastResourceSize only returns the size of the resource without the header
-uint32 CastMember::getCastResourceSize(uint32 version) {
- debug("CastMember::getInfoSize(): Defualt implementation of 'CASt' resource size, returning original size.");
- return _castResourceSize;
+uint32 CastMember::getCastResourceSize() {
+ uint32 headerSize = 0;
+
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ headerSize = 9;
+ if (_flags1 != 0xFF) {
+ headerSize += 1;
+ }
+ } else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ headerSize = 12;
+ }
+
+ return headerSize + getCastInfoSize() + getCastDataSize();
}
} // End of namespace Director
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index e5768fc24f4..d7d50c03cfa 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -101,10 +101,12 @@ public:
virtual CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) { return bbox.contains(pos) ? kCollisionYes : kCollisionNo; }
- virtual uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castId);
- virtual uint32 getDataSize();
- virtual uint32 getInfoSize();
- virtual uint32 getCastResourceSize(uint32 version);
+ uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 castIndex);
+ uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset);
+ uint32 getCastInfoSize();
+ uint32 getCastResourceSize();
+ virtual void writeCastData(Common::MemoryWriteStream *writeStream);
+ virtual uint32 getCastDataSize();
CastType _type;
Common::Rect _initialRect;
@@ -118,9 +120,6 @@ public:
/* Data fields used when saving the Cast Member */
uint32 _castDataSize;
- uint32 _castInfoSize;
- uint32 _castResourceSize;
- uint32 _castType;
uint8 _flags1;
protected:
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index 7d95d08b68b..10bb7fb395f 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -137,54 +137,6 @@ void PaletteCastMember::unload() {
// No unload necessary.
}
-uint32 PaletteCastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 id) {
- uint32 castResourceSize = getCastResourceSize(version);
-
- writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
- writeStream->writeUint32LE(castResourceSize); // this is excluding the 'CASt' header and the size itself (- 8 bytes)
-
- uint32 castDataToWrite = getDataSize();
- uint32 castInfoToWrite = getInfoSize();
-
- if (version >= kFileVer400 && version < kFileVer500) {
- writeStream->writeUint16BE(castDataToWrite);
- writeStream->writeUint32BE(castInfoToWrite);
- writeStream->writeByte(_castType);
-
- if (_flags1 != 0xFF) {
- writeStream->writeByte(_flags1);
- }
-
- // For cast members with dedicated resrouces for data, the castDataToWrite is zero
- // So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
- if (castDataToWrite) {
- // writeCastData(writeStream, writeStream->pos());
- }
-
- if (castInfoToWrite) {
- _cast->writeCastInfo(writeStream, _castId);
- }
- } else if (version >= kFileVer500 && version < kFileVer600) {
- writeStream->writeUint32BE(_castType);
- writeStream->writeUint32BE(castInfoToWrite);
- writeStream->writeUint32BE(castDataToWrite);
-
- if (castInfoToWrite) {
- _cast->writeCastInfo(writeStream, _castId);
- }
-
- // For cast members with dedicated resrouces for data, the castDataToWrite is zero
- // So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
- if (castDataToWrite) {
- // writeCastData();
- }
- }
-
- writePaletteData(nullptr, 0);
-
- return castResourceSize + 8;
-}
-
void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset) {
uint32 castSize = getPaletteDataSize() + 8;
byte *dumpData = nullptr;
@@ -226,11 +178,8 @@ void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream,
delete writeStream;
}
-uint32 PaletteCastMember::getInfoSize() {
- return _cast->getCastInfoSize(_castId);
-}
-
-uint32 PaletteCastMember::getDataSize() {
+// This is the data in 'CASt' resource
+uint32 PaletteCastMember::getCastDataSize() {
if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
return 0;
} else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
@@ -243,21 +192,6 @@ uint32 PaletteCastMember::getDataSize() {
return 0;
}
-uint32 PaletteCastMember::getCastResourceSize(uint32 version) {
- uint32 headerSize = 0;
-
- if (version >= kFileVer400 && version < kFileVer500) {
- headerSize = 9;
- if (_flags1 != 0xFF) {
- headerSize += 1;
- }
- } else if (version >= kFileVer500 && version < kFileVer600) {
- headerSize = 12;
- }
-
- return headerSize + getInfoSize() + getDataSize();
-}
-
uint32 PaletteCastMember::getPaletteDataSize() {
// This is the actual Palette data, in the 'CLUT' resource
// PaletteCastMembers data stored in the 'CLUT' resource does not change in size (may change in content) (need to verify)
@@ -266,4 +200,8 @@ uint32 PaletteCastMember::getPaletteDataSize() {
return _palette->length * 6;
}
+void PaletteCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+
+}
+
} // End of namespace Director
diff --git a/engines/director/castmember/palette.h b/engines/director/castmember/palette.h
index 9f07d118011..d62cacd9142 100644
--- a/engines/director/castmember/palette.h
+++ b/engines/director/castmember/palette.h
@@ -43,14 +43,10 @@ public:
void load() override;
void unload() override;
- uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castId) override;
void writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset);
- /* All three of following are part of 'CASt' Resource */
- uint32 getInfoSize() override; // This is the size of the info in the 'CASt' resource
- uint32 getDataSize() override; // This is the size of the data in the 'CASt' resource
- uint32 getCastResourceSize(uint32 version) override; // This is the size of the entire 'CASt' resource
-
+ uint32 getCastDataSize() override; // This is the size of the data in the 'CASt' resource
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
uint32 getPaletteDataSize();
PaletteV4 *_palette;
@@ -59,3 +55,4 @@ public:
} // End of namespace Director
#endif
+
\ No newline at end of file
diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index 9054e6ca796..2dab071af01 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -949,56 +949,7 @@ bool TextCastMember::setChunkField(int field, int start, int end, const Datum &d
return false;
}
-uint32 TextCastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castIndex) {
- uint32 castResourceSize = getCastResourceSize(version);
-
- writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
- writeStream->writeUint32LE(castResourceSize); // this is excluding the 'CASt' header and the size itself (- 8 bytes)
-
- uint32 castDataToWrite = getDataSize();
- uint32 castInfoToWrite = getInfoSize();
-
- if (version >= kFileVer400 && version < kFileVer500) {
- writeStream->writeUint16BE(castDataToWrite);
- writeStream->writeUint32BE(castInfoToWrite);
- writeStream->writeByte(_castType);
-
- if (_flags1 != 0xFF) { // In case of TextCastMember, this should be true
- writeStream->writeByte(_flags1);
- }
-
- // For cast members with dedicated resources for data, the castDataToWrite is zero
- // So for Palette Cast Member, the castDataToWrite is zero because it has a dedicated 'CLUT' resource for data
- if (castDataToWrite) {
- }
-
- if (castInfoToWrite) {
- _cast->writeCastInfo(writeStream, _castId);
- }
- } else if (version >= kFileVer500 && version < kFileVer600) {
- writeStream->writeUint32BE(_castType);
- writeStream->writeUint32BE(castInfoToWrite);
- writeStream->writeUint32BE(castDataToWrite);
-
- if (castInfoToWrite) {
- _cast->writeCastInfo(writeStream, _castId);
- }
-
- // For cast members with dedicated resrouces for data, the castDataToWrite is zero
- // So for Text Cast Member, the castDataToWrite is not zero
- // Its metadata is stored in this 'CASt' resource but it also has an child 'STXT' resource
- if (castDataToWrite) {
- writeCastData(writeStream, writeStream->pos());
- }
- }
- load();
- writeSTXTResource(nullptr, 0);
- return castResourceSize + 8;
-}
-
-void TextCastMember::writeCastData(Common::MemoryWriteStream *writeStream, uint64 offset) {
- writeStream->seek(offset);
-
+void TextCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
writeStream->writeByte(_borderSize);
writeStream->writeByte(_gutterSize);
writeStream->writeByte(_boxShadow);
@@ -1022,30 +973,11 @@ void TextCastMember::writeCastData(Common::MemoryWriteStream *writeStream, uint6
}
}
-uint32 TextCastMember::getInfoSize() {
- return _cast->getCastInfoSize(_castId);
-}
-
-uint32 TextCastMember::getDataSize() {
- // Need to verify if this changes, current observation: it doesn't
+uint32 TextCastMember::getCastDataSize() {
+ // Need to verify if this changes, current observation
return (_type == kCastButton) ? 31 : 29;
}
-uint32 TextCastMember::getCastResourceSize(uint32 version) {
- uint32 headerSize = 0;
-
- if (version >= kFileVer400 && version < kFileVer500) {
- headerSize = 9;
- if (_flags1 != 0xFF) {
- headerSize += 1;
- }
- } else if (version >= kFileVer500 && version < kFileVer600) {
- headerSize = 12;
- }
-
- return headerSize + getInfoSize() + getDataSize();
-}
-
uint32 TextCastMember::writeSTXTResource(Common::MemoryWriteStream *writeStream, uint32 offset) {
uint32 castSize = getSTXTResourceSize() + 10;
byte *dumpData = nullptr;
@@ -1063,7 +995,9 @@ uint32 TextCastMember::writeSTXTResource(Common::MemoryWriteStream *writeStream,
// Encode only in one format, original may be encoded in multiple formats
// Size of one Font Style is 20 + The number of encodings takes 2 bytes
writeStream->writeUint32BE(20 + 2);
- writeStream->writeString(_ptext.encode(Common::kMacRoman)); // Currently using MacRoman encoding only, may change later to include others
+
+ Common::CodePage encoding = detectFontEncoding(_cast->_platform, _fontId);
+ writeStream->writeString(_ptext.encode(encoding)); // Currently using MacRoman encoding only, may change later to include others
writeStream->writeUint16BE(1); // Only one formatting: MacRoman
diff --git a/engines/director/castmember/text.h b/engines/director/castmember/text.h
index 960b201f5c6..a813b93e7b7 100644
--- a/engines/director/castmember/text.h
+++ b/engines/director/castmember/text.h
@@ -92,14 +92,10 @@ public:
void load() override;
void unload() override;
- uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 version, uint32 castId) override;
- void writeCastData(Common::MemoryWriteStream *writeStream, uint64 offset);
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
uint32 writeSTXTResource(Common::MemoryWriteStream *writeStream, uint32 offset);
- /* All three of following are part of 'CASt' Resource */
- uint32 getInfoSize() override; // This is the size of the info in the 'CASt' resource
- uint32 getDataSize() override; // This is the size of the data in the 'CASt' resource
- uint32 getCastResourceSize(uint32 version) override; // This is the size of the entire 'CASt' resource
+ uint32 getCastDataSize() override; // This is the size of the data in the 'CASt' resource
uint32 getSTXTResourceSize();
uint8 _borderSize;
Commit: c49b627c2de29a9153544b6ca8431a99fb468ce7
https://github.com/scummvm/scummvm/commit/c49b627c2de29a9153544b6ca8431a99fb468ce7
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: saveInfoEntries(), helper dumpFile() and kDebugSaving
To quickly dump files and to help debugging while saving files
Add a new debugging channel: kDebugSaving
Add comments
Move the writing of CastInfo functionality to Movie to make it
symmetric with loading of Info entries
Changed paths:
engines/director/archive.cpp
engines/director/archive.h
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
engines/director/castmember/palette.cpp
engines/director/detection.cpp
engines/director/director.cpp
engines/director/director.h
engines/director/movie.cpp
engines/director/movie.h
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 9ad99e4fe5d..399239070eb 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -1283,7 +1283,7 @@ bool RIFXArchive::writeMemoryMap(Common::SeekableMemoryWriteStream *writeStream)
writeStream->writeUint32LE(0);
for (auto &it : _resources) {
- debugC(3, kDebugLoading, "Writing RIFX Resource: tag: %s, size: %d, offset: %08x, flags: %x, unk1: %x, nextFreeResourceID: %d",
+ debugC(3, kDebugSaving, "Writing RIFX Resource: tag: %s, size: %d, offset: %08x, flags: %x, unk1: %x, nextFreeResourceID: %d",
tag2str(it->tag), it->size, it->offset, it->flags, it->unk1, it->nextFreeResourceID);
// Write down the tag, the size and offset of the current resource
@@ -1343,7 +1343,7 @@ bool RIFXArchive::writeKeyTable(Common::SeekableMemoryWriteStream *writeStream,
KeyArray keyArray = parentIndex._value;
for (auto childIndex : keyArray) {
- debugC(3, kDebugLoading, "RIFXArchive::writeKeyTable: _keyData contains tag: %s, parentIndex: %d, childIndex: %d", tag2str(childTag._key), parentIndex._key, childIndex);
+ debugC(3, kDebugSaving, "RIFXArchive::writeKeyTable: _keyData contains tag: %s, parentIndex: %d, childIndex: %d", tag2str(childTag._key), parentIndex._key, childIndex);
writeStream->writeUint32LE(childIndex);
writeStream->writeUint32LE(parentIndex._key);
writeStream->writeUint32LE(childTag._key);
@@ -1368,4 +1368,20 @@ bool RIFXArchive::writeCast(Common::SeekableWriteStream *writeStream, uint32 off
return true;
}
+void dumpFile(Common::String fileName, uint32 id, uint32 tag, byte *dumpData, uint32 dumpSize) {
+ debug("dumpFile():: dumping file %s, resource: %s (id: %d)", fileName.c_str(), tag2str(tag), id);
+ Common::DumpFile out;
+ Common::String fname = Common::String::format("./dumps/%d-%s-%s", id, tag2str(tag), fileName.c_str());
+
+ // Write the movie out, stored in dumpData
+ if (out.open(Common::Path(fname), true)) {
+ out.write(dumpData, dumpSize);
+ out.flush();
+ out.close();
+ } else {
+ warning("RIFXArchive::writeStream: Error saving the file %s", fname.c_str());
+ }
+ free(dumpData);
+}
+
} // End of namespace Director
diff --git a/engines/director/archive.h b/engines/director/archive.h
index 66dc7a1c364..6463c211529 100644
--- a/engines/director/archive.h
+++ b/engines/director/archive.h
@@ -240,6 +240,9 @@ private:
bool _isLoaded;
};
+
+void dumpFile(Common::String filename, uint32 id, uint32 tag, byte *dumpData, uint32 dumpSize);
+
} // End of namespace Director
#endif
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index e4a01c91a0b..286c065ff73 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -32,6 +32,7 @@
#include "video/qt_decoder.h"
#include "director/director.h"
+#include "director/archive.h"
#include "director/cast.h"
#include "director/movie.h"
#include "director/rte.h"
@@ -518,28 +519,17 @@ bool Cast::loadConfig() {
_vm->setVersion(humanVer);
}
- uint32 castSize = stream->size() + 8;
- byte *dumpData = nullptr;
- dumpData = (byte *)calloc(castSize, sizeof(byte));
+ if (debugChannelSet(7, kDebugSaving)) {
+ // Adding +8 because the stream doesn't include the header and the entry for the size itself
+ uint32 configSize = stream->size() + 8;
+ byte *dumpData = (byte *)calloc(configSize, sizeof(byte));
- Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
+ Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, configSize);
- saveConfig(writeStream, 0);
- Common::DumpFile out;
- char buf[256];
- Common::sprintf_s(buf, "./dumps/%d-%s-%s", 0, tag2str(MKTAG('V', 'W', 'C', 'F')), "WrittenConfig");
-
- // Write the movie out, stored in dumpData
- if (out.open(buf, true)) {
- out.write(dumpData, castSize);
- out.flush();
- out.close();
- debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
- } else {
- warning("RIFXArchive::writeStream: Error saving the file %s", buf);
- }
- free(dumpData);
- delete writeStream;
+ saveConfig(writeStream, 0);
+ dumpFile("ConfigData", 0, MKTAG('V', 'W', 'C', 'F'), dumpData, configSize);
+ delete writeStream;
+ }
delete stream;
return true;
@@ -801,7 +791,7 @@ void Cast::loadCast() {
debugC(4, kDebugLoading, "'SCRF' resource skipped");
}
- if (debugChannelSet(7, kDebugLoading)) {
+ if (debugChannelSet(7, kDebugSaving)) {
debug("Cast::saveCast: Saving the Cast resources in ./dumps");
saveCast();
}
@@ -822,8 +812,9 @@ void Cast::saveCast() {
// So, RIFXArchive::getResourceDetail will return the list of IDs present in the keytable
// Whereas, in the _loadedCast, the key of these Cast members is given by castId
for (auto &it : cast) {
+ // I need to call this just because I need the id
Resource res = _castArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), it);
- uint16 id = res.castId + _castArrayStart;
+ uint16 id = res.castId + _castArrayStart; // Never encountered _castArrayStart != 0 till now
uint32 castSize = 0;
if (_loadedCast->contains(id)) {
@@ -837,16 +828,20 @@ void Cast::saveCast() {
castSize = _castArchive->getResourceSize(MKTAG('C', 'A', 'S', 't'), it) + 8;
}
- byte *dumpData = nullptr;
- dumpData = (byte *)calloc(castSize, sizeof(byte));
+ byte *dumpData = (byte *)calloc(castSize, sizeof(byte));
Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
+ CastType type = kCastTypeAny;
- if (!_loadedCast->contains(id)) {
+ if (!_loadedCast->contains(id)) {
+ writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
Common::SeekableReadStreamEndian *stream = getResource(MKTAG('C', 'A', 'S', 't'), it);
+ uint32 size = stream->size(); // This is the size of the Resource without header and size entry itself
+ writeStream->writeUint32LE(size);
writeStream->writeStream(stream);
} else {
CastMember *target = _loadedCast->getVal(id);
+ type = target->_type;
switch (target->_type) {
case (kCastPalette):
@@ -861,223 +856,155 @@ void Cast::saveCast() {
}
}
- Common::DumpFile out;
- char buf[256];
- Common::sprintf_s(buf, "./dumps/%d-%s-%s", it, tag2str(res.tag), "WrittenCAStResource");
-
- // Write the movie out, stored in dumpData
- if (out.open(buf, true)) {
- out.write(dumpData, castSize);
- out.flush();
- out.close();
- debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
- } else {
- warning("RIFXArchive::writeStream: Error saving the file %s", buf);
- }
- free(dumpData);
+ dumpFile(castType2str(type), res.index, MKTAG('C', 'A', 'S', 't'), dumpData, castSize);
delete writeStream;
}
}
void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId) {
- if (!_castsInfo.contains(castId)) {
- return;
- }
- CastMemberInfo *ci = _castsInfo[castId];
-
- writeStream->writeUint32BE(20); // The offset post-d4 movies is always 20
- writeStream->writeUint32BE(ci->unk1);
- writeStream->writeUint32BE(ci->unk2);
- writeStream->writeUint32BE(ci->flags); // Possibly no need to save
-
- writeStream->writeUint32BE(ci->scriptId);
-
- writeStream->writeUint16BE(ci->count); // count of strings in the info
-
- uint32 length = 0;
- writeStream->writeUint32BE(length);
-
// The structure of the CastMemberInfo is as follows:
// First some headers: offset, unkonwns and flags, and then a count of strings to be read
// (These strings contain properties of the cast member like filename, script attached to it, name, etc.)
// After the header, we have the next data is the lengths of the strings,
// The first int is 0, the second int is 0 + length of the first string, the third int is 0 + length of first string + length of second string and so on
// After the lengths of the strings are the actual strings
- for (int i = 1; i <= ci->count; i++) {
- switch (i) {
- default:
- debug("writeCastMemberInfo:: extra strings found, ignoring");
- break;
-
- case 1:
- length += ci->script.size();
- writeStream->writeUint32BE(length);
- break;
-
- case 2:
- length += ci->name.size();
- writeStream->writeUint32BE(length);
- break;
-
- case 3:
- length += ci->directory.size();
- writeStream->writeUint32BE(length);
- break;
-
- case 4:
- length += ci->fileName.size();
- writeStream->writeUint32BE(length);
- break;
-
- case 5:
- length += ci->type.size();
- writeStream->writeUint32BE(length);
- break;
- case 6:
- if (ci->scriptEditInfo.version) {
- length += 18; // The length of an edit info
- }
- writeStream->writeUint32BE(length);
- break;
-
- case 7:
- if (ci->scriptStyle.fontId) {
- length += 20; // The length of FontStyle
- writeStream->writeUint32BE(length);
- }
- break;
-
- case 8:
- if (ci->textEditInfo.version) {
- length += 18; // The length of an edit info
- }
- writeStream->writeUint32BE(length);
- break;
-
- case 9:
- length += ci->unknownString1.size();
- writeStream->writeUint32BE(length);
- break;
-
- case 10:
- length += ci->unknownString2.size();
- writeStream->writeUint32BE(length);
- break;
+ if (!_castsInfo.contains(castId)) {
+ return;
+ }
+ CastMemberInfo *ci = _castsInfo[castId];
- case 11:
- length += ci->unknownString3.size();
- writeStream->writeUint32BE(length);
- break;
+ InfoEntries castInfo;
- case 12:
- length += ci->unknownString4.size();
- writeStream->writeUint32BE(length);
- break;
-
- case 13:
- length += ci->unknownString5.size();
- writeStream->writeUint32BE(length);
- break;
-
- case 14:
- length += ci->unknownString6.size();
- writeStream->writeUint32BE(length);
- break;
+ castInfo.unk1 = ci->unk1;
+ castInfo.unk2 = ci->unk2;
+ castInfo.flags = ci->flags;
+ castInfo.scriptId = ci->scriptId;
+ castInfo.strings.resize(ci->count);
- case 15:
- length += ci->unknownString7.size();
- writeStream->writeUint32BE(length);
- break;
- }
+ for (int i = 1; i <= ci->count; i++) {
+ castInfo.strings[i - 1].len += getCastInfoStringLength(i, ci);
}
for (int i = 1; i <= ci->count; i++) {
+ if (!castInfo.strings[i - 1].len) {
+ continue;
+ }
+
switch (i) {
default:
- debug("writeCastMemberInfo::extra strings found, ignoring");
+ debug("Cast::writeCastInfo()::extra strings found, ignoring");
break;
case 1:
- writeStream->writeString(ci->script);
+ castInfo.strings[0].data = (byte *)malloc(castInfo.strings[0].len);
+ memcpy(castInfo.strings[0].data, ci->script.c_str(), castInfo.strings[0].len);
break;
case 2:
- writeStream->writeString(ci->name);
+ castInfo.strings[1].data = (byte *)malloc(castInfo.strings[1].len);
+ memcpy(castInfo.strings[1].data, ci->name.c_str(), castInfo.strings[1].len);
break;
case 3:
- writeStream->writeString(ci->directory);
+ castInfo.strings[2].data = (byte *)malloc(castInfo.strings[2].len);
+ memcpy(castInfo.strings[2].data, ci->directory.c_str(), castInfo.strings[2].len);
break;
case 4:
- writeStream->writeString(ci->fileName);
+ castInfo.strings[3].data = (byte *)malloc(castInfo.strings[3].len);
+ memcpy(castInfo.strings[3].data, ci->fileName.c_str(), castInfo.strings[3].len);
break;
case 5:
- writeStream->writeString(ci->type);
+ castInfo.strings[4].data = (byte *)malloc(castInfo.strings[4].len);
+ memcpy(castInfo.strings[4].data, ci->type.c_str(), castInfo.strings[4].len);
break;
case 6:
// Need a better check to see if script edit info is valid
if (ci->scriptEditInfo.version) {
- Movie::writeRect(writeStream, ci->scriptEditInfo.rect);
- writeStream->writeUint32BE(ci->scriptEditInfo.selStart);
- writeStream->writeUint32BE(ci->scriptEditInfo.selEnd);
- writeStream->writeByte(ci->scriptEditInfo.version);
- writeStream->writeByte(ci->scriptEditInfo.rulerFlag);
+ byte buf[18]; // Size of an EditInfo struct
+ Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(buf, 18);
+ Movie::writeRect(stream, ci->scriptEditInfo.rect);
+ stream->writeUint32BE(ci->scriptEditInfo.selStart);
+ stream->writeUint32BE(ci->scriptEditInfo.selEnd);
+ stream->writeByte(ci->scriptEditInfo.version);
+ stream->writeByte(ci->scriptEditInfo.rulerFlag);
+
+ castInfo.strings[5].data = (byte *)malloc(castInfo.strings[5].len);
+ memcpy(castInfo.strings[5].data, buf, 18);
}
break;
case 7:
// Need a better check to see if scriptStyle is valid
if (ci->scriptStyle.fontId) {
- writeStream->writeUint16LE(1); // FIXME: For CastMembers, the count is 1, observed value, need to validate
- ci->scriptStyle.write(writeStream);
+ byte buf[20]; // Size of the ScriptStyle FontStyle
+ Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(buf, 20);
+ stream->writeUint16LE(1); // FIXME: For CastMembers, the count is 1, observed value, need to validate
+ ci->scriptStyle.write(stream);
+
+ castInfo.strings[6].data = (byte *)malloc(castInfo.strings[6].len);
+ memcpy(castInfo.strings[6].data, buf, 20);
}
break;
case 8:
// Need a better check to see if text edit info is valid
if (ci->textEditInfo.version) {
- Movie::writeRect(writeStream, ci->textEditInfo.rect);
- writeStream->writeUint32BE(ci->textEditInfo.selStart);
- writeStream->writeUint32BE(ci->textEditInfo.selEnd);
- writeStream->writeByte(ci->textEditInfo.version);
- writeStream->writeByte(ci->textEditInfo.rulerFlag);
+ byte buf[18]; // Size of an EditInfo struct
+ Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(buf, 18);
+ Movie::writeRect(stream, ci->textEditInfo.rect);
+ stream->writeUint32BE(ci->textEditInfo.selStart);
+ stream->writeUint32BE(ci->textEditInfo.selEnd);
+ stream->writeByte(ci->textEditInfo.version);
+ stream->writeByte(ci->textEditInfo.rulerFlag);
+
+ castInfo.strings[7].data = (byte *)malloc(castInfo.strings[7].len);
+ memcpy(castInfo.strings[7].data, buf, 18);
}
break;
case 9:
- writeStream->writeString(ci->unknownString1);
+ castInfo.strings[8].data = (byte *)malloc(castInfo.strings[8].len);
+ memcpy(castInfo.strings[8].data, ci->unknown1.data(), castInfo.strings[8].len);
break;
case 10:
- writeStream->writeString(ci->unknownString2);
+ castInfo.strings[9].data = (byte *)malloc(castInfo.strings[9].len);
+ memcpy(castInfo.strings[9].data, ci->unknown2.data(), castInfo.strings[9].len);
break;
case 11:
- writeStream->writeString(ci->unknownString3);
+ castInfo.strings[10].data = (byte *)malloc(castInfo.strings[10].len);
+ memcpy(castInfo.strings[10].data, ci->unknown3.data(), castInfo.strings[10].len);
break;
case 12:
- writeStream->writeString(ci->unknownString4);
+ castInfo.strings[11].data = (byte *)malloc(castInfo.strings[11].len);
+ memcpy(castInfo.strings[11].data, ci->unknown4.data(), castInfo.strings[11].len);
break;
case 13:
- writeStream->writeString(ci->unknownString5);
+ castInfo.strings[12].data = (byte *)malloc(castInfo.strings[12].len);
+ memcpy(castInfo.strings[12].data, ci->unknown5.data(), castInfo.strings[12].len);
break;
case 14:
- writeStream->writeString(ci->unknownString6);
+ castInfo.strings[13].data = (byte *)malloc(castInfo.strings[13].len);
+ memcpy(castInfo.strings[13].data, ci->unknown6.data(), castInfo.strings[13].len);
break;
case 15:
- writeStream->writeString(ci->unknownString7);
+ castInfo.strings[14].data = (byte *)malloc(castInfo.strings[14].len);
+ memcpy(castInfo.strings[14].data, ci->unknown7.data(), castInfo.strings[14].len);
break;
}
}
+
+ Movie::saveInfoEntries(writeStream, castInfo);
}
// This function is called three separate times
@@ -1092,69 +1019,10 @@ uint32 Cast::getCastInfoSize(uint32 castId) {
}
uint32 length = 0;
-
- switch (ci->count) {
- default:
- debug("writeCastMemberInfo:: extra strings found, ignoring");
- break;
- case 15:
- length += ci->unknownString7.size();
- // fallthrough
- case 14:
- length += ci->unknownString6.size();
- // fallthrough
- case 13:
- length += ci->unknownString5.size();
- // fallthrough
- case 12:
- length += ci->unknownString4.size();
- // fallthrough
- case 11:
- length += ci->unknownString3.size();
- // fallthrough
- case 10:
- length += ci->unknownString2.size();
- // fallthrough
- case 9:
- length += ci->unknownString1.size();
- // fallthrough
- case 8:
- if (ci->textEditInfo.version) {
- length += 18; // The length of an edit info
- }
- // fallthrough
- case 7:
- if (ci->scriptStyle.fontId) {
- length += 20; // The length of FontStyle
- }
- // fallthrough
- case 6:
- if (ci->scriptEditInfo.version) {
- length += 18; // The length of an edit info
- }
- // fallthrough
- case 5:
- length += ci->type.size();
- // fallthrough
- case 4:
- length += ci->fileName.size();
- // fallthrough
- case 3:
- length += ci->directory.size();
- // fallthrough
- case 2:
- length += ci->name.size();
- debug("at 2: length = %d, name: %s", ci->name.size(), ci->name.c_str());
- // fallthrough
- case 1:
- length += ci->script.size();
- debug("at 1: length = %d", ci->name.size());
- // fallthrough
- case 0:
- break;
+ for (int i = 1; i <= ci->count; i++) {
+ length += getCastInfoStringLength(i, ci);
}
- debug("Header size = 20, length: %d, ci->count: %d, (ci->count + 1) * 4: %d", length, ci->count, (ci->count + 1) *4);
// The header + total length of the strings + number of length entries for the strings
return 22 + length + (ci->count + 1) * 4;
}
@@ -1164,6 +1032,61 @@ uint32 Cast::computeChecksum() {
return 0;
}
+// The 'CASt' resource has strings containing information about the respective CastMember
+// This function is for retreiving the size of each while writing them back
+uint32 Cast::getCastInfoStringLength(uint32 stringIndex, CastMemberInfo *ci) {
+ switch (stringIndex) {
+ default:
+ debug("writeCastMemberInfo:: extra string index out of bound");
+ return 0;
+
+ case 1:
+ return ci->script.size();
+
+ case 2:
+ return ci->name.size();
+
+ case 3:
+ return ci->directory.size();
+
+ case 4:
+ return ci->fileName.size();
+
+ case 5:
+ return ci->type.size();
+
+ case 6:
+ return 18; // The length of an edit info
+
+ case 7:
+ return 20; // The length of FontStyle
+
+ case 8:
+ return 18; // The length of an edit info
+
+ case 9:
+ return ci->unknown1.size();
+
+ case 10:
+ return ci->unknown2.size();
+
+ case 11:
+ return ci->unknown3.size();
+
+ case 12:
+ return ci->unknown4.size();
+
+ case 13:
+ return ci->unknown5.size();
+
+ case 14:
+ return ci->unknown6.size();
+
+ case 15:
+ return ci->unknown7.size();
+ }
+}
+
Common::String Cast::getLinkedPath(int castId) {
if (!_castsInfo.contains(castId))
return Common::String();
@@ -1807,49 +1730,49 @@ void Cast::loadCastInfo(Common::SeekableReadStreamEndian &stream, uint16 id) {
if (castInfo.strings[14].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 14, id);
Common::hexdump(castInfo.strings[14].data, castInfo.strings[14].len);
- ci->unknownString7 = castInfo.strings[14].readString();
+ ci->unknown7 = Common::Array<byte>(castInfo.strings[14].data, castInfo.strings[14].len);
}
// fallthrough
case 14:
if (castInfo.strings[13].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 13, id);
Common::hexdump(castInfo.strings[13].data, castInfo.strings[13].len);
- ci->unknownString6 = castInfo.strings[13].readString();
+ ci->unknown6 = Common::Array<byte>(castInfo.strings[13].data, castInfo.strings[13].len);
}
// fallthrough
case 13:
if (castInfo.strings[12].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 12, id);
Common::hexdump(castInfo.strings[12].data, castInfo.strings[12].len);
- ci->unknownString5 = castInfo.strings[12].readString();
+ ci->unknown5 = Common::Array<byte>(castInfo.strings[12].data, castInfo.strings[12].len);
}
// fallthrough
case 12:
if (castInfo.strings[11].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 11, id);
Common::hexdump(castInfo.strings[11].data, castInfo.strings[11].len);
- ci->unknownString4 = castInfo.strings[11].readString();
+ ci->unknown4 = Common::Array<byte>(castInfo.strings[11].data, castInfo.strings[11].len);
}
// fallthrough
case 11:
if (castInfo.strings[10].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 11, id);
Common::hexdump(castInfo.strings[10].data, castInfo.strings[10].len);
- ci->unknownString3 = castInfo.strings[10].readString();
+ ci->unknown3 =Common::Array<byte>(castInfo.strings[10].data, castInfo.strings[10].len);
}
// fallthrough
case 10:
if (castInfo.strings[9].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 10, id);
Common::hexdump(castInfo.strings[9].data, castInfo.strings[9].len);
- ci->unknownString2 = castInfo.strings[9].readString();
+ ci->unknown2 = Common::Array<byte>(castInfo.strings[9].data, castInfo.strings[9].len);
}
// fallthrough
case 9:
if (castInfo.strings[8].len) {
warning("Cast::loadCastInfo(): BUILDBOT: string #%d for castid %d", 9, id);
Common::hexdump(castInfo.strings[8].data, castInfo.strings[8].len);
- ci->unknownString1 = castInfo.strings[8].readString();
+ ci->unknown1 = Common::Array<byte>(castInfo.strings[8].data, castInfo.strings[8].len);
}
// fallthrough
case 8:
diff --git a/engines/director/cast.h b/engines/director/cast.h
index fcef398e706..a3421f996dc 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -111,6 +111,7 @@ public:
void saveCastData();
void writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId);
uint32 getCastInfoSize(uint32 castId);
+ uint32 getCastInfoStringLength(uint32 stringIndex, CastMemberInfo *ci);
int getCastSize();
int getCastMaxID();
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 1215b91a045..5f25cfd7eaa 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -314,7 +314,6 @@ void CastMember::unload() {
// Whereas _info_ is metadata (size, name, flags, etc.)
// Some castmembers have their _data_ as well as _info_ in this very 'CASt' resource, e.g. TextCastMember
// Whereas some other have their _info_ in a 'CASt' resource and _data_ in a dedicated resource (e.g. PaletteCastMember has 'CLUT' resource)
-
uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 castIndex) {
// We'll need the original resource stream if there is no change in the castmember
Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), castIndex);
@@ -373,13 +372,16 @@ uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uin
}
// This is the data that is inside the 'CASt' resource
+// These functions (getCastDataSize() and writeCastData() default implementations, are not supposed to be called
+// If the data is modified in the castmember, we implement a custom getCastDataSize() and writeCastData() for that member
+// If it is not modified, then we write it as it is from the original source
uint32 CastMember::getCastDataSize() {
- debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size, this is not supposed to be called");
+ debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size");
return _castDataSize;
}
void CastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
- debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data, this is not supposed to be called");
+ debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data");
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
if (_flags1 != 0xFF) {
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index d7d50c03cfa..9a2f1085790 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -161,13 +161,13 @@ struct CastMemberInfo {
// There just has to be a better solution
// It is not rare to find these strings in the CastMemberInfo
- Common::String unknownString1;
- Common::String unknownString2;
- Common::String unknownString3;
- Common::String unknownString4;
- Common::String unknownString5;
- Common::String unknownString6;
- Common::String unknownString7;
+ Common::Array<byte> unknown1;
+ Common::Array<byte> unknown2;
+ Common::Array<byte> unknown3;
+ Common::Array<byte> unknown4;
+ Common::Array<byte> unknown5;
+ Common::Array<byte> unknown6;
+ Common::Array<byte> unknown7;
CastMemberInfo() : autoHilite(false), scriptId(0) {}
};
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index 10bb7fb395f..f029319507d 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -139,10 +139,12 @@ void PaletteCastMember::unload() {
void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset) {
uint32 castSize = getPaletteDataSize() + 8;
+
+ /**/
byte *dumpData = nullptr;
dumpData = (byte *)calloc(castSize, sizeof(byte));
-
writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
+ /**/
// writeStream->seek(offset);
writeStream->writeUint32LE(MKTAG('C', 'L', 'U', 'T'));
@@ -161,20 +163,7 @@ void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream,
writeStream->writeByte(pal[3 * i + 2]);
}
- Common::DumpFile out;
- char buf[256];
- Common::sprintf_s(buf, "./dumps/%d-%s-%s", _castId, tag2str(MKTAG('C', 'L', 'U', 'T')), "WrittenPalette");
-
- // Write the movie out, stored in dumpData
- if (out.open(buf, true)) {
- out.write(dumpData, castSize);
- out.flush();
- out.close();
- debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
- } else {
- warning("RIFXArchive::writeStream: Error saving the file %s", buf);
- }
- free(dumpData);
+ dumpFile("PaletteData", _castId, MKTAG('C', 'L', 'U', 'T'), dumpData, castSize);
delete writeStream;
}
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index 59b83bf12a3..57a2fcf7056 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -78,6 +78,7 @@ static const DebugChannelDef debugFlagList[] = {
{Director::kDebugImGui, "imgui", "Show ImGui debug window (if available)"},
{Director::kDebugPaused, "paused", "Pause first movie right after start"},
{Director::kDebugPauseOnLoad, "pauseonload", "Pause every movie right after loading"},
+ {Director::kDebugSaving, "saving", "Show Debug output while saving movies"},
DEBUG_CHANNEL_END
};
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 8ceef336a4c..b6c3f302ae6 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -382,7 +382,7 @@ Common::Error DirectorEngine::run() {
_system->setImGuiCallbacks(ImGuiCallbacks());
#endif
- if (debugChannelSet(-1, kDebugLoading)) {
+ if (debugChannelSet(-1, kDebugSaving)) {
Common::Path writePath("./dumps/writtenMovie.dir");
_mainArchive->writeToFile(writePath);
}
diff --git a/engines/director/director.h b/engines/director/director.h
index 4ef8f27c87e..277c940b042 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -93,6 +93,7 @@ enum {
kDebugImGui,
kDebugPaused,
kDebugPauseOnLoad,
+ kDebugSaving,
};
enum {
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 0c80af28a22..24cb3fedd41 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -304,21 +304,21 @@ InfoEntries Movie::loadInfoEntries(Common::SeekableReadStreamEndian &stream, uin
res.scriptId = stream.readUint32();
stream.seek(offset);
- uint16 count = stream.readUint16() + 1;
+ uint16 count = stream.readUint16();
- debugC(3, kDebugLoading, "Movie::loadInfoEntries(): InfoEntry: %d entries", count - 1);
+ debugC(3, kDebugLoading, "Movie::loadInfoEntries(): InfoEntry: %d entries", count);
- if (count == 1)
+ if (count == 0)
return res;
- uint32 *entries = (uint32 *)calloc(count, sizeof(uint32));
+ uint32 *entries = (uint32 *)calloc(count + 1, sizeof(uint32));
- for (uint i = 0; i < count; i++)
+ for (int i = 0; i < count + 1; i++)
entries[i] = stream.readUint32();
- res.strings.resize(count - 1);
+ res.strings.resize(count);
- for (uint16 i = 0; i < count - 1; i++) {
+ for (uint16 i = 0; i < count; i++) {
res.strings[i].len = entries[i + 1] - entries[i];
res.strings[i].data = (byte *)malloc(res.strings[i].len);
stream.read(res.strings[i].data, res.strings[i].len);
@@ -331,6 +331,27 @@ InfoEntries Movie::loadInfoEntries(Common::SeekableReadStreamEndian &stream, uin
return res;
}
+void Movie::saveInfoEntries(Common::MemoryWriteStream *writeStream, InfoEntries info) {
+ // The writing functionality was intrioduced in Director 4
+ writeStream->writeUint32BE(20); // offset: d4 and up movies is always 20
+ writeStream->writeUint32BE(info.unk1);
+ writeStream->writeUint32BE(info.unk2);
+ writeStream->writeUint32BE(info.flags);
+ writeStream->writeUint32BE(info.scriptId);
+ writeStream->writeUint16BE(info.strings.size()); // count of strings in the info
+
+ uint32 length = 0;
+ writeStream->writeUint32LE(length);
+ for (uint16 i = 0; i < info.strings.size(); i++) {
+ length += info.strings[i].len;
+ writeStream->writeUint32LE(length);
+ }
+
+ for (uint16 i = 0; i < info.strings.size(); i++) {
+ writeStream->write(info.strings[i].data, info.strings[i].len);
+ }
+}
+
void Movie::loadFileInfo(Common::SeekableReadStreamEndian &stream) {
debugC(2, kDebugLoading, "****** Loading FileInfo VWFI");
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 8b23aa995cb..32a5ed5cb0e 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -91,6 +91,7 @@ public:
static Common::Rect readRect(Common::ReadStreamEndian &stream);
static InfoEntries loadInfoEntries(Common::SeekableReadStreamEndian &stream, uint16 version);
+ static void saveInfoEntries(Common::MemoryWriteStream *writeStream, InfoEntries info);
static void writeRect(Common::MemoryWriteStream *writeStream, Common::Rect rect);
Commit: 96d3dbc71036e2a83e623bbbb40060d8cdbb2a16
https://github.com/scummvm/scummvm/commit/96d3dbc71036e2a83e623bbbb40060d8cdbb2a16
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Write 'CASt' resources for all Cast Members
Added writeCastData() and getCastDataSize() functions for the
following CastMembers:
Shape, FilmLoop (Movie), RichText, Sound, DigitalVideo, BitMap,
Transition, Script
Changed paths:
engines/director/cast.cpp
engines/director/castmember/bitmap.cpp
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
engines/director/castmember/digitalvideo.cpp
engines/director/castmember/digitalvideo.h
engines/director/castmember/filmloop.cpp
engines/director/castmember/filmloop.h
engines/director/castmember/palette.cpp
engines/director/castmember/richtext.cpp
engines/director/castmember/richtext.h
engines/director/castmember/script.cpp
engines/director/castmember/script.h
engines/director/castmember/shape.cpp
engines/director/castmember/shape.h
engines/director/castmember/sound.cpp
engines/director/castmember/sound.h
engines/director/castmember/transition.cpp
engines/director/castmember/transition.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 286c065ff73..d44caebad8f 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -543,13 +543,13 @@ void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
writeStream->seek(offset); // This will allow us to write cast config at any offset
// These offsets are only for Director Version 4 to Director version 6
// offsets
- writeStream->writeUint16LE(_len); // 0
+ writeStream->writeUint16LE(_len); // 0 // This will change
writeStream->writeUint16LE(_fileVersion); // 2
Movie::writeRect(writeStream, _checkRect); // 4, 6, 8, 10
writeStream->writeUint16LE(_castArrayStart); // 12
- writeStream->writeUint16LE(_castArrayEnd); // 14
+ writeStream->writeUint16LE(_castArrayEnd); // 14 // This will change
writeStream->writeByte(_readRate); // 16
writeStream->writeByte(_lightswitch); // 17
@@ -835,19 +835,28 @@ void Cast::saveCast() {
if (!_loadedCast->contains(id)) {
writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
- Common::SeekableReadStreamEndian *stream = getResource(MKTAG('C', 'A', 'S', 't'), it);
+ Common::SeekableReadStreamEndian *stream = getResource(MKTAG('C', 'A', 'S', 't'), it);
uint32 size = stream->size(); // This is the size of the Resource without header and size entry itself
writeStream->writeUint32LE(size);
- writeStream->writeStream(stream);
+ writeStream->writeStream(stream);
+
+ delete stream;
} else {
CastMember *target = _loadedCast->getVal(id);
type = target->_type;
switch (target->_type) {
- case (kCastPalette):
- case (kCastBitmap):
- case (kCastText):
- case (kCastButton):
+ case kCastPalette:
+ case kCastBitmap:
+ case kCastText:
+ case kCastButton:
+ case kCastDigitalVideo:
+ case kCastFilmLoop:
+ case kCastMovie:
+ case kCastSound:
+ case kCastRichText:
+ case kCastLingoScript:
+ case kCastShape:
target->writeCAStResource(writeStream, 0);
break;
default:
diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index 87e9e0fd6b6..cbc55342917 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -22,7 +22,6 @@
#include "common/config-manager.h"
#include "common/macresman.h"
#include "common/substream.h"
-#include "common/macresman.h"
#include "common/memstream.h"
#include "graphics/surface.h"
#include "graphics/macgui/macwidget.h"
@@ -977,15 +976,23 @@ bool BitmapCastMember::setField(int field, const Datum &d) {
}
uint32 BitmapCastMember::getCastDataSize() {
- uint32 dataSize = 22;
+ // _pitch : 4 bytes
+ // _initialRect : 8 bytes
+ // _boundingRect : 8 bytes
+ // _regY : 2 bytes
+ // _regX : 2 bytes
+ // Total: 22 bytes
+ // For Director 4 : 2 byte extra for casttype and flags (See Cast::loadCastData())
+ uint32 dataSize = 22 + 2;
if (_bitsPerPixel != 0) {
dataSize += 6;
- if (_cast->_version >= kFileVer500) {
- dataSize += 2;
- }
+ // if (_cast->_version >= kFileVer500) {
+ // dataSize += 2; // Added two bytes for _clut.member
+ // dataSize -= 2; // Removed two byte for castType (See Cast::loadCastData())
+ // }
- if (_clut.member != 0) {
+ if (_flags2 != 0) {
dataSize += 16;
}
}
@@ -1001,6 +1008,32 @@ void BitmapCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
writeStream->writeUint16LE(_regY);
writeStream->writeUint16LE(_regX);
+ if (_bitsPerPixel != 0) {
+ writeStream->writeByte(0); // Skip one byte (not stored)
+ writeStream->writeByte(_bitsPerPixel);
+
+ if (_cast->_version >= kFileVer500) {
+ if (_clut.castLib == _cast->_castLibID) {
+ writeStream->writeSint16LE(-1);
+ } else {
+ writeStream->writeSint16LE(_clut.castLib);
+ }
+ }
+
+ if (_clut.member > 0) {
+ writeStream->writeSint16LE(_clut.member);
+ } else { // builtin palette
+ writeStream->writeSint16LE(_clut.member + 1);
+ }
+
+ if (_flags2 != 0) {
+ // Skipping 14 bytes because they are not stored in ScummVM Director
+ // May need to save in the future, see BitCastMember::BitCastMember constructor
+ writeStream->write(0, 14);
+ writeStream->writeUint16LE(_flags2);
+ }
+ }
+ // Ignoring the tail in the loading as well as saving
}
} // End of namespace Director
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 5f25cfd7eaa..1e84910d96d 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -374,7 +374,8 @@ uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uin
// This is the data that is inside the 'CASt' resource
// These functions (getCastDataSize() and writeCastData() default implementations, are not supposed to be called
// If the data is modified in the castmember, we implement a custom getCastDataSize() and writeCastData() for that member
-// If it is not modified, then we write it as it is from the original source
+// If it is not modified, then we write it as it is from the original source in the overridden
+// writeCAStResource(Common::MemoryWriteStream, uint32, uint32) function which doesn't call these default functions
uint32 CastMember::getCastDataSize() {
debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size");
return _castDataSize;
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index 9a2f1085790..04acda01384 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -101,6 +101,10 @@ public:
virtual CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) { return bbox.contains(pos) ? kCollisionYes : kCollisionNo; }
+ // When writing the 'CASt' resource, the general strucutre is the same for all the CastMembers
+ // Three parts to a 'CASt' resource (header + _info_, _data_)
+ // The headers, are common, the _info_ writing is handled by the Cast class, so no worries there
+ // So the only thing that differs is the _data_, for which we'll have separate implementations for each CastMember
uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 castIndex);
uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset);
uint32 getCastInfoSize();
diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index bd991c4ec62..975adf6ee7e 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -21,6 +21,7 @@
#include "audio/decoders/aiff.h"
#include "common/macresman.h"
+#include "common/memstream.h"
#include "graphics/paletteman.h"
#include "graphics/surface.h"
@@ -652,4 +653,23 @@ bool DigitalVideoCastMember::setField(int field, const Datum &d) {
return CastMember::setField(field, d);
}
+uint32 DigitalVideoCastMember::getCastDataSize() {
+ // We're only reading the _initialRect and _vflags from the Cast Data
+ // _initialRect : 8 bytes + _vflags : 4 bytes + (castType (see Cast::loadCastData() for Director 4 only) 1 byte
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ // It has been observed that the DigitalVideoCastMember has
+ return 8 + 4 + 1;
+ } else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ return 8 + 4;
+ }
+
+ warning("DigitalVideoCastMember::getCastDataSize(): unhandled or invalid cast version: %d", _cast->_version);
+ return 0;
+}
+
+void DigitalVideoCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ Movie::writeRect(writeStream, _initialRect);
+ writeStream->writeUint32LE(_vflags);
+}
+
} // End of namespace Director
diff --git a/engines/director/castmember/digitalvideo.h b/engines/director/castmember/digitalvideo.h
index 5ab694d06f0..78fdaa8376d 100644
--- a/engines/director/castmember/digitalvideo.h
+++ b/engines/director/castmember/digitalvideo.h
@@ -70,6 +70,9 @@ public:
Common::Point getRegistrationOffset() override;
Common::Point getRegistrationOffset(int16 width, int16 height) override;
+
+ uint32 getCastDataSize() override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
Common::String _filename;
diff --git a/engines/director/castmember/filmloop.cpp b/engines/director/castmember/filmloop.cpp
index 4b17ed6a0a3..ade62f044aa 100644
--- a/engines/director/castmember/filmloop.cpp
+++ b/engines/director/castmember/filmloop.cpp
@@ -20,6 +20,7 @@
*/
#include "common/stream.h"
+#include "common/memstream.h"
#include "graphics/surface.h"
#include "graphics/macgui/macwidget.h"
@@ -712,4 +713,38 @@ Common::Point FilmLoopCastMember::getRegistrationOffset(int16 currentWidth, int1
return Common::Point(currentWidth / 2, currentHeight / 2);
}
+uint32 FilmLoopCastMember::getCastDataSize() {
+ // We're only reading the _initialRect and _vflags from the Cast Data
+ // _initialRect : 8 bytes + _vflags : 4 bytes + (castType (see Cast::loadCastData() for Director 4 only) 1 byte
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ // It has been observed that the DigitalVideoCastMember has
+ return 8 + 4 + 1; // No flags (so instead of 2 extra bytes, we have 1) for FilmLoopCastMember
+ } else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ return 8 + 4;
+ }
+
+ warning("FilmLoopCastMember::getCastDataSize(): unhandled or invalid cast version: %d", _cast->_version);
+ return 0;
+}
+
+void FilmLoopCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ Movie::writeRect(writeStream, _initialRect);
+
+ uint32 flags = 0;
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ flags |= (_looping) ? 0 : 64;
+ flags |= (_enableSound) ? 8 : 0;
+ flags |= (_crop) ? 0 : 2;
+ flags |= (_center) ? 1 : 0;
+ } else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ flags |= (_looping) ? 0 : 32;
+ flags |= (_enableSound) ? 8 : 0;
+ flags |= (_crop) ? 0 : 2;
+ flags |= (_center) ? 1 : 0;
+ }
+
+ writeStream->writeUint32LE(flags);
+ writeStream->writeUint16LE(0); // May need to save proper value in the future, currently ignored
+}
+
} // End of namespace Director
diff --git a/engines/director/castmember/filmloop.h b/engines/director/castmember/filmloop.h
index 2113acfadeb..dd682ebb14d 100644
--- a/engines/director/castmember/filmloop.h
+++ b/engines/director/castmember/filmloop.h
@@ -58,6 +58,9 @@ public:
Common::Point getRegistrationOffset() override;
Common::Point getRegistrationOffset(int16 currentWidth, int16 currentHeight) override;
+ uint32 getCastDataSize() override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
+
bool _enableSound;
bool _looping;
bool _crop;
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index f029319507d..8dbea7f0f49 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -167,16 +167,15 @@ void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream,
delete writeStream;
}
+// PaletteCastMember has no data in the 'CASt' resource or is ignored
// This is the data in 'CASt' resource
uint32 PaletteCastMember::getCastDataSize() {
if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ // It has been observed as well that the Data size in PaletteCastMember's CASt resource is 0 for d5
return 0;
} else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- if (_flags1 != 0xFF) {
- return 3;
- } else {
- return 4;
- }
+ // (castType (see Cast::loadCastData() for Director 4 only) 1 byte
+ return 1; // Since SoundCastMember doesn't have any flags
}
return 0;
}
@@ -190,7 +189,8 @@ uint32 PaletteCastMember::getPaletteDataSize() {
}
void PaletteCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
-
+ // This should never get triggered
+ // Since there is no data to write
}
} // End of namespace Director
diff --git a/engines/director/castmember/richtext.cpp b/engines/director/castmember/richtext.cpp
index 9673c8823cc..9e492060b68 100644
--- a/engines/director/castmember/richtext.cpp
+++ b/engines/director/castmember/richtext.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/memstream.h"
#include "graphics/macgui/macwidget.h"
#include "director/director.h"
@@ -230,4 +231,45 @@ Common::String RichTextCastMember::formatInfo() {
format.c_str()
);
}
+
+uint32 RichTextCastMember::getCastDataSize() {
+ if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ // 8 bytes (_initialRect)
+ // 8 bytes (_boundingRect)
+ // Ignored 9 bytes
+ // 3 bytes r, g, b (foreground, each a byte)
+ // 6 bytes r, g, b (background, each 2 bytes)
+ return 26;
+ } else {
+ warning("RichTextCastMember()::getCastDataSize():>D5 isn't handled");
+ return 0;
+ }
+}
+
+void RichTextCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ Movie::writeRect(writeStream, _initialRect);
+ Movie::writeRect(writeStream, _boundingRect);
+
+ writeStream->write(0, 8);
+ writeStream->writeByte(0);
+
+ uint8 r, g, b;
+ _pf32.colorToRGB(_foreColor, r, g, b);
+ writeStream->writeByte(r);
+ writeStream->writeByte(g);
+ writeStream->writeByte(b);
+
+ _pf32.colorToRGB(_bgColor, r, g, b);
+ writeStream->writeByte(r);
+ writeStream->writeByte(0);
+ writeStream->writeByte(g);
+ writeStream->writeByte(0);
+ writeStream->writeByte(b);
+ writeStream->writeByte(0);
+ } else {
+ warning("RichTextCastMember()::writeCastData(): >D5 isn't handled");
+ }
}
+
+} // End of namespace Director
diff --git a/engines/director/castmember/richtext.h b/engines/director/castmember/richtext.h
index fdfa12a5f06..006a931a247 100644
--- a/engines/director/castmember/richtext.h
+++ b/engines/director/castmember/richtext.h
@@ -45,6 +45,9 @@ public:
Datum getField(int field) override;
bool setField(int field, const Datum &value) override;
+ uint32 getCastDataSize() override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
+
Common::String formatInfo() override;
private:
diff --git a/engines/director/castmember/script.cpp b/engines/director/castmember/script.cpp
index cd5c5b2b7f1..30138fc66ae 100644
--- a/engines/director/castmember/script.cpp
+++ b/engines/director/castmember/script.cpp
@@ -19,7 +19,9 @@
*
*/
+#include "common/memstream.h"
#include "director/director.h"
+#include "director/cast.h"
#include "director/castmember/script.h"
#include "director/lingo/lingo-the.h"
@@ -139,4 +141,39 @@ Common::String ScriptCastMember::formatInfo() {
);
}
+uint32 ScriptCastMember::getCastDataSize() {
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ // 2 bytes for type and unk1 + 1 byte for castType (see Cast::loadCastData() for Director 4 only
+ return 2 + 1;
+ } else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ // type and unk1: 2 bytes
+ return 2;
+ } else {
+ warning("ScriptCastMember::writeCastData(): invalid or unhandled Script version: %d", _cast->_version);
+ return 0;
+ }
+}
+
+void ScriptCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer600) {
+ writeStream->writeByte(0);
+
+ switch (_scriptType) {
+ case kScoreScript:
+ writeStream->writeByte(1);
+ break;
+ case kMovieScript:
+ writeStream->writeByte(3);
+ break;
+ case kParentScript:
+ writeStream->writeByte(7);
+ break;
+ default:
+ break;
+ }
+ } else {
+ warning("ScriptCastMember::writeCastData(): invalid or unhandled Script version: %d", _cast->_version);
+ }
+}
+
}
diff --git a/engines/director/castmember/script.h b/engines/director/castmember/script.h
index 79637eaba39..cd3d4bfd869 100644
--- a/engines/director/castmember/script.h
+++ b/engines/director/castmember/script.h
@@ -39,6 +39,9 @@ public:
Datum getField(int field) override;
bool setField(int field, const Datum &value) override;
+ uint32 getCastDataSize() override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
+
Common::String formatInfo() override;
};
diff --git a/engines/director/castmember/shape.cpp b/engines/director/castmember/shape.cpp
index d3680011628..887a61ef878 100644
--- a/engines/director/castmember/shape.cpp
+++ b/engines/director/castmember/shape.cpp
@@ -19,7 +19,9 @@
*
*/
+#include "common/memstream.h"
#include "director/director.h"
+#include "director/cast.h"
#include "director/movie.h"
#include "director/castmember/shape.h"
#include "director/lingo/lingo-the.h"
@@ -212,4 +214,43 @@ Common::String ShapeCastMember::formatInfo() {
);
}
+uint32 ShapeCastMember::getCastDataSize() {
+ // unk1 : 1 byte
+ // _shapeType : 1 byte
+ // _initalRect : 8 bytes
+ // _pattern : 2 bytes
+ // _fgCol : 1 byte
+ // _bgCol : 1 byte
+ // _fillType : 1 byte
+ // _lineThickness : 1 byte
+ // _lineDirection : 1 byte
+ // Total : 17 bytes
+ // For Director 4 : 1 byte extra for casttype (See Cast::loadCastData())
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ return 17 + 1;
+ } else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ return 17;
+ } else {
+ warning("ScriptCastMember::writeCastData(): invalid or unhandled Script version: %d", _cast->_version);
+ return 0;
+ }
}
+
+void ShapeCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ writeStream->writeByte(0);
+ writeStream->writeByte(1);
+
+ Movie::writeRect(writeStream, _initialRect);
+ writeStream->writeUint16LE(_pattern);
+
+ // The foreground and background colors are transformed
+ // Need to retreive the original colors for saving
+ writeStream->writeByte(_fgCol);
+ writeStream->writeByte(_bgCol);
+
+ writeStream->writeByte(_fillType);
+ writeStream->writeByte(_lineThickness);
+ writeStream->writeByte(_lineDirection);
+}
+
+} // End of namespace Director
diff --git a/engines/director/castmember/shape.h b/engines/director/castmember/shape.h
index ca2df0e0dca..f685075b3ff 100644
--- a/engines/director/castmember/shape.h
+++ b/engines/director/castmember/shape.h
@@ -44,6 +44,9 @@ public:
Common::String formatInfo() override;
+ uint32 getCastDataSize() override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
+
ShapeType _shapeType;
uint16 _pattern;
byte _fillType;
diff --git a/engines/director/castmember/sound.cpp b/engines/director/castmember/sound.cpp
index a854a88b378..a8f669c5b8c 100644
--- a/engines/director/castmember/sound.cpp
+++ b/engines/director/castmember/sound.cpp
@@ -199,6 +199,21 @@ bool SoundCastMember::setField(int field, const Datum &d) {
return CastMember::setField(field, d);
}
+// Similar to PaletteCastMember, SoundCastMember has no data in the 'CASt' resource or is ignored
+// This is the data in 'CASt' resource
+uint32 SoundCastMember::getCastDataSize() {
+ if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ return 0;
+ } else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
+ // (castType (see Cast::loadCastData() for Director 4 only) 1 byte
+ return 1; // Since SoundCastMember doesn't have any flags
+ }
+ return 0;
+}
+void SoundCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ // This should never get triggered
+ // since there is no data to write
+}
} // End of namespace Director
diff --git a/engines/director/castmember/sound.h b/engines/director/castmember/sound.h
index 79797d39be7..2477ea2a5f0 100644
--- a/engines/director/castmember/sound.h
+++ b/engines/director/castmember/sound.h
@@ -44,6 +44,9 @@ public:
Datum getField(int field) override;
bool setField(int field, const Datum &value) override;
+ uint32 getCastDataSize() override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
+
bool _looping;
AudioDecoder *_audio;
};
diff --git a/engines/director/castmember/transition.cpp b/engines/director/castmember/transition.cpp
index 3338350b313..836b3983ce7 100644
--- a/engines/director/castmember/transition.cpp
+++ b/engines/director/castmember/transition.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "common/memstream.h"
#include "director/director.h"
#include "director/cast.h"
#include "director/movie.h"
@@ -125,4 +126,30 @@ Common::String TransitionCastMember::formatInfo() {
return Common::String::format("transType: %d, durationMillis: %d, flags: %d, chunkSize: %d, area: %d", _transType, _durationMillis, _flags, _chunkSize, _area);
}
+uint32 TransitionCastMember::getCastDataSize() {
+ if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
+ // Ignored 1 byte
+ // _chunkSize 1 byte
+ // _transType 1 byte
+ // _flags 1 byte
+ // _durationMiilis 2 bytes
+ return 6;
+ } else {
+ warning("RichTextCastMember()::getCastDataSize(): CastMember version invalid or not handled");
+ return 0;
+ }
+}
+
+void TransitionCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
+ if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer600) {
+ writeStream->writeByte(0);
+ writeStream->writeByte(_chunkSize);
+ writeStream->writeByte((uint8)_transType);
+ writeStream->writeByte(_flags);
+ writeStream->writeUint16LE(_durationMillis);
+ } else {
+ warning("RichTextCastMember()::writeCastData(): CastMember version invalid or not handled");
+ }
+}
+
} // End of namespace Director
diff --git a/engines/director/castmember/transition.h b/engines/director/castmember/transition.h
index 46fa295eb3f..6498f0d0559 100644
--- a/engines/director/castmember/transition.h
+++ b/engines/director/castmember/transition.h
@@ -39,6 +39,9 @@ public:
Common::String formatInfo() override;
+ uint32 getCastDataSize() override;
+ void writeCastData(Common::MemoryWriteStream *writeStream) override;
+
TransitionType _transType;
uint16 _durationMillis;
uint8 _flags;
Commit: 83534578a9f9b60b1cf7ea9289ae80885760d831
https://github.com/scummvm/scummvm/commit/83534578a9f9b60b1cf7ea9289ae80885760d831
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Minor adjustments in writing 'CASt' Resources
Removed trailing whitespace in all files
Remove the 'STXT' and 'CLUT' resource writing for now
Changed paths:
engines/director/archive.cpp
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember/bitmap.cpp
engines/director/castmember/bitmap.h
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
engines/director/castmember/digitalvideo.cpp
engines/director/castmember/digitalvideo.h
engines/director/castmember/filmloop.cpp
engines/director/castmember/palette.cpp
engines/director/castmember/palette.h
engines/director/castmember/richtext.cpp
engines/director/castmember/script.cpp
engines/director/castmember/shape.cpp
engines/director/castmember/sound.cpp
engines/director/castmember/text.cpp
engines/director/castmember/text.h
engines/director/castmember/transition.cpp
engines/director/director.cpp
engines/director/movie.cpp
engines/director/stxt.cpp
engines/director/stxt.h
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 399239070eb..fd5030c9327 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -1277,7 +1277,7 @@ bool RIFXArchive::writeMemoryMap(Common::SeekableMemoryWriteStream *writeStream)
writeStream->writeUint32LE(newResCount + _totalCount - _resCount); // _totalCount - _resCount is the number of empty entries
writeStream->writeUint32LE(newResCount);
- writeStream->seek(8, SEEK_CUR); // In the original file, these 8 bytes are all 0xFF, so this will produce a diff
+ writeStream->seek(8, SEEK_CUR); // In the original file, these 8 bytes are all 0xFF, so this will produce a diff
// ID of the first 'free' resource
writeStream->writeUint32LE(0);
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index d44caebad8f..cad2cffd35a 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -543,7 +543,7 @@ void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
writeStream->seek(offset); // This will allow us to write cast config at any offset
// These offsets are only for Director Version 4 to Director version 6
// offsets
- writeStream->writeUint16LE(_len); // 0 // This will change
+ writeStream->writeUint16LE(_len); // 0 // This will change
writeStream->writeUint16LE(_fileVersion); // 2
Movie::writeRect(writeStream, _checkRect); // 4, 6, 8, 10
@@ -561,7 +561,7 @@ void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
writeStream->writeUint16LE(_stageColor); // 26
writeStream->writeUint16LE(_bitdepth); // 28
-
+
writeStream->writeByte(_field17); // 29
writeStream->writeByte(_field18); // 30
writeStream->writeSint32LE(_field19); // 34
@@ -582,11 +582,11 @@ void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
writeStream->writeSint32LE(_field29); // 60
// Currently a stub
- uint32 checksum = computeChecksum();
+ uint32 checksum = computeChecksum();
writeStream->writeUint32LE(checksum); // 64
if (_version >= kFileVer400 && _version < kFileVer500) {
- writeStream->writeSint16LE(_field30); // 68
+ writeStream->writeSint16LE(_field30); // 68
// This loop isn't writing meaningful data currently
// But it is possible that this data might be needed
@@ -790,23 +790,18 @@ void Cast::loadCast() {
if (_castArchive->hasResource(MKTAG('S', 'C', 'R', 'F'), -1)) {
debugC(4, kDebugLoading, "'SCRF' resource skipped");
}
-
- if (debugChannelSet(7, kDebugSaving)) {
- debug("Cast::saveCast: Saving the Cast resources in ./dumps");
- saveCast();
- }
}
void Cast::saveCast() {
// This offset is at which we will start writing our 'CASt' resources
// In the original file, all the 'CASt' resources don't necessarily appear side by side
// writeStream->seek(offset);
-
+
Common::Array<uint16> cast = _castArchive->getResourceIDList(MKTAG('C', 'A', 'S', 't'));
// Okay, this is going to cause confusion
- // In the director movie archive, each CASt resource is given an ID, Not sure how this ID is assigned
- // but it is present in the keytable and is loaded while reading the keytable in RIFXArchive::readKeyTable();
+ // In the director movie archive, each CASt resource is given an ID, Not sure how this ID is assigned
+ // but it is present in the keytable and is loaded while reading the keytable in RIFXArchive::readKeyTable();
// The castId on the other hand present in the Resource struct is assigned by ScummVM Director in RIFXArchive::readCast()
// It is basically the index at which it occurs in the CAS* resource
// So, RIFXArchive::getResourceDetail will return the list of IDs present in the keytable
@@ -820,20 +815,21 @@ void Cast::saveCast() {
if (_loadedCast->contains(id)) {
CastMember *target = _loadedCast->getVal(id);
// To make it consistent with how the data is stored originally, getResourceSize returns
- // the size excluding 'CASt' header and the entry for size itself. Adding 8 to compensate for that
- castSize = target->getCastResourceSize() + 8;
+ // the size excluding 'CASt' header and the entry for size itself. Adding 8 to compensate for that
+ castSize = target->getCastResourceSize() + 8;
} else {
- // The size stored in the memory map (_resources array), as well as the resource itself is the size
+ // The size stored in the memory map (_resources array), as well as the resource itself is the size
// excluding the 'CASt' header and the entry of size itself. Adding 8 to compensate for that
castSize = _castArchive->getResourceSize(MKTAG('C', 'A', 'S', 't'), it) + 8;
}
+ debugC(5, kDebugSaving, "Cast::saveCast()::Saving 'CASt' resource, id: %d, size: %d", id, castSize);
byte *dumpData = (byte *)calloc(castSize, sizeof(byte));
Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
CastType type = kCastTypeAny;
- if (!_loadedCast->contains(id)) {
+ if (!_loadedCast->contains(id)) {
writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
Common::SeekableReadStreamEndian *stream = getResource(MKTAG('C', 'A', 'S', 't'), it);
uint32 size = stream->size(); // This is the size of the Resource without header and size entry itself
@@ -863,12 +859,12 @@ void Cast::saveCast() {
target->writeCAStResource(writeStream, 0, it);
break;
}
- }
+ }
dumpFile(castType2str(type), res.index, MKTAG('C', 'A', 'S', 't'), dumpData, castSize);
delete writeStream;
}
-
+
}
void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId) {
@@ -877,8 +873,8 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
// (These strings contain properties of the cast member like filename, script attached to it, name, etc.)
// After the header, we have the next data is the lengths of the strings,
// The first int is 0, the second int is 0 + length of the first string, the third int is 0 + length of first string + length of second string and so on
- // After the lengths of the strings are the actual strings
-
+ // After the lengths of the strings are the actual strings
+
if (!_castsInfo.contains(castId)) {
return;
}
@@ -893,7 +889,7 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
castInfo.strings.resize(ci->count);
for (int i = 1; i <= ci->count; i++) {
- castInfo.strings[i - 1].len += getCastInfoStringLength(i, ci);
+ castInfo.strings[i - 1].len = getCastInfoStringLength(i, ci);
}
for (int i = 1; i <= ci->count; i++) {
@@ -901,16 +897,16 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
continue;
}
- switch (i) {
+ switch (i) {
default:
debug("Cast::writeCastInfo()::extra strings found, ignoring");
break;
-
+
case 1:
castInfo.strings[0].data = (byte *)malloc(castInfo.strings[0].len);
memcpy(castInfo.strings[0].data, ci->script.c_str(), castInfo.strings[0].len);
break;
-
+
case 2:
castInfo.strings[1].data = (byte *)malloc(castInfo.strings[1].len);
memcpy(castInfo.strings[1].data, ci->name.c_str(), castInfo.strings[1].len);
@@ -925,62 +921,58 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
castInfo.strings[3].data = (byte *)malloc(castInfo.strings[3].len);
memcpy(castInfo.strings[3].data, ci->fileName.c_str(), castInfo.strings[3].len);
break;
-
+
case 5:
castInfo.strings[4].data = (byte *)malloc(castInfo.strings[4].len);
memcpy(castInfo.strings[4].data, ci->type.c_str(), castInfo.strings[4].len);
break;
-
+
case 6:
- // Need a better check to see if script edit info is valid
- if (ci->scriptEditInfo.version) {
- byte buf[18]; // Size of an EditInfo struct
- Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(buf, 18);
+ {
+ castInfo.strings[5].data = (byte *)malloc(castInfo.strings[5].len);
+ Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(castInfo.strings[5].data, castInfo.strings[5].len);
+
Movie::writeRect(stream, ci->scriptEditInfo.rect);
stream->writeUint32BE(ci->scriptEditInfo.selStart);
stream->writeUint32BE(ci->scriptEditInfo.selEnd);
stream->writeByte(ci->scriptEditInfo.version);
stream->writeByte(ci->scriptEditInfo.rulerFlag);
-
- castInfo.strings[5].data = (byte *)malloc(castInfo.strings[5].len);
- memcpy(castInfo.strings[5].data, buf, 18);
+ delete stream;
}
break;
case 7:
- // Need a better check to see if scriptStyle is valid
- if (ci->scriptStyle.fontId) {
- byte buf[20]; // Size of the ScriptStyle FontStyle
- Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(buf, 20);
- stream->writeUint16LE(1); // FIXME: For CastMembers, the count is 1, observed value, need to validate
+ {
+ castInfo.strings[6].data = (byte *)malloc(castInfo.strings[6].len);
+
+ Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(castInfo.strings[6].data, castInfo.strings[6].len);
+ stream->writeUint16BE(1); // FIXME: For CastMembers, the count is 1, observed value, need to validate
ci->scriptStyle.write(stream);
- castInfo.strings[6].data = (byte *)malloc(castInfo.strings[6].len);
- memcpy(castInfo.strings[6].data, buf, 20);
+ delete stream;
}
break;
case 8:
- // Need a better check to see if text edit info is valid
- if (ci->textEditInfo.version) {
- byte buf[18]; // Size of an EditInfo struct
- Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(buf, 18);
+ {
+ castInfo.strings[7].data = (byte *)malloc(castInfo.strings[7].len);
+
+ Common::MemoryWriteStream *stream = new Common::MemoryWriteStream(castInfo.strings[7].data, castInfo.strings[7].len);
Movie::writeRect(stream, ci->textEditInfo.rect);
stream->writeUint32BE(ci->textEditInfo.selStart);
stream->writeUint32BE(ci->textEditInfo.selEnd);
stream->writeByte(ci->textEditInfo.version);
stream->writeByte(ci->textEditInfo.rulerFlag);
-
- castInfo.strings[7].data = (byte *)malloc(castInfo.strings[7].len);
- memcpy(castInfo.strings[7].data, buf, 18);
+
+ delete stream;
}
break;
-
+
case 9:
castInfo.strings[8].data = (byte *)malloc(castInfo.strings[8].len);
memcpy(castInfo.strings[8].data, ci->unknown1.data(), castInfo.strings[8].len);
break;
-
+
case 10:
castInfo.strings[9].data = (byte *)malloc(castInfo.strings[9].len);
memcpy(castInfo.strings[9].data, ci->unknown2.data(), castInfo.strings[9].len);
@@ -995,12 +987,12 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
castInfo.strings[11].data = (byte *)malloc(castInfo.strings[11].len);
memcpy(castInfo.strings[11].data, ci->unknown4.data(), castInfo.strings[11].len);
break;
-
+
case 13:
castInfo.strings[12].data = (byte *)malloc(castInfo.strings[12].len);
memcpy(castInfo.strings[12].data, ci->unknown5.data(), castInfo.strings[12].len);
break;
-
+
case 14:
castInfo.strings[13].data = (byte *)malloc(castInfo.strings[13].len);
memcpy(castInfo.strings[13].data, ci->unknown6.data(), castInfo.strings[13].len);
@@ -1016,11 +1008,11 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
Movie::saveInfoEntries(writeStream, castInfo);
}
-// This function is called three separate times
-// first when writing this 'CASt' resource in memory map (in getCastResourceSize())
-// second when writing the 'CASt' resource itself (in getCastResourceSize())
+// This function is called three separate times
+// first when writing this 'CASt' resource in memory map (in getCastResourceSize())
+// second when writing the 'CASt' resource itself (in getCastResourceSize())
// and thirdly when we're writing the info size in the 'CASt' resource
-// All three times, it returns the same value, this could be more efficient
+// All three times, it returns the same value, this could be more efficient
uint32 Cast::getCastInfoSize(uint32 castId) {
CastMemberInfo *ci = getCastMemberInfo(castId);
if (!ci) {
@@ -1032,26 +1024,26 @@ uint32 Cast::getCastInfoSize(uint32 castId) {
length += getCastInfoStringLength(i, ci);
}
- // The header + total length of the strings + number of length entries for the strings
+ // The header + total length of the strings + number of length entries for the strings
return 22 + length + (ci->count + 1) * 4;
}
-uint32 Cast::computeChecksum() {
+uint32 Cast::computeChecksum() {
warning("STUB::ConfigChunk::computeChecksum() is not implemented yet");
- return 0;
+ return 0;
}
// The 'CASt' resource has strings containing information about the respective CastMember
-// This function is for retreiving the size of each while writing them back
+// This function is for retreiving the size of each while writing them back
uint32 Cast::getCastInfoStringLength(uint32 stringIndex, CastMemberInfo *ci) {
- switch (stringIndex) {
+ switch (stringIndex) {
default:
debug("writeCastMemberInfo:: extra string index out of bound");
return 0;
-
+
case 1:
return ci->script.size();
-
+
case 2:
return ci->name.size();
@@ -1060,22 +1052,34 @@ uint32 Cast::getCastInfoStringLength(uint32 stringIndex, CastMemberInfo *ci) {
case 4:
return ci->fileName.size();
-
+
case 5:
return ci->type.size();
case 6:
- return 18; // The length of an edit info
+ // Need a better check to see if script edit info is valid
+ if (ci->scriptEditInfo.valid) {
+ return 18; // The length of an edit info
+ }
+ return 0;
case 7:
- return 20; // The length of FontStyle
+ // Need a better check to see if scriptStyle is valid
+ if (ci->scriptStyle.fontId) {
+ return 22; // The length of FontStyle
+ }
+ return 0;
case 8:
- return 18; // The length of an edit info
-
+ // Need a better check to see if text edit info is valid
+ if (ci->textEditInfo.valid) {
+ return 18; // The length of an edit info
+ }
+ return 0;
+
case 9:
return ci->unknown1.size();
-
+
case 10:
return ci->unknown2.size();
@@ -1084,7 +1088,7 @@ uint32 Cast::getCastInfoStringLength(uint32 stringIndex, CastMemberInfo *ci) {
case 12:
return ci->unknown4.size();
-
+
case 13:
return ci->unknown5.size();
@@ -1298,7 +1302,8 @@ static void readEditInfo(EditInfo *info, Common::ReadStreamEndian *stream) {
info->selEnd = stream->readUint32();
info->version = stream->readByte();
info->rulerFlag = stream->readByte();
-
+ // We're ignoring 2 bytes here
+ info->valid = true;
if (debugChannelSet(3, kDebugLoading)) {
info->rect.debugPrint(0, "EditInfo: ");
debug("selStart: %d selEnd: %d version: %d rulerFlag: %d", info->selStart,info->selEnd, info->version, info->rulerFlag);
@@ -1326,7 +1331,7 @@ void Cast::loadCastData(Common::SeekableReadStreamEndian &stream, uint16 id, Res
stream.hexdump(stream.size());
uint32 castDataSize, castInfoSize, castType, castDataSizeToRead, castDataOffset, castInfoOffset;
- uint8 flags1 = 0xFF;
+ uint8 flags1 = 0xFF;
byte unk1 = 0, unk2 = 0, unk3 = 0;
// D2-3 cast members should be loaded in loadCastDataVWCR
diff --git a/engines/director/cast.h b/engines/director/cast.h
index a3421f996dc..0928b4a3215 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -183,7 +183,7 @@ public:
LingoDec::ScriptContext *_lingodec = nullptr;
LingoDec::ChunkResolver *_chunkResolver = nullptr;
-
+
/* Data to be saved */
/* 0 */ uint16 _len;
/* 2 */ uint16 _fileVersion;
diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index cbc55342917..4b8804ef4ac 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -132,7 +132,7 @@ BitmapCastMember::BitmapCastMember(Cast *cast, uint16 castId, Common::SeekableRe
_clut = CastMemberID(clutId, clutCastLib);
}
if (stream.pos() < stream.size()) {
- // castSize > 28 bytes on D4, > 30 bytes on D5
+ // castSize > 26 bytes on D4, > 28 bytes on D5
stream.readUint16();
/* uint16 unk1 = */ stream.readUint16();
stream.readUint16();
@@ -976,17 +976,17 @@ bool BitmapCastMember::setField(int field, const Datum &d) {
}
uint32 BitmapCastMember::getCastDataSize() {
- // _pitch : 4 bytes
+ // _pitch : 2 bytes
// _initialRect : 8 bytes
// _boundingRect : 8 bytes
// _regY : 2 bytes
// _regX : 2 bytes
- // Total: 22 bytes
+ // Total: 22 bytes
// For Director 4 : 2 byte extra for casttype and flags (See Cast::loadCastData())
uint32 dataSize = 22 + 2;
-
+
if (_bitsPerPixel != 0) {
- dataSize += 6;
+ dataSize += 4;
// if (_cast->_version >= kFileVer500) {
// dataSize += 2; // Added two bytes for _clut.member
// dataSize -= 2; // Removed two byte for castType (See Cast::loadCastData())
@@ -1000,41 +1000,40 @@ uint32 BitmapCastMember::getCastDataSize() {
}
void BitmapCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
- writeStream->writeUint32LE(_pitch);
+ writeStream->writeUint16BE(_pitch);
Movie::writeRect(writeStream, _initialRect);
Movie::writeRect(writeStream, _boundingRect);
- writeStream->writeUint16LE(_regY);
- writeStream->writeUint16LE(_regX);
-
- if (_bitsPerPixel != 0) {
+ writeStream->writeUint16BE(_regY);
+ writeStream->writeUint16BE(_regX);
+
+ if (_bitsPerPixel != 0) {
writeStream->writeByte(0); // Skip one byte (not stored)
writeStream->writeByte(_bitsPerPixel);
if (_cast->_version >= kFileVer500) {
if (_clut.castLib == _cast->_castLibID) {
- writeStream->writeSint16LE(-1);
+ writeStream->writeSint16BE(-1);
} else {
- writeStream->writeSint16LE(_clut.castLib);
+ writeStream->writeSint16BE(_clut.castLib);
}
}
if (_clut.member > 0) {
- writeStream->writeSint16LE(_clut.member);
+ writeStream->writeSint16BE(_clut.member);
} else { // builtin palette
- writeStream->writeSint16LE(_clut.member + 1);
+ writeStream->writeSint16BE(_clut.member + 1);
}
if (_flags2 != 0) {
// Skipping 14 bytes because they are not stored in ScummVM Director
- // May need to save in the future, see BitCastMember::BitCastMember constructor
+ // May need to save in the future, see BitCastMember::BitCastMember constructor
writeStream->write(0, 14);
- writeStream->writeUint16LE(_flags2);
+ writeStream->writeUint16BE(_flags2);
}
}
// Ignoring the tail in the loading as well as saving
}
} // End of namespace Director
-
\ No newline at end of file
diff --git a/engines/director/castmember/bitmap.h b/engines/director/castmember/bitmap.h
index 5487cf62638..7b75c87926d 100644
--- a/engines/director/castmember/bitmap.h
+++ b/engines/director/castmember/bitmap.h
@@ -65,7 +65,7 @@ public:
CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) override;
void writeCastData(Common::MemoryWriteStream *writeStream) override;
-
+
uint32 getCastDataSize() override; // This is the size of the data in the 'CASt' resource
Picture *_picture = nullptr;
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 1e84910d96d..1d323fb0f89 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -311,17 +311,17 @@ void CastMember::unload() {
// Default implementation to write the 'CASt' resources as they are
// Cast members have two types of "information", one is _data_ and the other is _info_
// _data_ is the actual "data" (e.g. the pixel image data of a bitmap, sound data of a sound cast member)
-// Whereas _info_ is metadata (size, name, flags, etc.)
+// Whereas _info_ is metadata (size, name, flags, etc.)
// Some castmembers have their _data_ as well as _info_ in this very 'CASt' resource, e.g. TextCastMember
-// Whereas some other have their _info_ in a 'CASt' resource and _data_ in a dedicated resource (e.g. PaletteCastMember has 'CLUT' resource)
+// Whereas some other have their _info_ in a 'CASt' resource and _data_ in a dedicated resource (e.g. PaletteCastMember has 'CLUT' resource)
uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 castIndex) {
- // We'll need the original resource stream if there is no change in the castmember
+ // We'll need the original resource stream if there is no change in the castmember
Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), castIndex);
uint32 size = stream->size();
-
+
writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
writeStream->writeUint32LE(size);
-
+
writeStream->writeStream(stream);
return size + 8;
}
@@ -340,7 +340,7 @@ uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uin
writeStream->writeUint32BE(castInfoToWrite);
writeStream->writeByte((uint8)_type);
castDataToWrite -= 1;
-
+
if (_flags1 != 0xFF) { // In case of TextCastMember, this should be true
writeStream->writeByte(_flags1);
castDataToWrite -= 1;
@@ -374,7 +374,7 @@ uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uin
// This is the data that is inside the 'CASt' resource
// These functions (getCastDataSize() and writeCastData() default implementations, are not supposed to be called
// If the data is modified in the castmember, we implement a custom getCastDataSize() and writeCastData() for that member
-// If it is not modified, then we write it as it is from the original source in the overridden
+// If it is not modified, then we write it as it is from the original source in the overridden
// writeCAStResource(Common::MemoryWriteStream, uint32, uint32) function which doesn't call these default functions
uint32 CastMember::getCastDataSize() {
debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size");
@@ -405,12 +405,14 @@ uint32 CastMember::getCastResourceSize() {
uint32 headerSize = 0;
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- headerSize = 9;
+ // Header size for director version 4
+ headerSize = 7; // see Cast::loadCastData() for director version 4
if (_flags1 != 0xFF) {
headerSize += 1;
}
} else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
- headerSize = 12;
+ // Header size for director version 5
+ headerSize = 12; // See Cast::loadCastData() for director version 5
}
return headerSize + getCastInfoSize() + getCastDataSize();
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index 04acda01384..6574e27d3f0 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -121,7 +121,7 @@ public:
bool _erase;
int _purgePriority;
uint32 _size;
-
+
/* Data fields used when saving the Cast Member */
uint32 _castDataSize;
uint8 _flags1;
@@ -143,6 +143,9 @@ struct EditInfo {
int32 selEnd;
byte version;
byte rulerFlag;
+ bool valid;
+
+ EditInfo(): valid(false) {}
};
struct CastMemberInfo {
diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index 975adf6ee7e..e8f2833d5fb 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -655,10 +655,10 @@ bool DigitalVideoCastMember::setField(int field, const Datum &d) {
uint32 DigitalVideoCastMember::getCastDataSize() {
// We're only reading the _initialRect and _vflags from the Cast Data
- // _initialRect : 8 bytes + _vflags : 4 bytes + (castType (see Cast::loadCastData() for Director 4 only) 1 byte
+ // _initialRect : 8 bytes + _vflags : 4 bytes + castType and flags1 (see Cast::loadCastData() for Director 4 only) 2 byte
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- // It has been observed that the DigitalVideoCastMember has
- return 8 + 4 + 1;
+ // It has been observed that the DigitalVideoCastMember has
+ return (_flags1 == 0xFF) ? 13 : 14;
} else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
return 8 + 4;
}
@@ -669,7 +669,7 @@ uint32 DigitalVideoCastMember::getCastDataSize() {
void DigitalVideoCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
Movie::writeRect(writeStream, _initialRect);
- writeStream->writeUint32LE(_vflags);
+ writeStream->writeUint32BE(_vflags);
}
} // End of namespace Director
diff --git a/engines/director/castmember/digitalvideo.h b/engines/director/castmember/digitalvideo.h
index 78fdaa8376d..a5f126f8916 100644
--- a/engines/director/castmember/digitalvideo.h
+++ b/engines/director/castmember/digitalvideo.h
@@ -70,7 +70,7 @@ public:
Common::Point getRegistrationOffset() override;
Common::Point getRegistrationOffset(int16 width, int16 height) override;
-
+
uint32 getCastDataSize() override;
void writeCastData(Common::MemoryWriteStream *writeStream) override;
diff --git a/engines/director/castmember/filmloop.cpp b/engines/director/castmember/filmloop.cpp
index ade62f044aa..7ced1451e15 100644
--- a/engines/director/castmember/filmloop.cpp
+++ b/engines/director/castmember/filmloop.cpp
@@ -47,6 +47,7 @@ FilmLoopCastMember::FilmLoopCastMember(Cast *cast, uint16 castId, Common::Seekab
_crop = false;
_center = false;
+ // We are ignoring some of the bits in the flags
if (cast->_version >= kFileVer400 && cast->_version < kFileVer500) {
_initialRect = Movie::readRect(stream);
uint32 flags = stream.readUint32BE();
@@ -715,12 +716,12 @@ Common::Point FilmLoopCastMember::getRegistrationOffset(int16 currentWidth, int1
uint32 FilmLoopCastMember::getCastDataSize() {
// We're only reading the _initialRect and _vflags from the Cast Data
- // _initialRect : 8 bytes + _vflags : 4 bytes + (castType (see Cast::loadCastData() for Director 4 only) 1 byte
+ // _initialRect : 8 bytes + flags : 4 bytes + 2 bytes unk1 + (castType (see Cast::loadCastData() for Director 4 only) 1 byte
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- // It has been observed that the DigitalVideoCastMember has
- return 8 + 4 + 1; // No flags (so instead of 2 extra bytes, we have 1) for FilmLoopCastMember
+ // It has been observed that the DigitalVideoCastMember has
+ return 8 + 4 + 2 + 1; // No flags1 (differnt from flags read in the constructor) (so instead of 2 extra bytes, we have 1) for FilmLoopCastMember
} else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
- return 8 + 4;
+ return 8 + 4 + 2;
}
warning("FilmLoopCastMember::getCastDataSize(): unhandled or invalid cast version: %d", _cast->_version);
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index 8dbea7f0f49..8b9a9a69ee3 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -137,57 +137,19 @@ void PaletteCastMember::unload() {
// No unload necessary.
}
-void PaletteCastMember::writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset) {
- uint32 castSize = getPaletteDataSize() + 8;
-
- /**/
- byte *dumpData = nullptr;
- dumpData = (byte *)calloc(castSize, sizeof(byte));
- writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
- /**/
-
- // writeStream->seek(offset);
- writeStream->writeUint32LE(MKTAG('C', 'L', 'U', 'T'));
- writeStream->writeUint32LE(getPaletteDataSize());
-
- const byte *pal = _palette->palette;
-
- for (int i = 0; i < _palette->length; i++) {
- writeStream->writeByte(pal[3 * i]);
- writeStream->writeByte(pal[3 * i]);
-
- writeStream->writeByte(pal[3 * i + 1]);
- writeStream->writeByte(pal[3 * i + 1]);
-
- writeStream->writeByte(pal[3 * i + 2]);
- writeStream->writeByte(pal[3 * i + 2]);
- }
-
- dumpFile("PaletteData", _castId, MKTAG('C', 'L', 'U', 'T'), dumpData, castSize);
- delete writeStream;
-}
-
// PaletteCastMember has no data in the 'CASt' resource or is ignored
-// This is the data in 'CASt' resource
+// This is the data in 'CASt' resource
uint32 PaletteCastMember::getCastDataSize() {
if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
// It has been observed as well that the Data size in PaletteCastMember's CASt resource is 0 for d5
return 0;
} else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
// (castType (see Cast::loadCastData() for Director 4 only) 1 byte
- return 1; // Since SoundCastMember doesn't have any flags
+ return 1; // Since SoundCastMember doesn't have any flags
}
return 0;
}
-uint32 PaletteCastMember::getPaletteDataSize() {
- // This is the actual Palette data, in the 'CLUT' resource
- // PaletteCastMembers data stored in the 'CLUT' resource does not change in size (may change in content) (need to verify)
- // Hence their original size can be written
- // This is the length of the 'CLUT' resource without the header and size
- return _palette->length * 6;
-}
-
void PaletteCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
// This should never get triggered
// Since there is no data to write
diff --git a/engines/director/castmember/palette.h b/engines/director/castmember/palette.h
index d62cacd9142..3e25f4e26ce 100644
--- a/engines/director/castmember/palette.h
+++ b/engines/director/castmember/palette.h
@@ -43,11 +43,9 @@ public:
void load() override;
void unload() override;
- void writePaletteData(Common::MemoryWriteStream *writeStream, uint32 offset);
-
+ uint32 writeSTXTResource(Common::MemoryWriteStream *writeStream, uint32 offset);
uint32 getCastDataSize() override; // This is the size of the data in the 'CASt' resource
void writeCastData(Common::MemoryWriteStream *writeStream) override;
- uint32 getPaletteDataSize();
PaletteV4 *_palette;
};
@@ -55,4 +53,3 @@ public:
} // End of namespace Director
#endif
-
\ No newline at end of file
diff --git a/engines/director/castmember/richtext.cpp b/engines/director/castmember/richtext.cpp
index 9e492060b68..82dbf407db0 100644
--- a/engines/director/castmember/richtext.cpp
+++ b/engines/director/castmember/richtext.cpp
@@ -262,11 +262,11 @@ void RichTextCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
_pf32.colorToRGB(_bgColor, r, g, b);
writeStream->writeByte(r);
- writeStream->writeByte(0);
+ writeStream->writeByte(0);
writeStream->writeByte(g);
- writeStream->writeByte(0);
+ writeStream->writeByte(0);
writeStream->writeByte(b);
- writeStream->writeByte(0);
+ writeStream->writeByte(0);
} else {
warning("RichTextCastMember()::writeCastData(): >D5 isn't handled");
}
diff --git a/engines/director/castmember/script.cpp b/engines/director/castmember/script.cpp
index 30138fc66ae..8023986c79c 100644
--- a/engines/director/castmember/script.cpp
+++ b/engines/director/castmember/script.cpp
@@ -143,10 +143,10 @@ Common::String ScriptCastMember::formatInfo() {
uint32 ScriptCastMember::getCastDataSize() {
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- // 2 bytes for type and unk1 + 1 byte for castType (see Cast::loadCastData() for Director 4 only
+ // 2 bytes for type and unk1 + 1 byte for castType (see Cast::loadCastData() for Director 4 only
return 2 + 1;
} else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
- // type and unk1: 2 bytes
+ // type and unk1: 2 bytes
return 2;
} else {
warning("ScriptCastMember::writeCastData(): invalid or unhandled Script version: %d", _cast->_version);
diff --git a/engines/director/castmember/shape.cpp b/engines/director/castmember/shape.cpp
index 887a61ef878..4d27d18996f 100644
--- a/engines/director/castmember/shape.cpp
+++ b/engines/director/castmember/shape.cpp
@@ -224,7 +224,7 @@ uint32 ShapeCastMember::getCastDataSize() {
// _fillType : 1 byte
// _lineThickness : 1 byte
// _lineDirection : 1 byte
- // Total : 17 bytes
+ // Total : 17 bytes
// For Director 4 : 1 byte extra for casttype (See Cast::loadCastData())
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
return 17 + 1;
@@ -239,7 +239,7 @@ uint32 ShapeCastMember::getCastDataSize() {
void ShapeCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
writeStream->writeByte(0);
writeStream->writeByte(1);
-
+
Movie::writeRect(writeStream, _initialRect);
writeStream->writeUint16LE(_pattern);
diff --git a/engines/director/castmember/sound.cpp b/engines/director/castmember/sound.cpp
index a8f669c5b8c..85b3ae62231 100644
--- a/engines/director/castmember/sound.cpp
+++ b/engines/director/castmember/sound.cpp
@@ -200,7 +200,7 @@ bool SoundCastMember::setField(int field, const Datum &d) {
}
// Similar to PaletteCastMember, SoundCastMember has no data in the 'CASt' resource or is ignored
-// This is the data in 'CASt' resource
+// This is the data in 'CASt' resource
uint32 SoundCastMember::getCastDataSize() {
if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
return 0;
diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index 2dab071af01..e7b6865ffde 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -950,91 +950,31 @@ bool TextCastMember::setChunkField(int field, int start, int end, const Datum &d
}
void TextCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
- writeStream->writeByte(_borderSize);
- writeStream->writeByte(_gutterSize);
- writeStream->writeByte(_boxShadow);
- writeStream->writeByte(_textType);
- writeStream->writeByte(_textAlign);
- writeStream->writeSint16LE(_textAlign);
- writeStream->writeUint16LE(_bgpalinfo1);
- writeStream->writeUint16LE(_bgpalinfo2);
- writeStream->writeUint16LE(_bgpalinfo3);
- writeStream->writeUint16LE(_scroll);
-
- Movie::writeRect(writeStream, _initialRect);
- writeStream->writeUint16LE(_maxHeight);
- writeStream->writeByte(_textShadow);
- writeStream->writeByte(_textFlags);
-
- writeStream->writeUint16LE(_textHeight);
+ writeStream->writeByte(_borderSize); // 1 byte
+ writeStream->writeByte(_gutterSize); // 2 bytes
+ writeStream->writeByte(_boxShadow); // 3 bytes
+ writeStream->writeByte(_textType); // 4 bytes
+ writeStream->writeSint16LE(_textAlign); // 6 bytes
+ writeStream->writeUint16LE(_bgpalinfo1); // 8 bytes
+ writeStream->writeUint16LE(_bgpalinfo2); // 10 bytes
+ writeStream->writeUint16LE(_bgpalinfo3); // 12 bytes
+ writeStream->writeUint16LE(_scroll); // 14 bytes
+
+ Movie::writeRect(writeStream, _initialRect); // (+8) 22 bytes
+ writeStream->writeUint16LE(_maxHeight); // 24 bytes
+ writeStream->writeByte(_textShadow); // 25 bytes
+ writeStream->writeByte(_textFlags); // 26 bytes
+
+ writeStream->writeUint16LE(_textHeight); // 28 bytes
if (_type == kCastButton) {
- writeStream->writeUint16LE(_buttonType + 1);
+ writeStream->writeUint16LE(_buttonType + 1); // 30 bytes
}
}
uint32 TextCastMember::getCastDataSize() {
- // Need to verify if this changes, current observation
- return (_type == kCastButton) ? 31 : 29;
-}
-
-uint32 TextCastMember::writeSTXTResource(Common::MemoryWriteStream *writeStream, uint32 offset) {
- uint32 castSize = getSTXTResourceSize() + 10;
- byte *dumpData = nullptr;
- dumpData = (byte *)calloc(castSize, sizeof(byte));
-
- writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
-
- writeStream->seek(offset);
-
- writeStream->writeUint32BE(MKTAG('S', 'T', 'X', 'T'));
- writeStream->writeUint32BE(getSTXTResourceSize() + 8); // Size of the STXT resource without the header and size
-
- writeStream->writeUint32BE(12); // This is the offset, if it's not 12, we throw an error and exit ScummVM
- writeStream->writeUint32BE(_ptext.size());
- // Encode only in one format, original may be encoded in multiple formats
- // Size of one Font Style is 20 + The number of encodings takes 2 bytes
- writeStream->writeUint32BE(20 + 2);
-
- Common::CodePage encoding = detectFontEncoding(_cast->_platform, _fontId);
- writeStream->writeString(_ptext.encode(encoding)); // Currently using MacRoman encoding only, may change later to include others
-
- writeStream->writeUint16BE(1); // Only one formatting: MacRoman
-
- writeStream->writeUint32BE(0); // FontStyle::formatStartOffset
- writeStream->writeUint16BE(_height); // FontStyle::height // Apparently height doesn't matter
- writeStream->writeUint16BE(_ascent); // FontStyle::ascent // And neither does ascent
-
- writeStream->writeUint16BE(_fontId); // FontStyle::fontId
- writeStream->writeByte(_textSlant); // FontStyle::textSlant
- writeStream->writeByte(0); // padding
- writeStream->writeUint16BE(_fontSize); // FontStyle::fontSize
-
- writeStream->writeUint16BE(_fgpalinfo1); // FontStyle:r
- writeStream->writeUint16BE(_fgpalinfo2); // FontStyle:g
- writeStream->writeUint16BE(_fgpalinfo3); // FontStyle:b
-
- Common::DumpFile out;
- char buf[256];
- Common::sprintf_s(buf, "./dumps/%d-%s-%s", _castId, tag2str(MKTAG('S', 'T', 'X', 'T')), "WrittenSTXTResource");
-
- // Write the movie out, stored in dumpData
- if (out.open(buf, true)) {
- out.write(dumpData, castSize);
- out.flush();
- out.close();
- debugC(3, kDebugLoading, "RIFXArchive::writeStream:Saved the movie as file %s", buf);
- } else {
- warning("RIFXArchive::writeStream: Error saving the file %s", buf);
- }
- free(dumpData);
- delete writeStream;
- return getSTXTResourceSize() + 8;
-}
-
-uint32 TextCastMember::getSTXTResourceSize() {
- // Header (offset, string length, data length) + text string + data (FontStyle)
- return 12 + _ptext.size() + 22;
+ // In total 30 bytes for text and 28 for button
+ return (_type == kCastButton) ? 30 : 28;
}
} // End of namespace Director
diff --git a/engines/director/castmember/text.h b/engines/director/castmember/text.h
index a813b93e7b7..d81f3f9882c 100644
--- a/engines/director/castmember/text.h
+++ b/engines/director/castmember/text.h
@@ -93,10 +93,7 @@ public:
void unload() override;
void writeCastData(Common::MemoryWriteStream *writeStream) override;
- uint32 writeSTXTResource(Common::MemoryWriteStream *writeStream, uint32 offset);
-
uint32 getCastDataSize() override; // This is the size of the data in the 'CASt' resource
- uint32 getSTXTResourceSize();
uint8 _borderSize;
uint8 _gutterSize;
diff --git a/engines/director/castmember/transition.cpp b/engines/director/castmember/transition.cpp
index 836b3983ce7..aac0a4b3dbc 100644
--- a/engines/director/castmember/transition.cpp
+++ b/engines/director/castmember/transition.cpp
@@ -146,7 +146,7 @@ void TransitionCastMember::writeCastData(Common::MemoryWriteStream *writeStream)
writeStream->writeByte(_chunkSize);
writeStream->writeByte((uint8)_transType);
writeStream->writeByte(_flags);
- writeStream->writeUint16LE(_durationMillis);
+ writeStream->writeUint16LE(_durationMillis);
} else {
warning("RichTextCastMember()::writeCastData(): CastMember version invalid or not handled");
}
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index b6c3f302ae6..ed8f30e02f4 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -385,6 +385,7 @@ Common::Error DirectorEngine::run() {
if (debugChannelSet(-1, kDebugSaving)) {
Common::Path writePath("./dumps/writtenMovie.dir");
_mainArchive->writeToFile(writePath);
+ getCurrentMovie()->getCast()->saveCast();
}
return Common::kNoError;
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 24cb3fedd41..fc040e6c80f 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -333,20 +333,20 @@ InfoEntries Movie::loadInfoEntries(Common::SeekableReadStreamEndian &stream, uin
void Movie::saveInfoEntries(Common::MemoryWriteStream *writeStream, InfoEntries info) {
// The writing functionality was intrioduced in Director 4
- writeStream->writeUint32BE(20); // offset: d4 and up movies is always 20
+ writeStream->writeUint32BE(20); // offset: d4 and up movies is always 20
writeStream->writeUint32BE(info.unk1);
writeStream->writeUint32BE(info.unk2);
- writeStream->writeUint32BE(info.flags);
+ writeStream->writeUint32BE(info.flags);
writeStream->writeUint32BE(info.scriptId);
writeStream->writeUint16BE(info.strings.size()); // count of strings in the info
-
+
uint32 length = 0;
- writeStream->writeUint32LE(length);
+ writeStream->writeUint32BE(length);
for (uint16 i = 0; i < info.strings.size(); i++) {
- length += info.strings[i].len;
- writeStream->writeUint32LE(length);
+ length += info.strings[i].len;
+ writeStream->writeUint32BE(length);
}
-
+
for (uint16 i = 0; i < info.strings.size(); i++) {
writeStream->write(info.strings[i].data, info.strings[i].len);
}
diff --git a/engines/director/stxt.cpp b/engines/director/stxt.cpp
index 278a3ee9555..ce9339825d0 100644
--- a/engines/director/stxt.cpp
+++ b/engines/director/stxt.cpp
@@ -153,18 +153,18 @@ void FontStyle::read(Common::ReadStreamEndian &stream, Cast *cast) {
}
void FontStyle::write(Common::MemoryWriteStream *writeStream) {
- writeStream->writeUint32LE(formatStartOffset);
- writeStream->writeUint16LE(height);
- writeStream->writeUint16LE(ascent);
- writeStream->writeUint16LE(fontId);
+ writeStream->writeUint32BE(formatStartOffset);
+ writeStream->writeUint16BE(height);
+ writeStream->writeUint16BE(ascent);
+ writeStream->writeUint16BE(fontId);
writeStream->writeByte(textSlant);
- writeStream->seek(1, SEEK_CUR); // padding
- writeStream->writeUint16LE(fontSize);
+ writeStream->writeByte(0); // padding
+ writeStream->writeUint16BE(fontSize);
- writeStream->writeUint16LE(r);
- writeStream->writeUint16LE(g);
- writeStream->writeUint16LE(b);
+ writeStream->writeUint16BE(r);
+ writeStream->writeUint16BE(g);
+ writeStream->writeUint16BE(b);
}
} // End of namespace Director
diff --git a/engines/director/stxt.h b/engines/director/stxt.h
index d245617b841..95bc1245048 100644
--- a/engines/director/stxt.h
+++ b/engines/director/stxt.h
@@ -24,7 +24,7 @@
namespace Common {
class ReadStreamEndian;
-class MemoryWriteStream;
+class MemoryWriteStream;
}
namespace Director {
Commit: 85c7db7a6037e1f251e8bf006fbc912247dfcdb9
https://github.com/scummvm/scummvm/commit/85c7db7a6037e1f251e8bf006fbc912247dfcdb9
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Fix chechsum calculation mistake
Use _platformID instead of _platform to calculate checksum
Remove duplicated version variable
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index cad2cffd35a..1e9f298f3e7 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -319,7 +319,6 @@ bool Cast::loadConfig() {
if (stream->size() > 36) {
stream->seek(36); // Seek to version
_version = stream->readSint16(); // Read version for post-D3
- _directorVersion = _version;
stream->seek(0); // Seek to start of stream
}
@@ -411,7 +410,7 @@ bool Cast::loadConfig() {
_field18 = stream->readByte();
_field19 = stream->readSint32();
- _directorVersion = stream->readUint16();
+ /* version = */ stream->readUint16(); // We've already read it, this is offset 36
_field21 = stream->readSint16();
_field22 = stream->readSint32();
@@ -476,7 +475,7 @@ bool Cast::loadConfig() {
check += _field24 + 24;
check *= _field25 + 25;
check += _frameRate + 26;
- check *= _platform + 27;
+ check *= _platformID + 27;
check *= (_protection * 0xE06) + 0xFF450000u;
check ^= MKTAG('r', 'a', 'l', 'f');
@@ -566,7 +565,7 @@ void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
writeStream->writeByte(_field18); // 30
writeStream->writeSint32LE(_field19); // 34
- writeStream->writeUint16LE(_directorVersion); // 36
+ writeStream->writeUint16LE(_version); // 36
writeStream->writeUint16LE(_field21); // 38
writeStream->writeUint32LE(_field22); // 40
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 0928b4a3215..22081ee17a7 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -155,7 +155,6 @@ private:
public:
Archive *_castArchive;
- uint16 _version;
Common::Platform _platform;
uint16 _castLibID;
uint16 _libResourceId;
@@ -216,7 +215,7 @@ public:
/* 30 */ uint8 _field17;
/* 31 */ uint8 _field18;
/* 32 */ int32 _field19;
- /* 36 */ int16 _directorVersion;
+ /* 36 */ int16 _version;
/* 38 */ int16 _field21;
/* 40 */ int32 _field22;
/* 44 */ int32 _field23;
Commit: a9432dcce69bdf414a9e5ff53f730b8b391f6228
https://github.com/scummvm/scummvm/commit/a9432dcce69bdf414a9e5ff53f730b8b391f6228
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-07-07T11:42:14+02:00
Commit Message:
DIRECTOR: Minor Formatting Changes
Fixed comment spelling mistakes
Removed the extra unnecessary `writeCAStResource()` in CastMember
Changed paths:
engines/director/archive.cpp
engines/director/cast.cpp
engines/director/cast.h
engines/director/castmember/bitmap.cpp
engines/director/castmember/castmember.cpp
engines/director/castmember/castmember.h
engines/director/castmember/digitalvideo.cpp
engines/director/castmember/filmloop.cpp
engines/director/castmember/richtext.cpp
diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index fd5030c9327..a65f9e89770 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -1269,8 +1269,8 @@ bool RIFXArchive::writeMemoryMap(Common::SeekableMemoryWriteStream *writeStream)
uint32 newResCount = _resources.size();
- // Need to recalcualte the following things
- // Similarl to the RIFX resource, we'll need to update the size of the mmap resource whenever there is some change
+ // Need to recalculate the following things
+ // Similarly to the RIFX resource, we'll need to update the size of the mmap resource whenever there is some change
writeStream->writeUint32LE(getResourceSize(MKTAG('m', 'm', 'a', 'p'), 0));
writeStream->writeUint16LE(_mmapHeaderSize);
writeStream->writeUint16LE(_mmapEntrySize);
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 1e9f298f3e7..fb8bb4808f9 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -494,7 +494,7 @@ bool Cast::loadConfig() {
_defaultPalette.member -= 1;
else
_defaultPalette.castLib = DEFAULT_CAST_LIB;
- for (int i = 0; i < 0x08; i++){
+ for (int i = 0; i < 0x08; i++) {
stream->readByte();
}
} else if (_version >= kFileVer500 && _version < kFileVer600) {
@@ -540,9 +540,9 @@ void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
}
writeStream->seek(offset); // This will allow us to write cast config at any offset
- // These offsets are only for Director Version 4 to Director version 6
- // offsets
- writeStream->writeUint16LE(_len); // 0 // This will change
+ // These offsets are only for Director Version 4 to Director version 6
+ // offsets
+ writeStream->writeUint16LE(_len); // 0 // This will change
writeStream->writeUint16LE(_fileVersion); // 2
Movie::writeRect(writeStream, _checkRect); // 4, 6, 8, 10
@@ -565,7 +565,7 @@ void Cast::saveConfig(Common::MemoryWriteStream *writeStream, uint32 offset) {
writeStream->writeByte(_field18); // 30
writeStream->writeSint32LE(_field19); // 34
- writeStream->writeUint16LE(_version); // 36
+ writeStream->writeUint16LE(_version); // 36
writeStream->writeUint16LE(_field21); // 38
writeStream->writeUint32LE(_field22); // 40
@@ -806,7 +806,7 @@ void Cast::saveCast() {
// So, RIFXArchive::getResourceDetail will return the list of IDs present in the keytable
// Whereas, in the _loadedCast, the key of these Cast members is given by castId
for (auto &it : cast) {
- // I need to call this just because I need the id
+ // I need to call this just because I need the id
Resource res = _castArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), it);
uint16 id = res.castId + _castArrayStart; // Never encountered _castArrayStart != 0 till now
uint32 castSize = 0;
@@ -826,41 +826,24 @@ void Cast::saveCast() {
byte *dumpData = (byte *)calloc(castSize, sizeof(byte));
Common::SeekableMemoryWriteStream *writeStream = new Common::SeekableMemoryWriteStream(dumpData, castSize);
- CastType type = kCastTypeAny;
+ CastType type = kCastTypeAny;
if (!_loadedCast->contains(id)) {
- writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
- Common::SeekableReadStreamEndian *stream = getResource(MKTAG('C', 'A', 'S', 't'), it);
- uint32 size = stream->size(); // This is the size of the Resource without header and size entry itself
- writeStream->writeUint32LE(size);
- writeStream->writeStream(stream);
+ writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
+ Common::SeekableReadStreamEndian *stream = getResource(MKTAG('C', 'A', 'S', 't'), it);
+ uint32 size = stream->size(); // This is the size of the Resource without header and size entry itself
+ writeStream->writeUint32LE(size);
+ writeStream->writeStream(stream);
- delete stream;
+ delete stream;
} else {
CastMember *target = _loadedCast->getVal(id);
- type = target->_type;
-
- switch (target->_type) {
- case kCastPalette:
- case kCastBitmap:
- case kCastText:
- case kCastButton:
- case kCastDigitalVideo:
- case kCastFilmLoop:
- case kCastMovie:
- case kCastSound:
- case kCastRichText:
- case kCastLingoScript:
- case kCastShape:
- target->writeCAStResource(writeStream, 0);
- break;
- default:
- target->writeCAStResource(writeStream, 0, it);
- break;
- }
+ type = target->_type;
+ target->writeCAStResource(writeStream, 0);
+ break;
}
- dumpFile(castType2str(type), res.index, MKTAG('C', 'A', 'S', 't'), dumpData, castSize);
+ dumpFile(castType2str(type), res.index, MKTAG('C', 'A', 'S', 't'), dumpData, castSize);
delete writeStream;
}
@@ -868,9 +851,9 @@ void Cast::saveCast() {
void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId) {
// The structure of the CastMemberInfo is as follows:
- // First some headers: offset, unkonwns and flags, and then a count of strings to be read
+ // First some headers: offset, unknown and flags, and then a count of strings to be read
// (These strings contain properties of the cast member like filename, script attached to it, name, etc.)
- // After the header, we have the next data is the lengths of the strings,
+ // After the header, we have a sequence of the lengths of the strings,
// The first int is 0, the second int is 0 + length of the first string, the third int is 0 + length of first string + length of second string and so on
// After the lengths of the strings are the actual strings
@@ -1007,10 +990,10 @@ void Cast::writeCastInfo(Common::MemoryWriteStream *writeStream, uint32 castId)
Movie::saveInfoEntries(writeStream, castInfo);
}
-// This function is called three separate times
-// first when writing this 'CASt' resource in memory map (in getCastResourceSize())
-// second when writing the 'CASt' resource itself (in getCastResourceSize())
-// and thirdly when we're writing the info size in the 'CASt' resource
+// This function is called three separate times:
+// First, when writing this 'CASt' resource in memory map (in getCastResourceSize())
+// Second, when writing the 'CASt' resource itself (in getCastResourceSize())
+// Third, when we're writing the info size in the 'CASt' resource
// All three times, it returns the same value, this could be more efficient
uint32 Cast::getCastInfoSize(uint32 castId) {
CastMemberInfo *ci = getCastMemberInfo(castId);
@@ -1033,7 +1016,7 @@ uint32 Cast::computeChecksum() {
}
// The 'CASt' resource has strings containing information about the respective CastMember
-// This function is for retreiving the size of each while writing them back
+// This function is for retrieving the size of each while writing them back
uint32 Cast::getCastInfoStringLength(uint32 stringIndex, CastMemberInfo *ci) {
switch (stringIndex) {
default:
@@ -1056,7 +1039,7 @@ uint32 Cast::getCastInfoStringLength(uint32 stringIndex, CastMemberInfo *ci) {
return ci->type.size();
case 6:
- // Need a better check to see if script edit info is valid
+ // Need a better check to see if the script edit info is valid
if (ci->scriptEditInfo.valid) {
return 18; // The length of an edit info
}
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 22081ee17a7..de88ef24853 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -187,7 +187,7 @@ public:
/* 0 */ uint16 _len;
/* 2 */ uint16 _fileVersion;
/* 4, 6, 8, 10 */ Common::Rect _checkRect;
- /* 12 */ uint16 _castArrayStart;
+ /* 12 */ uint16 _castArrayStart;
/* 14 */ uint16 _castArrayEnd;
/* 16 */ byte _readRate;
/* 17 */ byte _lightswitch;
diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index 4b8804ef4ac..bb869190d10 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -989,7 +989,7 @@ uint32 BitmapCastMember::getCastDataSize() {
dataSize += 4;
// if (_cast->_version >= kFileVer500) {
// dataSize += 2; // Added two bytes for _clut.member
- // dataSize -= 2; // Removed two byte for castType (See Cast::loadCastData())
+ // dataSize -= 2; // Removed two bytes for _castType and _flags (See Cast::loadCastData())
// }
if (_flags2 != 0) {
@@ -1033,7 +1033,7 @@ void BitmapCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
writeStream->writeUint16BE(_flags2);
}
}
- // Ignoring the tail in the loading as well as saving
+ // Ignoring the tail during loading as well as saving
}
} // End of namespace Director
diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 1d323fb0f89..de457ff8c49 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -308,24 +308,11 @@ void CastMember::unload() {
_loaded = false;
}
-// Default implementation to write the 'CASt' resources as they are
// Cast members have two types of "information", one is _data_ and the other is _info_
// _data_ is the actual "data" (e.g. the pixel image data of a bitmap, sound data of a sound cast member)
// Whereas _info_ is metadata (size, name, flags, etc.)
-// Some castmembers have their _data_ as well as _info_ in this very 'CASt' resource, e.g. TextCastMember
+// Some cast members have their _data_ as well as _info_ in this very 'CASt' resource, e.g. TextCastMember
// Whereas some other have their _info_ in a 'CASt' resource and _data_ in a dedicated resource (e.g. PaletteCastMember has 'CLUT' resource)
-uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 castIndex) {
- // We'll need the original resource stream if there is no change in the castmember
- Common::SeekableReadStreamEndian *stream = _cast->getResource(MKTAG('C', 'A', 'S', 't'), castIndex);
- uint32 size = stream->size();
-
- writeStream->writeUint32LE(MKTAG('C', 'A', 'S', 't'));
- writeStream->writeUint32LE(size);
-
- writeStream->writeStream(stream);
- return size + 8;
-}
-
uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset) {
uint32 castResourceSize = getCastResourceSize();
@@ -363,7 +350,7 @@ uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uin
_cast->writeCastInfo(writeStream, _castId);
}
- // For cast members with dedicated resrouces for data, the castDataToWrite is zero
+ // For cast members with dedicated resources for data, the castDataToWrite is zero
if (castDataToWrite) {
writeCastData(writeStream);
}
@@ -373,16 +360,16 @@ uint32 CastMember::writeCAStResource(Common::MemoryWriteStream *writeStream, uin
// This is the data that is inside the 'CASt' resource
// These functions (getCastDataSize() and writeCastData() default implementations, are not supposed to be called
-// If the data is modified in the castmember, we implement a custom getCastDataSize() and writeCastData() for that member
+// If the data is modified in the cast member, we implement a custom getCastDataSize() and writeCastData() for that member
// If it is not modified, then we write it as it is from the original source in the overridden
// writeCAStResource(Common::MemoryWriteStream, uint32, uint32) function which doesn't call these default functions
uint32 CastMember::getCastDataSize() {
- debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size");
+ warning("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data size");
return _castDataSize;
}
void CastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
- debug("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data");
+ warning("CastMember::getDataSize(): Defualt implementation of 'CASt' resource data");
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
if (_flags1 != 0xFF) {
diff --git a/engines/director/castmember/castmember.h b/engines/director/castmember/castmember.h
index 6574e27d3f0..bd300b20b5e 100644
--- a/engines/director/castmember/castmember.h
+++ b/engines/director/castmember/castmember.h
@@ -101,11 +101,10 @@ public:
virtual CollisionTest isWithin(const Common::Rect &bbox, const Common::Point &pos, InkType ink) { return bbox.contains(pos) ? kCollisionYes : kCollisionNo; }
- // When writing the 'CASt' resource, the general strucutre is the same for all the CastMembers
+ // When writing the 'CASt' resource, the general structure is the same for all the CastMembers
// Three parts to a 'CASt' resource (header + _info_, _data_)
// The headers, are common, the _info_ writing is handled by the Cast class, so no worries there
- // So the only thing that differs is the _data_, for which we'll have separate implementations for each CastMember
- uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset, uint32 castIndex);
+ // So, the only thing that differs is the _data_, for which we'll have separate implementations for each CastMember
uint32 writeCAStResource(Common::MemoryWriteStream *writeStream, uint32 offset);
uint32 getCastInfoSize();
uint32 getCastResourceSize();
diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index e8f2833d5fb..f5d94c2df28 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -657,7 +657,7 @@ uint32 DigitalVideoCastMember::getCastDataSize() {
// We're only reading the _initialRect and _vflags from the Cast Data
// _initialRect : 8 bytes + _vflags : 4 bytes + castType and flags1 (see Cast::loadCastData() for Director 4 only) 2 byte
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- // It has been observed that the DigitalVideoCastMember has
+ // It has been observed that the DigitalVideoCastMember has _flags set to 0x00
return (_flags1 == 0xFF) ? 13 : 14;
} else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
return 8 + 4;
diff --git a/engines/director/castmember/filmloop.cpp b/engines/director/castmember/filmloop.cpp
index 7ced1451e15..723e29840d6 100644
--- a/engines/director/castmember/filmloop.cpp
+++ b/engines/director/castmember/filmloop.cpp
@@ -716,10 +716,10 @@ Common::Point FilmLoopCastMember::getRegistrationOffset(int16 currentWidth, int1
uint32 FilmLoopCastMember::getCastDataSize() {
// We're only reading the _initialRect and _vflags from the Cast Data
- // _initialRect : 8 bytes + flags : 4 bytes + 2 bytes unk1 + (castType (see Cast::loadCastData() for Director 4 only) 1 byte
+ // _initialRect : 8 bytes + flags : 4 bytes + 2 bytes unk1 + 2 bytes (castType and _flags1 (see Cast::loadCastData() for Director 4 only)
if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
- // It has been observed that the DigitalVideoCastMember has
- return 8 + 4 + 2 + 1; // No flags1 (differnt from flags read in the constructor) (so instead of 2 extra bytes, we have 1) for FilmLoopCastMember
+ // It has been observed that the FilmCastMember has _flags as 0x00
+ return 8 + 4 + 2 + 2;
} else if (_cast->_version >= kFileVer500 && _cast->_version < kFileVer600) {
return 8 + 4 + 2;
}
diff --git a/engines/director/castmember/richtext.cpp b/engines/director/castmember/richtext.cpp
index 82dbf407db0..3e357b9c16d 100644
--- a/engines/director/castmember/richtext.cpp
+++ b/engines/director/castmember/richtext.cpp
@@ -261,12 +261,9 @@ void RichTextCastMember::writeCastData(Common::MemoryWriteStream *writeStream) {
writeStream->writeByte(b);
_pf32.colorToRGB(_bgColor, r, g, b);
- writeStream->writeByte(r);
- writeStream->writeByte(0);
- writeStream->writeByte(g);
- writeStream->writeByte(0);
- writeStream->writeByte(b);
- writeStream->writeByte(0);
+ writeStream->writeUint16BE(r << 8);
+ writeStream->writeUint16BE(g << 8);
+ writeStream->writeUint16BE(b << 8);
} else {
warning("RichTextCastMember()::writeCastData(): >D5 isn't handled");
}
More information about the Scummvm-git-logs
mailing list