diff options
author | Joseph-Eugene Winzer | 2018-03-25 00:07:37 +0100 |
---|---|---|
committer | Thierry Crozat | 2018-04-15 18:28:29 +0100 |
commit | 2ead17f09fb9c3c4af46cd86736fee654e6ad072 (patch) | |
tree | 041063063fe40b2d14e22078203146d59d85bfa6 /engines/supernova | |
parent | ac438cc918150a7549eee9cc45f60ca04a13f7da (diff) | |
download | scummvm-rg350-2ead17f09fb9c3c4af46cd86736fee654e6ad072.tar.gz scummvm-rg350-2ead17f09fb9c3c4af46cd86736fee654e6ad072.tar.bz2 scummvm-rg350-2ead17f09fb9c3c4af46cd86736fee654e6ad072.zip |
SUPERNOVA: Implements render functions
Although SupernovaEngine forwards render calls to screen, it also
exposed members publicly like _brightness. Therefore, a few changes were
necessary in rooms and state.
Diffstat (limited to 'engines/supernova')
-rw-r--r-- | engines/supernova/rooms.cpp | 130 | ||||
-rw-r--r-- | engines/supernova/rooms.h | 5 | ||||
-rw-r--r-- | engines/supernova/screen.cpp | 578 | ||||
-rw-r--r-- | engines/supernova/screen.h | 103 | ||||
-rw-r--r-- | engines/supernova/state.cpp | 57 | ||||
-rw-r--r-- | engines/supernova/state.h | 1 | ||||
-rw-r--r-- | engines/supernova/supernova.cpp | 429 | ||||
-rw-r--r-- | engines/supernova/supernova.h | 137 |
8 files changed, 836 insertions, 604 deletions
diff --git a/engines/supernova/rooms.cpp b/engines/supernova/rooms.cpp index beddc34963..7d68cdfda1 100644 --- a/engines/supernova/rooms.cpp +++ b/engines/supernova/rooms.cpp @@ -24,6 +24,7 @@ #include "graphics/palette.h" #include "graphics/cursorman.h" +#include "supernova/screen.h" #include "supernova/supernova.h" #include "supernova/state.h" @@ -147,102 +148,11 @@ void Intro::onEntrance() { leaveCutscene(); } -class Marquee { -public: - enum MarqueeIndex { - kMarqueeIntro, - kMarqueeOutro - }; - - Marquee(SupernovaEngine *vm, MarqueeIndex id, const char *text) - : _text(text) - , _textBegin(text) - , _delay(0) - , _color(kColorLightBlue) - , _loop(false) - , _vm(vm) - { - if (id == kMarqueeIntro) { - _y = 191; - _loop = true; - } else if (id == kMarqueeOutro) { - _y = 1; - } - _textWidth = _vm->textWidth(_text); - _x = kScreenWidth / 2 - _textWidth / 2; - _vm->_textCursorX = _x; - _vm->_textCursorY = _y; - _vm->_textColor = _color; - } - - void renderCharacter(); - -private: - void clearText(); - - SupernovaEngine *_vm; - MarqueeIndex _id; - const char *const _textBegin; - const char *_text; - bool _loop; - int _delay; - int _color; - int _x; - int _y; - int _textWidth; -}; - -void Marquee::clearText() { - _vm->renderBox(_x, _y - 1, _textWidth + 1, 9, kColorBlack); -} - -void Marquee::renderCharacter() { - if (_delay != 0) { - _delay--; - return; - } - - switch (*_text) { - case '\233': - if (_loop) { - _loop = false; - _text = _textBegin; - clearText(); - _textWidth = _vm->textWidth(_text); - _x = kScreenWidth / 2 - _textWidth / 2; - _vm->_textCursorX = _x; - } - break; - case '\0': - clearText(); - _text++; - _textWidth = _vm->textWidth(_text); - _x = kScreenWidth / 2 - _textWidth / 2; - _vm->_textCursorX = _x; - _color = kColorLightBlue; - _vm->_textColor = _color; - break; - case '^': - _color = kColorLightYellow; - _vm->_textColor = _color; - _text++; - break; - case '#': - _delay = 50; - _text++; - break; - default: - _vm->renderText((uint16)*_text++); - _delay = 1; - break; - } -} - void Intro::titleScreen() { // Newspaper CursorMan.showMouse(false); - _vm->_brightness = 0; - _vm->_menuBrightness = 0; + _vm->_screen->setViewportBrightness(0); + _vm->_screen->setGuiBrightness(0); _vm->paletteBrightness(); _vm->setCurrentImage(1); _vm->renderImage(0); @@ -263,14 +173,14 @@ void Intro::titleScreen() { const Common::String& title1 = _vm->getGameString(kStringTitle1); const Common::String& title2 = _vm->getGameString(kStringTitle2); const Common::String& title3 = _vm->getGameString(kStringTitle3); - _vm->renderText(title1, 78 - _vm->textWidth(title1) / 2, 120, kColorLightBlue); - _vm->renderText(title2, 78 - _vm->textWidth(title2) / 2, 132, kColorWhite99); - _vm->renderText(title3, 78 - _vm->textWidth(title3) / 2, 142, kColorWhite99); + _vm->_screen->renderText(title1, 78 - Screen::textWidth(title1) / 2, 120, kColorLightBlue); + _vm->_screen->renderText(title2, 78 - Screen::textWidth(title2) / 2, 132, kColorWhite99); + _vm->_screen->renderText(title3, 78 - Screen::textWidth(title3) / 2, 142, kColorWhite99); _gm->wait(1); CursorMan.showMouse(true); _vm->playSound(kMusicIntro); - Marquee marquee(_vm, Marquee::kMarqueeIntro, _introText.c_str()); + Marquee marquee(_vm->_screen, Marquee::kMarqueeIntro, _introText.c_str()); while (!_vm->shouldQuit()) { _gm->updateEvents(); marquee.renderCharacter(); @@ -381,11 +291,11 @@ void Intro::cutscene() { _vm->_system->fillScreen(kColorBlack); _vm->setCurrentImage(31); - _vm->_menuBrightness = 255; + _vm->_screen->setGuiBrightness(255); _vm->paletteBrightness(); if (!animate(0, 0, 0, kMessageNormal, kStringIntroCutscene1)) return; - _vm->_menuBrightness = 0; + _vm->_screen->setGuiBrightness(0); _vm->paletteBrightness(); exitOnEscape(1); @@ -531,11 +441,11 @@ void Intro::cutscene() { exitOnEscape(1); _vm->_system->fillScreen(kColorBlack); - _vm->_menuBrightness = 255; + _vm->_screen->setGuiBrightness(255); _vm->paletteBrightness(); if (!animate(0, 0, 0, kMessageNormal, kStringIntroCutscene25)) return; - _vm->_menuBrightness = 5; + _vm->_screen->setGuiBrightness(5); _vm->paletteBrightness(); _vm->setCurrentImage(31); @@ -558,7 +468,7 @@ void Intro::cutscene() { return; CursorMan.showMouse(false); - _vm->_brightness = 0; + _vm->_screen->setViewportBrightness(0); _vm->paletteBrightness(); exitOnEscape(10); _vm->playSound(kAudioSnoring); @@ -605,7 +515,7 @@ void Intro::cutscene() { } void Intro::leaveCutscene() { - _vm->_brightness = 255; + _vm->_screen->setViewportBrightness(255); _vm->removeMessage(); _gm->changeRoom(CABIN_R3); _gm->_guiEnabled = true; @@ -1616,7 +1526,7 @@ bool ArsanoMeetup::interact(Action verb, Object &obj1, Object &obj2) { } void ArsanoEntrance::animation() { - if (!_vm->_messageDisplayed && isSectionVisible(kMaxSection - 5)) { + if (!_vm->_screen->isMessageShown() && isSectionVisible(kMaxSection - 5)) { _gm->animationOff(); // to avoid recursive call _vm->playSound(kAudioSlideDoor); _vm->renderImage(8); @@ -2097,12 +2007,12 @@ bool ArsanoRoger::interact(Action verb, Object &obj1, Object &obj2) { _vm->paletteFadeOut(); _gm->_inventory.remove(*_gm->_rooms[CABIN_R3]->getObject(0)); // Chess board g_system->fillScreen(kColorBlack); - _vm->_menuBrightness = 255; + _vm->_screen->setGuiBrightness(255); _vm->paletteBrightness(); _vm->renderMessage(kStringArsanoRoger39); _gm->waitOnInput(_gm->_messageDuration); _vm->removeMessage(); - _vm->_menuBrightness = 0; + _vm->_screen->setGuiBrightness(0); _vm->paletteBrightness(); _gm->_state._time += ticksToMsec(125000); // 2 hours _gm->_state._alarmOn = (_gm->_state._timeAlarm > _gm->_state._time); @@ -3207,12 +3117,12 @@ bool AxacussElevator::interact(Action verb, Object &obj1, Object &obj2) { } else if ((verb == ACTION_WALK) && (obj1._id == JUNGLE)) { _vm->paletteFadeOut(); g_system->fillScreen(kColorBlack); - _vm->_menuBrightness = 255; + _vm->_screen->setGuiBrightness(255); _vm->paletteBrightness(); _vm->renderMessage(kStringAxacussElevator_3); _gm->waitOnInput(_gm->_messageDuration); _vm->removeMessage(); - _vm->_menuBrightness = 0; + _vm->_screen->setGuiBrightness(0); _vm->paletteBrightness(); _gm->_state._time += ticksToMsec(125000); // 2 hours _gm->_state._alarmOn = (_gm->_state._timeAlarm > _gm->_state._time); @@ -3296,7 +3206,7 @@ void Outro::onEntrance() { } _vm->playSound(kMusicOutro); - Marquee marquee(_vm, Marquee::kMarqueeOutro, _outroText.c_str()); + Marquee marquee(_vm->_screen, Marquee::kMarqueeOutro, _outroText.c_str()); while (!_vm->shouldQuit()) { _gm->updateEvents(); marquee.renderCharacter(); @@ -3311,7 +3221,7 @@ void Outro::onEntrance() { _vm->paletteFadeIn(); _gm->getInput(); _vm->paletteFadeOut(); - _vm->_brightness = 1; + _vm->_screen->setViewportBrightness(1); Common::Event event; event.type = Common::EVENT_RTL; diff --git a/engines/supernova/rooms.h b/engines/supernova/rooms.h index 3cedc356db..59cec07d60 100644 --- a/engines/supernova/rooms.h +++ b/engines/supernova/rooms.h @@ -27,6 +27,11 @@ #include "msn_def.h" +namespace Common { +class ReadStream; +class WriteStream; +} + namespace Supernova { class GameManager; diff --git a/engines/supernova/screen.cpp b/engines/supernova/screen.cpp index a5285aafb6..93f52f53ba 100644 --- a/engines/supernova/screen.cpp +++ b/engines/supernova/screen.cpp @@ -20,14 +20,590 @@ * */ +#include "common/str.h" +#include "common/system.h" +#include "engines/util.h" +#include "graphics/palette.h" +#include "graphics/surface.h" + +#include "supernova/resman.h" +#include "supernova/state.h" #include "supernova/screen.h" +#include "supernova/supernova.h" #include "supernova/screenstatic.cpp" namespace Supernova { -Screen::Screen(SupernovaEngine *vm, ResourceManager *resMan) { +ScreenBuffer::ScreenBuffer() + : _x(0) + , _y(0) + , _width(0) + , _height(0) + , _pixels(nullptr) { +} + +ScreenBufferStack::ScreenBufferStack() + : _last(_buffer) { +} + +void ScreenBufferStack::push(int x, int y, int width, int height) { + if (_last == ARRAYEND(_buffer)) + return; + + Graphics::Surface *screenSurface = g_system->lockScreen(); + + if (x < 0) { + width += x; + x = 0; + } + + if (x + width > screenSurface->w) + width = screenSurface->w - x; + + if (y < 0) { + height += y; + y = 0; + } + + if (y + height > screenSurface->h) + height = screenSurface->h - y; + + _last->_pixels = new byte[width * height]; + byte *pixels = _last->_pixels; + const byte *screen = static_cast<const byte *>(screenSurface->getBasePtr(x, y)); + for (int i = 0; i < height; ++i) { + Common::copy(screen, screen + width, pixels); + screen += screenSurface->pitch; + pixels += width; + } + g_system->unlockScreen(); + + _last->_x = x; + _last->_y = y; + _last->_width = width; + _last->_height = height; + + ++_last; +} + +void ScreenBufferStack::restore() { + if (_last == _buffer) + return; + + --_last; + g_system->lockScreen()->copyRectToSurface(_last->_pixels, _last->_width, _last->_x, + _last->_y, _last->_width, _last->_height); + g_system->unlockScreen(); + + delete[] _last->_pixels; +} + +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; + } + + _textWidth = Screen::textWidth(_text); + _x = kScreenWidth / 2 - _textWidth / 2; + _screen->_textCursorX = _x; + _screen->_textCursorY = _y; + _screen->_textColor = _color; +} + +void Marquee::clearText() { + _screen->renderBox(_x, _y - 1, _textWidth + 1, 9, kColorBlack); +} + +void Marquee::renderCharacter() { + if (_delay != 0) { + _delay--; + return; + } + + switch (*_text) { + case '\233': + if (_loop) { + _loop = false; + _text = _textBegin; + clearText(); + _textWidth = Screen::textWidth(_text); + _x = kScreenWidth / 2 - _textWidth / 2; + _screen->_textCursorX = _x; + } + break; + case '\0': + clearText(); + _text++; + _textWidth = Screen::textWidth(_text); + _x = kScreenWidth / 2 - _textWidth / 2; + _screen->_textCursorX = _x; + _color = kColorLightBlue; + _screen->_textColor = _color; + break; + case '^': + _color = kColorLightYellow; + _screen->_textColor = _color; + _text++; + break; + case '#': + _delay = 50; + _text++; + break; + default: + _screen->renderText((uint16)*_text++); + _delay = 1; + break; + } +} + +Screen::Screen(SupernovaEngine *vm, GameManager *gm, ResourceManager *resMan) + : _vm(vm) + , _gm(gm) + , _resMan(resMan) + , _currentImage(nullptr) + , _viewportBrightness(255) + , _guiBrightness(255) + , _screenWidth(320) + , _screenHeight(200) + , _textColor(kColorBlack) + , _textCursorX(0) + , _textCursorY(0) + , _messageShown(false) { +} + +int Screen::getGuiBrightness() const { + return _guiBrightness; +} + +void Screen::setViewportBrightness(int brightness) { + _viewportBrightness = brightness; +} + +int Screen::getViewportBrightness() const { + return _viewportBrightness; +} + +void Screen::setGuiBrightness(int brightness) { + _guiBrightness = brightness; +} + +const MSNImage *Screen::getCurrentImage() const { + return _currentImage; +} + +bool Screen::isMessageShown() const { + return _messageShown; +} + +Common::Point Screen::getTextCursorPos() { + return Common::Point(_textCursorX, _textCursorY); +} + +void Screen::setTextCursorPos(int x, int y) { + _textCursorX = x; + _textCursorY = y; +} + +byte Screen::getTextCursorColor() { + return _textColor; +} + +void Screen::setTextCursorColor(byte color) { + _textColor = color; +} + +void Screen::renderMessage(StringID stringId, MessagePosition position, + Common::String var1, Common::String var2) { + Common::String text = _vm->getGameString(stringId); + + if (!var1.empty()) { + if (!var2.empty()) + text = Common::String::format(text.c_str(), var1.c_str(), var2.c_str()); + else + text = Common::String::format(text.c_str(), var1.c_str()); + } + + renderMessage(text, position); +} + +void Screen::renderMessage(const Common::String &text, MessagePosition position) { + if (!text.empty()) + renderMessage(text.c_str(), position); +} + +void Screen::renderText(const uint16 character) { + char text[2]; + text[0] = character & 0xFF; + text[1] = 0; + renderText(text, _textCursorX, _textCursorY, _textColor); +} + +void Screen::renderText(const char *text) { + renderText(text, _textCursorX, _textCursorY, _textColor); +} + +void Screen::renderText(StringID stringId) { + renderText(_vm->getGameString(stringId)); +} + +void Screen::renderText(const Common::String &text) { + if (!text.empty()) + renderText(text.c_str()); +} + +void Screen::renderText(const GuiElement &guiElement) { + renderText(guiElement.getText(), guiElement.getTextPos().x, + guiElement.getTextPos().y, guiElement.getTextColor()); +} + +void Screen::renderText(const uint16 character, int x, int y, byte color) { + char text[2]; + text[0] = character & 0xFF; + text[1] = 0; + renderText(text, x, y, color); +} + +void Screen::renderText(const char *text, int x, int y, byte color) { + Graphics::Surface *screen = _vm->_system->lockScreen(); + byte *cursor = static_cast<byte *>(screen->getBasePtr(x, y)); + const byte *basePtr = cursor; + + byte c; + while ((c = *text++) != '\0') { + if (c < 32) { + continue; + } else if (c == 225) { + c = 128; + } + + for (uint i = 0; i < 5; ++i) { + if (font[c - 32][i] == 0xff) { + break; + } + + byte *ascentLine = cursor; + for (byte j = font[c - 32][i]; j != 0; j >>= 1) { + if (j & 1) { + *cursor = color; + } + cursor += kScreenWidth; + } + cursor = ++ascentLine; + } + ++cursor; + } + _vm->_system->unlockScreen(); + + uint numChars = cursor - basePtr; + uint absPosition = y * kScreenWidth + x + numChars; + _textCursorX = absPosition % kScreenWidth; + _textCursorY = absPosition / kScreenWidth; + _textColor = color; +} + +void Screen::renderText(const Common::String &text, int x, int y, byte color) { + if (!text.empty()) + renderText(text.c_str(), x, y, color); +} + +void Screen::renderText(StringID stringId, int x, int y, byte color) { + renderText(_vm->getGameString(stringId), x, y, color); +} + +void Screen::renderImageSection(int section) { + // Note: inverting means we are removing the section. So we should get the rect for that + // section but draw the background (section 0) instead. + bool invert = false; + if (section > 128) { + section -= 128; + invert = true; + } + if (!_currentImage || section > _currentImage->_numSections - 1) + return; + + Common::Rect sectionRect(_currentImage->_section[section].x1, + _currentImage->_section[section].y1, + _currentImage->_section[section].x2 + 1, + _currentImage->_section[section].y2 + 1) ; + if (_currentImage->_filenumber == 1 || _currentImage->_filenumber == 2) { + sectionRect.setWidth(640); + sectionRect.setHeight(480); + if (_screenWidth != 640) { + _screenWidth = 640; + _screenHeight = 480; + initGraphics(_screenWidth, _screenHeight); + } + } else { + if (_screenWidth != 320) { + _screenWidth = 320; + _screenHeight = 200; + initGraphics(_screenWidth, _screenHeight); + } + } + + uint offset = 0; + int pitch = sectionRect.width(); + if (invert) { + pitch = _currentImage->_pitch; + offset = _currentImage->_section[section].y1 * pitch + + _currentImage->_section[section].x1; + section = 0; + } + + void *pixels = _currentImage->_sectionSurfaces[section]->getPixels(); + _vm->_system->copyRectToScreen(static_cast<const byte *>(pixels) + offset, + pitch, sectionRect.left, sectionRect.top, + sectionRect.width(), sectionRect.height()); +} + +void Screen::renderImage(ImageID id) { + // TODO: include staticscreen.cpp and render section of filenumber +} + +void Screen::renderImage(int section) { + if (!_currentImage) + return; + + bool sectionVisible = true; + + if (section > 128) { + sectionVisible = false; + section -= 128; + } + + _gm->_currentRoom->setSectionVisible(section, sectionVisible); + + do { + if (sectionVisible) + renderImageSection(section); + else + renderImageSection(section + 128); + section = _currentImage->_section[section].next; + } while (section != 0); +} + +bool Screen::setCurrentImage(int filenumber) { + _currentImage = _resMan->getImage(filenumber); + _vm->_system->getPaletteManager()->setPalette(_currentImage->getPalette(), 16, 239); + paletteBrightness(); + + return true; +} + +void Screen::saveScreen(int x, int y, int width, int height) { + _screenBuffer.push(x, y, width, height); +} + +void Screen::saveScreen(const GuiElement &guiElement) { + saveScreen(guiElement.left, guiElement.top, guiElement.width(), guiElement.height()); +} + +void Screen::restoreScreen() { + _screenBuffer.restore(); +} + +void Screen::renderRoom(Room &room) { + if (room.getId() == INTRO) + return; + + if (setCurrentImage(room.getFileNumber())) { + for (int i = 0; i < _currentImage->_numSections; ++i) { + int section = i; + if (room.isSectionVisible(section)) { + do { + renderImageSection(section); + section = _currentImage->_section[section].next; + } while (section != 0); + } + } + } +} + +int Screen::textWidth(const uint16 key) { + char text[2]; + text[0] = key & 0xFF; + text[1] = 0; + return textWidth(text); +} + +int Screen::textWidth(const char *text) { + int charWidth = 0; + while (*text != '\0') { + byte c = *text++; + if (c < 32) { + continue; + } else if (c == 225) { + c = 35; + } + + for (uint i = 0; i < 5; ++i) { + if (font[c - 32][i] == 0xff) { + break; + } + ++charWidth; + } + ++charWidth; + } + + return charWidth; +} + +int Screen::textWidth(const Common::String &text) { + return Screen::textWidth(text.c_str()); +} + +void Screen::renderMessage(const char *text, MessagePosition position) { + Common::String t(text); + char *row[20]; + Common::String::iterator p = t.begin(); + uint numRows = 0; + int rowWidthMax = 0; + int x = 0; + int y = 0; + byte textColor = 0; + + while (*p != '\0') { + row[numRows] = p; + ++numRows; + while ((*p != '\0') && (*p != '|')) { + ++p; + } + if (*p == '|') { + *p = '\0'; + ++p; + } + } + for (uint i = 0; i < numRows; ++i) { + int rowWidth = textWidth(row[i]); + if (rowWidth > rowWidthMax) + rowWidthMax = rowWidth; + } + + switch (position) { + case kMessageNormal: + x = 160 - rowWidthMax / 2; + textColor = kColorWhite99; + break; + case kMessageTop: + x = 160 - rowWidthMax / 2; + textColor = kColorLightYellow; + break; + case kMessageCenter: + x = 160 - rowWidthMax / 2; + textColor = kColorLightRed; + break; + case kMessageLeft: + x = 3; + textColor = kColorLightYellow; + break; + case kMessageRight: + x = 317 - rowWidthMax; + textColor = kColorLightGreen; + break; + } + + if (position == kMessageNormal) { + y = 70 - ((numRows * 9) / 2); + } else if (position == kMessageTop) { + y = 5; + } else { + y = 142; + } + + int message_columns = x - 3; + int message_rows = y - 3; + int message_width = rowWidthMax + 6; + int message_height = numRows * 9 + 5; + saveScreen(message_columns, message_rows, message_width, message_height); + renderBox(message_columns, message_rows, message_width, message_height, kColorWhite35); + for (uint i = 0; i < numRows; ++i) { + renderText(row[i], x, y, textColor); + y += 9; + } + + _messageShown = true; + _gm->_messageDuration = (Common::strnlen(text, 512) + 20) * _vm->_textSpeed / 10; +} + +void Screen::removeMessage() { + if (_messageShown) { + restoreScreen(); + _messageShown = false; + } +} + +void Screen::renderBox(int x, int y, int width, int height, byte color) { + Graphics::Surface *screen = _vm->_system->lockScreen(); + screen->fillRect(Common::Rect(x, y, x + width, y + height), color); + _vm->_system->unlockScreen(); +} + +void Screen::renderBox(const GuiElement &guiElement) { + renderBox(guiElement.left, guiElement.top, guiElement.width(), + guiElement.height(), guiElement.getBackgroundColor()); +} +void Screen::paletteBrightness() { + byte palette[768]; + + _vm->_system->getPaletteManager()->grabPalette(palette, 0, 255); + for (uint i = 0; i < 48; ++i) { + palette[i] = (initVGAPalette[i] * _guiBrightness) >> 8; + } + for (uint i = 0; i < 717; ++i) { + const byte *imagePalette; + if (_currentImage && _currentImage->getPalette()) { + imagePalette = _currentImage->getPalette(); + } else { + imagePalette = palette + 48; + } + palette[i + 48] = (imagePalette[i] * _viewportBrightness) >> 8; + } + _vm->_system->getPaletteManager()->setPalette(palette, 0, 255); +} + +void Screen::paletteFadeOut() { + while (_guiBrightness > 10) { + _guiBrightness -= 10; + if (_viewportBrightness > _guiBrightness) + _viewportBrightness = _guiBrightness; + paletteBrightness(); + _vm->_system->updateScreen(); + _vm->_system->delayMillis(_vm->_delay); + } + _guiBrightness = 0; + _viewportBrightness = 0; + paletteBrightness(); + _vm->_system->updateScreen(); +} + +void Screen::paletteFadeIn() { + while (_guiBrightness < 245) { + if (_viewportBrightness < _gm->_roomBrightness) + _viewportBrightness += 10; + _guiBrightness += 10; + paletteBrightness(); + _vm->_system->updateScreen(); + _vm->_system->delayMillis(_vm->_delay); + } + _guiBrightness = 255; + _viewportBrightness = _gm->_roomBrightness; + paletteBrightness(); + _vm->_system->updateScreen(); +} +void Screen::setColor63(byte value) { + byte color[3] = {value, value, value}; + _vm->_system->getPaletteManager()->setPalette(color, 63, 1); } } diff --git a/engines/supernova/screen.h b/engines/supernova/screen.h index df1b97bec3..6bfa1ba058 100644 --- a/engines/supernova/screen.h +++ b/engines/supernova/screen.h @@ -23,6 +23,8 @@ #ifndef SUPERNOVA_SCREEN_H #define SUPERNOVA_SCREEN_H +#include "common/array.h" +#include "common/rect.h" #include "common/scummsys.h" #include "supernova/imageid.h" @@ -31,11 +33,67 @@ namespace Supernova { class SupernovaEngine; +class GameManager; class ResourceManager; class GuiElement; class Room; +class MSNImage; +class Screen; + +class ScreenBuffer { + friend class ScreenBufferStack; + +public: + ScreenBuffer(); + +private: + byte *_pixels; + int _x; + int _y; + int _width; + int _height; +}; + +class ScreenBufferStack { +public: + ScreenBufferStack(); + + void push(int x, int y, int width, int height); + void restore(); + +private: + ScreenBuffer _buffer[8]; + ScreenBuffer *_last; +}; + +class Marquee { +public: + enum MarqueeId { + kMarqueeIntro, + kMarqueeOutro + }; + + Marquee(Screen *screen, MarqueeId id, const char *text); + + void renderCharacter(); + +private: + void clearText(); + + Screen *_screen; + const char *const _textBegin; + const char *_text; + bool _loop; + int _delay; + int _color; + int _x; + int _y; + int _textWidth; +}; class Screen { + friend class Marquee; + public: struct ImageInfo { int filenumber; @@ -43,11 +101,23 @@ public: }; public: - Screen(SupernovaEngine *vm, ResourceManager *resMan); + static int textWidth(const uint16 key); + static int textWidth(const char *text); + static int textWidth(const Common::String &text); + +public: + Screen(SupernovaEngine *vm, GameManager *gm, ResourceManager *resMan); + int getViewportBrightness() const; + void setViewportBrightness(int brightness); + int getGuiBrightness() const; + void setGuiBrightness(int brightness); + const MSNImage *getCurrentImage() const; + bool isMessageShown() const; void paletteFadeIn(); void paletteFadeOut(); void paletteBrightness(); + void renderImage(ImageID id); void renderImage(int section); void renderImageSection(int section); bool setCurrentImage(int filenumber); @@ -56,19 +126,42 @@ public: void restoreScreen(); void renderRoom(Room &room); void renderMessage(const char *text, MessagePosition position = kMessageNormal); + void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal); + void renderMessage(StringID stringId, MessagePosition position = kMessageNormal, + Common::String var1 = "", Common::String var2 = ""); void removeMessage(); - void renderText(const char *text, int x, int y, byte color); - void renderText(const uint16 character, int x, int y, byte color); - void renderText(const char *text); void renderText(const uint16 character); + void renderText(const char *text); + void renderText(const Common::String &text); + void renderText(StringID stringId); + void renderText(const uint16 character, int x, int y, byte color); + void renderText(const char *text, int x, int y, byte color); + void renderText(const Common::String &text, int x, int y, byte color); + void renderText(StringID stringId, int x, int y, byte color); void renderText(const GuiElement &guiElement); void renderBox(int x, int y, int width, int height, byte color); void renderBox(const GuiElement &guiElement); void setColor63(byte value); + Common::Point getTextCursorPos(); + void setTextCursorPos(int x, int y); + byte getTextCursorColor(); + void setTextCursorColor(byte color); void update(); private: - + SupernovaEngine *_vm; + GameManager *_gm; + ResourceManager *_resMan; + const MSNImage *_currentImage; + ScreenBufferStack _screenBuffer; + int _screenWidth; + int _screenHeight; + int _textCursorX; + int _textCursorY; + int _textColor; + byte _viewportBrightness; + byte _guiBrightness; + bool _messageShown; }; } diff --git a/engines/supernova/state.cpp b/engines/supernova/state.cpp index 5933c5fdf9..70a0767d49 100644 --- a/engines/supernova/state.cpp +++ b/engines/supernova/state.cpp @@ -21,11 +21,13 @@ */ #include "common/system.h" +#include "graphics/cursorman.h" #include "graphics/palette.h" #include "gui/message.h" + +#include "supernova/screen.h" #include "supernova/supernova.h" #include "supernova/state.h" -#include "graphics/cursorman.h" namespace Supernova { @@ -467,7 +469,7 @@ void GameManager::initGui() { int cmdAvailableSpace = 320 - (cmdCount - 1) * 2; for (int i = 0; i < cmdCount; ++i) { const Common::String &text = _vm->getGameString(guiCommands[i]); - cmdAvailableSpace -= _vm->textWidth(text); + cmdAvailableSpace -= Screen::textWidth(text); } int commandButtonX = 0; @@ -477,7 +479,7 @@ void GameManager::initGui() { if (i < cmdCount - 1) { int space = cmdAvailableSpace / (cmdCount - i); cmdAvailableSpace -= space; - width = _vm->textWidth(text) + space; + width = Screen::textWidth(text) + space; } else width = 320 - commandButtonX; @@ -506,7 +508,7 @@ void GameManager::initGui() { void GameManager::updateEvents() { handleTime(); - if (_animationEnabled && !_vm->_messageDisplayed && _animationTimer == 0) + if (_animationEnabled && !_vm->_screen->isMessageShown() && _animationTimer == 0) _currentRoom->animation(); if (_state._eventCallback != kNoFn && _state._time >= _state._eventTime) { @@ -645,7 +647,7 @@ void GameManager::processInput() { mouseLocation = onNone; if (_mouseClickType == Common::EVENT_LBUTTONUP) { - if (_vm->_messageDisplayed) { + if (_vm->_screen->isMessageShown()) { // Hide the message and consume the event _vm->removeMessage(); if (mouseLocation != onCmdButton) @@ -688,7 +690,7 @@ void GameManager::processInput() { } } else if (_mouseClickType == Common::EVENT_RBUTTONUP) { - if (_vm->_messageDisplayed) { + if (_vm->_screen->isMessageShown()) { // Hide the message and consume the event _vm->removeMessage(); return; @@ -740,8 +742,9 @@ void GameManager::processInput() { for (int i = 0; (_currentRoom->getObject(i)->_id != INVALIDOBJECT) && (field == -1) && i < kMaxObject; i++) { click = _currentRoom->getObject(i)->_click; - if (click != 255 && _vm->_currentImage) { - MSNImage::ClickField *clickField = _vm->_currentImage->_clickField; + const MSNImage *image = _vm->_screen->getCurrentImage(); + if (click != 255 && image) { + const MSNImage::ClickField *clickField = image->_clickField; do { if ((_mouseX >= clickField[click].x1) && (_mouseX <= clickField[click].x2) && (_mouseY >= clickField[click].y1) && (_mouseY <= clickField[click].y2)) @@ -1120,14 +1123,14 @@ void GameManager::supernovaEvent() { novaScroll(); _vm->paletteFadeOut(); _vm->renderBox(0, 0, 320, 200, kColorBlack); - _vm->_menuBrightness = 255; + _vm->_screen->setGuiBrightness(255); _vm->paletteBrightness(); if (_currentRoom->getId() == GLIDER) { _vm->renderMessage(kStringSupernova3); waitOnInput(_messageDuration); _vm->removeMessage(); - _vm->_menuBrightness = 0; + _vm->_screen->setGuiBrightness(0); _vm->paletteBrightness(); _vm->renderRoom(*_currentRoom); _vm->paletteFadeIn(); @@ -1153,7 +1156,7 @@ void GameManager::supernovaEvent() { _vm->renderMessage(kStringSupernova8); waitOnInput(_messageDuration); _vm->removeMessage(); - _vm->_menuBrightness = 0; + _vm->_screen->setGuiBrightness(0); _vm->paletteBrightness(); changeRoom(MEETUP2); if (_rooms[ROGER]->getObject(3)->hasProperty(CARRIED) && !_rooms[GLIDER]->isSectionVisible(5)) { @@ -1204,7 +1207,7 @@ void GameManager::guardWalkEvent() { _rooms[BCORRIDOR]->getObject(_state._origin + 4)->hasProperty(OPENED)); _rooms[BCORRIDOR]->getObject(_state._origin + 4)->disableProperty(OCCUPIED); if (_currentRoom == _rooms[BCORRIDOR]) { - if (_vm->_messageDisplayed) + if (_vm->_screen->isMessageShown()) _vm->removeMessage(); if (!behind) { @@ -1522,7 +1525,7 @@ void GameManager::turnOn() { return; _state._powerOff = false; - _vm->_brightness = 255; + _vm->_screen->setViewportBrightness(255); _rooms[SLEEP]->setSectionVisible(1, false); _rooms[SLEEP]->setSectionVisible(2, false); _rooms[COCKPIT]->setSectionVisible(22, false); @@ -1541,7 +1544,7 @@ void GameManager::takeObject(Object &obj) { void GameManager::drawCommandBox() { for (int i = 0; i < ARRAYSIZE(_guiCommandButton); ++i) { _vm->renderBox(_guiCommandButton[i]); - int space = (_guiCommandButton[i].width() - _vm->textWidth(_guiCommandButton[i].getText())) / 2; + int space = (_guiCommandButton[i].width() - Screen::textWidth(_guiCommandButton[i].getText())) / 2; _vm->renderText(_guiCommandButton[i].getText(), _guiCommandButton[i].getTextPos().x + space, _guiCommandButton[i].getTextPos().y, @@ -1628,8 +1631,8 @@ void GameManager::roomBrightness() { else if ((_currentRoom->getId() == GUARD3) && _state._powerOff) _roomBrightness = 0; - if (_vm->_brightness != 0) - _vm->_brightness = _roomBrightness; + if (_vm->_screen->getViewportBrightness() != 0) + _vm->_screen->setViewportBrightness(_roomBrightness); _vm->paletteBrightness(); } @@ -1774,24 +1777,24 @@ void GameManager::edit(Common::String &input, int x, int y, uint length) { kScreenWidth - x : (length + 1) * (kFontWidth + 2); while (isEditing) { - _vm->_textCursorX = x; - _vm->_textCursorY = y; - _vm->_textColor = kColorWhite99; + _vm->_screen->setTextCursorPos(x, y); + _vm->_screen->setTextCursorColor(kColorWhite99); _vm->renderBox(x, y - 1, overdrawWidth, 9, kColorDarkBlue); for (uint i = 0; i < input.size(); ++i) { // Draw char highlight depending on cursor position if (i == cursorIndex) { - _vm->renderBox(_vm->_textCursorX, y - 1, _vm->textWidth(input[i]), 9, kColorWhite99); - _vm->_textColor = kColorDarkBlue; + _vm->renderBox(_vm->_screen->getTextCursorPos().x, y - 1, + Screen::textWidth(input[i]), 9, kColorWhite99); + _vm->_screen->setTextCursorColor(kColorDarkBlue); _vm->renderText(input[i]); - _vm->_textColor = kColorWhite99; + _vm->_screen->setTextCursorColor(kColorWhite99); } else _vm->renderText(input[i]); } if (cursorIndex == input.size()) { - _vm->renderBox(_vm->_textCursorX + 1, y - 1, 6, 9, kColorDarkBlue); - _vm->renderBox(_vm->_textCursorX , y - 1, 1, 9, kColorWhite99); + _vm->renderBox(_vm->_screen->getTextCursorPos().x + 1, y - 1, 6, 9, kColorDarkBlue); + _vm->renderBox(_vm->_screen->getTextCursorPos().x, y - 1, 1, 9, kColorWhite99); } getKeyInput(true); @@ -2299,7 +2302,7 @@ void GameManager::handleInput() { } void GameManager::executeRoom() { - if (_processInput && !_vm->_messageDisplayed && _guiEnabled) { + if (_processInput && !_vm->_screen->isMessageShown() && _guiEnabled) { handleInput(); if (_mouseClicked) { Common::Event event; @@ -2315,7 +2318,7 @@ void GameManager::executeRoom() { } if (_guiEnabled) { - if (!_vm->_messageDisplayed) { + if (!_vm->_screen->isMessageShown()) { g_system->fillScreen(kColorBlack); _vm->renderRoom(*_currentRoom); } @@ -2326,7 +2329,7 @@ void GameManager::executeRoom() { } roomBrightness(); - if (_vm->_brightness == 0) + if (_vm->_screen->getViewportBrightness() == 0) _vm->paletteFadeIn(); if (!_currentRoom->hasSeen() && _newRoom) { diff --git a/engines/supernova/state.h b/engines/supernova/state.h index 46387811d1..dc2ff378e1 100644 --- a/engines/supernova/state.h +++ b/engines/supernova/state.h @@ -23,6 +23,7 @@ #ifndef SUPERNOVA_STATE_H #define SUPERNOVA_STATE_H +#include "common/events.h" #include "common/rect.h" #include "common/keyboard.h" #include "supernova/rooms.h" diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp index d1e1311a5a..d1921a8574 100644 --- a/engines/supernova/supernova.cpp +++ b/engines/supernova/supernova.cpp @@ -42,13 +42,13 @@ #include "gui/saveload.h" #include "supernova/resman.h" +#include "supernova/screen.h" #include "supernova/sound.h" #include "supernova/supernova.h" #include "supernova/state.h" namespace Supernova { - const Object Object::nullObject; ObjectType operator|(ObjectType a, ObjectType b) { @@ -79,25 +79,17 @@ SupernovaEngine::SupernovaEngine(OSystem *syst) : Engine(syst) , _console(nullptr) , _gm(nullptr) - , _currentImage(nullptr) + , _sound(nullptr) + , _resMan(nullptr) + , _screen(nullptr) , _rnd("supernova") - , _brightness(255) - , _menuBrightness(255) , _delay(33) , _textSpeed(kTextSpeed[2]) - , _screenWidth(320) - , _screenHeight(200) - , _messageDisplayed(false) , _allowLoadGame(true) - , _allowSaveGame(true) -{ -// const Common::FSNode gameDataDir(ConfMan.get("path")); -// SearchMan.addSubDirectoryMatching(gameDataDir, "sound"); - + , _allowSaveGame(true) { if (ConfMan.hasKey("textspeed")) _textSpeed = ConfMan.getInt("textspeed"); - // setup engine specific debug channels DebugMan.addDebugChannel(kDebugGeneral, "general", "Supernova general debug channel"); } @@ -108,6 +100,7 @@ SupernovaEngine::~SupernovaEngine() { delete _gm; delete _sound; delete _resMan; + delete _screen; } Common::Error SupernovaEngine::run() { @@ -134,7 +127,7 @@ void SupernovaEngine::init() { modes.push_back(Graphics::Mode(320, 200)); modes.push_back(Graphics::Mode(640, 480)); initGraphicsModes(modes); - initGraphics(_screenWidth, _screenHeight); + initGraphics(320, 200); Common::Error status = loadGameStrings(); if (status.getCode() != Common::kNoError) @@ -143,6 +136,7 @@ void SupernovaEngine::init() { _resMan = new ResourceManager(this); _sound = new Sound(_mixer, _resMan); _gm = new GameManager(this, _sound); + _screen = new Screen(this, _gm, _resMan); _console = new Console(this, _gm); setTotalPlayTime(0); @@ -231,6 +225,20 @@ Common::Error SupernovaEngine::loadGameStrings() { return Common::kReadingFailed; } +const Common::String &SupernovaEngine::getGameString(int idx) const { + if (idx < 0 || idx >= (int)_gameStrings.size()) + return _nullString; + return _gameStrings[idx]; +} + +void SupernovaEngine::setGameString(int idx, const Common::String &string) { + if (idx < 0) + return; + while ((int)_gameStrings.size() <= idx) + _gameStrings.push_back(Common::String()); + _gameStrings[idx] = string; +} + void SupernovaEngine::playSound(AudioIndex sample) { _sound->play(sample); } @@ -240,348 +248,114 @@ void SupernovaEngine::playSound(MusicIndex index) { } void SupernovaEngine::renderImageSection(int section) { - // Note: inverting means we are removing the section. So we should get the rect for that - // section but draw the background (section 0) instead. - bool invert = false; - if (section > 128) { - section -= 128; - invert = true; - } - if (!_currentImage || section > _currentImage->_numSections - 1) - return; - - Common::Rect sectionRect(_currentImage->_section[section].x1, - _currentImage->_section[section].y1, - _currentImage->_section[section].x2 + 1, - _currentImage->_section[section].y2 + 1) ; - if (_currentImage->_filenumber == 1 || _currentImage->_filenumber == 2) { - sectionRect.setWidth(640); - sectionRect.setHeight(480); - if (_screenWidth != 640) { - _screenWidth = 640; - _screenHeight = 480; - initGraphics(_screenWidth, _screenHeight); - } - } else { - if (_screenWidth != 320) { - _screenWidth = 320; - _screenHeight = 200; - initGraphics(_screenWidth, _screenHeight); - } - } - - uint offset = 0; - int pitch = sectionRect.width(); - if (invert) { - pitch = _currentImage->_pitch; - offset = _currentImage->_section[section].y1 * pitch + _currentImage->_section[section].x1; - section = 0; - } - - _system->copyRectToScreen(static_cast<const byte *>(_currentImage->_sectionSurfaces[section]->getPixels()) + offset, - pitch, - sectionRect.left, sectionRect.top, - sectionRect.width(), sectionRect.height()); + _screen->renderImageSection(section); } void SupernovaEngine::renderImage(int section) { - if (!_currentImage) - return; - - bool sectionVisible = true; - - if (section > 128) { - sectionVisible = false; - section -= 128; - } - - _gm->_currentRoom->setSectionVisible(section, sectionVisible); - - do { - if (sectionVisible) - renderImageSection(section); - else - renderImageSection(section + 128); - section = _currentImage->_section[section].next; - } while (section != 0); + _screen->renderImage(section); } bool SupernovaEngine::setCurrentImage(int filenumber) { - _currentImage = _resMan->getImage(filenumber); - _system->getPaletteManager()->setPalette(_currentImage->getPalette(), 16, 239); - paletteBrightness(); - - return true; + _screen->setCurrentImage(filenumber); } void SupernovaEngine::saveScreen(int x, int y, int width, int height) { - _screenBuffer.push(x, y, width, height); + _screen->saveScreen(x, y, width, height); } void SupernovaEngine::saveScreen(const GuiElement &guiElement) { - saveScreen(guiElement.left, guiElement.top, guiElement.width(), guiElement.height()); + _screen->saveScreen(guiElement); } void SupernovaEngine::restoreScreen() { - _screenBuffer.restore(); + _screen->restoreScreen(); } void SupernovaEngine::renderRoom(Room &room) { - if (room.getId() == INTRO) - return; - - if (setCurrentImage(room.getFileNumber())) { - for (int i = 0; i < _currentImage->_numSections; ++i) { - int section = i; - if (room.isSectionVisible(section)) { - do { - renderImageSection(section); - section = _currentImage->_section[section].next; - } while (section != 0); - } - } - } + _screen->renderRoom(room); } -int SupernovaEngine::textWidth(const uint16 key) { - char text[2]; - text[0] = key & 0xFF; - text[1] = 0; - return textWidth(text); +void SupernovaEngine::renderMessage(const char *text, MessagePosition position) { + _screen->renderMessage(text, position); } -int SupernovaEngine::textWidth(const char *text) { - int charWidth = 0; - while (*text != '\0') { - byte c = *text++; - if (c < 32) { - continue; - } else if (c == 225) { - c = 35; - } - - for (uint i = 0; i < 5; ++i) { - if (font[c - 32][i] == 0xff) { - break; - } - ++charWidth; - } - ++charWidth; - } - - return charWidth; +void SupernovaEngine::renderMessage(const Common::String &text, MessagePosition position) { + _screen->renderMessage(text, position); } -void SupernovaEngine::renderMessage(const char *text, MessagePosition position) { - Common::String t(text); - char *row[20]; - Common::String::iterator p = t.begin(); - uint numRows = 0; - int rowWidthMax = 0; - int x = 0; - int y = 0; - byte textColor = 0; - - while (*p != '\0') { - row[numRows] = p; - ++numRows; - while ((*p != '\0') && (*p != '|')) { - ++p; - } - if (*p == '|') { - *p = '\0'; - ++p; - } - } - for (uint i = 0; i < numRows; ++i) { - int rowWidth = textWidth(row[i]); - if (rowWidth > rowWidthMax) - rowWidthMax = rowWidth; - } - - switch (position) { - case kMessageNormal: - x = 160 - rowWidthMax / 2; - textColor = kColorWhite99; - break; - case kMessageTop: - x = 160 - rowWidthMax / 2; - textColor = kColorLightYellow; - break; - case kMessageCenter: - x = 160 - rowWidthMax / 2; - textColor = kColorLightRed; - break; - case kMessageLeft: - x = 3; - textColor = kColorLightYellow; - break; - case kMessageRight: - x = 317 - rowWidthMax; - textColor = kColorLightGreen; - break; - } - - if (position == kMessageNormal) { - y = 70 - ((numRows * 9) / 2); - } else if (position == kMessageTop) { - y = 5; - } else { - y = 142; - } - - int message_columns = x - 3; - int message_rows = y - 3; - int message_width = rowWidthMax + 6; - int message_height = numRows * 9 + 5; - saveScreen(message_columns, message_rows, message_width, message_height); - renderBox(message_columns, message_rows, message_width, message_height, kColorWhite35); - for (uint i = 0; i < numRows; ++i) { - renderText(row[i], x, y, textColor); - y += 9; - } - - _messageDisplayed = true; - _gm->_messageDuration = (Common::strnlen(text, 512) + 20) * _textSpeed / 10; +void SupernovaEngine::renderMessage(StringID stringId, MessagePosition position, Common::String var1, Common::String var2) { + _screen->renderMessage(stringId, position, var1, var2); } void SupernovaEngine::removeMessage() { - if (_messageDisplayed) { - restoreScreen(); - _messageDisplayed = false; - } + _screen->removeMessage(); } -void SupernovaEngine::renderText(const char *text, int x, int y, byte color) { - Graphics::Surface *screen = _system->lockScreen(); - byte *cursor = static_cast<byte *>(screen->getBasePtr(x, y)); - const byte *basePtr = cursor; - - byte c; - while ((c = *text++) != '\0') { - if (c < 32) { - continue; - } else if (c == 225) { - c = 128; - } +void SupernovaEngine::renderText(const uint16 character) { + _screen->renderText(character); +} - for (uint i = 0; i < 5; ++i) { - if (font[c - 32][i] == 0xff) { - break; - } +void SupernovaEngine::renderText(const char *text) { + _screen->renderText(text); +} - byte *ascentLine = cursor; - for (byte j = font[c - 32][i]; j != 0; j >>= 1) { - if (j & 1) { - *cursor = color; - } - cursor += kScreenWidth; - } - cursor = ++ascentLine; - } - ++cursor; - } - _system->unlockScreen(); +void SupernovaEngine::renderText(const Common::String &text) { + _screen->renderText(text); +} - uint numChars = cursor - basePtr; - uint absPosition = y * kScreenWidth + x + numChars; - _textCursorX = absPosition % kScreenWidth; - _textCursorY = absPosition / kScreenWidth; - _textColor = color; +void SupernovaEngine::renderText(StringID stringId) { + _screen->renderText(stringId); +} + +void SupernovaEngine::renderText(const GuiElement &guiElement) { + _screen->renderText(guiElement); } void SupernovaEngine::renderText(const uint16 character, int x, int y, byte color) { - char text[2]; - text[0] = character & 0xFF; - text[1] = 0; - renderText(text, x, y, color); + _screen->renderText(character, x, y, color); } -void SupernovaEngine::renderText(const char *text) { - renderText(text, _textCursorX, _textCursorY, _textColor); +void SupernovaEngine::renderText(const char *text, int x, int y, byte color) { + _screen->renderText(text, x, y, color); } -void SupernovaEngine::renderText(const uint16 character) { - char text[2]; - text[0] = character & 0xFF; - text[1] = 0; - renderText(text, _textCursorX, _textCursorY, _textColor); +void SupernovaEngine::renderText(const Common::String &text, int x, int y, byte color) { + _screen->renderText(text, x, y, color); } -void SupernovaEngine::renderText(const GuiElement &guiElement) { - renderText(guiElement.getText(), guiElement.getTextPos().x, - guiElement.getTextPos().y, guiElement.getTextColor()); + +void SupernovaEngine::renderText(StringID stringId, int x, int y, byte color) { + _screen->renderText(stringId, x, y, color); } void SupernovaEngine::renderBox(int x, int y, int width, int height, byte color) { - Graphics::Surface *screen = _system->lockScreen(); - screen->fillRect(Common::Rect(x, y, x + width, y + height), color); - _system->unlockScreen(); + _screen->renderBox(x, y, width, height, color); } void SupernovaEngine::renderBox(const GuiElement &guiElement) { - renderBox(guiElement.left, guiElement.top, guiElement.width(), - guiElement.height(), guiElement.getBackgroundColor()); + _screen->renderBox(guiElement); } void SupernovaEngine::paletteBrightness() { - byte palette[768]; - - _system->getPaletteManager()->grabPalette(palette, 0, 255); - for (uint i = 0; i < 48; ++i) { - palette[i] = (initVGAPalette[i] * _menuBrightness) >> 8; - } - for (uint i = 0; i < 717; ++i) { - const byte *imagePalette; - if (_currentImage && _currentImage->getPalette()) { - imagePalette = _currentImage->getPalette(); - } else { - imagePalette = palette + 48; - } - palette[i + 48] = (imagePalette[i] * _brightness) >> 8; - } - _system->getPaletteManager()->setPalette(palette, 0, 255); + _screen->paletteBrightness(); } void SupernovaEngine::paletteFadeOut() { - while (_menuBrightness > 10) { - _menuBrightness -= 10; - if (_brightness > _menuBrightness) - _brightness = _menuBrightness; - paletteBrightness(); - _system->updateScreen(); - _system->delayMillis(_delay); - } - _menuBrightness = 0; - _brightness = 0; - paletteBrightness(); - _system->updateScreen(); + _screen->paletteFadeOut(); } void SupernovaEngine::paletteFadeIn() { - while (_menuBrightness < 245) { - if (_brightness < _gm->_roomBrightness) - _brightness += 10; - _menuBrightness += 10; - paletteBrightness(); - _system->updateScreen(); - _system->delayMillis(_delay); - } - _menuBrightness = 255; - _brightness = _gm->_roomBrightness; - paletteBrightness(); - _system->updateScreen(); + _screen->paletteFadeIn(); } void SupernovaEngine::setColor63(byte value) { - byte color[3] = {value, value, value}; - _system->getPaletteManager()->setPalette(color, 63, 1); + _screen->setColor63(value); } void SupernovaEngine::setTextSpeed() { - const Common::String& textSpeedString = getGameString(kStringTextSpeed); - int stringWidth = textWidth(textSpeedString); - int textX = (320 - stringWidth) / 2; + const Common::String &textSpeedString = getGameString(kStringTextSpeed); + int stringWidth = Screen::textWidth(textSpeedString); + int textX = (kScreenWidth - stringWidth) / 2; int textY = 100; stringWidth += 4; - int boxX = stringWidth > 110 ? (320 - stringWidth) / 2 : 105; + int boxX = stringWidth > 110 ? (kScreenWidth - stringWidth) / 2 : 105; int boxY = 97; int boxWidth = stringWidth > 110 ? stringWidth : 110; int boxHeight = 27; @@ -743,10 +517,11 @@ bool SupernovaEngine::loadGame(int slot) { _gm->deserialize(savefile, saveVersion); if (saveVersion >= 5) { - _menuBrightness = savefile->readByte(); - _brightness = savefile->readByte(); + _screen->setGuiBrightness(savefile->readByte()); + _screen->setViewportBrightness(savefile->readByte()); } else { - _menuBrightness = _brightness = 255; + _screen->setGuiBrightness(255); + _screen->setViewportBrightness(255); } delete savefile; @@ -779,8 +554,8 @@ bool SupernovaEngine::saveGame(int slot, const Common::String &description) { Graphics::saveThumbnail(*savefile); _gm->serialize(savefile); - savefile->writeByte(_menuBrightness); - savefile->writeByte(_brightness); + savefile->writeByte(_screen->getGuiBrightness()); + savefile->writeByte(_screen->getViewportBrightness()); savefile->finalize(); delete savefile; @@ -795,59 +570,5 @@ void SupernovaEngine::errorTempSave(bool saving) { error("Unrecoverable error"); } -ScreenBufferStack::ScreenBufferStack() - : _last(_buffer) { -} - -void ScreenBufferStack::push(int x, int y, int width, int height) { - if (_last == ARRAYEND(_buffer)) - return; - - Graphics::Surface* screenSurface = g_system->lockScreen(); - - if (x < 0) { - width += x; - x = 0; - } - if (x + width > screenSurface->w) - width = screenSurface->w - x; - - if (y < 0) { - height += y; - y = 0; - } - if (y + height > screenSurface->h) - height = screenSurface->h - y; - - _last->_pixels = new byte[width * height]; - byte *pixels = _last->_pixels; - const byte *screen = static_cast<const byte *>(screenSurface->getBasePtr(x, y)); - for (int i = 0; i < height; ++i) { - Common::copy(screen, screen + width, pixels); - screen += screenSurface->pitch; - pixels += width; - } - g_system->unlockScreen(); - - _last->_x = x; - _last->_y = y; - _last->_width = width; - _last->_height = height; - - ++_last; -} - -void ScreenBufferStack::restore() { - if (_last == _buffer) - return; - - --_last; - g_system->lockScreen()->copyRectToSurface( - _last->_pixels, _last->_width, _last->_x, _last->_y, - _last->_width, _last->_height); - g_system->unlockScreen(); - - delete[] _last->_pixels; -} } diff --git a/engines/supernova/supernova.h b/engines/supernova/supernova.h index f23149b8d1..b33a4893dc 100644 --- a/engines/supernova/supernova.h +++ b/engines/supernova/supernova.h @@ -46,40 +46,12 @@ namespace Supernova { #define SUPERNOVA_DAT "supernova.dat" #define SUPERNOVA_DAT_VERSION 1 - -struct ScreenBuffer { - ScreenBuffer() - : _x(0) - , _y(0) - , _width(0) - , _height(0) - , _pixels(nullptr) - {} - - byte *_pixels; - int _x; - int _y; - int _width; - int _height; -}; -class ScreenBufferStack { -public: - ScreenBufferStack(); - - void push(int x, int y, int width, int height); - void restore(); - -private: - ScreenBuffer _buffer[8]; - ScreenBuffer *_last; -}; - - class GuiElement; class ResourceManager; class Sound; class console; class GameManager; +class Screen; class SupernovaEngine : public Engine { public: @@ -87,116 +59,67 @@ public: ~SupernovaEngine(); virtual Common::Error run(); + virtual Common::Error loadGameState(int slot); + virtual bool canLoadGameStateCurrently(); + virtual Common::Error saveGameState(int slot, const Common::String &desc); + virtual bool canSaveGameStateCurrently(); + virtual bool hasFeature(EngineFeature f) const; + virtual void pauseEngineIntern(bool pause); Common::RandomSource _rnd; GameManager *_gm; Console *_console; Sound *_sound; ResourceManager *_resMan; - ScreenBufferStack _screenBuffer; - MSNImage *_currentImage; - int _screenWidth; - int _screenHeight; + Screen *_screen; bool _allowLoadGame; bool _allowSaveGame; Common::StringArray _gameStrings; Common::String _nullString; - byte _menuBrightness; - byte _brightness; uint _delay; - bool _messageDisplayed; int _textSpeed; - int _textCursorX; - int _textCursorY; - int _textColor; - int textWidth(const char *text); - int textWidth(const uint16 key); Common::Error loadGameStrings(); void init(); + bool loadGame(int slot); + bool saveGame(int slot, const Common::String &description); + bool quitGameDialog(); + void errorTempSave(bool saving); + void setTextSpeed(); + const Common::String &getGameString(int idx) const; + void setGameString(int idx, const Common::String &string); + + // forwarding calls + void playSound(AudioIndex sample); + void playSound(MusicIndex index); void paletteFadeIn(); void paletteFadeOut(); void paletteBrightness(); - void playSound(AudioIndex sample); - void playSound(MusicIndex index); - void renderImageSection(int section); void renderImage(int section); + void renderImageSection(int section); bool setCurrentImage(int filenumber); void saveScreen(int x, int y, int width, int height); void saveScreen(const GuiElement &guiElement); void restoreScreen(); void renderRoom(Room &room); void renderMessage(const char *text, MessagePosition position = kMessageNormal); + void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal); + void renderMessage(StringID stringId, MessagePosition position = kMessageNormal, + Common::String var1 = "", Common::String var2 = ""); void removeMessage(); - void renderText(const char *text, int x, int y, byte color); - void renderText(const uint16 character, int x, int y, byte color); - void renderText(const char *text); void renderText(const uint16 character); + void renderText(const char *text); + void renderText(const Common::String &text); + void renderText(StringID stringId); + void renderText(const uint16 character, int x, int y, byte color); + void renderText(const char *text, int x, int y, byte color); + void renderText(const Common::String &text, int x, int y, byte color); + void renderText(StringID stringId, int x, int y, byte color); void renderText(const GuiElement &guiElement); void renderBox(int x, int y, int width, int height, byte color); void renderBox(const GuiElement &guiElement); void setColor63(byte value); - bool loadGame(int slot); - bool saveGame(int slot, const Common::String &description); - bool quitGameDialog(); - void errorTempSave(bool saving); - void setTextSpeed(); - - const Common::String &getGameString(int idx) const { - if (idx < 0 || idx >= (int)_gameStrings.size()) - return _nullString; - return _gameStrings[idx]; - } - - void setGameString(int idx, const Common::String &string) { - if (idx < 0) - return; - while ((int)_gameStrings.size() <= idx) - _gameStrings.push_back(Common::String()); - _gameStrings[idx] = string; - } - - int textWidth(const Common::String &text) { - if (text.empty()) - return 0; - return textWidth(text.c_str()); - } - void renderMessage(StringID stringId, MessagePosition position = kMessageNormal, Common::String var1 = "", Common::String var2 = "") { - Common::String text = getGameString(stringId); - if (!var1.empty()) { - if (!var2.empty()) - text = Common::String::format(text.c_str(), var1.c_str(), var2.c_str()); - else - text = Common::String::format(text.c_str(), var1.c_str()); - } - renderMessage(text, position); - } - void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal) { - if (!text.empty()) - renderMessage(text.c_str(), position); - } - void renderText(StringID stringId, int x, int y, byte color) { - renderText(getGameString(stringId), x, y, color); - } - void renderText(const Common::String &text, int x, int y, byte color) { - if (!text.empty()) - renderText(text.c_str(), x, y, color); - } - void renderText(StringID stringId) { - renderText(getGameString(stringId)); - } - void renderText(const Common::String &text) { - if (!text.empty()) - renderText(text.c_str()); - } - - virtual Common::Error loadGameState(int slot); - virtual bool canLoadGameStateCurrently(); - virtual Common::Error saveGameState(int slot, const Common::String &desc); - virtual bool canSaveGameStateCurrently(); - virtual bool hasFeature(EngineFeature f) const; - virtual void pauseEngineIntern(bool pause); }; } |