mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-07 18:31:37 +00:00
DIRECTOR: Add basic v3-5 exe parsing
This commit is contained in:
parent
a24668ff79
commit
eb16a726e9
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user