aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/support
diff options
context:
space:
mode:
Diffstat (limited to 'engines/titanic/support')
-rw-r--r--engines/titanic/support/avi_surface.cpp196
-rw-r--r--engines/titanic/support/avi_surface.h25
-rw-r--r--engines/titanic/support/credit_text.cpp4
-rw-r--r--engines/titanic/support/direct_draw.h2
-rw-r--r--engines/titanic/support/files_manager.cpp2
-rw-r--r--engines/titanic/support/files_manager.h2
-rw-r--r--engines/titanic/support/font.cpp9
-rw-r--r--engines/titanic/support/font.h4
-rw-r--r--engines/titanic/support/image_decoders.cpp4
-rw-r--r--engines/titanic/support/mouse_cursor.cpp54
-rw-r--r--engines/titanic/support/mouse_cursor.h8
-rw-r--r--engines/titanic/support/movie.cpp4
-rw-r--r--engines/titanic/support/movie.h30
-rw-r--r--engines/titanic/support/movie_clip.h2
-rw-r--r--engines/titanic/support/movie_range_info.cpp2
-rw-r--r--engines/titanic/support/screen_manager.cpp4
-rw-r--r--engines/titanic/support/screen_manager.h22
-rw-r--r--engines/titanic/support/simple_file.cpp12
-rw-r--r--engines/titanic/support/string.cpp4
-rw-r--r--engines/titanic/support/text_cursor.cpp6
-rw-r--r--engines/titanic/support/time_event_info.cpp4
-rw-r--r--engines/titanic/support/transparency_surface.cpp73
-rw-r--r--engines/titanic/support/transparency_surface.h84
-rw-r--r--engines/titanic/support/video_surface.cpp240
-rw-r--r--engines/titanic/support/video_surface.h89
25 files changed, 579 insertions, 307 deletions
diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp
index 2cc32971ae..9e465c705f 100644
--- a/engines/titanic/support/avi_surface.cpp
+++ b/engines/titanic/support/avi_surface.cpp
@@ -30,73 +30,46 @@
namespace Titanic {
-Video::AVIDecoder::AVIVideoTrack &AVIDecoder::getVideoTrack() {
- for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++)
- if ((*it)->getTrackType() == Track::kTrackTypeVideo)
- return *dynamic_cast<AVIVideoTrack *>(*it);
-
- error("Could not find video track");
-}
-
-/**
- * Track filter for AVIDecoder that filters out any secondary
- * video track some videos have to hold transparency masks
- */
-static bool primaryTrackSelect(bool isVideo, int trackCounter) {
- return !isVideo || trackCounter == 0;
-}
-
-/**
- * Track filter for AVIDecoder that only accepts the secondary
- * transparency msak video track for a video, if present
- */
-static bool secondaryTrackSelect(bool isVideo, int trackCounter) {
- return isVideo && trackCounter > 0;
+Video::AVIDecoder::AVIVideoTrack &AVIDecoder::getVideoTrack(uint idx) {
+ assert(idx < _videoTracks.size());
+ AVIVideoTrack *track = static_cast<AVIVideoTrack *>(_videoTracks[idx].track);
+ return *track;
}
AVISurface::AVISurface(const CResourceKey &key) {
_videoSurface = nullptr;
_streamCount = 0;
_movieFrameSurface[0] = _movieFrameSurface[1] = nullptr;
+ _framePixels = nullptr;
- // Reset current frame. We need to keep track of frames separately from the decoders,
+ // Reset current frame. We need to keep track of frames separately from the decoder,
// 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()))
+ // Create a decoder
+ _decoder = new AVIDecoder(Audio::Mixer::kPlainSoundType);
+ if (!_decoder->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;
- }
+ _streamCount = _decoder->videoTrackCount();
}
AVISurface::~AVISurface() {
if (_videoSurface)
- _videoSurface->_transBlitFlag = false;
+ _videoSurface->_flipVertically = false;
+ delete _framePixels;
delete _movieFrameSurface[0];
delete _movieFrameSurface[1];
- delete _decoders[0];
- delete _decoders[1];
+ delete _decoder;
}
bool AVISurface::play(uint flags, CGameObject *obj) {
if (flags & MOVIE_REVERSE)
- return play(_decoders[0]->getFrameCount() - 1, 0, flags, obj);
+ return play(_decoder->getFrameCount() - 1, 0, flags, obj);
else
- return play(0, _decoders[0]->getFrameCount() - 1, flags, obj);
+ return play(0, _decoder->getFrameCount() - 1, flags, obj);
}
bool AVISurface::play(int startFrame, int endFrame, uint flags, CGameObject *obj) {
@@ -121,26 +94,23 @@ bool AVISurface::play(int startFrame, int endFrame, int initialFrame, uint flags
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();
-
+ _decoder->stop();
_movieRangeInfo.destroyContents();
}
@@ -158,19 +128,14 @@ bool AVISurface::startAtFrame(int frameNumber) {
renderFrame();
// Start the playback
- _decoders[0]->start();
- if (_decoders[1])
- _decoders[1]->start();
-
+ _decoder->start();
+
return true;
}
void AVISurface::seekToFrame(uint frameNumber) {
if ((int)frameNumber != getFrame()) {
- _decoders[0]->seekToFrame(frameNumber);
- if (_decoders[1])
- _decoders[1]->seekToFrame(frameNumber);
-
+ _decoder->seekToFrame(frameNumber);
_currentFrame = (int)frameNumber;
}
@@ -178,10 +143,7 @@ void AVISurface::seekToFrame(uint frameNumber) {
}
void AVISurface::setReversed(bool isReversed) {
- _decoders[0]->setReverse(isReversed);
- if (_decoders[1])
- _decoders[1]->setReverse(isReversed);
-
+ _decoder->setReverse(isReversed);
_isReversed = isReversed;
}
@@ -219,7 +181,7 @@ bool AVISurface::handleEvents(CMovieEventList &events) {
setReversed(info->_isReversed);
seekToFrame(newFrame);
}
-
+
// Get any events for the given position
info->getMovieFrame(events, newFrame);
return renderFrame();
@@ -232,8 +194,8 @@ void AVISurface::setVideoSurface(CVideoSurface *surface) {
_videoSurface = surface;
// Handling for secondary video stream
- if (_decoders[1]) {
- const Common::String &streamName = _decoders[1]->getVideoTrack().getName();
+ if (_streamCount == 2) {
+ const Common::String &streamName = _decoder->getVideoTrack(1).getName();
if (streamName == "mask0") {
_videoSurface->_transparencyMode = TRANS_MASK0;
@@ -250,27 +212,56 @@ void AVISurface::setVideoSurface(CVideoSurface *surface) {
}
void AVISurface::setupDecompressor() {
- for (int idx = 0; idx < 2; ++idx) {
- if (!_decoders[idx])
- continue;
- AVIDecoder &decoder = *_decoders[idx];
+ if (!_decoder)
+ return;
+ for (int idx = 0; idx < _streamCount; ++idx) {
// Setup frame surface
- _movieFrameSurface[idx] = new Graphics::ManagedSurface(decoder.getWidth(), decoder.getHeight(),
- g_system->getScreenFormat());
+ _movieFrameSurface[idx] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(),
+ _decoder->getVideoTrack(idx).getPixelFormat());
+
+ bool flag = false;
+ if (idx == 0 && _videoSurface &&
+ _videoSurface->getPitch() == _movieFrameSurface[idx]->pitch) {
+ const uint bitCount = _decoder->getVideoTrack(0).getBitCount();
+ const int vDepth = _videoSurface->getPixelDepth();
+
+ switch (bitCount) {
+ case 15:
+ flag = vDepth == 1;
+ break;
+
+ case 16:
+ flag = vDepth == 1 || vDepth == 2;
+ break;
+
+ case 24:
+ flag = vDepth == 3;
+ break;
+
+ default:
+ break;
+ }
+ }
- // TODO: See whether this simplified form of original works
- if (idx == 1)
- _videoSurface->_transBlitFlag = true;
+ if (!flag) {
+ _framePixels = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(),
+ _decoder->getVideoTrack(0).getPixelFormat());
+ } else if (idx == 0) {
+ // The original developers used a vertical flipped playback to indicate
+ // an incompatibility between source video and dest surface bit-depths,
+ // which would result in poor playback performance
+ _videoSurface->_flipVertically = true;
+ }
}
}
uint AVISurface::getWidth() const {
- return _decoders[0]->getWidth();
+ return _decoder->getWidth();
}
uint AVISurface::getHeight() const {
- return _decoders[0]->getHeight();
+ return _decoder->getHeight();
}
void AVISurface::setFrame(int frameNumber) {
@@ -279,42 +270,49 @@ void AVISurface::setFrame(int frameNumber) {
stop();
// Ensure the frame number is valid
- if (frameNumber >= (int)_decoders[0]->getFrameCount())
- frameNumber = _decoders[0]->getFrameCount() - 1;
+ if (frameNumber >= (int)_decoder->getFrameCount())
+ frameNumber = _decoder->getFrameCount() - 1;
seekToFrame(frameNumber);
renderFrame();
}
bool AVISurface::isNextFrame() const {
- return _decoders[0]->getTimeToNextFrame() == 0;
+ return _decoder->getTimeToNextFrame() == 0;
}
bool AVISurface::renderFrame() {
// Check there's a frame ready for display
- if (!_decoders[0]->needsUpdate())
+ if (!_decoder->needsUpdate())
return false;
- // Decode each decoder's video stream into the appropriate surface
+ // Make a copy of each decoder's video frame
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;
- }
+ const Graphics::Surface *frame = (idx == 0) ?
+ _decoder->decodeNextFrame() : _decoder->decodeNextTransparency();
+
+ assert(_movieFrameSurface[idx]->format == frame->format);
+ _movieFrameSurface[idx]->blitFrom(*frame);
}
- // Blit the primary video frame onto the main overall surface
- _videoSurface->lock();
- _videoSurface->getRawSurface()->blitFrom(*_movieFrameSurface[0]);
- _videoSurface->unlock();
+ if (!_framePixels) {
+ if (_videoSurface->lock()) {
+ // Blit the frame directly to the video surface
+ assert(_streamCount == 1);
+ _videoSurface->blitFrom(Point(0, 0), &_movieFrameSurface[0]->rawSurface());
+
+ _videoSurface->unlock();
+ }
+ } else {
+ // Blit the primary video track's frame to the video surface
+ Graphics::Surface *s = _movieFrameSurface[0]->rawSurface().convertTo(
+ g_system->getScreenFormat(), _decoder->getPalette());
+ _videoSurface->lock();
+ _videoSurface->getRawSurface()->blitFrom(*s);
+ _videoSurface->unlock();
+ s->free();
+ delete s;
+ }
return false;
}
@@ -340,9 +338,7 @@ bool AVISurface::addEvent(int frameNumber, CGameObject *obj) {
}
void AVISurface::setFrameRate(double rate) {
- _decoders[0]->setRate(Common::Rational((int)rate));
- if (_decoders[1])
- _decoders[1]->setRate(Common::Rational((int)rate));
+ _decoder->setRate(Common::Rational((int)rate));
}
Graphics::ManagedSurface *AVISurface::getSecondarySurface() {
@@ -368,7 +364,7 @@ void AVISurface::playCutscene(const Rect &r, uint startFrame, uint endFrame) {
while (_currentFrame < (int)endFrame && !g_vm->shouldQuit()) {
if (isNextFrame()) {
renderFrame();
- _currentFrame = _decoders[0]->getCurFrame();
+ _currentFrame = _decoder->getCurFrame();
if (isDifferent) {
// Clear the destination area, and use the transBlitFrom method,
diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h
index 0acf7ab23b..b6231a646f 100644
--- a/engines/titanic/support/avi_surface.h
+++ b/engines/titanic/support/avi_surface.h
@@ -40,21 +40,30 @@ enum MovieFlag {
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();
+ AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType) :
+ Video::AVIDecoder(soundType) {}
+ AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType) :
+ Video::AVIDecoder(frameRateOverride, soundType) {}
+
+ /**
+ * Returns the number of video tracks the decoder has
+ */
+ uint videoTrackCount() const { return _videoTracks.size(); }
+
+ /**
+ * Returns the specified video track
+ */
+ Video::AVIDecoder::AVIVideoTrack &getVideoTrack(uint idx);
};
class AVISurface {
private:
- AVIDecoder *_decoders[2];
+ AVIDecoder *_decoder;
CVideoSurface *_videoSurface;
CMovieRangeInfoList _movieRangeInfo;
int _streamCount;
Graphics::ManagedSurface *_movieFrameSurface[2];
+ Graphics::ManagedSurface *_framePixels;
bool _isReversed;
int _currentFrame;
private:
@@ -113,7 +122,7 @@ public:
/**
* Return true if a video is currently playing
*/
- virtual bool isPlaying() const { return _decoders[0]->isPlaying(); }
+ virtual bool isPlaying() const { return _decoder->isPlaying(); }
/**
* Handle any movie events relevent for the frame
diff --git a/engines/titanic/support/credit_text.cpp b/engines/titanic/support/credit_text.cpp
index 009c3f4944..da6de6278e 100644
--- a/engines/titanic/support/credit_text.cpp
+++ b/engines/titanic/support/credit_text.cpp
@@ -67,7 +67,7 @@ void CCreditText::setup() {
// Create a new group and line within it
CCreditLineGroup *group = new CCreditLineGroup();
- CCreditLine *line = new CCreditLine(srcLine,
+ CCreditLine *line = new CCreditLine(srcLine,
_screenManagerP->stringWidth(srcLine));
group->_lines.push_back(line);
@@ -125,7 +125,7 @@ void CCreditText::handleDots(CCreditLineGroup *group) {
// 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
diff --git a/engines/titanic/support/direct_draw.h b/engines/titanic/support/direct_draw.h
index a7e9cc8d93..08ead6d798 100644
--- a/engines/titanic/support/direct_draw.h
+++ b/engines/titanic/support/direct_draw.h
@@ -70,7 +70,7 @@ public:
* @param width Screen width
* @param height Screen height
* @param bpp Bits per pixel
- * @param numBackSurfaces Number of back surfaces
+ * @param numBackSurfaces Number of back surfaces
*/
void initVideo(int width, int height, int bpp, int numBackSurfaces);
diff --git a/engines/titanic/support/files_manager.cpp b/engines/titanic/support/files_manager.cpp
index 22bff275d2..2882b8da85 100644
--- a/engines/titanic/support/files_manager.cpp
+++ b/engines/titanic/support/files_manager.cpp
@@ -75,7 +75,7 @@ bool CFilesManager::scanForFile(const CString &name) {
CString filename = name;
filename.toLowercase();
-
+
if (filename[0] == 'y' || filename[0] == 'z')
return true;
else if (filename[0] < 'a' || filename[0] > 'c')
diff --git a/engines/titanic/support/files_manager.h b/engines/titanic/support/files_manager.h
index a980ef1b25..45b067e86e 100644
--- a/engines/titanic/support/files_manager.h
+++ b/engines/titanic/support/files_manager.h
@@ -39,7 +39,7 @@ class CFilesManager {
struct ResourceEntry {
uint _offset;
uint _size;
-
+
ResourceEntry() : _offset(0), _size(0) {}
ResourceEntry(uint offset, uint size) : _offset(offset), _size(size) {}
};
diff --git a/engines/titanic/support/font.cpp b/engines/titanic/support/font.cpp
index e519237c3b..625d03720b 100644
--- a/engines/titanic/support/font.cpp
+++ b/engines/titanic/support/font.cpp
@@ -80,7 +80,7 @@ int STFont::getTextBounds(const CString &str, int maxWidth, Point *sizeOut) cons
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) {
@@ -296,8 +296,9 @@ void STFont::copyRect(CVideoSurface *surface, const Point &pt, Rect &rect) {
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);
+ const byte *transP = _dataPtr + yp * _dataWidth + xp;
+ surface->copyPixel(destP, &color, *transP >> 3,
+ surface->getRawSurface()->format, true);
}
}
@@ -330,7 +331,7 @@ void STFont::checkLineWrap(Point &textSize, int maxWidth, const char *&str) cons
flag = true;
}
}
-
+
if ((textSize.x + totalWidth) >= maxWidth && totalWidth < maxWidth) {
// Word wrap
textSize.x = 0;
diff --git a/engines/titanic/support/font.h b/engines/titanic/support/font.h
index 6c4fe8e9c3..685ab8ad73 100644
--- a/engines/titanic/support/font.h
+++ b/engines/titanic/support/font.h
@@ -50,13 +50,13 @@ 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,
+ void copyRect(CVideoSurface *surface, const Common::Point &destPos,
Rect &srcRect);
/**
* Write a character
*/
- WriteCharacterResult writeChar(CVideoSurface *surface, unsigned char c,
+ WriteCharacterResult writeChar(CVideoSurface *surface, unsigned char c,
const Common::Point &pt, const Rect &destRect, const Rect *srcRect);
/**
diff --git a/engines/titanic/support/image_decoders.cpp b/engines/titanic/support/image_decoders.cpp
index 495d1d0982..2dba66fbb3 100644
--- a/engines/titanic/support/image_decoders.cpp
+++ b/engines/titanic/support/image_decoders.cpp
@@ -32,9 +32,9 @@ void CJPEGDecode::decode(OSVideoSurface &surface, const CString &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
+ if (!surface.hasSurface() || surface.getWidth() != srcSurf->w
|| surface.getHeight() != srcSurf->h)
surface.recreate(srcSurf->w, srcSurf->h);
diff --git a/engines/titanic/support/mouse_cursor.cpp b/engines/titanic/support/mouse_cursor.cpp
index 0cefc368fa..4dd1ab4366 100644
--- a/engines/titanic/support/mouse_cursor.cpp
+++ b/engines/titanic/support/mouse_cursor.cpp
@@ -20,18 +20,16 @@
*
*/
-#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/support/transparency_surface.h"
#include "titanic/support/video_surface.h"
-#include "titanic/core/resource_key.h"
#include "titanic/titanic.h"
namespace Titanic {
+#define CURSOR_SIZE 64
+
static const int CURSOR_DATA[NUM_CURSORS][4] = {
{ 1, 136, 19, 18 },
{ 2, 139, 1, 1 },
@@ -52,10 +50,10 @@ static const int CURSOR_DATA[NUM_CURSORS][4] = {
CMouseCursor::CursorEntry::~CursorEntry() {
delete _videoSurface;
- delete _frameSurface;
+ delete _transSurface;
}
-CMouseCursor::CMouseCursor(CScreenManager *screenManager) :
+CMouseCursor::CMouseCursor(CScreenManager *screenManager) :
_screenManager(screenManager), _cursorId(CURSOR_HOURGLASS),
_setCursorCount(0), _fieldE4(0), _fieldE8(0) {
loadCursorImages();
@@ -75,16 +73,16 @@ void CMouseCursor::loadCursorImages() {
CURSOR_DATA[idx][3]);
// Create the surface
- CVideoSurface *surface = _screenManager->createSurface(64, 64);
+ CVideoSurface *surface = _screenManager->createSurface(CURSOR_SIZE, CURSOR_SIZE);
_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->setTransparencySurface(frameSurface);
+
+ Graphics::ManagedSurface *transSurface = movie.duplicateTransparency();
+ _cursors[idx]._transSurface = transSurface;
+ surface->setTransparencySurface(transSurface);
}
}
@@ -100,15 +98,35 @@ void CMouseCursor::setCursor(CursorId cursorId) {
++_setCursorCount;
if (cursorId != _cursorId) {
+ // The original cursors supported partial alpha when rendering the cursor.
+ // Since we're using the ScummVM CursorMan, we can't do that, so we need
+ // to build up a surface of the cursor with even partially transparent
+ // pixels as wholy transparent
CursorEntry &ce = _cursors[cursorId - 1];
- CVideoSurface &surface = *ce._videoSurface;
- surface.lock();
+ CVideoSurface &srcSurface = *ce._videoSurface;
+ srcSurface.lock();
+
+ Graphics::ManagedSurface surface(CURSOR_SIZE, CURSOR_SIZE, g_system->getScreenFormat());
+ const uint16 *srcP = srcSurface.getPixels();
+ CTransparencySurface transSurface(&ce._transSurface->rawSurface(), TRANS_DEFAULT);
+ uint16 *destP = (uint16 *)surface.getPixels();
- CursorMan.replaceCursor(surface.getPixels(), surface.getWidth(), surface.getHeight(),
- ce._centroid.x, ce._centroid.y, 0, false, &g_vm->_screen->format);
- surface.unlock();
+ for (int y = 0; y < CURSOR_SIZE; ++y) {
+ transSurface.setRow(y);
+ transSurface.setCol(0);
+ for (int x = 0; x < CURSOR_SIZE; ++x, ++srcP, ++destP) {
+ *destP = transSurface.isPixelTransparent() ? srcSurface.getTransparencyColor() : *srcP;
+ transSurface.moveX();
+ }
+ }
+
+ srcSurface.unlock();
+
+ // Set the cursor
_cursorId = cursorId;
+ CursorMan.replaceCursor(surface.getPixels(), CURSOR_SIZE, CURSOR_SIZE,
+ ce._centroid.x, ce._centroid.y, srcSurface.getTransparencyColor(), false, &g_vm->_screen->format);
}
}
@@ -129,7 +147,7 @@ void CMouseCursor::unlockE4() {
void CMouseCursor::setPosition(const Point &pt, double rate) {
assert(rate >= 0.0 && rate <= 1.0);
-
+
// TODO: Figure out use of the rate parameter
g_system->warpMouse(pt.x, pt.y);
}
diff --git a/engines/titanic/support/mouse_cursor.h b/engines/titanic/support/mouse_cursor.h
index 74fb1f6113..08de28e29d 100644
--- a/engines/titanic/support/mouse_cursor.h
+++ b/engines/titanic/support/mouse_cursor.h
@@ -55,10 +55,10 @@ class CVideoSurface;
class CMouseCursor {
struct CursorEntry {
CVideoSurface *_videoSurface;
- Graphics::ManagedSurface *_frameSurface;
+ Graphics::ManagedSurface *_transSurface;
Common::Point _centroid;
- CursorEntry() : _videoSurface(nullptr), _frameSurface(nullptr) {}
+ CursorEntry() : _videoSurface(nullptr), _transSurface(nullptr) {}
~CursorEntry();
};
private:
@@ -86,12 +86,12 @@ public:
* Hide the mouse cursor
*/
void hide();
-
+
/**
* Set the cursor
*/
void setCursor(CursorId cursorId);
-
+
/**
* Updates the mouse cursor
*/
diff --git a/engines/titanic/support/movie.cpp b/engines/titanic/support/movie.cpp
index a605cc3465..aea51e1a1e 100644
--- a/engines/titanic/support/movie.cpp
+++ b/engines/titanic/support/movie.cpp
@@ -125,7 +125,7 @@ void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags
void OSMovie::playCutscene(const Rect &drawRect, uint startFrame, uint endFrame) {
if (!_movieSurface)
_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340);
-
+
bool widthLess = _videoSurface->getWidth() < 600;
bool heightLess = _videoSurface->getHeight() < 340;
Rect r(drawRect.left, drawRect.top,
@@ -203,7 +203,7 @@ void OSMovie::setFrameRate(double rate) {
_aviSurface.setFrameRate(rate);
}
-Graphics::ManagedSurface *OSMovie::duplicateFrame() const {
+Graphics::ManagedSurface *OSMovie::duplicateTransparency() const {
return _aviSurface.duplicateTransparency();
}
diff --git a/engines/titanic/support/movie.h b/engines/titanic/support/movie.h
index 8c89f9e6dd..acc647065f 100644
--- a/engines/titanic/support/movie.h
+++ b/engines/titanic/support/movie.h
@@ -72,7 +72,7 @@ public:
* Starts playing the movie
*/
virtual void play(uint flags, CGameObject *obj) = 0;
-
+
/**
* Starts playing the movie
*/
@@ -82,13 +82,13 @@ public:
* 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, and doesn't return until either
* the playback ends or a key has been pressed
*/
virtual void playCutscene(const Rect &drawRect, uint startFrame, uint endFrame) = 0;
-
+
/**
* Stops the movie
*/
@@ -103,12 +103,12 @@ public:
* 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
*/
@@ -130,9 +130,9 @@ public:
virtual void setFrameRate(double rate) = 0;
/**
- * Creates a duplicate of the movie's frame
- */
- virtual Graphics::ManagedSurface *duplicateFrame() const = 0;
+ * Creates a duplicate of the transparency surface
+ */
+ virtual Graphics::ManagedSurface *duplicateTransparency() const = 0;
/**
* Removes the movie from the list of currently playing movies
@@ -171,17 +171,17 @@ public:
* 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, and doesn't return until either
* the playback ends or a key has been pressed
@@ -192,7 +192,7 @@ public:
* Stops the movie
*/
virtual void stop();
-
+
/**
* Add a playback event
*/
@@ -202,7 +202,7 @@ public:
* Set the current frame number
*/
virtual void setFrame(uint frameNumber);
-
+
/**
* Handle any pending movie events
*/
@@ -229,9 +229,9 @@ public:
virtual void setFrameRate(double rate);
/**
- * Creates a duplicate of the frame info
+ * Creates a duplicate of the transparency surface
*/
- virtual Graphics::ManagedSurface *duplicateFrame() const;
+ virtual Graphics::ManagedSurface *duplicateTransparency() const;
};
} // End of namespace Titanic
diff --git a/engines/titanic/support/movie_clip.h b/engines/titanic/support/movie_clip.h
index 513ed4a339..17c91b190c 100644
--- a/engines/titanic/support/movie_clip.h
+++ b/engines/titanic/support/movie_clip.h
@@ -27,7 +27,7 @@
namespace Titanic {
-enum ClipFlag {
+enum ClipFlag {
CLIPFLAG_HAS_END_FRAME = 1,
CLIPFLAG_4 = 4,
CLIPFLAG_HAS_START_FRAME = 8,
diff --git a/engines/titanic/support/movie_range_info.cpp b/engines/titanic/support/movie_range_info.cpp
index d4d9fc0e2a..018ffd63b5 100644
--- a/engines/titanic/support/movie_range_info.cpp
+++ b/engines/titanic/support/movie_range_info.cpp
@@ -91,7 +91,7 @@ void CMovieRangeInfo::process(CGameObject *owner) {
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_MOVIE_END) {
diff --git a/engines/titanic/support/screen_manager.cpp b/engines/titanic/support/screen_manager.cpp
index bcf43fc8cb..2e9bbcb6de 100644
--- a/engines/titanic/support/screen_manager.cpp
+++ b/engines/titanic/support/screen_manager.cpp
@@ -178,7 +178,7 @@ void OSScreenManager::blitFrom(SurfaceNum surfaceNum, CVideoSurface *src,
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;
@@ -220,7 +220,7 @@ void OSScreenManager::blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSu
destSurface->blitFrom(Point(rect->left, rect->top), src, rect);
}
-int OSScreenManager::writeString(int surfaceNum, const Rect &destRect,
+int OSScreenManager::writeString(int surfaceNum, const Rect &destRect,
int yOffset, const CString &str, CTextCursor *textCursor) {
CVideoSurface *surface;
Rect bounds;
diff --git a/engines/titanic/support/screen_manager.h b/engines/titanic/support/screen_manager.h
index cad6901b02..f88928af8b 100644
--- a/engines/titanic/support/screen_manager.h
+++ b/engines/titanic/support/screen_manager.h
@@ -78,7 +78,7 @@ public:
virtual void setWindowHandle(int v);
virtual bool resetWindowHandle(int v);
-
+
/**
* Sets the video mode
*/
@@ -88,17 +88,17 @@ public:
* 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
*/
@@ -108,7 +108,7 @@ public:
* Return the front render surface
*/
virtual CVideoSurface *getFrontRenderSurface() const = 0;
-
+
/**
* Fill an area with a specific color
*/
@@ -191,7 +191,7 @@ public:
* Creates a surface of a given size
*/
virtual CVideoSurface *createSurface(int w, int h) = 0;
-
+
/**
* Creates a surface from a specified resource
*/
@@ -213,7 +213,7 @@ public:
* Show the mouse cursor
*/
virtual void showCursor() = 0;
-
+
/**
* Hide the mouse cursor
*/
@@ -272,12 +272,12 @@ public:
* 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
*/
@@ -373,7 +373,7 @@ public:
* Creates a surface of a given size
*/
virtual CVideoSurface *createSurface(int w, int h);
-
+
/**
* Creates a surface from a specified resource
*/
@@ -383,7 +383,7 @@ public:
* Show the mouse cursor
*/
virtual void showCursor();
-
+
/**
* Hide the mouse cursor
*/
diff --git a/engines/titanic/support/simple_file.cpp b/engines/titanic/support/simple_file.cpp
index 35b2e28e4a..7e3cea35be 100644
--- a/engines/titanic/support/simple_file.cpp
+++ b/engines/titanic/support/simple_file.cpp
@@ -52,7 +52,7 @@ SimpleFile::~SimpleFile() {
}
void SimpleFile::open(Common::SeekableReadStream *stream) {
- close();
+ close();
_inStream = stream;
}
@@ -290,7 +290,7 @@ void SimpleFile::writeString(const CString &str) const {
const char *msgP = str.c_str();
char c;
-
+
while ((c = *msgP++) != '\0') {
switch (c) {
case '\r':
@@ -422,8 +422,8 @@ bool SimpleFile::scanf(const char *format, ...) {
while (!formatStr.empty()) {
if (formatStr.hasPrefix(" ")) {
formatStr.deleteChar(0);
-
- safeRead(&c, 1);
+
+ safeRead(&c, 1);
if (!Common::isSpace(c))
return false;
@@ -434,7 +434,7 @@ bool SimpleFile::scanf(const char *format, ...) {
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")) {
@@ -488,7 +488,7 @@ bool StdCWadFile::open(const Common::String &filename) {
CString resStr = name.mid(idx + 1, extPos - idx - 1);
int resIndex = resStr.readInt();
- // Open up the index for access
+ // Open up the index for access
f.open(fname);
int indexSize = f.readUint32LE() / 4;
assert(resIndex < indexSize);
diff --git a/engines/titanic/support/string.cpp b/engines/titanic/support/string.cpp
index 9961cfce59..cf1b29b6ec 100644
--- a/engines/titanic/support/string.cpp
+++ b/engines/titanic/support/string.cpp
@@ -41,7 +41,7 @@ CString CString::left(uint count) const {
CString CString::right(uint count) const {
uint strSize = size();
- return (count > strSize) ? CString() :
+ return (count > strSize) ? CString() :
CString(c_str() + strSize - count, c_str() + strSize);
}
@@ -85,7 +85,7 @@ FileType CString::fileTypeSuffix() const {
return FILETYPE_WAV;
else if (ext == "2" || ext == "3")
return FILETYPE_MOVIE;
-
+
ext = right(3);
if (ext == "tga" || ext == "jpg")
return FILETYPE_IMAGE;
diff --git a/engines/titanic/support/text_cursor.cpp b/engines/titanic/support/text_cursor.cpp
index ad3fe4ed26..5c7593ba68 100644
--- a/engines/titanic/support/text_cursor.cpp
+++ b/engines/titanic/support/text_cursor.cpp
@@ -27,7 +27,7 @@
namespace Titanic {
-CTextCursor::CTextCursor(CScreenManager *screenManager) :
+CTextCursor::CTextCursor(CScreenManager *screenManager) :
_screenManager(screenManager), _active(false), _blinkVisible(false),
_backRenderSurface(nullptr), _frontRenderSurface(nullptr),
_blinkDelay(300), _size(2, 10), _priorBlinkTime(0),
@@ -70,7 +70,7 @@ void CTextCursor::draw() {
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);
@@ -80,7 +80,7 @@ void CTextCursor::draw() {
_backRenderSurface->_ddSurface->fillRect(&cursorRect,
_cursorR, _cursorG, _cursorB);
}
-
+
//_screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &_pos);
}
}
diff --git a/engines/titanic/support/time_event_info.cpp b/engines/titanic/support/time_event_info.cpp
index 0226223f1a..e088a8e0c2 100644
--- a/engines/titanic/support/time_event_info.cpp
+++ b/engines/titanic/support/time_event_info.cpp
@@ -90,7 +90,7 @@ void CTimeEventInfoList::setPersisent(uint id, bool flag) {
uint CTimeEventInfo::_nextId;
-CTimeEventInfo::CTimeEventInfo() : ListItem(), _lockCounter(0),
+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) {
@@ -147,7 +147,7 @@ void CTimeEventInfo::load(SimpleFile *file) {
void CTimeEventInfo::postLoad(uint ticks, CProjectItem *project) {
if (!_persisent || _targetName.empty())
_done = true;
-
+
// Get the timer's target
if (project)
_target = project->findByName(_targetName);
diff --git a/engines/titanic/support/transparency_surface.cpp b/engines/titanic/support/transparency_surface.cpp
new file mode 100644
index 0000000000..5ffa8b99b1
--- /dev/null
+++ b/engines/titanic/support/transparency_surface.cpp
@@ -0,0 +1,73 @@
+/* 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/transparency_surface.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Titanic {
+
+CTransparencySurface::CTransparencySurface(const Graphics::Surface *surface,
+ TransparencyMode transMode) : _surface(surface) {
+ _pitch = 0;
+ _runLength = 0;
+ _flag = false;
+ _flag1 = false;
+ _flag2 = true;
+
+ switch (transMode) {
+ case TRANS_MASK0:
+ case TRANS_ALPHA0:
+ _flag2 = false;
+ _flag1 = true;
+ break;
+ case TRANS_MASK255:
+ case TRANS_ALPHA255:
+ _flag2 = true;
+ _flag1 = false;
+ break;
+ case TRANS_DEFAULT:
+ if (*(byte *)surface->getPixels() < 0x80) {
+ _flag1 = true;
+ _flag2 = false;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+int CTransparencySurface::moveX() {
+ if (++_pos.x >= _surface->w) {
+ _pos.x = 0;
+ ++_pos.y;
+ }
+
+ return 1;
+}
+
+uint CTransparencySurface::getPixel() const {
+ const byte *pixelP = (const byte *)_surface->getBasePtr(_pos.x, _pos.y);
+ return *pixelP;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/support/transparency_surface.h b/engines/titanic/support/transparency_surface.h
new file mode 100644
index 0000000000..0391b6d5b7
--- /dev/null
+++ b/engines/titanic/support/transparency_surface.h
@@ -0,0 +1,84 @@
+/* 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_TRANSPARENCY_SURFACE_H
+#define TITANIC_TRANSPARENCY_SURFACE_H
+
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Titanic {
+
+enum TransparencyMode {
+ TRANS_MASK0 = 0, TRANS_MASK255 = 1, TRANS_ALPHA0 = 2,
+ TRANS_ALPHA255 = 3, TRANS_DEFAULT = 4
+};
+
+class CTransparencySurface {
+private:
+ const Graphics::Surface *_surface;
+ Common::Point _pos;
+ int _pitch;
+ int _runLength;
+ bool _flag;
+ bool _flag1;
+ bool _flag2;
+public:
+ /**
+ * Constructor
+ */
+ CTransparencySurface(const Graphics::Surface *surface, TransparencyMode transMode);
+
+ /**
+ * Sets the row to get transparencies from
+ */
+ void setRow(int yp) { _pos.y = yp; }
+
+ /**
+ * Sets the column to get transparencies from
+ */
+ void setCol(int xp) { _pos.x = xp; }
+
+ /**
+ * Moves reading position horizontally by a single pixel
+ */
+ int moveX();
+
+ /**
+ * Returns a byte from the transparency surface
+ */
+ uint getPixel() const;
+
+ /**
+ * Returns the alpha value for the pixel (0-31)
+ */
+ uint getAlpha() const { return 31 - (getPixel() >> 3); }
+
+ /**
+ * Returns true if the pixel is completely transparent
+ */
+ bool isPixelTransparent() const { return getAlpha() == 31; }
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_TRANSPARENCY_SURFACE_H */
diff --git a/engines/titanic/support/video_surface.cpp b/engines/titanic/support/video_surface.cpp
index 63ad782722..45813bb740 100644
--- a/engines/titanic/support/video_surface.cpp
+++ b/engines/titanic/support/video_surface.cpp
@@ -23,16 +23,19 @@
#include "titanic/support/video_surface.h"
#include "titanic/support/image_decoders.h"
#include "titanic/support/screen_manager.h"
+#include "titanic/support/transparency_surface.h"
#include "titanic/titanic.h"
namespace Titanic {
int CVideoSurface::_videoSurfaceCounter = 0;
+byte CVideoSurface::_palette1[32][32];
+byte CVideoSurface::_palette2[32][32];
CVideoSurface::CVideoSurface(CScreenManager *screenManager) :
_screenManager(screenManager), _rawSurface(nullptr), _movie(nullptr),
- _pendingLoad(false), _transBlitFlag(false), _fastBlitFlag(false),
- _transparencySurface(nullptr), _transparencyMode(TRANS_DEFAULT),
+ _pendingLoad(false), _flipVertically(false), _fastBlitFlag(false),
+ _transparencySurface(nullptr), _transparencyMode(TRANS_DEFAULT),
_freeTransparencySurface(DisposeAfterUse::NO), _hasFrame(true), _lockCount(0) {
_videoSurfaceNum = _videoSurfaceCounter++;
}
@@ -46,6 +49,19 @@ CVideoSurface::~CVideoSurface() {
delete _transparencySurface;
}
+void CVideoSurface::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) {
+ uint v = base / 31;
+ palette[idx1][idx2] = (byte)v;
+
+ if (val != 0xff && v != idx2) {
+ assert(0);
+ }
+ }
+ }
+}
+
void CVideoSurface::setSurface(CScreenManager *screenManager, DirectDrawSurface *surface) {
_screenManager = screenManager;
_ddSurface = surface;
@@ -56,10 +72,10 @@ void CVideoSurface::blitFrom(const Point &destPos, CVideoSurface *src, const Rec
Rect srcBounds, destBounds;
clipBounds(srcBounds, destBounds, src, srcRect, &destPos);
- if (src->_transBlitFlag)
- blitRect2(srcBounds, destBounds, src);
+ if (src->_flipVertically)
+ flippedBlitRect(srcBounds, destBounds, src);
else
- blitRect1(srcBounds, destBounds, src);
+ blitRect(srcBounds, destBounds, src);
}
}
@@ -132,44 +148,118 @@ void CVideoSurface::clipBounds(Rect &srcRect, Rect &destRect,
error("Invalid rect");
}
-void CVideoSurface::blitRect1(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) {
+void CVideoSurface::blitRect(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 (getTransparencySurface()) {
- transBlitRect(srcRect, destRect, src);
- } else {
- _rawSurface->transBlitFrom(*src->_rawSurface, srcRect, destRect, src->getTransparencyColor());
- }
+ } else if (src->getTransparencySurface()) {
+ transBlitRect(srcRect, destRect, src, false);
+ } else if (lock()) {
+ if (src->lock()) {
+ const Graphics::ManagedSurface *srcSurface = src->_rawSurface;
+ Graphics::ManagedSurface *destSurface = _rawSurface;
+ Graphics::Surface destArea = destSurface->getSubArea(destRect);
+ const uint transColor = src->getTransparencyColor();
+
+ const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr(
+ srcRect.left, srcRect.top);
+ uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, 0);
+
+ for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr,
+ srcPtr += src->getPitch() / 2,
+ destPtr += destArea.pitch / 2) {
+ // Prepare for copying the line
+ const uint16 *lineSrcP = srcPtr;
+ uint16 *lineDestP = destPtr;
+
+ for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX, ++lineSrcP, ++lineDestP) {
+ if (*lineSrcP != transColor)
+ *lineDestP = *lineSrcP;
+ }
+ }
- src->unlock();
- unlock();
+ src->unlock();
+ }
+
+ unlock();
+ }
}
-void CVideoSurface::blitRect2(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) {
- if (getTransparencySurface()) {
- transBlitRect(srcRect, destRect, src);
- } else {
- src->lock();
- lock();
+void CVideoSurface::flippedBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) {
+ if (src->getTransparencySurface()) {
+ transBlitRect(srcRect, destRect, src, true);
+ } else if (lock()) {
+ if (src->lock()) {
+ const Graphics::ManagedSurface *srcSurface = src->_rawSurface;
+ Graphics::ManagedSurface *destSurface = _rawSurface;
+ Graphics::Surface destArea = destSurface->getSubArea(destRect);
+ const uint transColor = src->getTransparencyColor();
+
+ const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr(
+ srcRect.left, srcRect.top);
+ uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, destArea.h - 1);
+
+ for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr,
+ srcPtr += src->getPitch() / 2,
+ destPtr -= destArea.pitch / 2) {
+ // Prepare for copying the line
+ const uint16 *lineSrcP = srcPtr;
+ uint16 *lineDestP = destPtr;
+
+ for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX, ++lineSrcP, ++lineDestP) {
+ if (*lineSrcP != transColor)
+ *lineDestP = *lineSrcP;
+ }
+ }
- _rawSurface->blitFrom(*src->_rawSurface, srcRect, Point(destRect.left, destRect.top));
+ src->unlock();
+ }
- src->unlock();
unlock();
}
}
-void CVideoSurface::transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) {
+void CVideoSurface::transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src, bool flipFlag) {
+ assert(srcRect.width() == destRect.width() && srcRect.height() == destRect.height());
+
if (lock()) {
if (src->lock()) {
Graphics::ManagedSurface *srcSurface = src->_rawSurface;
Graphics::ManagedSurface *destSurface = _rawSurface;
-
- // TODO: Handle the transparency mode correctly
- destSurface->blitFrom(*srcSurface, srcRect, Point(srcRect.left, srcRect.top));
+ Graphics::Surface destArea = destSurface->getSubArea(destRect);
+
+ const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr(
+ srcRect.left, flipFlag ? srcRect.top : srcRect.bottom - 1);
+ uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, destArea.h - 1);
+ bool isAlpha = src->_transparencyMode == TRANS_ALPHA0 ||
+ src->_transparencyMode == TRANS_ALPHA255;
+
+ CTransparencySurface transSurface(src->getTransparencySurface(), src->_transparencyMode);
+
+ for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) {
+ // Prepare for copying the line
+ const uint16 *lineSrcP = srcPtr;
+ uint16 *lineDestP = destPtr;
+ transSurface.setRow(flipFlag ? srcRect.top + yCtr : srcRect.bottom - yCtr - 1);
+ transSurface.setCol(srcRect.left);
+
+ for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX) {
+ if (!transSurface.isPixelTransparent()) {
+ copyPixel(lineDestP, lineSrcP, transSurface.getAlpha(), srcSurface->format, isAlpha);
+ }
+
+ ++lineSrcP;
+ ++lineDestP;
+ transSurface.moveX();
+ }
+
+ // Move to next line
+ srcPtr = flipFlag ? srcPtr + (src->getPitch() / 2) :
+ srcPtr - (src->getPitch() / 2);
+ destPtr -= destArea.pitch / 2;
+ }
src->unlock();
}
@@ -196,10 +286,40 @@ bool CVideoSurface::hasFrame() {
}
}
-/*------------------------------------------------------------------------*/
+#define RGB_SHIFT 3
+void CVideoSurface::copyPixel(uint16 *destP, const uint16 *srcP, byte alpha,
+ const Graphics::PixelFormat &srcFormat, bool isAlpha) {
+ const Graphics::PixelFormat destFormat = _ddSurface->getFormat();
+ alpha &= 0xff;
+ assert(alpha < 32);
+
+ // Get the source color
+ byte r, g, b;
+ srcFormat.colorToRGB(*srcP, r, g, b);
+ r >>= RGB_SHIFT;
+ g >>= RGB_SHIFT;
+ b >>= RGB_SHIFT;
+
+ if (isAlpha) {
+ r = _palette1[31 - alpha][r];
+ g = _palette1[31 - alpha][g];
+ b = _palette1[31 - alpha][b];
+ }
-byte OSVideoSurface::_palette1[32][32];
-byte OSVideoSurface::_palette2[32][32];
+ byte r2, g2, b2;
+ destFormat.colorToRGB(*destP, r2, g2, b2);
+ r2 >>= RGB_SHIFT;
+ g2 >>= RGB_SHIFT;
+ b2 >>= RGB_SHIFT;
+ r2 = _palette1[alpha][r2];
+ g2 = _palette1[alpha][g2];
+ b2 = _palette1[alpha][b2];
+
+ *destP = destFormat.RGBToColor((r + r2) << RGB_SHIFT,
+ (g + g2) << RGB_SHIFT, (b + b2) << RGB_SHIFT);
+}
+
+/*------------------------------------------------------------------------*/
OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, DirectDrawSurface *surface) :
CVideoSurface(screenManager) {
@@ -210,7 +330,7 @@ OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, const CResourceKey
CVideoSurface(screenManager) {
_ddSurface = nullptr;
_pendingLoad = pendingLoad;
-
+
if (_pendingLoad) {
loadResource(key);
} else {
@@ -219,24 +339,6 @@ OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, const CResourceKey
}
}
-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;
@@ -351,7 +453,7 @@ void OSVideoSurface::recreate(int width, int height) {
}
void OSVideoSurface::resize(int width, int height) {
- if (!_ddSurface || _ddSurface->getWidth() != width ||
+ if (!_ddSurface || _ddSurface->getWidth() != width ||
_ddSurface->getHeight() != height)
recreate(width, height);
}
@@ -365,7 +467,7 @@ int OSVideoSurface::getPixelDepth() {
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
@@ -408,8 +510,13 @@ uint16 OSVideoSurface::getPixel(const Common::Point &pt) {
if (pt.x >= 0 && pt.y >= 0 && pt.x < getWidth() && pt.y < getHeight()) {
if (_transparencySurface) {
- const byte *pixelP = (const byte *)_transparencySurface->getBasePtr(pt.x, pt.y);
- if (*pixelP != 0xF0)
+ // WORKAROUND: Original had the setRow _flipVertically check in reverse.
+ // Pretty sure putting it the way is below is the correct way
+ CTransparencySurface transSurface(&_transparencySurface->rawSurface(), _transparencyMode);
+ transSurface.setRow(_flipVertically ? getHeight() - pt.y - 1 : pt.y);
+ transSurface.setCol(pt.x);
+
+ if (transSurface.isPixelTransparent())
return getTransparencyColor();
}
@@ -429,29 +536,6 @@ void OSVideoSurface::setPixel(const Point &pt, uint pixel) {
*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;
@@ -510,7 +594,7 @@ const CMovieRangeInfoList *OSVideoSurface::getMovieRangeInfo() const {
}
void OSVideoSurface::flipVertically(bool needsLock) {
- if (!loadIfReady() || !_transBlitFlag)
+ if (!loadIfReady() || !_flipVertically)
return;
if (needsLock)
@@ -529,7 +613,7 @@ void OSVideoSurface::flipVertically(bool needsLock) {
Common::copy(lineBuffer, lineBuffer + pitch, line1P);
}
- _transBlitFlag = false;
+ _flipVertically = false;
if (needsLock)
unlock();
}
@@ -576,8 +660,8 @@ void OSVideoSurface::transPixelate() {
unlock();
}
-Graphics::ManagedSurface *OSVideoSurface::dupMovieFrame() const {
- return _movie ? _movie->duplicateFrame() : nullptr;
+Graphics::ManagedSurface *OSVideoSurface::dupMovieTransparency() const {
+ return _movie ? _movie->duplicateTransparency() : nullptr;
}
int OSVideoSurface::freeSurface() {
diff --git a/engines/titanic/support/video_surface.h b/engines/titanic/support/video_surface.h
index c21149333d..690669b79b 100644
--- a/engines/titanic/support/video_surface.h
+++ b/engines/titanic/support/video_surface.h
@@ -31,16 +31,12 @@
#include "titanic/support/movie.h"
#include "titanic/support/movie_range_info.h"
#include "titanic/support/rect.h"
+#include "titanic/support/transparency_surface.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;
@@ -49,15 +45,38 @@ class CVideoSurface : public ListItem {
friend class CJPEGDecode;
friend class CTargaDecode;
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);
+ }
+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 transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src);
+ /**
+ * Copies a rect from a given source surface
+ */
+ void blitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src);
+
+ /**
+ * Copies a rect from a given source surface and draws it vertically flipped
+ */
+ void flippedBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src);
+
+ void transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src, bool flipFlag);
protected:
static int _videoSurfaceCounter;
protected:
@@ -73,7 +92,7 @@ public:
CMovie *_movie;
DirectDrawSurface *_ddSurface;
bool _fastBlitFlag;
- bool _transBlitFlag;
+ bool _flipVertically;
CResourceKey _resourceKey;
TransparencyMode _transparencyMode;
public:
@@ -186,11 +205,6 @@ public:
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;
@@ -270,9 +284,9 @@ public:
virtual bool hasFrame();
/**
- * Duplicates movie frame surface
+ * Duplicates movie transparency surface
*/
- virtual Graphics::ManagedSurface *dupMovieFrame() const = 0;
+ virtual Graphics::ManagedSurface *dupMovieTransparency() const = 0;
/**
* Frees the underlying surface
@@ -302,7 +316,9 @@ public:
/**
* Get the previously set transparency mask surface
*/
- Graphics::ManagedSurface *getTransparencySurface() const { return _transparencySurface; }
+ const Graphics::Surface *getTransparencySurface() const {
+ return _transparencySurface ? &_transparencySurface->rawSurface() : nullptr;
+ }
/**
* Get the pixels associated with the surface. Only valid when the
@@ -320,26 +336,23 @@ public:
* Returns the transparent color
*/
uint getTransparencyColor();
+
+ /**
+ * Copies a pixel, handling transparency
+ * @param destP Dest pointer to 16-bit pixel
+ * @param srcP Source pointer to 16-bit pixel
+ * @param alpha Alpha (0-31). At 0, it's completely opaque,
+ * and overwrites the dest pixel. Through to 31, which is completely
+ * transparent, and ignores the source pixel.
+ * @param srcFormat The source surface format
+ * @param isAlpha If true, has alpha channel
+ */
+ void copyPixel(uint16 *destP, const uint16 *srcP, byte alpha,
+ const Graphics::PixelFormat &srcFormat, bool isAlpha);
};
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);
@@ -437,11 +450,6 @@ public:
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();
@@ -516,10 +524,9 @@ public:
virtual void transPixelate();
/**
- * Duplicates movie frame surface
+ * Duplicates movie transparency surface
*/
- virtual Graphics::ManagedSurface *dupMovieFrame() const;
-
+ virtual Graphics::ManagedSurface *dupMovieTransparency() const;
/**
* Frees the underlying surface