DIRECTOR: Refactor movie loaders to allow loading from executables
This commit is contained in:
parent
05ca29629a
commit
d76b359ac2
3 changed files with 138 additions and 83 deletions
|
@ -52,12 +52,8 @@ Common::Error Window::loadInitialMovie() {
|
|||
debug(0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
Common::String movie = (_vm->getGameGID() == GID_TESTALL) ? getNextMovieFromQueue().movie : _vm->getEXEName();
|
||||
|
||||
if (g_director->getPlatform() == Common::kPlatformWindows) {
|
||||
loadEXE(movie);
|
||||
} else {
|
||||
probeProjector(movie);
|
||||
loadMac(movie);
|
||||
}
|
||||
loadINIStream();
|
||||
_mainArchive = openArchive(movie);
|
||||
|
||||
if (!_mainArchive) {
|
||||
warning("Cannot open main movie");
|
||||
|
@ -152,8 +148,10 @@ void Window::probeMacBinary(MacArchive *archive) {
|
|||
_nextMovie.movie = moviePath;
|
||||
warning("Replaced score name with: %s (from %s)", _nextMovie.movie.c_str(), sname.c_str());
|
||||
|
||||
delete _currentMovie;
|
||||
_currentMovie = nullptr;
|
||||
if (_currentMovie) {
|
||||
delete _currentMovie;
|
||||
_currentMovie = nullptr;
|
||||
}
|
||||
|
||||
probeProjector(moviePath);
|
||||
} else {
|
||||
|
@ -193,23 +191,34 @@ void Window::probeMacBinary(MacArchive *archive) {
|
|||
g_director->_allOpenResFiles.setVal(archive->getPathName(), archive);
|
||||
}
|
||||
|
||||
Archive *Window::openMainArchive(const Common::String movie) {
|
||||
debug(1, "openMainArchive(\"%s\")", movie.c_str());
|
||||
Archive *Window::openArchive(const Common::String movie) {
|
||||
debug(1, "openArchive(\"%s\")", movie.c_str());
|
||||
|
||||
_mainArchive = g_director->createArchive();
|
||||
|
||||
if (!_mainArchive->openFile(movie)) {
|
||||
delete _mainArchive;
|
||||
_mainArchive = nullptr;
|
||||
|
||||
warning("openMainArchive(): Could not open '%s'", movie.c_str());
|
||||
return nullptr;
|
||||
// If the archive is already open, don't reopen it;
|
||||
// just init from the existing archive. This prevents errors that
|
||||
// can happen when trying to load the same archive more than once.
|
||||
if (g_director->_allOpenResFiles.contains(movie) && SearchMan.hasFile(movie)) {
|
||||
return g_director->_allOpenResFiles.getVal(movie);
|
||||
}
|
||||
|
||||
return _mainArchive;
|
||||
Archive *result = nullptr;
|
||||
if (g_director->getPlatform() == Common::kPlatformWindows) {
|
||||
result = loadEXE(movie);
|
||||
} else {
|
||||
probeProjector(movie);
|
||||
result = loadMac(movie);
|
||||
}
|
||||
if (!result) {
|
||||
result = g_director->createArchive();
|
||||
if (!result->openFile(movie)) {
|
||||
delete result;
|
||||
result = nullptr;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::loadEXE(const Common::String movie) {
|
||||
void Window::loadINIStream() {
|
||||
Common::SeekableReadStream *iniStream = SearchMan.createReadStreamForMember("LINGO.INI");
|
||||
if (iniStream) {
|
||||
char *script = (char *)calloc(iniStream->size() + 1, 1);
|
||||
|
@ -226,31 +235,42 @@ void Window::loadEXE(const Common::String movie) {
|
|||
} else {
|
||||
warning("No LINGO.INI");
|
||||
}
|
||||
}
|
||||
|
||||
Archive *Window::loadEXE(const Common::String movie) {
|
||||
Common::SeekableReadStream *exeStream = SearchMan.createReadStreamForMember(Common::Path(movie, g_director->_dirSeparator));
|
||||
if (!exeStream)
|
||||
error("Failed to open EXE '%s'", g_director->getEXEName().c_str());
|
||||
if (!exeStream) {
|
||||
warning("Window::loadEXE(): Failed to open EXE '%s'", g_director->getEXEName().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Archive *result = nullptr;
|
||||
|
||||
uint32 initialTag = exeStream->readUint32LE();
|
||||
if (initialTag == MKTAG('R', 'I', 'F', 'X') || initialTag == MKTAG('X', 'F', 'I', 'R')) {
|
||||
// we've encountered a movie saved from Director, not a projector.
|
||||
loadEXERIFX(exeStream, 0);
|
||||
result = loadEXERIFX(exeStream, 0);
|
||||
} else if (initialTag == MKTAG('R', 'I', 'F', 'F') || initialTag == MKTAG('F', 'F', 'I', 'R')) { // This is just a normal movie
|
||||
_mainArchive = new RIFFArchive();
|
||||
result = new RIFFArchive();
|
||||
|
||||
if (!_mainArchive->openStream(exeStream, 0))
|
||||
error("Failed to load RIFF");
|
||||
if (!result->openStream(exeStream, 0)) {
|
||||
warning("Window::loadEXE(): Failed to load RIFF");
|
||||
delete result;
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
Common::WinResources *exe = Common::WinResources::createFromEXE(movie);
|
||||
if (!exe)
|
||||
error("Failed to open EXE '%s'", g_director->getEXEName().c_str());
|
||||
if (!exe) {
|
||||
warning("Window::loadEXE(): Failed to open EXE '%s'", g_director->getEXEName().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Common::Array<Common::WinResourceID> versions = exe->getIDList(Common::kWinVersion);
|
||||
for (uint i = 0; i < versions.size(); i++) {
|
||||
Common::WinResources::VersionInfo *info = exe->getVersionResource(versions[i]);
|
||||
|
||||
for (Common::WinResources::VersionHash::const_iterator it = info->hash.begin(); it != info->hash.end(); ++it)
|
||||
warning("info <%s>: <%s>", it->_key.c_str(), it->_value.encode().c_str());
|
||||
warning("Window::loadEXE(): info <%s>: <%s>", it->_key.c_str(), it->_value.encode().c_str());
|
||||
|
||||
delete info;
|
||||
|
||||
|
@ -268,23 +288,25 @@ void Window::loadEXE(const Common::String movie) {
|
|||
exeStream->seek(exeStream->readUint32LE());
|
||||
|
||||
if (g_director->getVersion() >= 700) {
|
||||
loadEXEv7(exeStream);
|
||||
result = loadEXEv7(exeStream);
|
||||
} else if (g_director->getVersion() >= 500) {
|
||||
loadEXEv5(exeStream);
|
||||
result = loadEXEv5(exeStream);
|
||||
} else if (g_director->getVersion() >= 400) {
|
||||
loadEXEv4(exeStream);
|
||||
result = loadEXEv4(exeStream);
|
||||
} else if (g_director->getVersion() >= 200) {
|
||||
loadEXEv3(exeStream);
|
||||
result = loadEXEv3(exeStream);
|
||||
} else {
|
||||
error("Unhandled Windows EXE version %d", g_director->getVersion());
|
||||
warning("Window::loadEXE(): Unhandled Windows EXE version %d", g_director->getVersion());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_mainArchive)
|
||||
_mainArchive->setPathName(movie);
|
||||
if (result)
|
||||
result->setPathName(movie);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::loadEXEv3(Common::SeekableReadStream *stream) {
|
||||
Archive *Window::loadEXEv3(Common::SeekableReadStream *stream) {
|
||||
uint32 mmmSize = 0;
|
||||
Common::String mmmFileName;
|
||||
Common::String directoryName;
|
||||
|
@ -308,12 +330,12 @@ void Window::loadEXEv3(Common::SeekableReadStream *stream) {
|
|||
directoryName = directoryName_;
|
||||
} else {
|
||||
if (!SearchMan.hasFile(Common::Path(mmmFileName_, g_director->_dirSeparator)))
|
||||
warning("Failed to find MMM '%s'", mmmFileName_.c_str());
|
||||
warning("Window::loadEXEv3(): Failed to find MMM '%s'", mmmFileName_.c_str());
|
||||
else {
|
||||
Common::SeekableReadStream *const mmmFile_ = SearchMan.createReadStreamForMember(Common::Path(mmmFileName_, g_director->_dirSeparator));
|
||||
uint32 mmmFileSize_ = mmmFile_->size();
|
||||
if (mmmSize_ != mmmFileSize_)
|
||||
warning("File size for '%s' doesn't match. Got %d (0x%x), want %d (0x%x)", mmmFileName_.c_str(), mmmFileSize_, mmmFileSize_, mmmSize_, mmmSize_);
|
||||
warning("Window::loadEXEv3(): File size for '%s' doesn't match. Got %d (0x%x), want %d (0x%x)", mmmFileName_.c_str(), mmmFileSize_, mmmFileSize_, mmmSize_, mmmSize_);
|
||||
delete mmmFile_;
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +343,7 @@ void Window::loadEXEv3(Common::SeekableReadStream *stream) {
|
|||
debugC(1, kDebugLoading, "%s", "");
|
||||
}
|
||||
|
||||
Archive *result = nullptr;
|
||||
if (mmmSize) {
|
||||
uint32 riffOffset = stream->pos();
|
||||
|
||||
|
@ -347,25 +370,34 @@ void Window::loadEXEv3(Common::SeekableReadStream *stream) {
|
|||
}
|
||||
|
||||
|
||||
_mainArchive = new RIFFArchive();
|
||||
result = new RIFFArchive();
|
||||
|
||||
if (_mainArchive->openStream(stream, riffOffset))
|
||||
return;
|
||||
if (result->openStream(stream, riffOffset))
|
||||
return result;
|
||||
|
||||
warning("Failed to load RIFF from EXE");
|
||||
delete _mainArchive;
|
||||
_mainArchive = nullptr;
|
||||
warning("Window::loadEXEv3(): Failed to load RIFF from EXE");
|
||||
delete result;
|
||||
result = nullptr;
|
||||
delete stream;
|
||||
}
|
||||
|
||||
openMainArchive(mmmFileName);
|
||||
result = g_director->createArchive();
|
||||
|
||||
if (!result->openFile(mmmFileName)) {
|
||||
warning("Window::loadEXEv3(): Could not open '%s'", mmmFileName.c_str());
|
||||
delete result;
|
||||
result = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::loadEXEv4(Common::SeekableReadStream *stream) {
|
||||
Archive *Window::loadEXEv4(Common::SeekableReadStream *stream) {
|
||||
uint32 ver = stream->readUint32BE();
|
||||
|
||||
if (ver != MKTAG('P', 'J', '9', '3'))
|
||||
error("Invalid projector tag found in v4 EXE [%s]", tag2str(ver));
|
||||
if (ver != MKTAG('P', 'J', '9', '3')) {
|
||||
warning("Window::loadEXEv4(): Invalid projector tag found in v4 EXE [%s]", tag2str(ver));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 rifxOffset = stream->readUint32LE();
|
||||
/* uint32 fontMapOffset = */ stream->readUint32LE();
|
||||
|
@ -376,16 +408,18 @@ void Window::loadEXEv4(Common::SeekableReadStream *stream) {
|
|||
/* uint32 rifxOffsetAlt = */ stream->readUint32LE(); // equivalent to rifxOffset
|
||||
uint32 flags = stream->readUint32LE();
|
||||
|
||||
warning("PJ93 projector flags: %08x", flags);
|
||||
warning("Window::loadEXEv4(): PJ93 projector flags: %08x", flags);
|
||||
|
||||
loadEXERIFX(stream, rifxOffset);
|
||||
return loadEXERIFX(stream, rifxOffset);
|
||||
}
|
||||
|
||||
void Window::loadEXEv5(Common::SeekableReadStream *stream) {
|
||||
Archive *Window::loadEXEv5(Common::SeekableReadStream *stream) {
|
||||
uint32 ver = stream->readUint32LE();
|
||||
|
||||
if (ver != MKTAG('P', 'J', '9', '5'))
|
||||
error("Invalid projector tag found in v5 EXE [%s]", tag2str(ver));
|
||||
if (ver != MKTAG('P', 'J', '9', '5')) {
|
||||
warning("Window::loadEXEv5(): Invalid projector tag found in v5 EXE [%s]", tag2str(ver));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 rifxOffset = stream->readUint32LE();
|
||||
uint32 pflags = stream->readUint32LE();
|
||||
|
@ -398,16 +432,18 @@ void Window::loadEXEv5(Common::SeekableReadStream *stream) {
|
|||
stream->readUint32LE(); // number of driver files
|
||||
stream->readUint32LE(); // fontMapOffset
|
||||
|
||||
warning("PJ95 projector pflags: %08x flags: %08x", pflags, flags);
|
||||
warning("Window::loadEXEv5(): PJ95 projector pflags: %08x flags: %08x", pflags, flags);
|
||||
|
||||
loadEXERIFX(stream, rifxOffset);
|
||||
return loadEXERIFX(stream, rifxOffset);
|
||||
}
|
||||
|
||||
void Window::loadEXEv7(Common::SeekableReadStream *stream) {
|
||||
Archive *Window::loadEXEv7(Common::SeekableReadStream *stream) {
|
||||
uint32 ver = stream->readUint32LE();
|
||||
|
||||
if (ver != MKTAG('P', 'J', '0', '0') && ver != MKTAG('P', 'J', '0', '1'))
|
||||
error("Invalid projector tag found in v7 EXE [%s]", tag2str(ver));
|
||||
if (ver != MKTAG('P', 'J', '0', '0') && ver != MKTAG('P', 'J', '0', '1')) {
|
||||
warning("Window::loadEXEv7(): Invalid projector tag found in v7 EXE [%s]", tag2str(ver));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 rifxOffset = stream->readUint32LE();
|
||||
stream->readUint32LE(); // unknown
|
||||
|
@ -416,27 +452,40 @@ void Window::loadEXEv7(Common::SeekableReadStream *stream) {
|
|||
stream->readUint32LE(); // unknown
|
||||
stream->readUint32LE(); // some DLL offset
|
||||
|
||||
loadEXERIFX(stream, rifxOffset);
|
||||
return loadEXERIFX(stream, rifxOffset);
|
||||
}
|
||||
|
||||
void Window::loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset) {
|
||||
_mainArchive = new RIFXArchive();
|
||||
Archive *Window::loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset) {
|
||||
Archive *result = new RIFXArchive();
|
||||
|
||||
if (!_mainArchive->openStream(stream, offset))
|
||||
error("Failed to load RIFX from EXE");
|
||||
if (!result->openStream(stream, offset)) {
|
||||
warning("Window::loadEXERIFX(): Failed to load RIFX from EXE");
|
||||
delete result;
|
||||
result = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::loadMac(const Common::String movie) {
|
||||
Archive *Window::loadMac(const Common::String movie) {
|
||||
Archive *result = nullptr;
|
||||
if (g_director->getVersion() < 400) {
|
||||
// The data is part of the resource fork of the executable
|
||||
openMainArchive(movie);
|
||||
result = g_director->createArchive();
|
||||
|
||||
if (!result->openFile(movie)) {
|
||||
delete result;
|
||||
result = nullptr;
|
||||
warning("Window::loadMac(): Could not open '%s'", movie.c_str());
|
||||
}
|
||||
} else {
|
||||
// The RIFX is located in the data fork of the executable
|
||||
Common::SeekableReadStream *dataFork = Common::MacResManager::openFileOrDataFork(Common::Path(movie, g_director->_dirSeparator));
|
||||
if (!dataFork)
|
||||
error("Failed to open Mac binary '%s'", movie.c_str());
|
||||
_mainArchive = new RIFXArchive();
|
||||
_mainArchive->setPathName(movie);
|
||||
if (!dataFork) {
|
||||
warning("Window::loadMac(): Failed to open Mac binary '%s'", movie.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
result = new RIFXArchive();
|
||||
result->setPathName(movie);
|
||||
|
||||
// First we need to detect PPC vs. 68k
|
||||
|
||||
|
@ -451,12 +500,17 @@ void Window::loadMac(const Common::String movie) {
|
|||
startOffset = 0;
|
||||
}
|
||||
|
||||
if (!_mainArchive->openStream(dataFork, startOffset)) {
|
||||
warning("Failed to load RIFX from Mac binary");
|
||||
delete _currentMovie;
|
||||
_currentMovie = nullptr;
|
||||
if (!result->openStream(dataFork, startOffset)) {
|
||||
warning("Window::loadMac(): Failed to load RIFX from Mac binary");
|
||||
delete result;
|
||||
result = nullptr;
|
||||
if (_currentMovie) {
|
||||
delete _currentMovie;
|
||||
_currentMovie = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::loadStartMovieXLibs() {
|
||||
|
|
|
@ -313,7 +313,7 @@ bool Window::loadNextMovie() {
|
|||
delete _currentMovie;
|
||||
_currentMovie = nullptr;
|
||||
|
||||
Archive *mov = openMainArchive(_currentPath + Common::lastPathComponent(_nextMovie.movie, g_director->_dirSeparator));
|
||||
Archive *mov = openArchive(_currentPath + Common::lastPathComponent(_nextMovie.movie, g_director->_dirSeparator));
|
||||
|
||||
if (!mov)
|
||||
return false;
|
||||
|
|
|
@ -171,14 +171,15 @@ public:
|
|||
Common::Error loadInitialMovie();
|
||||
void probeProjector(const Common::String &movie);
|
||||
void probeMacBinary(MacArchive *archive);
|
||||
Archive *openMainArchive(const Common::String movie);
|
||||
void loadEXE(const Common::String movie);
|
||||
void loadEXEv3(Common::SeekableReadStream *stream);
|
||||
void loadEXEv4(Common::SeekableReadStream *stream);
|
||||
void loadEXEv5(Common::SeekableReadStream *stream);
|
||||
void loadEXEv7(Common::SeekableReadStream *stream);
|
||||
void loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset);
|
||||
void loadMac(const Common::String movie);
|
||||
void loadINIStream();
|
||||
Archive *openArchive(const Common::String movie);
|
||||
Archive *loadEXE(const Common::String movie);
|
||||
Archive *loadEXEv3(Common::SeekableReadStream *stream);
|
||||
Archive *loadEXEv4(Common::SeekableReadStream *stream);
|
||||
Archive *loadEXEv5(Common::SeekableReadStream *stream);
|
||||
Archive *loadEXEv7(Common::SeekableReadStream *stream);
|
||||
Archive *loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset);
|
||||
Archive *loadMac(const Common::String movie);
|
||||
void loadStartMovieXLibs();
|
||||
|
||||
// lingo/lingo-object.cpp
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue