From eb16a726e90133592f0ea0bde2bb94dab99d3911 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 14 Nov 2012 11:16:35 -0500 Subject: DIRECTOR: Add basic v3-5 exe parsing --- engines/director/detection.cpp | 4 ++ engines/director/director.cpp | 101 +++++++++++++++++++++++++++++++++++++++++ engines/director/director.h | 12 +++++ 3 files changed, 117 insertions(+) (limited to 'engines') diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp index 18e60091e7..e553c57d2f 100644 --- a/engines/director/detection.cpp +++ b/engines/director/detection.cpp @@ -54,6 +54,10 @@ Common::Language DirectorEngine::getLanguage() const { return _gameDescription->desc.language; } +Common::String DirectorEngine::getEXEName() const { + return _gameDescription->desc.filesDescriptions[0].fileName; +} + bool DirectorEngine::hasFeature(EngineFeature f) const { return (f == kSupportsRTL); diff --git a/engines/director/director.cpp b/engines/director/director.cpp index 840692ae7f..7fe0c6966a 100644 --- a/engines/director/director.cpp +++ b/engines/director/director.cpp @@ -22,12 +22,15 @@ #include "audio/mixer.h" +#include "common/debug.h" #include "common/scummsys.h" #include "common/error.h" +#include "common/stream.h" #include "common/system.h" #include "common/textconsole.h" #include "director/director.h" +#include "director/resource.h" namespace Director { @@ -37,13 +40,111 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam // Setup mixer syncSoundSettings(); + + _mainArchive = 0; } DirectorEngine::~DirectorEngine() { + delete _mainArchive; } Common::Error DirectorEngine::run() { + debug("Starting v%d Director game", getVersion()); + + if (getPlatform() == Common::kPlatformWindows) + loadEXE(); + return Common::kNoError; } +void DirectorEngine::loadEXE() { + Common::SeekableReadStream *exeStream = SearchMan.createReadStreamForMember(getEXEName()); + if (!exeStream) + error("Failed to open EXE '%s'", getEXEName().c_str()); + + exeStream->seek(-4, SEEK_END); + exeStream->seek(exeStream->readUint32LE()); + + switch (getVersion()) { + case 3: + loadEXEv3(exeStream); + break; + case 4: + loadEXEv4(exeStream); + break; + case 5: + loadEXEv5(exeStream); + break; + } +} + +void DirectorEngine::loadEXEv3(Common::SeekableReadStream *stream) { + stream->readUint32LE(); // unknown + stream->readUint16LE(); // unknown + stream->readUint32LE(); // Main MMM size + stream->readByte(); // zero + Common::String mmmFileName = readPascalString(*stream); + Common::String directoryName = readPascalString(*stream); + + debug("Main MMM: '%s'", mmmFileName.c_str()); + debug("Directory Name: '%s'", directoryName.c_str()); + + _mainArchive = new RIFFArchive(); + + // TODO: Convert MMM name and load + + delete stream; +} + +void DirectorEngine::loadEXEv4(Common::SeekableReadStream *stream) { + if (stream->readUint32BE() != MKTAG('P', 'J', '9', '3')) + error("Invalid projector tag found in v4 EXE"); + + uint32 rifxOffset = stream->readUint32LE(); + /* uint32 fontMapOffset = */ stream->readUint32LE(); + /* uint32 resourceForkOffset1 = */ stream->readUint32LE(); + /* uint32 resourceForkOffset2 = */ stream->readUint32LE(); + stream->readUint32LE(); // graphics DLL offset + stream->readUint32LE(); // sound DLL offset + /* uint32 rifxOffsetAlt = */ stream->readUint32LE(); // equivalent to rifxOffset + + loadEXERIFX(stream, rifxOffset); +} + +void DirectorEngine::loadEXEv5(Common::SeekableReadStream *stream) { + if (stream->readUint32LE() != MKTAG('P', 'J', '9', '5')) + error("Invalid projector tag found in v5 EXE"); + + uint32 rifxOffset = stream->readUint32LE(); + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + /* uint16 screenWidth = */ stream->readUint16LE(); + /* uint16 screenHeight = */ stream->readUint16LE(); + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + /* uint32 fontMapOffset = */ stream->readUint32LE(); + + loadEXERIFX(stream, rifxOffset); +} + +void DirectorEngine::loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset) { + stream->seek(offset); + + _mainArchive = new RIFXArchive(); + + if (!_mainArchive->openStream(stream)) + error("Failed to load RIFX from EXE"); +} + +Common::String DirectorEngine::readPascalString(Common::SeekableReadStream &stream) { + byte length = stream.readByte(); + Common::String x; + + while (length--) + x += (char)stream.readByte(); + + return x; +} + } // End of namespace Director diff --git a/engines/director/director.h b/engines/director/director.h index 6fe173c3f0..f1186f3b20 100644 --- a/engines/director/director.h +++ b/engines/director/director.h @@ -35,6 +35,7 @@ enum DirectorGameID { GID_GENERIC }; +class Archive; struct DirectorGameDescription; class DirectorEngine : public ::Engine { @@ -48,6 +49,7 @@ public: uint16 getVersion() const; Common::Platform getPlatform() const; Common::Language getLanguage() const; + Common::String getEXEName() const; bool hasFeature(EngineFeature f) const; @@ -56,6 +58,16 @@ protected: private: const DirectorGameDescription *_gameDescription; + + void loadEXE(); + void loadEXEv3(Common::SeekableReadStream *stream); + void loadEXEv4(Common::SeekableReadStream *stream); + void loadEXEv5(Common::SeekableReadStream *stream); + void loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset); + + Common::String readPascalString(Common::SeekableReadStream &stream); + + Archive *_mainArchive; }; } // End of namespace Director -- cgit v1.2.3