2010-02-02 16:25:35 +00:00
|
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
|
*
|
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
2014-02-18 02:34:24 +01:00
|
|
|
|
*
|
2010-02-02 16:25:35 +00:00
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
2014-02-18 02:34:24 +01:00
|
|
|
|
*
|
2010-02-02 16:25:35 +00:00
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2011-04-24 11:34:27 +03:00
|
|
|
|
#include "common/algorithm.h"
|
|
|
|
|
#include "common/events.h"
|
|
|
|
|
#include "common/keyboard.h"
|
2016-01-02 15:32:38 +02:00
|
|
|
|
#include "common/list.h"
|
2011-04-24 11:34:27 +03:00
|
|
|
|
#include "common/str.h"
|
|
|
|
|
#include "common/system.h"
|
|
|
|
|
#include "common/textconsole.h"
|
|
|
|
|
#include "engines/engine.h"
|
2012-08-16 13:30:32 -04:00
|
|
|
|
#include "graphics/palette.h"
|
2011-04-24 11:34:27 +03:00
|
|
|
|
#include "graphics/surface.h"
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
|
|
|
|
#include "sci/sci.h"
|
2012-05-21 01:29:30 +03:00
|
|
|
|
#include "sci/console.h"
|
2010-06-23 15:23:37 +00:00
|
|
|
|
#include "sci/engine/kernel.h"
|
2010-02-02 16:25:35 +00:00
|
|
|
|
#include "sci/engine/state.h"
|
|
|
|
|
#include "sci/engine/selector.h"
|
|
|
|
|
#include "sci/engine/vm.h"
|
|
|
|
|
#include "sci/graphics/cache.h"
|
2010-02-06 19:35:51 +00:00
|
|
|
|
#include "sci/graphics/coordadjuster.h"
|
2011-10-19 20:27:43 +03:00
|
|
|
|
#include "sci/graphics/compare.h"
|
2010-02-03 01:36:53 +00:00
|
|
|
|
#include "sci/graphics/font.h"
|
2010-02-02 16:25:35 +00:00
|
|
|
|
#include "sci/graphics/view.h"
|
|
|
|
|
#include "sci/graphics/screen.h"
|
2010-02-04 17:57:44 +00:00
|
|
|
|
#include "sci/graphics/paint32.h"
|
2016-01-06 20:00:28 -06:00
|
|
|
|
#include "sci/graphics/palette32.h"
|
2010-02-02 16:25:35 +00:00
|
|
|
|
#include "sci/graphics/picture.h"
|
2011-09-03 14:50:58 +03:00
|
|
|
|
#include "sci/graphics/text32.h"
|
2016-01-18 00:12:47 -06:00
|
|
|
|
#include "sci/graphics/plane32.h"
|
|
|
|
|
#include "sci/graphics/screen_item32.h"
|
2010-02-02 16:25:35 +00:00
|
|
|
|
#include "sci/graphics/frameout.h"
|
2011-02-07 12:24:09 +00:00
|
|
|
|
#include "sci/video/robot_decoder.h"
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
|
|
|
|
namespace Sci {
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// TODO/FIXME: This is partially guesswork
|
2010-10-31 01:45:24 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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 }
|
2012-06-09 12:12:44 +03:00
|
|
|
|
};
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32) :
|
2016-02-18 21:09:15 -06:00
|
|
|
|
_isHiRes(false),
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_cache(cache),
|
|
|
|
|
_palette(palette),
|
2016-02-18 21:09:15 -06:00
|
|
|
|
_resMan(resMan),
|
|
|
|
|
_screen(screen),
|
|
|
|
|
_segMan(segMan),
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_paint32(paint32),
|
|
|
|
|
_showStyles(nullptr),
|
|
|
|
|
// TODO: Stop using _gfxScreen
|
|
|
|
|
_currentBuffer(screen->getWidth(), screen->getHeight(), nullptr),
|
|
|
|
|
_priorityMap(screen->getWidth(), screen->getHeight(), nullptr),
|
2016-02-18 21:09:15 -06:00
|
|
|
|
_remapOccurred(false),
|
|
|
|
|
_frameNowVisible(false),
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_screenRect(screen->getWidth(), screen->getHeight()),
|
2016-02-18 21:09:15 -06:00
|
|
|
|
_overdrawThreshold(0),
|
|
|
|
|
_palMorphIsOn(false) {
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
_currentBuffer.setPixels(calloc(1, screen->getWidth() * screen->getHeight()));
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2016-01-20 20:06:45 -06:00
|
|
|
|
|
|
|
|
|
// TODO: Make hires detection work uniformly across all SCI engine
|
|
|
|
|
// versions (this flag is normally passed by SCI::MakeGraphicsMgr
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// to the GraphicsMgr constructor depending upon video configuration,
|
|
|
|
|
// so should be handled upstream based on game configuration instead
|
|
|
|
|
// of here)
|
2016-01-20 20:06:45 -06:00
|
|
|
|
if (getSciVersion() >= SCI_VERSION_2_1_EARLY && _resMan->detectHires()) {
|
|
|
|
|
_isHiRes = true;
|
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
|
|
|
|
|
_dissolveSequenceSeeds = dissolveSequences[0];
|
|
|
|
|
_defaultDivisions = divisionsDefaults[0];
|
|
|
|
|
_defaultUnknownC = unknownCDefaults[0];
|
|
|
|
|
} 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);
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GfxFrameout::~GfxFrameout() {
|
2016-01-18 00:12:47 -06:00
|
|
|
|
CelObj::deinit();
|
2012-01-15 18:35:33 +02:00
|
|
|
|
clear();
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::run() {
|
|
|
|
|
CelObj::init();
|
|
|
|
|
Plane::init();
|
|
|
|
|
ScreenItem::init();
|
|
|
|
|
|
|
|
|
|
// NOTE: This happens in SCI::InitPlane in the actual engine,
|
|
|
|
|
// and is a background fill plane to ensure hidden planes
|
|
|
|
|
// (planes with a priority of -1) are never drawn
|
2016-02-18 00:07:28 -06:00
|
|
|
|
Plane *initPlane = new Plane(Common::Rect(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight));
|
2016-01-18 00:12:47 -06:00
|
|
|
|
initPlane->_priority = 0;
|
|
|
|
|
_planes.add(initPlane);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-14 22:38:12 -05:00
|
|
|
|
void GfxFrameout::clear() {
|
|
|
|
|
_planes.clear();
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_showList.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
|
#pragma mark Screen items
|
|
|
|
|
|
|
|
|
|
void GfxFrameout::kernelAddScreenItem(const reg_t object) {
|
|
|
|
|
const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
|
|
|
|
|
|
|
|
|
|
// TODO: Remove
|
|
|
|
|
// debug("Adding screen item %04x:%04x to plane %04x:%04x", PRINT_REG(object), PRINT_REG(planeObject));
|
|
|
|
|
|
|
|
|
|
_segMan->getObject(object)->setInfoSelectorFlag(kInfoFlagViewInserted);
|
|
|
|
|
|
|
|
|
|
Plane *plane = _planes.findByObject(planeObject);
|
|
|
|
|
if (plane == nullptr) {
|
|
|
|
|
error("Invalid plane selector passed to kAddScreenItem");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
|
|
|
|
|
if (screenItem != nullptr) {
|
|
|
|
|
screenItem->update(object);
|
2012-06-07 11:26:32 +03:00
|
|
|
|
} else {
|
2016-01-18 00:12:47 -06:00
|
|
|
|
screenItem = new ScreenItem(object);
|
|
|
|
|
plane->_screenItemList.add(screenItem);
|
2012-06-07 11:26:32 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::kernelUpdateScreenItem(const reg_t object) {
|
|
|
|
|
const reg_t magnifierObject = readSelector(_segMan, object, SELECTOR(magnifier));
|
|
|
|
|
if (magnifierObject.isNull()) {
|
|
|
|
|
const reg_t planeObject = readSelector(_segMan, object, SELECTOR(plane));
|
|
|
|
|
Plane *plane = _planes.findByObject(planeObject);
|
|
|
|
|
if (plane == nullptr) {
|
|
|
|
|
error("Invalid plane selector passed to kUpdateScreenItem");
|
|
|
|
|
}
|
2012-06-07 11:26:32 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
ScreenItem *screenItem = plane->_screenItemList.findByObject(object);
|
|
|
|
|
if (screenItem == nullptr) {
|
|
|
|
|
error("Invalid screen item passed to kUpdateScreenItem");
|
|
|
|
|
}
|
2010-09-19 14:50:28 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
screenItem->update(object);
|
|
|
|
|
} else {
|
|
|
|
|
warning("TODO: Magnifier view not implemented yet!");
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-19 14:50:28 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::kernelDeleteScreenItem(const reg_t object) {
|
|
|
|
|
_segMan->getObject(object)->clearInfoSelectorFlag(kInfoFlagViewInserted);
|
2012-09-26 04:17:31 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
|
|
|
|
}
|
2011-10-14 13:51:59 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// TODO: Remove
|
|
|
|
|
// debug("Deleting screen item %04x:%04x from plane %04x:%04x", PRINT_REG(object), PRINT_REG(planeObject));
|
2010-09-19 14:50:28 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
|
|
|
|
}
|
2010-09-19 14:50:28 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (screenItem->_created == 0) {
|
|
|
|
|
screenItem->_created = 0;
|
|
|
|
|
screenItem->_updated = 0;
|
|
|
|
|
screenItem->_deleted = getScreenCount();
|
|
|
|
|
} else {
|
|
|
|
|
plane->_screenItemList.erase(screenItem);
|
|
|
|
|
plane->_screenItemList.pack();
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-19 14:50:28 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
#pragma mark -
|
|
|
|
|
#pragma mark Planes
|
2010-10-23 19:23:07 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::kernelAddPlane(const reg_t object) {
|
|
|
|
|
Plane *plane = _planes.findByObject(object);
|
|
|
|
|
if (plane != nullptr) {
|
|
|
|
|
plane->update(object);
|
|
|
|
|
updatePlane(*plane);
|
|
|
|
|
} else {
|
|
|
|
|
plane = new Plane(object);
|
|
|
|
|
addPlane(*plane);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-23 19:23:07 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::kernelUpdatePlane(const reg_t object) {
|
|
|
|
|
Plane *plane = _planes.findByObject(object);
|
|
|
|
|
if (plane == nullptr) {
|
|
|
|
|
error("Invalid plane selector passed to kUpdatePlane");
|
2010-07-24 16:47:12 +00:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
plane->update(object);
|
|
|
|
|
updatePlane(*plane);
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::kernelDeletePlane(const reg_t object) {
|
|
|
|
|
Plane *plane = _planes.findByObject(object);
|
|
|
|
|
if (plane == nullptr) {
|
|
|
|
|
error("Invalid plane selector passed to kDeletePlane");
|
|
|
|
|
}
|
2012-01-14 14:22:23 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (plane->_created) {
|
|
|
|
|
// NOTE: The original engine calls some `AbortPlane` function that
|
|
|
|
|
// 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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-07-25 19:56:44 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
int16 GfxFrameout::kernelGetHighPlanePri() {
|
|
|
|
|
return _planes.getTopSciPlanePriority();
|
|
|
|
|
}
|
2012-06-22 09:31:51 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::addPlane(Plane &plane) {
|
|
|
|
|
if (_planes.findByObject(plane._object) == nullptr) {
|
|
|
|
|
plane.clipScreenRect(_screenRect);
|
|
|
|
|
_planes.add(&plane);
|
|
|
|
|
} else {
|
|
|
|
|
plane._deleted = 0;
|
|
|
|
|
if (plane._created == 0) {
|
|
|
|
|
plane._moved = g_sci->_gfxFrameout->getScreenCount();
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_planes.sort();
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::updatePlane(Plane &plane) {
|
|
|
|
|
// NOTE: This assertion comes from SCI engine code.
|
|
|
|
|
assert(_planes.findByObject(plane._object) == &plane);
|
2012-06-09 12:12:44 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
Plane *visiblePlane = _visiblePlanes.findByObject(plane._object);
|
|
|
|
|
plane.sync(visiblePlane, _screenRect);
|
|
|
|
|
// NOTE: updateScreenRect was originally called a second time here,
|
|
|
|
|
// but it is already called at the end of the Plane::Update call
|
|
|
|
|
// in the original engine anyway.
|
|
|
|
|
|
|
|
|
|
_planes.sort();
|
2010-07-26 14:41:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
#pragma mark -
|
|
|
|
|
#pragma mark Pics
|
2012-01-15 18:35:33 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 x, const int16 y, const bool mirrorX) {
|
|
|
|
|
Plane *plane = _planes.findByObject(planeObject);
|
|
|
|
|
if (plane == nullptr) {
|
|
|
|
|
error("Invalid plane selector passed to kAddPicAt");
|
2010-07-26 14:41:19 +00:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
plane->addPic(pictureId, Common::Point(x, y), mirrorX);
|
2010-07-26 14:41:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
#pragma mark -
|
|
|
|
|
#pragma mark Rendering
|
|
|
|
|
|
|
|
|
|
void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &rect) {
|
|
|
|
|
// TODO: Robot
|
|
|
|
|
// if (_robot != nullptr) {
|
|
|
|
|
// _robot.doRobot();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// 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());
|
|
|
|
|
|
|
|
|
|
// _numActiveRemaps was a global in SCI engine
|
|
|
|
|
if (/* TODO Remap::_numActiveRemaps > 0 */ false && _remapOccurred) {
|
|
|
|
|
// remapMarkRedraw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
calcLists(screenItemLists, eraseLists, rect);
|
|
|
|
|
|
|
|
|
|
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();
|
2012-06-09 15:36:36 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_remapOccurred = _palette->updateForFrame();
|
|
|
|
|
|
|
|
|
|
// NOTE: SCI engine set this to false on each loop through the
|
|
|
|
|
// planelist iterator below. Since that is a waste, we only set
|
|
|
|
|
// it once.
|
|
|
|
|
_frameNowVisible = false;
|
|
|
|
|
|
|
|
|
|
for (PlaneList::size_type i = 0; i < _planes.size(); ++i) {
|
|
|
|
|
drawEraseList(eraseLists[i], *_planes[i]);
|
|
|
|
|
drawScreenItemList(screenItemLists[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Robot
|
|
|
|
|
// if (_robot != nullptr) {
|
|
|
|
|
// _robot->frameAlmostVisible();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
_palette->updateHardware();
|
|
|
|
|
|
|
|
|
|
if (shouldShowBits) {
|
|
|
|
|
showBits();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_frameNowVisible = true;
|
|
|
|
|
|
|
|
|
|
// TODO: Robot
|
|
|
|
|
// if (_robot != nullptr) {
|
|
|
|
|
// robot->frameNowVisible();
|
|
|
|
|
// }
|
2012-06-09 15:36:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&outRects)[4]) {
|
|
|
|
|
if (!r.intersects(other)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
if (r.top < other.top) {
|
|
|
|
|
Common::Rect &t = outRects[count++];
|
|
|
|
|
t = r;
|
|
|
|
|
t.bottom = other.top;
|
|
|
|
|
r.top = other.top;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r.bottom > other.bottom) {
|
|
|
|
|
Common::Rect &t = outRects[count++];
|
|
|
|
|
t = r;
|
|
|
|
|
t.top = other.bottom;
|
|
|
|
|
r.bottom = other.bottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r.left < other.left) {
|
|
|
|
|
Common::Rect &t = outRects[count++];
|
|
|
|
|
t = r;
|
|
|
|
|
t.right = other.left;
|
|
|
|
|
r.left = other.left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r.right > other.right) {
|
|
|
|
|
Common::Rect &t = outRects[count++];
|
|
|
|
|
t = r;
|
|
|
|
|
t.left = other.right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GfxFrameout::calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &calcRect) {
|
|
|
|
|
RectList rectlist;
|
|
|
|
|
Common::Rect outRects[4];
|
|
|
|
|
|
|
|
|
|
int deletedPlaneCount = 0;
|
|
|
|
|
bool addedToRectList = false;
|
|
|
|
|
int planeCount = _planes.size();
|
|
|
|
|
bool foundTransparentPlane = false;
|
|
|
|
|
|
|
|
|
|
if (!calcRect.isEmpty()) {
|
|
|
|
|
addedToRectList = true;
|
|
|
|
|
rectlist.add(calcRect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int outerPlaneIndex = 0; outerPlaneIndex < planeCount; ++outerPlaneIndex) {
|
|
|
|
|
Plane *outerPlane = _planes[outerPlaneIndex];
|
|
|
|
|
|
|
|
|
|
if (outerPlane->_type == kPlaneTypeTransparent) {
|
|
|
|
|
foundTransparentPlane = true;
|
|
|
|
|
}
|
2012-07-05 13:42:00 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
Plane *visiblePlane = _visiblePlanes.findByObject(outerPlane->_object);
|
|
|
|
|
|
|
|
|
|
if (outerPlane->_deleted) {
|
|
|
|
|
if (visiblePlane != nullptr) {
|
|
|
|
|
if (!visiblePlane->_screenRect.isEmpty()) {
|
|
|
|
|
addedToRectList = true;
|
|
|
|
|
rectlist.add(visiblePlane->_screenRect);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++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 {
|
|
|
|
|
for (int i = 0; i < splitcount; ++i) {
|
|
|
|
|
rectlist.add(outRects[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addedToRectList = 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;
|
|
|
|
|
}
|
2012-06-09 15:36:36 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int splitCount = splitRects(**rect, innerPlane->_screenRect, outRects);
|
|
|
|
|
for (int i = 0; i < splitCount; ++i) {
|
|
|
|
|
rectlist.add(outRects[i]);
|
|
|
|
|
}
|
2012-07-05 13:42:00 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
rectlist.erase(rect);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-06-09 15:36:36 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
rectlist.pack();
|
2012-06-09 15:36:36 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// clean up deleted planes
|
|
|
|
|
if (deletedPlaneCount) {
|
|
|
|
|
for (int planeIndex = planeCount - 1; planeIndex >= 0; --planeIndex) {
|
|
|
|
|
Plane *plane = _planes[planeIndex];
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2013-01-11 00:45:10 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_planes.remove_at(planeIndex);
|
|
|
|
|
eraseLists.remove_at(planeIndex);
|
|
|
|
|
drawLists.remove_at(planeIndex);
|
|
|
|
|
}
|
2013-01-11 00:45:10 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (--deletedPlaneCount <= 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-01-11 00:45:10 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
rectlist.add(outerPlane->_screenRect.findIntersectingRect(visibleOuterPlane->_screenRect));
|
|
|
|
|
|
|
|
|
|
for (int innerIndex = 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);
|
|
|
|
|
|
|
|
|
|
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]);
|
|
|
|
|
} else {
|
|
|
|
|
eraseLists[outerIndex].add(*rectlist[rectIndex]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rectlist.erase_at(rectIndex);
|
|
|
|
|
} else if (splitCount != -1) {
|
|
|
|
|
for (int i = 0; i < splitCount; ++i) {
|
|
|
|
|
rectlist.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]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rectlist.erase_at(rectIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rectlist.pack();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-01-11 00:45:10 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
|
|
|
|
|
Plane *plane = _planes[planeIndex];
|
|
|
|
|
Plane *visiblePlane = nullptr;
|
2013-01-11 00:45:10 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
PlaneList::iterator visiblePlaneIt = Common::find_if(_visiblePlanes.begin(), _visiblePlanes.end(), FindByObject<Plane *>(plane->_object));
|
|
|
|
|
if (visiblePlaneIt != _visiblePlanes.end()) {
|
|
|
|
|
visiblePlane = *visiblePlaneIt;
|
|
|
|
|
}
|
2013-01-11 00:45:10 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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));
|
|
|
|
|
}
|
2013-01-11 00:45:10 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
plane->calcLists(*visiblePlane, _planes, drawLists[planeIndex], eraseLists[planeIndex]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (plane->_created) {
|
|
|
|
|
_visiblePlanes.add(new Plane(*plane));
|
|
|
|
|
--plane->_created;
|
|
|
|
|
} else if (plane->_moved) {
|
|
|
|
|
assert(visiblePlaneIt != _visiblePlanes.end());
|
|
|
|
|
**visiblePlaneIt = *plane;
|
|
|
|
|
--plane->_moved;
|
|
|
|
|
}
|
2012-07-04 02:17:27 +03:00
|
|
|
|
}
|
2010-10-23 19:23:07 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (foundTransparentPlane) {
|
|
|
|
|
for (int planeIndex = 0; planeIndex < planeCount; ++planeIndex) {
|
|
|
|
|
for (int 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) {
|
|
|
|
|
_planes[i]->filterDownEraseRects(drawLists[i], eraseLists[i], eraseLists[planeIndex]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (eraseLists[planeIndex].size() > 0) {
|
|
|
|
|
error("Transparent plane's erase list not absorbed");
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-23 19:23:07 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
for (int i = planeIndex + 1; i < planeCount; ++i) {
|
|
|
|
|
if (_planes[i]->_type == kPlaneTypeTransparent) {
|
|
|
|
|
_planes[i]->filterUpDrawRects(drawLists[i], drawLists[planeIndex]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::drawEraseList(const RectList &eraseList, const Plane &plane) {
|
|
|
|
|
if (plane._type != kPlaneTypeColored) {
|
2010-10-23 19:23:07 +00:00
|
|
|
|
return;
|
2012-07-04 02:17:27 +03:00
|
|
|
|
}
|
2010-10-23 19:23:07 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
for (RectList::const_iterator it = eraseList.begin(); it != eraseList.end(); ++it) {
|
|
|
|
|
mergeToShowList(**it, _showList, _overdrawThreshold);
|
|
|
|
|
_currentBuffer.fillRect(**it, 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-23 19:23:07 +00:00
|
|
|
|
}
|
2011-10-12 02:43:08 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
for (DrawList::const_iterator it = screenItemList.begin(); it != screenItemList.end(); ++it) {
|
|
|
|
|
DrawItem &drawItem = **it;
|
|
|
|
|
mergeToShowList(drawItem.rect, _showList, _overdrawThreshold);
|
|
|
|
|
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);
|
|
|
|
|
CelObj &celObj = *screenItem._celObj;
|
|
|
|
|
celObj.draw(_currentBuffer, screenItem, drawItem.rect, screenItem._mirrorX ^ celObj._mirrorX);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-10-12 02:43:08 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-01-13 17:28:09 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
count = showList.pack();
|
2013-01-11 00:45:10 +02:00
|
|
|
|
}
|
2012-05-14 02:30:15 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
showList.add(merged);
|
2010-09-19 14:50:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle) {
|
|
|
|
|
Palette sourcePalette(*_palette->getNextPalette());
|
|
|
|
|
alterVmap(sourcePalette, sourcePalette, -1, styleRanges);
|
2011-10-12 02:43:08 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// 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();
|
2011-10-12 02:43:08 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
Common::Rect rect(_screen->getDisplayWidth(), _screen->getDisplayHeight());
|
|
|
|
|
_showList.add(rect);
|
|
|
|
|
showBits();
|
2012-01-14 14:22:23 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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();
|
2012-01-15 18:35:33 +02:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
}
|
2012-09-26 04:17:31 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_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 (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;
|
|
|
|
|
}
|
2012-01-15 18:35:33 +02:00
|
|
|
|
}
|
2012-01-14 14:22:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_palette->submit(sourcePalette);
|
|
|
|
|
_palette->updateFFrame();
|
|
|
|
|
_palette->updateHardware();
|
|
|
|
|
alterVmap(nextPalette, sourcePalette, 1, _styleRanges);
|
|
|
|
|
|
|
|
|
|
if (showStyle->type > 0 && showStyle->type < 15) {
|
|
|
|
|
// TODO: SCI2.1mid transition effects
|
|
|
|
|
// processEffects();
|
|
|
|
|
warning("Transition not implemented!");
|
|
|
|
|
} else {
|
|
|
|
|
showBits();
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
2011-10-12 02:43:08 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_frameNowVisible = true;
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
for (PlaneList::iterator plane = _planes.begin(); plane != _planes.end(); ++plane) {
|
|
|
|
|
// TODO:
|
|
|
|
|
// plane->updateRedrawAllCount();
|
|
|
|
|
}
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// TODO: Remap
|
|
|
|
|
// _numActiveRemaps was a global in SCI engine
|
|
|
|
|
// if (Remap::_numActiveRemaps > 0 && _remapOccurred) {
|
|
|
|
|
// _screen->remapMarkRedraw();
|
|
|
|
|
// }
|
2010-07-25 20:41:23 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
calcLists(screenItemLists, eraseLists, calcRect);
|
|
|
|
|
for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) {
|
|
|
|
|
list->sort();
|
2010-07-24 18:06:49 +00:00
|
|
|
|
}
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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]);
|
|
|
|
|
}
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_palette->submit(nextPalette);
|
|
|
|
|
_palette->updateFFrame();
|
|
|
|
|
_palette->updateHardware();
|
|
|
|
|
showBits();
|
2010-06-14 16:58:15 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
_frameNowVisible = true;
|
2010-06-20 17:17:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// 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() {
|
|
|
|
|
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
|
|
|
|
|
// different masking here to ensure that the width of rects
|
|
|
|
|
// was always even.
|
|
|
|
|
rounded.left &= ~1;
|
|
|
|
|
rounded.right = (rounded.right + 1) & ~1;
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
|
// _cursor->GonnaPaint(rounded);
|
2010-06-20 17:17:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// TODO:
|
|
|
|
|
// _cursor->PaintStarting();
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
// different masking here to ensure that the width of rects
|
|
|
|
|
// was always even.
|
|
|
|
|
rounded.left &= ~1;
|
|
|
|
|
rounded.right = (rounded.right + 1) & ~1;
|
|
|
|
|
|
|
|
|
|
byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.screenWidth + rounded.left;
|
|
|
|
|
|
|
|
|
|
g_system->copyRectToScreen(sourceBuffer, _currentBuffer.screenWidth, rounded.left, rounded.top, rounded.width(), rounded.height());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
|
// _cursor->DonePainting();
|
|
|
|
|
|
|
|
|
|
_showList.clear();
|
2010-06-20 17:17:46 +00:00
|
|
|
|
}
|
2010-06-14 16:58:15 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, const int8 style, const int8 *const styleRanges) {
|
|
|
|
|
uint8 clut[256];
|
|
|
|
|
|
|
|
|
|
for (int paletteIndex = 0; paletteIndex < ARRAYSIZE(palette1.colors); ++paletteIndex) {
|
|
|
|
|
int outerR = palette1.colors[paletteIndex].r;
|
|
|
|
|
int outerG = palette1.colors[paletteIndex].g;
|
|
|
|
|
int outerB = palette1.colors[paletteIndex].b;
|
|
|
|
|
|
|
|
|
|
if (styleRanges[paletteIndex] == style) {
|
|
|
|
|
int minDiff = 262140;
|
|
|
|
|
int minDiffIndex;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 236; ++i) {
|
|
|
|
|
if (styleRanges[i] != style) {
|
|
|
|
|
int r = palette1.colors[i].r;
|
|
|
|
|
int g = palette1.colors[i].g;
|
|
|
|
|
int b = palette1.colors[i].b;
|
|
|
|
|
int diffSquared = (outerR - r) * (outerR - r) + (outerG - g) * (outerG - g) + (outerB - b) * (outerB - b);
|
|
|
|
|
if (diffSquared < minDiff) {
|
|
|
|
|
minDiff = diffSquared;
|
|
|
|
|
minDiffIndex = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
clut[paletteIndex] = minDiffIndex;
|
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (style == 1 && styleRanges[paletteIndex] == 0) {
|
|
|
|
|
int minDiff = 262140;
|
|
|
|
|
int minDiffIndex;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
for (int i = 0; i < 236; ++i) {
|
|
|
|
|
int r = palette2.colors[i].r;
|
|
|
|
|
int g = palette2.colors[i].g;
|
|
|
|
|
int b = palette2.colors[i].b;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
int diffSquared = (outerR - r) * (outerR - r) + (outerG - g) * (outerG - g) + (outerB - b) * (outerB - b);
|
|
|
|
|
if (diffSquared < minDiff) {
|
|
|
|
|
minDiff = diffSquared;
|
|
|
|
|
minDiffIndex = i;
|
|
|
|
|
}
|
2011-02-07 12:24:09 +00:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
clut[paletteIndex] = minDiffIndex;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
}
|
2011-02-07 12:24:09 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// 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]];
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (
|
|
|
|
|
(styleRangeValue == 1 && styleRangeValue == style) ||
|
|
|
|
|
(styleRangeValue == 0 && style == 1)
|
|
|
|
|
) {
|
|
|
|
|
pixels[pixelIndex] = clut[currentValue];
|
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
entry = entry->next;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
return entry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline ShowStyleEntry *GfxFrameout::deleteShowStyleInternal(ShowStyleEntry *const showStyle) {
|
|
|
|
|
ShowStyleEntry *lastEntry = nullptr;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
for (ShowStyleEntry *testEntry = _showStyles; testEntry != nullptr; testEntry = testEntry->next) {
|
|
|
|
|
if (testEntry == showStyle) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
lastEntry = testEntry;
|
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (lastEntry == nullptr) {
|
|
|
|
|
_showStyles = showStyle->next;
|
|
|
|
|
lastEntry = _showStyles;
|
|
|
|
|
} else {
|
|
|
|
|
lastEntry->next = showStyle->next;
|
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// 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;
|
2011-02-07 12:24:09 +00:00
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
} else {
|
|
|
|
|
#endif
|
|
|
|
|
delete[] showStyle->fadeColorRanges;
|
|
|
|
|
#if 0
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
delete showStyle;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// TODO: Verify that this is the correct entry to return
|
|
|
|
|
// for the loop in processShowStyles to work correctly
|
|
|
|
|
return lastEntry;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// 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;
|
|
|
|
|
}
|
2011-02-07 12:24:09 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
bool isFadeUp;
|
|
|
|
|
int16 color;
|
|
|
|
|
if (back != -1) {
|
|
|
|
|
isFadeUp = false;
|
|
|
|
|
color = back;
|
|
|
|
|
} else {
|
|
|
|
|
isFadeUp = true;
|
|
|
|
|
color = 0;
|
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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];
|
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (useExisting) {
|
|
|
|
|
createNewEntry = false;
|
|
|
|
|
isFadeUp = true;
|
|
|
|
|
entry->currentStep = 0;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
} else {
|
2016-01-18 00:12:47 -06:00
|
|
|
|
isFadeUp = true;
|
|
|
|
|
color = entry->color;
|
|
|
|
|
deleteShowStyleInternal(entry/*, true*/);
|
|
|
|
|
entry = nullptr;
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
2011-02-07 12:24:09 +00:00
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
}
|
2011-11-17 22:08:36 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
#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);
|
2011-11-17 22:08:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
|
|
|
|
} 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);
|
|
|
|
|
}
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
}
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
int temp = rect.left;
|
|
|
|
|
rect.left = showStyle->width - rect.right - 1;
|
|
|
|
|
rect.right = showStyle->width - temp - 1;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
addFrameoutEntryInternal(showStyle, priority, celInfo, rect);
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (!retval) {
|
|
|
|
|
continueProcessing = true;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (retval && showStyle->processed) {
|
|
|
|
|
showStyle = deleteShowStyleInternal(showStyle);
|
|
|
|
|
} else {
|
|
|
|
|
showStyle = showStyle->next;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
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);
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
showStyle->processed = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
bool GfxFrameout::processShowStyleMorph(ShowStyleEntry *const showStyle) {
|
|
|
|
|
palMorphFrameOut(_styleRanges, showStyle);
|
|
|
|
|
showStyle->processed = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
// 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;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
percent *= 100;
|
|
|
|
|
percent /= showStyle->divisions - 1;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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);
|
|
|
|
|
}
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
++showStyle->currentStep;
|
|
|
|
|
showStyle->nextTick += showStyle->delay;
|
|
|
|
|
unchanged = false;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (showStyle->currentStep >= showStyle->divisions && unchanged) {
|
|
|
|
|
if (direction > 0) {
|
|
|
|
|
showStyle->processed = true;
|
|
|
|
|
}
|
2016-01-06 20:03:27 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
return true;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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();
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
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();
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
shutterMiddleX -= divisions;
|
|
|
|
|
--shutterDivisionWidth;
|
2016-01-06 20:03:27 -06:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
2011-02-07 12:24:09 +00:00
|
|
|
|
}
|
2011-01-22 13:01:10 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
|
|
|
|
}
|
2016-01-14 10:50:41 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
index *= showStyle->edgeCount;
|
2016-01-14 10:50:41 -06:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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);
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
delete screenItem;
|
|
|
|
|
showStyle->screenItems[index + i] = nullptr;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ScreenItem *screenItem = showStyle->screenItems[index + i];
|
|
|
|
|
// TODO: _screen->addScreenItem(screenItem);
|
|
|
|
|
_screenItems.push_back(screenItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-06-09 15:36:36 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
++showStyle->currentStep;
|
|
|
|
|
showStyle->nextTick += showStyle->delay;
|
2012-06-09 15:36:36 +03:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
}
|
2012-06-09 15:36:36 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (showStyle->currentStep >= showStyle->divisions) {
|
|
|
|
|
if (showStyle->fadeUp) {
|
|
|
|
|
showStyle->processed = true;
|
2010-07-24 15:25:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-02-04 17:57:44 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void fillRect(byte *data, const Common::Rect &rect, const int16 color, const int16 stride) {
|
2010-02-04 17:57:44 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
}
|
2010-06-20 17:17:46 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
bool GfxFrameout::processShowStyle11(ShowStyleEntry *const showStyle) {
|
|
|
|
|
int divisions = showStyle->divisions * showStyle->divisions;
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
byte *bitmapData = _segMan->getHunkPointer(showStyle->bitmapMemId) + sizeof(GfxBitmapHeader);
|
2010-06-20 17:17:46 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
int ebx;
|
2012-09-26 04:17:31 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (showStyle->currentStep == 0) {
|
|
|
|
|
int ctr = 0;
|
|
|
|
|
int bloot = divisions;
|
|
|
|
|
do {
|
|
|
|
|
bloot >>= 1;
|
|
|
|
|
++ctr;
|
|
|
|
|
} while (bloot != 1);
|
2010-07-22 10:24:08 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
2011-10-29 01:39:37 +03:00
|
|
|
|
} else {
|
2016-01-18 00:12:47 -06:00
|
|
|
|
ebx = eax;
|
|
|
|
|
}
|
|
|
|
|
} while (ebx >= divisions);
|
2011-02-02 22:29:14 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (ebx == showStyle->dissolveInitial) {
|
|
|
|
|
ebx = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-10-18 03:10:19 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
Common::Rect rect;
|
2013-07-30 04:21:51 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
rect.left = (showStyle->width + showStyle->divisions - 1) / showStyle->divisions;
|
|
|
|
|
rect.top = (showStyle->height + showStyle->divisions - 1) / showStyle->divisions;
|
2010-07-22 19:20:26 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (showStyle->currentStep <= showStyle->divisions) {
|
|
|
|
|
int ebp = 0;
|
|
|
|
|
do {
|
|
|
|
|
int ecx = ebx % showStyle->divisions;
|
2010-02-02 16:25:35 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
2011-10-29 01:39:37 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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;
|
2010-06-30 14:26:47 +00:00
|
|
|
|
}
|
2010-02-04 16:12:47 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (drawRect.top < 0) {
|
|
|
|
|
drawRect.top = 0;
|
2010-07-22 19:20:26 +00:00
|
|
|
|
}
|
2011-10-28 22:04:27 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (drawRect.right > rect.right) {
|
|
|
|
|
drawRect.right = rect.right;
|
2010-02-03 01:36:53 +00:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
if (drawRect.bottom > rect.bottom) {
|
|
|
|
|
drawRect.bottom = rect.bottom;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
drawRect.right = 0;
|
|
|
|
|
drawRect.bottom = 0;
|
|
|
|
|
drawRect.left = 0;
|
|
|
|
|
drawRect.top = 0;
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
2010-06-20 17:17:46 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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 (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);
|
2010-07-26 14:41:19 +00:00
|
|
|
|
}
|
2016-01-18 00:12:47 -06:00
|
|
|
|
|
|
|
|
|
} while (ebp <= showStyle->divisions);
|
|
|
|
|
|
|
|
|
|
showStyle->unknown3A = ebx;
|
|
|
|
|
++showStyle->currentStep;
|
|
|
|
|
showStyle->nextTick += showStyle->delay;
|
|
|
|
|
// _screen->updateScreenItem(showStyle->bitmapScreenItem);
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
2010-06-20 17:17:46 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (showStyle->currentStep >= showStyle->divisions) {
|
|
|
|
|
if (showStyle->fadeUp) {
|
|
|
|
|
showStyle->processed = true;
|
|
|
|
|
}
|
2012-06-07 11:26:32 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2010-07-24 16:52:08 +00:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
return false;
|
2010-02-02 16:25:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
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();
|
|
|
|
|
// }
|
2012-05-21 01:29:30 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
Common::Rect frameOutRect(0, 0);
|
|
|
|
|
frameOut(shouldShowBits, frameOutRect);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-21 01:29:30 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
#pragma mark -
|
|
|
|
|
#pragma mark Debugging
|
2012-05-21 01:29:30 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::printPlaneListInternal(Console *con, const PlaneList &planeList) const {
|
|
|
|
|
for (PlaneList::const_iterator it = planeList.begin(); it != planeList.end(); ++it) {
|
|
|
|
|
Plane *p = *it;
|
|
|
|
|
p->printDebugInfo(con);
|
2012-05-21 01:29:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::printPlaneList(Console *con) const {
|
|
|
|
|
printPlaneListInternal(con, _planes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GfxFrameout::printVisiblePlaneList(Console *con) const {
|
|
|
|
|
printPlaneListInternal(con, _visiblePlanes);
|
|
|
|
|
}
|
2012-09-26 04:17:31 +02:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
void GfxFrameout::printPlaneItemList(Console *con, const reg_t planeObject) const {
|
|
|
|
|
Plane *p = _planes.findByObject(planeObject);
|
2012-05-21 01:29:30 +03:00
|
|
|
|
|
2016-01-18 00:12:47 -06:00
|
|
|
|
if (p == nullptr) {
|
|
|
|
|
con->debugPrintf("Plane does not exist");
|
|
|
|
|
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);
|
2012-05-21 01:29:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-28 22:18:10 +03:00
|
|
|
|
} // End of namespace Sci
|