diff options
-rw-r--r-- | audio/audiostream.cpp | 55 | ||||
-rw-r--r-- | audio/audiostream.h | 7 | ||||
-rw-r--r-- | audio/decoders/aac.cpp | 1 | ||||
-rw-r--r-- | audio/decoders/qdm2.cpp | 1 | ||||
-rw-r--r-- | engines/scumm/charset.cpp | 95 | ||||
-rw-r--r-- | engines/scumm/charset.h | 29 | ||||
-rw-r--r-- | engines/scumm/nut_renderer.cpp | 55 | ||||
-rw-r--r-- | engines/scumm/smush/smush_font.cpp | 66 |
8 files changed, 241 insertions, 68 deletions
diff --git a/audio/audiostream.cpp b/audio/audiostream.cpp index 4dd5d236be..c413edb73d 100644 --- a/audio/audiostream.cpp +++ b/audio/audiostream.cpp @@ -98,7 +98,7 @@ LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops // TODO: Properly indicate error _loops = _completeIterations = 1; } - if (stream->endOfData()) { + if (stream->endOfStream()) { // Apparently this is an empty stream _loops = _completeIterations = 1; } @@ -122,7 +122,7 @@ int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) { _loops = _completeIterations = 1; return samplesRead; } - if (_parent->endOfData()) { + if (_parent->endOfStream()) { // Apparently this is an empty stream _loops = _completeIterations = 1; } @@ -134,7 +134,11 @@ int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) { } bool LoopingAudioStream::endOfData() const { - return (_loops != 0 && (_completeIterations == _loops)); + return (_loops != 0 && _completeIterations == _loops) || _parent->endOfData(); +} + +bool LoopingAudioStream::endOfStream() const { + return _loops != 0 && _completeIterations == _loops; } AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops) { @@ -189,7 +193,7 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) { int framesRead = _parent->readBuffer(buffer, framesLeft); _pos = _pos.addFrames(framesRead); - if (framesRead < framesLeft && _parent->endOfData()) { + if (framesRead < framesLeft && _parent->endOfStream()) { // TODO: Proper error indication. _done = true; return framesRead; @@ -216,6 +220,18 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) { } } +bool SubLoopingAudioStream::endOfData() const { + // We're out of data if this stream is finished or the parent + // has run out of data for now. + return _done || _parent->endOfData(); +} + +bool SubLoopingAudioStream::endOfStream() const { + // The end of the stream has been reached only when we've gone + // through all the iterations. + return _done; +} + #pragma mark - #pragma mark --- SubSeekableAudioStream --- #pragma mark - @@ -315,18 +331,27 @@ public: virtual int readBuffer(int16 *buffer, const int numSamples); virtual bool isStereo() const { return _stereo; } virtual int getRate() const { return _rate; } + virtual bool endOfData() const { - //Common::StackLock lock(_mutex); - return _queue.empty(); + Common::StackLock lock(_mutex); + return _queue.empty() || _queue.front()._stream->endOfData(); + } + + virtual bool endOfStream() const { + Common::StackLock lock(_mutex); + return _finished && _queue.empty(); } - virtual bool endOfStream() const { return _finished && _queue.empty(); } // Implement the QueuingAudioStream API virtual void queueAudioStream(AudioStream *stream, DisposeAfterUse::Flag disposeAfterUse); - virtual void finish() { _finished = true; } + + virtual void finish() { + Common::StackLock lock(_mutex); + _finished = true; + } uint32 numQueuedStreams() const { - //Common::StackLock lock(_mutex); + Common::StackLock lock(_mutex); return _queue.size(); } }; @@ -356,11 +381,17 @@ int QueuingAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) { AudioStream *stream = _queue.front()._stream; samplesDecoded += stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded); - if (stream->endOfData()) { + // Done with the stream completely + if (stream->endOfStream()) { StreamHolder tmp = _queue.pop(); if (tmp._disposeAfterUse == DisposeAfterUse::YES) delete stream; + continue; } + + // Done with data but not the stream, bail out + if (stream->endOfData()) + break; } return samplesDecoded; @@ -416,12 +447,14 @@ public: return samplesRead; } - bool endOfData() const { return _parentStream->endOfData() || _samplesRead >= _totalSamples; } + bool endOfData() const { return _parentStream->endOfData() || reachedLimit(); } + bool endOfStream() const { return _parentStream->endOfStream() || reachedLimit(); } bool isStereo() const { return _parentStream->isStereo(); } int getRate() const { return _parentStream->getRate(); } private: int getChannels() const { return isStereo() ? 2 : 1; } + bool reachedLimit() const { return _samplesRead >= _totalSamples; } AudioStream *_parentStream; DisposeAfterUse::Flag _disposeAfterUse; diff --git a/audio/audiostream.h b/audio/audiostream.h index d5d7d0b6c7..5202a4711c 100644 --- a/audio/audiostream.h +++ b/audio/audiostream.h @@ -118,6 +118,7 @@ public: int readBuffer(int16 *buffer, const int numSamples); bool endOfData() const; + bool endOfStream() const; bool isStereo() const { return _parent->isStereo(); } int getRate() const { return _parent->getRate(); } @@ -247,7 +248,8 @@ public: DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); int readBuffer(int16 *buffer, const int numSamples); - bool endOfData() const { return _done; } + bool endOfData() const; + bool endOfStream() const; bool isStereo() const { return _parent->isStereo(); } int getRate() const { return _parent->getRate(); } @@ -287,7 +289,8 @@ public: int getRate() const { return _parent->getRate(); } - bool endOfData() const { return (_pos >= _length) || _parent->endOfStream(); } + bool endOfData() const { return (_pos >= _length) || _parent->endOfData(); } + bool endOfStream() const { return (_pos >= _length) || _parent->endOfStream(); } bool seek(const Timestamp &where); diff --git a/audio/decoders/aac.cpp b/audio/decoders/aac.cpp index 7700bb3215..beabf7bff9 100644 --- a/audio/decoders/aac.cpp +++ b/audio/decoders/aac.cpp @@ -117,6 +117,7 @@ AudioStream *AACDecoder::decodeFrame(Common::SeekableReadStream &stream) { inBufferPos += frameInfo.bytesconsumed; } + audioStream->finish(); return audioStream; } diff --git a/audio/decoders/qdm2.cpp b/audio/decoders/qdm2.cpp index 743ca1cb7d..97d73b3a03 100644 --- a/audio/decoders/qdm2.cpp +++ b/audio/decoders/qdm2.cpp @@ -2607,6 +2607,7 @@ AudioStream *QDM2Stream::decodeFrame(Common::SeekableReadStream &stream) { while (qdm2_decodeFrame(stream, audioStream)) ; + audioStream->finish(); return audioStream; } diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 185ebbce6e..e546c805b5 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -253,7 +253,7 @@ CharsetRenderer::~CharsetRenderer() { CharsetRendererCommon::CharsetRendererCommon(ScummEngine *vm) : CharsetRenderer(vm), _bytesPerPixel(0), _fontHeight(0), _numChars(0) { - _shadowMode = false; + _enableShadow = false; _shadowColor = 0; } @@ -392,6 +392,10 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) { } else if (chr & 0x80) { pos++; width += _vm->_2byteWidth; + // Original keeps glyph width and character dimensions separately + if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) { + width++; + } continue; } } @@ -478,6 +482,12 @@ void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) { } else if (chr & 0x80) { pos++; curw += _vm->_2byteWidth; + // Original keeps glyph width and character dimensions separately + if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) { + curw++; + } + } else { + curw += getCharWidth(chr); } } else { curw += getCharWidth(chr); @@ -507,12 +517,17 @@ int CharsetRendererV3::getCharWidth(uint16 chr) { return spacing; } -void CharsetRendererV3::enableShadow(bool enable) { +void CharsetRendererPC::enableShadow(bool enable) { _shadowColor = 0; - _shadowMode = enable; + _enableShadow = enable; + + if (_vm->_game.version >= 7 && _vm->_language == Common::KO_KOR) + _shadowType = kHorizontalShadowType; + else + _shadowType = kNormalShadowType; } -void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) { +void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) { byte *dst = (byte *)dest.getBasePtr(x, y); byte bits = 0; @@ -525,8 +540,12 @@ void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const b if ((x % 8) == 0) bits = *src++; if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) { - if (_shadowMode) - dst[1] = dst2[0] = dst2[1] = _shadowColor; + if (_enableShadow) { + if (_shadowType == kNormalShadowType) + dst[1] = dst2[0] = dst2[1] = _shadowColor; + else if (_shadowType == kHorizontalShadowType) + dst[1] = _shadowColor; + } dst[0] = col; } dst += dest.format.bytesPerPixel; @@ -615,7 +634,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { if (_left + origWidth > _right + 1) return; - if (_shadowMode) { + if (_enableShadow) { width++; height++; } @@ -658,7 +677,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { if (_str.right < _left) { _str.right = _left; - if (_shadowMode) + if (_enableShadow) _str.right++; } @@ -776,11 +795,15 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { printCharIntern(is2byte, _charPtr, _origWidth, _origHeight, _width, _height, vs, ignoreCharsetMask); + // Original keeps glyph width and character dimensions separately + if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte) + _origWidth++; + _left += _origWidth; if (_str.right < _left) { _str.right = _left; - if (_vm->_game.platform != Common::kPlatformFMTowns && _shadowMode) + if (_vm->_game.platform != Common::kPlatformFMTowns && _enableShadow) _str.right++; } @@ -844,7 +867,10 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, drawTop = _top - _vm->_screenTop; } - drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight); + if (is2byte && _vm->_game.platform != Common::kPlatformFMTowns) + drawBits1(dstSurface, _left, drawTop, charPtr, drawTop, origWidth, origHeight); + else + drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight); if (_blitAlso && vs->hasTwoBuffers) { // FIXME: Revisiting this code, I think the _blitAlso mode is likely broken @@ -884,6 +910,24 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, } bool CharsetRendererClassic::prepareDraw(uint16 chr) { + bool is2byte = (chr >= 256 && _vm->_useCJKMode); + if (is2byte) { + if (_vm->_language == Common::KO_KOR) + enableShadow(true); + + _charPtr = _vm->get2byteCharPtr(chr); + _width = _origWidth = _vm->_2byteWidth; + _height = _origHeight = _vm->_2byteHeight; + _offsX = _offsY = 0; + + if (_enableShadow) { + _width++; + _height++; + } + + return true; + } + uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4); assert(charOffs < 0x14000); if (!charOffs) @@ -908,8 +952,14 @@ bool CharsetRendererClassic::prepareDraw(uint16 chr) { void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) { if (!prepareDraw(chr)) return; + byte *dst = (byte *)s.getBasePtr(x, y); - drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height); + + bool is2byte = (_vm->_useCJKMode && chr >= 256); + if (is2byte) + drawBits1(s, x, y, _charPtr, y, _width, _height); + else + drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height); } void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) { @@ -982,7 +1032,7 @@ int CharsetRendererTownsV3::getFontHeight() { void CharsetRendererTownsV3::enableShadow(bool enable) { _shadowColor = 8; - _shadowMode = enable; + _enableShadow = enable; #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE _shadowColor = 0x88; @@ -1027,13 +1077,13 @@ void CharsetRendererTownsV3::drawBits1(Graphics::Surface &dest, int x, int y, co bits = *src++; if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) { if (dest.format.bytesPerPixel == 2) { - if (_shadowMode) { + if (_enableShadow) { WRITE_UINT16(dst + 2, _vm->_16BitPalette[_shadowColor]); WRITE_UINT16(dst + dest.pitch, _vm->_16BitPalette[_shadowColor]); } WRITE_UINT16(dst, _vm->_16BitPalette[_color]); } else { - if (_shadowMode) { + if (_enableShadow) { #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE if (scale2x) { dst[2] = dst[3] = dst2[2] = dst2[3] = _shadowColor; @@ -1124,11 +1174,11 @@ void CharsetRendererPCE::drawBits1(Graphics::Surface &dest, int x, int y, const bits = *src++; if ((bits & revBitMask(bitCount % 8)) && y + drawTop >= 0) { if (dest.format.bytesPerPixel == 2) { - if (_shadowMode) + if (_enableShadow) WRITE_UINT16(dst + dest.pitch + 2, _vm->_16BitPalette[_shadowColor]); WRITE_UINT16(dst, _vm->_16BitPalette[_color]); } else { - if (_shadowMode) + if (_enableShadow) *(dst + dest.pitch + 1) = _shadowColor; *dst = _color; } @@ -1227,7 +1277,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) { int width = _current->getCharWidth(chr); int height = _current->getCharHeight(chr); - if (chr >= 256 && _vm->_useCJKMode) + bool is2byte = chr >= 256 && _vm->_useCJKMode; + if (is2byte) width = _vm->_2byteWidth; shadow.right = _left + width; @@ -1259,8 +1310,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) { _str.left = _left; // Original keeps glyph width and character dimensions separately - if (_vm->_language == Common::ZH_TWN && width == 16) - width = 17; + if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte) + width++; _left += width; @@ -1327,7 +1378,7 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) { if (_str.right < _left) { _str.right = _left; - if (_shadowMode) + if (_enableShadow) _str.right++; } @@ -1483,7 +1534,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) { _origHeight = _height = _vm->_2byteHeight; _charPtr = _vm->get2byteCharPtr(chr); _offsX = _offsY = 0; - if (_shadowMode) { + if (_enableShadow) { _width++; _height++; } @@ -1495,7 +1546,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) { } void CharsetRendererTownsClassic::setupShadowMode() { - _shadowMode = true; + _enableShadow = true; _shadowColor = _vm->_townsCharsetColorMap[0]; assert(_vm->_cjkFont); diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h index 5a9977b7d6..b4b3d88ccd 100644 --- a/engines/scumm/charset.h +++ b/engines/scumm/charset.h @@ -100,7 +100,7 @@ protected: int _numChars; byte _shadowColor; - bool _shadowMode; + bool _enableShadow; public: CharsetRendererCommon(ScummEngine *vm); @@ -110,7 +110,24 @@ public: virtual int getFontHeight(); }; -class CharsetRendererClassic : public CharsetRendererCommon { +class CharsetRendererPC : public CharsetRendererCommon { + enum ShadowType { + kNoShadowType, + kNormalShadowType, + kHorizontalShadowType + }; + + ShadowType _shadowType; + +protected: + virtual void enableShadow(bool enable); + virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height); + +public: + CharsetRendererPC(ScummEngine *vm) : CharsetRendererCommon(vm), _shadowType(kNoShadowType) { } +}; + +class CharsetRendererClassic : public CharsetRendererPC { protected: virtual void drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height); void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask); @@ -124,7 +141,7 @@ protected: VirtScreenNumber _drawScreen; public: - CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {} + CharsetRendererClassic(ScummEngine *vm) : CharsetRendererPC(vm) {} void printChar(int chr, bool ignoreCharsetMask); void drawChar(int chr, Graphics::Surface &s, int x, int y); @@ -170,10 +187,8 @@ public: int getCharWidth(uint16 chr) { return 8; } }; -class CharsetRendererV3 : public CharsetRendererCommon { +class CharsetRendererV3 : public CharsetRendererPC { protected: - virtual void enableShadow(bool enable); - virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height); virtual int getDrawWidthIntern(uint16 chr); virtual int getDrawHeightIntern(uint16 chr); virtual void setDrawCharIntern(uint16 chr) {} @@ -181,7 +196,7 @@ protected: const byte *_widthTable; public: - CharsetRendererV3(ScummEngine *vm) : CharsetRendererCommon(vm) {} + CharsetRendererV3(ScummEngine *vm) : CharsetRendererPC(vm) {} void printChar(int chr, bool ignoreCharsetMask); void drawChar(int chr, Graphics::Surface &s, int x, int y); diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp index 1d5761ef48..d8672c473c 100644 --- a/engines/scumm/nut_renderer.cpp +++ b/engines/scumm/nut_renderer.cpp @@ -395,10 +395,6 @@ void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byt } void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) { - // FIXME: This gets passed a const destination Surface. Intuitively this - // should never get written to. But sadly it does... For now we simply - // cast the const qualifier away. - byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y)); const int width = _vm->_2byteWidth; const int height = MIN(_vm->_2byteHeight, s.h - y); const byte *src = _vm->get2byteCharPtr(c); @@ -408,17 +404,50 @@ void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byt return; } - for (int ty = 0; ty < height; ty++) { - for (int tx = 0; tx < width; tx++) { - if ((tx & 7) == 0) - bits = *src++; - if (x + tx < 0 || x + tx >= s.w || y + ty < 0) - continue; - if (bits & revBitMask(tx % 8)) { - dst[tx] = color; + enum ShadowMode { + kNone, + kKoreanV8ShadowMode + }; + + ShadowMode shadowMode = kNone; + + if (_vm->_language == Common::KO_KOR && _vm->_game.version == 8) { + shadowMode = kKoreanV8ShadowMode; + } + + int shadowOffsetXTable[4] = {-1, 0, 1, 0}; + int shadowOffsetYTable[4] = {0, 1, 0, 0}; + int shadowOffsetColorTable[4] = {0, 0, 0, color}; + + int shadowIdx = 3; + if (shadowMode == kKoreanV8ShadowMode) + shadowIdx = 0; + + const byte *origSrc = src; + + for (; shadowIdx < 4; shadowIdx++) { + int offX = x + shadowOffsetXTable[shadowIdx]; + int offY = y + shadowOffsetYTable[shadowIdx]; + byte drawColor = shadowOffsetColorTable[shadowIdx]; + + // FIXME: This gets passed a const destination Surface. Intuitively this + // should never get written to. But sadly it does... For now we simply + // cast the const qualifier away. + byte *dst = (byte *)const_cast<void *>(s.getBasePtr(offX, offY)); + src = origSrc; + + for (int ty = 0; ty < height; ty++) { + for (int tx = 0; tx < width; tx++) { + if ((tx & 7) == 0) + bits = *src++; + if (offX + tx < 0 || offX + tx >= s.w || offY + ty < 0) + continue; + if (bits & revBitMask(tx % 8)) { + dst[tx] = drawColor; + } } + dst += s.pitch; } - dst += s.pitch; } } diff --git a/engines/scumm/smush/smush_font.cpp b/engines/scumm/smush/smush_font.cpp index 4c04901b42..e2f75a6862 100644 --- a/engines/scumm/smush/smush_font.cpp +++ b/engines/scumm/smush/smush_font.cpp @@ -115,9 +115,7 @@ int SmushFont::drawChar(byte *buffer, int dst_width, int x, int y, byte chr) { int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) { int w = _vm->_2byteWidth; int h = _vm->_2byteHeight; - - byte *src = _vm->get2byteCharPtr(idx); - byte *dst = buffer + dst_width * (y + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + x; + const byte *src = _vm->get2byteCharPtr(idx); byte bits = 0; char color = (_color != -1) ? _color : 1; @@ -128,18 +126,60 @@ int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) { if (_vm->_game.id == GID_FT) color = 1; - for (int j = 0; j < h; j++) { - for (int i = 0; i < w; i++) { - if ((i % 8) == 0) - bits = *src++; - if (bits & revBitMask(i % 8)) { - dst[i + 1] = 0; - dst[dst_width + i] = 0; - dst[dst_width + i + 1] = 0; - dst[i] = color; + enum ShadowMode { + kNone, + kNormalShadowMode, + kKoreanV7ShadowMode, + kKoreanV8ShadowMode + }; + + ShadowMode shadowMode = kNone; + + if (_vm->_language == Common::KO_KOR) { + if (_vm->_game.version == 8) + shadowMode = kKoreanV8ShadowMode; + else + shadowMode = kKoreanV7ShadowMode; + } + + int shadowOffsetXTable[4] = {-1, 0, 1, 0}; + int shadowOffsetYTable[4] = {0, 1, 0, 0}; + int shadowOffsetColorTable[4] = {0, 0, 0, color}; + + int shadowIdx = 3; + if (shadowMode == kKoreanV8ShadowMode) + shadowIdx = 0; + else if (shadowMode == kKoreanV7ShadowMode) + shadowIdx = 2; + + const byte *origSrc = src; + + for (; shadowIdx < 4; shadowIdx++) { + int offX = x + shadowOffsetXTable[shadowIdx]; + int offY = y + shadowOffsetYTable[shadowIdx]; + byte drawColor = shadowOffsetColorTable[shadowIdx]; + + src = origSrc; + + byte *dst = buffer + dst_width * (offY + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + offX; + + for (int j = 0; j < h; j++) { + for (int i = 0; i < w; i++) { + if (offX + i < 0) + continue; + if ((i % 8) == 0) + bits = *src++; + if (bits & revBitMask(i % 8)) { + if (shadowMode == kNormalShadowMode) { + dst[i + 1] = 0; + dst[dst_width + i] = 0; + dst[dst_width + i + 1] = 0; + } + dst[i] = drawColor; + } } + dst += dst_width; } - dst += dst_width; } return w + 1; } |