scummvm/engines/twine/slideshow.cpp
2021-12-26 18:48:43 +01:00

248 lines
6.3 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "twine/slideshow.h"
#include "common/file.h"
#include "common/tokenizer.h"
#include "image/pcx.h"
#include "twine/movies.h"
#include "twine/renderer/screens.h"
#include "twine/resources/resources.h"
#include "twine/text.h"
#include "twine/twine.h"
namespace TwinE {
class Slideshow {
private:
TwinEEngine *_engine;
int _textY = 0;
bool _aborted = false;
int _lineHeight = 40;
uint32 _pal[NUMOFCOLORS]{};
void setPalette(const uint8 *in, int colors) {
uint8 *paletteOut = (uint8 *)_pal;
for (int i = 0; i < colors; i++) {
paletteOut[0] = in[0];
paletteOut[1] = in[1];
paletteOut[2] = in[2];
paletteOut[3] = 0xFF;
paletteOut += 4;
in += 3;
}
_engine->setPalette(_pal);
}
bool loadPCX(const Common::String &pcx, bool onlyPalette = false) {
Image::PCXDecoder decoder;
Common::File file;
if (!file.open(pcx)) {
return false;
}
if (!decoder.loadStream(file)) {
return false;
}
const Graphics::Surface *src = decoder.getSurface();
if (src == nullptr) {
return false;
}
Graphics::ManagedSurface &target = _engine->_frontVideoBuffer;
target.blitFrom(src);
if (decoder.hasPalette()) {
setPalette(decoder.getPalette(), decoder.getPaletteColorCount());
}
return true;
}
bool loadFont() {
Common::File font;
if (!font.open("LBA.FNT")) {
return false;
}
_engine->_resources->_fontBufSize = (int)font.size();
_engine->_resources->_fontPtr = (uint8 *)malloc(_engine->_resources->_fontBufSize);
font.read(_engine->_resources->_fontPtr, _engine->_resources->_fontBufSize);
_engine->_text->setFontParameters(4, 8);
return true;
}
void scriptCls() {
_textY = 0;
_engine->_screens->clearScreen();
}
void scriptPause(const Common::String &params) {
_engine->_frontVideoBuffer.update();
const int seconds = atoi(params.c_str());
if (_engine->delaySkip(1000 * seconds)) {
_aborted = true;
}
}
void scriptColor(const Common::String &params) {
const int color = atoi(params.c_str());
_engine->_text->setFontColor(color);
}
void scriptText(const Common::String &params) {
if (!params.empty()) {
_pal[255] = _pal[15] = 0xffffffff;
_engine->setPalette(_pal);
const int32 length = _engine->_text->getTextSize(params.c_str());
const int x = 0;
_engine->_text->drawText(x, _textY, params.c_str());
_engine->_frontVideoBuffer.addDirtyRect(Common::Rect(x, _textY, x + length, _textY + _lineHeight));
}
_textY += _lineHeight;
}
void scriptRText(const Common::String &params) {
if (!params.empty()) {
_pal[255] = _pal[15] = 0xffffffff;
_engine->setPalette(_pal);
const int32 length = _engine->_text->getTextSize(params.c_str());
const int x = _engine->width() - length;
_engine->_text->drawText(x, _textY, params.c_str());
_engine->_frontVideoBuffer.update();
_engine->_frontVideoBuffer.addDirtyRect(Common::Rect(x, _textY, x + length, _textY + _lineHeight));
}
_textY += _lineHeight;
}
void scriptTitle(const Common::String &params) {
if (!params.empty()) {
_pal[255] = _pal[15] = 0xffffffff;
_engine->setPalette(_pal);
const int32 length = _engine->_text->getTextSize(params.c_str());
const int x = _engine->width() / 2 - length / 2;
_engine->_text->drawText(x, _textY, params.c_str());
_engine->_frontVideoBuffer.addDirtyRect(Common::Rect(x, _textY, x + length, _textY + _lineHeight));
}
_textY += _lineHeight;
}
void scriptFadeIn() {
_engine->_screens->fadeIn(_pal);
}
void scriptFadeOut() {
_engine->_screens->fadeOut(_pal);
}
void scriptPCX(const Common::String &params) {
loadPCX(params + ".PCX");
}
void scriptShow() {
// TODO: _engine->setPalette(_pal);
// or updateScreen?
}
void scriptFLA(const Common::String &params) {
if (!_engine->_movie->playMovie(params.c_str())) {
_aborted = true;
}
}
bool playScript() {
Common::File scriptFile;
if (!scriptFile.open("LBA_SHOW.SHO")) {
return false;
}
while (!scriptFile.eos() && !scriptFile.err()) {
if (_aborted) {
break;
}
const Common::String &line = scriptFile.readLine();
if (line.empty()) {
continue;
}
Common::String cmd;
Common::String params;
const size_t index = line.findFirstOf(' ');
if (index == Common::String::npos) {
cmd = line;
} else {
cmd = line.substr(0, index);
params = line.substr(index + 1);
}
debug("cmd: '%s %s'", cmd.c_str(), params.c_str());
if (cmd == "cls") {
scriptCls();
} else if (cmd == "text") {
scriptText(params);
} else if (cmd == "rtext") {
scriptRText(params);
} else if (cmd == "title") {
scriptTitle(params);
} else if (cmd == "color") {
scriptColor(params);
} else if (cmd == "pause") {
scriptPause(params);
} else if (cmd == "pcx") {
scriptPCX(params);
} else if (cmd == "fla") {
scriptFLA(params);
} else if (cmd == "fade_in") {
scriptFadeIn();
} else if (cmd == "fade_out") {
scriptFadeOut();
} else if (cmd == "show") {
scriptShow();
} else if (cmd == "restart") {
return true;
} else {
warning("Unknown command %s (%s)", cmd.c_str(), params.c_str());
}
}
return false;
}
public:
Slideshow(TwinEEngine *engine) : _engine(engine) {
}
~Slideshow() {
free(_engine->_resources->_fontPtr);
_engine->_resources->_fontPtr = nullptr;
}
void play() {
loadFont();
loadPCX("ADELINE.PCX", true);
while (playScript()) {
}
}
};
void playSlideShow(TwinEEngine *engine) {
Slideshow slideshow(engine);
slideshow.play();
}
} // namespace TwinE