From c7c5f28bdb2f393c1290bcac803cf9fc86ac8ed8 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Fri, 6 Oct 2017 22:05:57 -0500 Subject: [PATCH] SCI32: Clean up scriptWidth/scriptHeight/screenWidth/screenHeight This removes the unnecessary Buffer subclass and stops most places where the output buffer was being interrogated about dimensions instead of GfxFrameout. --- engines/sci/engine/kgraphics32.cpp | 31 +++++----- engines/sci/engine/kvideo.cpp | 4 +- engines/sci/engine/savegame.cpp | 2 +- engines/sci/engine/segment.h | 6 +- engines/sci/event.cpp | 4 +- engines/sci/graphics/celobj32.cpp | 8 +-- engines/sci/graphics/controls32.cpp | 4 +- engines/sci/graphics/cursor32.cpp | 23 ++++---- engines/sci/graphics/frameout.cpp | 81 +++++++++++++++----------- engines/sci/graphics/frameout.h | 58 ++++++++++++++---- engines/sci/graphics/helpers.h | 37 +----------- engines/sci/graphics/paint32.cpp | 4 +- engines/sci/graphics/plane32.cpp | 8 +-- engines/sci/graphics/screen_item32.cpp | 12 ++-- engines/sci/graphics/text32.cpp | 24 ++++---- engines/sci/graphics/text32.h | 12 ++-- engines/sci/graphics/transitions32.cpp | 6 +- engines/sci/graphics/video32.cpp | 31 +++------- engines/sci/video/robot_decoder.cpp | 20 +++---- 19 files changed, 191 insertions(+), 184 deletions(-) diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 02b2cea9a902..f9c1edee4202 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -77,7 +77,7 @@ reg_t kBaseSetter32(EngineState *s, int argc, reg_t *argv) { Ratio scaleX; if (getSciVersion() < SCI_VERSION_2_1_LATE) { - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); scaleX = Ratio(scriptWidth, celObj._xResolution); } @@ -160,11 +160,12 @@ reg_t kShakeScreen32(EngineState *s, int argc, reg_t *argv) { } reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) { - const Buffer &buffer = g_sci->_gfxFrameout->getCurrentBuffer(); - if (buffer.screenWidth < 640 || buffer.screenHeight < 400) - return make_reg(0, 0); + const GfxFrameout *gfxFrameout = g_sci->_gfxFrameout; + if (gfxFrameout->getScreenWidth() < 640 || gfxFrameout->getScreenHeight() < 400) { + return NULL_REG; + } - return make_reg(0, 1); + return TRUE_REG; } reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) { @@ -412,25 +413,25 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { } reg_t kCelHigh32(EngineState *s, int argc, reg_t *argv) { - GuiResourceId resourceId = argv[0].toUint16(); - int16 loopNo = argv[1].toSint16(); - int16 celNo = argv[2].toSint16(); - CelObjView celObj(resourceId, loopNo, celNo); + const GuiResourceId resourceId = argv[0].toUint16(); + const int16 loopNo = argv[1].toSint16(); + const int16 celNo = argv[2].toSint16(); + const CelObjView celObj(resourceId, loopNo, celNo); int16 height = celObj._height; if (getSciVersion() < SCI_VERSION_2_1_LATE) { - height = mulru(height, Ratio(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, celObj._yResolution)); + height = mulru(height, Ratio(g_sci->_gfxFrameout->getScriptHeight(), celObj._yResolution)); } return make_reg(0, height); } reg_t kCelWide32(EngineState *s, int argc, reg_t *argv) { - GuiResourceId resourceId = argv[0].toUint16(); - int16 loopNo = argv[1].toSint16(); - int16 celNo = argv[2].toSint16(); - CelObjView celObj(resourceId, loopNo, celNo); + const GuiResourceId resourceId = argv[0].toUint16(); + const int16 loopNo = argv[1].toSint16(); + const int16 celNo = argv[2].toSint16(); + const CelObjView celObj(resourceId, loopNo, celNo); int16 width = celObj._width; if (getSciVersion() < SCI_VERSION_2_1_LATE) { - width = mulru(width, Ratio(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, celObj._xResolution)); + width = mulru(width, Ratio(g_sci->_gfxFrameout->getScriptWidth(), celObj._xResolution)); } return make_reg(0, width); } diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 98b2ba2b8539..1bd886c8311b 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -460,8 +460,8 @@ reg_t kPlayVMDShowCursor(EngineState *s, int argc, reg_t *argv) { } reg_t kPlayVMDSetBlackoutArea(EngineState *s, int argc, reg_t *argv) { - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); Common::Rect blackoutArea; blackoutArea.left = MAX(0, argv[0].toSint16()); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 06a26ec58e72..a7ebe0b4df94 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -801,7 +801,7 @@ void SciBitmap::saveLoadWithSerializer(Common::Serializer &s) { s.syncBytes(_data, _dataSize); if (s.isLoading()) { - _buffer = Buffer(getWidth(), getHeight(), getPixels()); + _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8()); } } #endif diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 2a4fd9149bbe..14744e3e3978 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -977,7 +977,7 @@ class SciBitmap : public Common::Serializable { _data = (byte *)malloc(other._dataSize); memcpy(_data, other._data, other._dataSize); if (_dataSize) { - _buffer = Buffer(getWidth(), getHeight(), getPixels()); + _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8()); } _gc = other._gc; } @@ -998,7 +998,7 @@ class SciBitmap : public Common::Serializable { _data = (byte *)malloc(other._dataSize); memcpy(_data, other._data, _dataSize); if (_dataSize) { - _buffer = Buffer(getWidth(), getHeight(), getPixels()); + _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8()); } _gc = other._gc; @@ -1032,7 +1032,7 @@ class SciBitmap : public Common::Serializable { setXResolution(xResolution); setYResolution(yResolution); - _buffer = Buffer(getWidth(), getHeight(), getPixels()); + _buffer.init(getWidth(), getHeight(), getWidth(), getPixels(), Graphics::PixelFormat::createFormatCLUT8()); } inline int getRawSize() const { diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index e69095a6b19d..aef84e212df3 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -164,7 +164,7 @@ SciEvent EventManager::getScummVMEvent() { #if ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { - const Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer(); + const GfxFrameout *gfxFrameout = g_sci->_gfxFrameout; // This will clamp `mousePos` according to the restricted zone, // so any cursor or screen item associated with the mouse position @@ -172,7 +172,7 @@ SciEvent EventManager::getScummVMEvent() { g_sci->_gfxCursor32->deviceMoved(mousePos); Common::Point mousePosSci = mousePos; - mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight)); + mulru(mousePosSci, Ratio(gfxFrameout->getScriptWidth(), gfxFrameout->getScreenWidth()), Ratio(gfxFrameout->getScriptHeight(), gfxFrameout->getScreenHeight())); noEvent.mousePosSci = input.mousePosSci = mousePosSci; if (_hotRectanglesActive) { diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp index c2ae29b24e0e..fb7abe8a77bb 100644 --- a/engines/sci/graphics/celobj32.cpp +++ b/engines/sci/graphics/celobj32.cpp @@ -658,9 +658,9 @@ struct RENDERER { _skipColor(skipColor) {} inline void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const { - byte *targetPixel = (byte *)target.getPixels() + target.screenWidth * targetRect.top + targetRect.left; + byte *targetPixel = (byte *)target.getPixels() + target.w * targetRect.top + targetRect.left; - const int16 skipStride = target.screenWidth - targetRect.width(); + const int16 skipStride = target.w - targetRect.width(); const int16 targetWidth = targetRect.width(); const int16 targetHeight = targetRect.height(); for (int16 y = 0; y < targetHeight; ++y) { @@ -1265,8 +1265,8 @@ CelObjColor::CelObjColor(const uint8 color, const int16 width, const int16 heigh _info.color = color; _origin.x = 0; _origin.y = 0; - _xResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - _yResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + _xResolution = g_sci->_gfxFrameout->getScriptWidth(); + _yResolution = g_sci->_gfxFrameout->getScriptHeight(); _hunkPaletteOffset = 0; _mirrorX = false; _remap = false; diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp index 82b99e68cfd4..fa4396c1d8b9 100644 --- a/engines/sci/graphics/controls32.cpp +++ b/engines/sci/graphics/controls32.cpp @@ -391,8 +391,8 @@ ScrollWindow::ScrollWindow(SegManager *segMan, const Common::Rect &gameRect, con _gfxText32.setFont(_fontId); _pointSize = _gfxText32._font->getHeight(); - const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const uint16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const uint16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); Common::Rect bitmapRect(gameRect); mulinc(bitmapRect, Ratio(_gfxText32._xResolution, scriptWidth), Ratio(_gfxText32._yResolution, scriptHeight)); diff --git a/engines/sci/graphics/cursor32.cpp b/engines/sci/graphics/cursor32.cpp index ae8c01495caf..f401d1ba80fc 100644 --- a/engines/sci/graphics/cursor32.cpp +++ b/engines/sci/graphics/cursor32.cpp @@ -39,7 +39,7 @@ GfxCursor32::GfxCursor32() : void GfxCursor32::init(const Buffer &outputBuffer) { _screen = outputBuffer; - _screenRegion.rect = Common::Rect(_screen.screenWidth, _screen.screenHeight); + _screenRegion.rect = Common::Rect(_screen.w, _screen.h); _screenRegion.data = static_cast(_screen.getPixels()); _restrictedArea = _screenRegion.rect; } @@ -151,10 +151,10 @@ void GfxCursor32::show() { void GfxCursor32::setRestrictedArea(const Common::Rect &rect) { _restrictedArea = rect; - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); mulru(_restrictedArea, Ratio(screenWidth, scriptWidth), Ratio(screenHeight, scriptHeight), 0); @@ -259,7 +259,7 @@ void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const // threshold size because inventory items usually have a // high-resolution cursor representation. bool pixelDouble = false; - if (g_sci->_gfxFrameout->_isHiRes && + if (g_sci->_gfxFrameout->isHiRes() && (g_sci->getGameId() == GID_GK1 || (g_sci->getGameId() == GID_PQ4 && _width <= 22 && _height <= 22))) { @@ -275,7 +275,8 @@ void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const memset(_cursor.data, 255, _width * _height); _cursor.skipColor = 255; - Buffer target(_width, _height, _cursor.data); + Buffer target; + target.init(_width, _height, _width, _cursor.data, Graphics::PixelFormat::createFormatCLUT8()); if (pixelDouble) { view.draw(target, _cursor.rect, Common::Point(0, 0), false, 2, 2); } else { @@ -314,10 +315,10 @@ void GfxCursor32::copyFromScreen(DrawRegion &target) { } void GfxCursor32::setPosition(const Common::Point &position) { - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); Common::Point newPosition; newPosition.x = (position.x * Ratio(screenWidth, scriptWidth)).toInt(); diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index a8746eeef8a4..7fc92a829dc6 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -61,7 +61,7 @@ namespace Sci { GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor) : - _isHiRes(gameIsHiRes()), + _isHiRes(detectHiRes()), _palette(palette), _cursor(cursor), _segMan(segMan), @@ -74,15 +74,13 @@ GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitio _lastScreenUpdateTick(0) { if (g_sci->getGameId() == GID_PHANTASMAGORIA) { - _currentBuffer = Buffer(630, 450, nullptr); + _currentBuffer.create(630, 450, Graphics::PixelFormat::createFormatCLUT8()); } else if (_isHiRes) { - _currentBuffer = Buffer(640, 480, nullptr); + _currentBuffer.create(640, 480, Graphics::PixelFormat::createFormatCLUT8()); } else { - _currentBuffer = Buffer(320, 200, nullptr); + _currentBuffer.create(320, 200, Graphics::PixelFormat::createFormatCLUT8()); } - _currentBuffer.setPixels(calloc(1, _currentBuffer.screenWidth * _currentBuffer.screenHeight)); - _screenRect = Common::Rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight); - initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes); + initGraphics(_currentBuffer.w, _currentBuffer.h, _isHiRes); switch (g_sci->getGameId()) { case GID_HOYLE5: @@ -91,18 +89,20 @@ GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitio case GID_PHANTASMAGORIA2: case GID_TORIN: case GID_RAMA: - _currentBuffer.scriptWidth = 640; - _currentBuffer.scriptHeight = 480; + _scriptWidth = 640; + _scriptHeight = 480; break; case GID_GK2: case GID_PQSWAT: if (!g_sci->isDemo()) { - _currentBuffer.scriptWidth = 640; - _currentBuffer.scriptHeight = 480; + _scriptWidth = 640; + _scriptHeight = 480; + break; } - break; + // fall through default: - // default script width for other games is 320x200 + _scriptWidth = 320; + _scriptHeight = 200; break; } } @@ -110,7 +110,7 @@ GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitio GfxFrameout::~GfxFrameout() { clear(); CelObj::deinit(); - free(_currentBuffer.getPixels()); + _currentBuffer.free(); } void GfxFrameout::run() { @@ -122,7 +122,7 @@ void GfxFrameout::run() { // This plane is created in SCI::InitPlane in SSCI, and is a background fill // plane to ensure "hidden" planes (planes with negative priority) are never // drawn - Plane *initPlane = new Plane(Common::Rect(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight)); + Plane *initPlane = new Plane(Common::Rect(_scriptWidth, _scriptHeight)); initPlane->_priority = 0; _planes.add(initPlane); } @@ -133,7 +133,7 @@ void GfxFrameout::clear() { _showList.clear(); } -bool GfxFrameout::gameIsHiRes() const { +bool GfxFrameout::detectHiRes() const { // QFG4 is always low resolution if (g_sci->getGameId() == GID_QFG4) { return false; @@ -360,7 +360,7 @@ void GfxFrameout::addPlane(Plane *plane) { error("Plane %04x:%04x already exists", PRINT_REG(plane->_object)); } - plane->clipScreenRect(_screenRect); + plane->clipScreenRect(Common::Rect(_currentBuffer.w, _currentBuffer.h)); _planes.add(plane); } @@ -369,7 +369,7 @@ void GfxFrameout::updatePlane(Plane &plane) { assert(_planes.findByObject(plane._object) == &plane); Plane *visiblePlane = _visiblePlanes.findByObject(plane._object); - plane.sync(visiblePlane, _screenRect); + plane.sync(visiblePlane, Common::Rect(_currentBuffer.w, _currentBuffer.h)); // updateScreenRect was called a second time here in SSCI, but it is already // called at the end of the sync call (also in SSCI) so there is no reason // to do it again @@ -455,7 +455,7 @@ void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *show int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][kGlobalVarPreviousRoomNo].toSint16(); - Common::Rect rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight); + Common::Rect rect(_currentBuffer.w, _currentBuffer.h); _showList.add(rect); showBits(); @@ -557,24 +557,39 @@ void GfxFrameout::directFrameOut(const Common::Rect &showRect) { } #ifdef USE_RGB_COLOR +void GfxFrameout::redrawGameScreen(const Common::Rect &skipRect) const { + Common::ScopedPtr game(_currentBuffer.convertTo(g_system->getScreenFormat(), _palette->getHardwarePalette())); + assert(game); + + Common::Rect rects[4]; + int splitCount = splitRects(Common::Rect(game->w, game->h), skipRect, rects); + if (splitCount != -1) { + while (splitCount--) { + const Common::Rect &drawRect = rects[splitCount]; + g_system->copyRectToScreen(game->getBasePtr(drawRect.left, drawRect.top), game->pitch, drawRect.left, drawRect.top, drawRect.width(), drawRect.height()); + } + } + + game->free(); +} + void GfxFrameout::resetHardware() { updateMousePositionForRendering(); - _showList.add(Common::Rect(getCurrentBuffer().screenWidth, getCurrentBuffer().screenHeight)); + _showList.add(Common::Rect(_currentBuffer.w, _currentBuffer.h)); g_system->getPaletteManager()->setPalette(_palette->getHardwarePalette(), 0, 256); showBits(); } #endif /** - * Determines the parts of `middleRect` that aren't overlapped - * by `showRect`, optimised for contiguous memory writes. - * Returns -1 if `middleRect` and `showRect` have no intersection. - * Returns number of returned parts (in `outRects`) otherwise. - * (In particular, this returns 0 if `middleRect` is contained - * in `other`.) + * Determines the parts of `middleRect` that aren't overlapped by `showRect`, + * optimised for contiguous memory writes. + * + * `middleRect` is modified directly to extend into the upper and lower rects. * - * `middleRect` is modified directly to extend into the upper - * and lower rects. + * @returns -1 if `middleRect` and `showRect` have no intersection, or the + * number of returned parts (in `outRects`) otherwise. (In particular, this + * returns 0 if `middleRect` is contained in `showRect`.) */ int splitRectsForRender(Common::Rect &middleRect, const Common::Rect &showRect, Common::Rect(&outRects)[2]) { if (!middleRect.intersects(showRect)) { @@ -998,7 +1013,7 @@ void GfxFrameout::showBits() { rounded.left &= ~1; rounded.right = (rounded.right + 1) & ~1; - byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.screenWidth + rounded.left; + byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.w + rounded.left; // Sometimes screen items (especially from SCI2.1early transitions, like // in the asteroids minigame in PQ4) generate zero-dimension show @@ -1023,7 +1038,7 @@ void GfxFrameout::showBits() { #else { #endif - g_system->copyRectToScreen(sourceBuffer, _currentBuffer.screenWidth, rounded.left, rounded.top, rounded.width(), rounded.height()); + g_system->copyRectToScreen(sourceBuffer, _currentBuffer.w, rounded.left, rounded.top, rounded.width(), rounded.height()); } } @@ -1083,7 +1098,7 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co byte *pixels = (byte *)_currentBuffer.getPixels(); - for (int pixelIndex = 0, numPixels = _currentBuffer.screenWidth * _currentBuffer.screenHeight; pixelIndex < numPixels; ++pixelIndex) { + for (int pixelIndex = 0, numPixels = _currentBuffer.w * _currentBuffer.h; pixelIndex < numPixels; ++pixelIndex) { byte currentValue = pixels[pixelIndex]; int8 styleRangeValue = styleRanges[currentValue]; if (styleRangeValue == -1 && styleRangeValue == style) { @@ -1205,7 +1220,7 @@ reg_t GfxFrameout::kernelIsOnMe(const reg_t object, const Common::Point &positio bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const Common::Point &position, const bool checkPixel) const { Common::Point scaledPosition(position); - mulru(scaledPosition, Ratio(_currentBuffer.screenWidth, _currentBuffer.scriptWidth), Ratio(_currentBuffer.screenHeight, _currentBuffer.scriptHeight)); + mulru(scaledPosition, Ratio(_currentBuffer.w, _scriptWidth), Ratio(_currentBuffer.h, _scriptHeight)); scaledPosition.x += plane._planeRect.left; scaledPosition.y += plane._planeRect.top; @@ -1222,7 +1237,7 @@ bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const scaledPosition.y -= screenItem._scaledPosition.y; if (getSciVersion() < SCI_VERSION_2_1_LATE) { - mulru(scaledPosition, Ratio(celObj._xResolution, _currentBuffer.screenWidth), Ratio(celObj._yResolution, _currentBuffer.screenHeight)); + mulru(scaledPosition, Ratio(celObj._xResolution, _currentBuffer.w), Ratio(celObj._yResolution, _currentBuffer.h)); } if (screenItem._scale.signal != kScaleSignalNone && screenItem._scale.x && screenItem._scale.y) { diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 78bf2e068aa7..55ba631cb77c 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -47,22 +47,57 @@ class GfxFrameout { GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor); ~GfxFrameout(); - bool _isHiRes; - void clear(); void run(); + /** + * Returns true if the game should render at a resolution greater than + * 320x240. + */ + inline bool isHiRes() const { return _isHiRes; } + + /** + * Gets the x-resolution used by game scripts. + */ + inline int16 getScriptWidth() const { return _scriptWidth; } + + /** + * Gets the y-resolution used by game scripts. + */ + inline int16 getScriptHeight() const { return _scriptHeight; } + + /** + * Gets the x-resolution of the output buffer. + */ + inline int16 getScreenWidth() const { return _currentBuffer.w; } + + /** + * Gets the y-resolution of the output buffer. + */ + inline int16 getScreenHeight() const { return _currentBuffer.h; } + private: GfxCursor32 *_cursor; GfxPalette32 *_palette; GfxTransitions32 *_transitions; SegManager *_segMan; + /** + * Whether or not the game should render at a resolution above 320x240. + */ + bool _isHiRes; + + /** + * The resolution used by game scripts. + * @see celobj32.h comments on kLowResX/kLowResY. + */ + int16 _scriptWidth, _scriptHeight; + /** * Determines whether the current game should be rendered in high * resolution. */ - bool gameIsHiRes() const; + bool detectHiRes() const; #pragma mark - #pragma mark Screen items @@ -172,7 +207,7 @@ class GfxFrameout { * Resets the pixel format of the hardware surface to the given format. */ void setPixelFormat(const Graphics::PixelFormat &format) const { - initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes, &format); + initGraphics(_currentBuffer.w, _currentBuffer.h, _isHiRes, &format); } /** @@ -216,6 +251,14 @@ class GfxFrameout { */ void directFrameOut(const Common::Rect &showRect); + /** + * Redraws the game screen from the internal frame buffer to the system. + * Used after pixel format changes. + * + * @param skipRect An area of the screen that does not need to be redrawn. + */ + void redrawGameScreen(const Common::Rect &skipRect) const; + #ifdef USE_RGB_COLOR /** * Sends the entire internal screen buffer and palette to hardware. @@ -270,13 +313,6 @@ class GfxFrameout { */ bool _remapOccurred; - /** - * The dimensions of the output buffer, in display coordinates. - * - * @note This field is on `GraphicsMgr.screen` in SSCI. - */ - Common::Rect _screenRect; - /** * A list of rectangles, in screen coordinates, that represent portions of * the internal screen buffer that are dirty and should be drawn to the diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h index 9d266fcf0077..5842bf088728 100644 --- a/engines/sci/graphics/helpers.h +++ b/engines/sci/graphics/helpers.h @@ -225,42 +225,7 @@ inline int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&o return splitCount; } -struct Buffer : public Graphics::Surface { - uint16 screenWidth; - uint16 screenHeight; - uint16 scriptWidth; - uint16 scriptHeight; - - Buffer() : - screenWidth(0), - screenHeight(0), - scriptWidth(320), - scriptHeight(200) {} - - Buffer(const uint16 width, const uint16 height, uint8 *const pix) : - screenWidth(width), - screenHeight(height), - scriptWidth(320), - scriptHeight(200) { - init(width, height, width, pix, Graphics::PixelFormat::createFormatCLUT8()); - } - - void clear(const uint8 value) { - memset(pixels, value, w * h); - } - - inline uint8 *getAddress(const uint16 x, const uint16 y) { - return (uint8 *)getBasePtr(x, y); - } - - inline uint8 *getAddressSimRes(const uint16 x, const uint16 y) { - return (uint8*)pixels + (y * w * screenHeight / scriptHeight) + (x * screenWidth / scriptWidth); - } - - bool isNull() { - return pixels == nullptr; - } -}; +typedef Graphics::Surface Buffer; #endif struct Color { diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index f4d9c9f4d3f9..f80f115e1b9f 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -126,8 +126,8 @@ reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common:: thickness = (MAX(1, thickness) - 1) | 1; const uint8 halfThickness = thickness >> 1; - const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const uint16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const uint16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); outRect.left = MIN(startPoint.x, endPoint.x); outRect.top = MIN(startPoint.y, endPoint.y); diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp index 77ca620975fc..46a8aedbb076 100644 --- a/engines/sci/graphics/plane32.cpp +++ b/engines/sci/graphics/plane32.cpp @@ -137,10 +137,10 @@ void Plane::init() { } void Plane::convertGameRectToPlaneRect() { - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); const Ratio ratioX = Ratio(screenWidth, scriptWidth); const Ratio ratioY = Ratio(screenHeight, scriptHeight); diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp index 4e1ed8399bc9..0addd773dea5 100644 --- a/engines/sci/graphics/screen_item32.cpp +++ b/engines/sci/graphics/screen_item32.cpp @@ -251,10 +251,10 @@ void ScreenItem::setFromObject(SegManager *segMan, const reg_t object, const boo } void ScreenItem::calcRects(const Plane &plane) { - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); const CelObj &celObj = getCelObj(); @@ -587,8 +587,8 @@ Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const { nsRect = celObjRect; } - const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const uint16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const uint16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); Ratio scaleX, scaleY; if (_scale.signal == kScaleSignalManual) { diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 1fcf2920cc6c..6ebbcc0f0e4a 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -53,8 +53,8 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts) : } void GfxText32::init() { - _xResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - _yResolution = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + _xResolution = g_sci->_gfxFrameout->getScriptWidth(); + _yResolution = g_sci->_gfxFrameout->getScriptHeight(); } reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const bool dimmed, const bool doScaling, const bool gc) { @@ -73,8 +73,8 @@ reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect setFont(fontId); if (doScaling) { - int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); Ratio scaleX(_xResolution, scriptWidth); Ratio scaleY(_yResolution, scriptHeight); @@ -115,8 +115,8 @@ reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect & setFont(fontId); - int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); mulinc(_textRect, Ratio(_xResolution, scriptWidth), Ratio(_yResolution, scriptHeight)); @@ -218,7 +218,7 @@ void GfxText32::drawChar(const char charIndex) { } int16 GfxText32::getScaledFontHeight() const { - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); return (_font->getHeight() * scriptHeight + _yResolution - 1) / _yResolution; } @@ -335,7 +335,7 @@ void GfxText32::drawText(const uint index, uint length) { void GfxText32::invertRect(const reg_t bitmapId, int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling) { Common::Rect targetRect = rect; if (doScaling) { - bitmapStride = bitmapStride * _xResolution / g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + bitmapStride = bitmapStride * _xResolution / g_sci->_gfxFrameout->getScriptWidth(); targetRect = scaleRect(rect); } @@ -566,8 +566,8 @@ Common::Rect GfxText32::getTextSize(const Common::String &text, int16 maxWidth, Common::Rect result; - int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); maxWidth = maxWidth * _xResolution / scriptWidth; @@ -638,8 +638,8 @@ int16 GfxText32::getStringWidth(const Common::String &text) { } int16 GfxText32::getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling) { - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); Common::Rect scaledRect(textRect); if (doScaling) { diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 945cc8113077..f9de3ad5fb93 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -139,10 +139,10 @@ class GfxText32 { inline Common::Rect scaleRect(const Common::Rect &rect) { Common::Rect scaledRect(rect); - int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - Ratio scaleX(_xResolution, scriptWidth); - Ratio scaleY(_yResolution, scriptHeight); + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); + const Ratio scaleX(_xResolution, scriptWidth); + const Ratio scaleY(_yResolution, scriptHeight); mulinc(scaledRect, scaleX, scaleY); return scaledRect; } @@ -191,12 +191,12 @@ class GfxText32 { reg_t createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed, const bool gc); inline int scaleUpWidth(int value) const { - const int scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); return (value * scriptWidth + _xResolution - 1) / _xResolution; } inline int scaleUpHeight(int value) const { - const int scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); return (value * scriptHeight + _yResolution - 1) / _yResolution; } diff --git a/engines/sci/graphics/transitions32.cpp b/engines/sci/graphics/transitions32.cpp index 8be9e6396553..43479a2505eb 100644 --- a/engines/sci/graphics/transitions32.cpp +++ b/engines/sci/graphics/transitions32.cpp @@ -544,7 +544,8 @@ void GfxTransitions32::configure21EarlyDissolve(PlaneShowStyle &showStyle, const showStyle.bitmap = bitmapId; const Buffer &source = g_sci->_gfxFrameout->getCurrentBuffer(); - Buffer target(showStyle.width, showStyle.height, bitmap.getPixels()); + Buffer target; + target.init(showStyle.width, showStyle.height, showStyle.width, bitmap.getPixels(), Graphics::PixelFormat::createFormatCLUT8()); target.fillRect(Common::Rect(bitmap.getWidth(), bitmap.getHeight()), kDefaultSkipColor); target.copyRectToSurface(source, 0, 0, gameRect); @@ -754,7 +755,8 @@ bool GfxTransitions32::processPixelDissolve21Early(PlaneShowStyle &showStyle) { bool unchanged = true; SciBitmap &bitmap = *_segMan->lookupBitmap(showStyle.bitmap); - Buffer buffer(showStyle.width, showStyle.height, bitmap.getPixels()); + Buffer buffer; + buffer.init(showStyle.width, showStyle.height, showStyle.width, bitmap.getPixels(), Graphics::PixelFormat::createFormatCLUT8()); uint32 numPixels = showStyle.width * showStyle.height; uint32 numPixelsPerDivision = (numPixels + showStyle.divisions) / showStyle.divisions; diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp index c128ba13269a..8d68c8e3bb50 100644 --- a/engines/sci/graphics/video32.cpp +++ b/engines/sci/graphics/video32.cpp @@ -307,10 +307,10 @@ void SEQPlayer::play(const Common::String &fileName, const int16 numTicks, const return; } - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); const int16 scaledWidth = (_decoder->getWidth() * Ratio(screenWidth, scriptWidth)).toInt(); const int16 scaledHeight = (_decoder->getHeight() * Ratio(screenHeight, scriptHeight)).toInt(); @@ -392,8 +392,8 @@ AVIPlayer::IOStatus AVIPlayer::init(const bool doublePixels) { height *= 2; } - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); // When scaling videos, they must not grow larger than the hardware screen // or else the engine will crash. This is particularly important for the GK1 @@ -783,20 +783,7 @@ void VMDPlayer::redrawGameScreen() const { return; } - Graphics::Surface *game = g_sci->_gfxFrameout->getCurrentBuffer().convertTo(g_system->getScreenFormat(), g_sci->_gfxPalette32->getHardwarePalette()); - assert(game); - - Common::Rect rects[4]; - int splitCount = splitRects(Common::Rect(game->w, game->h), _drawRect, rects); - if (splitCount != -1) { - while (splitCount--) { - const Common::Rect &drawRect = rects[splitCount]; - g_system->copyRectToScreen(game->getBasePtr(drawRect.left, drawRect.top), game->pitch, drawRect.left, drawRect.top, drawRect.width(), drawRect.height()); - } - } - - game->free(); - delete game; + g_sci->_gfxFrameout->redrawGameScreen(_drawRect); } #endif @@ -900,8 +887,8 @@ void VMDPlayer::initComposited() { } const uint32 hunkPaletteSize = HunkPalette::calculateHunkPaletteSize(256, false); - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); SciBitmap &vmdBitmap = *_segMan->allocateBitmap(&_bitmapId, _drawRect.width(), _drawRect.height(), 255, 0, 0, screenWidth, screenHeight, hunkPaletteSize, false, false); vmdBitmap.getBuffer().fillRect(Common::Rect(_drawRect.width(), _drawRect.height()), 0); diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index 49ca2267741a..4711a971a46a 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -447,8 +447,8 @@ void RobotDecoder::initVideo(const int16 x, const int16 y, const int16 scale, co if (_xResolution == 0 || _yResolution == 0) { // In SSCI, default values were taken from RESOURCE.CFG hires property // if it exists, but no games seem to take advantage of this - _xResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - _yResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + _xResolution = g_sci->_gfxFrameout->getScreenWidth(); + _yResolution = g_sci->_gfxFrameout->getScreenHeight(); } if (hasPalette) { @@ -677,10 +677,10 @@ void RobotDecoder::showFrame(const uint16 frameNo, const uint16 newX, const uint if (_isHiRes) { SciBitmap &bitmap = *_segMan->lookupBitmap(_celHandles[i].bitmapId); - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); if (scriptWidth == kLowResX && scriptHeight == kLowResY) { const Ratio lowResToScreenX(screenWidth, kLowResX); @@ -1453,10 +1453,10 @@ uint32 RobotDecoder::createCel5(const byte *rawVideoData, const int16 screenItem rawVideoData += kCelHeaderSize; - const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; - const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; - const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth(); + const int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight(); + const int16 screenWidth = g_sci->_gfxFrameout->getScreenWidth(); + const int16 screenHeight = g_sci->_gfxFrameout->getScreenHeight(); Common::Point origin; if (scriptWidth == kLowResX && scriptHeight == kLowResY) {