diff options
author | Jaromir Wysoglad | 2019-06-19 17:59:36 +0200 |
---|---|---|
committer | Thierry Crozat | 2019-07-28 15:09:14 +0100 |
commit | 5f355734fd8648d03d4e691c7c3bc70cfaeaf0a6 (patch) | |
tree | 71a13f299bd9bacf46d43cdd6e5c8dde6fe64d36 | |
parent | ee5b907f6279d8b28b799922ca11e2bbaaa72c46 (diff) | |
download | scummvm-rg350-5f355734fd8648d03d4e691c7c3bc70cfaeaf0a6.tar.gz scummvm-rg350-5f355734fd8648d03d4e691c7c3bc70cfaeaf0a6.tar.bz2 scummvm-rg350-5f355734fd8648d03d4e691c7c3bc70cfaeaf0a6.zip |
SUPERNOVA: Partial merge of the engine
I am merging the second engine to the first one. Both should be
fully functional as before right now
Current merge file status:
console: should be done
graphics: should be done
detection: 0% merged
imageid: appears to not be used anywhere, so it may be removed
resman: partialy merged
rooms: totaly different, 0% merged
screen: should be done
screenstatic: done
sound: partialy done
state: a lot different, just started to merge
supernova: mostly done
-rw-r--r-- | engines/supernova/graphics.cpp | 91 | ||||
-rw-r--r-- | engines/supernova/graphics.h | 3 | ||||
-rw-r--r-- | engines/supernova/module.mk | 4 | ||||
-rw-r--r-- | engines/supernova/resman.cpp | 86 | ||||
-rw-r--r-- | engines/supernova/resman.h | 17 | ||||
-rw-r--r-- | engines/supernova/screen.cpp | 86 | ||||
-rw-r--r-- | engines/supernova/screen.h | 15 | ||||
-rw-r--r-- | engines/supernova/screenstatic.cpp | 299 | ||||
-rw-r--r-- | engines/supernova/sound.cpp | 16 | ||||
-rw-r--r-- | engines/supernova/sound.h | 6 | ||||
-rw-r--r-- | engines/supernova/state.cpp | 4 | ||||
-rw-r--r-- | engines/supernova/state.h | 1 | ||||
-rw-r--r-- | engines/supernova/supernova.cpp | 99 | ||||
-rw-r--r-- | engines/supernova/supernova.h | 9 | ||||
-rw-r--r-- | engines/supernova2/state.cpp | 1 | ||||
-rw-r--r-- | engines/supernova2/state.h | 4 | ||||
-rw-r--r-- | engines/supernova2/supernova2.cpp | 13 |
17 files changed, 616 insertions, 138 deletions
diff --git a/engines/supernova/graphics.cpp b/engines/supernova/graphics.cpp index ff385f947f..a317672183 100644 --- a/engines/supernova/graphics.cpp +++ b/engines/supernova/graphics.cpp @@ -35,7 +35,8 @@ namespace Supernova { -MSNImage::MSNImage() { +MSNImage::MSNImage(int MSPart) + : _MSPart(MSPart) { _palette = nullptr; _encodedImage = nullptr; _filenumber = -1; @@ -68,9 +69,17 @@ MSNImage::~MSNImage() { bool MSNImage::init(int filenumber) { Common::File file; - if (!file.open(Common::String::format("msn_data.%03d", filenumber))) { - warning("Image data file msn_data.%03d could not be read!", filenumber); - return false; + if (_MSPart == 1) { + if (!file.open(Common::String::format("msn_data.%03d", filenumber))) { + warning("Image data file msn_data.%03d could not be read!", filenumber); + return false; + } + } + else if (_MSPart == 2) { + if (!file.open(Common::String::format("ms2_data.%03d", filenumber))) { + warning("Image data file ms2_data.%03d could not be read!", filenumber); + return false; + } } _filenumber = filenumber; @@ -81,30 +90,49 @@ bool MSNImage::init(int filenumber) { bool MSNImage::loadFromEngineDataFile() { Common::String name; - if (_filenumber == 1) - name = "IMG1"; - else if (_filenumber == 2) - name = "IMG2"; - else - return false; + Common::File f; + char id[5], lang[5]; + id[4] = lang[4] = '\0'; + if (_MSPart == 1) { + if (_filenumber == 1) + name = "IMG1"; + else if (_filenumber == 2) + name = "IMG2"; + else + + return false; + if (!f.open(SUPERNOVA_DAT)) + return false; + + f.read(id, 3); + if (strncmp(id, "MSN", 3) != 0) + return false; + int version = f.readByte(); + if (version != SUPERNOVA_DAT_VERSION) + return false; + } else if (_MSPart == 2) { + if (_filenumber == 28) + name = "IMG1"; + else + return false; + + if (!f.open(SUPERNOVA2_DAT)) + return false; + + f.read(id, 3); + if (strncmp(id, "MS2", 3) != 0) + return false; + int version = f.readByte(); + if (version != SUPERNOVA2_DAT_VERSION) + return false; + } Common::String cur_lang = ConfMan.get("language"); // Note: we don't print any warning or errors here if we cannot find the file // or the format is not as expected. We will get those warning when reading the // strings anyway (actually the engine will even refuse to start). - Common::File f; - if (!f.open(SUPERNOVA_DAT)) - return false; - char id[5], lang[5]; - id[4] = lang[4] = '\0'; - f.read(id, 3); - if (strncmp(id, "MSN", 3) != 0) - return false; - int version = f.readByte(); - if (version != SUPERNOVA_DAT_VERSION) - return false; while (!f.eos()) { f.read(id, 4); @@ -219,9 +247,11 @@ bool MSNImage::loadStream(Common::SeekableReadStream &stream) { } bool MSNImage::loadSections() { - bool isNewspaper = _filenumber == 1 || _filenumber == 2; - int imageWidth = isNewspaper ? 640 : 320; - int imageHeight = isNewspaper ? 480 : 200; + bool isNewspaper = (_MSPart == 1 && (_filenumber == 1 || _filenumber == 2)) || + (_MSPart == 2 && _filenumber == 38); + bool isCypheredText = _MSPart == 2 && _filenumber == 28 && ConfMan.get("language") == "en"; + int imageWidth = isNewspaper || isCypheredText ? 640 : 320; + int imageHeight = isNewspaper || isCypheredText ? 480 : 200; _pitch = imageWidth; for (int section = 0; section < _numSections; ++section) { @@ -241,6 +271,19 @@ bool MSNImage::loadSections() { *surfacePixels++ = (_encodedImage[i] & 0x02) ? kColorWhite63 : kColorBlack; *surfacePixels++ = (_encodedImage[i] & 0x01) ? kColorWhite63 : kColorBlack; } + } else if (isCypheredText) { + surface->create(imageWidth, imageHeight, g_system->getScreenFormat()); + byte *surfacePixels = static_cast<byte *>(surface->getPixels()); + for (int i = 0; i < imageWidth * imageHeight / 8; ++i) { + *surfacePixels++ = (_encodedImage[i] & 0x80) ? kColorWhite44 : kColorBlack; + *surfacePixels++ = (_encodedImage[i] & 0x40) ? kColorWhite44 : kColorBlack; + *surfacePixels++ = (_encodedImage[i] & 0x20) ? kColorWhite44 : kColorBlack; + *surfacePixels++ = (_encodedImage[i] & 0x10) ? kColorWhite44 : kColorBlack; + *surfacePixels++ = (_encodedImage[i] & 0x08) ? kColorWhite44 : kColorBlack; + *surfacePixels++ = (_encodedImage[i] & 0x04) ? kColorWhite44 : kColorBlack; + *surfacePixels++ = (_encodedImage[i] & 0x02) ? kColorWhite44 : kColorBlack; + *surfacePixels++ = (_encodedImage[i] & 0x01) ? kColorWhite44 : kColorBlack; + } } else { uint32 offset = (_section[section].addressHigh << 16) + _section[section].addressLow; if (offset == kInvalidAddress || _section[section].x2 == 0) { diff --git a/engines/supernova/graphics.h b/engines/supernova/graphics.h index 058da45ba8..5a790ec249 100644 --- a/engines/supernova/graphics.h +++ b/engines/supernova/graphics.h @@ -38,7 +38,7 @@ namespace Supernova { class MSNImage : public Image::ImageDecoder { public: - MSNImage(); + MSNImage(int MSPart); virtual ~MSNImage(); virtual void destroy(); @@ -79,6 +79,7 @@ public: } _clickField[kMaxClickFields]; private: + int _MSPart; bool loadFromEngineDataFile(); bool loadSections(); }; diff --git a/engines/supernova/module.mk b/engines/supernova/module.mk index 722a230cde..c9bc1ca0b7 100644 --- a/engines/supernova/module.mk +++ b/engines/supernova/module.mk @@ -1,14 +1,14 @@ MODULE := engines/supernova MODULE_OBJS := \ - console.o \ detection.o \ + state.o \ graphics.o \ resman.o \ rooms.o \ screen.o \ + console.o \ sound.o \ - state.o \ supernova.o MODULE_DIRS += \ diff --git a/engines/supernova/resman.cpp b/engines/supernova/resman.cpp index d7ea0b3a71..f2b9f312c9 100644 --- a/engines/supernova/resman.cpp +++ b/engines/supernova/resman.cpp @@ -92,12 +92,18 @@ static const byte mouseWait[64] = { }; -ResourceManager::ResourceManager() - : _audioRate(11931) { +ResourceManager::ResourceManager(int MSPart) + : _audioRate(11931) + , _MSPart(MSPart) { initSoundFiles(); initGraphics(); } +ResourceManager::~ResourceManager() { + for (int i = 0; i < kNumImageFiles; i++) + delete _images[i]; +} + void ResourceManager::initSoundFiles() { // Sound // Note: @@ -164,10 +170,12 @@ void ResourceManager::initCursorGraphics() { void ResourceManager::initImages() { for (int i = 0; i < 44; ++i) { - if (!_images[i].init(i)) + _images[i] = new MSNImage(_MSPart); + if (!_images[i]->init(i)) error("Failed reading image file msn_data.%03d", i); } - if (!_images[44].init(55)) + _images[44] = new MSNImage(_MSPart); + if (!_images[44]->init(55)) error("Failed reading image file msn_data.055"); } @@ -183,6 +191,9 @@ Audio::AudioStream *ResourceManager::getSoundStream(MusicId index) { case kMusicIntro: _musicIntro.reset(Audio::makeProtrackerStream(_musicIntroBuffer.get())); return _musicIntro.get(); + case kMusicMadMonkeys: + _musicMadMonkeys.reset(Audio::makeProtrackerStream(_musicMadMonkeysBuffer.get())); + return _musicMadMonkeys.get(); case kMusicOutro: _musicOutro.reset(Audio::makeProtrackerStream(_musicOutroBuffer.get())); return _musicOutro.get(); @@ -191,11 +202,15 @@ Audio::AudioStream *ResourceManager::getSoundStream(MusicId index) { } } -const MSNImage *ResourceManager::getImage(int filenumber) const { +Audio::AudioStream *ResourceManager::getSirenStream() { + return _sirenStream.get(); +} + +MSNImage *ResourceManager::getImage(int filenumber) { if (filenumber < 44) - return &_images[filenumber]; + return _images[filenumber]; else if (filenumber == 55) - return &_images[44]; + return _images[44]; else return nullptr; } @@ -211,6 +226,47 @@ const byte *ResourceManager::getImage(CursorId id) const { } } +// Generate a tone which minimal length is the length and ends at the end +// of sine period +// NOTE: Size of the SineTable has to be the same as audioRate and a multiple of 4 +byte *ResourceManager::generateTone(byte *buffer, int frequency, int length, int audioRate, Common::SineTable &table) { + int i = 0; + + // Make sure length is a multiple of audioRate / frequency to end on a full sine wave and not in the middle. + // Also the length we have is a minimum length, so only increase it. + int r = 1 + (length - 1) * frequency / audioRate; + length = (1 + 2 * r * audioRate / frequency) / 2; + for(; i < length; i++) { + buffer[i] = (byte) + ((table.at((i * frequency) % audioRate) * 127) + 127); + } + return buffer + length; +} + +// Tones with frequencies between 1500 Hz and 1800 Hz, frequencies go up and down +// with a step of 10 Hz. +void ResourceManager::initSiren() { + int audioRate = 44000; + int length = audioRate / 90; // minimal length of each tone + + // * 60 for the minimal length, another 20 * length as a spare, for longer tones + byte *buffer = new byte[length * 80]; + byte *pBuffer = buffer; + Common::SineTable table(audioRate); + + for (int i = 0; i < 30; i++) + pBuffer = generateTone(pBuffer, 1800 - i * 10, length, audioRate, table); + + for (int i = 0; i < 30; i++) + pBuffer = generateTone(pBuffer, 1500 + i * 10, length, audioRate, table); + + byte streamFlag = Audio::FLAG_UNSIGNED; + + _sirenStream.reset(Audio::makeLoopingAudioStream( + Audio::makeRawStream(buffer, pBuffer - buffer, audioRate, + streamFlag, DisposeAfterUse::YES), 0)); +} + static Common::MemoryReadStream *convertToMod(const char *filename, int version) { // MSN format struct { @@ -397,4 +453,20 @@ static Common::MemoryReadStream *convertToMod(const char *filename, int version) return new Common::MemoryReadStream(buffer.getData(), buffer.size(), DisposeAfterUse::YES); } +int ResourceManager::getAudioRate() { + return _audioRate; +} + +//TODO: leave only one function for getting Cursor image +const byte *ResourceManager::getCursor(CursorId id) const { + switch (id) { + case kCursorNormal: + return _cursorNormal; + case kCursorWait: + return _cursorWait; + default: + return nullptr; + } +} + } diff --git a/engines/supernova/resman.h b/engines/supernova/resman.h index 080497e904..194b79875b 100644 --- a/engines/supernova/resman.h +++ b/engines/supernova/resman.h @@ -25,6 +25,7 @@ #include "audio/audiostream.h" #include "common/ptr.h" +#include "common/sinetables.h" #include "supernova/graphics.h" #include "supernova/sound.h" @@ -47,27 +48,37 @@ public: static const int kNumImageFiles = 45; public: - ResourceManager(); + ResourceManager(int MSPart); + ~ResourceManager(); Audio::SeekableAudioStream *getSoundStream(AudioId index); Audio::AudioStream *getSoundStream(MusicId index); - const MSNImage *getImage(int filenumber) const; + Audio::AudioStream *getSirenStream(); + MSNImage *getImage(int filenumber); const byte *getImage(CursorId id) const; + const byte *getCursor(CursorId id) const; + int getAudioRate(); private: void initSoundFiles(); void initGraphics(); void initCursorGraphics(); void initImages(); + void initSiren(); + byte *generateTone(byte *buffer, int frequency, int length, int audioRate, Common::SineTable &table); private: Common::ScopedPtr<Audio::SeekableAudioStream> _soundSamples[kAudioNumSamples]; Common::ScopedPtr<Common::MemoryReadStream> _musicIntroBuffer; Common::ScopedPtr<Common::MemoryReadStream> _musicOutroBuffer; + Common::ScopedPtr<Common::MemoryReadStream> _musicMadMonkeysBuffer; Common::ScopedPtr<Audio::AudioStream> _musicIntro; Common::ScopedPtr<Audio::AudioStream> _musicOutro; + Common::ScopedPtr<Audio::AudioStream> _sirenStream; + Common::ScopedPtr<Audio::AudioStream> _musicMadMonkeys; + int _MSPart; int _audioRate; - MSNImage _images[kNumImageFiles]; + MSNImage *_images[kNumImageFiles]; byte _cursorNormal[256]; byte _cursorWait[256]; }; diff --git a/engines/supernova/screen.cpp b/engines/supernova/screen.cpp index f28af28134..0240a7619e 100644 --- a/engines/supernova/screen.cpp +++ b/engines/supernova/screen.cpp @@ -26,6 +26,7 @@ #include "graphics/cursorman.h" #include "graphics/palette.h" #include "graphics/surface.h" +#include "common/config-manager.h" #include "supernova/imageid.h" #include "supernova/resman.h" @@ -105,14 +106,24 @@ Marquee::Marquee(Screen *screen, MarqueeId id, const char *text) : _text(text) , _textBegin(text) , _delay(0) - , _color(kColorLightBlue) , _loop(false) , _screen(screen) { - if (id == kMarqueeIntro) { - _y = 191; - _loop = true; - } else if (id == kMarqueeOutro) { - _y = 1; + if (_screen->_vm->_MSPart == 1) { + _color = kColorLightBlue; + if (id == kMarqueeIntro) { + _y = 191; + _loop = true; + } else if (id == kMarqueeOutro) { + _y = 1; + } + } else if (_screen->_vm->_MSPart == 2) { + _color = kColorPurple; + if (id == kMarqueeIntro) { + _y = 191; + _loop = true; + } else if (id == kMarqueeOutro) { + _y = 191; + } } _textWidth = Screen::textWidth(_text); @@ -126,10 +137,18 @@ void Marquee::clearText() { _screen->renderBox(_x, _y - 1, _textWidth + 1, 9, kColorBlack); } -void Marquee::renderCharacter() { +void Marquee::reset() { + _text = _textBegin; + clearText(); + _textWidth = Screen::textWidth(_text); + _x = kScreenWidth / 2 - _textWidth / 2; + _screen->_textCursorX = _x; +} + +bool Marquee::renderCharacter() { if (_delay != 0) { _delay--; - return; + return true; } switch (*_text) { @@ -141,7 +160,8 @@ void Marquee::renderCharacter() { _textWidth = Screen::textWidth(_text); _x = kScreenWidth / 2 - _textWidth / 2; _screen->_textCursorX = _x; - } + } else + return false; break; case '\0': clearText(); @@ -149,8 +169,13 @@ void Marquee::renderCharacter() { _textWidth = Screen::textWidth(_text); _x = kScreenWidth / 2 - _textWidth / 2; _screen->_textCursorX = _x; - _color = kColorLightBlue; - _screen->_textColor = _color; + if (_screen->_vm->_MSPart == 1) { + _color = kColorLightBlue; + _screen->_textColor = _color; + } else if (_screen->_vm->_MSPart == 2) { + _color = kColorPurple; + _screen->_textColor = _color; + } break; case '^': _color = kColorLightYellow; @@ -166,6 +191,7 @@ void Marquee::renderCharacter() { _delay = 1; break; } + return true; } Screen::Screen(SupernovaEngine *vm, ResourceManager *resMan) @@ -181,10 +207,7 @@ Screen::Screen(SupernovaEngine *vm, ResourceManager *resMan) , _textCursorY(0) , _messageShown(false) { - CursorMan.replaceCursor(_resMan->getImage(ResourceManager::kCursorNormal), - 16, 16, 0, 0, kColorCursorTransparent); - CursorMan.replaceCursorPalette(initVGAPalette, 0, 16); - CursorMan.showMouse(true); + changeCursor(ResourceManager::kCursorNormal); } int Screen::getScreenWidth() const { @@ -211,7 +234,7 @@ void Screen::setGuiBrightness(int brightness) { _guiBrightness = brightness; } -const MSNImage *Screen::getCurrentImage() const { +MSNImage *Screen::getCurrentImage() { return _currentImage; } @@ -348,7 +371,13 @@ void Screen::renderImageSection(const MSNImage *image, int section, bool invert) image->_section[section].y1, image->_section[section].x2 + 1, image->_section[section].y2 + 1); - if (image->_filenumber == 1 || image->_filenumber == 2) { + bool bigImage = false; + if (_vm->_MSPart == 1) + bigImage = image->_filenumber == 1 || image->_filenumber == 2; + else if (_vm->_MSPart == 2) + bigImage = image->_filenumber == 38 || + (image->_filenumber == 28 && ConfMan.get("language") == "en"); + if (bigImage) { sectionRect.setWidth(640); sectionRect.setHeight(480); if (_screenWidth != 640) { @@ -478,7 +507,7 @@ int Screen::textWidth(const Common::String &text) { return Screen::textWidth(text.c_str()); } -void Screen::renderMessage(const char *text, MessagePosition position) { +void Screen::renderMessage(const char *text, MessagePosition position, int positionX, int positionY) { Common::String t(text); char *row[20]; Common::String::iterator p = t.begin(); @@ -536,6 +565,11 @@ void Screen::renderMessage(const char *text, MessagePosition position) { y = 142; } + if (positionX != -1 && positionY != -1) { + x = positionX; + y = positionY; + } + int message_columns = x - 3; int message_rows = y - 3; int message_width = rowWidthMax + 6; @@ -591,8 +625,8 @@ void Screen::paletteBrightness() { _vm->_system->getPaletteManager()->setPalette(palette, 0, 255); } -void Screen::paletteFadeOut() { - while (_guiBrightness > 10) { +void Screen::paletteFadeOut(int minBrightness) { + while (_guiBrightness > minBrightness + 10) { _guiBrightness -= 10; if (_viewportBrightness > _guiBrightness) _viewportBrightness = _guiBrightness; @@ -600,8 +634,8 @@ void Screen::paletteFadeOut() { _vm->_system->updateScreen(); _vm->_system->delayMillis(_vm->_delay); } - _guiBrightness = 0; - _viewportBrightness = 0; + _guiBrightness = minBrightness; + _viewportBrightness = minBrightness; paletteBrightness(); _vm->_system->updateScreen(); } @@ -626,4 +660,12 @@ void Screen::setColor63(byte value) { _vm->_system->getPaletteManager()->setPalette(color, 63, 1); } +void Screen::changeCursor(ResourceManager::CursorId id) { + CursorMan.replaceCursor(_resMan->getCursor(id), + 16, 16, 0, 0, kColorCursorTransparent); + CursorMan.replaceCursorPalette(initVGAPalette, 0, 16); + CursorMan.showMouse(true); +} + + } diff --git a/engines/supernova/screen.h b/engines/supernova/screen.h index 3e90e21b1a..dc5aa4dc2f 100644 --- a/engines/supernova/screen.h +++ b/engines/supernova/screen.h @@ -29,7 +29,7 @@ #include "supernova/imageid.h" #include "supernova/msn_def.h" -#include "supernova2/resman.h" +#include "supernova/resman.h" namespace Supernova { @@ -63,6 +63,7 @@ enum Color { kColorLightGreen = 13, kColorLightYellow = 14, kColorLightRed = 15, + kColorPurple = 35, kColorCursorTransparent = kColorWhite25 }; @@ -101,7 +102,8 @@ public: Marquee(Screen *screen, MarqueeId id, const char *text); - void renderCharacter(); + bool renderCharacter(); + void reset(); private: void clearText(); @@ -141,11 +143,11 @@ public: void setViewportBrightness(int brightness); int getGuiBrightness() const; void setGuiBrightness(int brightness); - const MSNImage *getCurrentImage() const; + MSNImage *getCurrentImage(); const ImageInfo *getImageInfo(ImageId id) const; bool isMessageShown() const; void paletteFadeIn(int maxViewportBrightness); - void paletteFadeOut(); + void paletteFadeOut(int minBrightness); void paletteBrightness(); void renderImage(ImageId id, bool removeImage = false); void renderImage(int section); @@ -154,7 +156,7 @@ public: void saveScreen(const GuiElement &guiElement); void restoreScreen(); void renderRoom(Room &room); - void renderMessage(const char *text, MessagePosition position = kMessageNormal); + void renderMessage(const char *text, MessagePosition position = kMessageNormal, int positionX = -1, int positionY = -1); void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal); void renderMessage(StringId stringId, MessagePosition position = kMessageNormal, Common::String var1 = "", Common::String var2 = ""); @@ -176,6 +178,7 @@ public: byte getTextCursorColor(); void setTextCursorColor(byte color); void update(); + void changeCursor(ResourceManager::CursorId); private: void renderImageSection(const MSNImage *image, int section, bool invert); @@ -183,7 +186,7 @@ private: private: SupernovaEngine *_vm; ResourceManager *_resMan; - const MSNImage *_currentImage; + MSNImage *_currentImage; ScreenBufferStack _screenBuffer; int _screenWidth; int _screenHeight; diff --git a/engines/supernova/screenstatic.cpp b/engines/supernova/screenstatic.cpp index 796c1483e1..20c7262309 100644 --- a/engines/supernova/screenstatic.cpp +++ b/engines/supernova/screenstatic.cpp @@ -145,49 +145,262 @@ static const Screen::ImageInfo imageInfo[] = { // Default palette static const byte initVGAPalette[768] = { - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x58, 0x58, 0x70, 0x70, 0x70, 0xfc, 0xfc, 0xfc, 0x00, 0xd0, 0x00, - 0x00, 0xfc, 0x00, 0xd8, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xb0, 0xa0, 0xa0, 0xa0, - 0x50, 0xc8, 0xfc, 0x28, 0xfc, 0x28, 0xf0, 0xf0, 0x00, 0xfc, 0x28, 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, - 0x20, 0x20, 0x20, 0x2c, 0x2c, 0x2c, 0x38, 0x38, 0x38, 0x44, 0x44, 0x44, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60, - 0x70, 0x70, 0x70, 0x80, 0x80, 0x80, 0x90, 0x90, 0x90, 0xa0, 0xa0, 0xa0, 0xb4, 0xb4, 0xb4, 0xc8, 0xc8, 0xc8, - 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, - 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, - 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00, - 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, - 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, - 0xfc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, - 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c, - 0x7c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, - 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, - 0xfc, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, - 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4, - 0xb4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, - 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, - 0x70, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00, - 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, - 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, - 0x70, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, - 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38, - 0x38, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, - 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, - 0x70, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, - 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50, - 0x50, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, - 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, - 0x40, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00, - 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, - 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, - 0x40, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, - 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20, - 0x20, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, - 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, - 0x40, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, - 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c, - 0x2c, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, - 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, + 0x40, 0x40, 0x40, + 0x58, 0x58, 0x58, + 0x70, 0x70, 0x70, + 0xfc, 0xfc, 0xfc, + 0x00, 0xd0, 0x00, + 0x00, 0xfc, 0x00, + 0xd8, 0x00, 0x00, + 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x78, + 0x00, 0x00, 0xb0, + 0xa0, 0xa0, 0xa0, + 0x50, 0xc8, 0xfc, + 0x28, 0xfc, 0x28, + 0xf0, 0xf0, 0x00, + 0xfc, 0x28, 0x28, + 0x00, 0x00, 0x00, + 0x14, 0x14, 0x14, + 0x20, 0x20, 0x20, + 0x2c, 0x2c, 0x2c, + 0x38, 0x38, 0x38, + 0x44, 0x44, 0x44, + 0x50, 0x50, 0x50, + 0x60, 0x60, 0x60, + 0x70, 0x70, 0x70, + 0x80, 0x80, 0x80, + 0x90, 0x90, 0x90, + 0xa0, 0xa0, 0xa0, + 0xb4, 0xb4, 0xb4, + 0xc8, 0xc8, 0xc8, + 0xe0, 0xe0, 0xe0, + 0xfc, 0xfc, 0xfc, + 0x00, 0x00, 0xfc, + 0x40, 0x00, 0xfc, + 0x7c, 0x00, 0xfc, + 0xbc, 0x00, 0xfc, + 0xfc, 0x00, 0xfc, + 0xfc, 0x00, 0xbc, + 0xfc, 0x00, 0x7c, + 0xfc, 0x00, 0x40, + 0xfc, 0x00, 0x00, + 0xfc, 0x40, 0x00, + 0xfc, 0x7c, 0x00, + 0xfc, 0xbc, 0x00, + 0xfc, 0xfc, 0x00, + 0xbc, 0xfc, 0x00, + 0x7c, 0xfc, 0x00, + 0x40, 0xfc, 0x00, + 0x00, 0xfc, 0x00, + 0x00, 0xfc, 0x40, + 0x00, 0xfc, 0x7c, + 0x00, 0xfc, 0xbc, + 0x00, 0xfc, 0xfc, + 0x00, 0xbc, 0xfc, + 0x00, 0x7c, 0xfc, + 0x00, 0x40, 0xfc, + 0x7c, 0x7c, 0xfc, + 0x9c, 0x7c, 0xfc, + 0xbc, 0x7c, 0xfc, + 0xdc, 0x7c, 0xfc, + 0xfc, 0x7c, 0xfc, + 0xfc, 0x7c, 0xdc, + 0xfc, 0x7c, 0xbc, + 0xfc, 0x7c, 0x9c, + 0xfc, 0x7c, 0x7c, + 0xfc, 0x9c, 0x7c, + 0xfc, 0xbc, 0x7c, + 0xfc, 0xdc, 0x7c, + 0xfc, 0xfc, 0x7c, + 0xdc, 0xfc, 0x7c, + 0xbc, 0xfc, 0x7c, + 0x9c, 0xfc, 0x7c, + 0x7c, 0xfc, 0x7c, + 0x7c, 0xfc, 0x9c, + 0x7c, 0xfc, 0xbc, + 0x7c, 0xfc, 0xdc, + 0x7c, 0xfc, 0xfc, + 0x7c, 0xdc, 0xfc, + 0x7c, 0xbc, 0xfc, + 0x7c, 0x9c, 0xfc, + 0xb4, 0xb4, 0xfc, + 0xc4, 0xb4, 0xfc, + 0xd8, 0xb4, 0xfc, + 0xe8, 0xb4, 0xfc, + 0xfc, 0xb4, 0xfc, + 0xfc, 0xb4, 0xe8, + 0xfc, 0xb4, 0xd8, + 0xfc, 0xb4, 0xc4, + 0xfc, 0xb4, 0xb4, + 0xfc, 0xc4, 0xb4, + 0xfc, 0xd8, 0xb4, + 0xfc, 0xe8, 0xb4, + 0xfc, 0xfc, 0xb4, + 0xe8, 0xfc, 0xb4, + 0xd8, 0xfc, 0xb4, + 0xc4, 0xfc, 0xb4, + 0xb4, 0xfc, 0xb4, + 0xb4, 0xfc, 0xc4, + 0xb4, 0xfc, 0xd8, + 0xb4, 0xfc, 0xe8, + 0xb4, 0xfc, 0xfc, + 0xb4, 0xe8, 0xfc, + 0xb4, 0xd8, 0xfc, + 0xb4, 0xc4, 0xfc, + 0x00, 0x00, 0x70, + 0x1c, 0x00, 0x70, + 0x38, 0x00, 0x70, + 0x54, 0x00, 0x70, + 0x70, 0x00, 0x70, + 0x70, 0x00, 0x54, + 0x70, 0x00, 0x38, + 0x70, 0x00, 0x1c, + 0x70, 0x00, 0x00, + 0x70, 0x1c, 0x00, + 0x70, 0x38, 0x00, + 0x70, 0x54, 0x00, + 0x70, 0x70, 0x00, + 0x54, 0x70, 0x00, + 0x38, 0x70, 0x00, + 0x1c, 0x70, 0x00, + 0x00, 0x70, 0x00, + 0x00, 0x70, 0x1c, + 0x00, 0x70, 0x38, + 0x00, 0x70, 0x54, + 0x00, 0x70, 0x70, + 0x00, 0x54, 0x70, + 0x00, 0x38, 0x70, + 0x00, 0x1c, 0x70, + 0x38, 0x38, 0x70, + 0x44, 0x38, 0x70, + 0x54, 0x38, 0x70, + 0x60, 0x38, 0x70, + 0x70, 0x38, 0x70, + 0x70, 0x38, 0x60, + 0x70, 0x38, 0x54, + 0x70, 0x38, 0x44, + 0x70, 0x38, 0x38, + 0x70, 0x44, 0x38, + 0x70, 0x54, 0x38, + 0x70, 0x60, 0x38, + 0x70, 0x70, 0x38, + 0x60, 0x70, 0x38, + 0x54, 0x70, 0x38, + 0x44, 0x70, 0x38, + 0x38, 0x70, 0x38, + 0x38, 0x70, 0x44, + 0x38, 0x70, 0x54, + 0x38, 0x70, 0x60, + 0x38, 0x70, 0x70, + 0x38, 0x60, 0x70, + 0x38, 0x54, 0x70, + 0x38, 0x44, 0x70, + 0x50, 0x50, 0x70, + 0x58, 0x50, 0x70, + 0x60, 0x50, 0x70, + 0x68, 0x50, 0x70, + 0x70, 0x50, 0x70, + 0x70, 0x50, 0x68, + 0x70, 0x50, 0x60, + 0x70, 0x50, 0x58, + 0x70, 0x50, 0x50, + 0x70, 0x58, 0x50, + 0x70, 0x60, 0x50, + 0x70, 0x68, 0x50, + 0x70, 0x70, 0x50, + 0x68, 0x70, 0x50, + 0x60, 0x70, 0x50, + 0x58, 0x70, 0x50, + 0x50, 0x70, 0x50, + 0x50, 0x70, 0x58, + 0x50, 0x70, 0x60, + 0x50, 0x70, 0x68, + 0x50, 0x70, 0x70, + 0x50, 0x68, 0x70, + 0x50, 0x60, 0x70, + 0x50, 0x58, 0x70, + 0x00, 0x00, 0x40, + 0x10, 0x00, 0x40, + 0x20, 0x00, 0x40, + 0x30, 0x00, 0x40, + 0x40, 0x00, 0x40, + 0x40, 0x00, 0x30, + 0x40, 0x00, 0x20, + 0x40, 0x00, 0x10, + 0x40, 0x00, 0x00, + 0x40, 0x10, 0x00, + 0x40, 0x20, 0x00, + 0x40, 0x30, 0x00, + 0x40, 0x40, 0x00, + 0x30, 0x40, 0x00, + 0x20, 0x40, 0x00, + 0x10, 0x40, 0x00, + 0x00, 0x40, 0x00, + 0x00, 0x40, 0x10, + 0x00, 0x40, 0x20, + 0x00, 0x40, 0x30, + 0x00, 0x40, 0x40, + 0x00, 0x30, 0x40, + 0x00, 0x20, 0x40, + 0x00, 0x10, 0x40, + 0x20, 0x20, 0x40, + 0x28, 0x20, 0x40, + 0x30, 0x20, 0x40, + 0x38, 0x20, 0x40, + 0x40, 0x20, 0x40, + 0x40, 0x20, 0x38, + 0x40, 0x20, 0x30, + 0x40, 0x20, 0x28, + 0x40, 0x20, 0x20, + 0x40, 0x28, 0x20, + 0x40, 0x30, 0x20, + 0x40, 0x38, 0x20, + 0x40, 0x40, 0x20, + 0x38, 0x40, 0x20, + 0x30, 0x40, 0x20, + 0x28, 0x40, 0x20, + 0x20, 0x40, 0x20, + 0x20, 0x40, 0x28, + 0x20, 0x40, 0x30, + 0x20, 0x40, 0x38, + 0x20, 0x40, 0x40, + 0x20, 0x38, 0x40, + 0x20, 0x30, 0x40, + 0x20, 0x28, 0x40, + 0x2c, 0x2c, 0x40, + 0x30, 0x2c, 0x40, + 0x34, 0x2c, 0x40, + 0x3c, 0x2c, 0x40, + 0x40, 0x2c, 0x40, + 0x40, 0x2c, 0x3c, + 0x40, 0x2c, 0x34, + 0x40, 0x2c, 0x30, + 0x40, 0x2c, 0x2c, + 0x40, 0x30, 0x2c, + 0x40, 0x34, 0x2c, + 0x40, 0x3c, 0x2c, + 0x40, 0x40, 0x2c, + 0x3c, 0x40, 0x2c, + 0x34, 0x40, 0x2c, + 0x30, 0x40, 0x2c, + 0x2c, 0x40, 0x2c, + 0x2c, 0x40, 0x30, + 0x2c, 0x40, 0x34, + 0x2c, 0x40, 0x3c, + 0x2c, 0x40, 0x40, + 0x2c, 0x3c, 0x40, + 0x2c, 0x34, 0x40, + 0x2c, 0x30, 0x40, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; static const byte font[][5] = { diff --git a/engines/supernova/sound.cpp b/engines/supernova/sound.cpp index e7f3ce83bd..dc1c7c3630 100644 --- a/engines/supernova/sound.cpp +++ b/engines/supernova/sound.cpp @@ -53,6 +53,14 @@ void Sound::play(MusicId index) { -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); } +void Sound::playSiren() { + Audio::AudioStream *stream = _resMan->getSirenStream(); + + stop(); + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, stream, + -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); +} + bool Sound::isPlaying() { return _mixer->isSoundHandleActive(_soundHandle); } @@ -62,4 +70,12 @@ void Sound::stop() { _mixer->stopHandle(_soundHandle); } +int Sound::getVolume() { + return _mixer->getChannelVolume(_soundHandle); +} + +void Sound::setVolume(int volume) { + _mixer->setChannelVolume(_soundHandle, volume); +} + } diff --git a/engines/supernova/sound.h b/engines/supernova/sound.h index 100c9a372b..bfea0194ac 100644 --- a/engines/supernova/sound.h +++ b/engines/supernova/sound.h @@ -56,7 +56,8 @@ enum AudioId { enum MusicId { kMusicIntro = 49, - kMusicOutro = 52 + kMusicOutro = 52, + kMusicMadMonkeys = 51 }; class Sound { @@ -67,6 +68,9 @@ public: void play(AudioId index); void play(MusicId index); + void playSiren(); + void setVolume(int volume); + int getVolume(); void stop(); bool isPlaying(); private: diff --git a/engines/supernova/state.cpp b/engines/supernova/state.cpp index 2a1c9fbbaf..a0c06a93de 100644 --- a/engines/supernova/state.cpp +++ b/engines/supernova/state.cpp @@ -506,6 +506,10 @@ void GameManager::initGui() { _guiInventoryArrow[1].setTextPosition(273, 186); } +bool GameManager::canSaveGameStateCurrently() { + return _animationEnabled && _guiEnabled; +} + void GameManager::updateEvents() { handleTime(); if (_animationEnabled && !_vm->_screen->isMessageShown() && _animationTimer == 0) diff --git a/engines/supernova/state.h b/engines/supernova/state.h index 6b9d463dd5..f78f2191f5 100644 --- a/engines/supernova/state.h +++ b/engines/supernova/state.h @@ -187,6 +187,7 @@ public: void initRooms(); void destroyRooms(); void initGui(); + bool canSaveGameStateCurrently(); bool genericInteract(Action verb, Object &obj1, Object &obj2); bool isHelmetOff(); void great(uint number); diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp index ba309e8b49..c07edfadba 100644 --- a/engines/supernova/supernova.cpp +++ b/engines/supernova/supernova.cpp @@ -89,6 +89,12 @@ SupernovaEngine::SupernovaEngine(OSystem *syst) if (ConfMan.hasKey("textspeed")) _textSpeed = ConfMan.getInt("textspeed"); + if (ConfMan.get("gameid") == "msn1") + _MSPart = 1; + else if (ConfMan.get("gameid") == "msn2") + _MSPart = 2; + else + _MSPart = 0; DebugMan.addDebugChannel(kDebugGeneral, "general", "Supernova general debug channel"); } @@ -133,7 +139,7 @@ void SupernovaEngine::init() { if (status.getCode() != Common::kNoError) error("Failed reading game strings"); - _resMan = new ResourceManager(); + _resMan = new ResourceManager(_MSPart); _sound = new Sound(_mixer, _resMan); _gm = new GameManager(this, _sound); _screen = new Screen(this, _resMan); @@ -173,29 +179,52 @@ Common::Error SupernovaEngine::loadGameStrings() { // Note: we don't print any warning or errors here if we cannot find the file // or the format is not as expected. We will get those warning when reading the // strings anyway (actually the engine will even refuse to start). - Common::File f; - if (!f.open(SUPERNOVA_DAT)) { - GUIErrorMessageFormat(_("Unable to locate the '%s' engine data file."), SUPERNOVA_DAT); - return Common::kReadingFailed; - } + // Validate the data file header + Common::File f; char id[5], lang[5]; id[4] = lang[4] = '\0'; - f.read(id, 3); - if (strncmp(id, "MSN", 3) != 0) { - GUIErrorMessageFormat(_("The '%s' engine data file is corrupt."), SUPERNOVA_DAT); - return Common::kReadingFailed; + if (_MSPart == 1) { + if (!f.open(SUPERNOVA_DAT)) { + GUIErrorMessageFormat(_("Unable to locate the '%s' engine data file."), SUPERNOVA_DAT); + return Common::kReadingFailed; + } + f.read(id, 3); + if (strncmp(id, "MSN", 3) != 0) { + GUIErrorMessageFormat(_("The '%s' engine data file is corrupt."), SUPERNOVA_DAT); + return Common::kReadingFailed; + } + + int version = f.readByte(); + if (version != SUPERNOVA_DAT_VERSION) { + GUIErrorMessageFormat( + _("Incorrect version of the '%s' engine data file found. Expected %d but got %d."), + SUPERNOVA_DAT, SUPERNOVA_DAT_VERSION, version); + return Common::kReadingFailed; + } } + else if (_MSPart == 2) { + if (!f.open(SUPERNOVA2_DAT)) { + GUIErrorMessageFormat(_("Unable to locate the '%s' engine data file."), SUPERNOVA2_DAT); + return Common::kReadingFailed; + } + f.read(id, 3); + if (strncmp(id, "MS2", 3) != 0) { + GUIErrorMessageFormat(_("The '%s' engine data file is corrupt."), SUPERNOVA2_DAT); + return Common::kReadingFailed; + } - int version = f.readByte(); - if (version != SUPERNOVA_DAT_VERSION) { - GUIErrorMessageFormat( - _("Incorrect version of the '%s' engine data file found. Expected %d but got %d."), - SUPERNOVA_DAT, SUPERNOVA_DAT_VERSION, version); - return Common::kReadingFailed; + int version = f.readByte(); + if (version != SUPERNOVA2_DAT_VERSION) { + GUIErrorMessageFormat( + _("Incorrect version of the '%s' engine data file found. Expected %d but got %d."), + SUPERNOVA2_DAT, SUPERNOVA2_DAT_VERSION, version); + return Common::kReadingFailed; + } } + while (!f.eos()) { f.read(id, 4); f.read(lang, 4); @@ -217,7 +246,7 @@ Common::Error SupernovaEngine::loadGameStrings() { } Common::Language l = Common::parseLanguage(cur_lang); - GUIErrorMessageFormat(_("Unable to locate the text for %s language in '%s' engine data file."), Common::getLanguageDescription(l), SUPERNOVA_DAT); + GUIErrorMessageFormat(_("Unable to locate the text for %s language in engine data file."), Common::getLanguageDescription(l)); return Common::kReadingFailed; } @@ -294,6 +323,11 @@ void SupernovaEngine::renderMessage(StringId stringId, MessagePosition position, _screen->renderMessage(stringId, position, var1, var2); } +void SupernovaEngine::renderMessage(StringId stringId, int x, int y) { + _gm->_messageDuration = (getGameString(stringId).size() + 20) * _textSpeed / 10; + _screen->renderMessage(getGameString(stringId).c_str(), kMessageNormal, x, y); +} + void SupernovaEngine::removeMessage() { _screen->removeMessage(); } @@ -346,9 +380,9 @@ void SupernovaEngine::paletteBrightness() { _screen->paletteBrightness(); } -void SupernovaEngine::paletteFadeOut() { +void SupernovaEngine::paletteFadeOut(int minBrightness) { if (!shouldQuit()) - _screen->paletteFadeOut(); + _screen->paletteFadeOut(minBrightness); } void SupernovaEngine::paletteFadeIn() { @@ -586,7 +620,7 @@ Common::Error SupernovaEngine::loadGameState(int slot) { bool SupernovaEngine::canSaveGameStateCurrently() { // Do not allow saving when either _allowSaveGame, _animationEnabled or _guiEnabled is false - return _allowSaveGame && _gm->_animationEnabled && _gm->_guiEnabled; + return _allowSaveGame && _gm->canSaveGameStateCurrently(); } Common::Error SupernovaEngine::saveGameState(int slot, const Common::String &desc) { @@ -633,13 +667,18 @@ bool SupernovaEngine::loadGame(int slot) { // continue to try to load it from there. } - Common::String filename = Common::String::format("msn_save.%03d", slot); + Common::String filename; + if (_MSPart == 1) + filename = Common::String::format("msn_save.%03d", slot); + else if (_MSPart == 2) + filename = Common::String::format("ms2_save.%03d", slot); Common::InSaveFile *savefile = _saveFileMan->openForLoading(filename); if (!savefile) return false; uint saveHeader = savefile->readUint32LE(); - if (saveHeader != SAVEGAME_HEADER) { + if ((_MSPart == 1 && saveHeader != SAVEGAME_HEADER) || + (_MSPart == 2 && saveHeader != SAVEGAME_HEADER2)) { warning("No header found in '%s'", filename.c_str()); delete savefile; return false; //Common::kUnknownError @@ -695,12 +734,20 @@ bool SupernovaEngine::saveGame(int slot, const Common::String &description) { return true; } - Common::String filename = Common::String::format("msn_save.%03d", slot); + Common::String filename; + if (_MSPart == 1) + filename = Common::String::format("msn_save.%03d", slot); + else if (_MSPart == 2) + filename = Common::String::format("ms2_save.%03d", slot); + Common::OutSaveFile *savefile = _saveFileMan->openForSaving(filename); if (!savefile) return false; - savefile->writeUint32LE(SAVEGAME_HEADER); + if (_MSPart == 1) + savefile->writeUint32LE(SAVEGAME_HEADER); + else if (_MSPart == 2) + savefile->writeUint32LE(SAVEGAME_HEADER2); savefile->writeByte(SAVEGAME_VERSION); TimeDate currentDate; @@ -736,5 +783,9 @@ void SupernovaEngine::errorTempSave(bool saving) { error("Unrecoverable error"); } +void SupernovaEngine::stopSound() { + _sound->stop(); +} + } diff --git a/engines/supernova/supernova.h b/engines/supernova/supernova.h index 94f07ee3bc..afdcf1ccef 100644 --- a/engines/supernova/supernova.h +++ b/engines/supernova/supernova.h @@ -44,11 +44,15 @@ namespace Common { namespace Supernova { #define SAVEGAME_HEADER MKTAG('M','S','N','1') +#define SAVEGAME_HEADER2 MKTAG('M','S','N','2') #define SAVEGAME_VERSION 9 #define SUPERNOVA_DAT "supernova.dat" #define SUPERNOVA_DAT_VERSION 1 +#define SUPERNOVA2_DAT "supernova2.dat" +#define SUPERNOVA2_DAT_VERSION 1 + class GuiElement; class ResourceManager; class Sound; @@ -83,6 +87,7 @@ public: uint _delay; int _textSpeed; + char _MSPart; Common::Error loadGameStrings(); void init(); @@ -102,7 +107,7 @@ public: void playSound(AudioId sample); void playSound(MusicId index); void paletteFadeIn(); - void paletteFadeOut(); + void paletteFadeOut(int minBrightness = 0); void paletteBrightness(); void renderImage(int section); void renderImage(ImageId id, bool removeImage = false); @@ -115,6 +120,7 @@ public: void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal); void renderMessage(StringId stringId, MessagePosition position = kMessageNormal, Common::String var1 = "", Common::String var2 = ""); + void renderMessage(StringId stringId, int x, int y); void removeMessage(); void renderText(const uint16 character); void renderText(const char *text); @@ -128,6 +134,7 @@ public: void renderBox(int x, int y, int width, int height, byte color); void renderBox(const GuiElement &guiElement); void setColor63(byte value); + void stopSound(); }; } diff --git a/engines/supernova2/state.cpp b/engines/supernova2/state.cpp index 0a35090ac0..67aa17292a 100644 --- a/engines/supernova2/state.cpp +++ b/engines/supernova2/state.cpp @@ -352,6 +352,7 @@ void GameManager::initState() { _processInput = false; _guiEnabled = true; _animationEnabled = true; + _roomBrightness = 255; _mouseClicked = false; _keyPressed = false; _mouseX = -1; diff --git a/engines/supernova2/state.h b/engines/supernova2/state.h index 1851da50fc..ce1e88f266 100644 --- a/engines/supernova2/state.h +++ b/engines/supernova2/state.h @@ -165,6 +165,7 @@ public: bool _processInput; bool _guiEnabled; bool _animationEnabled; + byte _roomBrightness; Action _inputVerb; Object _nullObject; Object *_currentInputObject; @@ -209,6 +210,7 @@ public: void waitOnInput(int ticks); bool waitOnInput(int ticks, Common::KeyCode &keycode); void screenShake(); + void roomBrightness() {} void showMenu(); void animationOff(); void animationOn(); @@ -223,6 +225,8 @@ public: void handleInput(); void handleTime(); void pauseTimer(bool pause); + void loadTime() {} + void saveTime() {} void setAnimationTimer(int ticks); void dead(StringId messageId); int dialog(int num, byte rowLength[6], StringId text[6], int number); diff --git a/engines/supernova2/supernova2.cpp b/engines/supernova2/supernova2.cpp index 938cfe6a52..6023d4d5f3 100644 --- a/engines/supernova2/supernova2.cpp +++ b/engines/supernova2/supernova2.cpp @@ -95,12 +95,12 @@ Supernova2Engine::Supernova2Engine(OSystem *syst) Supernova2Engine::~Supernova2Engine() { DebugMan.clearAllDebugChannels(); + delete _sleepAutoSave; delete _console; delete _gm; + delete _sound; delete _resMan; delete _screen; - delete _sleepAutoSave; - delete _sound; } Common::Error Supernova2Engine::run() { @@ -293,6 +293,7 @@ void Supernova2Engine::renderMessage(StringId stringId, MessagePosition position _gm->_messageDuration = (getGameString(stringId).size() + 20) * _textSpeed / 10; _screen->renderMessage(stringId, position, var1, var2); } + void Supernova2Engine::renderMessage(StringId stringId, int x, int y) { _gm->_messageDuration = (getGameString(stringId).size() + 20) * _textSpeed / 10; _screen->renderMessage(getGameString(stringId).c_str(), kMessageNormal, x, y); @@ -356,8 +357,10 @@ void Supernova2Engine::paletteFadeOut(int minBrightness) { } void Supernova2Engine::paletteFadeIn() { - if (!shouldQuit()) - _screen->paletteFadeIn(255); + if (!shouldQuit()) { + _gm->roomBrightness(); + _screen->paletteFadeIn(_gm->_roomBrightness); + } } void Supernova2Engine::setColor63(byte value) { @@ -376,6 +379,7 @@ void Supernova2Engine::setTextSpeed() { int boxHeight = 27; _gm->animationOff(); + _gm->saveTime(); saveScreen(boxX, boxY, boxWidth, boxHeight); renderBox(boxX, boxY, boxWidth, boxHeight, kColorBlue); @@ -413,6 +417,7 @@ void Supernova2Engine::setTextSpeed() { _gm->resetInputState(); restoreScreen(); + _gm->loadTime(); _gm->animationOn(); } |