aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/supernova/graphics.cpp91
-rw-r--r--engines/supernova/graphics.h3
-rw-r--r--engines/supernova/module.mk4
-rw-r--r--engines/supernova/resman.cpp86
-rw-r--r--engines/supernova/resman.h17
-rw-r--r--engines/supernova/screen.cpp86
-rw-r--r--engines/supernova/screen.h15
-rw-r--r--engines/supernova/screenstatic.cpp299
-rw-r--r--engines/supernova/sound.cpp16
-rw-r--r--engines/supernova/sound.h6
-rw-r--r--engines/supernova/state.cpp4
-rw-r--r--engines/supernova/state.h1
-rw-r--r--engines/supernova/supernova.cpp99
-rw-r--r--engines/supernova/supernova.h9
-rw-r--r--engines/supernova2/state.cpp1
-rw-r--r--engines/supernova2/state.h4
-rw-r--r--engines/supernova2/supernova2.cpp13
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();
}