diff --git a/engines/xeen/dialogs_quests.cpp b/engines/xeen/dialogs_quests.cpp index 284e15781be..38011f1106c 100644 --- a/engines/xeen/dialogs_quests.cpp +++ b/engines/xeen/dialogs_quests.cpp @@ -245,7 +245,7 @@ void Quests::addButtons() { } void Quests::loadQuestNotes() { - File f("qnotes.bin", *_vm->_files->_sideArchives[_vm->getGameID() == GType_Clouds ? 0 : 1]); + File f("qnotes.bin", _vm->getGameID() == GType_Clouds ? GAME_ARCHIVE : ALTSIDE_ARCHIVE); while (f.pos() < f.size()) _questNotes.push_back(f.readString()); f.close(); diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp index bcee6bf9f6d..443a296bd46 100644 --- a/engines/xeen/files.cpp +++ b/engines/xeen/files.cpp @@ -183,35 +183,64 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S /*------------------------------------------------------------------------*/ +CCArchive *FileManager::_archives[3]; + FileManager::FileManager(XeenEngine *vm) { Common::File f; int sideNum = 0; _isDarkCc = vm->getGameID() == GType_DarkSide; - _sideArchives[0] = _sideArchives[1] = nullptr; + _archives[0] = _archives[1] = _archives[2] = nullptr; if (vm->getGameID() != GType_DarkSide) { - _sideArchives[0] = new CCArchive("xeen.cc", "xeen", true); - SearchMan.add("xeen", _sideArchives[0]); + _archives[0] = new CCArchive("xeen.cc", "xeen", true); + SearchMan.add("xeen", _archives[0]); sideNum = 1; } if (vm->getGameID() == GType_DarkSide || vm->getGameID() == GType_WorldOfXeen) { - _sideArchives[sideNum] = new CCArchive("dark.cc", "dark", true); - SearchMan.add("dark", _sideArchives[sideNum]); + _archives[sideNum] = new CCArchive("dark.cc", "dark", true); + SearchMan.add("dark", _archives[sideNum]); } - SearchMan.add("intro", new CCArchive("intro.cc", "intro", true)); + if (f.exists("intro.cc")) { + _archives[2] = new CCArchive("intro.cc", "intro", true); + SearchMan.add("intro", _archives[2]); + } + + File::_currentArchive = GAME_ARCHIVE; +} + +void FileManager::setGameCc(bool isDarkCc) { + _isDarkCc = isDarkCc; + File::_currentArchive = isDarkCc ? ALTSIDE_ARCHIVE : GAME_ARCHIVE; } /*------------------------------------------------------------------------*/ -void File::openFile(const Common::String &filename) { +ArchiveType File::_currentArchive; + +bool File::open(const Common::String &filename) { + CCArchive &arc = *FileManager::_archives[_currentArchive]; if (!Common::File::open(filename)) error("Could not open file - %s", filename.c_str()); + return true; } -void File::openFile(const Common::String &filename, Common::Archive &archive) { +bool File::open(const Common::String &filename, ArchiveType archiveType) { + if (archiveType == ANY_ARCHIVE) { + Common::File::open(filename); + } else { + CCArchive &archive = *FileManager::_archives[archiveType]; + Common::File::open(filename, archive); + } + + if (!isOpen()) + error("Could not open file - %s", filename.c_str()); + return true; +} + +bool File::open(const Common::String &filename, Common::Archive &archive) { if (!Common::File::open(filename, archive)) error("Could not open file - %s", filename.c_str()); } @@ -226,5 +255,4 @@ Common::String File::readString() { return result; } - } // End of namespace Xeen diff --git a/engines/xeen/files.h b/engines/xeen/files.h index fc75031a729..75389ff60e1 100644 --- a/engines/xeen/files.h +++ b/engines/xeen/files.h @@ -28,12 +28,17 @@ #include "common/file.h" #include "common/serializer.h" #include "graphics/surface.h" -#include "xeen/xsurface.h" namespace Xeen { +enum ArchiveType { + ANY_ARCHIVE = -1, GAME_ARCHIVE = 0, ALTSIDE_ARCHIVE = 1, + INTRO_ARCHIVE = 2 +}; + class XeenEngine; class CCArchive; +class File; #define SYNC_AS(SUFFIX,STREAM,TYPE,SIZE) \ template \ @@ -48,43 +53,59 @@ class CCArchive; } \ _bytesSynced += SIZE; \ } + /* * Main resource manager */ class FileManager { + friend class File; +private: + static CCArchive *_archives[3]; public: bool _isDarkCc; - CCArchive *_sideArchives[2]; public: /** * Instantiates the resource manager */ FileManager(XeenEngine *vm); - void setGameCc(bool isDarkCc) { _isDarkCc = isDarkCc; } + /** + * Set which game side files to use + */ + void setGameCc(bool isDarkCc); }; /** * Derived file class */ class File : public Common::File { +public: + static ArchiveType _currentArchive; public: File() : Common::File() {} - File(const Common::String &filename) { openFile(filename); } + File(const Common::String &filename) { File::open(filename); } + File(const Common::String &filename, ArchiveType archiveType) { + File::open(filename, archiveType); + } File(const Common::String &filename, Common::Archive &archive) { - openFile(filename, archive); + open(filename, archive); } virtual ~File() {} /** * Opens the given file, throwing an error if it can't be opened */ - void openFile(const Common::String &filename); + virtual bool open(const Common::String &filename); /** * Opens the given file, throwing an error if it can't be opened */ - void openFile(const Common::String &filename, Common::Archive &archive); + virtual bool open(const Common::String &filename, ArchiveType archiveType); + + /** + * Opens the given file, throwing an error if it can't be opened + */ + virtual bool open(const Common::String &filename, Common::Archive &archive); Common::String readString(); }; diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index 6816423a193..c683987c917 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -1069,27 +1069,27 @@ void Map::load(int mapId) { // Read in the object sprites _mobData._objectSprites[i]._sprites.load(filename, - *_vm->_files->_sideArchives[_sideObjects]); + _sideObjects ? ALTSIDE_ARCHIVE : GAME_ARCHIVE); } // Load sprites for the monsters for (uint i = 0; i < _mobData._monsterSprites.size(); ++i) { - CCArchive *archive = _vm->_files->_sideArchives[ + ArchiveType archiveType = _mobData._monsterSprites[i]._spriteId == 91 && _vm->getGameID() == GType_WorldOfXeen ? - 0 : _sideMonsters]; + ALTSIDE_ARCHIVE : GAME_ARCHIVE; filename = Common::String::format("%03d.mon", _mobData._monsterSprites[i]._spriteId); - _mobData._monsterSprites[i]._sprites.load(filename, *archive); + _mobData._monsterSprites[i]._sprites.load(filename, archiveType); filename = Common::String::format("%03d.att", _mobData._monsterSprites[i]._spriteId); - _mobData._monsterSprites[i]._attackSprites.load(filename, *archive); + _mobData._monsterSprites[i]._attackSprites.load(filename, archiveType); } // Load wall picture sprite resources for (uint i = 0; i < _mobData._wallItemSprites.size(); ++i) { filename = Common::String::format("%03d.pic", _mobData._wallItems[i]._spriteId); _mobData._wallItemSprites[i]._sprites.load(filename, - *_vm->_files->_sideArchives[_sidePictures]); + _sidePictures ? ALTSIDE_ARCHIVE : GAME_ARCHIVE); } // Handle loading miscellaneous sprites for the map diff --git a/engines/xeen/music.cpp b/engines/xeen/music.cpp index 5d3cc623a21..19a836b12f9 100644 --- a/engines/xeen/music.cpp +++ b/engines/xeen/music.cpp @@ -34,7 +34,7 @@ namespace Xeen { MusicDriver::MusicDriver() : _musicPlaying(false), _fxPlaying(false), _musCountdownTimer(0), _fxCountdownTimer(0), _musDataPtr(nullptr), _fxDataPtr(nullptr), _fxStartPtr(nullptr), _musStartPtr(nullptr), - _exclude7(false), _frameCtr(0) { + _exclude7(0), _frameCtr(0) { _channels.resize(CHANNEL_COUNT); } @@ -204,7 +204,7 @@ void MusicDriver::playFX(uint effectId, const byte *data) { _fxDataPtr = _fxStartPtr = data; _fxCountdownTimer = 0; _channels[7]._changeFrequency = _channels[8]._changeFrequency = false; - resetFX(); + stopFX(); _fxPlaying = true; } @@ -283,7 +283,7 @@ void AdlibMusicDriver::initialize() { write(0xBD, 0); resetFrequencies(); - AdlibMusicDriver::resetFX(); + AdlibMusicDriver::stopFX(); } void AdlibMusicDriver::playFX(uint effectId, const byte *data) { @@ -387,7 +387,7 @@ void AdlibMusicDriver::pausePostProcess() { } } -void AdlibMusicDriver::resetFX() { +void AdlibMusicDriver::stopFX() { if (!_exclude7) { _channels[7]._frequency = 0; setFrequency(7, 0); @@ -399,6 +399,7 @@ void AdlibMusicDriver::resetFX() { setFrequency(8, 0); _channels[8]._volume = 63; setOutputLevel(8, 63); + _fxPlaying = false; } void AdlibMusicDriver::resetFrequencies() { @@ -625,7 +626,7 @@ bool AdlibMusicDriver::fxPlayInstrument(const byte *&srcP, byte param) { byte instrument = *srcP++; debugC(3, kDebugSound, "fxPlayInstrument %d, %d", param, instrument); - if (!_exclude7 || param != 7) + if (_exclude7 != 2 || param != 7) playInstrument(param, _fxInstrumentPtrs[instrument]); return false; @@ -648,9 +649,9 @@ const uint AdlibMusicDriver::WAVEFORMS[24] = { /*------------------------------------------------------------------------*/ -Music::Music() : _musicDriver(nullptr), _songData(nullptr) { +Music::Music() : _musicDriver(nullptr), _songData(nullptr), + _archiveType(ANY_ARCHIVE), _effectsData(nullptr) { _musicDriver = new AdlibMusicDriver(); - loadEffectsData(); } Music::~Music() { @@ -661,13 +662,17 @@ Music::~Music() { } void Music::loadEffectsData() { - File file("admus"); - Common::String md5str = Common::computeStreamMD5AsString(file, 8192); + // Check whether it's the first load, or switching from intro to game data + if (_effectsData && !(_archiveType == INTRO_ARCHIVE && File::_currentArchive != INTRO_ARCHIVE)) + return; - if (md5str != "be8989a5e868913f0e53963046e3ea13") - error("Unknown music driver encountered"); + // Stop any prior FX + _musicDriver->stopFX(); - // Load in the driver data + + // Load in the entire driver so we have quick access to the effects data + // that's hardcoded within it + File file("promus"); byte *effectsData = new byte[file.size()]; file.seek(0); file.read(effectsData, file.size()); @@ -682,6 +687,9 @@ void Music::loadEffectsData() { } void Music::playFX(uint effectId) { + _musicDriver->stopFX(); + loadEffectsData(); + if (effectId < _effectsOffsets.size()) { const byte *dataP = &_effectsData[_effectsOffsets[effectId]]; _musicDriver->playFX(effectId, dataP); diff --git a/engines/xeen/music.h b/engines/xeen/music.h index 84096945e89..1182be43772 100644 --- a/engines/xeen/music.h +++ b/engines/xeen/music.h @@ -29,6 +29,7 @@ #include "common/mutex.h" #include "common/queue.h" #include "common/stack.h" +#include "xeen/files.h" #define CHANNEL_COUNT 9 @@ -90,7 +91,7 @@ private: bool command(const byte *&srcP); protected: Common::Array _channels; - bool _exclude7; + int _exclude7; bool _musicPlaying; bool _fxPlaying; protected: @@ -135,11 +136,6 @@ protected: * Post-processing done when a pause countdown starts or is in progress */ virtual void pausePostProcess() = 0; - - /** - * Does a reset of any sound effect - */ - virtual void resetFX() = 0; public: /** * Constructor @@ -156,6 +152,11 @@ public: */ virtual void playFX(uint effectId, const byte *data); + /** + * Does a reset of any sound effect + */ + virtual void stopFX() = 0; + /** * Plays a song */ @@ -261,11 +262,6 @@ protected: * Post-processing done when a pause countdown starts or is in progress */ virtual void pausePostProcess(); - - /** - * Does a reset of any sound effect - */ - virtual void resetFX(); public: /** * Constructor @@ -282,6 +278,11 @@ public: */ virtual void playFX(uint effectId, const byte *data); + /** + * Does a reset of any sound effect + */ + virtual void stopFX(); + /** * Plays a song */ @@ -299,6 +300,7 @@ private: const byte *_effectsData; Common::Array _effectsOffsets; const byte *_songData; + ArchiveType _archiveType; private: /** * Loads effects data that was embedded in the music driver diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp index 4804f0aa66e..3758a0f4ad4 100644 --- a/engines/xeen/sprites.cpp +++ b/engines/xeen/sprites.cpp @@ -71,8 +71,8 @@ void SpriteResource::load(const Common::String &filename) { load(f); } -void SpriteResource::load(const Common::String &filename, Common::Archive &archive) { - File f(filename, archive); +void SpriteResource::load(const Common::String &filename, ArchiveType archiveType) { + File f(filename, archiveType); load(f); } diff --git a/engines/xeen/sprites.h b/engines/xeen/sprites.h index 9a241c21000..f660daa0536 100644 --- a/engines/xeen/sprites.h +++ b/engines/xeen/sprites.h @@ -27,6 +27,7 @@ #include "common/array.h" #include "common/file.h" #include "graphics/surface.h" +#include "xeen/files.h" #include "xeen/xsurface.h" namespace Xeen { @@ -88,7 +89,7 @@ public: /** * Load a sprite resource from a given file and archive */ - void load(const Common::String &filename, Common::Archive &archive); + void load(const Common::String &filename, ArchiveType archiveType); /** * Clears the sprite resource diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp index 71fbe8f3285..d9c4fe90d93 100644 --- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp +++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp @@ -32,8 +32,6 @@ bool DarkSideCutscenes::showDarkSideTitle() { Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; - // TODO: Starting method, and sound - //sub_28F40 screen.loadPalette("dark.pal"); SpriteResource nwc[4] = { SpriteResource("nwc1.int"), SpriteResource("nwc2.int"), @@ -55,6 +53,11 @@ bool DarkSideCutscenes::showDarkSideTitle() { screen.draw(); screen.fadeIn(4); + sound.setMusicVolume(0x5f); + sound.playFX(2); + events.wait(1000, true); + int64 v = 0; + // Initial loop for dragon roaring int nwcIndex = 0, nwcFrame = 0; for (int idx = 0; idx < 55 && !_vm->shouldQuit(); ++idx) { @@ -114,12 +117,14 @@ bool DarkSideCutscenes::showDarkSideTitle() { if (events.wait(2, true)) return false; } + if (_vm->shouldQuit()) + return false; // Pause for a bit if (events.wait(10, true)) return false; - sound.songCommand(95); + sound.setMusicVolume(95); screen.loadBackground("jvc.raw"); screen.fadeOut(8); diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp index 2013ae660da..153228cefb1 100644 --- a/engines/xeen/xeen.cpp +++ b/engines/xeen/xeen.cpp @@ -34,6 +34,8 @@ namespace Xeen { +XeenEngine *g_vm = nullptr; + XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Xeen") { // Set up debug channels @@ -61,6 +63,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc) _noDirectionSense = false; _mode = MODE_0; _startupWindowActive = false; + g_vm = this; } XeenEngine::~XeenEngine() { @@ -79,6 +82,7 @@ XeenEngine::~XeenEngine() { delete _eventData; delete _resources; delete _files; + g_vm = nullptr; } void XeenEngine::initialize() { diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h index d0a69394e1c..8f641a83431 100644 --- a/engines/xeen/xeen.h +++ b/engines/xeen/xeen.h @@ -208,6 +208,8 @@ public: static Common::String printK2(uint value); }; +extern XeenEngine *g_vm; + } // End of namespace Xeen #endif /* XEEN_XEEN_H */