aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorJoseph-Eugene Winzer2018-03-25 00:07:37 +0100
committerThierry Crozat2018-04-15 18:28:29 +0100
commit2ead17f09fb9c3c4af46cd86736fee654e6ad072 (patch)
tree041063063fe40b2d14e22078203146d59d85bfa6 /engines
parentac438cc918150a7549eee9cc45f60ca04a13f7da (diff)
downloadscummvm-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')
-rw-r--r--engines/supernova/rooms.cpp130
-rw-r--r--engines/supernova/rooms.h5
-rw-r--r--engines/supernova/screen.cpp578
-rw-r--r--engines/supernova/screen.h103
-rw-r--r--engines/supernova/state.cpp57
-rw-r--r--engines/supernova/state.h1
-rw-r--r--engines/supernova/supernova.cpp429
-rw-r--r--engines/supernova/supernova.h137
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);
};
}