aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/frameout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/graphics/frameout.cpp')
-rw-r--r--engines/sci/graphics/frameout.cpp2120
1 files changed, 746 insertions, 1374 deletions
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index ccce8ef046..fe43c75e5a 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -29,112 +29,82 @@
#include "common/system.h"
#include "common/textconsole.h"
#include "engines/engine.h"
+#include "engines/util.h"
#include "graphics/palette.h"
#include "graphics/surface.h"
#include "sci/sci.h"
#include "sci/console.h"
+#include "sci/engine/features.h"
#include "sci/engine/kernel.h"
#include "sci/engine/state.h"
#include "sci/engine/selector.h"
#include "sci/engine/vm.h"
#include "sci/graphics/cache.h"
-#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/compare.h"
+#include "sci/graphics/cursor32.h"
#include "sci/graphics/font.h"
-#include "sci/graphics/view.h"
-#include "sci/graphics/screen.h"
+#include "sci/graphics/frameout.h"
#include "sci/graphics/paint32.h"
#include "sci/graphics/palette32.h"
-#include "sci/graphics/picture.h"
-#include "sci/graphics/text32.h"
#include "sci/graphics/plane32.h"
+#include "sci/graphics/remap32.h"
+#include "sci/graphics/screen.h"
#include "sci/graphics/screen_item32.h"
+#include "sci/graphics/text32.h"
#include "sci/graphics/frameout.h"
-#include "sci/video/robot_decoder.h"
+#include "sci/graphics/transitions32.h"
+#include "sci/graphics/video32.h"
namespace Sci {
-// TODO/FIXME: This is partially guesswork
-
-static int dissolveSequences[2][20] = {
- /* SCI2.1early- */ { 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080 },
- /* SCI2.1mid+ */ { 0, 0, 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080, 73728, 132096, 466944 }
-};
-static int16 divisionsDefaults[2][16] = {
- /* SCI2.1early- */ { 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 40, 40, 101, 101 },
- /* SCI2.1mid+ */ { 1, 20, 20, 20, 20, 10, 10, 10, 10, 20, 20, 6, 10, 101, 101, 2 }
-};
-static int16 unknownCDefaults[2][16] = {
- /* SCI2.1early- */ { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 0 },
- /* SCI2.1mid+ */ { 0, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 0, 0, 7, 7, 0 }
-};
-
-GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32) :
- _isHiRes(false),
- _cache(cache),
+GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor) :
+ _isHiRes(gameIsHiRes()),
_palette(palette),
- _resMan(resMan),
- _screen(screen),
+ _cursor(cursor),
_segMan(segMan),
- _paint32(paint32),
- _showStyles(nullptr),
- // TODO: Stop using _gfxScreen
- _currentBuffer(screen->getDisplayWidth(), screen->getDisplayHeight(), nullptr),
- _priorityMap(screen->getDisplayWidth(), screen->getDisplayHeight(), nullptr),
+ _transitions(transitions),
+ _benchmarkingFinished(false),
+ _throttleFrameOut(true),
+ _throttleState(0),
_remapOccurred(false),
_frameNowVisible(false),
- _screenRect(screen->getDisplayWidth(), screen->getDisplayHeight()),
_overdrawThreshold(0),
_palMorphIsOn(false) {
- _currentBuffer.setPixels(calloc(1, screen->getDisplayWidth() * screen->getDisplayHeight()));
-
- for (int i = 0; i < 236; i += 2) {
- _styleRanges[i] = 0;
- _styleRanges[i + 1] = -1;
- }
- for (int i = 236; i < ARRAYSIZE(_styleRanges); ++i) {
- _styleRanges[i] = 0;
- }
-
- // TODO: Make hires detection work uniformly across all SCI engine
- // versions (this flag is normally passed by SCI::MakeGraphicsMgr
- // to the GraphicsMgr constructor depending upon video configuration,
- // so should be handled upstream based on game configuration instead
- // of here)
- if (getSciVersion() >= SCI_VERSION_2_1_EARLY && _resMan->detectHires()) {
- _isHiRes = true;
- }
-
- if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
- _dissolveSequenceSeeds = dissolveSequences[0];
- _defaultDivisions = divisionsDefaults[0];
- _defaultUnknownC = unknownCDefaults[0];
+ if (g_sci->getGameId() == GID_PHANTASMAGORIA) {
+ _currentBuffer = Buffer(630, 450, nullptr);
+ } else if (_isHiRes) {
+ _currentBuffer = Buffer(640, 480, nullptr);
} else {
- _dissolveSequenceSeeds = dissolveSequences[1];
- _defaultDivisions = divisionsDefaults[1];
- _defaultUnknownC = unknownCDefaults[1];
- }
-
- // TODO: Nothing in the renderer really uses this. Currently,
- // the cursor renderer does, and kLocalToGlobal/kGlobalToLocal
- // do, but in the real engine (1) the cursor is handled in
- // frameOut, and (2) functions do a very simple lookup of the
- // plane and arithmetic with the plane's gameRect. In
- // principle, CoordAdjuster could be reused for
- // convertGameRectToPlaneRect, but it is not super clear yet
- // what the benefit would be to do that.
- _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster;
-
- // TODO: Script resolution is hard-coded per game;
- // also this must be set or else the engine will crash
- _coordAdjuster->setScriptsResolution(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight);
+ _currentBuffer = Buffer(320, 200, nullptr);
+ }
+ _currentBuffer.setPixels(calloc(1, _currentBuffer.screenWidth * _currentBuffer.screenHeight));
+ _screenRect = Common::Rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight);
+ initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes);
+
+ switch (g_sci->getGameId()) {
+ case GID_HOYLE5:
+ case GID_GK2:
+ case GID_LIGHTHOUSE:
+ case GID_LSL7:
+ case GID_PHANTASMAGORIA2:
+ case GID_PQSWAT:
+ case GID_TORIN:
+ case GID_RAMA:
+ _currentBuffer.scriptWidth = 640;
+ _currentBuffer.scriptHeight = 480;
+ break;
+ default:
+ // default script width for other games is 320x200
+ break;
+ }
}
GfxFrameout::~GfxFrameout() {
- CelObj::deinit();
clear();
+ CelObj::deinit();
+ free(_currentBuffer.getPixels());
}
void GfxFrameout::run() {
@@ -172,7 +142,7 @@ void GfxFrameout::syncWithScripts(bool addElements) {
return;
// Get planes list object
- reg_t planesListObject = engineState->variables[VAR_GLOBAL][10];
+ reg_t planesListObject = engineState->variables[VAR_GLOBAL][kGlobalVarPlanes];
reg_t planesListElements = readSelector(segMan, planesListObject, SELECTOR(elements));
List *planesList = segMan->lookupList(planesListElements);
@@ -239,22 +209,115 @@ void GfxFrameout::syncWithScripts(bool addElements) {
}
}
+bool GfxFrameout::gameIsHiRes() const {
+ // QFG4 is always low resolution
+ if (g_sci->getGameId() == GID_QFG4) {
+ return false;
+ }
+
+ // GK1 DOS floppy is low resolution only, but GK1 Mac floppy is high
+ // resolution only
+ if (g_sci->getGameId() == GID_GK1 &&
+ !g_sci->isCD() &&
+ g_sci->getPlatform() != Common::kPlatformMacintosh) {
+
+ return false;
+ }
+
+ // All other games are either high resolution by default, or have a
+ // user-defined toggle
+ return ConfMan.getBool("enable_high_resolution_graphics");
+}
+
+#pragma mark -
+#pragma mark Benchmarking
+
+bool GfxFrameout::checkForFred(const reg_t object) {
+ const int16 viewId = readSelectorValue(_segMan, object, SELECTOR(view));
+ const SciGameId gameId = g_sci->getGameId();
+
+ if (gameId == GID_QFG4 && viewId == 9999) {
+ return true;
+ }
+
+ if (gameId != GID_QFG4 && viewId == -556) {
+ return true;
+ }
+
+ if (Common::String(_segMan->getObjectName(object)) == "fred") {
+ return true;
+ }
+
+ return false;
+}
+
#pragma mark -
#pragma mark Screen items
+void GfxFrameout::addScreenItem(ScreenItem &screenItem) const {
+ Plane *plane = _planes.findByObject(screenItem._plane);
+ if (plane == nullptr) {
+ error("GfxFrameout::addScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x", PRINT_REG(screenItem._plane), PRINT_REG(screenItem._object));
+ }
+ plane->_screenItemList.add(&screenItem);
+}
+
+void GfxFrameout::updateScreenItem(ScreenItem &screenItem) const {
+ // TODO: In SCI3+ this will need to go through Plane
+// Plane *plane = _planes.findByObject(screenItem._plane);
+// if (plane == nullptr) {
+// error("GfxFrameout::updateScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x", PRINT_REG(screenItem._plane), PRINT_REG(screenItem._object));
+// }
+
+ screenItem.update();
+}
+
+void GfxFrameout::deleteScreenItem(ScreenItem &screenItem) {
+ Plane *plane = _planes.findByObject(screenItem._plane);
+ if (plane == nullptr) {
+ error("GfxFrameout::deleteScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x", PRINT_REG(screenItem._plane), PRINT_REG(screenItem._object));
+ }
+ if (plane->_screenItemList.findByObject(screenItem._object) == nullptr) {
+ error("GfxFrameout::deleteScreenItem: Screen item %04x:%04x not found in plane %04x:%04x", PRINT_REG(screenItem._object), PRINT_REG(screenItem._plane));
+ }
+ deleteScreenItem(screenItem, *plane);
+}
+
+void GfxFrameout::deleteScreenItem(ScreenItem &screenItem, Plane &plane) {
+ if (screenItem._created == 0) {
+ screenItem._created = 0;
+ screenItem._updated = 0;
+ screenItem._deleted = getScreenCount();
+ } else {
+ plane._screenItemList.erase(&screenItem);
+ plane._screenItemList.pack();
+ }
+}
+
+void GfxFrameout::deleteScreenItem(ScreenItem &screenItem, const reg_t planeObject) {
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ error("GfxFrameout::deleteScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(screenItem._object));
+ }
+ deleteScreenItem(screenItem, *plane);
+}
+
void GfxFrameout::kernelAddScreenItem(const reg_t object) {
- const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
+ // The "fred" object is used to test graphics performance;
+ // it is impacted by framerate throttling, so disable the
+ // throttling when this item is on the screen for the
+ // performance check to pass.
+ if (!_benchmarkingFinished && _throttleFrameOut && checkForFred(object)) {
+ _throttleFrameOut = false;
+ }
-// TODO: Remove
-// debug("Adding screen item %04x:%04x to plane %04x:%04x", PRINT_REG(object), PRINT_REG(planeObject));
+ const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
_segMan->getObject(object)->setInfoSelectorFlag(kInfoFlagViewInserted);
Plane *plane = _planes.findByObject(planeObject);
if (plane == nullptr) {
- warning("screen item %x:%x (%s)", object.getSegment(), object.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(object));
- warning("plane %x:%x (%s)", planeObject.getSegment(), planeObject.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(planeObject));
- error("Invalid plane selector passed to kAddScreenItem");
+ error("kAddScreenItem: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(object));
}
ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
@@ -272,53 +335,44 @@ void GfxFrameout::kernelUpdateScreenItem(const reg_t object) {
const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
Plane *plane = _planes.findByObject(planeObject);
if (plane == nullptr) {
- warning("screen item %x:%x (%s)", object.getSegment(), object.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(object));
- warning("plane %x:%x (%s)", planeObject.getSegment(), planeObject.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(planeObject));
- error("Invalid plane selector passed to kUpdateScreenItem");
+ error("kUpdateScreenItem: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(object));
}
ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
if (screenItem == nullptr) {
- warning("screen item %x:%x (%s)", object.getSegment(), object.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(object));
- warning("plane %x:%x (%s)", planeObject.getSegment(), planeObject.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(planeObject));
- error("Invalid screen item passed to kUpdateScreenItem");
+ error("kUpdateScreenItem: Screen item %04x:%04x not found in plane %04x:%04x", PRINT_REG(object), PRINT_REG(planeObject));
}
screenItem->update(object);
} else {
- warning("TODO: Magnifier view not implemented yet!");
+ error("Magnifier view is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!");
}
}
void GfxFrameout::kernelDeleteScreenItem(const reg_t object) {
+ // The "fred" object is used to test graphics performance;
+ // it is impacted by framerate throttling, so disable the
+ // throttling when this item is on the screen for the
+ // performance check to pass.
+ if (!_benchmarkingFinished && checkForFred(object)) {
+ _benchmarkingFinished = true;
+ _throttleFrameOut = true;
+ }
+
_segMan->getObject(object)->clearInfoSelectorFlag(kInfoFlagViewInserted);
const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
Plane *plane = _planes.findByObject(planeObject);
if (plane == nullptr) {
- // TODO: Remove
-// warning("Invalid plane selector %04x:%04x passed to kDeleteScreenItem (real engine ignores this)", PRINT_REG(object));
return;
}
-// TODO: Remove
-// debug("Deleting screen item %04x:%04x from plane %04x:%04x", PRINT_REG(object), PRINT_REG(planeObject));
-
ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
if (screenItem == nullptr) {
-// TODO: Remove
-// warning("Invalid screen item %04x:%04x passed to kDeleteScreenItem (real engine ignores this)", PRINT_REG(object));
return;
}
- if (screenItem->_created == 0) {
- screenItem->_created = 0;
- screenItem->_updated = 0;
- screenItem->_deleted = getScreenCount();
- } else {
- plane->_screenItemList.erase(screenItem);
- plane->_screenItemList.pack();
- }
+ deleteScreenItem(*screenItem, *plane);
}
#pragma mark -
@@ -338,8 +392,7 @@ void GfxFrameout::kernelAddPlane(const reg_t object) {
void GfxFrameout::kernelUpdatePlane(const reg_t object) {
Plane *plane = _planes.findByObject(object);
if (plane == nullptr) {
- warning("plane %x:%x (%s)", object.getSegment(), object.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(object));
- error("Invalid plane selector passed to kUpdatePlane");
+ error("kUpdatePlane: Plane %04x:%04x not found", PRINT_REG(object));
}
plane->update(object);
@@ -349,8 +402,7 @@ void GfxFrameout::kernelUpdatePlane(const reg_t object) {
void GfxFrameout::kernelDeletePlane(const reg_t object) {
Plane *plane = _planes.findByObject(object);
if (plane == nullptr) {
- warning("plane %x:%x (%s)", object.getSegment(), object.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(object));
- error("Invalid plane selector passed to kDeletePlane");
+ error("kDeletePlane: Plane %04x:%04x not found", PRINT_REG(object));
}
if (plane->_created) {
@@ -358,13 +410,53 @@ void GfxFrameout::kernelDeletePlane(const reg_t object) {
// just ends up doing this anyway so we skip the extra indirection
_planes.erase(plane);
} else {
- // TODO: Remove
-// debug("Deleting plane %04x:%04x", PRINT_REG(object));
plane->_created = 0;
plane->_deleted = g_sci->_gfxFrameout->getScreenCount();
}
}
+void GfxFrameout::deletePlane(Plane &planeToFind) {
+ Plane *plane = _planes.findByObject(planeToFind._object);
+ if (plane == nullptr) {
+ error("deletePlane: Plane %04x:%04x not found", PRINT_REG(planeToFind._object));
+ }
+
+ if (plane->_created) {
+ _planes.erase(plane);
+ } else {
+ plane->_created = 0;
+ plane->_moved = 0;
+ plane->_deleted = getScreenCount();
+ }
+}
+
+void GfxFrameout::kernelMovePlaneItems(const reg_t object, const int16 deltaX, const int16 deltaY, const bool scrollPics) {
+ Plane *plane = _planes.findByObject(object);
+ if (plane == nullptr) {
+ error("kMovePlaneItems: Plane %04x:%04x not found", PRINT_REG(object));
+ }
+
+ plane->scrollScreenItems(deltaX, deltaY, scrollPics);
+
+ for (ScreenItemList::iterator it = plane->_screenItemList.begin(); it != plane->_screenItemList.end(); ++it) {
+ ScreenItem &screenItem = **it;
+
+ // If object is a number, the screen item from the
+ // engine, not a script, and should be ignored
+ if (screenItem._object.isNumber()) {
+ continue;
+ }
+
+ if (deltaX != 0) {
+ writeSelectorValue(_segMan, screenItem._object, SELECTOR(x), readSelectorValue(_segMan, screenItem._object, SELECTOR(x)) + deltaX);
+ }
+
+ if (deltaY != 0) {
+ writeSelectorValue(_segMan, screenItem._object, SELECTOR(y), readSelectorValue(_segMan, screenItem._object, SELECTOR(y)) + deltaY);
+ }
+ }
+}
+
int16 GfxFrameout::kernelGetHighPlanePri() {
return _planes.getTopSciPlanePriority();
}
@@ -398,23 +490,24 @@ void GfxFrameout::updatePlane(Plane &plane) {
#pragma mark -
#pragma mark Pics
-void GfxFrameout::kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 x, const int16 y, const bool mirrorX) {
+void GfxFrameout::kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 x, const int16 y, const bool mirrorX, const bool deleteDuplicate) {
Plane *plane = _planes.findByObject(planeObject);
if (plane == nullptr) {
- warning("plane %x:%x (%s)", planeObject.getSegment(), planeObject.getOffset(), g_sci->getEngineState()->_segMan->getObjectName(planeObject));
- error("Invalid plane selector passed to kAddPicAt");
+ error("kAddPicAt: Plane %04x:%04x not found", PRINT_REG(planeObject));
}
- plane->addPic(pictureId, Common::Point(x, y), mirrorX);
+ plane->addPic(pictureId, Common::Point(x, y), mirrorX, deleteDuplicate);
}
#pragma mark -
#pragma mark Rendering
-void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &rect) {
-// TODO: Robot
-// if (_robot != nullptr) {
-// _robot.doRobot();
-// }
+void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &eraseRect) {
+ RobotDecoder &robotPlayer = g_sci->_video32->getRobotPlayer();
+ const bool robotIsActive = robotPlayer.getStatus() != RobotDecoder::kRobotStatusUninitialized;
+
+ if (robotIsActive) {
+ robotPlayer.doRobot();
+ }
// NOTE: The original engine allocated these as static arrays of 100
// pointers to ScreenItemList / RectList
@@ -424,12 +517,11 @@ void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &rect)
screenItemLists.resize(_planes.size());
eraseLists.resize(_planes.size());
- // _numActiveRemaps was a global in SCI engine
- if (/* TODO Remap::_numActiveRemaps > 0 */ false && _remapOccurred) {
- // remapMarkRedraw();
+ if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) {
+ remapMarkRedraw();
}
- calcLists(screenItemLists, eraseLists, rect);
+ calcLists(screenItemLists, eraseLists, eraseRect);
for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
list->sort();
@@ -453,12 +545,11 @@ void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &rect)
drawScreenItemList(screenItemLists[i]);
}
-// TODO: Robot
-// if (_robot != nullptr) {
-// _robot->frameAlmostVisible();
-// }
+ if (robotIsActive) {
+ robotPlayer.frameAlmostVisible();
+ }
- _palette->updateHardware();
+ _palette->updateHardware(!shouldShowBits);
if (shouldShowBits) {
showBits();
@@ -466,136 +557,335 @@ void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &rect)
_frameNowVisible = true;
-// TODO: Robot
-// if (_robot != nullptr) {
-// robot->frameNowVisible();
-// }
+ if (robotIsActive) {
+ robotPlayer.frameNowVisible();
+ }
+}
+
+void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *showStyle) {
+ Palette sourcePalette(_palette->getNextPalette());
+ alterVmap(sourcePalette, sourcePalette, -1, styleRanges);
+
+ int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][kGlobalVarPreviousRoomNo].toSint16();
+
+ Common::Rect rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight);
+ _showList.add(rect);
+ showBits();
+
+ // NOTE: The original engine allocated these as static arrays of 100
+ // pointers to ScreenItemList / RectList
+ ScreenItemListList screenItemLists;
+ EraseListList eraseLists;
+
+ screenItemLists.resize(_planes.size());
+ eraseLists.resize(_planes.size());
+
+ if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) {
+ remapMarkRedraw();
+ }
+
+ calcLists(screenItemLists, eraseLists);
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ list->sort();
+ }
+
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) {
+ (*drawItem)->screenItem->getCelObj().submitPalette();
+ }
+ }
+
+ _remapOccurred = _palette->updateForFrame();
+ _frameNowVisible = false;
+
+ for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
+ drawEraseList(eraseLists[i], *_planes[i]);
+ drawScreenItemList(screenItemLists[i]);
+ }
+
+ Palette nextPalette(_palette->getNextPalette());
+
+ if (prevRoom < 1000) {
+ for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
+ if (styleRanges[i] == -1 || styleRanges[i] == 0) {
+ sourcePalette.colors[i] = nextPalette.colors[i];
+ sourcePalette.colors[i].used = true;
+ }
+ }
+ } else {
+ for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
+ if (styleRanges[i] == -1 || validZeroStyle(styleRanges[i], i)) {
+ sourcePalette.colors[i] = nextPalette.colors[i];
+ sourcePalette.colors[i].used = true;
+ }
+ }
+ }
+
+ _palette->submit(sourcePalette);
+ _palette->updateFFrame();
+ _palette->updateHardware();
+ alterVmap(nextPalette, sourcePalette, 1, _transitions->_styleRanges);
+
+ if (showStyle && showStyle->type != kShowStyleMorph) {
+ _transitions->processEffects(*showStyle);
+ } else {
+ showBits();
+ }
+
+ _frameNowVisible = true;
+
+ for (PlaneList::iterator plane = _planes.begin(); plane != _planes.end(); ++plane) {
+ (*plane)->_redrawAllCount = getScreenCount();
+ }
+
+ if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) {
+ remapMarkRedraw();
+ }
+
+ calcLists(screenItemLists, eraseLists);
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ list->sort();
+ }
+
+ for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
+ for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) {
+ (*drawItem)->screenItem->getCelObj().submitPalette();
+ }
+ }
+
+ _remapOccurred = _palette->updateForFrame();
+ // NOTE: During this second loop, `_frameNowVisible = false` is
+ // inside the next loop in SCI2.1mid
+ _frameNowVisible = false;
+
+ for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
+ drawEraseList(eraseLists[i], *_planes[i]);
+ drawScreenItemList(screenItemLists[i]);
+ }
+
+ _palette->submit(nextPalette);
+ _palette->updateFFrame();
+ _palette->updateHardware(false);
+ showBits();
+
+ _frameNowVisible = true;
}
-// Determine the parts of 'r' that aren't overlapped by 'other'.
-// Returns -1 if r and other have no intersection.
-// Returns number of returned parts (in outRects) otherwise.
-// (In particular, this returns 0 if r is contained in other.)
+/**
+ * Determines the parts of `r` that aren't overlapped by `other`.
+ * Returns -1 if `r` and `other` have no intersection.
+ * Returns number of returned parts (in `outRects`) otherwise.
+ * (In particular, this returns 0 if `r` is contained in `other`.)
+ */
int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&outRects)[4]) {
if (!r.intersects(other)) {
return -1;
}
- int count = 0;
+ int splitCount = 0;
if (r.top < other.top) {
- Common::Rect &t = outRects[count++];
+ Common::Rect &t = outRects[splitCount++];
t = r;
t.bottom = other.top;
r.top = other.top;
}
if (r.bottom > other.bottom) {
- Common::Rect &t = outRects[count++];
+ Common::Rect &t = outRects[splitCount++];
t = r;
t.top = other.bottom;
r.bottom = other.bottom;
}
if (r.left < other.left) {
- Common::Rect &t = outRects[count++];
+ Common::Rect &t = outRects[splitCount++];
t = r;
t.right = other.left;
r.left = other.left;
}
if (r.right > other.right) {
- Common::Rect &t = outRects[count++];
+ Common::Rect &t = outRects[splitCount++];
t = r;
t.left = other.right;
}
- return count;
+ return splitCount;
}
-void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &calcRect) {
- RectList rectlist;
- Common::Rect outRects[4];
+/**
+ * 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`.)
+ *
+ * `middleRect` is modified directly to extend into the upper
+ * and lower rects.
+ */
+int splitRectsForRender(Common::Rect &middleRect, const Common::Rect &showRect, Common::Rect(&outRects)[2]) {
+ if (!middleRect.intersects(showRect)) {
+ return -1;
+ }
+
+ const int16 minLeft = MIN(middleRect.left, showRect.left);
+ const int16 maxRight = MAX(middleRect.right, showRect.right);
+
+ int16 upperLeft, upperTop, upperRight, upperMaxTop;
+ if (middleRect.top < showRect.top) {
+ upperLeft = middleRect.left;
+ upperTop = middleRect.top;
+ upperRight = middleRect.right;
+ upperMaxTop = showRect.top;
+ }
+ else {
+ upperLeft = showRect.left;
+ upperTop = showRect.top;
+ upperRight = showRect.right;
+ upperMaxTop = middleRect.top;
+ }
+
+ int16 lowerLeft, lowerRight, lowerBottom, lowerMinBottom;
+ if (middleRect.bottom > showRect.bottom) {
+ lowerLeft = middleRect.left;
+ lowerRight = middleRect.right;
+ lowerBottom = middleRect.bottom;
+ lowerMinBottom = showRect.bottom;
+ } else {
+ lowerLeft = showRect.left;
+ lowerRight = showRect.right;
+ lowerBottom = showRect.bottom;
+ lowerMinBottom = middleRect.bottom;
+ }
+
+ int splitCount = 0;
+ middleRect.left = minLeft;
+ middleRect.top = upperMaxTop;
+ middleRect.right = maxRight;
+ middleRect.bottom = lowerMinBottom;
+
+ if (upperTop != upperMaxTop) {
+ Common::Rect &upperRect = outRects[0];
+ upperRect.left = upperLeft;
+ upperRect.top = upperTop;
+ upperRect.right = upperRight;
+ upperRect.bottom = upperMaxTop;
+
+ // Merge upper rect into middle rect if possible
+ if (upperRect.left == middleRect.left && upperRect.right == middleRect.right) {
+ middleRect.top = upperRect.top;
+ } else {
+ ++splitCount;
+ }
+ }
+
+ if (lowerBottom != lowerMinBottom) {
+ Common::Rect &lowerRect = outRects[splitCount];
+ lowerRect.left = lowerLeft;
+ lowerRect.top = lowerMinBottom;
+ lowerRect.right = lowerRight;
+ lowerRect.bottom = lowerBottom;
+
+ // Merge lower rect into middle rect if possible
+ if (lowerRect.left == middleRect.left && lowerRect.right == middleRect.right) {
+ middleRect.bottom = lowerRect.bottom;
+ } else {
+ ++splitCount;
+ }
+ }
+
+ assert(splitCount <= 2);
+ return splitCount;
+}
+// NOTE: The third rectangle parameter is only ever given a non-empty rect
+// by VMD code, via `frameOut`
+void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &eraseRect) {
+ RectList eraseList;
+ Common::Rect outRects[4];
int deletedPlaneCount = 0;
- bool addedToRectList = false;
- int planeCount = _planes.size();
+ bool addedToEraseList = false;
bool foundTransparentPlane = false;
- if (!calcRect.isEmpty()) {
- addedToRectList = true;
- rectlist.add(calcRect);
+ if (!eraseRect.isEmpty()) {
+ addedToEraseList = true;
+ eraseList.add(eraseRect);
}
- for (int outerPlaneIndex = 0; outerPlaneIndex < planeCount; ++outerPlaneIndex) {
- Plane *outerPlane = _planes[outerPlaneIndex];
+ PlaneList::size_type planeCount = _planes.size();
+ for (PlaneList::size_type outerPlaneIndex = 0; outerPlaneIndex < planeCount; ++outerPlaneIndex) {
+ const Plane *outerPlane = _planes[outerPlaneIndex];
+ const Plane *visiblePlane = _visiblePlanes.findByObject(outerPlane->_object);
+ // NOTE: SSCI only ever checks for kPlaneTypeTransparent here, even
+ // though kPlaneTypeTransparentPicture is also a transparent plane
if (outerPlane->_type == kPlaneTypeTransparent) {
foundTransparentPlane = true;
}
- Plane *visiblePlane = _visiblePlanes.findByObject(outerPlane->_object);
-
if (outerPlane->_deleted) {
- if (visiblePlane != nullptr) {
- if (!visiblePlane->_screenRect.isEmpty()) {
- addedToRectList = true;
- rectlist.add(visiblePlane->_screenRect);
- }
+ if (visiblePlane != nullptr && !visiblePlane->_screenRect.isEmpty()) {
+ eraseList.add(visiblePlane->_screenRect);
+ addedToEraseList = true;
}
++deletedPlaneCount;
- } else if (visiblePlane != nullptr) {
- if (outerPlane->_updated) {
- --outerPlane->_updated;
-
- int splitcount = splitRects(visiblePlane->_screenRect, outerPlane->_screenRect, outRects);
- if (splitcount) {
- if (splitcount == -1) {
- if (!visiblePlane->_screenRect.isEmpty()) {
- rectlist.add(visiblePlane->_screenRect);
- }
+ } else if (visiblePlane != nullptr && outerPlane->_moved) {
+ // _moved will be decremented in the final loop through the planes,
+ // at the end of this function
+
+ {
+ const int splitCount = splitRects(visiblePlane->_screenRect, outerPlane->_screenRect, outRects);
+ if (splitCount) {
+ if (splitCount == -1 && !visiblePlane->_screenRect.isEmpty()) {
+ eraseList.add(visiblePlane->_screenRect);
} else {
- for (int i = 0; i < splitcount; ++i) {
- rectlist.add(outRects[i]);
+ for (int i = 0; i < splitCount; ++i) {
+ eraseList.add(outRects[i]);
}
}
-
- addedToRectList = true;
+ addedToEraseList = true;
}
+ }
- if (!outerPlane->_redrawAllCount) {
- int splitCount = splitRects(outerPlane->_screenRect, visiblePlane->_screenRect, outRects);
- if (splitCount) {
- for (int i = 0; i < splitCount; ++i) {
- rectlist.add(outRects[i]);
- }
- addedToRectList = true;
+ if (!outerPlane->_redrawAllCount) {
+ const int splitCount = splitRects(outerPlane->_screenRect, visiblePlane->_screenRect, outRects);
+ if (splitCount) {
+ for (int i = 0; i < splitCount; ++i) {
+ eraseList.add(outRects[i]);
}
+ addedToEraseList = true;
}
}
}
- if (addedToRectList) {
- for (RectList::iterator rect = rectlist.begin(); rect != rectlist.end(); ++rect) {
- for (int innerPlaneIndex = _planes.size() - 1; innerPlaneIndex >= 0; --innerPlaneIndex) {
- Plane *innerPlane = _planes[innerPlaneIndex];
-
- if (!innerPlane->_deleted && innerPlane->_type != kPlaneTypeTransparent && innerPlane->_screenRect.intersects(**rect)) {
- if (innerPlane->_redrawAllCount == 0) {
- eraseLists[innerPlaneIndex].add(innerPlane->_screenRect.findIntersectingRect(**rect));
+ if (addedToEraseList) {
+ for (RectList::size_type rectIndex = 0; rectIndex < eraseList.size(); ++rectIndex) {
+ const Common::Rect &rect = *eraseList[rectIndex];
+ for (int innerPlaneIndex = planeCount - 1; innerPlaneIndex >= 0; --innerPlaneIndex) {
+ const Plane &innerPlane = *_planes[innerPlaneIndex];
+
+ if (
+ !innerPlane._deleted &&
+ innerPlane._type != kPlaneTypeTransparent &&
+ innerPlane._screenRect.intersects(rect)
+ ) {
+ if (!innerPlane._redrawAllCount) {
+ eraseLists[innerPlaneIndex].add(innerPlane._screenRect.findIntersectingRect(rect));
}
- int splitCount = splitRects(**rect, innerPlane->_screenRect, outRects);
+ const int splitCount = splitRects(rect, innerPlane._screenRect, outRects);
for (int i = 0; i < splitCount; ++i) {
- rectlist.add(outRects[i]);
+ eraseList.add(outRects[i]);
}
- rectlist.erase(rect);
+ eraseList.erase_at(rectIndex);
break;
}
}
}
- rectlist.pack();
+ eraseList.pack();
}
}
@@ -607,9 +897,9 @@ void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseL
if (plane->_deleted) {
--plane->_deleted;
if (plane->_deleted <= 0) {
- PlaneList::iterator visiblePlaneIt = Common::find_if(_visiblePlanes.begin(), _visiblePlanes.end(), FindByObject<Plane *>(plane->_object));
- if (visiblePlaneIt != _visiblePlanes.end()) {
- _visiblePlanes.erase(visiblePlaneIt);
+ const int visiblePlaneIndex = _visiblePlanes.findIndexByObject(plane->_object);
+ if (visiblePlaneIndex != -1) {
+ _visiblePlanes.remove_at(visiblePlaneIndex);
}
_planes.remove_at(planeIndex);
@@ -624,103 +914,118 @@ void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseL
}
}
+ // Some planes may have been deleted, so re-retrieve count
planeCount = _planes.size();
- for (int outerIndex = 0; outerIndex < planeCount; ++outerIndex) {
- // "outer" just refers to the outer loop
- Plane *outerPlane = _planes[outerIndex];
- if (outerPlane->_priorityChanged) {
- --outerPlane->_priorityChanged;
- Plane *visibleOuterPlane = _visiblePlanes.findByObject(outerPlane->_object);
+ for (PlaneList::size_type outerIndex = 0; outerIndex < planeCount; ++outerIndex) {
+ // "outer" just refers to the outer loop
+ Plane &outerPlane = *_planes[outerIndex];
+ if (outerPlane._priorityChanged) {
+ --outerPlane._priorityChanged;
+
+ const Plane *visibleOuterPlane = _visiblePlanes.findByObject(outerPlane._object);
+ if (visibleOuterPlane == nullptr) {
+ warning("calcLists could not find visible plane for %04x:%04x", PRINT_REG(outerPlane._object));
+ continue;
+ }
- rectlist.add(outerPlane->_screenRect.findIntersectingRect(visibleOuterPlane->_screenRect));
+ eraseList.add(outerPlane._screenRect.findIntersectingRect(visibleOuterPlane->_screenRect));
- for (int innerIndex = planeCount - 1; innerIndex >= 0; --innerIndex) {
+ for (int innerIndex = (int)planeCount - 1; innerIndex >= 0; --innerIndex) {
// "inner" just refers to the inner loop
- Plane *innerPlane = _planes[innerIndex];
- Plane *visibleInnerPlane = _visiblePlanes.findByObject(innerPlane->_object);
-
- int rectCount = rectlist.size();
- for (int rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
- int splitCount = splitRects(*rectlist[rectIndex], _planes[innerIndex]->_screenRect, outRects);
+ const Plane &innerPlane = *_planes[innerIndex];
+ const Plane *visibleInnerPlane = _visiblePlanes.findByObject(innerPlane._object);
+ const RectList::size_type rectCount = eraseList.size();
+ for (RectList::size_type rectIndex = 0; rectIndex < rectCount; ++rectIndex) {
+ const int splitCount = splitRects(*eraseList[rectIndex], innerPlane._screenRect, outRects);
if (splitCount == 0) {
if (visibleInnerPlane != nullptr) {
// same priority, or relative priority between inner/outer changed
- if ((visibleOuterPlane->_priority - visibleInnerPlane->_priority) * (outerPlane->_priority - innerPlane->_priority) <= 0) {
- if (outerPlane->_priority <= innerPlane->_priority) {
- eraseLists[innerIndex].add(*rectlist[rectIndex]);
+ if ((visibleOuterPlane->_priority - visibleInnerPlane->_priority) * (outerPlane._priority - innerPlane._priority) <= 0) {
+ if (outerPlane._priority <= innerPlane._priority) {
+ eraseLists[innerIndex].add(*eraseList[rectIndex]);
} else {
- eraseLists[outerIndex].add(*rectlist[rectIndex]);
+ eraseLists[outerIndex].add(*eraseList[rectIndex]);
}
}
}
- rectlist.erase_at(rectIndex);
+ eraseList.erase_at(rectIndex);
} else if (splitCount != -1) {
for (int i = 0; i < splitCount; ++i) {
- rectlist.add(outRects[i]);
+ eraseList.add(outRects[i]);
}
if (visibleInnerPlane != nullptr) {
// same priority, or relative priority between inner/outer changed
- if ((visibleOuterPlane->_priority - visibleInnerPlane->_priority) * (outerPlane->_priority - innerPlane->_priority) <= 0) {
- *rectlist[rectIndex] = outerPlane->_screenRect.findIntersectingRect(innerPlane->_screenRect);
- if (outerPlane->_priority <= innerPlane->_priority) {
- eraseLists[innerIndex].add(*rectlist[rectIndex]);
- }
- else {
- eraseLists[outerIndex].add(*rectlist[rectIndex]);
+ if ((visibleOuterPlane->_priority - visibleInnerPlane->_priority) * (outerPlane._priority - innerPlane._priority) <= 0) {
+ *eraseList[rectIndex] = outerPlane._screenRect.findIntersectingRect(innerPlane._screenRect);
+
+ if (outerPlane._priority <= innerPlane._priority) {
+ eraseLists[innerIndex].add(*eraseList[rectIndex]);
+ } else {
+ eraseLists[outerIndex].add(*eraseList[rectIndex]);
}
}
}
- rectlist.erase_at(rectIndex);
+ eraseList.erase_at(rectIndex);
}
}
- rectlist.pack();
+ eraseList.pack();
}
}
}
- for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
- Plane *plane = _planes[planeIndex];
- Plane *visiblePlane = nullptr;
+ for (PlaneList::size_type planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
+ Plane &plane = *_planes[planeIndex];
+ Plane *visiblePlane = _visiblePlanes.findByObject(plane._object);
- PlaneList::iterator visiblePlaneIt = Common::find_if(_visiblePlanes.begin(), _visiblePlanes.end(), FindByObject<Plane *>(plane->_object));
- if (visiblePlaneIt != _visiblePlanes.end()) {
- visiblePlane = *visiblePlaneIt;
- }
+ if (!plane._screenRect.isEmpty()) {
+ if (plane._redrawAllCount) {
+ plane.redrawAll(visiblePlane, _planes, drawLists[planeIndex], eraseLists[planeIndex]);
+ } else {
+ if (visiblePlane == nullptr) {
+ error("Missing visible plane for source plane %04x:%04x", PRINT_REG(plane._object));
+ }
- if (plane->_redrawAllCount) {
- plane->redrawAll(visiblePlane, _planes, drawLists[planeIndex], eraseLists[planeIndex]);
- } else {
- if (visiblePlane == nullptr) {
- error("Missing visible plane for source plane %04x:%04x", PRINT_REG(plane->_object));
+ plane.calcLists(*visiblePlane, _planes, drawLists[planeIndex], eraseLists[planeIndex]);
}
+ } else {
+ plane.decrementScreenItemArrayCounts(visiblePlane, false);
+ }
- plane->calcLists(*visiblePlane, _planes, drawLists[planeIndex], eraseLists[planeIndex]);
+ if (plane._moved) {
+ // the work for handling moved/resized planes was already done
+ // earlier in the function, we are just cleaning up now
+ --plane._moved;
}
- if (plane->_created) {
- _visiblePlanes.add(new Plane(*plane));
- --plane->_created;
- } else if (plane->_moved) {
- assert(visiblePlaneIt != _visiblePlanes.end());
- **visiblePlaneIt = *plane;
- --plane->_moved;
+ if (plane._created) {
+ _visiblePlanes.add(new Plane(plane));
+ --plane._created;
+ } else if (plane._updated) {
+ if (visiblePlane == nullptr) {
+ error("[GfxFrameout::calcLists]: Attempt to update nonexistent visible plane");
+ }
+
+ *visiblePlane = plane;
+ --plane._updated;
}
}
+ // NOTE: SSCI only looks for kPlaneTypeTransparent, not
+ // kPlaneTypeTransparentPicture
if (foundTransparentPlane) {
- for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
- for (int i = planeIndex + 1; i < planeCount; ++i) {
+ for (PlaneList::size_type planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
+ for (PlaneList::size_type i = planeIndex + 1; i < planeCount; ++i) {
if (_planes[i]->_type == kPlaneTypeTransparent) {
_planes[i]->filterUpEraseRects(drawLists[i], eraseLists[planeIndex]);
}
}
if (_planes[planeIndex]->_type == kPlaneTypeTransparent) {
- for (int i = planeIndex - 1; i >= 0; --i) {
+ for (int i = (int)planeIndex - 1; i >= 0; --i) {
_planes[i]->filterDownEraseRects(drawLists[i], eraseLists[i], eraseLists[planeIndex]);
}
@@ -729,7 +1034,7 @@ void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseL
}
}
- for (int i = planeIndex + 1; i < planeCount; ++i) {
+ for (PlaneList::size_type i = planeIndex + 1; i < planeCount; ++i) {
if (_planes[i]->_type == kPlaneTypeTransparent) {
_planes[i]->filterUpDrawRects(drawLists[i], drawLists[planeIndex]);
}
@@ -743,188 +1048,90 @@ void GfxFrameout::drawEraseList(const RectList &eraseList, const Plane &plane) {
return;
}
- for (RectList::const_iterator it = eraseList.begin(); it != eraseList.end(); ++it) {
- mergeToShowList(**it, _showList, _overdrawThreshold);
- _currentBuffer.fillRect(**it, plane._back);
+ const RectList::size_type eraseListSize = eraseList.size();
+ for (RectList::size_type i = 0; i < eraseListSize; ++i) {
+ mergeToShowList(*eraseList[i], _showList, _overdrawThreshold);
+ _currentBuffer.fillRect(*eraseList[i], plane._back);
}
}
void GfxFrameout::drawScreenItemList(const DrawList &screenItemList) {
- _hasRemappedScreenItem = false;
- if (/* TODO: g_Remap_UnknownCounter2 */ false && !_priorityMap.isNull()) {
- for (DrawList::const_iterator it = screenItemList.begin(); it != screenItemList.end(); ++it) {
- if ((*it)->screenItem->getCelObj()._remap) {
- _hasRemappedScreenItem = true;
- break;
- }
- }
- }
-
- for (DrawList::const_iterator it = screenItemList.begin(); it != screenItemList.end(); ++it) {
- DrawItem &drawItem = **it;
+ const DrawList::size_type drawListSize = screenItemList.size();
+ for (DrawList::size_type i = 0; i < drawListSize; ++i) {
+ const DrawItem &drawItem = *screenItemList[i];
mergeToShowList(drawItem.rect, _showList, _overdrawThreshold);
- ScreenItem &screenItem = *drawItem.screenItem;
+ const ScreenItem &screenItem = *drawItem.screenItem;
// TODO: Remove
-// debug("Drawing item %04x:%04x to %d %d %d %d", PRINT_REG(screenItem._object), drawItem.rect.left, drawItem.rect.top, drawItem.rect.right, drawItem.rect.bottom);
+// debug("Drawing item %04x:%04x to %d %d %d %d", PRINT_REG(screenItem._object), PRINT_RECT(drawItem.rect));
CelObj &celObj = *screenItem._celObj;
celObj.draw(_currentBuffer, screenItem, drawItem.rect, screenItem._mirrorX ^ celObj._mirrorX);
}
}
void GfxFrameout::mergeToShowList(const Common::Rect &drawRect, RectList &showList, const int overdrawThreshold) {
- Common::Rect merged(drawRect);
-
- bool didDelete = true;
- RectList::size_type count = showList.size();
- while (didDelete && count) {
- didDelete = false;
-
- for (RectList::size_type i = 0; i < count; ++i) {
- Common::Rect existing = *showList[i];
- Common::Rect candidate;
- candidate.left = MIN(merged.left, existing.left);
- candidate.top = MIN(merged.top, existing.top);
- candidate.right = MAX(merged.right, existing.right);
- candidate.bottom = MAX(merged.bottom, existing.bottom);
-
- if (candidate.height() * candidate.width() - merged.width() * merged.height() - existing.width() * existing.height() <= overdrawThreshold) {
- merged = candidate;
- showList.erase_at(i);
- didDelete = true;
- }
- }
-
- count = showList.pack();
- }
-
- showList.add(merged);
-}
-
-void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle) {
- Palette sourcePalette(*_palette->getNextPalette());
- alterVmap(sourcePalette, sourcePalette, -1, styleRanges);
-
- // TODO: unsure if this is what this variable actually
- // represents, but it is the correct variable number
- int16 lastRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][12].toSint16();
-
- Common::Rect rect(_screen->getDisplayWidth(), _screen->getDisplayHeight());
- _showList.add(rect);
- showBits();
-
- Common::Rect calcRect(0, 0);
-
- // NOTE: The original engine allocated these as static arrays of 100
- // pointers to ScreenItemList / RectList
- ScreenItemListList screenItemLists;
- EraseListList eraseLists;
-
- screenItemLists.resize(_planes.size());
- eraseLists.resize(_planes.size());
-
- // TODO: Remap
- // _numActiveRemaps was a global in SCI engine
- // if (Remap::_numActiveRemaps > 0 && _remapOccurred) {
- // _screen->remapMarkRedraw();
- // }
-
- calcLists(screenItemLists, eraseLists, calcRect);
- for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
- list->sort();
- }
-
- for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
- for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) {
- (*drawItem)->screenItem->getCelObj().submitPalette();
- }
- }
-
- _remapOccurred = _palette->updateForFrame();
- _frameNowVisible = false;
-
- for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
- drawEraseList(eraseLists[i], *_planes[i]);
- drawScreenItemList(screenItemLists[i]);
- }
-
- Palette nextPalette(*_palette->getNextPalette());
+ RectList mergeList;
+ Common::Rect merged;
+ mergeList.add(drawRect);
+
+ for (RectList::size_type i = 0; i < mergeList.size(); ++i) {
+ bool didMerge = false;
+ const Common::Rect &r1 = *mergeList[i];
+ if (!r1.isEmpty()) {
+ for (RectList::size_type j = 0; j < showList.size(); ++j) {
+ const Common::Rect &r2 = *showList[j];
+ if (!r2.isEmpty()) {
+ merged = r1;
+ merged.extend(r2);
+
+ int difference = merged.width() * merged.height();
+ difference -= r1.width() * r1.height();
+ difference -= r2.width() * r2.height();
+ if (r1.intersects(r2)) {
+ const Common::Rect overlap = r1.findIntersectingRect(r2);
+ difference += overlap.width() * overlap.height();
+ }
- if (lastRoom < 1000) {
- for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
- if (styleRanges[i] == -1 || styleRanges[i] == 0) {
- sourcePalette.colors[i] = nextPalette.colors[i];
- sourcePalette.colors[i].used = true;
- }
- }
- } else {
- for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) {
- if (styleRanges[i] == -1 || (styleRanges[i] == 0 && i > 71 && i < 104)) {
- sourcePalette.colors[i] = nextPalette.colors[i];
- sourcePalette.colors[i].used = true;
+ if (difference <= overdrawThreshold) {
+ mergeList.erase_at(i);
+ showList.erase_at(j);
+ mergeList.add(merged);
+ didMerge = true;
+ break;
+ } else {
+ Common::Rect outRects[2];
+ int splitCount = splitRectsForRender(*mergeList[i], *showList[j], outRects);
+ if (splitCount != -1) {
+ mergeList.add(*mergeList[i]);
+ mergeList.erase_at(i);
+ showList.erase_at(j);
+ didMerge = true;
+ while (splitCount--) {
+ mergeList.add(outRects[splitCount]);
+ }
+ break;
+ }
+ }
+ }
}
- }
- }
- _palette->submit(sourcePalette);
- _palette->updateFFrame();
- _palette->updateHardware();
- alterVmap(nextPalette, sourcePalette, 1, _styleRanges);
-
- if (showStyle && showStyle->type != kShowStyleUnknown) {
-// TODO: SCI2.1mid transition effects
-// processEffects();
- warning("Transition not implemented!");
- } else {
- showBits();
- }
-
- _frameNowVisible = true;
-
- for (PlaneList::iterator plane = _planes.begin(); plane != _planes.end(); ++plane) {
-// TODO:
-// plane->updateRedrawAllCount();
- }
-
- // TODO: Remap
- // _numActiveRemaps was a global in SCI engine
- // if (Remap::_numActiveRemaps > 0 && _remapOccurred) {
- // _screen->remapMarkRedraw();
- // }
-
- calcLists(screenItemLists, eraseLists, calcRect);
- for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
- list->sort();
- }
-
- for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
- for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) {
- (*drawItem)->screenItem->getCelObj().submitPalette();
+ if (didMerge) {
+ showList.pack();
+ }
}
}
- _remapOccurred = _palette->updateForFrame();
- // NOTE: During this second loop, `_frameNowVisible = false` is
- // inside the next loop in SCI2.1mid
- _frameNowVisible = false;
-
- for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
- drawEraseList(eraseLists[i], *_planes[i]);
- drawScreenItemList(screenItemLists[i]);
+ mergeList.pack();
+ for (RectList::size_type i = 0; i < mergeList.size(); ++i) {
+ showList.add(*mergeList[i]);
}
-
- _palette->submit(nextPalette);
- _palette->updateFFrame();
- _palette->updateHardware();
- showBits();
-
- _frameNowVisible = true;
}
-// TODO: What does the bit masking for the show rects do,
-// and does it cause an off-by-one error in rect calculations
-// since SOL_Rect is BR inclusive and Common::Rect is BR
-// exclusive?
void GfxFrameout::showBits() {
+ if (!_showList.size()) {
+ g_system->updateScreen();
+ return;
+ }
+
for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
Common::Rect rounded(**rect);
// NOTE: SCI engine used BR-inclusive rects so used slightly
@@ -932,13 +1139,10 @@ void GfxFrameout::showBits() {
// was always even.
rounded.left &= ~1;
rounded.right = (rounded.right + 1) & ~1;
-
- // TODO:
- // _cursor->GonnaPaint(rounded);
+ _cursor->gonnaPaint(rounded);
}
- // TODO:
- // _cursor->PaintStarting();
+ _cursor->paintStarting();
for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
Common::Rect rounded(**rect);
@@ -950,13 +1154,20 @@ void GfxFrameout::showBits() {
byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.screenWidth + rounded.left;
+ // TODO: Sometimes transition screen items generate zero-dimension
+ // show rectangles. Is this a bug?
+ if (rounded.width() == 0 || rounded.height() == 0) {
+ warning("Zero-dimension show rectangle ignored");
+ continue;
+ }
+
g_system->copyRectToScreen(sourceBuffer, _currentBuffer.screenWidth, rounded.left, rounded.top, rounded.width(), rounded.height());
}
- // TODO:
- // _cursor->DonePainting();
+ _cursor->donePainting();
_showList.clear();
+ g_system->updateScreen();
}
void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, const int8 style, const int8 *const styleRanges) {
@@ -969,7 +1180,7 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co
if (styleRanges[paletteIndex] == style) {
int minDiff = 262140;
- int minDiffIndex;
+ int minDiffIndex = paletteIndex;
for (int i = 0; i < 236; ++i) {
if (styleRanges[i] != style) {
@@ -989,7 +1200,7 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co
if (style == 1 && styleRanges[paletteIndex] == 0) {
int minDiff = 262140;
- int minDiffIndex;
+ int minDiffIndex = paletteIndex;
for (int i = 0; i < 236; ++i) {
int r = palette2.colors[i].r;
@@ -1007,17 +1218,17 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co
}
}
- // NOTE: This is currBuffer->ptr in SCI engine
byte *pixels = (byte *)_currentBuffer.getPixels();
- // TODO: Guessing that display width/height is the correct
- // equivalent to screen width/height in SCI engine
for (int pixelIndex = 0, numPixels = _currentBuffer.screenWidth * _currentBuffer.screenHeight; pixelIndex < numPixels; ++pixelIndex) {
byte currentValue = pixels[pixelIndex];
int8 styleRangeValue = styleRanges[currentValue];
if (styleRangeValue == -1 && styleRangeValue == style) {
currentValue = pixels[pixelIndex] = clut[currentValue];
- styleRangeValue = styleRanges[clut[currentValue]];
+ // NOTE: In original engine this assignment happens outside of the
+ // condition, but if the branch is not followed the value is just
+ // going to be the same as it was before
+ styleRangeValue = styleRanges[currentValue];
}
if (
@@ -1029,1009 +1240,155 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co
}
}
-void GfxFrameout::kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor) {
- if (toColor > fromColor) {
- return;
- }
-
- for (int i = fromColor; i < toColor; ++i) {
- _styleRanges[i] = 0;
- }
-}
-
-inline ShowStyleEntry * GfxFrameout::findShowStyleForPlane(const reg_t planeObj) const {
- ShowStyleEntry *entry = _showStyles;
- while (entry != nullptr) {
- if (entry->plane == planeObj) {
- break;
- }
- entry = entry->next;
- }
-
- return entry;
-}
-
-inline ShowStyleEntry *GfxFrameout::deleteShowStyleInternal(ShowStyleEntry *const showStyle) {
- ShowStyleEntry *lastEntry = nullptr;
-
- for (ShowStyleEntry *testEntry = _showStyles; testEntry != nullptr; testEntry = testEntry->next) {
- if (testEntry == showStyle) {
- break;
- }
- lastEntry = testEntry;
- }
-
- if (lastEntry == nullptr) {
- _showStyles = showStyle->next;
- lastEntry = _showStyles;
+void GfxFrameout::kernelFrameOut(const bool shouldShowBits) {
+ if (_transitions->hasShowStyles()) {
+ _transitions->processShowStyles();
+ } else if (_palMorphIsOn) {
+ palMorphFrameOut(_transitions->_styleRanges, nullptr);
+ _palMorphIsOn = false;
} else {
- lastEntry->next = showStyle->next;
- }
-
- // NOTE: Differences from SCI2/2.1early engine:
- // 1. Memory of ShowStyle-owned objects was freed before ShowStyle was
- // removed from the linked list, but since this operation is position
- // independent, it has been moved after removal from the list for
- // consistency with SCI2.1mid+
- // 2. In SCI2, `screenItems` was a pointer to an array of pointers, so
- // extra deletes were performed here; we use an owned container object
- // instead, which is automatically freed when ShowStyle is freed
-#if 0
- if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
- uint8 type = showStyle->type;
-
- if (type >= 1 && type <= 10) {
- ScreenItemList &styleItems = showStyle->screenItems;
- for (ScreenItemList::iterator it = styleItems.begin(); it != styleItems.end(); ++it) {
- if (active) {
- // TODO: _screen->deleteScreenItem(showStyle->plane, *it->id);
- _screenItems.remove(*it);
- }
- delete *it;
- }
- } else if (type == 11 || type == 12) {
- if (!showStyle->bitmapMemId.isNull()) {
- _segMan->freeHunkEntry(showStyle->bitmapMemId);
- }
- if (showStyle->bitmapScreenItem != nullptr) {
- // TODO: _screen->deleteScreenItem(showStyle->plane, showStyle->bitmapScreenItem->id);
- _screenItems.remove(showStyle->bitmapScreenItem);
- delete showStyle->bitmapScreenItem;
- }
+ if (_transitions->hasScrolls()) {
+ _transitions->processScrolls();
}
- } else {
-#endif
- delete[] showStyle->fadeColorRanges;
-#if 0
- }
-#endif
- delete showStyle;
-
- // TODO: Verify that this is the correct entry to return
- // for the loop in processShowStyles to work correctly
- return lastEntry;
-}
-
-// TODO: 10-argument version is only in SCI3; argc checks are currently wrong for this version
-// and need to be fixed in future
-// TODO: SQ6 does not use 'priority' (exists since SCI2) or 'blackScreen' (exists since SCI3);
-// check to see if other versions use or if they are just always ignored
-void GfxFrameout::kernelSetShowStyle(const uint16 argc, const reg_t &planeObj, const ShowStyleType type, const int16 seconds, const int16 back, const int16 priority, const int16 animate, const int16 frameOutNow, const reg_t &pFadeArray, const int16 divisions, const int16 blackScreen) {
-
- bool hasDivisions = false;
- bool hasFadeArray = false;
- if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
- hasDivisions = argc > 7;
- hasFadeArray = false;
- } else if (getSciVersion() < SCI_VERSION_3) {
- hasDivisions = argc > 8;
- hasFadeArray = argc > 7;
- } else {
- hasDivisions = argc > 9;
- hasFadeArray = argc > 8;
+ frameOut(shouldShowBits);
}
- bool isFadeUp;
- int16 color;
- if (back != -1) {
- isFadeUp = false;
- color = back;
- } else {
- isFadeUp = true;
- color = 0;
- }
-
- if ((getSciVersion() < SCI_VERSION_2_1_MIDDLE && type == 15) || type > 15) {
- error("Illegal show style %d for plane %04x:%04x", type, PRINT_REG(planeObj));
- }
-
- Plane *plane = _planes.findByObject(planeObj);
- if (plane == nullptr) {
- error("Plane %04x:%04x is not present in active planes list", PRINT_REG(planeObj));
- }
-
- // TODO: This is Plane.gameRect in SCI engine, not planeRect. Engine uses
- // Plane::ConvGameRectToPlaneRect to convert from gameRect to planeRect.
- // Also this never gets used by SQ6 so it is not clear what it does yet
- // Common::Rect gameRect = plane.planeRect;
-
- bool createNewEntry = true;
- ShowStyleEntry *entry = findShowStyleForPlane(planeObj);
- if (entry != nullptr) {
- bool useExisting = true;
-
- if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
- useExisting = plane->_planeRect.width() == entry->width && plane->_planeRect.height() == entry->height;
- }
-
- if (useExisting) {
- useExisting = entry->divisions == (hasDivisions ? divisions : _defaultDivisions[type]) && entry->unknownC == _defaultUnknownC[type];
- }
-
- if (useExisting) {
- createNewEntry = false;
- isFadeUp = true;
- entry->currentStep = 0;
- } else {
- isFadeUp = true;
- color = entry->color;
- deleteShowStyleInternal(entry/*, true*/);
- entry = nullptr;
- }
- }
-
- if (type > 0) {
- if (createNewEntry) {
- entry = new ShowStyleEntry;
- // NOTE: SCI2.1 engine tests if allocation returned a null pointer
- // but then only avoids setting currentStep if this is so. Since
- // this is a nonsensical approach, we do not do that here
- entry->currentStep = 0;
- entry->unknownC = _defaultUnknownC[type];
- entry->processed = false;
- entry->divisions = hasDivisions ? divisions : _defaultDivisions[type];
- entry->plane = planeObj;
-
-#if 0
- if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
- entry->bitmapMemId = NULL_REG;
- entry->screenItems.empty();
- entry->width = plane->_planeRect.width();
- entry->height = plane->_planeRect.height();
- } else {
-#endif
- entry->fadeColorRanges = nullptr;
- if (hasFadeArray) {
- // NOTE: SCI2.1mid engine does no check to verify that an array is
- // successfully retrieved, and SegMan will cause a fatal error
- // if we try to use a memory segment that is not an array
- SciArray<reg_t> *table = _segMan->lookupArray(pFadeArray);
-
- uint32 rangeCount = table->getSize();
- entry->fadeColorRangesCount = rangeCount;
-
- // NOTE: SCI engine code always allocates memory even if the range
- // table has no entries, but this does not really make sense, so
- // we avoid the allocation call in this case
- if (rangeCount > 0) {
- entry->fadeColorRanges = new uint16[rangeCount];
- for (size_t i = 0; i < rangeCount; ++i) {
- entry->fadeColorRanges[i] = table->getValue(i).toUint16();
- }
- }
- } else {
- entry->fadeColorRangesCount = 0;
- }
-#if 0
- }
-#endif
- }
-
- // NOTE: The original engine had no nullptr check and would just crash
- // if it got to here
- if (entry == nullptr) {
- error("Cannot edit non-existing ShowStyle entry");
- }
-
- entry->fadeUp = isFadeUp;
- entry->color = color;
- entry->nextTick = g_sci->getTickCount();
- entry->type = type;
- entry->animate = animate;
- entry->delay = (seconds * 60 + entry->divisions - 1) / entry->divisions;
-
- if (entry->delay == 0) {
-#if 0
- if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE && entry->fadeColorRanges != nullptr) {
-#endif
- if (entry->fadeColorRanges != nullptr) {
- delete[] entry->fadeColorRanges;
- }
- delete entry;
- error("ShowStyle has no duration");
- }
-
- if (frameOutNow) {
- Common::Rect frameOutRect(0, 0);
- frameOut(false, frameOutRect);
- }
-
- if (createNewEntry) {
- // TODO: Implement SCI3, which may or may not actually have
- // the same transitions as SCI2/SCI2.1early, but implemented
- // differently
-#if 0
- if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
- switch (entry->type) {
- case kShowStyleHShutterIn:
- case kShowStyleHShutterOut:
- prepareShowStyleWipe(entry, priority, 2, true);
- break;
-
- case kShowStyleVShutterIn:
- case kShowStyleVShutterOut:
- prepareShowStyleWipe(entry, priority, 2, false);
- break;
-
- case kShowStyleHWipe1:
- case kShowStyleHWipe2:
- prepareShowStyleWipe(entry, priority, 1, true);
- break;
-
- case kShowStyleVWipe1:
- case kShowStyleVWipe2:
- prepareShowStyleWipe(entry, priority, 1, false);
- break;
-
- case kShowStyleIrisIn:
- case kShowStyleIrisOut:
- prepareShowStyleIris(entry, priority);
- break;
-
- case kShowStyle11:
- case kShowStyle12:
- prepareShowStylePixels(entry, priority, plane->planeRect);
- break;
-
- default:
- break;
- }
- }
-#endif
-
- entry->next = _showStyles;
- _showStyles = entry;
- }
- }
+ throttle();
}
-#if 0
-void addFrameoutEntryInternal(ShowStyleEntry *const showStyle, const int16 priority, const CelInfo32 &celInfo, const Common::Rect &rect) {
- ScreenItem *screenItem = new ScreenItem;
- screenItem->plane = showStyle->plane;
- screenItem->celInfo = celInfo;
- screenItem->celRect = rect;
- screenItem->isInList = true;
- screenItem->priority = priority;
- screenItem->visible = true;
- showStyle->screenItems.push_back(screenItem);
-}
-
-void GfxFrameout::prepareShowStyleWipe(ShowStyleEntry *const showStyle, const int16 priority, const int16 edgeCount, const bool horizontal) {
- assert(edgeCount == 1 || edgeCount == 2);
-
- const int numScreenItems = showStyle->divisions * edgeCount;
- const int extra = edgeCount > 1 ? 1 : 0;
-
- showStyle->edgeCount = edgeCount;
- showStyle->screenItems.reserve(numScreenItems);
-
- CelInfo32 celInfo;
- celInfo.bitmap = NULL_REG;
- celInfo.type = kCelObjTypeView;
- celInfo.color = showStyle->color;
-
- for (int i = 0; i < numScreenItems; ++i) {
- Common::Rect rect;
-
- if (horizontal) {
- rect.top = 0;
- rect.bottom = showStyle->height - 1;
- rect.left = (showStyle->width * i) / (showStyle->divisions * edgeCount);
- rect.right = ((i + 1) * (showStyle->width + extra)) / (showStyle->divisions * edgeCount) - 1;
+void GfxFrameout::throttle() {
+ if (_throttleFrameOut) {
+ uint8 throttleTime;
+ if (_throttleState == 2) {
+ throttleTime = 16;
+ _throttleState = 0;
} else {
- rect.left = 0;
- rect.right = showStyle->width - 1;
- rect.top = (showStyle->height * i) / (showStyle->divisions * edgeCount);
- rect.bottom = ((i + 1) * (showStyle->height + extra)) / (showStyle->divisions * edgeCount) - 1;
- }
-
- addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
-
- if (edgeCount == 2) {
- if (horizontal) {
- int temp = rect.left;
- rect.left = showStyle->width - rect.right - 1;
- rect.right = showStyle->width - temp - 1;
- } else {
- int temp = rect.top;
- rect.top = showStyle->height - rect.bottom - 1;
- rect.bottom = showStyle->height - temp - 1;
- }
-
- addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
- }
- }
-}
-
-void GfxFrameout::prepareShowStyleIris(ShowStyleEntry *const showStyle, const int16 priority) {
- const int edgeCount = 4;
- const int numScreenItems = showStyle->divisions * edgeCount;
-
- showStyle->edgeCount = edgeCount;
- showStyle->screenItems.reserve(numScreenItems);
-
- CelInfo32 celInfo;
- celInfo.bitmap = NULL_REG;
- celInfo.type = kCelObjTypeView;
- celInfo.color = showStyle->color;
-
- for (int i = 0; i < numScreenItems; ++i) {
- Common::Rect rect;
-
- rect.right = showStyle->width - ((showStyle->width * i) / (showStyle->divisions * 2)) - 1;
- rect.left = (showStyle->width * i) / (showStyle->divisions * 2);
- rect.top = (showStyle->height * i) / (showStyle->divisions * 2);
- rect.bottom = ((i + 1) * (showStyle->height + 1)) / (showStyle->divisions * 2) - 1;
-
- addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
-
- {
- int temp = rect.top;
- rect.top = showStyle->height - rect.bottom - 1;
- rect.bottom = showStyle->height - temp - 1;
+ throttleTime = 17;
+ ++_throttleState;
}
- addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
-
- rect.top = ((i + 1) * (showStyle->height + 1)) / (showStyle->divisions * 2);
- rect.right = ((i + 1) * (showStyle->width + 1)) / (showStyle->divisions * 2) - 1;
- rect.bottom = ((i + 1) * (showStyle->height + 1)) / (showStyle->divisions * 2) - 1;
-
- addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
-
- {
- int temp = rect.left;
- rect.left = showStyle->width - rect.right - 1;
- rect.right = showStyle->width - temp - 1;
- }
-
- addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
+ g_sci->getEngineState()->speedThrottler(throttleTime);
+ g_sci->getEngineState()->_throttleTrigger = true;
}
}
-void GfxFrameout::prepareShowStylePixels(ShowStyleEntry *const showStyle, const int16 priority, const Common::Rect planeGameRect) {
- const int bitmapSize = showStyle->width * showStyle->height;
-
- // TODO: Verify that memory type 0x200 (what GK1 engine uses)
- // is Hunk type
- reg_t bitmapMemId = _segMan->allocateHunkEntry("ShowStylePixels()", bitmapSize + sizeof(GfxBitmapHeader));
- showStyle->bitmapMemId = bitmapMemId;
-
- // TODO: SCI2 GK1 uses a Bitmap constructor function to
- // do this work
- byte *bitmap = _segMan->getHunkPointer(bitmapMemId);
- GfxBitmapHeader *header = (GfxBitmapHeader *)bitmap;
- byte *bitmapData = bitmap + sizeof(GfxBitmapHeader);
-
- // TODO: These are defaults from the Bitmap constructor in
- // GK1, not specific values set by this function.
- // TODO: This probably should not even be using a struct at
- // all since this information is machine endian dependent
- // and will be reversed for Mac versions or when running
- // ScummVM on big-endian systems. GK1 used packed structs
- // everywhere so this probably worked better there too.
- header->field_18 = 36;
- header->field_1c = 36;
- memset(header, 0, sizeof(GfxBitmapHeader));
-
- header->width = showStyle->width;
- header->height = showStyle->height;
- header->field_8 = 250;
- header->size = bitmapSize;
-
- // TODO: Scaled dimensions in bitmap headers was not added
- // until SCI2.1mid. It is not clear what the right thing to
- // do here is.
- if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) {
- header->scaledWidth = _currentBuffer.scriptWidth;
- header->scaledHeight = _currentBuffer.scriptHeight;
- }
-
- Common::Rect copyRect;
- // TODO: planeGameRect is supposedly in script coordinates,
- // which are usually 320x200. If bitsSaveDisplayScreen is
- // in native resolution then seemingly this function will
- // not work properly since we will be not copy enough bits,
- // or from the correct location.
- copyRect.left = planeGameRect.left;
- copyRect.top = planeGameRect.top;
- copyRect.right = planeGameRect.left + showStyle->width;
- copyRect.bottom = planeGameRect.top + showStyle->height;
- _screen->bitsSaveDisplayScreen(copyRect, bitmapData);
-
- CelInfo32 celInfo;
- celInfo.bitmap = bitmapMemId;
- celInfo.type = kCelObjTypeMem;
-
- ScreenItem *screenItem = new ScreenItem;
-
- screenItem->position.x = 0;
- screenItem->position.y = 0;
-
- showStyle->bitmapScreenItem = screenItem;
- screenItem->priority = priority;
-
- // TODO: Have not seen/identified this particular flag yet in
- // SCI2.1mid (SQ6) engine; maybe (1) a duplicate of `created`,
- // or (2) does not exist any more, or (3) one of the other
- // still-unidentified fields. Probably need to look at the
- // GK1 source for its use in drawing algorithms to determine
- // if/how this correlates to ScreenItem members in the
- // SCI2.1mid engine.
-// screenItem->isInList = true;
-
- Plane *plane = _planes.findByObject(showStyle.plane);
- plane->_screenItemList.add(screenItem);
-}
-#endif
-
-// NOTE: Different version of SCI engine support different show styles
-// SCI2 implements 0, 1/3/5/7/9, 2/4/6/8/10, 11, 12, 13, 14
-// SCI2.1 implements 0, 1/2/3/4/5/6/7/8/9/10/11/12/15, 13, 14
-// SCI3 implements 0, 1/3/5/7/9, 2/4/6/8/10, 11, 12/15, 13, 14
-// TODO: Sierra code needs to be replaced with code that uses the
-// computed entry->delay property instead of just counting divisors,
-// as the latter is machine-speed-dependent and leads to wrong
-// transition speeds
-void GfxFrameout::processShowStyles() {
- uint32 now = g_sci->getTickCount();
-
- bool continueProcessing;
-
- // TODO: Change to bool? Engine uses inc to set the value to true,
- // but there does not seem to be any reason to actually count how
- // many times it was set
- int doFrameOut;
- do {
- continueProcessing = false;
- doFrameOut = 0;
- ShowStyleEntry *showStyle = _showStyles;
- while (showStyle != nullptr) {
- bool retval = false;
-
- if (!showStyle->animate) {
- ++doFrameOut;
- }
-
- if (showStyle->nextTick < now || !showStyle->animate) {
- // TODO: Different versions of SCI use different processors!
- // This is the SQ6/KQ7/SCI2.1mid table.
- switch (showStyle->type) {
- case kShowStyleNone: {
- retval = processShowStyleNone(showStyle);
- break;
- }
- case kShowStyleHShutterOut:
- case kShowStyleVShutterOut:
- case kShowStyleWipeLeft:
- case kShowStyleWipeUp:
- case kShowStyleIrisOut:
-#if 0
- if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) {
-#endif
- retval = processShowStyleMorph(showStyle);
-#if 0
- } else {
- retval = processShowStyleWipe(-1, showStyle);
- }
-#endif
- break;
- case kShowStyleHShutterIn:
- case kShowStyleVShutterIn:
- case kShowStyleWipeRight:
- case kShowStyleWipeDown:
- case kShowStyleIrisIn:
-#if 0
- if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) {
-#endif
- retval = processShowStyleMorph(showStyle);
-#if 0
- } else {
- retval = processShowStyleWipe(1, showStyle);
- }
-#endif
- break;
- case kShowStyle11:
-#if 0
- if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) {
-#endif
- retval = processShowStyleMorph(showStyle);
-#if 0
- } else {
- retval = processShowStyle11(showStyle);
- }
-#endif
- break;
- case kShowStyle12:
- case kShowStyleUnknown: {
-#if 0
- if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) {
-#endif
- retval = processShowStyleMorph(showStyle);
-#if 0
- } else {
- retval = processShowStyle12(showStyle);
- }
-#endif
- break;
- }
- case kShowStyleFadeOut: {
- retval = processShowStyleFade(-1, showStyle);
- break;
- }
- case kShowStyleFadeIn: {
- retval = processShowStyleFade(1, showStyle);
- break;
- }
- }
- }
-
- if (!retval) {
- continueProcessing = true;
- }
-
- if (retval && showStyle->processed) {
- showStyle = deleteShowStyleInternal(showStyle);
- } else {
- showStyle = showStyle->next;
- }
- }
-
- if (doFrameOut) {
- Common::Rect frameOutRect(0, 0);
- frameOut(true, frameOutRect);
-
- // TODO: It seems like transitions without the “animate”
- // flag are too fast in in SCI2–2.1early, but the throttle
- // value is arbitrary. Someone on real hardware probably
- // needs to test what the actual speed of transitions
- // should be
- //state->speedThrottler(30);
- //state->_throttleTrigger = true;
- }
- } while(continueProcessing && doFrameOut);
-}
-
-bool GfxFrameout::processShowStyleNone(ShowStyleEntry *const showStyle) {
- if (showStyle->fadeUp) {
- _palette->setFade(100, 0, 255);
- } else {
- _palette->setFade(0, 0, 255);
- }
-
- showStyle->processed = true;
- return true;
-}
-
-bool GfxFrameout::processShowStyleMorph(ShowStyleEntry *const showStyle) {
- palMorphFrameOut(_styleRanges, showStyle);
- showStyle->processed = true;
- return true;
-}
-
-// TODO: Normalise use of 'entry' vs 'showStyle'
-bool GfxFrameout::processShowStyleFade(const int direction, ShowStyleEntry *const showStyle) {
- bool unchanged = true;
- if (showStyle->currentStep < showStyle->divisions) {
- int percent;
- if (direction <= 0) {
- percent = showStyle->divisions - showStyle->currentStep - 1;
- } else {
- percent = showStyle->currentStep;
- }
-
- percent *= 100;
- percent /= showStyle->divisions - 1;
-
- if (showStyle->fadeColorRangesCount > 0) {
- for (int i = 0, len = showStyle->fadeColorRangesCount; i < len; i += 2) {
- _palette->setFade(percent, showStyle->fadeColorRanges[i], showStyle->fadeColorRanges[i + 1]);
- }
- } else {
- _palette->setFade(percent, 0, 255);
- }
-
- ++showStyle->currentStep;
- showStyle->nextTick += showStyle->delay;
- unchanged = false;
+void GfxFrameout::shakeScreen(int16 numShakes, const ShakeDirection direction) {
+ if (direction & kShakeHorizontal) {
+ // Used by QFG4 room 750
+ warning("TODO: Horizontal shake not implemented");
+ return;
}
- if (showStyle->currentStep >= showStyle->divisions && unchanged) {
- if (direction > 0) {
- showStyle->processed = true;
+ while (numShakes--) {
+ if (direction & kShakeVertical) {
+ g_system->setShakePos(_isHiRes ? 8 : 4);
}
- return true;
- }
-
- return false;
-}
-
-// TODO: Rect sizes are wrong, rects in SCI are inclusive of bottom/right but
-// in ScummVM are exclusive so extra ±1 operations here are wrong
-#if 0
-bool GfxFrameout::processShowStyleWipe(const ShowStyleEntry *const style) {
- const int16 divisions = style->divisions;
- Common::Rect rect(divisions, divisions);
-
- const Plane *const plane = _visibleScreen->planeList->findByObject(style->plane);
-
- const int16 planeLeft = plane->field_4C.left;
- const int16 planeTop = plane->field_4C.top;
- const int16 planeRight = plane->field_4C.right;
- const int16 planeBottom = plane->field_4C.bottom;
- const int16 planeWidth = planeRight - planeLeft + 1;
- const int16 planeHeight = planeBottom - planeTop + 1;
-
- const int16 divisionWidth = planeWidth / divisions - 1;
- int16 shutterDivisionWidth = planeWidth / (2 * divisions);
- if (shutterDivisionWidth >= 0) {
- const int16 heightPerDivision = planeHeight / divisions;
- int16 shutterMiddleX = divisions * shutterDivisionWidth;
- for (int16 x = divisionWidth - shutterDivisionWidth; x <= divisionWidth; ++x) {
- int16 divisionTop = 0;
- for (int16 y = 0; y < heightPerDivision; ++y, divisionTop += divisions) {
- rect.top = planeTop + divisionTop;
- rect.bottom = rect.top + divisions - 1;
- rect.left = planeLeft + shutterMiddleX;
- rect.right = rect.left + divisions - 1;
- // _screen->rectList.clear();
- // _screen->rectList.add(rect);
- // showBits();
- }
- // number of divisions does not divide evenly into plane height,
- // draw the remainder
- if (planeHeight % divisions) {
- rect.top = planeTop + divisionTop;
- rect.bottom = rect.top + planeHeight % divisions - 1;
- rect.left = planeLeft + shutterMiddleX;
- rect.right = rect.left + divisions - 1;
- // _screen->rectList.clear();
- // _screen->rectList.add(rect);
- // showBits();
- }
+ g_system->updateScreen();
+ g_sci->getEngineState()->wait(3);
- divisionTop = 0;
- for (int16 y = 0; y < heightPerDivision; ++y, divisionTop += divisions) {
- rect.top = planeTop + divisionTop;
- rect.bottom = rect.top + divisions - 1;
- rect.left = planeLeft + divisions * x;
- rect.right = rect.left + divisions - 1;
- // _screen->rectList.clear();
- // _screen->rectList.add(rect);
- // showBits();
- }
- if (planeHeight % divisions) {
- rect.top = planeTop + divisionTop;
- rect.bottom = rect.top + planeHeight % divisions - 1;
- rect.left = planeLeft + divisions * x;
- rect.right = rect.left + divisions - 1;
- // _screen->rectList.clear();
- // _screen->rectList.add(rect);
- // showBits();
- }
-
- shutterMiddleX -= divisions;
- --shutterDivisionWidth;
+ if (direction & kShakeVertical) {
+ g_system->setShakePos(0);
}
- }
- if (planeWidth % divisions) {
- const int16 roundedPlaneWidth = divisions * divisionWidth;
- int16 divisionTop = 0;
- for (int16 y = 0; y < planeHeight / divisions; ++y, divisionTop += divisions) {
- rect.top = planeTop + divisionTop;
- rect.bottom = rect.top + divisions - 1;
- rect.left = planeLeft + roundedPlaneWidth;
- rect.right = rect.left + planeWidth % divisions + divisions - 1;
- // _screen->rectList.clear();
- // _screen->rectList.add(rect);
- // showBits();
- }
- if (planeHeight % divisions) {
- rect.top = planeTop + divisionTop;
- rect.bottom = rect.top + planeHeight % divisions - 1;
- rect.left = planeLeft + roundedPlaneWidth;
- rect.right = rect.left + planeWidth % divisions + divisions - 1;
- // _screen->rectList.clear();
- // _screen->rectList.add(rect);
- // showBits();
- }
+ g_system->updateScreen();
+ g_sci->getEngineState()->wait(3);
}
-
- rect.right = planeRight;
- rect.left = planeLeft;
- rect.top = planeTop;
- rect.bottom = planeBottom;
- // _screen->rectList.clear();
- // _screen->rectList.add(rect);
- // showBits();
}
-#endif
-#if 0
-bool GfxFrameout::processShowStyleWipe(const int direction, ShowStyleEntry *const showStyle) {
- if (showStyle->currentStep < showStyle->divisions) {
- int index;
- if (direction <= 0) {
- index = showStyle->divisions - showStyle->currentStep - 1;
- } else {
- index = showStyle->currentStep;
- }
- index *= showStyle->edgeCount;
-
- if (showStyle->edgeCount > 0) {
- for (int i = 0; i < showStyle->edgeCount; ++i) {
- if (showStyle->fadeUp) {
- ScreenItem *screenItem = showStyle->screenItems[index + i];
- if (screenItem != nullptr) {
- // TODO: _screen->deleteScreenItem(screenItem);
- _screenItems.remove(screenItem);
-
- delete screenItem;
- showStyle->screenItems[index + i] = nullptr;
- }
- } else {
- ScreenItem *screenItem = showStyle->screenItems[index + i];
- // TODO: _screen->addScreenItem(screenItem);
- _screenItems.push_back(screenItem);
- }
- }
+#pragma mark -
+#pragma mark Mouse cursor
- ++showStyle->currentStep;
- showStyle->nextTick += showStyle->delay;
- }
+reg_t GfxFrameout::kernelIsOnMe(const reg_t object, const Common::Point &position, bool checkPixel) const {
+ const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
+ Plane *plane = _visiblePlanes.findByObject(planeObject);
+ if (plane == nullptr) {
+ return make_reg(0, 0);
}
- if (showStyle->currentStep >= showStyle->divisions) {
- if (showStyle->fadeUp) {
- showStyle->processed = true;
- }
-
- return true;
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
+ if (screenItem == nullptr) {
+ return make_reg(0, 0);
}
- return false;
+ // NOTE: The original engine passed a copy of the ScreenItem into isOnMe
+ // as a hack around the fact that the screen items in `_visiblePlanes`
+ // did not have their `_celObj` pointers cleared when their CelInfo was
+ // updated by `Plane::decrementScreenItemArrayCounts`. We handle this
+ // this more intelligently by clearing `_celObj` in the copy assignment
+ // operator, which is only ever called by `decrementScreenItemArrayCounts`
+ // anyway.
+ return make_reg(0, isOnMe(*screenItem, *plane, position, checkPixel));
}
-void fillRect(byte *data, const Common::Rect &rect, const int16 color, const int16 stride) {
-
-}
-
-bool GfxFrameout::processShowStyle11(ShowStyleEntry *const showStyle) {
- int divisions = showStyle->divisions * showStyle->divisions;
-
- byte *bitmapData = _segMan->getHunkPointer(showStyle->bitmapMemId) + sizeof(GfxBitmapHeader);
+bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const Common::Point &position, const bool checkPixel) const {
- int ebx;
+ Common::Point scaledPosition(position);
+ mulru(scaledPosition, Ratio(_currentBuffer.screenWidth, _currentBuffer.scriptWidth), Ratio(_currentBuffer.screenHeight, _currentBuffer.scriptHeight));
+ scaledPosition.x += plane._planeRect.left;
+ scaledPosition.y += plane._planeRect.top;
- if (showStyle->currentStep == 0) {
- int ctr = 0;
- int bloot = divisions;
- do {
- bloot >>= 1;
- ++ctr;
- } while (bloot != 1);
-
- showStyle->dissolveSeed = _dissolveSequenceSeeds[ctr];
- ebx = 800;
- showStyle->unknown3A = 800;
- showStyle->dissolveInitial = 800;
- } else {
- int ebx = showStyle->unknown3A;
- do {
- int eax = ebx >> 1;
- if (ebx & 1) {
- ebx = showStyle->dissolveSeed ^ eax;
- } else {
- ebx = eax;
- }
- } while (ebx >= divisions);
-
- if (ebx == showStyle->dissolveInitial) {
- ebx = 0;
- }
+ if (!screenItem._screenRect.contains(scaledPosition)) {
+ return false;
}
- Common::Rect rect;
-
- rect.left = (showStyle->width + showStyle->divisions - 1) / showStyle->divisions;
- rect.top = (showStyle->height + showStyle->divisions - 1) / showStyle->divisions;
-
- if (showStyle->currentStep <= showStyle->divisions) {
- int ebp = 0;
- do {
- int ecx = ebx % showStyle->divisions;
-
- Common::Rect drawRect;
- drawRect.left = rect.left * ecx;
- drawRect.right = drawRect.left + rect.left - 1;
- drawRect.top = rect.top * ebx;
- drawRect.bottom = rect.top * ebx + rect.top - 1;
-
- bool doit;
- if (drawRect.right >= 0 && drawRect.bottom >= 0 && drawRect.left <= rect.right && drawRect.top <= rect.bottom) {
- doit = true;
- } else {
- doit = false;
- }
-
- if (doit) {
- if (drawRect.left < 0) {
- drawRect.left = 0;
- }
-
- if (drawRect.top < 0) {
- drawRect.top = 0;
- }
-
- if (drawRect.right > rect.right) {
- drawRect.right = rect.right;
- }
-
- if (drawRect.bottom > rect.bottom) {
- drawRect.bottom = rect.bottom;
- }
- } else {
- drawRect.right = 0;
- drawRect.bottom = 0;
- drawRect.left = 0;
- drawRect.top = 0;
- }
-
- fillRect(bitmapData, drawRect, showStyle->color, showStyle->width);
-
- int eax = ebx;
- do {
- eax >>= 1;
- if (ebx & 1) {
- ebx = showStyle->dissolveSeed;
- ebx ^= eax;
- } else {
- ebx = eax;
- }
- } while (ebx >= divisions);
+ if (checkPixel) {
+ CelObj &celObj = screenItem.getCelObj();
- if (showStyle->currentStep != showStyle->divisions) {
- ebp++;
- } else {
- drawRect.left = 0;
- drawRect.top = 0;
- drawRect.right = showStyle->width - 1;
- drawRect.bottom = showStyle->height - 1;
- fillRect(bitmapData, drawRect, showStyle->color, showStyle->width);
- }
+ bool mirrorX = screenItem._mirrorX ^ celObj._mirrorX;
- } while (ebp <= showStyle->divisions);
+ scaledPosition.x -= screenItem._scaledPosition.x;
+ scaledPosition.y -= screenItem._scaledPosition.y;
- showStyle->unknown3A = ebx;
- ++showStyle->currentStep;
- showStyle->nextTick += showStyle->delay;
- // _screen->updateScreenItem(showStyle->bitmapScreenItem);
- }
+ mulru(scaledPosition, Ratio(celObj._xResolution, _currentBuffer.screenWidth), Ratio(celObj._yResolution, _currentBuffer.screenHeight));
- if (showStyle->currentStep >= showStyle->divisions) {
- if (showStyle->fadeUp) {
- showStyle->processed = true;
+ if (screenItem._scale.signal != kScaleSignalNone && screenItem._scale.x && screenItem._scale.y) {
+ scaledPosition.x = scaledPosition.x * 128 / screenItem._scale.x;
+ scaledPosition.y = scaledPosition.y * 128 / screenItem._scale.y;
}
- return true;
+ uint8 pixel = celObj.readPixel(scaledPosition.x, scaledPosition.y, mirrorX);
+ return pixel != celObj._skipColor;
}
- return false;
-}
-
-bool GfxFrameout::processShowStyle12(ShowStyleEntry *const showStyle) {
return true;
}
-#endif
-
-void GfxFrameout::kernelFrameout(const bool shouldShowBits) {
- if (_showStyles != nullptr) {
- processShowStyles();
- } else if (_palMorphIsOn) {
- palMorphFrameOut(_styleRanges, nullptr);
- _palMorphIsOn = false;
- } else {
-// TODO: Window scroll
-// if (g_ScrollWindow) {
-// doScroll();
-// }
-
- Common::Rect frameOutRect(0, 0);
- frameOut(shouldShowBits, frameOutRect);
- }
-}
-uint16 GfxFrameout::kernelIsOnMe(int16 x, int16 y, uint16 checkPixels, reg_t screenObject) {
- reg_t planeObject = readSelector(_segMan, screenObject, SELECTOR(plane));
- Plane *screenItemPlane = _visiblePlanes.findByObject(planeObject); // Search for plane in visible planes
- ScreenItem *screenItem = nullptr;
+bool GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const {
+ const reg_t planeObject = readSelector(_segMan, screenItemObject, SELECTOR(plane));
- if (!screenItemPlane) {
- // Specified plane not found
- return 0;
+ Plane *plane = _planes.findByObject(planeObject);
+ if (plane == nullptr) {
+ error("kSetNowSeen: Plane %04x:%04x not found for screen item %04x:%04x", PRINT_REG(planeObject), PRINT_REG(screenItemObject));
}
- screenItem = screenItemPlane->_screenItemList.findByObject(screenObject);
- if (!screenItem) {
- // Specified screen object not in item list
- return 0;
+ ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject);
+ if (screenItem == nullptr) {
+ return false;
}
- // Original SCI32 seems to have made a copy (?) of the screenitem?
- // there is also a "or [ebp+arg_56], 1 - not sure what that did
- return isOnMe(screenItemPlane, screenItem, x, y, checkPixels);
-}
-
-uint16 GfxFrameout::isOnMe(Plane *screenItemPlane, ScreenItem *screenItem, int16 x, int16 y, uint16 checkPixels) {
- // adjust coordinate according to resolution
- int32 adjustedX = x * getCurrentBuffer().screenWidth / getCurrentBuffer().scriptWidth;
- int32 adjustedY = y * getCurrentBuffer().screenHeight / getCurrentBuffer().scriptHeight;
-
- adjustedX += screenItemPlane->_planeRect.left;
- adjustedY += screenItemPlane->_planeRect.top;
-
- //warning("kIsOnMe %s %d (%d, %d -> %d, %d) mouse %d, %d", _segMan->getObjectName(screenObject), checkPixels, screenItem->_screenRect.left, screenItem->_screenRect.top, screenItem->_screenRect.right, screenItem->_screenRect.bottom, adjustedX, adjustedY);
+ Common::Rect result = screenItem->getNowSeenRect(*plane);
- if (!screenItem->_screenRect.contains(adjustedX, adjustedY)) {
- // Specified coordinates are not within screen item
- return 0;
+ if (g_sci->_features->usesAlternateSelectors()) {
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(left), result.left);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(top), result.top);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(right), result.right - 1);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(bottom), result.bottom - 1);
+ } else {
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsLeft), result.left);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsTop), result.top);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsRight), result.right - 1);
+ writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsBottom), result.bottom - 1);
}
+ return true;
+}
- //warning("HIT!");
- if (checkPixels) {
- //warning("Check Pixels");
- CelObj &screenItemCelObject = screenItem->getCelObj();
-
- Common::Point celAdjustedPoint(adjustedX, adjustedY);
- bool celMirrored = screenItem->_mirrorX ^ screenItemCelObject._mirrorX;
-
- celAdjustedPoint.x -= screenItem->_scaledPosition.x;
- celAdjustedPoint.y -= screenItem->_scaledPosition.y;
-
- Ratio celAdjustXRatio(screenItemCelObject._scaledWidth, getCurrentBuffer().screenWidth);
- Ratio celAdjustYRatio(screenItemCelObject._scaledHeight, getCurrentBuffer().screenHeight);
- mulru(celAdjustedPoint, celAdjustXRatio, celAdjustYRatio);
-
- if ((screenItem->_scale.signal) && (screenItem->_scale.x) && (screenItem->_scale.y)) {
- // Apply scaling
- celAdjustedPoint.x = celAdjustedPoint.x * 128 / screenItem->_scale.x;
- celAdjustedPoint.y = celAdjustedPoint.y * 128 / screenItem->_scale.y;
- }
-
- byte coordinateColor = screenItemCelObject.readPixel(celAdjustedPoint.x, celAdjustedPoint.y, celMirrored);
- byte transparentColor = screenItemCelObject._transparentColor;
-
- if (coordinateColor == transparentColor) {
- // Coordinate is transparent
- //warning("TRANSPARENT!");
- return 0;
- }
+void GfxFrameout::remapMarkRedraw() {
+ for (PlaneList::const_iterator it = _planes.begin(); it != _planes.end(); ++it) {
+ Plane *p = *it;
+ p->remapMarkRedraw();
}
- return 1;
}
#pragma mark -
@@ -2052,6 +1409,15 @@ void GfxFrameout::printVisiblePlaneList(Console *con) const {
printPlaneListInternal(con, _visiblePlanes);
}
+void GfxFrameout::printPlaneItemListInternal(Console *con, const ScreenItemList &screenItemList) const {
+ ScreenItemList::size_type i = 0;
+ for (ScreenItemList::const_iterator sit = screenItemList.begin(); sit != screenItemList.end(); sit++) {
+ ScreenItem *screenItem = *sit;
+ con->debugPrintf("%2d: ", i++);
+ screenItem->printDebugInfo(con);
+ }
+}
+
void GfxFrameout::printPlaneItemList(Console *con, const reg_t planeObject) const {
Plane *p = _planes.findByObject(planeObject);
@@ -2060,12 +1426,18 @@ void GfxFrameout::printPlaneItemList(Console *con, const reg_t planeObject) cons
return;
}
- ScreenItemList::size_type i = 0;
- for (ScreenItemList::iterator sit = p->_screenItemList.begin(); sit != p->_screenItemList.end(); sit++) {
- ScreenItem *screenItem = *sit;
- con->debugPrintf("%2d: ", i++);
- screenItem->printDebugInfo(con);
+ printPlaneItemListInternal(con, p->_screenItemList);
+}
+
+void GfxFrameout::printVisiblePlaneItemList(Console *con, const reg_t planeObject) const {
+ Plane *p = _visiblePlanes.findByObject(planeObject);
+
+ if (p == nullptr) {
+ con->debugPrintf("Plane does not exist");
+ return;
}
+
+ printPlaneItemListInternal(con, p->_screenItemList);
}
} // End of namespace Sci