aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2012-11-14 11:16:35 -0500
committerEugene Sandulenko2016-08-03 23:40:36 +0200
commiteb16a726e90133592f0ea0bde2bb94dab99d3911 (patch)
treebdf2a95e0173a5163c033e2067ab16a81b6c0faa
parenta24668ff797675039135c4aeb2b4b78c800abe3e (diff)
downloadscummvm-rg350-eb16a726e90133592f0ea0bde2bb94dab99d3911.tar.gz
scummvm-rg350-eb16a726e90133592f0ea0bde2bb94dab99d3911.tar.bz2
scummvm-rg350-eb16a726e90133592f0ea0bde2bb94dab99d3911.zip
DIRECTOR: Add basic v3-5 exe parsing
-rw-r--r--engines/director/detection.cpp4
-rw-r--r--engines/director/director.cpp101
-rw-r--r--engines/director/director.h12
3 files changed, 117 insertions, 0 deletions
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