diff options
Diffstat (limited to 'engines/sci/graphics/celobj32.cpp')
-rw-r--r-- | engines/sci/graphics/celobj32.cpp | 118 |
1 files changed, 50 insertions, 68 deletions
diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp index a49690a703..c2ae29b24e 100644 --- a/engines/sci/graphics/celobj32.cpp +++ b/engines/sci/graphics/celobj32.cpp @@ -35,7 +35,7 @@ namespace Sci { #pragma mark CelScaler -CelScaler *CelObj::_scaler = nullptr; +Common::ScopedPtr<CelScaler> CelObj::_scaler; void CelScaler::activateScaleTables(const Ratio &scaleX, const Ratio &scaleY) { for (int i = 0; i < ARRAYSIZE(_scaleTables); ++i) { @@ -74,9 +74,9 @@ void CelScaler::buildLookupTable(int *table, const Ratio &ratio, const int size) } } -const CelScalerTable *CelScaler::getScalerTable(const Ratio &scaleX, const Ratio &scaleY) { +const CelScalerTable &CelScaler::getScalerTable(const Ratio &scaleX, const Ratio &scaleY) { activateScaleTables(scaleX, scaleY); - return &_scaleTables[_activeIndex]; + return _scaleTables[_activeIndex]; } #pragma mark - @@ -87,21 +87,13 @@ void CelObj::init() { CelObj::deinit(); _drawBlackLines = false; _nextCacheId = 1; - _scaler = new CelScaler(); - _cache = new CelCache; - _cache->resize(100); + _scaler.reset(new CelScaler()); + _cache.reset(new CelCache(100)); } void CelObj::deinit() { - delete _scaler; - _scaler = nullptr; - if (_cache != nullptr) { - for (CelCache::iterator it = _cache->begin(); it != _cache->end(); ++it) { - delete it->celObj; - } - } - delete _cache; - _cache = nullptr; + _scaler.reset(); + _cache.reset(); } #pragma mark - @@ -172,10 +164,9 @@ struct SCALER_Scale { _minX(targetRect.left), _maxX(targetRect.right - 1), #endif - // The maximum width of the scaled object may not be as - // wide as the source data it requires if downscaling, - // so just always make the reader decompress an entire - // line of source data when scaling + // The maximum width of the scaled object may not be as wide as the source + // data it requires if downscaling, so just always make the reader + // decompress an entire line of source data when scaling _reader(celObj, celObj._width) { #ifndef NDEBUG assert(_minX <= _maxX); @@ -203,39 +194,39 @@ struct SCALER_Scale { // games which use global scaling are the ones that use low-resolution // script coordinates too. - const CelScalerTable *table = CelObj::_scaler->getScalerTable(scaleX, scaleY); + const CelScalerTable &table = CelObj::_scaler->getScalerTable(scaleX, scaleY); - if (g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth == kLowResX) { + if (g_sci->_gfxFrameout->getScriptWidth() == kLowResX) { const int16 unscaledX = (scaledPosition.x / scaleX).toInt(); if (FLIP) { const int lastIndex = celObj._width - 1; for (int16 x = targetRect.left; x < targetRect.right; ++x) { - _valuesX[x] = lastIndex - (table->valuesX[x] - unscaledX); + _valuesX[x] = lastIndex - (table.valuesX[x] - unscaledX); } } else { for (int16 x = targetRect.left; x < targetRect.right; ++x) { - _valuesX[x] = table->valuesX[x] - unscaledX; + _valuesX[x] = table.valuesX[x] - unscaledX; } } const int16 unscaledY = (scaledPosition.y / scaleY).toInt(); for (int16 y = targetRect.top; y < targetRect.bottom; ++y) { - _valuesY[y] = table->valuesY[y] - unscaledY; + _valuesY[y] = table.valuesY[y] - unscaledY; } } else { if (FLIP) { const int lastIndex = celObj._width - 1; for (int16 x = targetRect.left; x < targetRect.right; ++x) { - _valuesX[x] = lastIndex - table->valuesX[x - scaledPosition.x]; + _valuesX[x] = lastIndex - table.valuesX[x - scaledPosition.x]; } } else { for (int16 x = targetRect.left; x < targetRect.right; ++x) { - _valuesX[x] = table->valuesX[x - scaledPosition.x]; + _valuesX[x] = table.valuesX[x - scaledPosition.x]; } } for (int16 y = targetRect.top; y < targetRect.bottom; ++y) { - _valuesY[y] = table->valuesY[y - scaledPosition.y]; + _valuesY[y] = table.valuesY[y - scaledPosition.y]; } } } @@ -412,8 +403,8 @@ struct MAPPER_NoMDNoSkip { struct MAPPER_Map { inline void draw(byte *target, const byte pixel, const uint8 skipColor) const { if (pixel != skipColor) { - // NOTE: For some reason, SSCI never checks if the source - // pixel is *above* the range of remaps. + // For some reason, SSCI never checks if the source pixel is *above* + // the range of remaps, so we do not either. if (pixel < g_sci->_gfxRemap32->getStartColor()) { *target = pixel; } else if (g_sci->_gfxRemap32->remapEnabled(pixel)) { @@ -429,8 +420,8 @@ struct MAPPER_Map { */ struct MAPPER_NoMap { inline void draw(byte *target, const byte pixel, const uint8 skipColor) const { - // NOTE: For some reason, SSCI never checks if the source - // pixel is *above* the range of remaps. + // For some reason, SSCI never checks if the source pixel is *above* the + // range of remaps, so we do not either. if (pixel != skipColor && pixel < g_sci->_gfxRemap32->getStartColor()) { *target = pixel; } @@ -444,9 +435,9 @@ void CelObj::draw(Buffer &target, const ScreenItem &screenItem, const Common::Re _drawBlackLines = screenItem._drawBlackLines; if (_remap) { - // NOTE: In the original code this check was `g_Remap_numActiveRemaps && _remap`, - // but since we are already in a `_remap` branch, there is no reason to check it - // again + // In SSCI, this check was `g_Remap_numActiveRemaps && _remap`, but + // since we are already in a `_remap` branch, there is no reason to + // check that again if (g_sci->_gfxRemap32->getRemapCount()) { if (scaleX.isOne() && scaleY.isOne()) { if (_compressionType == kCelCompressionNone) { @@ -612,7 +603,7 @@ void CelObj::submitPalette() const { #pragma mark CelObj - Caching int CelObj::_nextCacheId = 1; -CelCache *CelObj::_cache = nullptr; +Common::ScopedPtr<CelCache> CelObj::_cache; int CelObj::searchCache(const CelInfo32 &celInfo, int *const nextInsertIndex) const { *nextInsertIndex = -1; @@ -648,12 +639,7 @@ void CelObj::putCopyInCache(const int cacheIndex) const { } CelCacheEntry &entry = (*_cache)[cacheIndex]; - - if (entry.celObj != nullptr) { - delete entry.celObj; - } - - entry.celObj = duplicate(); + entry.celObj.reset(duplicate()); entry.id = ++_nextCacheId; } @@ -807,8 +793,8 @@ void CelObj::drawUncompHzFlipNoMDNoSkip(Buffer &target, const Common::Rect &targ } void CelObj::scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const { - // In SSCI the checks are > because their rects are BR-inclusive; - // our checks are >= because our rects are BR-exclusive + // In SSCI the checks are > because their rects are BR-inclusive; our checks + // are >= because our rects are BR-exclusive if (g_sci->_features->hasEmptyScaleDrawHack() && (targetRect.left >= targetRect.right || targetRect.top >= targetRect.bottom)) { @@ -822,8 +808,8 @@ void CelObj::scaleDrawNoMD(Buffer &target, const Ratio &scaleX, const Ratio &sca } void CelObj::scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Ratio &scaleY, const Common::Rect &targetRect, const Common::Point &scaledPosition) const { - // In SSCI the checks are > because their rects are BR-inclusive; - // our checks are >= because our rects are BR-exclusive + // In SSCI the checks are > because their rects are BR-inclusive; our checks + // are >= because our rects are BR-exclusive if (g_sci->_features->hasEmptyScaleDrawHack() && (targetRect.left >= targetRect.right || targetRect.top >= targetRect.bottom)) { @@ -861,11 +847,11 @@ int16 CelObjView::getNumCels(const GuiResourceId viewId, int16 loopNo) { const uint16 loopCount = data[2]; - // Every version of SCI32 has a logic error in this function that causes - // random memory to be read if a script requests the cel count for one - // past the maximum loop index. For example, GK1 room 808 does this, and - // gets stuck in an infinite loop because the game script expects this - // method to return a non-zero value. + // Every version of SSCI has a logic error in this function that causes + // random memory to be read if a script requests the cel count for one past + // the maximum loop index. For example, GK1 room 808 does this, and gets + // stuck in an infinite loop because the game script expects this method to + // return a non-zero value. // This bug is triggered in basically every SCI32 game and appears to be // universally fixable simply by always using the next lowest loop instead. if (loopNo == loopCount) { @@ -904,7 +890,7 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int const int cacheIndex = searchCache(_info, &cacheInsertIndex); if (cacheIndex != -1) { CelCacheEntry &entry = (*_cache)[cacheIndex]; - const CelObjView *const cachedCelObj = dynamic_cast<CelObjView *>(entry.celObj); + const CelObjView *const cachedCelObj = dynamic_cast<CelObjView *>(entry.celObj.get()); if (cachedCelObj == nullptr) { error("Expected a CelObjView in cache slot %d", cacheIndex); } @@ -915,7 +901,7 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, viewId), false); - // NOTE: SCI2.1/SQ6 just silently returns here. + // SSCI just silently returns here if (!resource) { error("View resource %d not found", viewId); } @@ -944,8 +930,6 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int _info.loopNo = loopCount - 1; } - // NOTE: This is the actual check, in the actual location, - // from SCI engine. if (loopNo < 0) { error("Loop is less than 0"); } @@ -1011,10 +995,8 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int error("Compression type not supported - V: %d L: %d C: %d", _info.resourceId, _info.loopNo, _info.celNo); } - if (celHeader[10] & 128) { - // NOTE: This is correct according to SCI2.1/SQ6/DOS; - // the engine re-reads the byte value as a word value - const uint16 flags = celHeader.getUint16SEAt(10); + const uint16 flags = celHeader.getUint16SEAt(10); + if (flags & 0x80) { _transparent = flags & 1 ? true : false; _remap = flags & 2 ? true : false; } else if (_compressionType == kCelCompressionNone) { @@ -1096,7 +1078,7 @@ Common::Point CelObjView::getLinkPosition(const int16 linkId) const { Common::Point point; point.x = linkTable.getInt16SEAt(0); if (_mirrorX) { - // NOTE: SSCI had an off-by-one error here (missing -1) + // SSCI had an off-by-one error here (missing -1) point.x = _width - point.x - 1; } point.y = linkTable.getInt16SEAt(2); @@ -1127,7 +1109,7 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { const int cacheIndex = searchCache(_info, &cacheInsertIndex); if (cacheIndex != -1) { CelCacheEntry &entry = (*_cache)[cacheIndex]; - const CelObjPic *const cachedCelObj = dynamic_cast<CelObjPic *>(entry.celObj); + const CelObjPic *const cachedCelObj = dynamic_cast<CelObjPic *>(entry.celObj.get()); if (cachedCelObj == nullptr) { error("Expected a CelObjPic in cache slot %d", cacheIndex); } @@ -1138,7 +1120,7 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypePic, picId), false); - // NOTE: SCI2.1/SQ6 just silently returns here. + // SSCI just silently returns here if (!resource) { error("Pic resource %d not found", picId); } @@ -1183,10 +1165,9 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { _yResolution = 400; } - if (celHeader.getUint8At(10) & 128) { - // NOTE: This is correct according to SCI2.1/SQ6/DOS; - // the engine re-reads the byte value as a word value - const uint16 flags = celHeader.getUint16SEAt(10); + + const uint16 flags = celHeader.getUint16SEAt(10); + if (flags & 0x80) { _transparent = flags & 1 ? true : false; _remap = flags & 2 ? true : false; } else { @@ -1251,7 +1232,8 @@ CelObjMem::CelObjMem(const reg_t bitmapObject) { SciBitmap *bitmap = g_sci->getEngineState()->_segMan->lookupBitmap(bitmapObject); - // NOTE: SSCI did no error checking here at all. + // SSCI did no error checking here at all so would just end up reading + // garbage or crashing if this ever happened if (!bitmap) { error("Bitmap %04x:%04x not found", PRINT_REG(bitmapObject)); } @@ -1293,8 +1275,8 @@ CelObjColor::CelObjColor(const uint8 color, const int16 width, const int16 heigh } void CelObjColor::draw(Buffer &target, const ScreenItem &screenItem, const Common::Rect &targetRect, const bool mirrorX) { - // TODO: The original engine sets this flag but why? One cannot - // draw a solid color mirrored. + // One cannot draw a solid color mirrored, but SSCI sets it anyway, so we do + // too _drawMirrored = mirrorX; draw(target, targetRect); } |