aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/support
diff options
context:
space:
mode:
authorEugene Sandulenko2016-08-01 00:27:28 +0300
committerGitHub2016-08-01 00:27:28 +0300
commit9d3a2c1c7f9365f65908f583e62047830f60693d (patch)
treed7ba49593a1e3d79f17b350e700b1fbcf71f5b22 /engines/titanic/support
parent567054d8298a013f93dd9e0e332e2a08402b10a6 (diff)
parent19f8a0965be832a71a101054748cf000adf16add (diff)
downloadscummvm-rg350-9d3a2c1c7f9365f65908f583e62047830f60693d.tar.gz
scummvm-rg350-9d3a2c1c7f9365f65908f583e62047830f60693d.tar.bz2
scummvm-rg350-9d3a2c1c7f9365f65908f583e62047830f60693d.zip
Merge pull request #786 from dreammaster/titanic
TITANIC: Starship Titanic engine
Diffstat (limited to 'engines/titanic/support')
-rw-r--r--engines/titanic/support/avi_surface.cpp361
-rw-r--r--engines/titanic/support/avi_surface.h183
-rw-r--r--engines/titanic/support/credit_text.cpp153
-rw-r--r--engines/titanic/support/credit_text.h106
-rw-r--r--engines/titanic/support/direct_draw.cpp109
-rw-r--r--engines/titanic/support/direct_draw.h105
-rw-r--r--engines/titanic/support/direct_draw_surface.cpp100
-rw-r--r--engines/titanic/support/direct_draw_surface.h126
-rw-r--r--engines/titanic/support/exe_resources.cpp37
-rw-r--r--engines/titanic/support/exe_resources.h51
-rw-r--r--engines/titanic/support/files_manager.cpp132
-rw-r--r--engines/titanic/support/files_manager.h109
-rw-r--r--engines/titanic/support/font.cpp279
-rw-r--r--engines/titanic/support/font.h123
-rw-r--r--engines/titanic/support/image.cpp56
-rw-r--r--engines/titanic/support/image.h43
-rw-r--r--engines/titanic/support/image_decoders.cpp81
-rw-r--r--engines/titanic/support/image_decoders.h52
-rw-r--r--engines/titanic/support/mouse_cursor.cpp135
-rw-r--r--engines/titanic/support/mouse_cursor.h114
-rw-r--r--engines/titanic/support/movie.cpp218
-rw-r--r--engines/titanic/support/movie.h237
-rw-r--r--engines/titanic/support/movie_clip.cpp100
-rw-r--r--engines/titanic/support/movie_clip.h92
-rw-r--r--engines/titanic/support/movie_event.cpp64
-rw-r--r--engines/titanic/support/movie_event.h66
-rw-r--r--engines/titanic/support/movie_manager.cpp35
-rw-r--r--engines/titanic/support/movie_manager.h65
-rw-r--r--engines/titanic/support/movie_range_info.cpp112
-rw-r--r--engines/titanic/support/movie_range_info.h81
-rw-r--r--engines/titanic/support/proximity.cpp37
-rw-r--r--engines/titanic/support/proximity.h69
-rw-r--r--engines/titanic/support/rect.cpp44
-rw-r--r--engines/titanic/support/rect.h61
-rw-r--r--engines/titanic/support/screen_manager.cpp326
-rw-r--r--engines/titanic/support/screen_manager.h395
-rw-r--r--engines/titanic/support/simple_file.cpp512
-rw-r--r--engines/titanic/support/simple_file.h321
-rw-r--r--engines/titanic/support/string.cpp125
-rw-r--r--engines/titanic/support/string.h114
-rw-r--r--engines/titanic/support/text_cursor.cpp88
-rw-r--r--engines/titanic/support/text_cursor.h121
-rw-r--r--engines/titanic/support/time_event_info.cpp206
-rw-r--r--engines/titanic/support/time_event_info.h138
-rw-r--r--engines/titanic/support/video_surface.cpp583
-rw-r--r--engines/titanic/support/video_surface.h537
46 files changed, 7202 insertions, 0 deletions
diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp
new file mode 100644
index 0000000000..6507c8bbd4
--- /dev/null
+++ b/engines/titanic/support/avi_surface.cpp
@@ -0,0 +1,361 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/avi_surface.h"
+#include "titanic/support/screen_manager.h"
+#include "titanic/support/video_surface.h"
+#include "common/system.h"
+#include "graphics/pixelformat.h"
+#include "video/avi_decoder.h"
+
+namespace Titanic {
+
+Video::AVIDecoder::AVIVideoTrack &AVIDecoder::getVideoTrack() {
+ for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++)
+ if ((*it)->getTrackType() == Track::kTrackTypeVideo)
+ return *static_cast<AVIVideoTrack *>(*it);
+
+ error("Could not find video track");
+}
+
+/**
+ * Track filter for AVIDecoder that filters out any secondary video track
+ */
+static bool primaryTrackSelect(bool isVideo, int trackCounter) {
+ return !isVideo || trackCounter == 0;
+}
+
+/**
+ * Track filter for AVIDecoder that only accepts the secondary video track
+ * for a video, if present
+ */
+static bool secondaryTrackSelect(bool isVideo, int trackCounter) {
+ return isVideo && trackCounter > 0;
+}
+
+AVISurface::AVISurface(const CResourceKey &key) {
+ _videoSurface = nullptr;
+ _streamCount = 0;
+ _movieFrameSurface[0] = _movieFrameSurface[1] = nullptr;
+
+ // Reset current frame. We need to keep track of frames separately from the decoders,
+ // since it needs to be able to go beyond the frame count or to negative to allow
+ // correct detection of when range playbacks have finished
+ _currentFrame = -1;
+ _isReversed = false;
+
+ // Create a decoder for the audio (if any) and primary video track
+ _decoders[0] = new AVIDecoder(Audio::Mixer::kPlainSoundType, primaryTrackSelect);
+ if (!_decoders[0]->loadFile(key.getString()))
+ error("Could not open video - %s", key.getString().c_str());
+
+ _streamCount = 1;
+
+ // Create a decoder for any secondary video track
+ AVIDecoder *decoder2 = new AVIDecoder(Audio::Mixer::kPlainSoundType, secondaryTrackSelect);
+ if (decoder2->loadFile(key.getString())) {
+ _decoders[1] = decoder2;
+ ++_streamCount;
+ } else {
+ delete decoder2;
+ _decoders[1] = nullptr;
+ }
+}
+
+AVISurface::~AVISurface() {
+ if (_videoSurface)
+ _videoSurface->_transBlitFlag = false;
+ delete _movieFrameSurface[0];
+ delete _movieFrameSurface[1];
+ delete _decoders[0];
+ delete _decoders[1];
+}
+
+bool AVISurface::play(uint flags, CGameObject *obj) {
+ if (flags & MOVIE_REVERSE)
+ return play(_decoders[0]->getFrameCount() - 1, 0, flags, obj);
+ else
+ return play(0, _decoders[0]->getFrameCount() - 1, flags, obj);
+}
+
+bool AVISurface::play(int startFrame, int endFrame, uint flags, CGameObject *obj) {
+ if (flags & MOVIE_STOP_PREVIOUS)
+ stop();
+
+ return play(startFrame, endFrame, -1, flags, obj);
+}
+
+bool AVISurface::play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj) {
+ CMovieRangeInfo *info = new CMovieRangeInfo();
+ info->_startFrame = startFrame;
+ info->_endFrame = endFrame;
+ info->_isReversed = endFrame < startFrame;
+ info->_initialFrame = 0;
+ info->_isRepeat = flags & MOVIE_REPEAT;
+
+ if (obj) {
+ CMovieEvent *me = new CMovieEvent();
+ me->_type = MET_MOVIE_END;
+ me->_startFrame = startFrame;
+ me->_endFrame = endFrame;
+ me->_initialFrame = 0;
+ me->_gameObject = obj;
+
+ info->addEvent(me);
+ }
+
+ _movieRangeInfo.push_back(info);
+
+ if (_movieRangeInfo.size() == 1) {
+ // First play call, so start the movie playing
+ setReversed(info->_isReversed);
+ return startAtFrame(initialFrame);
+ } else {
+ return true;
+ }
+}
+
+void AVISurface::stop() {
+ _decoders[0]->stop();
+ if (_decoders[1])
+ _decoders[1]->stop();
+
+ _movieRangeInfo.destroyContents();
+}
+
+bool AVISurface::startAtFrame(int frameNumber) {
+ if (isPlaying())
+ // If it's already playing, then don't allow it
+ return false;
+
+ if (frameNumber == -1)
+ // Default to starting frame of first movie range
+ frameNumber = _movieRangeInfo.front()->_startFrame;
+
+ // Get the initial frame
+ seekToFrame(frameNumber);
+ renderFrame();
+
+ // Start the playback
+ _decoders[0]->start();
+ if (_decoders[1])
+ _decoders[1]->start();
+
+ return true;
+}
+
+void AVISurface::seekToFrame(uint frameNumber) {
+ if ((int)frameNumber != getFrame()) {
+ _decoders[0]->seekToFrame(frameNumber);
+ if (_decoders[1])
+ _decoders[1]->seekToFrame(frameNumber);
+
+ _currentFrame = (int)frameNumber;
+ }
+
+ renderFrame();
+}
+
+void AVISurface::setReversed(bool isReversed) {
+ _decoders[0]->setReverse(isReversed);
+ if (_decoders[1])
+ _decoders[1]->setReverse(isReversed);
+
+ _isReversed = isReversed;
+}
+
+bool AVISurface::handleEvents(CMovieEventList &events) {
+ if (!isPlaying())
+ return true;
+
+ CMovieRangeInfo *info = _movieRangeInfo.front();
+ _currentFrame += _isReversed ? -1 : 1;
+
+ int newFrame = _currentFrame;
+ if ((info->_isReversed && newFrame <= info->_endFrame) ||
+ (!info->_isReversed && newFrame >= info->_endFrame)) {
+ if (info->_isRepeat) {
+ newFrame = info->_startFrame;
+ } else {
+ info->getMovieEnd(events);
+ _movieRangeInfo.remove(info);
+ delete info;
+
+ if (_movieRangeInfo.empty()) {
+ // NO more ranges, so stop playback
+ stop();
+ } else {
+ // Not empty, so move onto new first one
+ info = _movieRangeInfo.front();
+ newFrame = info->_startFrame;
+ }
+ }
+ }
+
+ if (isPlaying()) {
+ if (newFrame != getFrame()) {
+ // The frame has been changed, so move to new position
+ setReversed(info->_isReversed);
+ seekToFrame(newFrame);
+ }
+
+ // Get any events for the given position
+ info->getMovieFrame(events, newFrame);
+ return renderFrame();
+ } else {
+ return false;
+ }
+}
+
+void AVISurface::setVideoSurface(CVideoSurface *surface) {
+ _videoSurface = surface;
+
+ // Handling for secondary video stream
+ if (_decoders[1]) {
+ const Common::String &streamName = _decoders[1]->getVideoTrack().getName();
+
+ if (streamName == "mask0") {
+ _videoSurface->_transparencyMode = TRANS_MASK0;
+ } else if (streamName == "mask255") {
+ _videoSurface->_transparencyMode = TRANS_MASK255;
+ } else if (streamName == "alpha0") {
+ _videoSurface->_transparencyMode = TRANS_ALPHA0;
+ } else if (streamName == "alpha255") {
+ _videoSurface->_transparencyMode = TRANS_ALPHA255;
+ }
+ }
+
+ setupDecompressor();
+}
+
+void AVISurface::setupDecompressor() {
+ for (int idx = 0; idx < 2; ++idx) {
+ if (!_decoders[idx])
+ continue;
+ AVIDecoder &decoder = *_decoders[idx];
+
+ // Setup frame surface
+ _movieFrameSurface[idx] = new Graphics::ManagedSurface(decoder.getWidth(), decoder.getHeight(),
+ g_system->getScreenFormat());
+
+ // TODO: See whether this simplified form of original works
+ if (idx == 2)
+ _videoSurface->_transBlitFlag = true;
+ }
+}
+
+uint AVISurface::getWidth() const {
+ return _decoders[0]->getWidth();
+}
+
+uint AVISurface::getHeight() const {
+ return _decoders[0]->getHeight();
+}
+
+void AVISurface::setFrame(int frameNumber) {
+ // If playback was in process, stop it
+ if (isPlaying())
+ stop();
+
+ // Ensure the frame number is valid
+ if (frameNumber >= (int)_decoders[0]->getFrameCount())
+ frameNumber = _decoders[0]->getFrameCount() - 1;
+
+ seekToFrame(frameNumber);
+ renderFrame();
+}
+
+bool AVISurface::isNextFrame() const {
+ return _decoders[0]->getTimeToNextFrame() == 0;
+}
+
+bool AVISurface::renderFrame() {
+ // Check there's a frame ready for display
+ if (!_decoders[0]->needsUpdate())
+ return false;
+
+ // Decode each decoder's video stream into the appropriate surface
+ for (int idx = 0; idx < _streamCount; ++idx) {
+ const Graphics::Surface *frame = _decoders[idx]->decodeNextFrame();
+
+ if (_movieFrameSurface[idx]->format == frame->format) {
+ _movieFrameSurface[idx]->blitFrom(*frame);
+ } else {
+ // Format mis-match, so we need to convert the frame
+ Graphics::Surface *s = frame->convertTo(_movieFrameSurface[idx]->format,
+ _decoders[idx]->getPalette());
+ _movieFrameSurface[idx]->blitFrom(*s);
+ s->free();
+ delete s;
+ }
+ }
+
+ // Blit the primary video frame onto the main overall surface
+ _videoSurface->lock();
+ _videoSurface->getRawSurface()->blitFrom(*_movieFrameSurface[0]);
+ _videoSurface->unlock();
+
+ return false;
+}
+
+bool AVISurface::addEvent(int frameNumber, CGameObject *obj) {
+ if (!_movieRangeInfo.empty()) {
+ CMovieRangeInfo *tail = _movieRangeInfo.back();
+ if (frameNumber == -1)
+ frameNumber = tail->_startFrame;
+
+ CMovieEvent *me = new CMovieEvent();
+ me->_type = MET_FRAME;
+ me->_startFrame = 0;
+ me->_endFrame = 0;
+ me->_initialFrame = frameNumber;
+ me->_gameObject = obj;
+ tail->addEvent(me);
+
+ return _movieRangeInfo.size() == 1 && frameNumber == getFrame();
+ }
+
+ return false;
+}
+
+void AVISurface::setFrameRate(double rate) {
+ _decoders[0]->setRate(Common::Rational(rate));
+ if (_decoders[1])
+ _decoders[1]->setRate(Common::Rational(rate));
+}
+
+Graphics::ManagedSurface *AVISurface::getSecondarySurface() {
+ return _streamCount <= 1 ? nullptr : _movieFrameSurface[1];
+}
+
+Graphics::ManagedSurface *AVISurface::duplicateSecondaryFrame() const {
+ if (_streamCount <= 1) {
+ return nullptr;
+ } else {
+ Graphics::ManagedSurface *dest = new Graphics::ManagedSurface(_movieFrameSurface[1]->w,
+ _movieFrameSurface[1]->h, _movieFrameSurface[1]->format);
+ dest->blitFrom(*_movieFrameSurface[1]);
+ return dest;
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h
new file mode 100644
index 0000000000..d21182bca9
--- /dev/null
+++ b/engines/titanic/support/avi_surface.h
@@ -0,0 +1,183 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_AVI_SURFACE_H
+#define TITANIC_AVI_SURFACE_H
+
+#include "video/avi_decoder.h"
+#include "graphics/managed_surface.h"
+#include "titanic/core/resource_key.h"
+#include "titanic/support/movie_range_info.h"
+
+namespace Titanic {
+
+class CSoundManager;
+class CVideoSurface;
+
+enum MovieFlag {
+ MOVIE_REPEAT = 1, MOVIE_STOP_PREVIOUS = 2, MOVIE_NOTIFY_OBJECT = 4,
+ MOVIE_REVERSE = 8, MOVIE_GAMESTATE = 0x10
+};
+
+class AVIDecoder : public Video::AVIDecoder {
+public:
+ AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType, SelectTrackFn trackFn = nullptr) :
+ Video::AVIDecoder(soundType, trackFn) {}
+ AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType,
+ SelectTrackFn trackFn = nullptr) : Video::AVIDecoder(frameRateOverride, soundType, trackFn) {}
+
+ Video::AVIDecoder::AVIVideoTrack &getVideoTrack();
+};
+
+class AVISurface {
+private:
+ AVIDecoder *_decoders[2];
+ CVideoSurface *_videoSurface;
+ CMovieRangeInfoList _movieRangeInfo;
+ int _streamCount;
+ Graphics::ManagedSurface *_movieFrameSurface[2];
+ bool _isReversed;
+ int _currentFrame;
+private:
+ /**
+ * Render a frame to the video surface
+ */
+ bool renderFrame();
+
+ /**
+ * Sets up for video decompression
+ */
+ void setupDecompressor();
+protected:
+ /**
+ * Start playback at the specified frame
+ */
+ bool startAtFrame(int frameNumber);
+
+ /**
+ * Sets whether the movie is playing in reverse
+ */
+ void setReversed(bool isReversed);
+
+ /**
+ * Seeks to a given frame number in the video
+ */
+ virtual void seekToFrame(uint frameNumber);
+public:
+ CSoundManager *_soundManager;
+ bool _hasAudio;
+ double _frameRate;
+public:
+ AVISurface(const CResourceKey &key);
+ virtual ~AVISurface();
+
+ /**
+ * Start playing the loaded AVI video
+ */
+ virtual bool play(uint flags, CGameObject *obj);
+
+ /**
+ * Start playing the loaded AVI video
+ */
+ virtual bool play(int startFrame, int endFrame, uint flags, CGameObject *obj);
+
+ /**
+ * Start playing the loaded AVI video
+ */
+ virtual bool play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj);
+
+ /**
+ * Stop the currently playing video
+ */
+ virtual void stop();
+
+ /**
+ * Return true if a video is currently playing
+ */
+ virtual bool isPlaying() const { return _decoders[0]->isPlaying(); }
+
+ /**
+ * Handle any movie events relevent for the frame
+ */
+ virtual bool handleEvents(CMovieEventList &events);
+
+ /**
+ * Set the video surface the AVI Surface will render on
+ */
+ void setVideoSurface(CVideoSurface *surface);
+
+ /**
+ * Get the width of the video
+ */
+ uint getWidth() const;
+
+ /**
+ * Get the height of the video
+ */
+ uint getHeight() const;
+
+ /**
+ * Set the current frame
+ */
+ void setFrame(int frameNumber);
+
+ /**
+ * Gets the current frame
+ */
+ int getFrame() const { return _currentFrame; }
+
+ /**
+ * Add a movie event
+ */
+ bool addEvent(int frameNumber, CGameObject *obj);
+
+ /**
+ * Set the frame rate
+ */
+ void setFrameRate(double rate);
+
+ /**
+ * Returns the surface for the secondary video track frame, if present
+ */
+ Graphics::ManagedSurface *getSecondarySurface();
+
+ /**
+ * Get a reference to the movie range info list
+ */
+ const CMovieRangeInfoList *getMovieRangeInfo() const {
+ return &_movieRangeInfo;
+ }
+
+ /**
+ * Duplicates the secondary frame, if the movie has a second video track
+ */
+ Graphics::ManagedSurface *duplicateSecondaryFrame() const;
+
+ /**
+ * Returns true if it's time for the next
+ */
+ bool isNextFrame() const;
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_AVI_SURFACE_H */
diff --git a/engines/titanic/support/credit_text.cpp b/engines/titanic/support/credit_text.cpp
new file mode 100644
index 0000000000..0e9715aaa6
--- /dev/null
+++ b/engines/titanic/support/credit_text.cpp
@@ -0,0 +1,153 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/credit_text.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+CCreditText::CCreditText() : _screenManagerP(nullptr), _field14(0),
+ _ticks(0), _fontHeight(1), _objectP(nullptr), _totalHeight(0),
+ _field40(0), _field44(0), _field48(0), _field4C(0), _field50(0),
+ _field54(0), _field58(0), _field5C(0) {
+}
+
+void CCreditText::clear() {
+ _groups.destroyContents();
+ _objectP = nullptr;
+}
+
+void CCreditText::load(CGameObject *obj, CScreenManager *screenManager,
+ const Rect &rect, int v) {
+ _objectP = obj;
+ _screenManagerP = screenManager;
+ _field14 = v;
+
+ setup();
+
+ _ticks = g_vm->_events->getTicksCount();
+ _field40 = 0;
+ _field44 = 0xFF;
+ _field48 = 0xFF;
+ _field4C = 0xFF;
+ _field50 = 0;
+ _field54 = 0;
+ _field58 = 0;
+ _field5C = 0;
+}
+
+void CCreditText::setup() {
+ Common::SeekableReadStream *stream = g_vm->_filesManager->getResource(
+ CString::format("TEXT/155"));
+ int oldFontNumber = _screenManagerP->setFontNumber(3);
+ _fontHeight = _screenManagerP->getFontHeight();
+
+ while (stream->pos() < stream->size()) {
+ // Read in the line
+ CString srcLine = readLine(stream);
+
+ // Create a new group and line within it
+ CCreditLineGroup *group = new CCreditLineGroup();
+ CCreditLine *line = new CCreditLine(srcLine,
+ _screenManagerP->stringWidth(srcLine));
+ group->_lines.push_back(line);
+
+ // Loop to add more lines to the group
+ bool hasDots = false;
+ while (stream->pos() < stream->size()) {
+ srcLine = readLine(stream);
+ if (srcLine.empty())
+ break;
+
+ line = new CCreditLine(srcLine,
+ _screenManagerP->stringWidth(srcLine));
+ group->_lines.push_back(line);
+
+ if (srcLine.contains("...."))
+ hasDots = true;
+ }
+
+ _groups.push_back(group);
+ }
+
+ _groupIt = _groups.begin();
+ _lineIt = (*_groupIt)->_lines.begin();
+ _totalHeight = _objectP->getBounds().height() + _fontHeight * 2;
+}
+
+CString CCreditText::readLine(Common::SeekableReadStream *stream) {
+ CString line;
+ char c = stream->readByte();
+
+ while (c != '\r' && c != '\n' && c != '\0') {
+ line += c;
+
+ if (stream->pos() == stream->size())
+ break;
+ c = stream->readByte();
+ }
+
+ if (c == '\r') {
+ // Read following '\n'
+ stream->readByte();
+ }
+
+ return line;
+}
+
+void CCreditText::handleDots(CCreditLineGroup *group) {
+ uint maxWidth = 0;
+ CCreditLines::iterator second = group->_lines.begin();
+ ++second;
+
+ // Figure out the maximum width of secondary lines
+ for (CCreditLines::iterator i = second; i != group->_lines.end(); ++i)
+ maxWidth = MAX(maxWidth, (*i)->_lineWidth);
+
+ int charWidth = _screenManagerP->stringWidth(".");
+
+ // Process the secondary lines
+ for (CCreditLines::iterator i = second; i != group->_lines.end(); ++i) {
+ CCreditLine *line = *i;
+ if (line->_lineWidth >= maxWidth)
+ continue;
+
+ int dotsCount = (maxWidth + charWidth / 2 - line->_lineWidth) / charWidth;
+ int dotIndex = line->_line.indexOf("....");
+
+ if (dotIndex > 0) {
+ CString leftStr = line->_line.left(dotIndex);
+ CString dotsStr('.', dotsCount);
+ CString rightStr = line->_line.right(dotIndex);
+
+ line->_line = CString::format("%s%s%s", leftStr.c_str(),
+ dotsStr.c_str(), rightStr.c_str());
+ line->_lineWidth = maxWidth;
+ }
+ }
+}
+
+bool CCreditText::draw() {
+ return false;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/credit_text.h b/engines/titanic/support/credit_text.h
new file mode 100644
index 0000000000..ec8fc22cda
--- /dev/null
+++ b/engines/titanic/support/credit_text.h
@@ -0,0 +1,106 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_CREDIT_TEXT_H
+#define TITANIC_CREDIT_TEXT_H
+
+#include "titanic/core/list.h"
+
+namespace Titanic {
+
+class CGameObject;
+class CScreenManager;
+
+class CCreditLine : public ListItem {
+public:
+ CString _line;
+ uint _lineWidth;
+public:
+ CCreditLine() : _lineWidth(0) {}
+ CCreditLine(const CString &line, uint lineWidth) : _line(line), _lineWidth(lineWidth) {}
+};
+typedef List<CCreditLine> CCreditLines;
+
+class CCreditLineGroup : public ListItem {
+public:
+ CCreditLines _lines;
+};
+typedef List<CCreditLineGroup> CCreditLineGroups;
+
+class CCreditText {
+private:
+ /**
+ * Sets up needed data
+ */
+ void setup();
+
+ /**
+ * Read in a text line from the passed stream
+ */
+ CString readLine(Common::SeekableReadStream *stream);
+
+ /**
+ * Handles a group where the .... sequence was encountered
+ */
+ void handleDots(CCreditLineGroup *group);
+public:
+ CScreenManager *_screenManagerP;
+ Rect _rect;
+ int _field14;
+ CCreditLineGroups _groups;
+ uint _ticks;
+ uint _fontHeight;
+ CGameObject *_objectP;
+ CCreditLineGroups::iterator _groupIt;
+ CCreditLines::iterator _lineIt;
+ uint _totalHeight;
+ int _field40;
+ int _field44;
+ int _field48;
+ int _field4C;
+ int _field50;
+ int _field54;
+ int _field58;
+ int _field5C;
+public:
+ CCreditText();
+
+ /**
+ * Clears the object
+ */
+ void clear();
+
+ /**
+ * Sets the game object this override is associated with
+ */
+ void load(CGameObject *obj, CScreenManager *screenManager,
+ const Rect &rect, int v = 0);
+
+ /**
+ * Draw the item
+ */
+ bool draw();
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_CREDIT_TEXT_H */
diff --git a/engines/titanic/support/direct_draw.cpp b/engines/titanic/support/direct_draw.cpp
new file mode 100644
index 0000000000..5ddb25bec9
--- /dev/null
+++ b/engines/titanic/support/direct_draw.cpp
@@ -0,0 +1,109 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/debug.h"
+#include "engines/util.h"
+#include "graphics/pixelformat.h"
+#include "titanic/titanic.h"
+#include "titanic/support/direct_draw.h"
+
+namespace Titanic {
+
+DirectDraw::DirectDraw(TitanicEngine *vm) : _vm(vm),
+ _windowed(false), _fieldC(0), _width(0), _height(0),
+ _bpp(0), _numBackSurfaces(0), _field24(0) {
+}
+
+void DirectDraw::setDisplayMode(int width, int height, int bpp, int refreshRate) {
+ debugC(ERROR_BASIC, kDebugGraphics, "DirectDraw::SetDisplayMode (%d x %d), %d bpp",
+ width, height, bpp);
+ assert(bpp == 16);
+
+ Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ initGraphics(width, height, true, &pixelFormat);
+}
+
+void DirectDraw::diagnostics() {
+ debugC(ERROR_BASIC, kDebugGraphics, "Running DirectDraw Diagnostic...");
+}
+
+DirectDrawSurface *DirectDraw::createSurfaceFromDesc(const DDSurfaceDesc &desc) {
+ DirectDrawSurface *surface = new DirectDrawSurface();
+ surface->create(desc._w, desc._h);
+
+ return surface;
+}
+
+/*------------------------------------------------------------------------*/
+
+DirectDrawManager::DirectDrawManager(TitanicEngine *vm, bool windowed) : _directDraw(vm) {
+ _mainSurface = nullptr;
+ _backSurfaces[0] = _backSurfaces[1] = nullptr;
+ _directDraw._windowed = windowed;
+}
+
+void DirectDrawManager::initVideo(int width, int height, int bpp, int numBackSurfaces) {
+ debugC(ERROR_BASIC, kDebugGraphics, "Initialising video surfaces");
+ _directDraw._width = width;
+ _directDraw._numBackSurfaces = numBackSurfaces;
+ _directDraw._height = height;
+ _directDraw._bpp = bpp;
+
+ if (_directDraw._windowed) {
+ initWindowed();
+ } else {
+ initFullScreen();
+ }
+}
+
+void DirectDrawManager::setResolution() {
+ // TODO
+}
+
+void DirectDrawManager::proc2() {
+
+}
+
+void DirectDrawManager::proc3() {
+
+}
+
+void DirectDrawManager::initFullScreen() {
+ debugC(ERROR_BASIC, kDebugGraphics, "Creating surfaces");
+ _directDraw.setDisplayMode(_directDraw._width, _directDraw._height,
+ _directDraw._bpp, 0);
+
+ _mainSurface = new DirectDrawSurface();
+ _mainSurface->create(g_vm->_screen);
+ _backSurfaces[0] = new DirectDrawSurface();
+ _backSurfaces[0]->create(_directDraw._width, _directDraw._height);
+}
+
+DirectDrawSurface *DirectDrawManager::createSurface(int w, int h, int surfaceNum) {
+ if (surfaceNum)
+ return nullptr;
+
+ assert(_mainSurface);
+ return _directDraw.createSurfaceFromDesc(DDSurfaceDesc(w, h));
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/direct_draw.h b/engines/titanic/support/direct_draw.h
new file mode 100644
index 0000000000..85c344c600
--- /dev/null
+++ b/engines/titanic/support/direct_draw.h
@@ -0,0 +1,105 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_DIRECT_DRAW_H
+#define TITANIC_DIRECT_DRAW_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "titanic/support/direct_draw_surface.h"
+
+namespace Titanic {
+
+class TitanicEngine;
+
+class DirectDraw {
+private:
+ TitanicEngine *_vm;
+public:
+ bool _windowed;
+ int _fieldC;
+ int _width;
+ int _height;
+ int _bpp;
+ int _numBackSurfaces;
+ int _field24;
+public:
+ DirectDraw(TitanicEngine *vm);
+
+ /**
+ * Sets a new display mode
+ */
+ void setDisplayMode(int width, int height, int bpp, int refreshRate);
+
+ /**
+ * Logs diagnostic information
+ */
+ void diagnostics();
+
+ /**
+ * Create a surface from a passed description record
+ */
+ DirectDrawSurface *createSurfaceFromDesc(const DDSurfaceDesc &desc);
+};
+
+class DirectDrawManager {
+public:
+ DirectDraw _directDraw;
+ DirectDrawSurface *_mainSurface;
+ DirectDrawSurface *_backSurfaces[2];
+public:
+ DirectDrawManager(TitanicEngine *vm, bool windowed);
+
+ /**
+ * Initializes video surfaces
+ * @param width Screen width
+ * @param height Screen height
+ * @param bpp Bits per pixel
+ * @param numBackSurfaces Number of back surfaces
+ */
+ void initVideo(int width, int height, int bpp, int numBackSurfaces);
+
+ void setResolution();
+
+ void proc2();
+
+ void proc3();
+
+ /**
+ * Initializes the surfaces in windowed mode
+ */
+ void initWindowed() { initFullScreen(); }
+
+ /**
+ * Initializes the surfaces for the screen
+ */
+ void initFullScreen();
+
+ /**
+ * Create a surface
+ */
+ DirectDrawSurface *createSurface(int w, int h, int surfaceNum);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_DIRECT_DRAW_H */
diff --git a/engines/titanic/support/direct_draw_surface.cpp b/engines/titanic/support/direct_draw_surface.cpp
new file mode 100644
index 0000000000..9ebda15b0e
--- /dev/null
+++ b/engines/titanic/support/direct_draw_surface.cpp
@@ -0,0 +1,100 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/direct_draw_surface.h"
+
+namespace Titanic {
+
+DirectDrawSurface::DirectDrawSurface() : _surface(nullptr),
+ _disposeAfterUse(DisposeAfterUse::YES) {
+}
+
+DirectDrawSurface::~DirectDrawSurface() {
+ free();
+}
+
+void DirectDrawSurface::create(Graphics::ManagedSurface *surface) {
+ free();
+ _surface = surface;
+ _disposeAfterUse = DisposeAfterUse::NO;
+}
+
+void DirectDrawSurface::create(int w, int h) {
+ Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ _surface = new Graphics::ManagedSurface(w, h, pixelFormat);
+ _disposeAfterUse = DisposeAfterUse::YES;
+}
+
+void DirectDrawSurface::free() {
+ if (_disposeAfterUse == DisposeAfterUse::YES)
+ delete _surface;
+ _surface = nullptr;
+ _disposeAfterUse = DisposeAfterUse::NO;
+}
+
+Graphics::ManagedSurface *DirectDrawSurface::lock(const Rect *bounds, int flags) {
+ assert(!_surface->empty());
+ return _surface;
+}
+
+void DirectDrawSurface::unlock() {
+ assert(_surface->w != 0 && _surface->h != 0);
+}
+
+void DirectDrawSurface::fill(const Rect *bounds, uint32 color) {
+ Rect tempBounds;
+
+ assert(_surface);
+ if (bounds) {
+ // Bounds are provided, clip them to the bounds of this surface
+ tempBounds = *bounds;
+ tempBounds.clip(Rect(0, 0, _surface->w, _surface->h));
+ } else {
+ // No bounds provided, so use the entire surface
+ tempBounds = Rect(0, 0, _surface->w, _surface->h);
+ }
+
+ // Fill the area
+ _surface->fillRect(tempBounds, color);
+}
+
+void DirectDrawSurface::fillRect(Rect *rect, byte r, byte g, byte b) {
+ uint color = _surface->format.RGBToColor(r, g, b);
+ Rect tempRect = rect ? *rect : Rect(0, 0, getWidth(), getHeight());
+
+ _surface->fillRect(tempRect, color);
+}
+
+void DirectDrawSurface::blit(const Rect &destRect, DirectDrawSurface *srcSurface, Rect &srcRect) {
+ assert(srcSurface);
+ if (!destRect.isEmpty())
+ _surface->transBlitFrom(*srcSurface->_surface, srcRect, destRect, (uint)-1);
+}
+
+void DirectDrawSurface::blit(const Point &destPos, DirectDrawSurface *srcSurface, Rect *bounds) {
+ if (bounds)
+ _surface->blitFrom(*srcSurface->_surface, *bounds, destPos);
+ else
+ _surface->blitFrom(*srcSurface->_surface, destPos);
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/direct_draw_surface.h b/engines/titanic/support/direct_draw_surface.h
new file mode 100644
index 0000000000..af19e369d2
--- /dev/null
+++ b/engines/titanic/support/direct_draw_surface.h
@@ -0,0 +1,126 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_DIRECT_DRAW_SURFACE_H
+#define TITANIC_DIRECT_DRAW_SURFACE_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "graphics/managed_surface.h"
+#include "titanic/support/rect.h"
+
+namespace Titanic {
+
+class TitanicEngine;
+
+struct DDSurfaceDesc {
+ int _w;
+ int _h;
+ int _flags;
+ int _caps;
+
+ DDSurfaceDesc(int w, int h) : _w(w), _h(h), _flags(0x1006), _caps(64) {}
+};
+
+class DirectDrawSurface {
+private:
+ Graphics::ManagedSurface *_surface;
+ DisposeAfterUse::Flag _disposeAfterUse;
+public:
+ DirectDrawSurface();
+ ~DirectDrawSurface();
+
+ /**
+ * Create a surface
+ */
+ void create(int w, int h);
+
+ /**
+ * Create a surface based on a passed surface
+ */
+ void create(Graphics::ManagedSurface *surface);
+
+ /**
+ * Frees the surface
+ */
+ void free();
+
+ /**
+ * Return the size of the surface in ytes
+ */
+ int getSize() const { return _surface->pitch * _surface->h; }
+
+ /**
+ * Return the surface width
+ */
+ int getWidth() const { return _surface->w; }
+
+ /**
+ * Return the surface width
+ */
+ int getHeight() const { return _surface->h; }
+
+ /**
+ * Return the surface pitch
+ */
+ int getPitch() const { return _surface->pitch; }
+
+ /**
+ * Return the surface's format
+ */
+ const Graphics::PixelFormat &getFormat() { return _surface->format; }
+
+ /**
+ * Lock the surface for access
+ */
+ Graphics::ManagedSurface *lock(const Rect *bounds, int flags);
+
+ /**
+ * Unlocks the surface at the end of direct accesses
+ */
+ void unlock();
+
+ /**
+ * Fills an area of the surfae with the specified color. If no bounds are passed,
+ * then the entire surface is filled
+ */
+ void fill(const Rect *bounds, uint32 color);
+
+ /**
+ * Fill an area with a specific color
+ */
+ void fillRect(Rect *rect, byte r, byte g, byte b);
+
+ /**
+ * Copy data from a source surfcae into this one
+ */
+ void blit(const Rect &destRect, DirectDrawSurface *srcSurface, Rect &srcRect);
+
+ /**
+ * Copy data from a source surfcae into this one
+ */
+ void blit(const Point &destPos, DirectDrawSurface *srcSurface, Rect *bounds);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_DIRECT_DRAW_SURFACE_H */
diff --git a/engines/titanic/support/exe_resources.cpp b/engines/titanic/support/exe_resources.cpp
new file mode 100644
index 0000000000..522e92f718
--- /dev/null
+++ b/engines/titanic/support/exe_resources.cpp
@@ -0,0 +1,37 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/exe_resources.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+CExeResources::CExeResources() : _owner(nullptr), _field4(0), _field8(0),
+ _fieldC(0), _field10(0), _field14(0), _field18(0) {
+}
+
+void CExeResources::reset(CScriptHandler *owner, int val1, int val2) {
+ _owner = owner;
+ _field18 = val2;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/exe_resources.h b/engines/titanic/support/exe_resources.h
new file mode 100644
index 0000000000..49e05aa56f
--- /dev/null
+++ b/engines/titanic/support/exe_resources.h
@@ -0,0 +1,51 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_EXE_RESOURCES_H
+#define TITANIC_EXE_RESOURCES_H
+
+namespace Titanic {
+
+class CScriptHandler;
+
+enum FileHandle { HANDLE_STDIN = 0, HANDLE_STDOUT = 1, HANDLE_STDERR = 2 };
+
+class CExeResources {
+public:
+ CScriptHandler *_owner;
+ int _field4;
+ int _field8;
+ int _fieldC;
+ int _field10;
+ int _field14;
+ int _field18;
+public:
+ CExeResources();
+
+ void reset(CScriptHandler *owner, int val1, int val2);
+
+ bool is18Equals(int val) const { return _field18 == val; }
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_EXE_RESOURCES_H */
diff --git a/engines/titanic/support/files_manager.cpp b/engines/titanic/support/files_manager.cpp
new file mode 100644
index 0000000000..04928b96d6
--- /dev/null
+++ b/engines/titanic/support/files_manager.cpp
@@ -0,0 +1,132 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/file.h"
+#include "titanic/support/files_manager.h"
+#include "titanic/game_manager.h"
+
+namespace Titanic {
+
+CFilesManager::CFilesManager() : _gameManager(nullptr), _assetsPath("Assets"),
+ _field0(0), _drive(-1), _field18(0), _field1C(0), _field3C(0) {
+ loadResourceIndex();
+}
+
+CFilesManager::~CFilesManager() {
+ _datFile.close();
+}
+
+void CFilesManager::loadResourceIndex() {
+ if (!_datFile.open("titanic.dat"))
+ error("Could not find titanic.dat data file");
+
+ uint headerId = _datFile.readUint32BE();
+ uint version = _datFile.readUint16LE();
+ if (headerId != MKTAG('S', 'V', 'T', 'N') || version < 1)
+ error("Invalid data file");
+
+ // Read in entries
+ uint offset, size;
+ char c;
+ Common::String resourceName;
+ for (;;) {
+ offset = _datFile.readUint32LE();
+ size = _datFile.readUint32LE();
+ if (size == 0)
+ break;
+
+ Common::String resName;
+ while ((c = _datFile.readByte()) != '\0')
+ resName += c;
+
+ _resources[resName] = ResourceEntry(offset, size);
+ }
+}
+
+bool CFilesManager::fileExists(const CString &name) {
+ Common::File f;
+ return f.exists(name);
+}
+
+bool CFilesManager::scanForFile(const CString &name) {
+ if (name.empty())
+ return false;
+
+ CString filename = name;
+ filename.toLowercase();
+
+ if (filename[0] == 'y' || filename[0] == 'z')
+ return true;
+ else if (filename[0] < 'a' || filename[0] > 'c')
+ return false;
+
+ CString fname = filename;
+ int idx = fname.indexOf('#');
+ if (idx >= 0) {
+ fname = fname.left(idx);
+ fname += ".st";
+ }
+
+ // Return true if the file exists
+ if (fileExists(fname))
+ return true;
+
+ // Couldn't find file. Start by calling the game manager's viewChange
+ // method, which handles all active scene objects freeing their resources
+ if (_gameManager)
+ _gameManager->viewChange();
+
+ return false;
+}
+
+void CFilesManager::loadDrive() {
+ assert(_drive == -1);
+ resetView();
+}
+
+void CFilesManager::debug(CScreenManager *screenManager) {
+ warning("TODO: CFilesManager::debug");
+}
+
+void CFilesManager::resetView() {
+ if (_gameManager) {
+ _gameManager->_gameState.setMode(GSMODE_INTERACTIVE);
+ _gameManager->initBounds();
+ }
+}
+
+void CFilesManager::fn4(const CString &name) {
+ warning("TODO: CFilesManager::fn4");
+}
+
+void CFilesManager::preload(const CString &name) {
+ // We don't currently do any preloading of resources
+}
+
+Common::SeekableReadStream *CFilesManager::getResource(const CString &str) {
+ ResourceEntry resEntry = _resources[str];
+ _datFile.seek(resEntry._offset);
+
+ return _datFile.readStream(resEntry._size);
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/files_manager.h b/engines/titanic/support/files_manager.h
new file mode 100644
index 0000000000..ec0c7fc008
--- /dev/null
+++ b/engines/titanic/support/files_manager.h
@@ -0,0 +1,109 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_FILES_MANAGER_H
+#define TITANIC_FILES_MANAGER_H
+
+#include "common/hashmap.h"
+#include "titanic/core/list.h"
+#include "titanic/support/screen_manager.h"
+
+namespace Titanic {
+
+class CGameManager;
+
+class CFilesManagerList : public List<ListItem> {
+};
+
+class CFilesManager {
+ struct ResourceEntry {
+ uint _offset;
+ uint _size;
+
+ ResourceEntry() : _offset(0), _size(0) {}
+ ResourceEntry(uint offset, uint size) : _offset(offset), _size(size) {}
+ };
+ typedef Common::HashMap<Common::String, ResourceEntry> ResourceHash;
+private:
+ CGameManager *_gameManager;
+ Common::File _datFile;
+ ResourceHash _resources;
+ CFilesManagerList _list;
+ CString _string1;
+ CString _string2;
+ int _field0;
+ int _drive;
+ int _field18;
+ int _field1C;
+ int _field3C;
+ const CString _assetsPath;
+private:
+ void loadResourceIndex();
+public:
+ CFilesManager();
+ ~CFilesManager();
+
+ /**
+ * Sets the game manager
+ */
+ void setGameManager(CGameManager *gameManager) {
+ _gameManager = gameManager;
+ }
+
+ /**
+ * Returns true if a file of the given name exists
+ */
+ static bool fileExists(const CString &name);
+
+ /**
+ * Scans for a file with a matching name
+ */
+ bool scanForFile(const CString &name);
+
+ /**
+ * Handles displaying a load drive view if necessary
+ */
+ void loadDrive();
+
+ void debug(CScreenManager *screenManager);
+
+ /**
+ * Resets the view being displayed
+ */
+ void resetView();
+
+ void fn4(const CString &name);
+
+ /**
+ * Preloads and caches a file for access shortly
+ */
+ void preload(const CString &name);
+
+ /**
+ * Get a resource from the executable
+ */
+ Common::SeekableReadStream *getResource(const CString &str);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_FILES_MANAGER_H */
diff --git a/engines/titanic/support/font.cpp b/engines/titanic/support/font.cpp
new file mode 100644
index 0000000000..07e4c28991
--- /dev/null
+++ b/engines/titanic/support/font.cpp
@@ -0,0 +1,279 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/textconsole.h"
+#include "titanic/support/font.h"
+#include "titanic/support/files_manager.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+STFont::STFont() {
+ _dataPtr = nullptr;
+ _dataSize = 0;
+ _fontHeight = 0;
+ _dataWidth = 0;
+ _fontR = _fontG = _fontB = 0;
+}
+
+STFont::~STFont() {
+ delete[] _dataPtr;
+}
+
+void STFont::load(int fontNumber) {
+ assert(!_dataPtr);
+ Common::SeekableReadStream *stream = g_vm->_filesManager->getResource(
+ CString::format("STFONT/%d", fontNumber));
+ if (!stream)
+ error("Could not locate the specified font");
+
+ _fontHeight = stream->readUint32LE();
+ _dataWidth = stream->readUint32LE();
+ for (uint idx = 0; idx < 256; ++idx)
+ _chars[idx]._width = stream->readUint32LE();
+ for (uint idx = 0; idx < 256; ++idx)
+ _chars[idx]._offset = stream->readUint32LE();
+
+ _dataSize = stream->readUint32LE();
+ _dataPtr = new byte[_dataSize];
+ stream->read(_dataPtr, _dataSize);
+
+ delete stream;
+}
+
+void STFont::setColor(byte r, byte g, byte b) {
+ _fontR = r;
+ _fontG = g;
+ _fontB = b;
+}
+
+uint16 STFont::getColor() const {
+ return g_system->getScreenFormat().RGBToColor(_fontR, _fontG, _fontB);
+}
+
+int STFont::getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const {
+ Point textSize;
+
+ // Reset output dimensions if provided
+ if (sizeOut)
+ *sizeOut = Point(0, 0);
+
+ if (_fontHeight == 0 || !_dataPtr)
+ // No font, so return immediately
+ return 0;
+
+ // Loop through the characters of the string
+ if (!str.empty()) {
+ for (const char *strP = str.c_str(); *strP; ++strP) {
+ if (*strP == TEXTCMD_NPC) {
+ strP += 3;
+ } else if (*strP == TEXTCMD_SET_COLOR) {
+ strP += 4;
+ } else {
+ if (*strP == ' ') {
+ // Check fo rline wrapping
+ checkLineWrap(textSize, maxWidth, strP);
+ }
+
+ extendBounds(textSize, *strP, maxWidth);
+ }
+ }
+ }
+
+ if (sizeOut)
+ *sizeOut = textSize;
+
+ return textSize.y + _fontHeight;
+}
+
+int STFont::stringWidth(const CString &text) const {
+ if (text.empty())
+ return 0;
+
+ const char *srcP = text.c_str();
+ int total = 0;
+ char c;
+ while ((c = *srcP++)) {
+ if (c == 26) {
+ // Skip over command parameter bytes
+ srcP += 3;
+ } else if (c == TEXTCMD_SET_COLOR) {
+ // Skip over command parameter bytes
+ srcP += 4;
+ } else if (c != '\n') {
+ total += _chars[(byte)c]._width;
+ }
+ }
+
+ return total;
+}
+
+int STFont::writeString(CVideoSurface *surface, const Rect &rect1, const Rect &destRect,
+ int yOffset, const CString &str, CTextCursor *textCursor) {
+ if (!_fontHeight || !_dataPtr)
+ return -1;
+
+ Point textSize(0, -yOffset);
+ Rect destBounds = destRect;
+ destBounds.constrain(rect1);
+ if (destBounds.isEmpty())
+ return -1;
+
+ const char *endP = nullptr;
+ const char *strEndP = str.c_str() + str.size() - 1;
+ for (const char *srcP = str.c_str(); *srcP; ++srcP) {
+ if (*srcP == TEXTCMD_NPC) {
+ srcP += 3;
+ } else if (*srcP == TEXTCMD_SET_COLOR) {
+ // Change the color used for characters
+ byte r = *++srcP;
+ byte g = *++srcP;
+ byte b = *++srcP;
+ ++srcP;
+ setColor(r, g, b);
+ } else {
+ if (*srcP == ' ') {
+ // Check fo rline wrapping
+ checkLineWrap(textSize, rect1.width(), srcP);
+ if (!*srcP)
+ return endP - str.c_str();
+ }
+
+ if (*srcP != '\n') {
+ WriteCharacterResult result = writeChar(surface, *srcP, textSize, rect1, &destBounds);
+ if (result == WC_OUTSIDE_BOTTOM)
+ return endP - str.c_str();
+ else if (result == WC_IN_BOUNDS)
+ endP = srcP;
+ }
+
+ if (srcP < strEndP)
+ extendBounds(textSize, *srcP, rect1.width());
+ }
+ }
+
+ if (textCursor && textCursor->getMode() == -2) {
+ Point cursorPos(rect1.left + textSize.x, rect1.top + textSize.y);
+ textCursor->setPos(cursorPos);
+ }
+
+ return endP ? endP - str.c_str() : 0;
+}
+
+WriteCharacterResult STFont::writeChar(CVideoSurface *surface, unsigned char c, const Point &pt,
+ const Rect &destRect, const Rect *srcRect) {
+ if (c == 233)
+ c = '$';
+
+ Rect tempRect;
+ tempRect.left = _chars[c]._offset;
+ tempRect.right = _chars[c]._offset + _chars[c]._width;
+ tempRect.top = 0;
+ tempRect.bottom = _fontHeight;
+ Point destPos(pt.x + destRect.left, pt.y + destRect.top);
+
+ if (srcRect->isEmpty())
+ srcRect = &destRect;
+ if (destPos.y > srcRect->bottom)
+ return WC_OUTSIDE_BOTTOM;
+
+ if ((destPos.y + tempRect.height()) > srcRect->bottom) {
+ tempRect.bottom += tempRect.top - destPos.y;
+ }
+
+ if (destPos.y < srcRect->top) {
+ if ((tempRect.height() + destPos.y) < srcRect->top)
+ return WC_OUTSIDE_TOP;
+
+ tempRect.top += srcRect->top - destPos.y;
+ destPos.y = srcRect->top;
+ }
+
+ if (destPos.x < srcRect->left) {
+ if ((tempRect.width() + destPos.x) < srcRect->left)
+ return WC_OUTSIDE_LEFT;
+
+ tempRect.left += srcRect->left - destPos.x;
+ destPos.x = srcRect->left;
+ } else {
+ if ((tempRect.width() + destPos.x) > srcRect->right) {
+ if (destPos.x > srcRect->right)
+ return WC_OUTSIDE_RIGHT;
+
+ tempRect.right += srcRect->left - destPos.x;
+ }
+ }
+
+ copyRect(surface, destPos, tempRect);
+ return WC_IN_BOUNDS;
+}
+
+void STFont::copyRect(CVideoSurface *surface, const Point &pt, Rect &rect) {
+ if (surface->lock()) {
+ uint16 *lineP = surface->getBasePtr(pt.x, pt.y);
+ uint16 color = getColor();
+
+ for (int yp = rect.top; yp < rect.bottom; ++yp, lineP += surface->getWidth()) {
+ uint16 *destP = lineP;
+ for (int xp = rect.left; xp < rect.right; ++xp, ++destP) {
+ const byte *srcP = _dataPtr + yp * _dataWidth + xp;
+ surface->changePixel(destP, &color, *srcP >> 3, true);
+ }
+ }
+
+ surface->unlock();
+ }
+}
+
+void STFont::extendBounds(Point &textSize, byte c, int maxWidth) const {
+ textSize.x += _chars[c]._width;
+
+ if (c == '\n' || textSize.x > maxWidth) {
+ textSize.x = 0;
+ textSize.y += _fontHeight;
+ }
+}
+
+void STFont::checkLineWrap(Point &textSize, int maxWidth, const char *&str) const {
+ bool flag = false;
+ int totalWidth = 0;
+ for (const char *srcPtr = str; *srcPtr && *srcPtr != ' '; ++srcPtr) {
+ if (*srcPtr == ' ' && flag)
+ break;
+
+ if (*srcPtr == TEXTCMD_NPC)
+ srcPtr += 3;
+ else if (*srcPtr == TEXTCMD_SET_COLOR)
+ srcPtr += 4;
+ else
+ totalWidth += _chars[(byte)*srcPtr]._width;
+ }
+
+ if ((textSize.x + totalWidth) >= maxWidth && totalWidth < maxWidth) {
+ // Word wrap
+ textSize.x = 0;
+ textSize.y += _fontHeight;
+ ++str;
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/font.h b/engines/titanic/support/font.h
new file mode 100644
index 0000000000..591fb4661c
--- /dev/null
+++ b/engines/titanic/support/font.h
@@ -0,0 +1,123 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_FONT_H
+#define TITANIC_FONT_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "titanic/support/rect.h"
+#include "titanic/support/string.h"
+#include "titanic/support/text_cursor.h"
+
+namespace Titanic {
+
+enum TextCommand { TEXTCMD_NPC = 26, TEXTCMD_SET_COLOR = 27 };
+
+enum WriteCharacterResult {
+ WC_IN_BOUNDS = 0, WC_OUTSIDE_TOP = -1, WC_OUTSIDE_BOTTOM = -2,
+ WC_OUTSIDE_LEFT = -3, WC_OUTSIDE_RIGHT = -4
+};
+
+class CVideoSurface;
+
+class STFont {
+ struct CharEntry {
+ uint _width;
+ uint _offset;
+ };
+private:
+ /**
+ * Copys a rectangle representing a character in the font data to
+ * a given destination position in the surface
+ */
+ void copyRect(CVideoSurface *surface, const Common::Point &destPos,
+ Rect &srcRect);
+
+ /**
+ * Write a character
+ */
+ WriteCharacterResult writeChar(CVideoSurface *surface, unsigned char c,
+ const Common::Point &pt, const Rect &destRect, const Rect *srcRect);
+
+ /**
+ * Extends a passed text area by the space required for
+ * the given character
+ */
+ void extendBounds(Point &textSize, byte c, int maxWidth) const;
+
+ /**
+ * Called at spacing between words, checks for line wrapping
+ */
+ void checkLineWrap(Point &textSize, int maxWidth, const char *&str) const;
+public:
+ byte *_dataPtr;
+ size_t _dataSize;
+ int _fontHeight;
+ uint _dataWidth;
+ CharEntry _chars[256];
+ byte _fontR, _fontG, _fontB;
+public:
+ STFont();
+ ~STFont();
+
+ /**
+ * Load a specified font
+ */
+ void load(int fontNumber);
+
+ /**
+ * Return the width in pixels of the specified text
+ */
+ int stringWidth(const CString &text) const;
+
+ /**
+ * Write a string to the specified surface
+ * @returns The index of the last character that was visible
+ * with the drawing area
+ */
+ int writeString(CVideoSurface *surface, const Rect &rect1, const Rect &destRect,
+ int yOffset, const CString &str, CTextCursor *textCursor);
+
+ /**
+ * Get the text area a string will fit into
+ * @param str String
+ * @param maxWidth Maximum width in pixels
+ * @param sizeOut Optional pointer to output size (width, height)
+ * @returns Required height
+ */
+ int getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const;
+
+ /**
+ * Sets the font color
+ */
+ void setColor(byte r, byte g, byte b);
+
+ /**
+ * Gets the font color
+ */
+ uint16 getColor() const;
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_FONT_H */
diff --git a/engines/titanic/support/image.cpp b/engines/titanic/support/image.cpp
new file mode 100644
index 0000000000..1e936b6940
--- /dev/null
+++ b/engines/titanic/support/image.cpp
@@ -0,0 +1,56 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/image.h"
+#include "titanic/titanic.h"
+#include "image/bmp.h"
+
+namespace Titanic {
+
+void Image::load(const CString &resName) {
+ Common::SeekableReadStream *stream = g_vm->_filesManager->getResource(resName);
+ loadBitmap(*stream);
+ delete stream;
+}
+
+void Image::loadBitmap(Common::SeekableReadStream &s) {
+ ::Image::BitmapDecoder decoder;
+ decoder.loadStream(s);
+ const Graphics::Surface *src = decoder.getSurface();
+ Graphics::PixelFormat scrFormat = g_system->getScreenFormat();
+
+ if (src->format == scrFormat) {
+ create(src->w, src->h, scrFormat);
+ blitFrom(*src);
+ } else {
+ // Convert the loaded surface to the screen surface format
+ const byte *palette = decoder.getPalette();
+ Graphics::Surface *surface = src->convertTo(scrFormat, palette);
+ create(surface->w, surface->h, scrFormat);
+ blitFrom(*surface);
+
+ surface->free();
+ delete surface;
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/image.h b/engines/titanic/support/image.h
new file mode 100644
index 0000000000..9876f15c40
--- /dev/null
+++ b/engines/titanic/support/image.h
@@ -0,0 +1,43 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_IMAGE_H
+#define TITANIC_IMAGE_H
+
+#include "common/stream.h"
+#include "graphics/managed_surface.h"
+#include "titanic/support/string.h"
+
+namespace Titanic {
+
+class Image : public Graphics::ManagedSurface {
+private:
+ void loadBitmap(Common::SeekableReadStream &s);
+public:
+ virtual ~Image() {}
+
+ void load(const CString &resName);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_IMAGE_H */
diff --git a/engines/titanic/support/image_decoders.cpp b/engines/titanic/support/image_decoders.cpp
new file mode 100644
index 0000000000..495d1d0982
--- /dev/null
+++ b/engines/titanic/support/image_decoders.cpp
@@ -0,0 +1,81 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/image_decoders.h"
+
+namespace Titanic {
+
+void CJPEGDecode::decode(OSVideoSurface &surface, const CString &name) {
+ // Open up the resource
+ StdCWadFile file;
+ file.open(name);
+
+ // Use the ScucmmVM deoder to decode it
+ loadStream(*file.readStream());
+ const Graphics::Surface *srcSurf = getSurface();
+
+ // Resize the surface if necessary
+ if (!surface.hasSurface() || surface.getWidth() != srcSurf->w
+ || surface.getHeight() != srcSurf->h)
+ surface.recreate(srcSurf->w, srcSurf->h);
+
+ // Convert the decoded surface to the correct pixel format, and then copy it over
+ surface.lock();
+ Graphics::Surface *convertedSurface = srcSurf->convertTo(surface._rawSurface->format);
+
+ Common::copy((byte *)convertedSurface->getPixels(), (byte *)convertedSurface->getPixels() +
+ surface.getPitch() * surface.getHeight(), (byte *)surface._rawSurface->getPixels());
+
+ convertedSurface->free();
+ delete convertedSurface;
+ surface.unlock();
+}
+
+/*------------------------------------------------------------------------*/
+
+void CTargaDecode::decode(OSVideoSurface &surface, const CString &name) {
+ // Open up the resource
+ StdCWadFile file;
+ file.open(name);
+
+ // Use the ScucmmVM deoder to decode it
+ loadStream(*file.readStream());
+ const Graphics::Surface *srcSurf = getSurface();
+
+ // Resize the surface if necessary
+ if (!surface.hasSurface() || surface.getWidth() != srcSurf->w
+ || surface.getHeight() != srcSurf->h)
+ surface.recreate(srcSurf->w, srcSurf->h);
+
+ // Convert the decoded surface to the correct pixel format, and then copy it over
+ surface.lock();
+ Graphics::Surface *convertedSurface = srcSurf->convertTo(surface._rawSurface->format);
+
+ Common::copy((byte *)convertedSurface->getPixels(), (byte *)convertedSurface->getPixels() +
+ surface.getPitch() * surface.getHeight(), (byte *)surface._rawSurface->getPixels());
+
+ convertedSurface->free();
+ delete convertedSurface;
+ surface.unlock();
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/image_decoders.h b/engines/titanic/support/image_decoders.h
new file mode 100644
index 0000000000..b824b786a7
--- /dev/null
+++ b/engines/titanic/support/image_decoders.h
@@ -0,0 +1,52 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_IMAGE_DECODERS_H
+#define TITANIC_IMAGE_DECODERS_H
+
+#include "image/jpeg.h"
+#include "image/tga.h"
+#include "titanic/support/string.h"
+#include "titanic/support/simple_file.h"
+#include "titanic/support/video_surface.h"
+
+namespace Titanic {
+
+class CJPEGDecode : public Image::JPEGDecoder {
+public:
+ /**
+ * Decode the image file onto the passed surface
+ */
+ void decode(OSVideoSurface &surface, const CString &name);
+};
+
+class CTargaDecode : public Image::TGADecoder {
+public:
+ /**
+ * Decode the image file onto the passed surface
+ */
+ void decode(OSVideoSurface &surface, const CString &name);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_IMAGE_DECODERS_H */
diff --git a/engines/titanic/support/mouse_cursor.cpp b/engines/titanic/support/mouse_cursor.cpp
new file mode 100644
index 0000000000..d6a42823f5
--- /dev/null
+++ b/engines/titanic/support/mouse_cursor.cpp
@@ -0,0 +1,135 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/memstream.h"
+#include "common/textconsole.h"
+#include "graphics/cursorman.h"
+#include "titanic/support/mouse_cursor.h"
+#include "titanic/support/movie.h"
+#include "titanic/support/screen_manager.h"
+#include "titanic/titanic.h"
+#include "titanic/support/video_surface.h"
+#include "titanic/core/resource_key.h"
+
+namespace Titanic {
+
+static const int CURSOR_DATA[NUM_CURSORS][4] = {
+ { 1, 136, 19, 18 },
+ { 2, 139, 1, 1 },
+ { 3, 140, 32, 1 },
+ { 4, 137, 13, 0 },
+ { 5, 145, 13, 0 },
+ { 6, 144, 13, 22 },
+ { 7, 137, 14, 0 },
+ { 8, 148, 22, 40 },
+ { 9, 136, 19, 18 },
+ { 10, 143, 11, 11 },
+ { 11, 146, 11, 11 },
+ { 12, 136, 19, 18 },
+ { 13, 136, 19, 25 },
+ { 14, 136, 13, 22 },
+ { 15, 138, 20, 28 }
+};
+
+CMouseCursor::CursorEntry::~CursorEntry() {
+ delete _videoSurface;
+ delete _frameSurface;
+}
+
+CMouseCursor::CMouseCursor(CScreenManager *screenManager) :
+ _screenManager(screenManager), _cursorId(CURSOR_HOURGLASS),
+ _setCursorCount(0), _fieldE4(0), _fieldE8(0) {
+ loadCursorImages();
+ setCursor(CURSOR_ARROW);
+}
+
+CMouseCursor::~CMouseCursor() {
+}
+
+void CMouseCursor::loadCursorImages() {
+ const CResourceKey key("ycursors.avi");
+ g_vm->_filesManager->fn4(key.getString());
+
+ // Iterate through getting each cursor
+ for (int idx = 0; idx < NUM_CURSORS; ++idx) {
+ assert(CURSOR_DATA[idx][0] == (idx + 1));
+ _cursors[idx]._centroid = Common::Point(CURSOR_DATA[idx][2],
+ CURSOR_DATA[idx][3]);
+
+ // Create the surface
+ CVideoSurface *surface = _screenManager->createSurface(64, 64);
+ _cursors[idx]._videoSurface = surface;
+
+ // Open the cursors video and move to the given frame
+ OSMovie movie(key, surface);
+ movie.setFrame(idx);
+
+ Graphics::ManagedSurface *frameSurface = movie.duplicateFrame();
+ _cursors[idx]._frameSurface = frameSurface;
+ surface->setMovieFrameSurface(frameSurface);
+ }
+}
+
+void CMouseCursor::show() {
+ CursorMan.showMouse(true);
+}
+
+void CMouseCursor::hide() {
+ CursorMan.showMouse(false);
+}
+
+void CMouseCursor::setCursor(CursorId cursorId) {
+ ++_setCursorCount;
+
+ if (cursorId != _cursorId) {
+ CursorEntry &ce = _cursors[cursorId - 1];
+ CVideoSurface &surface = *ce._videoSurface;
+ surface.lock();
+
+ CursorMan.replaceCursor(surface.getPixels(), surface.getWidth(), surface.getHeight(),
+ ce._centroid.x, ce._centroid.y, 0, false, &g_vm->_screen->format);
+ surface.unlock();
+
+ _cursorId = cursorId;
+ }
+}
+
+void CMouseCursor::update() {
+ // No implementation needed
+}
+
+void CMouseCursor::lockE4() {
+ _fieldE4 = 0;
+ CScreenManager::_screenManagerPtr->_inputHandler->incLockCount();
+}
+
+void CMouseCursor::unlockE4() {
+ _fieldE4 = 1;
+ _fieldE8 = 0;
+ CScreenManager::_screenManagerPtr->_inputHandler->decLockCount();
+}
+
+void CMouseCursor::saveState(int v1, int v2, int v3) {
+ // TODO
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/mouse_cursor.h b/engines/titanic/support/mouse_cursor.h
new file mode 100644
index 0000000000..7a81ad43fa
--- /dev/null
+++ b/engines/titanic/support/mouse_cursor.h
@@ -0,0 +1,114 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_MOUSE_CURSOR_H
+#define TITANIC_MOUSE_CURSOR_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+#include "graphics/managed_surface.h"
+
+namespace Titanic {
+
+#define NUM_CURSORS 15
+
+enum CursorId {
+ CURSOR_ARROW = 1,
+ CURSOR_MOVE_LEFT = 2,
+ CURSOR_MOVE_RIGHT = 3,
+ CURSOR_MOVE_FORWARD = 4,
+ CURSOR_MOVE_UP = 5,
+ CURSOR_MOVE_DOWN1 = 6,
+ CURSOR_MOVE_FORWARD2 = 7,
+ CURSOR_HAND = 8,
+ CURSOR_ACTIVATE = 9,
+ CURSOR_INVALID = 10,
+ CURSOR_MAGNIFIER = 11,
+ CURSOR_IGNORE = 12,
+ CURSOR_BACKWARDS = 13,
+ CURSOR_DOWN = 14,
+ CURSOR_HOURGLASS = 15
+};
+
+class CScreenManager;
+class CVideoSurface;
+
+class CMouseCursor {
+ struct CursorEntry {
+ CVideoSurface *_videoSurface;
+ Graphics::ManagedSurface *_frameSurface;
+ Common::Point _centroid;
+
+ CursorEntry() : _videoSurface(nullptr), _frameSurface(nullptr) {}
+ ~CursorEntry();
+ };
+private:
+ CScreenManager *_screenManager;
+ CursorId _cursorId;
+ CursorEntry _cursors[NUM_CURSORS];
+ uint _setCursorCount;
+ int _fieldE4;
+ int _fieldE8;
+
+ /**
+ * Load the images for each cursor
+ */
+ void loadCursorImages();
+public:
+ CMouseCursor(CScreenManager *screenManager);
+ ~CMouseCursor();
+
+ /**
+ * Make the mouse cursor visible
+ */
+ void show();
+
+ /**
+ * Hide the mouse cursor
+ */
+ void hide();
+
+ /**
+ * Set the cursor
+ */
+ void setCursor(CursorId cursorId);
+
+ /**
+ * Updates the mouse cursor
+ */
+ void update();
+
+ /**
+ * Returns the number of times the cursor has been set
+ */
+ uint getChangeCount() const { return _setCursorCount; }
+
+ void lockE4();
+ void unlockE4();
+
+ void saveState(int v1, int v2, int v3);
+};
+
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_MOUSE_CURSOR_H */
diff --git a/engines/titanic/support/movie.cpp b/engines/titanic/support/movie.cpp
new file mode 100644
index 0000000000..3c935e83a8
--- /dev/null
+++ b/engines/titanic/support/movie.cpp
@@ -0,0 +1,218 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/movie.h"
+#include "titanic/support/avi_surface.h"
+#include "titanic/sound/sound_manager.h"
+#include "titanic/messages/messages.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+#define CLIP_WIDTH 600
+#define CLIP_WIDTH_REDUCED (CLIP_WIDTH / 2)
+#define CLIP_HEIGHT 340
+#define CLIP_HEIGHT_REDUCED (CLIP_HEIGHT / 2)
+
+CMovieList *CMovie::_playingMovies;
+CVideoSurface *CMovie::_movieSurface;
+
+CMovie::CMovie() : ListItem(), _handled(false), _hasVideoFrame(false),
+ _field14(0) {
+}
+
+CMovie::~CMovie() {
+ removeFromPlayingMovies();
+}
+
+void CMovie::init() {
+ _playingMovies = new CMovieList();
+ _movieSurface = nullptr;
+}
+
+void CMovie::deinit() {
+ // Delete each movie in turn
+ for (CMovieList::iterator i = _playingMovies->begin(); i != _playingMovies->end(); ) {
+ // We need to increment iterator before deleting movie,
+ // since the CMovie destructor calls removeFromPlayingMovies
+ CMovie *movie = *i;
+ ++i;
+ delete movie;
+ }
+
+ delete _playingMovies;
+ delete _movieSurface;
+}
+
+void CMovie::addToPlayingMovies() {
+ if (!isActive())
+ _playingMovies->push_back(this);
+}
+
+void CMovie::removeFromPlayingMovies() {
+ _playingMovies->remove(this);
+}
+
+bool CMovie::isActive() const {
+ return _playingMovies->contains(this);
+}
+
+bool CMovie::hasVideoFrame() {
+ if (_hasVideoFrame) {
+ _hasVideoFrame = 0;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) :
+ _aviSurface(name), _videoSurface(surface) {
+ _field18 = 0;
+ _field24 = 0;
+ _field28 = 0;
+ _field2C = 0;
+
+ surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight());
+ _aviSurface.setVideoSurface(surface);
+}
+
+OSMovie::~OSMovie() {
+}
+
+void OSMovie::play(uint flags, CGameObject *obj) {
+ _aviSurface.play(flags, obj);
+
+ if (_aviSurface.isPlaying())
+ movieStarted();
+}
+
+void OSMovie::play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) {
+ _aviSurface.play(startFrame, endFrame, flags, obj);
+
+ if (_aviSurface.isPlaying())
+ movieStarted();
+}
+
+void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) {
+ _aviSurface.play(startFrame, endFrame, initialFrame, flags, obj);
+
+ if (_aviSurface.isPlaying())
+ movieStarted();
+}
+
+void OSMovie::playClip(const Point &drawPos, uint startFrame, uint endFrame) {
+ if (!_movieSurface)
+ _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340);
+
+ bool widthLess = _videoSurface->getWidth() < 600;
+ bool heightLess = _videoSurface->getHeight() < 340;
+ Rect r(drawPos.x, drawPos.y,
+ drawPos.x + widthLess ? CLIP_WIDTH_REDUCED : CLIP_WIDTH,
+ drawPos.y + heightLess ? CLIP_HEIGHT_REDUCED : CLIP_HEIGHT
+ );
+
+ uint timePerFrame = 1000 / _aviSurface._frameRate;
+
+ for (; endFrame >= startFrame; ++startFrame) {
+ // Set the frame
+ _aviSurface.setFrame(startFrame);
+
+ // TODO: See if we need to do anything further here. The original had a bunch
+ // of calls and using of the _movieSurface; perhaps to allow scaling down
+ // videos to half-size
+ if (widthLess || heightLess)
+ warning("Not properly reducing clip size: %d %d", r.width(), r.height());
+
+ // Wait for the next frame, unless the user interrupts the clip
+ if (g_vm->_events->waitForPress(timePerFrame))
+ break;
+ }
+}
+
+void OSMovie::stop() {
+ _aviSurface.stop();
+ removeFromPlayingMovies();
+}
+
+void OSMovie::addEvent(int frameNumber, CGameObject *obj) {
+ if (_aviSurface.addEvent(frameNumber, obj)) {
+ CMovieFrameMsg frameMsg(frameNumber, 0);
+ frameMsg.execute(obj);
+ }
+}
+
+void OSMovie::setFrame(uint frameNumber) {
+ _aviSurface.setFrame(frameNumber);
+ _videoSurface->setMovieFrameSurface(_aviSurface.getSecondarySurface());
+}
+
+bool OSMovie::handleEvents(CMovieEventList &events) {
+ if (!_aviSurface.isPlaying())
+ return false;
+ if (!_aviSurface.isNextFrame())
+ return _aviSurface.isPlaying();
+
+ // Handle updating the frame
+ while (_aviSurface.isPlaying() && _aviSurface.isNextFrame()) {
+ _aviSurface.handleEvents(events);
+ _videoSurface->setMovieFrameSurface(_aviSurface.getSecondarySurface());
+ }
+
+ // Flag there's a video frame
+ _hasVideoFrame = true;
+
+ return _aviSurface.isPlaying();
+}
+
+const CMovieRangeInfoList *OSMovie::getMovieRangeInfo() const {
+ return _aviSurface.getMovieRangeInfo();
+}
+
+void OSMovie::setSoundManager(CSoundManager *soundManager) {
+ _aviSurface._soundManager = soundManager;
+}
+
+int OSMovie::getFrame() const {
+ return _aviSurface.getFrame();
+}
+
+void OSMovie::movieStarted() {
+ if (_aviSurface._hasAudio)
+ _aviSurface._soundManager->movieStarted();
+
+ // Register the movie in the playing list
+ addToPlayingMovies();
+ _hasVideoFrame = true;
+}
+
+void OSMovie::setFrameRate(double rate) {
+ _aviSurface.setFrameRate(rate);
+}
+
+Graphics::ManagedSurface *OSMovie::duplicateFrame() const {
+ return _aviSurface.duplicateSecondaryFrame();
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/movie.h b/engines/titanic/support/movie.h
new file mode 100644
index 0000000000..2a7d589194
--- /dev/null
+++ b/engines/titanic/support/movie.h
@@ -0,0 +1,237 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_MOVIE_H
+#define TITANIC_MOVIE_H
+
+#include "common/list.h"
+#include "video/video_decoder.h"
+#include "titanic/core/list.h"
+#include "titanic/core/resource_key.h"
+#include "titanic/support/avi_surface.h"
+#include "titanic/support/movie_range_info.h"
+
+namespace Titanic {
+
+class CGameObject;
+class CMovie;
+class CSoundManager;
+class CVideoSurface;
+
+class CMovieList : public List<CMovie> {
+public:
+};
+
+class CMovie : public ListItem {
+protected:
+ /**
+ * Adds the movie to the list of currently playing movies
+ */
+ void addToPlayingMovies();
+public:
+ bool _handled;
+ bool _hasVideoFrame;
+ int _field14;
+public:
+ static CMovieList *_playingMovies;
+ static CVideoSurface *_movieSurface;
+
+ /**
+ * Initializes statics
+ */
+ static void init();
+
+ /**
+ * Deinitializes statics
+ */
+ static void deinit();
+public:
+ CMovie();
+ virtual ~CMovie();
+
+ /**
+ * Starts playing the movie
+ */
+ virtual void play(uint flags, CGameObject *obj) = 0;
+
+ /**
+ * Starts playing the movie
+ */
+ virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0;
+
+ /**
+ * Starts playing the movie
+ */
+ virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0;
+
+ /**
+ * Plays a sub-section of a movie
+ */
+ virtual void playClip(const Point &drawPos, uint startFrame, uint endFrame) = 0;
+
+ /**
+ * Stops the movie
+ */
+ virtual void stop() = 0;
+
+ /**
+ * Add a playback event
+ */
+ virtual void addEvent(int frameNumber, CGameObject *obj) = 0;
+
+ /**
+ * Set the current frame number
+ */
+ virtual void setFrame(uint frameNumber) = 0;
+
+ /**
+ * Handle any pending movie events
+ */
+ virtual bool handleEvents(CMovieEventList &events) = 0;
+
+ /**
+ * Return any movie range info associated with the movie
+ */
+ virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0;
+
+ /**
+ * Set the sound manager reference
+ */
+ virtual void setSoundManager(CSoundManager *soundManager) = 0;
+
+ /**
+ * Get the current movie frame
+ */
+ virtual int getFrame() const = 0;
+
+ /**
+ * Set the frame rate for the movie
+ */
+ virtual void setFrameRate(double rate) = 0;
+
+ /**
+ * Creates a duplicate of the movie's frame
+ */
+ virtual Graphics::ManagedSurface *duplicateFrame() const = 0;
+
+ /**
+ * Removes the movie from the list of currently playing movies
+ */
+ void removeFromPlayingMovies();
+
+ /**
+ * Returns true if the movie is currently active
+ */
+ bool isActive() const;
+
+ /**
+ * Returns true if there's a video frame
+ */
+ bool hasVideoFrame();
+};
+
+class OSMovie : public CMovie {
+private:
+ AVISurface _aviSurface;
+ CVideoSurface *_videoSurface;
+ int _field18;
+ int _field24;
+ int _field28;
+ int _field2C;
+private:
+ /**
+ * Called when a movie is started playing
+ */
+ void movieStarted();
+public:
+ OSMovie(const CResourceKey &name, CVideoSurface *surface);
+ virtual ~OSMovie();
+
+ /**
+ * Starts playing the movie
+ */
+ virtual void play(uint flags, CGameObject *obj);
+
+ /**
+ * Starts playing the movie
+ */
+ virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj);
+
+ /**
+ * Starts playing the movie
+ */
+ virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj);
+
+ /**
+ * Plays a sub-section of a movie
+ */
+ virtual void playClip(const Point &drawPos, uint startFrame, uint endFrame);
+
+ /**
+ * Stops the movie
+ */
+ virtual void stop();
+
+ /**
+ * Add a playback event
+ */
+ virtual void addEvent(int eventId, CGameObject *obj);
+
+ /**
+ * Set the current frame number
+ */
+ virtual void setFrame(uint frameNumber);
+
+ /**
+ * Handle any pending movie events
+ */
+ virtual bool handleEvents(CMovieEventList &events);
+
+ /**
+ * Get the current frame number
+ */
+ virtual int getFrame() const;
+
+ /**
+ * Return any movie range info associated with the movie
+ */
+ virtual const CMovieRangeInfoList *getMovieRangeInfo() const;
+
+ /**
+ * Set the sound manager reference
+ */
+ virtual void setSoundManager(CSoundManager *soundManager);
+
+ /**
+ * Set the frame rate for the movie
+ */
+ virtual void setFrameRate(double rate);
+
+ /**
+ * Creates a duplicate of the frame info
+ */
+ virtual Graphics::ManagedSurface *duplicateFrame() const;
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_MOVIE_H */
diff --git a/engines/titanic/support/movie_clip.cpp b/engines/titanic/support/movie_clip.cpp
new file mode 100644
index 0000000000..1f2ef66428
--- /dev/null
+++ b/engines/titanic/support/movie_clip.cpp
@@ -0,0 +1,100 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/movie_clip.h"
+#include "titanic/core/game_object.h"
+
+namespace Titanic {
+
+CMovieClip::CMovieClip(): ListItem(), _startFrame(0), _endFrame(0) {
+}
+
+CMovieClip::CMovieClip(const CString &name, int startFrame, int endFrame):
+ ListItem(), _name(name), _startFrame(startFrame), _endFrame(endFrame) {
+}
+
+void CMovieClip::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(2, indent);
+ file->writeQuotedLine("Clip", indent);
+ file->writeQuotedLine(_name, indent);
+ file->writeNumberLine(_startFrame, indent);
+ file->writeNumberLine(_endFrame, indent);
+
+ ListItem::save(file, indent);
+}
+
+void CMovieClip::load(SimpleFile *file) {
+ int val = file->readNumber();
+
+ switch (val) {
+ case 1:
+ // This should never be used
+ assert(0);
+ break;
+
+ case 2:
+ file->readString();
+ _name = file->readString();
+ _startFrame = file->readNumber();
+ _endFrame = file->readNumber();
+ break;
+
+ default:
+ break;
+ }
+
+ ListItem::load(file);
+}
+
+/*------------------------------------------------------------------------*/
+
+CMovieClip *CMovieClipList::findByName(const Common::String &name) const {
+ for (const_iterator i = begin(); i != end(); ++i) {
+ CMovieClip *clip = *i;
+ if (clip->_name == name)
+ return clip;
+ }
+
+ return nullptr;
+}
+
+bool CMovieClipList::existsByStart(const CString &name, int startFrame) const {
+ for (const_iterator i = begin(); i != end(); ++i) {
+ CMovieClip *clip = *i;
+ if (clip->_startFrame == startFrame && clip->_name == name)
+ return true;
+ }
+
+ return false;
+}
+
+bool CMovieClipList::existsByEnd(const CString &name, int endFrame) const {
+ for (const_iterator i = begin(); i != end(); ++i) {
+ CMovieClip *clip = *i;
+ if (clip->_endFrame == endFrame && clip->_name == name)
+ return true;
+ }
+
+ return false;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/movie_clip.h b/engines/titanic/support/movie_clip.h
new file mode 100644
index 0000000000..513ed4a339
--- /dev/null
+++ b/engines/titanic/support/movie_clip.h
@@ -0,0 +1,92 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_MOVIE_CLIP_H
+#define TITANIC_MOVIE_CLIP_H
+
+#include "titanic/core/list.h"
+
+namespace Titanic {
+
+enum ClipFlag {
+ CLIPFLAG_HAS_END_FRAME = 1,
+ CLIPFLAG_4 = 4,
+ CLIPFLAG_HAS_START_FRAME = 8,
+ CLIPFLAG_PLAY = 0x10
+};
+
+class CGameObject;
+
+/**
+ * Movie clip
+ */
+class CMovieClip : public ListItem {
+private:
+ Common::List<void *> _items;
+ CString _string2;
+ CString _string3;
+public:
+ CString _name;
+ int _startFrame;
+ int _endFrame;
+public:
+ CLASSDEF;
+ CMovieClip();
+ CMovieClip(const CString &name, int startFrame, int endFrame);
+
+ /**
+ * Save the data for the class to file
+ */
+ virtual void save(SimpleFile *file, int indent);
+
+ /**
+ * Load the data for the class from file
+ */
+ virtual void load(SimpleFile *file);
+};
+
+/**
+ * Movie clip list
+ */
+class CMovieClipList: public List<CMovieClip> {
+public:
+ /**
+ * Finds and returns a movie clip in the list by name
+ */
+ CMovieClip *findByName(const Common::String &name) const;
+
+ /**
+ * Returns true if a clip exists in the list with a given name
+ * and starting frame number
+ */
+ bool existsByStart(const CString &name, int startFrame = 0) const;
+
+ /**
+ * Returns true if a clip exists in the list with a given name
+ * and starting frame number
+ */
+ bool existsByEnd(const CString &name, int endFrame = 0) const;
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_MOVIE_CLIP_H */
diff --git a/engines/titanic/support/movie_event.cpp b/engines/titanic/support/movie_event.cpp
new file mode 100644
index 0000000000..5f8a6da019
--- /dev/null
+++ b/engines/titanic/support/movie_event.cpp
@@ -0,0 +1,64 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/movie_event.h"
+#include "titanic/core/game_object.h"
+
+namespace Titanic {
+
+CMovieEvent::CMovieEvent() : ListItem(), _type(MET_PLAY), _startFrame(0),
+ _endFrame(0), _initialFrame(0), _gameObject(nullptr) {
+}
+
+CMovieEvent::CMovieEvent(const CMovieEvent *src) {
+ _type = src->_type;
+ _startFrame = src->_startFrame;
+ _endFrame = src->_endFrame;
+ _initialFrame = src->_initialFrame;
+ _gameObject = src->_gameObject;
+}
+
+void CMovieEvent::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(0, indent);
+ file->writeNumberLine(_startFrame, indent + 1);
+ file->writeNumberLine(_endFrame, indent + 1);
+ error("FIXME: Original save/loaded object pointer");
+ // file->writeNumberLine(_gameObject, indent + 1);
+ file->writeNumberLine(_initialFrame, indent + 1);
+
+ ListItem::save(file, indent);
+}
+
+void CMovieEvent::load(SimpleFile *file) {
+ int val = file->readNumber();
+ if (!val) {
+ _startFrame = file->readNumber();
+ _endFrame = file->readNumber();
+ file->readNumber();
+ error("FIXME: Original save/loaded object pointer");
+ _initialFrame = file->readNumber();
+ }
+
+ ListItem::load(file);
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/movie_event.h b/engines/titanic/support/movie_event.h
new file mode 100644
index 0000000000..af93c76a31
--- /dev/null
+++ b/engines/titanic/support/movie_event.h
@@ -0,0 +1,66 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_MOVIE_EVENT_H
+#define TITANIC_MOVIE_EVENT_H
+
+#include "titanic/core/list.h"
+
+namespace Titanic {
+
+enum MovieEventType { MET_PLAY = 0, MET_MOVIE_END = 1, MET_FRAME = 2 };
+
+class CGameObject;
+
+class CMovieEvent : public ListItem {
+public:
+ MovieEventType _type;
+ int _startFrame;
+ int _endFrame;
+ CGameObject *_gameObject;
+ int _initialFrame;
+public:
+ CMovieEvent();
+ CMovieEvent(const CMovieEvent *src);
+ virtual ~CMovieEvent() {}
+
+ /**
+ * Save the data for the class to file
+ */
+ virtual void save(SimpleFile *file, int indent);
+
+ /**
+ * Load the data for the class from file
+ */
+ virtual void load(SimpleFile *file);
+};
+
+class CMovieEventList : public List<CMovieEvent> {
+};
+
+class CSharedMovieEventList : public Common::List<CMovieEvent> {
+};
+
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_MOVIE_EVENT_H */
diff --git a/engines/titanic/support/movie_manager.cpp b/engines/titanic/support/movie_manager.cpp
new file mode 100644
index 0000000000..bfeb081b5c
--- /dev/null
+++ b/engines/titanic/support/movie_manager.cpp
@@ -0,0 +1,35 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/movie_manager.h"
+#include "titanic/support/movie.h"
+#include "titanic/support/video_surface.h"
+
+namespace Titanic {
+
+CMovie *CMovieManager::createMovie(const CResourceKey &key, CVideoSurface *surface) {
+ CMovie *movie = new OSMovie(key, surface);
+ movie->setSoundManager(_soundManager);
+ return movie;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/movie_manager.h b/engines/titanic/support/movie_manager.h
new file mode 100644
index 0000000000..2920d909b7
--- /dev/null
+++ b/engines/titanic/support/movie_manager.h
@@ -0,0 +1,65 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_MOVIE_MANAGER_H
+#define TITANIC_MOVIE_MANAGER_H
+
+#include "titanic/core/list.h"
+#include "titanic/core/resource_key.h"
+#include "titanic/sound/sound_manager.h"
+
+namespace Titanic {
+
+class CMovie;
+class CVideoSurface;
+
+class CMovieManagerBase {
+public:
+ virtual ~CMovieManagerBase() {}
+
+ /**
+ * Create a new movie and return it
+ */
+ virtual CMovie *createMovie(const CResourceKey &key, CVideoSurface *surface) = 0;
+};
+
+class CMovieManager : public CMovieManagerBase {
+private:
+ CSoundManager *_soundManager;
+public:
+ CMovieManager() : CMovieManagerBase(), _soundManager(nullptr) {}
+ virtual ~CMovieManager() {}
+
+ /**
+ * Create a new movie and return it
+ */
+ virtual CMovie *createMovie(const CResourceKey &key, CVideoSurface *surface);
+
+ /**
+ * Sets the sound manager that will be attached to all created movies
+ */
+ void setSoundManager(CSoundManager *soundManager) { _soundManager = soundManager; }
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_MOVIE_MANAGER_H */
diff --git a/engines/titanic/support/movie_range_info.cpp b/engines/titanic/support/movie_range_info.cpp
new file mode 100644
index 0000000000..634ab1cc62
--- /dev/null
+++ b/engines/titanic/support/movie_range_info.cpp
@@ -0,0 +1,112 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/movie_range_info.h"
+#include "titanic/support/movie_clip.h"
+#include "titanic/core/game_object.h"
+
+namespace Titanic {
+
+CMovieRangeInfo::CMovieRangeInfo() : ListItem(), _startFrame(0), _endFrame(0) {
+}
+
+CMovieRangeInfo::~CMovieRangeInfo() {
+ _events.destroyContents();
+}
+
+CMovieRangeInfo::CMovieRangeInfo(const CMovieRangeInfo *src) : ListItem() {
+ _startFrame = src->_startFrame;
+ _endFrame = src->_endFrame;
+ _initialFrame = src->_initialFrame;
+ _isReversed = src->_isReversed;
+ _isRepeat = src->_isRepeat;
+
+ // Duplicate the events list
+ for (CMovieEventList::const_iterator i = _events.begin();
+ i != _events.end(); ++i) {
+ _events.push_back(new CMovieEvent(*i));
+ }
+}
+
+void CMovieRangeInfo::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(0, indent);
+ file->writeNumberLine(_startFrame, indent + 1);
+ file->writeNumberLine(_endFrame, indent + 1);
+ file->writeNumberLine(_initialFrame, indent + 1);
+ file->writeNumberLine(_isRepeat, indent + 1);
+ file->writeNumberLine(_isReversed, indent + 1);
+ _events.save(file, indent + 1);
+}
+
+void CMovieRangeInfo::load(SimpleFile *file) {
+ int val = file->readNumber();
+ if (!val) {
+ _startFrame = file->readNumber();
+ _endFrame = file->readNumber();
+ _initialFrame = file->readNumber();
+ _isRepeat = file->readNumber();
+ _isReversed = file->readNumber();
+ _events.load(file);
+ }
+}
+
+void CMovieRangeInfo::getMovieEnd(CMovieEventList &list) {
+ for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) {
+ CMovieEvent *movieEvent = *i;
+ if (movieEvent->_type == MET_MOVIE_END)
+ list.push_back(new CMovieEvent(movieEvent));
+ }
+}
+
+void CMovieRangeInfo::getMovieFrame(CMovieEventList &list, int frameNumber) {
+ for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) {
+ CMovieEvent *movieEvent = *i;
+ if (movieEvent->_type == MET_FRAME && movieEvent->_initialFrame == frameNumber)
+ list.push_back(new CMovieEvent(movieEvent));
+ }
+}
+
+void CMovieRangeInfo::process(CGameObject *owner) {
+ int flags = 0;
+ if (_endFrame)
+ flags |= MOVIE_REPEAT;
+ if (_startFrame)
+ flags |= MOVIE_REVERSE;
+
+ for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) {
+ CMovieEvent *movieEvent = *i;
+ if (!movieEvent->_type == MET_PLAY) {
+ flags |= CLIPFLAG_PLAY;
+ break;
+ }
+ }
+
+ owner->playMovie(_startFrame, _endFrame, _initialFrame, flags);
+
+ for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) {
+ CMovieEvent *movieEvent = *i;
+ if (movieEvent->_type == MET_PLAY)
+ owner->movieEvent(movieEvent->_initialFrame);
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/movie_range_info.h b/engines/titanic/support/movie_range_info.h
new file mode 100644
index 0000000000..6b13fbadb5
--- /dev/null
+++ b/engines/titanic/support/movie_range_info.h
@@ -0,0 +1,81 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_MOVIE_RANGE_INFO_H
+#define TITANIC_MOVIE_RANGE_INFO_H
+
+#include "video/video_decoder.h"
+#include "titanic/core/list.h"
+#include "titanic/core/resource_key.h"
+#include "titanic/support/movie_event.h"
+
+namespace Titanic {
+
+class CGameObject;
+
+class CMovieRangeInfo : public ListItem {
+public:
+ int _startFrame;
+ int _endFrame;
+ int _initialFrame;
+ bool _isReversed;
+ bool _isRepeat;
+ CMovieEventList _events;
+public:
+ CMovieRangeInfo();
+ CMovieRangeInfo(const CMovieRangeInfo *src);
+ virtual ~CMovieRangeInfo();
+
+ /**
+ * Save the data for the class to file
+ */
+ virtual void save(SimpleFile *file, int indent);
+
+ /**
+ * Load the data for the class from file
+ */
+ virtual void load(SimpleFile *file);
+
+ /**
+ * Adds an event to the events list
+ */
+ void addEvent(CMovieEvent *movieEvent) { _events.push_back(movieEvent); }
+
+ /**
+ * Get any movie end events for the range
+ */
+ void getMovieEnd(CMovieEventList &list);
+
+ /**
+ * Get any movie frame events for a specified frame number
+ */
+ void getMovieFrame(CMovieEventList &list, int frameNumber);
+
+ void process(CGameObject *owner);
+};
+
+class CMovieRangeInfoList : public List<CMovieRangeInfo> {
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_MOVIE_RANGE_INFO_H */
diff --git a/engines/titanic/support/proximity.cpp b/engines/titanic/support/proximity.cpp
new file mode 100644
index 0000000000..4a832b9217
--- /dev/null
+++ b/engines/titanic/support/proximity.cpp
@@ -0,0 +1,37 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/proximity.h"
+#include "titanic/true_talk/tt_talker.h"
+
+namespace Titanic {
+
+CProximity::CProximity() : _field4(0), _field8(100), _fieldC(0),
+ _speechHandle(-1), _field14(0), _field18(0), _field1C(0x3FF00000),
+ _field20(0), _field24(10), _field28(0), _field2C(0),
+ _field30(0x3F000000), _field34(0), _double1(0.0), _double2(0.0),
+ _double3(0.0), _field44(0), _field48(0), _field4C(0),
+ _field50(0), _field54(0), _field58(0), _field5C(0),
+ _field60(0), _method1(nullptr), _talker(nullptr), _field6C(0) {
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/proximity.h b/engines/titanic/support/proximity.h
new file mode 100644
index 0000000000..935e2e6b1c
--- /dev/null
+++ b/engines/titanic/support/proximity.h
@@ -0,0 +1,69 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_PROXIMITY_H
+#define TITANIC_PROXIMITY_H
+
+#include "common/scummsys.h"
+
+namespace Titanic {
+
+typedef bool (*CProximityFn)(int val);
+
+class TTtalker;
+
+class CProximity {
+public:
+ int _field4;
+ int _field8;
+ int _fieldC;
+ int _speechHandle;
+ int _field14;
+ int _field18;
+ int _field1C;
+ int _field20;
+ int _field24;
+ int _field28;
+ uint32 _field2C;
+ int _field30;
+ int _field34;
+ double _double1;
+ double _double2;
+ double _double3;
+ int _field44;
+ int _field48;
+ int _field4C;
+ int _field50;
+ int _field54;
+ int _field58;
+ int _field5C;
+ int _field60;
+ CProximityFn _method1;
+ TTtalker *_talker;
+ int _field6C;
+public:
+ CProximity();
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_PROXIMITY_H */
diff --git a/engines/titanic/support/rect.cpp b/engines/titanic/support/rect.cpp
new file mode 100644
index 0000000000..5fce4402cb
--- /dev/null
+++ b/engines/titanic/support/rect.cpp
@@ -0,0 +1,44 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/rect.h"
+
+namespace Titanic {
+
+void Rect::combine(const Rect &r) {
+ if (isEmpty() || r.isEmpty())
+ return;
+
+ Common::Rect::extend(r);
+}
+
+void Rect::constrain(const Rect &r) {
+ if (!isEmpty()) {
+ if (r.isEmpty()) {
+ clear();
+ } else {
+ Common::Rect::clip(r);
+ }
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/rect.h b/engines/titanic/support/rect.h
new file mode 100644
index 0000000000..1661711870
--- /dev/null
+++ b/engines/titanic/support/rect.h
@@ -0,0 +1,61 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_RECT_H
+#define TITANIC_RECT_H
+
+#include "common/rect.h"
+
+namespace Titanic {
+
+typedef Common::Point Point;
+
+class Rect : public Common::Rect {
+public:
+ Rect() : Common::Rect() {}
+ Rect(int16 w, int16 h) : Common::Rect(w, h) {}
+ Rect(int16 x1, int16 y1, int16 x2, int16 y2) : Common::Rect(x1, y1, x2, y2) {}
+
+ /**
+ * Returns the top/left corner of the rect as a point
+ */
+ operator const Point() { return Point(left, top); }
+
+ /**
+ * Clear the rect
+ */
+ void clear() { left = top = right = bottom = 0; }
+
+ /**
+ * Combine another rect into this one
+ */
+ void combine(const Rect &r);
+
+ /**
+ * Constrains/clips to the intersection area of the given rect
+ */
+ void constrain(const Rect &r);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_RECT_H */
diff --git a/engines/titanic/support/screen_manager.cpp b/engines/titanic/support/screen_manager.cpp
new file mode 100644
index 0000000000..d795f78764
--- /dev/null
+++ b/engines/titanic/support/screen_manager.cpp
@@ -0,0 +1,326 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/screen_manager.h"
+#include "titanic/titanic.h"
+#include "titanic/support/video_surface.h"
+
+namespace Titanic {
+
+CScreenManager *CScreenManager::_screenManagerPtr;
+CScreenManager *CScreenManager::_currentScreenManagerPtr;
+
+CScreenManager::CScreenManager(TitanicEngine *vm): _vm(vm) {
+ _screenManagerPtr = nullptr;
+ _currentScreenManagerPtr = nullptr;
+
+ _frontRenderSurface = nullptr;
+ _mouseCursor = nullptr;
+ _textCursor = nullptr;
+ _inputHandler = nullptr;
+ _fontNumber = 0;
+ // TODO: Further initialization
+
+ _screenManagerPtr = this;
+}
+
+CScreenManager::~CScreenManager() {
+ _screenManagerPtr = nullptr;
+}
+
+void CScreenManager::setWindowHandle(int v) {
+ // Not needed
+}
+
+bool CScreenManager::resetWindowHandle(int v) {
+ hideCursor();
+ return true;
+}
+
+CScreenManager *CScreenManager::setCurrent() {
+ if (!_currentScreenManagerPtr)
+ _currentScreenManagerPtr = _screenManagerPtr;
+
+ return _currentScreenManagerPtr;
+}
+
+void CScreenManager::setSurfaceBounds(SurfaceNum surfaceNum, const Rect &r) {
+ if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size())
+ _backSurfaces[surfaceNum]._bounds = r;
+}
+
+int CScreenManager::setFontNumber(int fontNumber) {
+ int oldFontNumber = _fontNumber;
+ _fontNumber = fontNumber;
+ return oldFontNumber;
+}
+
+/*------------------------------------------------------------------------*/
+
+OSScreenManager::OSScreenManager(TitanicEngine *vm): CScreenManager(vm),
+ _directDrawManager(vm, false) {
+ _field48 = 0;
+ _field4C = 0;
+ _field50 = 0;
+ _field54 = 0;
+}
+
+OSScreenManager::~OSScreenManager() {
+ destroyFrontAndBackBuffers();
+ delete _mouseCursor;
+ delete _textCursor;
+}
+
+void OSScreenManager::setMode(int width, int height, int bpp, uint numBackSurfaces, bool flag2) {
+ assert(bpp == 16);
+ destroyFrontAndBackBuffers();
+ _directDrawManager.initVideo(width, height, bpp, numBackSurfaces);
+
+ _vm->_screen->create(width, height, g_system->getScreenFormat());
+ _frontRenderSurface = new OSVideoSurface(this, nullptr);
+ _frontRenderSurface->setSurface(this, _directDrawManager._mainSurface);
+
+ _backSurfaces.resize(numBackSurfaces);
+ for (uint idx = 0; idx < numBackSurfaces; ++idx) {
+ _backSurfaces[idx]._surface = new OSVideoSurface(this, nullptr);
+ _backSurfaces[idx]._surface->setSurface(this, _directDrawManager._backSurfaces[idx]);
+ }
+
+ // Load fonts
+ _fonts[0].load(149);
+ _fonts[1].load(151);
+ _fonts[2].load(152);
+ _fonts[3].load(153);
+
+ // Load the cursors
+ loadCursors();
+}
+
+void OSScreenManager::drawCursors() {
+ // The original did both text and mouse cursor drawing here.
+ // For ScummVM, we only need to worry about the text cursor
+ _textCursor->draw();
+}
+
+DirectDrawSurface *OSScreenManager::getDDSurface(SurfaceNum surfaceNum) {
+ if (surfaceNum == SURFACE_PRIMARY)
+ return _directDrawManager._mainSurface;
+ else if (surfaceNum < (int)_backSurfaces.size())
+ return _directDrawManager._backSurfaces[surfaceNum];
+ else
+ return nullptr;
+}
+
+CVideoSurface *OSScreenManager::lockSurface(SurfaceNum surfaceNum) {
+ CVideoSurface *surface = getSurface(surfaceNum);
+ surface->lock();
+ return surface;
+}
+
+void OSScreenManager::unlockSurface(CVideoSurface *surface) {
+ surface->unlock();
+}
+
+CVideoSurface *OSScreenManager::getSurface(SurfaceNum surfaceNum) const {
+ if (surfaceNum == SURFACE_PRIMARY)
+ return _frontRenderSurface;
+ else if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size())
+ return _backSurfaces[surfaceNum]._surface;
+ else
+ return nullptr;
+}
+
+void OSScreenManager::fillRect(SurfaceNum surfaceNum, Rect *rect, byte r, byte g, byte b) {
+ DirectDrawSurface *surface = getDDSurface(surfaceNum);
+ if (!surface)
+ return;
+
+ // If bounds are provided, clip and use them. Otherwise, use entire surface area
+ Rect surfaceRect(0, 0, surface->getWidth(), surface->getHeight());
+ Rect tempRect;
+
+ if (rect) {
+ tempRect = *rect;
+ tempRect.clip(surfaceRect);
+ } else {
+ tempRect = surfaceRect;
+ }
+
+ if (tempRect.isValidRect())
+ surface->fillRect(&tempRect, r, g, b);
+}
+
+void OSScreenManager::blitFrom(SurfaceNum surfaceNum, CVideoSurface *src,
+ const Point *destPos, const Rect *srcRect) {
+ // Get the dest surface
+ CVideoSurface *destSurface = _frontRenderSurface;
+ if (surfaceNum < -1)
+ return;
+ if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size())
+ destSurface = _backSurfaces[surfaceNum]._surface;
+ if (!destSurface->hasSurface())
+ return;
+
+ Point destPoint = destPos ? *destPos : Point(0, 0);
+ Rect srcBounds = srcRect ? *srcRect : Rect(0, 0, src->getWidth(), src->getHeight());
+ Rect *bounds = &srcBounds;
+ Rect rect2;
+
+ if (surfaceNum >= 0 && !_backSurfaces[surfaceNum]._bounds.isEmpty()) {
+ // Perform clipping to the bounds of the back surface
+ rect2 = srcBounds;
+ rect2.translate(-srcBounds.left, -srcBounds.top);
+ rect2.translate(destPoint.x, destPoint.y);
+ rect2.constrain(_backSurfaces[surfaceNum]._bounds);
+
+ rect2.translate(-destPoint.x, -destPoint.y);
+ rect2.translate(srcBounds.left, srcBounds.top);
+
+ if (rect2.isEmpty())
+ return;
+
+ destPoint.x += rect2.left - srcBounds.left;
+ destPoint.y += rect2.top - srcBounds.top;
+ bounds = &rect2;
+ }
+
+ if (!bounds->isEmpty())
+ destSurface->blitFrom(destPoint, src, bounds);
+}
+
+void OSScreenManager::blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSurface *src, int v) {
+ // Get the dest surface
+ CVideoSurface *destSurface = _frontRenderSurface;
+ if (surfaceNum < -1)
+ return;
+ if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size())
+ destSurface = _backSurfaces[surfaceNum]._surface;
+ if (!destSurface->hasSurface())
+ return;
+
+ if (!rect->isEmpty())
+ destSurface->blitFrom(Point(rect->left, rect->top), src, rect);
+}
+
+int OSScreenManager::writeString(int surfaceNum, const Rect &destRect,
+ int yOffset, const CString &str, CTextCursor *textCursor) {
+ CVideoSurface *surface;
+ Rect bounds;
+
+ if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) {
+ surface = _backSurfaces[surfaceNum]._surface;
+ bounds = _backSurfaces[surfaceNum]._bounds;
+ } else if (surfaceNum == -1) {
+ surface = _frontRenderSurface;
+ bounds = Rect(0, 0, surface->getWidth(), surface->getHeight());
+ } else {
+ return -1;
+ }
+
+ return _fonts[_fontNumber].writeString(surface, destRect, bounds,
+ yOffset, str, textCursor);
+}
+
+int OSScreenManager::writeString(int surfaceNum, const Rect &srcRect,
+ const Rect &destRect, const CString &str, CTextCursor *textCursor) {
+ // TODO
+ return 0;
+}
+
+void OSScreenManager::setFontColor(byte r, byte g, byte b) {
+ _fonts[_fontNumber].setColor(r, g, b);
+}
+
+int OSScreenManager::getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const {
+ return _fonts[_fontNumber].getTextBounds(str, maxWidth, sizeOut);
+}
+
+int OSScreenManager::getFontHeight() const {
+ return _fonts[_fontNumber]._fontHeight;
+}
+
+int OSScreenManager::stringWidth(const CString &str) {
+ return _fonts[_fontNumber].stringWidth(str);
+}
+
+void OSScreenManager::frameRect(SurfaceNum surfaceNum, const Rect &rect, byte r, byte g, byte b) {
+ Rect top(rect.left, rect.top, rect.right, rect.top + 1);
+ fillRect(surfaceNum, &top, r, g, b);
+ Rect bottom(rect.left, rect.bottom - 1, rect.right, rect.bottom);
+ fillRect(surfaceNum, &bottom, r, g, b);
+ Rect left(rect.left, rect.top, rect.left + 1, rect.bottom);
+ fillRect(surfaceNum, &left, r, g, b);
+ Rect right(rect.right - 1, rect.top, rect.right, rect.bottom);
+}
+
+void OSScreenManager::clearSurface(SurfaceNum surfaceNum, Rect *bounds) {
+ if (surfaceNum == SURFACE_PRIMARY)
+ _directDrawManager._mainSurface->fill(bounds, 0);
+ else if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size())
+ _directDrawManager._backSurfaces[surfaceNum]->fill(bounds, 0);
+}
+
+void OSScreenManager::resizeSurface(CVideoSurface *surface, int width, int height) {
+ DirectDrawSurface *ddSurface = _directDrawManager.createSurface(width, height, 0);
+ surface->setSurface(this, ddSurface);
+}
+
+CVideoSurface *OSScreenManager::createSurface(int w, int h) {
+ DirectDrawSurface *ddSurface = _directDrawManager.createSurface(w, h, 0);
+ return new OSVideoSurface(this, ddSurface);
+}
+
+CVideoSurface *OSScreenManager::createSurface(const CResourceKey &key) {
+ return new OSVideoSurface(this, key);
+}
+
+void OSScreenManager::showCursor() {
+ CScreenManager::_screenManagerPtr->_mouseCursor->show();
+}
+
+void OSScreenManager::hideCursor() {
+ CScreenManager::_screenManagerPtr->_mouseCursor->hide();
+}
+
+void OSScreenManager::destroyFrontAndBackBuffers() {
+ delete _frontRenderSurface;
+ _frontRenderSurface = nullptr;
+
+ for (uint idx = 0; idx < _backSurfaces.size(); ++idx)
+ delete _backSurfaces[idx]._surface;
+ _backSurfaces.clear();
+}
+
+void OSScreenManager::loadCursors() {
+ if (_mouseCursor) {
+ hideCursor();
+ delete _mouseCursor;
+ }
+ _mouseCursor = new CMouseCursor(this);
+ showCursor();
+
+ if (!_textCursor) {
+ _textCursor = new CTextCursor(this);
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/screen_manager.h b/engines/titanic/support/screen_manager.h
new file mode 100644
index 0000000000..0736f1393c
--- /dev/null
+++ b/engines/titanic/support/screen_manager.h
@@ -0,0 +1,395 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_SCREEN_MANAGER_H
+#define TITANIC_SCREEN_MANAGER_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "titanic/support/direct_draw.h"
+#include "titanic/support/font.h"
+#include "titanic/input_handler.h"
+#include "titanic/support/mouse_cursor.h"
+#include "titanic/support/text_cursor.h"
+#include "titanic/support/video_surface.h"
+#include "titanic/core/resource_key.h"
+
+namespace Titanic {
+
+/**
+ * The original used page flipping with one primary and one back buffer.
+ * Since we don't need that in ScummVM, the back buffer number below is
+ * remapped to the primary surface
+ */
+enum SurfaceNum {
+ SURFACE_PRIMARY = -1, // Surface 0
+ SURFACE_BACKBUFFER = -1 // Surface -1
+};
+
+class TitanicEngine;
+
+class CScreenManager {
+ struct VideoSurfaceEntry {
+ CVideoSurface *_surface;
+ Rect _bounds;
+ };
+protected:
+ TitanicEngine *_vm;
+public:
+ static CScreenManager *_screenManagerPtr;
+ static CScreenManager *_currentScreenManagerPtr;
+
+ /**
+ * Set the current screen manager
+ */
+ static CScreenManager *setCurrent();
+public:
+ Common::Array<VideoSurfaceEntry> _backSurfaces;
+ CVideoSurface *_frontRenderSurface;
+ CMouseCursor *_mouseCursor;
+ CTextCursor *_textCursor;
+ CInputHandler *_inputHandler;
+ int _fontNumber;
+public:
+ CScreenManager(TitanicEngine *vm);
+ virtual ~CScreenManager();
+
+ void fn1() {}
+ void fn2() {}
+
+ virtual void setWindowHandle(int v);
+ virtual bool resetWindowHandle(int v);
+
+ /**
+ * Sets the video mode
+ */
+ virtual void setMode(int width, int height, int bpp, uint numBackSurfaces, bool flag2) = 0;
+
+ /**
+ * Handles drawing the cursors
+ */
+ virtual void drawCursors() = 0;
+
+ /**
+ * Locks a specified surface number for access and returns a pointer to it
+ */
+ virtual CVideoSurface *lockSurface(SurfaceNum surfaceNum) = 0;
+
+ /**
+ * Unlocks a previously locked surface
+ */
+ virtual void unlockSurface(CVideoSurface *surface) = 0;
+
+ /**
+ * Gets a specified surface number
+ */
+ virtual CVideoSurface *getSurface(SurfaceNum surfaceNum) const = 0;
+
+ /**
+ * Return the front render surface
+ */
+ virtual CVideoSurface *getFrontRenderSurface() const = 0;
+
+ /**
+ * Fill an area with a specific color
+ */
+ virtual void fillRect(SurfaceNum surfaceNum, Rect *rect, byte r, byte g, byte b) = 0;
+
+ /**
+ * Blits a surface onto one of the screen surfaces
+ */
+ virtual void blitFrom(SurfaceNum surfaceNum, CVideoSurface *src, const Point *destPos = nullptr,
+ const Rect *srcRect = nullptr) = 0;
+
+ /**
+ * Blits a surface onto one of the screen surfaces
+ */
+ virtual void blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSurface *src, int v = 0) = 0;
+
+ /**
+ * Write a string
+ * @param surfaceNum Destination surface
+ * @param destRect Bounds within dest surface
+ * @param yOffset Y offset for drawing, to allow for parts of
+ * the text to be scrolled off-screen
+ * @param str Line or lines to write
+ * @param textCursor Optional text cursor pointer
+ */
+ virtual int writeString(int surfaceNum, const Rect &destRect,
+ int yOffset, const CString &str, CTextCursor *textCursor) = 0;
+
+ /**
+ * Write a string
+ * @param surfaceNum Destination surface
+ * @param srcRect Drawing area
+ * @param destRect Bounds of dest surface
+ * @param str Line or lines to write
+ * @param textCursor Optional text cursor pointer
+ */
+ virtual int writeString(int surfaceNum, const Rect &srcRect,
+ const Rect &destRect, const CString &str, CTextCursor *textCursor) = 0;
+
+ /**
+ * Set the font color
+ */
+ virtual void setFontColor(byte r, byte g, byte b) = 0;
+
+ /**
+ * Get the text area a string will fit into
+ * @param str String
+ * @param maxWidth Maximum width in pixels
+ * @param sizeOut Optional pointer to output size
+ * @returns Required height
+ */
+ virtual int getTextBounds(const CString &str, int maxWidth, Point *sizeOut = nullptr) const = 0;
+
+ /**
+ * Get the current font height
+ */
+ virtual int getFontHeight() const = 0;
+
+ /**
+ * Returns the width of a given string in pixels
+ */
+ virtual int stringWidth(const CString &str) = 0;
+
+ /**
+ * Draws a frame enclosing the specified area
+ */
+ virtual void frameRect(SurfaceNum surfaceNum, const Rect &rect, byte r, byte g, byte b) = 0;
+
+ /**
+ * Clear a portion of a specified surface
+ */
+ virtual void clearSurface(SurfaceNum surfaceNum, Rect *_bounds) = 0;
+
+ /**
+ * Resize the passed surface
+ */
+ virtual void resizeSurface(CVideoSurface *surface, int width, int height) = 0;
+
+ /**
+ * Creates a surface of a given size
+ */
+ virtual CVideoSurface *createSurface(int w, int h) = 0;
+
+ /**
+ * Creates a surface from a specified resource
+ */
+ virtual CVideoSurface *createSurface(const CResourceKey &key) = 0;
+
+ /**
+ * Get the top-left corner of the screen in global screen co-ordinates
+ * For ScummVM, this is always (0, 0), even in Windowed mode
+ */
+ virtual Point getScreenTopLeft() { return Point(0, 0); }
+
+ /**
+ * Waits for a vertical screen sync
+ * For ScummVM, this can be safely ignored
+ */
+ virtual void waitForVSync() {}
+
+ /**
+ * Show the mouse cursor
+ */
+ virtual void showCursor() = 0;
+
+ /**
+ * Hide the mouse cursor
+ */
+ virtual void hideCursor() = 0;
+
+ /**
+ * Set drawing bounds for a specified surface
+ */
+ void setSurfaceBounds(SurfaceNum surfaceNum, const Rect &r);
+
+ /**
+ * Set the current font number
+ */
+ int setFontNumber(int fontNumber);
+};
+
+class OSScreenManager: CScreenManager {
+private:
+ DirectDrawManager _directDrawManager;
+
+ /**
+ * Frees any surface buffers
+ */
+ void destroyFrontAndBackBuffers();
+
+ /**
+ * Load game cursors
+ */
+ void loadCursors();
+
+ /**
+ * Gets an underlying surface
+ */
+ DirectDrawSurface *getDDSurface(SurfaceNum surfaceNum);
+public:
+ int _field48;
+ int _field4C;
+ int _field50;
+ int _field54;
+ STFont _fonts[4];
+public:
+ OSScreenManager(TitanicEngine *vm);
+ virtual ~OSScreenManager();
+
+ /**
+ * Sets the video mode
+ */
+ virtual void setMode(int width, int height, int bpp, uint numBackSurfaces, bool flag2);
+
+ /**
+ * Handles drawing the cursors
+ */
+ virtual void drawCursors();
+
+ /**
+ * Locks a specified surface number for access and returns a pointer to it
+ */
+ virtual CVideoSurface *lockSurface(SurfaceNum surfaceNum);
+
+ /**
+ * Unlocks a previously locked surface
+ */
+ virtual void unlockSurface(CVideoSurface *surface);
+
+ /**
+ * Gets a specified surface number
+ */
+ virtual CVideoSurface *getSurface(SurfaceNum surfaceNum) const;
+
+ /**
+ * Return the front render surface
+ */
+ virtual CVideoSurface *getFrontRenderSurface() const {
+ return _frontRenderSurface;
+ }
+
+
+ /**
+ * Fill an area with a specific color
+ */
+ virtual void fillRect(SurfaceNum surfaceNum, Rect *rect, byte r, byte g, byte b);
+
+ /**
+ * Blits a surface onto one of the screen surfaces
+ */
+ virtual void blitFrom(SurfaceNum surfaceNum, CVideoSurface *src, const Point *destPos,
+ const Rect *srcRect = nullptr);
+
+ /**
+ * Blits a surface onto one of the screen surfaces
+ */
+ virtual void blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSurface *src, int v = 0);
+
+ /**
+ * Write a string
+ * @param surfaceNum Destination surface
+ * @param destRect Bounds within dest surface
+ * @param yOffset Y offset for drawing, to allow for parts of
+ * the text to be scrolled off-screen
+ * @param str Line or lines to write
+ * @param textCursor Optional text cursor pointer
+ */
+ virtual int writeString(int surfaceNum, const Rect &destRect,
+ int yOffset, const CString &str, CTextCursor *textCursor);
+
+ /**
+ * Write a string
+ * @param surfaceNum Destination surface
+ * @param srcRect Drawing area
+ * @param destRect Bounds of dest surface
+ * @param str Line or lines to write
+ * @param textCursor Optional text cursor pointer
+ */
+ virtual int writeString(int surfaceNum, const Rect &srcRect,
+ const Rect &destRect, const CString &str, CTextCursor *textCursor);
+
+ /**
+ * Set the font color
+ */
+ virtual void setFontColor(byte r, byte g, byte b);
+
+ /**
+ * Get the text area a string will fit into
+ * @param str String
+ * @param maxWidth Maximum width in pixels
+ * @param sizeOut Optional pointer to output size
+ * @returns Required height
+ */
+ virtual int getTextBounds(const CString &str, int maxWidth, Point *sizeOut = nullptr) const;
+
+ /**
+ * Get the current font height
+ */
+ virtual int getFontHeight() const;
+
+ /**
+ * Returns the width of a given string in pixels
+ */
+ virtual int stringWidth(const CString &str);
+
+ /**
+ * Draws a frame enclosing the specified area
+ */
+ virtual void frameRect(SurfaceNum surfaceNum, const Rect &rect, byte r, byte g, byte b);
+
+ /**
+ * Clear a portion of the screen surface
+ */
+ virtual void clearSurface(SurfaceNum surfaceNum, Rect *bounds);
+
+ /**
+ * Resize the passed surface
+ */
+ virtual void resizeSurface(CVideoSurface *surface, int width, int height);
+
+ /**
+ * Creates a surface of a given size
+ */
+ virtual CVideoSurface *createSurface(int w, int h);
+
+ /**
+ * Creates a surface from a specified resource
+ */
+ virtual CVideoSurface *createSurface(const CResourceKey &key);
+
+ /**
+ * Show the mouse cursor
+ */
+ virtual void showCursor();
+
+ /**
+ * Hide the mouse cursor
+ */
+ virtual void hideCursor();
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_SCREEN_MANAGER_H */
diff --git a/engines/titanic/support/simple_file.cpp b/engines/titanic/support/simple_file.cpp
new file mode 100644
index 0000000000..35b2e28e4a
--- /dev/null
+++ b/engines/titanic/support/simple_file.cpp
@@ -0,0 +1,512 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/util.h"
+#include "titanic/support/simple_file.h"
+
+namespace Titanic {
+
+CString readStringFromStream(Common::SeekableReadStream *s) {
+ CString result;
+ char c;
+ while ((c = s->readByte()) != '\0')
+ result += c;
+
+ return result;
+}
+
+/*------------------------------------------------------------------------*/
+
+bool File::open(const Common::String &filename) {
+ if (!Common::File::open(filename))
+ error("Could not open file - %s", filename.c_str());
+ return true;
+}
+
+/*------------------------------------------------------------------------*/
+
+SimpleFile::SimpleFile(): _inStream(nullptr), _outStream(nullptr), _lineCount(1) {
+}
+
+SimpleFile::~SimpleFile() {
+ close();
+}
+
+void SimpleFile::open(Common::SeekableReadStream *stream) {
+ close();
+ _inStream = stream;
+}
+
+void SimpleFile::open(Common::OutSaveFile *stream) {
+ close();
+ _outStream = stream;
+}
+
+void SimpleFile::close() {
+ if (_outStream) {
+ _outStream->finalize();
+ delete _outStream;
+ _outStream = nullptr;
+ }
+
+ if (_inStream) {
+ delete _inStream;
+ _inStream = nullptr;
+ }
+}
+
+void SimpleFile::safeRead(void *dst, size_t count) {
+ if (unsafeRead(dst, count) != count)
+ error("Could not read %d bytes", (int)count);
+}
+
+size_t SimpleFile::unsafeRead(void *dst, size_t count) {
+ assert(_inStream);
+ return _inStream->read(dst, count);
+}
+
+size_t SimpleFile::write(const void *src, size_t count) const {
+ assert(_outStream);
+ return _outStream->write(src, count);
+}
+
+void SimpleFile::seek(int offset, int origin) {
+ assert(_inStream);
+ _inStream->seek(offset, origin);
+}
+
+byte SimpleFile::readByte() {
+ byte b;
+ safeRead(&b, 1);
+ return b;
+}
+
+uint SimpleFile::readUint16LE() {
+ uint val;
+ safeRead(&val, 2);
+ return READ_LE_UINT16(&val);
+}
+
+uint SimpleFile::readUint32LE() {
+ uint val;
+ safeRead(&val, 4);
+ return READ_LE_UINT32(&val);
+}
+
+CString SimpleFile::readString() {
+ char c;
+ CString result;
+ bool backslashFlag = false;
+
+ // First skip any spaces
+ do {
+ safeRead(&c, 1);
+ } while (Common::isSpace(c));
+
+ // Ensure we've found a starting quote for the string
+ if (c != '"')
+ error("Could not find starting quote");
+
+ bool endFlag = false;
+ while (!endFlag) {
+ // Read the next character
+ safeRead(&c, 1);
+
+ if (backslashFlag) {
+ backslashFlag = false;
+ switch (c) {
+ case 'n':
+ result += '\n';
+ break;
+ case 'r':
+ result += '\r';
+ break;
+ case '\t':
+ result += '\t';
+ break;
+ default:
+ result += c;
+ break;
+ }
+ } else {
+ switch (c) {
+ case '"':
+ endFlag = true;
+ break;
+ case '\\':
+ backslashFlag = true;
+ break;
+ default:
+ result += c;
+ break;
+ }
+ }
+ }
+
+ // Return the string
+ return result;
+}
+
+int SimpleFile::readNumber() {
+ char c;
+ int result = 0;
+ bool minusFlag = false;
+
+ // First skip any spaces
+ do {
+ safeRead(&c, 1);
+ } while (Common::isSpace(c));
+
+ // Check for prefix sign
+ if (c == '+' || c == '-') {
+ minusFlag = c == '-';
+ safeRead(&c, 1);
+ }
+
+ // Read in the number
+ if (!Common::isDigit(c))
+ error("Invalid number");
+
+ while (Common::isDigit(c)) {
+ result = result * 10 + (c - '0');
+ safeRead(&c, 1);
+ }
+
+ // Finally, if it's a minus value, then negate it
+ if (minusFlag)
+ result = -result;
+
+ return result;
+}
+
+double SimpleFile::readFloat() {
+ char c;
+ Common::String result;
+
+ // First skip any spaces
+ do {
+ safeRead(&c, 1);
+ } while (Common::isSpace(c));
+
+ // Check for prefix sign
+ if (c == '+' || c == '-') {
+ result += c;
+ safeRead(&c, 1);
+ }
+
+ // Read in the number
+ if (!Common::isDigit(c))
+ error("Invalid number");
+
+ while (Common::isDigit(c) || c == '.') {
+ result += c;
+ safeRead(&c, 1);
+ }
+
+ // Convert to a float and return it
+ float floatValue;
+ sscanf(result.c_str(), "%f", &floatValue);
+
+ return floatValue;
+}
+
+Point SimpleFile::readPoint() {
+ Point pt;
+ pt.x = readNumber();
+ pt.y = readNumber();
+
+ return pt;
+}
+
+Rect SimpleFile::readRect() {
+ Rect r;
+ r.left = readNumber();
+ r.top = readNumber();
+ r.right = readNumber();
+ r.bottom = readNumber();
+
+ return r;
+}
+
+Rect SimpleFile::readBounds() {
+ Rect r;
+ r.left = readNumber();
+ r.top = readNumber();
+ r.setWidth(readNumber());
+ r.setHeight(readNumber());
+
+ return r;
+}
+
+void SimpleFile::readBuffer(char *buffer, size_t count) {
+ CString tempString = readString();
+ if (buffer) {
+ strncpy(buffer, tempString.c_str(), count);
+ buffer[count - 1] = '\0';
+ }
+}
+
+void SimpleFile::writeUint16LE(uint val) {
+ byte lo = val & 0xff;
+ byte hi = (val >> 8) & 0xff;
+ write(&lo, 1);
+ write(&hi, 1);
+}
+
+void SimpleFile::writeUint32LE(uint val) {
+ uint16 lo = val & 0xffff;
+ uint16 hi = (val >> 16) & 0xff;
+ writeUint16LE(lo);
+ writeUint16LE(hi);
+}
+
+void SimpleFile::writeLine(const CString &str) const {
+ write(str.c_str(), str.size());
+ write("\r\n", 2);
+}
+
+void SimpleFile::writeString(const CString &str) const {
+ if (str.empty())
+ return;
+
+ const char *msgP = str.c_str();
+ char c;
+
+ while ((c = *msgP++) != '\0') {
+ switch (c) {
+ case '\r':
+ write("\\r", 2);
+ break;
+ case '\n':
+ write("\\n", 2);
+ break;
+ case '\t':
+ write("\\t", 2);
+ break;
+ case '\"':
+ write("\\\"", 2);
+ break;
+ case '\\':
+ write("\\\\", 2);
+ break;
+ case '{':
+ write("\\{", 2);
+ break;
+ case '}':
+ write("\\}", 2);
+ break;
+ default:
+ write(&c, 1);
+ break;
+ }
+ }
+}
+
+void SimpleFile::writeQuotedString(const CString &str) const {
+ write("\"", 1);
+ writeString(str);
+ write("\" ", 2);
+}
+
+void SimpleFile::writeQuotedLine(const CString &str, int indent) const {
+ writeIndent(indent);
+ writeQuotedString(str);
+ write("\n", 1);
+}
+
+void SimpleFile::writeNumber(int val) const {
+ CString str = CString::format("%d ", val);
+ write(str.c_str(), str.size());
+}
+
+void SimpleFile::writeNumberLine(int val, int indent) const {
+ writeIndent(indent);
+ writeNumber(val);
+ write("\n", 1);
+}
+
+void SimpleFile::writeFloat(double val) const {
+ Common::String valStr = Common::String::format("%f ", val);
+ write(valStr.c_str(), valStr.size());
+}
+
+void SimpleFile::writeFloatLine(double val, int indent) const {
+ writeIndent(indent);
+ writeFloat(val);
+ write("\n", 1);
+}
+
+void SimpleFile::writePoint(const Point &pt, int indent) const {
+ writeIndent(indent);
+ writeNumber(pt.x);
+ writeNumber(pt.y);
+ write("\n", 1);
+}
+
+void SimpleFile::writeRect(const Rect &r, int indent) const {
+ writePoint(Point(r.left, r.top), indent);
+ writePoint(Point(r.right, r.bottom), indent);
+}
+
+void SimpleFile::writeBounds(const Rect &r, int indent) const {
+ writePoint(Point(r.left, r.top), indent);
+ writePoint(Point(r.width(), r.height()), indent);
+}
+
+void SimpleFile::writeFormat(const char *format, ...) const {
+ // Convert the format specifier and params to a string
+ va_list va;
+ va_start(va, format);
+ CString line = CString::vformat(format, va);
+ va_end(va);
+
+ // Write out the string
+ write(format, strlen(format));
+}
+
+void SimpleFile::writeIndent(uint indent) const {
+ for (uint idx = 0; idx < indent; ++idx)
+ write("\t", 1);
+}
+
+bool SimpleFile::IsClassStart() {
+ char c;
+
+ do {
+ safeRead(&c, 1);
+ } while (Common::isSpace(c));
+
+ assert(c == '{' || c == '}');
+ return c == '{';
+}
+
+void SimpleFile::writeClassStart(const CString &classStr, int indent) {
+ write("\n", 1);
+ writeIndent(indent);
+ write("{\n", 2);
+ writeIndent(indent + 1);
+ writeQuotedString(classStr);
+ write("\n", 1);
+}
+
+void SimpleFile::writeClassEnd(int indent) {
+ writeIndent(indent);
+ write("}\n", 2);
+}
+
+bool SimpleFile::scanf(const char *format, ...) {
+ va_list va;
+ va_start(va, format);
+ char c;
+
+ CString formatStr(format);
+ while (!formatStr.empty()) {
+ if (formatStr.hasPrefix(" ")) {
+ formatStr.deleteChar(0);
+
+ safeRead(&c, 1);
+ if (!Common::isSpace(c))
+ return false;
+
+ // Skip over whitespaces
+ skipSpaces();
+ } else if (formatStr.hasPrefix("%d")) {
+ // Read in a number
+ formatStr = CString(formatStr.c_str() + 2);
+ int *param = (int *)va_arg(va, int *);
+ *param = readNumber();
+
+ if (!eos())
+ _inStream->seek(-1, SEEK_CUR);
+ } else if (formatStr.hasPrefix("%s")) {
+ // Read in text until the next space
+ formatStr = CString(formatStr.c_str() + 2);
+ CString *str = (CString *)va_arg(va, CString *);
+ str->clear();
+ while (!eos() && !Common::isSpace(c = readByte()))
+ *str += c;
+
+ if (!eos())
+ _inStream->seek(-1, SEEK_CUR);
+ }
+ }
+
+ skipSpaces();
+ va_end(va);
+ return true;
+}
+
+void SimpleFile::skipSpaces() {
+ char c = ' ';
+ while (!eos() && Common::isSpace(c))
+ safeRead(&c, 1);
+
+ if (!eos())
+ _inStream->seek(-1, SEEK_CUR);
+}
+
+/*------------------------------------------------------------------------*/
+
+bool StdCWadFile::open(const Common::String &filename) {
+ File f;
+ CString name = filename;
+
+ // Check for whether it is indeed a file/resource pair
+ int idx = name.indexOf('#');
+
+ if (idx < 0) {
+ // Nope, so open up file for standard reading
+ assert(!name.empty());
+ f.open(name);
+
+ SimpleFile::open(f.readStream(f.size()));
+ return true;
+ }
+
+ // Split up the name and resource, and get the resource index
+ CString fname = name.left(idx) + ".st";
+ int extPos = name.lastIndexOf('.');
+ CString resStr = name.mid(idx + 1, extPos - idx - 1);
+ int resIndex = resStr.readInt();
+
+ // Open up the index for access
+ f.open(fname);
+ int indexSize = f.readUint32LE() / 4;
+ assert(resIndex < indexSize);
+
+ // Get the specific resource's offset, and size by also
+ // getting the offset of the following resource
+ f.seek(resIndex * 4);
+ uint resOffset = f.readUint32LE();
+ uint nextOffset = (resIndex == (indexSize - 1)) ? f.size() :
+ f.readUint32LE();
+
+ // Read in the resource
+ f.seek(resOffset);
+ Common::SeekableReadStream *stream = f.readStream(nextOffset - resOffset);
+ SimpleFile::open(stream);
+
+ f.close();
+ return true;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/simple_file.h b/engines/titanic/support/simple_file.h
new file mode 100644
index 0000000000..f5d0bc7c1b
--- /dev/null
+++ b/engines/titanic/support/simple_file.h
@@ -0,0 +1,321 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_SIMPLE_FILE_H
+#define TITANIC_SIMPLE_FILE_H
+
+#include "common/file.h"
+#include "titanic/support/rect.h"
+#include "common/savefile.h"
+#include "common/stream.h"
+#include "common/zlib.h"
+#include "titanic/support/string.h"
+
+namespace Titanic {
+
+class Decompressor;
+class DecompressorData;
+
+/**
+ * Simple ScummVM File descendent that throws a wobbly if
+ * the file it tries to open isn't present
+ */
+class File : public Common::File {
+public:
+ virtual bool open(const Common::String &filename);
+};
+
+/**
+ * This class implements basic reading and writing to files
+ */
+class SimpleFile {
+private:
+ /**
+ * Skip over any pending spaces
+ */
+ void skipSpaces();
+protected:
+ Common::SeekableReadStream *_inStream;
+ Common::OutSaveFile *_outStream;
+ int _lineCount;
+public:
+ SimpleFile();
+ virtual ~SimpleFile();
+
+ operator Common::SeekableReadStream &() { return *_inStream; }
+ operator Common::WriteStream &() { return *_outStream; }
+
+ /**
+ * Set up a stream for read access
+ */
+ virtual void open(Common::SeekableReadStream *stream);
+
+ /**
+ * Set up a stream for write access
+ */
+ virtual void open(Common::OutSaveFile *stream);
+
+ /**
+ * Close the file
+ */
+ virtual void close();
+
+ /**
+ * Read from the file with validation
+ */
+ virtual void safeRead(void *dst, size_t count);
+
+ /**
+ * Read from the file
+ */
+ virtual size_t unsafeRead(void *dst, size_t count);
+
+ /**
+ * Write out data
+ */
+ virtual size_t write(const void *src, size_t count) const;
+
+ /**
+ * Seek
+ */
+ virtual void seek(int offset, int origin);
+ /**
+ * Read a byte
+ */
+ byte readByte();
+
+ /**
+ * Read a 16-bit LE number
+ */
+ uint readUint16LE();
+
+ /**
+ * Read a 32-bit LE number
+ */
+ uint readUint32LE();
+
+ /**
+ * Read a string from the file
+ */
+ CString readString();
+
+ /**
+ * Read a number from the file
+ */
+ int readNumber();
+
+ /**
+ * Read a floating point number from the file
+ */
+ double readFloat();
+
+ /**
+ * Read in a point
+ */
+ Point readPoint();
+
+ /**
+ * Read in a rect
+ */
+ Rect readRect();
+
+ /**
+ * Rect in a bounds
+ */
+ Rect readBounds();
+
+ /**
+ * Read a string and copy it into an optionally passed buffer
+ */
+ void readBuffer(char *buffer = nullptr, size_t count = 0);
+
+ /**
+ * Scan in values from the file
+ */
+ bool scanf(const char *format, ...);
+
+ /**
+ * Write out a byte
+ */
+ void writeByte(byte b) { write(&b, 1); }
+
+ /**
+ * Write out a raw 16-bit LE number
+ */
+ void writeUint16LE(uint val);
+
+ /**
+ * Write out a raw 32-bit LE number
+ */
+ void writeUint32LE(uint val);
+
+ /**
+ * Write a string line
+ */
+ void writeLine(const CString &str) const;
+
+ /**
+ * Write a string
+ */
+ void writeString(const CString &str) const;
+
+ /**
+ * Write a quoted string
+ */
+ void writeQuotedString(const CString &str) const;
+
+ /**
+ * Write a quoted string line
+ */
+ void writeQuotedLine(const CString &str, int indent) const;
+
+ /**
+ * Write a number to file
+ */
+ void writeNumber(int val) const;
+
+ /**
+ * Write a number line to file
+ */
+ void writeNumberLine(int val, int indent) const;
+
+ /**
+ * Write a floating point number
+ */
+ void writeFloat(double val) const;
+
+ /**
+ * Write a floating point number as a line
+ */
+ void writeFloatLine(double val, int indent) const;
+
+ /**
+ * Write out a point line
+ */
+ void writePoint(const Point &pt, int indent)const;
+
+ /**
+ * Write out a rect line
+ */
+ void writeRect(const Rect &r, int indent) const;
+
+ /**
+ * Write out a bounds line
+ */
+ void writeBounds(const Rect &r, int indent) const;
+
+ /**
+ * Write out a string using a format specifier, just like fprintf
+ */
+ void writeFormat(const char *format, ...) const;
+
+ /**
+ * Write out a number of tabs to form an indent in the output
+ */
+ void writeIndent(uint indent) const;
+
+ /**
+ * Validates that the following non-space character is either
+ * an opening or closing squiggly bracket denoting a class
+ * definition start or end. Returns true if it's a class start
+ */
+ bool IsClassStart();
+
+ /**
+ * Write the starting header for a class definition
+ */
+ void writeClassStart(const CString &classStr, int indent);
+
+ /**
+ * Write out the ending footer for a class definition
+ */
+ void writeClassEnd(int indent);
+
+ /**
+ * Return true if the stream has finished being read
+ */
+ bool eos() const {
+ assert(_inStream);
+ return _inStream->pos() >= _inStream->size();
+ }
+};
+
+/**
+ * Derived file that handles compressed files
+ */
+class CompressedFile : public SimpleFile {
+public:
+ CompressedFile() : SimpleFile() {}
+ virtual ~CompressedFile() {}
+
+ /**
+ * Set up a stream for read access
+ */
+ virtual void open(Common::SeekableReadStream *stream) {
+ SimpleFile::open(Common::wrapCompressedReadStream(stream));
+ }
+
+ /**
+ * Set up a stream for write access
+ */
+ virtual void open(Common::OutSaveFile *stream) {
+ SimpleFile::open(Common::wrapCompressedWriteStream(stream));
+ }
+};
+
+/**
+ * Derived file that handles WAD archives containing multiple files
+ */
+class StdCWadFile : public SimpleFile {
+public:
+ StdCWadFile() : SimpleFile() {}
+ virtual ~StdCWadFile() {}
+
+ /**
+ * Open up the specified file
+ */
+ virtual bool open(const Common::String &filename);
+
+ /**
+ * Unsupported open method from parent class
+ */
+ virtual void open(Common::SeekableReadStream *stream) {}
+
+ /**
+ * Unsupported open method from parent class
+ */
+ virtual void open(Common::OutSaveFile *stream) {}
+
+ /**
+ * Return a reference to the read stream
+ */
+ Common::SeekableReadStream *readStream() const { return _inStream; }
+};
+
+/**
+ * General purpose support method for reading an ASCIIZ string from a stream
+ */
+CString readStringFromStream(Common::SeekableReadStream *s);
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_SIMPLE_FILE_H */
diff --git a/engines/titanic/support/string.cpp b/engines/titanic/support/string.cpp
new file mode 100644
index 0000000000..cd39c03861
--- /dev/null
+++ b/engines/titanic/support/string.cpp
@@ -0,0 +1,125 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/algorithm.h"
+#include "titanic/support/string.h"
+
+namespace Titanic {
+
+CString::CString(char c, uint32 len) : Common::String() {
+ ensureCapacity(len, false);
+ for (uint idx = 0; idx < len; ++idx)
+ (*this) += c;
+}
+
+CString::CString(int val) : Common::String() {
+ *this = CString::format("%d", val);
+}
+
+CString CString::left(uint count) const {
+ return (count > size()) ? CString() : CString(c_str(), c_str() + count);
+}
+
+CString CString::right(uint count) const {
+ uint strSize = size();
+ return (count > strSize) ? CString() :
+ CString(c_str() + strSize - count, c_str() + strSize);
+}
+
+CString CString::mid(uint start, uint count) const {
+ if (start >= size())
+ return CString();
+ else
+ return CString(c_str() + start, MIN(count, size() - start));
+}
+
+CString CString::mid(uint start) const {
+ uint strSize = size();
+ assert(start <= strSize);
+ return mid(start, strSize - start);
+}
+
+int CString::indexOf(char c) const {
+ const char *charP = strchr(c_str(), c);
+ return charP ? charP - c_str() : -1;
+}
+
+int CString::indexOf(const char *s) const {
+ const char *strP = strstr(c_str(), s);
+ return strP ? strP - c_str() : -1;
+}
+
+int CString::lastIndexOf(char c) const {
+ const char *charP = strrchr(c_str(), c);
+ return charP ? charP - c_str() : -1;
+}
+
+FileType CString::fileTypeSuffix() const {
+ CString ext = right(1);
+ if (ext == "0" || ext == "4")
+ return FILETYPE_IMAGE;
+ else if (ext == "1")
+ return FILETYPE_WAV;
+ else if (ext == "2" || ext == "3")
+ return FILETYPE_MOVIE;
+
+ ext = right(3);
+ if (ext == "tga" || ext == "jpg")
+ return FILETYPE_IMAGE;
+ else if (ext == "wav")
+ return FILETYPE_WAV;
+ else if (ext == "avi" || ext == "mov")
+ return FILETYPE_MOVIE;
+ else if (ext == "dlg")
+ return FILETYPE_DLG;
+ else
+ return FILETYPE_UNKNOWN;
+}
+
+ImageType CString::imageTypeSuffix() const {
+ CString ext = right(1);
+ if (ext == "0")
+ return IMAGETYPE_TARGA;
+ else if (ext == "4")
+ return IMAGETYPE_JPEG;
+
+ ext = right(3);
+ if (ext == "tga")
+ return IMAGETYPE_TARGA;
+ else if (ext == "jpg")
+ return IMAGETYPE_JPEG;
+ else
+ return IMAGETYPE_UNKNOWN;
+}
+
+CString CString::format(const char *fmt, ...) {
+ String output;
+
+ va_list va;
+ va_start(va, fmt);
+ output = String::vformat(fmt, va);
+ va_end(va);
+
+ return output;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/string.h b/engines/titanic/support/string.h
new file mode 100644
index 0000000000..9550ce88a7
--- /dev/null
+++ b/engines/titanic/support/string.h
@@ -0,0 +1,114 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_STRING_H
+#define TITANIC_STRING_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/str.h"
+
+namespace Titanic {
+
+enum FileType {
+ FILETYPE_UNKNOWN = 0, FILETYPE_IMAGE = 1, FILETYPE_MOVIE = 2,
+ FILETYPE_WAV = 3, FILETYPE_DLG = 4
+};
+
+enum ImageType {
+ IMAGETYPE_UNKNOWN = 0, IMAGETYPE_TARGA = 1, IMAGETYPE_JPEG = 2
+};
+
+class CString : public Common::String {
+public:
+ CString() : Common::String() {}
+ CString(const char *str) : Common::String(str) {}
+ CString(const char *str, uint32 len) : Common::String(str, len) {}
+ CString(const char *beginP, const char *endP) : Common::String(beginP, endP) {}
+ CString(const String &str) : Common::String(str) {}
+ CString(char c, uint32 len);
+ explicit CString(char c) : Common::String(c) {}
+ explicit CString(int val);
+
+ /**
+ * Returns the left n characters of the string
+ */
+ CString left(uint count) const;
+
+ /**
+ * Returns the right n characters of the string
+ */
+ CString right(uint count) const;
+
+ /**
+ * Returns a substring from within the string
+ */
+ CString mid(uint start, uint count) const;
+
+ /**
+ * Returns a substring from within the string
+ */
+ CString mid(uint start) const;
+
+ /**
+ * Returns the index of the first occurance of a given character
+ */
+ int indexOf(char c) const;
+
+ /**
+ * Returns the index of the first occurance of a given string
+ */
+ int indexOf(const char *s) const;
+
+ /**
+ * Returns the index of the last occurance of a given character
+ */
+ int lastIndexOf(char c) const;
+
+ /**
+ * Returns the type of a filename based on it's extension
+ */
+ FileType fileTypeSuffix() const;
+
+ /**
+ * Returns the type of an image filename based on it's extension
+ */
+ ImageType imageTypeSuffix() const;
+
+ /**
+ * Parses the string as an integer and returns the value
+ */
+ int readInt() const {
+ return atoi(c_str());
+ }
+
+ /**
+ * Format a string
+ */
+ static CString format(const char *fmt, ...);
+};
+
+typedef Common::Array<CString> StringArray;
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_STRING_H */
diff --git a/engines/titanic/support/text_cursor.cpp b/engines/titanic/support/text_cursor.cpp
new file mode 100644
index 0000000000..ad3fe4ed26
--- /dev/null
+++ b/engines/titanic/support/text_cursor.cpp
@@ -0,0 +1,88 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/textconsole.h"
+#include "titanic/support/text_cursor.h"
+#include "titanic/support/screen_manager.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+CTextCursor::CTextCursor(CScreenManager *screenManager) :
+ _screenManager(screenManager), _active(false), _blinkVisible(false),
+ _backRenderSurface(nullptr), _frontRenderSurface(nullptr),
+ _blinkDelay(300), _size(2, 10), _priorBlinkTime(0),
+ _cursorR(0), _cursorG(0), _cursorB(0), _mode(-1) {
+ _surface = screenManager->createSurface(10, 10);
+}
+
+CTextCursor::~CTextCursor() {
+ delete _surface;
+}
+
+void CTextCursor::setColor(byte r, byte g, byte b) {
+ _cursorR = r;
+ _cursorG = g;
+ _cursorB = b;
+}
+
+void CTextCursor::show() {
+ _backRenderSurface = _screenManager->getSurface(SURFACE_BACKBUFFER);
+ _frontRenderSurface = _screenManager->getFrontRenderSurface();
+ _active = true;
+ _priorBlinkTime = g_vm->_events->getTicksCount();
+}
+
+void CTextCursor::hide() {
+ _active = false;
+}
+
+void CTextCursor::draw() {
+ if (!_active)
+ return;
+
+ // Handle updating whether the blinking cursor is visible or not
+ uint newTicks = g_vm->_events->getTicksCount();
+ while (newTicks > (_priorBlinkTime + _blinkDelay)) {
+ _priorBlinkTime += _blinkDelay;
+ _blinkVisible = !_blinkVisible;
+ }
+
+ if (_blinkVisible) {
+ Rect cursorRect = getCursorBounds();
+ _surface->blitFrom(Common::Point(0, 0), _backRenderSurface, &cursorRect);
+
+ if (!_screenBounds.isEmpty())
+ // Limit the cursor rect to only within designated screen area
+ cursorRect.constrain(_screenBounds);
+
+ if (!cursorRect.isEmpty()) {
+ // Draw cursor onto the screen
+ _backRenderSurface->_ddSurface->fillRect(&cursorRect,
+ _cursorR, _cursorG, _cursorB);
+ }
+
+ //_screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &_pos);
+ }
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/text_cursor.h b/engines/titanic/support/text_cursor.h
new file mode 100644
index 0000000000..d8c6ac0653
--- /dev/null
+++ b/engines/titanic/support/text_cursor.h
@@ -0,0 +1,121 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_TEXT_CURSOR_H
+#define TITANIC_TEXT_CURSOR_H
+
+#include "common/scummsys.h"
+#include "titanic/support/rect.h"
+
+namespace Titanic {
+
+class CScreenManager;
+class CVideoSurface;
+
+class CTextCursor {
+private:
+ CScreenManager *_screenManager;
+ CVideoSurface *_backRenderSurface;
+ CVideoSurface *_frontRenderSurface;
+ Point _pos;
+ Rect _screenBounds;
+ uint _blinkDelay;
+ bool _blinkVisible;
+ Point _size;
+ Point _screenTopLeft;
+ uint _priorBlinkTime;
+ byte _cursorR;
+ byte _cursorG;
+ byte _cursorB;
+ CVideoSurface *_surface;
+ int _mode;
+public:
+ bool _active;
+public:
+ CTextCursor(CScreenManager *screenManager);
+ ~CTextCursor();
+
+ /**
+ * Sets the position of the cursor
+ */
+ void setPos(const Point &pt) { _pos = pt; }
+
+ /**
+ * Sets the size of the cursor
+ */
+ void setSize(const Point &size) { _size = size; }
+
+ /**
+ * Returns the bounds for the cursor
+ */
+ Rect getCursorBounds() const {
+ return Rect(_pos.x, _pos.y, _pos.x + _size.x, _pos.y + _size.y);
+ }
+
+ /**
+ * Set bounds
+ */
+ void setBounds(const Rect &r) { _screenBounds = r; }
+
+ /**
+ * Clear the bounds
+ */
+ void clearBounds() { _screenBounds.clear(); }
+
+ /**
+ * Set the blinking rate
+ */
+ void setBlinkRate(uint ticks) { _blinkDelay = ticks; }
+
+ /**
+ * Set the cursor color
+ */
+ void setColor(byte r, byte g, byte b);
+
+ /**
+ * Returns whether the text cursor is active
+ */
+ bool isActive() const { return _active; }
+
+ int getMode() const { return _mode; }
+
+ void setMode(int mode) { _mode = mode; }
+
+ /**
+ * Show the text cursor
+ */
+ void show();
+
+ /**
+ * Hide the text cursor
+ */
+ void hide();
+
+ /**
+ * Update and draw the cursor if necessary
+ */
+ void draw();
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_TEXT_CURSOR_H */
diff --git a/engines/titanic/support/time_event_info.cpp b/engines/titanic/support/time_event_info.cpp
new file mode 100644
index 0000000000..0226223f1a
--- /dev/null
+++ b/engines/titanic/support/time_event_info.cpp
@@ -0,0 +1,206 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/time_event_info.h"
+#include "titanic/core/game_object.h"
+#include "titanic/core/project_item.h"
+#include "titanic/messages/messages.h"
+
+namespace Titanic {
+
+void CTimeEventInfoList::postLoad(uint ticks, CProjectItem *project) {
+ for (iterator i = begin(); i != end(); ++i)
+ (*i)->postLoad(ticks, project);
+}
+
+void CTimeEventInfoList::preSave(uint ticks) {
+ for (iterator i = begin(); i != end(); ++i)
+ (*i)->preSave(ticks);
+}
+
+void CTimeEventInfoList::postSave() {
+ for (iterator i = begin(); i != end(); ++i)
+ (*i)->postSave();
+}
+
+void CTimeEventInfoList::update(uint ticks) {
+ // Remove any items that are done
+ for (iterator i = begin(); i != end(); ) {
+ CTimeEventInfo *item = *i;
+ if (item->_done) {
+ i = erase(i);
+ delete item;
+ } else {
+ ++i;
+ }
+ }
+
+ // Handle updating the items
+ for (iterator i = begin(); i != end(); ) {
+ CTimeEventInfo *item = *i;
+ if (!item->update(ticks)) {
+ ++i;
+ } else {
+ i = erase(i);
+ delete item;
+ }
+ }
+}
+
+void CTimeEventInfoList::stop(uint id) {
+ for (iterator i = begin(); i != end(); ++i) {
+ CTimeEventInfo *item = *i;
+ if (item->_id == id) {
+ item->_done = true;
+ return;
+ }
+ }
+}
+
+void CTimeEventInfoList::setPersisent(uint id, bool flag) {
+ for (iterator i = begin(); i != end(); ++i) {
+ CTimeEventInfo *item = *i;
+ if (item->_id == id) {
+ item->setPersisent(flag);
+ return;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+uint CTimeEventInfo::_nextId;
+
+CTimeEventInfo::CTimeEventInfo() : ListItem(), _lockCounter(0),
+ _repeated(false), _firstDuration(0), _repeatDuration(0),
+ _target(nullptr), _actionVal(0), _timerCtr(0), _done(false),
+ _lastTimerTicks(0), _relativeTicks(0), _persisent(true) {
+ _id = _nextId++;
+}
+
+CTimeEventInfo::CTimeEventInfo(uint ticks, bool repeated, uint firstDuration,
+ uint repeatDuration, CTreeItem *target, int endVal, const CString &action) :
+ ListItem(), _lockCounter(0), _repeated(repeated), _firstDuration(firstDuration),
+ _repeatDuration(repeatDuration), _target(target), _actionVal(endVal), _done(false),
+ _timerCtr(0), _lastTimerTicks(ticks), _relativeTicks(0), _persisent(true) {
+ _id = _nextId++;
+}
+
+void CTimeEventInfo::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(0, indent);
+
+ CString targetName;
+ if (_target)
+ targetName = _target->getName();
+ file->writeQuotedLine(targetName, indent);
+ file->writeNumberLine(_id, indent);
+ file->writeNumberLine(_repeated, indent);
+ file->writeNumberLine(_firstDuration, indent);
+ file->writeNumberLine(_repeatDuration, indent);
+ file->writeNumberLine(_actionVal, indent);
+ file->writeQuotedLine(_action, indent);
+ file->writeNumberLine(_timerCtr, indent);
+ file->writeNumberLine(_relativeTicks, indent);
+ file->writeNumberLine(_done, indent);
+ file->writeNumberLine(_persisent, indent);
+}
+
+void CTimeEventInfo::load(SimpleFile *file) {
+ lock();
+ int val = file->readNumber();
+
+ if (!val) {
+ _targetName = file->readString();
+ _id = file->readNumber();
+ _repeated = file->readNumber();
+ _firstDuration = file->readNumber();
+ _repeatDuration = file->readNumber();
+ _actionVal = file->readNumber();
+ _action = file->readString();
+ _timerCtr = file->readNumber();
+ _relativeTicks = file->readNumber();
+ _done = file->readNumber() != 0;
+ _persisent = file->readNumber() != 0;
+ _target = nullptr;
+ }
+}
+
+void CTimeEventInfo::postLoad(uint ticks, CProjectItem *project) {
+ if (!_persisent || _targetName.empty())
+ _done = true;
+
+ // Get the timer's target
+ if (project)
+ _target = project->findByName(_targetName);
+ if (!_target)
+ _done = true;
+
+ _lastTimerTicks = ticks + _relativeTicks;
+ if (_id >= _nextId)
+ _nextId = _id + 1;
+
+ unlock();
+}
+
+void CTimeEventInfo::preSave(uint ticks) {
+ _relativeTicks = _lastTimerTicks - ticks;
+ lock();
+}
+
+void CTimeEventInfo::postSave() {
+ unlock();
+}
+
+bool CTimeEventInfo::update(uint ticks) {
+ if (_lockCounter)
+ return false;
+
+ if (_timerCtr) {
+ if (ticks > (_lastTimerTicks + _repeatDuration)) {
+ ++_timerCtr;
+ _lastTimerTicks = ticks;
+
+ if (_target) {
+ CTimerMsg timerMsg(ticks, _timerCtr, _actionVal, _action);
+ timerMsg.execute(_target);
+ }
+ }
+ } else {
+ if (ticks > (_lastTimerTicks + _firstDuration)) {
+ _timerCtr = 1;
+ _lastTimerTicks = ticks;
+
+ if (_target) {
+ CTimerMsg timerMsg(ticks, _timerCtr, _actionVal, _action);
+ timerMsg.execute(_target);
+ }
+
+ if (!_repeated)
+ // Event is done, and can be removed
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/time_event_info.h b/engines/titanic/support/time_event_info.h
new file mode 100644
index 0000000000..ebf5b54458
--- /dev/null
+++ b/engines/titanic/support/time_event_info.h
@@ -0,0 +1,138 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_TIMER_H
+#define TITANIC_TIMER_H
+
+#include "common/algorithm.h"
+#include "titanic/core/list.h"
+
+namespace Titanic {
+
+class CTreeItem;
+class CProjectItem;
+
+class CTimeEventInfo : public ListItem {
+private:
+ /**
+ * Increments the counter
+ */
+ void lock() { ++_lockCounter; }
+
+ /**
+ * Called at the end of both post load and post save actions
+ */
+ void unlock() {
+ _lockCounter = MAX(_lockCounter - 1, 0);
+ }
+public:
+ static uint _nextId;
+public:
+ int _lockCounter;
+ uint _id;
+ bool _repeated;
+ uint _firstDuration;
+ uint _repeatDuration;
+ CTreeItem *_target;
+ uint _actionVal;
+ CString _action;
+ uint _timerCtr;
+ uint _lastTimerTicks;
+ uint _relativeTicks;
+ bool _done;
+ bool _persisent;
+ CString _targetName;
+public:
+ CLASSDEF;
+ CTimeEventInfo();
+ CTimeEventInfo(uint ticks, bool repeated, uint firstDuration, uint repeatDuration,
+ CTreeItem *target, int endVal, const CString &action);
+
+ /**
+ * Save the data for the class to file
+ */
+ virtual void save(SimpleFile *file, int indent);
+
+ /**
+ * Load the data for the class from file
+ */
+ virtual void load(SimpleFile *file);
+
+ /**
+ * Called after loading a game has finished
+ */
+ void postLoad(uint ticks, CProjectItem *project);
+
+ /**
+ * Called when a game is about to be saved
+ */
+ void preSave(uint ticks);
+
+ /**
+ * Called when a game has finished being saved
+ */
+ void postSave();
+
+ bool update(uint ticks);
+
+ /**
+ * Flags whether the timer will be persisent across save & loads
+ */
+ void setPersisent(bool val) { _persisent = val; }
+};
+
+class CTimeEventInfoList : public List<CTimeEventInfo> {
+public:
+ /**
+ * Called after loading a game has finished
+ */
+ void postLoad(uint ticks, CProjectItem *project);
+
+ /**
+ * Called when a game is about to be saved
+ */
+ void preSave(uint ticks);
+
+ /**
+ * Called when a game has finished being saved
+ */
+ void postSave();
+
+ /**
+ * Handles an update
+ */
+ void update(uint ticks);
+
+ /**
+ * Remove an item with the given Id
+ */
+ void stop(uint id);
+
+ /**
+ * Sets whether a timer with a given Id will be persisent across saves
+ */
+ void setPersisent(uint id, bool flag);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_TIMER_H */
diff --git a/engines/titanic/support/video_surface.cpp b/engines/titanic/support/video_surface.cpp
new file mode 100644
index 0000000000..594f660937
--- /dev/null
+++ b/engines/titanic/support/video_surface.cpp
@@ -0,0 +1,583 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/support/video_surface.h"
+#include "titanic/support/image_decoders.h"
+#include "titanic/support/screen_manager.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+int CVideoSurface::_videoSurfaceCounter = 0;
+
+CVideoSurface::CVideoSurface(CScreenManager *screenManager) :
+ _screenManager(screenManager), _rawSurface(nullptr), _movie(nullptr),
+ _pendingLoad(false), _transBlitFlag(false), _fastBlitFlag(false),
+ _movieFrameSurface(nullptr), _transparencyMode(TRANS_DEFAULT),
+ _freeMovieSurface(DisposeAfterUse::NO), _hasFrame(true), _lockCount(0) {
+ _videoSurfaceNum = _videoSurfaceCounter++;
+}
+
+CVideoSurface::~CVideoSurface() {
+ if (_ddSurface)
+ _videoSurfaceCounter -= freeSurface();
+ --_videoSurfaceCounter;
+
+ if (_freeMovieSurface == DisposeAfterUse::YES)
+ delete _movieFrameSurface;
+}
+
+void CVideoSurface::setSurface(CScreenManager *screenManager, DirectDrawSurface *surface) {
+ _screenManager = screenManager;
+ _ddSurface = surface;
+}
+
+void CVideoSurface::blitFrom(const Point &destPos, CVideoSurface *src, const Rect *srcRect) {
+ if (loadIfReady() && src->loadIfReady() && _ddSurface && src->_ddSurface) {
+ Rect srcBounds, destBounds;
+ clipBounds(srcBounds, destBounds, src, srcRect, &destPos);
+
+ if (src->_transBlitFlag)
+ blitRect2(srcBounds, destBounds, src);
+ else
+ blitRect1(srcBounds, destBounds, src);
+ }
+}
+
+void CVideoSurface::blitFrom(const Point &destPos, const Graphics::Surface *src) {
+ lock();
+ _rawSurface->blitFrom(*src, destPos);
+ unlock();
+}
+
+void CVideoSurface::clipBounds(Rect &srcRect, Rect &destRect,
+ CVideoSurface *srcSurface, const Rect *subRect, const Point *destPos) {
+ // Figure out initial source rect and dest rect, based on whether
+ // specific subRect and/or destPos have been passed
+ if (destPos) {
+ destRect.left = destPos->x;
+ destRect.top = destPos->y;
+ } else {
+ destRect.left = destRect.top = 0;
+ }
+
+ if (subRect) {
+ destRect.right = destRect.left + subRect->width();
+ destRect.bottom = destRect.top + subRect->height();
+ srcRect = *subRect;
+ } else {
+ srcRect.right = srcRect.left + srcSurface->getWidth();
+ srcRect.bottom = srcRect.top + srcSurface->getHeight();
+ srcRect = Rect(0, 0, srcSurface->getWidth(), srcSurface->getHeight());
+ }
+
+ // Clip destination rect to be on-screen
+ if (destRect.left < 0) {
+ srcRect.left -= destRect.left;
+ destRect.left = 0;
+ }
+ if (destRect.top < 0) {
+ srcRect.top -= destRect.top;
+ destRect.top = 0;
+ }
+ if (destRect.right > getWidth()) {
+ srcRect.right += getWidth() - destRect.right;
+ destRect.right = getWidth();
+ }
+ if (destRect.bottom > getHeight()) {
+ srcRect.bottom += getHeight() - destRect.bottom;
+ destRect.bottom = getHeight();
+ }
+
+ // Clip source rect to be within the source surface
+ if (srcRect.left < 0) {
+ destRect.left -= srcRect.left;
+ srcRect.left = 0;
+ }
+ if (srcRect.top < 0) {
+ destRect.top -= srcRect.top;
+ srcRect.top = 0;
+ }
+ if (srcRect.right > srcSurface->getWidth()) {
+ destRect.right += srcSurface->getWidth() - srcRect.right;
+ srcRect.right = srcSurface->getWidth();
+ }
+ if (srcRect.bottom > srcSurface->getHeight()) {
+ destRect.bottom += srcSurface->getHeight() - srcRect.bottom;
+ srcRect.bottom = srcSurface->getHeight();
+ }
+
+ // Validate that the resulting rects are valid
+ if (destRect.left >= destRect.right || destRect.top >= destRect.bottom
+ || srcRect.left >= srcRect.right || srcRect.top >= srcRect.bottom)
+ error("Invalid rect");
+}
+
+void CVideoSurface::blitRect1(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) {
+ src->lock();
+ lock();
+
+ if (src->_fastBlitFlag) {
+ _rawSurface->blitFrom(*src->_rawSurface, srcRect, Point(destRect.left, destRect.top));
+ } else if (getMovieFrameSurface()) {
+ movieBlitRect(srcRect, destRect, src);
+ } else {
+ _rawSurface->transBlitFrom(*src->_rawSurface, srcRect, destRect, src->getTransparencyColor());
+ }
+
+ src->unlock();
+ unlock();
+}
+
+void CVideoSurface::blitRect2(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) {
+ if (getMovieFrameSurface()) {
+ movieBlitRect(srcRect, destRect, src);
+ } else {
+ src->lock();
+ lock();
+
+ _rawSurface->blitFrom(*src->_rawSurface, srcRect, Point(destRect.left, destRect.top));
+
+ src->unlock();
+ unlock();
+ }
+}
+
+void CVideoSurface::movieBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) {
+ // TODO
+}
+
+uint CVideoSurface::getTransparencyColor() {
+ uint32 val = -(getPixelDepth() - 2);
+ val &= 0xFFFF8400;
+ val += 0xF81F;
+ return val;
+}
+
+bool CVideoSurface::hasFrame() {
+ if (_hasFrame) {
+ _hasFrame = false;
+ return true;
+ } else if (_movie) {
+ return _movie->hasVideoFrame();
+ } else {
+ return false;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+byte OSVideoSurface::_palette1[32][32];
+byte OSVideoSurface::_palette2[32][32];
+
+OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, DirectDrawSurface *surface) :
+ CVideoSurface(screenManager) {
+ _ddSurface = surface;
+}
+
+OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, const CResourceKey &key, bool pendingLoad) :
+ CVideoSurface(screenManager) {
+ _ddSurface = nullptr;
+ _pendingLoad = pendingLoad;
+
+ if (_pendingLoad) {
+ loadResource(key);
+ } else {
+ _resourceKey = key;
+ load();
+ }
+}
+
+void OSVideoSurface::setupPalette(byte palette[32][32], byte val) {
+ for (uint idx1 = 0; idx1 < 32; ++idx1) {
+ for (uint idx2 = 0, base = 0; idx2 < 32; ++idx2, base += idx1) {
+ int64 v = 0x84210843;
+ v *= base;
+ uint v2 = (v >> 36);
+ v = ((v2 >> 31) + v2) & 0xff;
+ palette[idx1][idx2] = v << 3;
+
+ if (val != 0xff && v != idx2) {
+ v = 0x80808081 * v * val;
+ v2 = v >> 39;
+ palette[idx1][idx2] = ((v2 >> 31) + v2) << 3;
+ }
+ }
+ }
+}
+
+void OSVideoSurface::loadResource(const CResourceKey &key) {
+ _resourceKey = key;
+ _pendingLoad = true;
+
+ if (hasSurface())
+ load();
+}
+
+void OSVideoSurface::loadTarga(const CResourceKey &key) {
+ // Decode the image
+ CTargaDecode decoder;
+ decoder.decode(*this, key.getString());
+
+ if (getPixelDepth() == 2)
+ shiftColors();
+
+ _resourceKey = key;
+
+}
+
+void OSVideoSurface::loadJPEG(const CResourceKey &key) {
+ // Decode the image
+ CJPEGDecode decoder;
+ decoder.decode(*this, key.getString());
+
+ if (getPixelDepth() == 2)
+ shiftColors();
+
+ _resourceKey = key;
+}
+
+void OSVideoSurface::loadTarga(const CString &name) {
+ CResourceKey key(name);
+ loadTarga(key);
+}
+
+void OSVideoSurface::loadMovie(const CResourceKey &key, bool destroyFlag) {
+ // Delete any prior movie
+ if (_movie) {
+ delete _movie;
+ _movie = nullptr;
+ }
+
+ // Create the new movie and load the first frame to the video surface
+ _movie = g_vm->_movieManager.createMovie(key, this);
+ _movie->setFrame(0);
+
+ // If flagged to destroy, then immediately destroy movie instance
+ if (destroyFlag) {
+ delete _movie;
+ _movie = nullptr;
+ }
+
+ _resourceKey = key;
+}
+
+bool OSVideoSurface::lock() {
+ if (!loadIfReady())
+ return false;
+
+ ++_lockCount;
+ _rawSurface = _ddSurface->lock(nullptr, 0);
+ return true;
+}
+
+void OSVideoSurface::unlock() {
+ if (!--_lockCount) {
+ if (_rawSurface)
+ _ddSurface->unlock();
+ _rawSurface = nullptr;
+ }
+}
+
+bool OSVideoSurface::hasSurface() {
+ return _ddSurface != nullptr;
+}
+
+int OSVideoSurface::getWidth() {
+ if (!loadIfReady())
+ error("Could not load resource");
+
+ return _ddSurface->getWidth();
+}
+
+int OSVideoSurface::getHeight() {
+ if (!loadIfReady())
+ error("Could not load resource");
+
+ return _ddSurface->getHeight();
+}
+
+int OSVideoSurface::getPitch() {
+ if (!loadIfReady())
+ error("Could not load resource");
+
+ return _ddSurface->getPitch();
+}
+
+int OSVideoSurface::getBpp() {
+ if (!loadIfReady())
+ error("Could not load resource");
+
+ return getPixelDepth();
+}
+
+void OSVideoSurface::recreate(int width, int height) {
+ freeSurface();
+
+ _screenManager->resizeSurface(this, width, height);
+ if (_ddSurface)
+ _videoSurfaceCounter += _ddSurface->getSize();
+}
+
+void OSVideoSurface::resize(int width, int height) {
+ if (!_ddSurface || _ddSurface->getWidth() != width ||
+ _ddSurface->getHeight() != height)
+ recreate(width, height);
+}
+
+void OSVideoSurface::detachSurface() {
+ _ddSurface = nullptr;
+}
+
+int OSVideoSurface::getPixelDepth() {
+ if (!loadIfReady())
+ error("Could not load resource");
+
+ lock();
+
+ int result = _rawSurface->format.bytesPerPixel;
+ if (result == 1)
+ // Paletted 8-bit images don't store the color directly in the pixels
+ result = 0;
+
+ unlock();
+ return result;
+}
+
+bool OSVideoSurface::load() {
+ if (!_resourceKey.scanForFile())
+ return false;
+
+ switch (_resourceKey.fileTypeSuffix()) {
+ case FILETYPE_IMAGE:
+ switch (_resourceKey.imageTypeSuffix()) {
+ case IMAGETYPE_TARGA:
+ loadTarga(_resourceKey);
+ break;
+ case IMAGETYPE_JPEG:
+ loadJPEG(_resourceKey);
+ break;
+ default:
+ break;
+ }
+ return true;
+
+ case FILETYPE_MOVIE:
+ loadMovie(_resourceKey);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+uint16 OSVideoSurface::getPixel(const Common::Point &pt) {
+ if (!loadIfReady())
+ return 0;
+
+ if (pt.x >= 0 && pt.y >= 0 && pt.x < getWidth() && pt.y < getHeight()) {
+ lock();
+ uint16 pixel = *(uint16 *)_rawSurface->getBasePtr(pt.x, pt.y);
+ unlock();
+ return pixel;
+ } else {
+ return getTransparencyColor();
+ }
+}
+
+void OSVideoSurface::setPixel(const Point &pt, uint pixel) {
+ assert(getPixelDepth() == 2);
+
+ uint16 *pixelP = (uint16 *)_rawSurface->getBasePtr(pt.x, pt.y);
+ *pixelP = pixel;
+}
+
+void OSVideoSurface::changePixel(uint16 *pixelP, uint16 *color, byte srcVal, bool remapFlag) {
+ assert(getPixelDepth() == 2);
+ const Graphics::PixelFormat &destFormat = _ddSurface->getFormat();
+ const Graphics::PixelFormat srcFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+
+ // Get the color
+ byte r, g, b;
+ srcFormat.colorToRGB(*color, r, g, b);
+ if (remapFlag) {
+ r = _palette1[31 - srcVal][r >> 3];
+ g = _palette1[31 - srcVal][g >> 3];
+ b = _palette1[31 - srcVal][b >> 3];
+ }
+
+ byte r2, g2, b2;
+ destFormat.colorToRGB(*pixelP, r2, g2, b2);
+ r2 = _palette1[srcVal][r2 >> 3];
+ g2 = _palette1[srcVal][g2 >> 3];
+ b2 = _palette1[srcVal][b2 >> 3];
+
+ *pixelP = destFormat.RGBToColor(r + r2, g + g2, b + b2);
+}
+
+void OSVideoSurface::shiftColors() {
+ if (!loadIfReady())
+ return;
+
+ // Currently no further processing is needed, since for ScummVM,
+ // we already convert 16-bit surfaces as soon as they're loaded
+}
+
+void OSVideoSurface::clear() {
+ if (!loadIfReady())
+ error("Could not load resource");
+
+}
+
+void OSVideoSurface::playMovie(uint flags, CGameObject *obj) {
+ if (loadIfReady() && _movie)
+ _movie->play(flags, obj);
+
+ _ddSurface->fill(nullptr, 0);
+}
+
+void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) {
+ if (loadIfReady() && _movie) {
+ _movie->play(startFrame, endFrame, flags, obj);
+ }
+}
+
+void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) {
+ if (loadIfReady() && _movie) {
+ _movie->play(startFrame, endFrame, initialFrame, flags, obj);
+ }
+}
+
+void OSVideoSurface::stopMovie() {
+ if (_movie)
+ _movie->stop();
+}
+
+void OSVideoSurface::setMovieFrame(uint frameNumber) {
+ if (loadIfReady() && _movie)
+ _movie->setFrame(frameNumber);
+}
+
+void OSVideoSurface::addMovieEvent(int frameNumber, CGameObject *obj) {
+ if (_movie)
+ _movie->addEvent(frameNumber, obj);
+}
+
+void OSVideoSurface::setMovieFrameRate(double rate) {
+ if (_movie)
+ _movie->setFrameRate(rate);
+}
+
+const CMovieRangeInfoList *OSVideoSurface::getMovieRangeInfo() const {
+ return _movie ? _movie->getMovieRangeInfo() : nullptr;
+}
+
+void OSVideoSurface::flipVertically(bool needsLock) {
+ if (!loadIfReady() || !_transBlitFlag)
+ return;
+
+ if (needsLock)
+ lock();
+
+ byte lineBuffer[SCREEN_WIDTH * 2];
+ int pitch = getBpp() * getWidth();
+ assert(pitch < (SCREEN_WIDTH * 2));
+
+ for (int yp = 0; yp < (_rawSurface->h / 2); ++yp) {
+ byte *line1P = (byte *)_rawSurface->getBasePtr(0, yp);
+ byte *line2P = (byte *)_rawSurface->getBasePtr(0, _rawSurface->h - yp - 1);
+
+ Common::copy(line1P, line1P + pitch, lineBuffer);
+ Common::copy(line2P, line2P + pitch, line1P);
+ Common::copy(lineBuffer, lineBuffer + pitch, line1P);
+ }
+
+ _transBlitFlag = false;
+ if (needsLock)
+ unlock();
+}
+
+bool OSVideoSurface::loadIfReady() {
+ _videoSurfaceNum = _videoSurfaceCounter;
+
+ if (hasSurface()) {
+ return true;
+ } else if (_pendingLoad) {
+ _hasFrame = true;
+ load();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void OSVideoSurface::transPixelate() {
+ if (!loadIfReady())
+ return;
+
+ lock();
+ Graphics::ManagedSurface *surface = _rawSurface;
+ uint transColor = getTransparencyColor();
+ // TODO: Check whether color is correct
+ uint pixelColor = surface->format.RGBToColor(0x50, 0, 0);
+
+ for (int yp = 0; yp < surface->h; ++yp) {
+ uint16 *pixelsP = (uint16 *)surface->getBasePtr(0, yp);
+ bool bitFlag = (yp % 2) == 0;
+ int replaceCtr = yp & 3;
+
+ for (int xp = 0; xp < surface->w; ++xp, ++pixelsP) {
+ if (bitFlag && *pixelsP == transColor && replaceCtr == 0)
+ *pixelsP = pixelColor;
+
+ bitFlag = !bitFlag;
+ replaceCtr = (replaceCtr + 1) & 3;
+ }
+ }
+
+ surface->markAllDirty();
+ unlock();
+}
+
+Graphics::ManagedSurface *OSVideoSurface::dupMovieFrame() const {
+ return _movie ? _movie->duplicateFrame() : nullptr;
+}
+
+int OSVideoSurface::freeSurface() {
+ if (!_ddSurface)
+ return 0;
+ int surfaceSize = _ddSurface->getSize();
+
+ delete _movie;
+ _movie = nullptr;
+ delete _ddSurface;
+ _ddSurface = nullptr;
+
+ return surfaceSize;
+}
+
+uint16 *OSVideoSurface::getBasePtr(int x, int y) {
+ assert(_rawSurface);
+ return (uint16 *)_rawSurface->getBasePtr(x, y);
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/video_surface.h b/engines/titanic/support/video_surface.h
new file mode 100644
index 0000000000..053eabb0f9
--- /dev/null
+++ b/engines/titanic/support/video_surface.h
@@ -0,0 +1,537 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TITANIC_VIDEO_SURFACE_H
+#define TITANIC_VIDEO_SURFACE_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "graphics/managed_surface.h"
+#include "titanic/support/font.h"
+#include "titanic/support/direct_draw.h"
+#include "titanic/support/movie.h"
+#include "titanic/support/movie_range_info.h"
+#include "titanic/support/rect.h"
+#include "titanic/core/list.h"
+#include "titanic/core/resource_key.h"
+
+namespace Titanic {
+
+enum TransparencyMode {
+ TRANS_MASK0 = 0, TRANS_MASK255 = 1, TRANS_ALPHA0 = 2,
+ TRANS_ALPHA255 = 3, TRANS_DEFAULT = 4
+};
+
+class CScreenManager;
+class CJPEGDecode;
+class CTargaDecode;
+
+class CVideoSurface : public ListItem {
+ friend class CJPEGDecode;
+ friend class CTargaDecode;
+private:
+ /**
+ * Calculates blitting bounds
+ */
+ void clipBounds(Rect &srcRect, Rect &destRect, CVideoSurface *srcSurface,
+ const Rect *subRect = nullptr, const Point *destPos = nullptr);
+
+ void blitRect1(const Rect &srcRect, const Rect &destRect, CVideoSurface *src);
+ void blitRect2(const Rect &srcRect, const Rect &destRect, CVideoSurface *src);
+ void movieBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src);
+protected:
+ static int _videoSurfaceCounter;
+protected:
+ CScreenManager *_screenManager;
+ Graphics::ManagedSurface *_rawSurface;
+ bool _pendingLoad;
+ Graphics::ManagedSurface *_movieFrameSurface;
+ DisposeAfterUse::Flag _freeMovieSurface;
+ int _videoSurfaceNum;
+ bool _hasFrame;
+ int _lockCount;
+public:
+ CMovie *_movie;
+ DirectDrawSurface *_ddSurface;
+ bool _fastBlitFlag;
+ bool _transBlitFlag;
+ CResourceKey _resourceKey;
+ TransparencyMode _transparencyMode;
+public:
+ CVideoSurface(CScreenManager *screenManager);
+ virtual ~CVideoSurface();
+
+ /**
+ * Set the underlying surface for this video surface
+ */
+ void setSurface(CScreenManager *screenManager, DirectDrawSurface *surface);
+
+ /**
+ * Load the data for the class from file
+ */
+ virtual void load(SimpleFile *file) {
+ ListItem::load(file);
+ }
+
+ /**
+ * Load the surface with the passed resource
+ */
+ virtual void loadResource(const CResourceKey &key) = 0;
+
+ /**
+ * Loads a Targa image file specified by the resource key
+ */
+ virtual void loadTarga(const CResourceKey &key) = 0;
+
+ /**
+ * Loads a JPEG image file specified by the resource key
+ */
+ virtual void loadJPEG(const CResourceKey &key) = 0;
+
+ /**
+ * Loads a Targa image file specified by the given name
+ */
+ virtual void loadTarga(const CString &name) = 0;
+
+ /**
+ * Loads a movie file specified by the resource key.
+ * @param key Resource key for movie to load
+ * @param destroyFlag Immediately destroy movie after decoding first frame
+ */
+ virtual void loadMovie(const CResourceKey &key, bool destroyFlag = false) = 0;
+
+ /**
+ * Lock the surface for direct access to the pixels
+ */
+ virtual bool lock() = 0;
+
+ /**
+ * Unlocks the surface after prior calls to lock()
+ */
+ virtual void unlock() = 0;
+
+ /**
+ * Returns true if an underlying raw surface has been set
+ */
+ virtual bool hasSurface() = 0;
+
+ /**
+ * Returns the width of the surface
+ */
+ virtual int getWidth() = 0;
+
+ /**
+ * Returns the height of the surface
+ */
+ virtual int getHeight() = 0;
+
+ /**
+ * Returns the pitch of the surface in bytes
+ */
+ virtual int getPitch() = 0;
+
+ /**
+ * Returns the bytes per pixel of the surface
+ */
+ virtual int getBpp() = 0;
+
+ /**
+ * Recreates the surface
+ */
+ virtual void recreate(int width, int height) = 0;
+
+ /**
+ * Resizes the surface
+ */
+ virtual void resize(int width, int height) = 0;
+
+ /**
+ * Detachs the underlying raw surface
+ */
+ virtual void detachSurface() = 0;
+
+ /**
+ * Returns the number of bytes per pixel in the surface
+ */
+ virtual int getPixelDepth() = 0;
+
+ /**
+ * Gets the pixel at the specified position within the surface
+ */
+ virtual uint16 getPixel(const Common::Point &pt) = 0;
+
+
+ /**
+ * Sets a pixel at a specified position within the surface
+ */
+ virtual void setPixel(const Point &pt, uint pixel) = 0;
+
+ /**
+ * Change a pixel
+ */
+ virtual void changePixel(uint16 *pixelP, uint16 *color, byte srcVal, bool remapFlag = true) = 0;
+
+ /**
+ * Shifts the colors of the surface.. maybe greys it out?
+ */
+ virtual void shiftColors() = 0;
+
+ /**
+ * Clears the entire surface to black
+ */
+ virtual void clear() = 0;
+
+ /**
+ * Plays a movie, loading it from the specified _resource
+ * if not already loaded
+ */
+ virtual void playMovie(uint flags, CGameObject *obj) = 0;
+
+ /**
+ * Plays a movie, loading it from the specified _resource
+ * if not already loaded
+ */
+ virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0;
+
+ /**
+ * Plays a movie, loading it from the specified _resource
+ * if not already loaded
+ */
+ virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0;
+
+ /**
+ * Stops any movie currently attached to the surface
+ */
+ virtual void stopMovie() = 0;
+
+ /**
+ * Set the current movie frame number
+ */
+ virtual void setMovieFrame(uint frameNumber) = 0;
+
+ /**
+ * Adds a movie playback event
+ */
+ virtual void addMovieEvent(int eventId, CGameObject *obj) = 0;
+
+ /**
+ * Set the movie frame rate
+ */
+ virtual void setMovieFrameRate(double rate) = 0;
+
+ /**
+ * Return any movie range info associated with the surface's movie
+ */
+ virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0;
+
+ /**
+ *
+ */
+ virtual void flipVertically(bool needsLock = true) = 0;
+
+ /**
+ * Loads the surface's resource if there's one pending
+ */
+ virtual bool loadIfReady() = 0;
+
+ /**
+ * Loads the surface data based on the currently set resource key
+ */
+ virtual bool load() = 0;
+
+ /**
+ * Does a replacement of transparent pixels on certain lines at regular
+ * intervals. This is totally weird
+ */
+ virtual void transPixelate() = 0;
+
+ /**
+ * Returns true if there's a frame to display on the video surface
+ */
+ virtual bool hasFrame();
+
+ /**
+ * Duplicates movie frame surface
+ */
+ virtual Graphics::ManagedSurface *dupMovieFrame() const = 0;
+
+ /**
+ * Frees the underlying surface
+ */
+ virtual int freeSurface() { return 0; }
+
+ /**
+ * Get a pointer into the underlying surface
+ */
+ virtual uint16 *getBasePtr(int x, int y) = 0;
+
+ /**
+ * Blit from another surface
+ */
+ void blitFrom(const Point &destPos, CVideoSurface *src, const Rect *srcRect = nullptr);
+
+ /**
+ * Blit from another surface
+ */
+ void blitFrom(const Point &destPos, const Graphics::Surface *src);
+
+ /**
+ * Sets the movie frame surface containing frame data from an active movie
+ */
+ void setMovieFrameSurface(Graphics::ManagedSurface *frameSurface) { _movieFrameSurface = frameSurface; }
+
+ /**
+ * Get the previously set movie frame surface
+ */
+ Graphics::ManagedSurface *getMovieFrameSurface() const { return _movieFrameSurface; }
+
+ /**
+ * Get the pixels associated with the surface. Only valid when the
+ * surface has been locked for access
+ */
+ uint16 *getPixels() { return (uint16 *)_rawSurface->getPixels(); }
+
+ /**
+ * Get a reference to the underlying surface. Only valid when the surface
+ * has been locked for access
+ */
+ Graphics::ManagedSurface *getRawSurface() { return _rawSurface; }
+
+ /**
+ * Returns the transparent color
+ */
+ uint getTransparencyColor();
+};
+
+class OSVideoSurface : public CVideoSurface {
+ friend class OSMovie;
+private:
+ static byte _palette1[32][32];
+ static byte _palette2[32][32];
+
+ /**
+ * Setup the shading palettes
+ */
+ static void setupPalette(byte palette[32][32], byte val);
+public:
+ /**
+ * Setup statics
+ */
+ static void setup() {
+ setupPalette(_palette1, 0xff);
+ setupPalette(_palette2, 0xe0);
+ }
+public:
+ OSVideoSurface(CScreenManager *screenManager, DirectDrawSurface *surface);
+ OSVideoSurface(CScreenManager *screenManager, const CResourceKey &key, bool flag = false);
+
+ /**
+ * Load the surface with the passed resource
+ */
+ virtual void loadResource(const CResourceKey &key);
+
+ /**
+ * Loads a Targa image file specified by the resource key
+ */
+ virtual void loadTarga(const CResourceKey &key);
+
+ /**
+ * Loads a JPEG image file specified by the resource key
+ */
+ virtual void loadJPEG(const CResourceKey &key);
+
+ /**
+ * Loads a Targa image file specified by the given name
+ */
+ virtual void loadTarga(const CString &name);
+
+ /**
+ * Loads a movie file specified by the resource key.
+ * @param key Resource key for movie to load
+ * @param destroyFlag Immediately destroy movie after decoding first frame
+ */
+ virtual void loadMovie(const CResourceKey &key, bool destroyFlag = false);
+
+ /**
+ * Lock the surface for direct access to the pixels
+ */
+ virtual bool lock();
+
+ /**
+ * Unlocks the surface after prior calls to lock()
+ */
+ virtual void unlock();
+
+ /**
+ * Returns true if an underlying raw surface has been set
+ */
+ virtual bool hasSurface();
+
+ /**
+ * Returns the width of the surface
+ */
+ virtual int getWidth();
+
+ /**
+ * Returns the height of the surface
+ */
+ virtual int getHeight();
+
+ /**
+ * Returns the pitch of the surface in bytes
+ */
+ virtual int getPitch();
+
+ /**
+ * Returns the bytes per pixel of the surface
+ */
+ virtual int getBpp();
+
+ /**
+ * Recreates the surface with the designated size
+ */
+ virtual void recreate(int width, int height);
+
+ /**
+ * Resizes the surface
+ */
+ virtual void resize(int width, int height);
+
+ /**
+ * Detachs the underlying raw surface
+ */
+ virtual void detachSurface();
+
+ /**
+ * Returns the number of bytes per pixel in the surface
+ */
+ virtual int getPixelDepth();
+
+ /**
+ * Gets the pixel at the specified position within the surface
+ */
+ virtual uint16 getPixel(const Point &pt);
+
+ /**
+ * Sets a pixel at a specified position within the surface
+ */
+ virtual void setPixel(const Point &pt, uint pixel);
+
+ /**
+ * Change a pixel
+ */
+ virtual void changePixel(uint16 *pixelP, uint16 *color, byte srcVal, bool remapFlag = true);
+
+ /**
+ * Shifts the colors of the surface.. maybe greys it out?
+ */
+ virtual void shiftColors();
+
+ /**
+ * Clears the entire surface to black
+ */
+ virtual void clear();
+
+ /**
+ * Plays a movie, loading it from the specified _resource
+ * if not already loaded
+ */
+ virtual void playMovie(uint flags, CGameObject *obj);
+
+ /**
+ * Plays a movie, loading it from the specified _resource
+ * if not already loaded
+ */
+ virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj);
+
+ /**
+ * Plays a movie, loading it from the specified _resource
+ * if not already loaded
+ */
+ virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj);
+
+ /**
+ * Stops any movie currently attached to the surface
+ */
+ virtual void stopMovie();
+
+ /**
+ * Sets the movie to the specified frame number
+ */
+ virtual void setMovieFrame(uint frameNumber);
+
+ /**
+ * Adds a movie playback event
+ */
+ virtual void addMovieEvent(int frameNumber, CGameObject *obj);
+
+ /**
+ * Set the movie frame rate
+ */
+ virtual void setMovieFrameRate(double rate);
+
+ /**
+ * Return any movie range info associated with the surface's movie
+ */
+ virtual const CMovieRangeInfoList *getMovieRangeInfo() const;
+
+ /**
+ *
+ */
+ virtual void flipVertically(bool needsLock = true);
+
+ /**
+ * Loads the surface's resource if there's one pending
+ */
+ virtual bool loadIfReady();
+
+ /**
+ * Loads the surface data based on the currently set resource key
+ */
+ virtual bool load();
+
+ /**
+ * Does a replacement of transparent pixels on certain lines at regular
+ * intervals. This is totally weird
+ */
+ virtual void transPixelate();
+
+ /**
+ * Duplicates movie frame surface
+ */
+ virtual Graphics::ManagedSurface *dupMovieFrame() const;
+
+
+ /**
+ * Frees the underlying surface
+ */
+ virtual int freeSurface();
+
+ /**
+ * Get a pointer into the underlying surface
+ */
+ virtual uint16 *getBasePtr(int x, int y);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_VIDEO_SURFACE_H */