コード例 #1
0
ファイル: compare.cpp プロジェクト: AReim1982/scummvm
void GfxCompare::kernelBaseSetter(reg_t object) {
	if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) {
		int16 x = readSelectorValue(_segMan, object, SELECTOR(x));
		int16 y = readSelectorValue(_segMan, object, SELECTOR(y));
		int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0;
		int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep));
		GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view));
		int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop));
		int16 celNo = readSelectorValue(_segMan, object, SELECTOR(cel));
		uint16 scaleSignal = 0;
		if (getSciVersion() >= SCI_VERSION_1_1)
			scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal));

		Common::Rect celRect;

		GfxView *tmpView = _cache->getView(viewId);
		if (!tmpView->isScaleable())
			scaleSignal = 0;

		if (scaleSignal & kScaleSignalDoScaling) {
			celRect = getNSRect(object);
		} else {
			tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);
		}

		celRect.bottom = y + 1;
		celRect.top = celRect.bottom - yStep;

		writeSelectorValue(_segMan, object, SELECTOR(brLeft), celRect.left);
		writeSelectorValue(_segMan, object, SELECTOR(brRight), celRect.right);
		writeSelectorValue(_segMan, object, SELECTOR(brTop), celRect.top);
		writeSelectorValue(_segMan, object, SELECTOR(brBottom), celRect.bottom);
	}
}
コード例 #2
0
ファイル: compare.cpp プロジェクト: 86400/scummvm
bool GfxCompare::kernelIsItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position) {
	GfxView *tmpView = _cache->getView(viewId);
	const CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo);
	position.x = CLIP<int>(position.x, 0, celInfo->width - 1);
	position.y = CLIP<int>(position.y, 0, celInfo->height - 1);
	const byte *celData = tmpView->getBitmap(loopNo, celNo);
	bool result = (celData[position.y * celInfo->width + position.x] == celInfo->clearKey);
	return result;
}
コード例 #3
0
ファイル: paint32.cpp プロジェクト: Templier/scummvm-test
// This is "hacked" together, because its only used by debug command
void GfxPaint32::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) {
	GfxView *view = _cache->getView(viewId);
	Common::Rect celRect(50, 50, 50, 50);
	Common::Rect translatedRect;
	celRect.bottom += view->getHeight(loopNo, celNo);
	celRect.right += view->getWidth(loopNo, celNo);
	view->draw(celRect, celRect, celRect, loopNo, celNo, 255, 0, false);
	_screen->copyRectToScreen(celRect);
}
コード例 #4
0
ファイル: paint16.cpp プロジェクト: Templier/scummvm-test
// This is used as replacement for drawCelAndShow() when hires-cels are drawn to
// screen. Hires-cels are available only SCI 1.1+.
void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX, uint16 scaleY) {
	GfxView *view = _cache->getView(viewId);
	Common::Rect celRect, curPortRect, clipRect, clipRectTranslated;
	Common::Point curPortPos;
	bool upscaledHiresHack = false;

	if (view) {
		if ((leftPos == 0) && (topPos == 0)) {
			// HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we
			// need to get coordinates from upscaledHiresHandle. I'm not sure if
			// this is what we are supposed to do or if there is some other bug
			// that actually makes coordinates to be 0 in the first place.
			byte *memoryPtr = NULL;
			memoryPtr = _segMan->getHunkPointer(upscaledHiresHandle);
			if (memoryPtr) {
				Common::Rect upscaledHiresRect;
				_screen->bitsGetRect(memoryPtr, &upscaledHiresRect);
				leftPos = upscaledHiresRect.left;
				topPos = upscaledHiresRect.top;
				upscaledHiresHack = true;
			}
		}

		celRect.left = leftPos;
		celRect.top = topPos;
		celRect.right = celRect.left + view->getWidth(loopNo, celNo);
		celRect.bottom = celRect.top + view->getHeight(loopNo, celNo);
		// adjust curPort to upscaled hires
		clipRect = celRect;
		curPortRect = _ports->_curPort->rect;
		_screen->adjustToUpscaledCoordinates(curPortRect.top, curPortRect.left);
		_screen->adjustToUpscaledCoordinates(curPortRect.bottom, curPortRect.right);
		curPortRect.bottom++;
		curPortRect.right++;
		clipRect.clip(curPortRect);
		if (clipRect.isEmpty()) // nothing to draw
			return;

		clipRectTranslated = clipRect;
		if (!upscaledHiresHack) {
			curPortPos.x = _ports->_curPort->left; curPortPos.y = _ports->_curPort->top;
			_screen->adjustToUpscaledCoordinates(curPortPos.y, curPortPos.x);
			clipRectTranslated.top += curPortPos.y; clipRectTranslated.bottom += curPortPos.y;
			clipRectTranslated.left += curPortPos.x; clipRectTranslated.right += curPortPos.x;
		}

		view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, true);
		if (!_screen->_picNotValidSci11) {
			_screen->copyDisplayRectToScreen(clipRectTranslated);
		}
	}
}
コード例 #5
0
void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) {
	// Sometimes invalid viewIds are asked for, ignore those (e.g. qfg1vga)
	//if (!_resMan->testResource(ResourceId(kResourceTypeView, resourceId)))
	//	return;
	// maybe we took the wrong parameter before, if this causes invalid view again, enable to commented out code again

	GfxView *view = g_sci->_gfxCache->getView(resourceId);
	Palette *viewPalette = view->getPalette();
	if (viewPalette) {
		// merge/insert this palette
		set(viewPalette, true);
	}
}
コード例 #6
0
ファイル: animate.cpp プロジェクト: MathiasBartl/scummvm
void GfxAnimate::addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 x, int16 y, int16 priority, int16 control) {
	GfxView *view = _cache->getView(viewId);
	Common::Rect celRect;

	if (priority == -1)
		priority = _ports->kernelCoordinateToPriority(y);

	// Create rect according to coordinates and given cel
	view->getCelRect(loopNo, celNo, x, y, 0, celRect);
	_paint16->drawCel(view, loopNo, celNo, celRect, priority, 0);

	if (control != -1) {
		celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(priority) - 1, celRect.top, celRect.bottom - 1);
		_paint16->fillRect(celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, control);
	}
}
コード例 #7
0
ファイル: animate.cpp プロジェクト: MathiasBartl/scummvm
void GfxAnimate::throttleSpeed() {
	switch (_lastCastData.size()) {
	case 0:
		// No entries drawn -> no speed throttler triggering
		break;
	case 1: {

		// One entry drawn -> check if that entry was a speed benchmark view, if not enable speed throttler
		AnimateEntry *onlyCast = &_lastCastData[0];
		if ((onlyCast->viewId == 0) && (onlyCast->loopNo == 13) && (onlyCast->celNo == 0)) {
			// this one is used by jones talkie
			if ((onlyCast->celRect.height() == 8) && (onlyCast->celRect.width() == 8)) {
				_s->_gameIsBenchmarking = true;
				return;
			}
		}
		// first loop and first cel used?
		if ((onlyCast->loopNo == 0) && (onlyCast->celNo == 0)) {
			// and that cel has a known speed benchmark resolution
			int16 onlyHeight = onlyCast->celRect.height();
			int16 onlyWidth = onlyCast->celRect.width();
			if (((onlyWidth == 12) && (onlyHeight == 35)) || // regular benchmark view ("fred", "Speedy", "ego")
				((onlyWidth == 29) && (onlyHeight == 45)) || // King's Quest 5 french "fred"
				((onlyWidth == 1) && (onlyHeight == 5)) || // Freddy Pharkas "fred"
				((onlyWidth == 1) && (onlyHeight == 1))) { // Laura Bow 2 Talkie
				// check further that there is only one cel in that view
				GfxView *onlyView = _cache->getView(onlyCast->viewId);
				if ((onlyView->getLoopCount() == 1) && (onlyView->getCelCount(0))) {
					_s->_gameIsBenchmarking = true;
					return;
				}
			}
		}
		_s->_gameIsBenchmarking = false;
		_s->_throttleTrigger = true;
		break;
	}
	default:
		// More than 1 entry drawn -> time for speed throttling
		_s->_gameIsBenchmarking = false;
		_s->_throttleTrigger = true;
		break;
	}
}
コード例 #8
0
ファイル: compare.cpp プロジェクト: 86400/scummvm
void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
	GfxView *view = NULL;
	Common::Rect celRect(0, 0);
	GuiResourceId viewId = (GuiResourceId)readSelectorValue(_segMan, objectReference, SELECTOR(view));
	int16 loopNo = readSelectorValue(_segMan, objectReference, SELECTOR(loop));
	int16 celNo = readSelectorValue(_segMan, objectReference, SELECTOR(cel));
	int16 x = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(x));
	int16 y = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(y));
	int16 z = 0;
	if (SELECTOR(z) > -1)
		z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z));

	view = _cache->getView(viewId);
	view->getCelRect(loopNo, celNo, x, y, z, celRect);

	if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) {
		setNSRect(objectReference, celRect);
	}
}
コード例 #9
0
ファイル: animate.cpp プロジェクト: MathiasBartl/scummvm
void GfxAnimate::addToPicDrawCels() {
	reg_t curObject;
	GfxView *view = NULL;
	AnimateList::iterator it;
	const AnimateList::iterator end = _list.end();

	for (it = _list.begin(); it != end; ++it) {
		curObject = it->object;

		// Get the corresponding view
		view = _cache->getView(it->viewId);

		// kAddToPic does not do loop/cel-number fixups

		if (it->priority == -1)
			it->priority = _ports->kernelCoordinateToPriority(it->y);

		if (!view->isScaleable()) {
			// Laura Bow 2 specific - ffs. fill()
			it->scaleSignal = 0;
			it->scaleY = it->scaleX = 128;
		}

		// Create rect according to coordinates and given cel
		if (it->scaleSignal & kScaleSignalDoScaling) {
			if (it->scaleSignal & kScaleSignalGlobalScaling) {
				applyGlobalScaling(it, view);
			}
			view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect);
			g_sci->_gfxCompare->setNSRect(curObject, it->celRect);
		} else {
			view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect);
		}

		// draw corresponding cel
		_paint16->drawCel(view, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY);
		if (!(it->signal & kSignalIgnoreActor)) {
			it->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1);
			_paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15);
		}
	}
}
コード例 #10
0
ファイル: paint16.cpp プロジェクト: Templier/scummvm-test
// This one is the only one that updates screen!
void GfxPaint16::drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
	GfxView *view = _cache->getView(viewId);
	Common::Rect celRect;

	if (view) {
		celRect.left = leftPos;
		celRect.top = topPos;
		celRect.right = celRect.left + view->getWidth(loopNo, celNo);
		celRect.bottom = celRect.top + view->getHeight(loopNo, celNo);

		drawCel(view, loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY);

		if (getSciVersion() >= SCI_VERSION_1_1) {
			if (!_screen->_picNotValidSci11) {
				bitsShow(celRect);
			}
		} else {
			if (!_screen->_picNotValid)
				bitsShow(celRect);
		}
	}
}
コード例 #11
0
ファイル: compare.cpp プロジェクト: Fyre91/scummvm
void GfxCompare::kernelBaseSetter(reg_t object) {
	if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) {
		int16 x = readSelectorValue(_segMan, object, SELECTOR(x));
		int16 y = readSelectorValue(_segMan, object, SELECTOR(y));
		int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0;
		int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep));
		GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view));
		int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop));
		int16 celNo = readSelectorValue(_segMan, object, SELECTOR(cel));

		// HACK: Ignore invalid views for now (perhaps unimplemented text views?)
		if (viewId == 0xFFFF)	// invalid view
			return;

		uint16 scaleSignal = 0;
		if (getSciVersion() >= SCI_VERSION_1_1) {
			scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal));
		}

		Common::Rect celRect;

		GfxView *tmpView = _cache->getView(viewId);
		if (!tmpView->isScaleable())
			scaleSignal = 0;

		if (scaleSignal & kScaleSignalDoScaling) {
			celRect = getNSRect(object);
		} else {
			if (tmpView->isSci2Hires())
				tmpView->adjustToUpscaledCoordinates(y, x);

			tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);

			if (tmpView->isSci2Hires()) {
				tmpView->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
				tmpView->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
			}
		}

		celRect.bottom = y + 1;
		celRect.top = celRect.bottom - yStep;

		writeSelectorValue(_segMan, object, SELECTOR(brLeft), celRect.left);
		writeSelectorValue(_segMan, object, SELECTOR(brRight), celRect.right);
		writeSelectorValue(_segMan, object, SELECTOR(brTop), celRect.top);
		writeSelectorValue(_segMan, object, SELECTOR(brBottom), celRect.bottom);
	}
}
コード例 #12
0
ファイル: compare.cpp プロジェクト: Fyre91/scummvm
void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
	GfxView *view = NULL;
	Common::Rect celRect(0, 0);
	GuiResourceId viewId = (GuiResourceId)readSelectorValue(_segMan, objectReference, SELECTOR(view));

	// HACK: Ignore invalid views for now (perhaps unimplemented text views?)
	if (viewId == 0xFFFF)	// invalid view
		return;

	int16 loopNo = readSelectorValue(_segMan, objectReference, SELECTOR(loop));
	int16 celNo = readSelectorValue(_segMan, objectReference, SELECTOR(cel));
	int16 x = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(x));
	int16 y = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(y));
	int16 z = 0;
	if (SELECTOR(z) > -1)
		z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z));

	view = _cache->getView(viewId);

#ifdef ENABLE_SCI32
	if (view->isSci2Hires())
		view->adjustToUpscaledCoordinates(y, x);
	else if (getSciVersion() == SCI_VERSION_2_1)
		_coordAdjuster->fromScriptToDisplay(y, x);
#endif

	view->getCelRect(loopNo, celNo, x, y, z, celRect);

#ifdef ENABLE_SCI32
	if (view->isSci2Hires()) {
		view->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
		view->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
	} else if (getSciVersion() == SCI_VERSION_2_1) {
		_coordAdjuster->fromDisplayToScript(celRect.top, celRect.left);
		_coordAdjuster->fromDisplayToScript(celRect.bottom, celRect.right);
	}
#endif

	if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) {
		setNSRect(objectReference, celRect);
	}
}
コード例 #13
0
ファイル: frameout.cpp プロジェクト: alcherk/scummvm
void GfxFrameout::kernelFrameout() {
	if (g_sci->_robotDecoder->isVideoLoaded()) {
		showVideo();
		return;
	}

	_palette->palVaryUpdate();

	for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
		reg_t planeObject = it->object;

		// Draw any plane lines, if they exist
		// These are drawn on invisible planes as well. (e.g. "invisiblePlane" in LSL6 hires)
		// FIXME: Lines aren't always drawn (e.g. when the narrator speaks in LSL6 hires).
		// Perhaps something is painted over them?
		for (PlaneLineList::iterator it2 = it->lines.begin(); it2 != it->lines.end(); ++it2) {
			Common::Point startPoint = it2->startPoint;
			Common::Point endPoint = it2->endPoint;
			_coordAdjuster->kernelLocalToGlobal(startPoint.x, startPoint.y, it->object);
			_coordAdjuster->kernelLocalToGlobal(endPoint.x, endPoint.y, it->object);
			_screen->drawLine(startPoint, endPoint, it2->color, it2->priority, it2->control);
		}

		int16 planeLastPriority = it->lastPriority;

		// Update priority here, sq6 sets it w/o UpdatePlane
		int16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));

		it->lastPriority = planePriority;
		if (planePriority < 0) { // Plane currently not meant to be shown
			// If plane was shown before, delete plane rect
			if (planePriority != planeLastPriority)
				_paint32->fillRect(it->planeRect, 0);
			continue;
		}

		// There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX.
		// Since I first wrote the patch, the race has stopped occurring for me though.
		// I'll leave this for investigation later, when someone can reproduce.
		//if (it->pictureId == kPlanePlainColored)	// FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes)
		if (it->pictureId == kPlanePlainColored && (it->planeBack || g_sci->getGameId() != GID_GK1))
			_paint32->fillRect(it->planeRect, it->planeBack);

		_coordAdjuster->pictureSetDisplayArea(it->planeRect);
		// Invoking drewPicture() with an invalid picture ID in SCI32 results in
		// invalidating the palVary palette when a palVary effect is active. This
		// is quite obvious in QFG4, where the day time palette is incorrectly
		// shown when exiting the caves, and the correct night time palette
		// flashes briefly each time that kPalVaryInit is called.
		if (it->pictureId != 0xFFFF)
			_palette->drewPicture(it->pictureId);

		FrameoutList itemList;

		createPlaneItemList(planeObject, itemList);

		for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) {
			FrameoutEntry *itemEntry = *listIterator;

			if (!itemEntry->visible)
				continue;

			if (itemEntry->object.isNull()) {
				// Picture cel data
				_coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
				_coordAdjuster->fromScriptToDisplay(itemEntry->picStartY, itemEntry->picStartX);

				if (!isPictureOutOfView(itemEntry, it->planeRect, it->planeOffsetX, it->planeOffsetY))
					drawPicture(itemEntry, it->planeOffsetX, it->planeOffsetY, it->planePictureMirrored);
			} else {
				GfxView *view = (itemEntry->viewId != 0xFFFF) ? _cache->getView(itemEntry->viewId) : NULL;
				int16 dummyX = 0;

				if (view && view->isSci2Hires()) {
					view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
					view->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
				} else if (getSciVersion() >= SCI_VERSION_2_1) {
					_coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
					_coordAdjuster->fromScriptToDisplay(itemEntry->z, dummyX);
				}

				// Adjust according to current scroll position
				itemEntry->x -= it->planeOffsetX;
				itemEntry->y -= it->planeOffsetY;

				uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect));
				if (useInsetRect) {
					itemEntry->celRect.top = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inTop));
					itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft));
					itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom));
					itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight));
					if (view && view->isSci2Hires()) {
						view->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
						view->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
					}
					itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
					// TODO: maybe we should clip the cels rect with this, i'm not sure
					//  the only currently known usage is game menu of gk1
				} else if (view) {
					// Process global scaling, if needed.
					// TODO: Seems like SCI32 always processes global scaling for scaled objects
					// TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY)
					if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) && 
					   !(itemEntry->scaleSignal & kScaleSignalDisableGlobalScaling32) &&
					    (itemEntry->scaleX == itemEntry->scaleY) &&
						itemEntry->scaleX != 128)
						applyGlobalScaling(itemEntry, it->planeRect, view->getHeight(itemEntry->loopNo, itemEntry->celNo));

					if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
						view->getCelRect(itemEntry->loopNo, itemEntry->celNo,
							itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect);
					else
						view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo,
							itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX,
							itemEntry->scaleY, itemEntry->celRect);

					Common::Rect nsRect = itemEntry->celRect;
					// Translate back to actual coordinate within scrollable plane
					nsRect.translate(it->planeOffsetX, it->planeOffsetY);

					if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {
						// HACK: Some (?) objects in Phantasmagoria 2 have no NS rect. Skip them for now.
						// TODO: Remove once we figure out how Phantasmagoria 2 draws objects on screen.
						if (lookupSelector(_segMan, itemEntry->object, SELECTOR(nsLeft), NULL, NULL) != kSelectorVariable)
							continue;
					}

					if (view && view->isSci2Hires()) {
						view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
						view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
						g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
					} else if (getSciVersion() >= SCI_VERSION_2_1 && _resMan->detectHires()) {
						_coordAdjuster->fromDisplayToScript(nsRect.top, nsRect.left);
						_coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right);
						g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
					}
				}

				// Don't attempt to draw sprites that are outside the visible
				// screen area. An example is the random people walking in
				// Jackson Square in GK1.
				if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top  >= _screen->getDisplayHeight() ||
				    itemEntry->celRect.right  < 0 || itemEntry->celRect.left >= _screen->getDisplayWidth())
					continue;

				Common::Rect clipRect, translatedClipRect;
				clipRect = itemEntry->celRect;

				if (view && view->isSci2Hires()) {
					clipRect.clip(it->upscaledPlaneClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top);
				} else {
					// QFG4 passes invalid rectangles when a battle is starting
					if (!clipRect.isValidRect())
						continue;
					clipRect.clip(it->planeClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->planeRect.left, it->planeRect.top);
				}

				if (view) {
					if (!clipRect.isEmpty()) {
						if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
							view->draw(itemEntry->celRect, clipRect, translatedClipRect,
								itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
						else
							view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect,
								itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
					}
				}

				// Draw text, if it exists
				if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) {
					g_sci->_gfxText32->drawTextBitmap(itemEntry->x, itemEntry->y, it->planeRect, itemEntry->object);
				}
			}
		}

		for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
			if (pictureIt->object == planeObject) {
				delete[] pictureIt->pictureCels;
				pictureIt->pictureCels = 0;
			}
		}
	}

	showCurrentScrollText();

	_screen->copyToScreen();

	g_sci->getEngineState()->_throttleTrigger = true;
}
コード例 #14
0
ファイル: frameout.cpp プロジェクト: shailendji/nefertiti
void GfxFrameout::kernelFrameout() {
	if (g_sci->_robotDecoder->isVideoLoaded()) {
		bool skipVideo = false;
		RobotDecoder *videoDecoder = g_sci->_robotDecoder;
		uint16 x = videoDecoder->getPos().x;
		uint16 y = videoDecoder->getPos().y;

		if (videoDecoder->hasDirtyPalette())
			videoDecoder->setSystemPalette();

		while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
			if (videoDecoder->needsUpdate()) {
				const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
				if (frame) {
					g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);

					if (videoDecoder->hasDirtyPalette())
						videoDecoder->setSystemPalette();

					g_system->updateScreen();
				}
			}

			Common::Event event;
			while (g_system->getEventManager()->pollEvent(event)) {
				if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
					skipVideo = true;
			}

			g_system->delayMillis(10);
		}
		return;
	}

	_palette->palVaryUpdate();

	for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
		reg_t planeObject = it->object;
		uint16 planeLastPriority = it->lastPriority;

		// Update priority here, sq6 sets it w/o UpdatePlane
		uint16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));

		it->lastPriority = planePriority;
		if (planePriority == 0xffff) { // Plane currently not meant to be shown
			// If plane was shown before, delete plane rect
			if (planePriority != planeLastPriority)
				_paint32->fillRect(it->planeRect, 0);
			continue;
		}

		if (it->planeBack)
			_paint32->fillRect(it->planeRect, it->planeBack);

		GuiResourceId planeMainPictureId = it->pictureId;

		_coordAdjuster->pictureSetDisplayArea(it->planeRect);
		_palette->drewPicture(planeMainPictureId);

		FrameoutList itemList;

		// Copy screen items of the current frame to the list of items to be drawn
		for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) {
			reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane));
			if (planeObject == itemPlane) {
				kernelUpdateScreenItem((*listIterator)->object);	// TODO: Why is this necessary?
				itemList.push_back(*listIterator);
			}
		}

		for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
			if (pictureIt->object == planeObject) {
				GfxPicture *planePicture = pictureIt->picture;
				// Allocate memory for picture cels
				pictureIt->pictureCels = new FrameoutEntry[planePicture->getSci32celCount()];

				// Add following cels to the itemlist
				FrameoutEntry *picEntry = pictureIt->pictureCels;
				int planePictureCels = planePicture->getSci32celCount();
				for (int pictureCelNr = 0; pictureCelNr < planePictureCels; pictureCelNr++) {
					picEntry->celNo = pictureCelNr;
					picEntry->object = NULL_REG;
					picEntry->picture = planePicture;
					picEntry->y = planePicture->getSci32celY(pictureCelNr);
					picEntry->x = planePicture->getSci32celX(pictureCelNr);
					picEntry->picStartX = pictureIt->startX;

					picEntry->priority = planePicture->getSci32celPriority(pictureCelNr);

					itemList.push_back(picEntry);
					picEntry++;
				}
			}
		}

		// Now sort our itemlist
		Common::sort(itemList.begin(), itemList.end(), sortHelper);

//		warning("Plane %s", _segMan->getObjectName(planeObject));

		for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) {
			FrameoutEntry *itemEntry = *listIterator;

			if (itemEntry->object.isNull()) {
				// Picture cel data
				itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight);
				itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth);
				itemEntry->picStartX = ((itemEntry->picStartX * _screen->getWidth()) / scriptsRunningWidth);

				// Out of view
				int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x;
				int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo);
				int16 planeStartX = it->planeOffsetX;
				int16 planeEndX = planeStartX + it->planeRect.width();
				if (pictureCelEndX < planeStartX)
					continue;
				if (pictureCelStartX > planeEndX)
					continue;

				int16 pictureOffsetX = it->planeOffsetX;
				int16 pictureX = itemEntry->x;
				if ((it->planeOffsetX) || (itemEntry->picStartX)) {
					if (it->planeOffsetX <= itemEntry->picStartX) {
						pictureX += itemEntry->picStartX - it->planeOffsetX;
						pictureOffsetX = 0;
					} else {
						pictureOffsetX = it->planeOffsetX - itemEntry->picStartX;
					}
				}

				itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, it->planePictureMirrored);
//				warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);

			} else if (itemEntry->viewId != 0xFFFF) {
				GfxView *view = _cache->getView(itemEntry->viewId);

//				warning("view %s %04x:%04x", _segMan->getObjectName(itemEntry->object), PRINT_REG(itemEntry->object));


				if (view->isSci2Hires()) {
					int16 dummyX = 0;
					_screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
					_screen->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
				} else if (getSciVersion() == SCI_VERSION_2_1) {
					itemEntry->y = (itemEntry->y * _screen->getHeight()) / scriptsRunningHeight;
					itemEntry->x = (itemEntry->x * _screen->getWidth()) / scriptsRunningWidth;
					itemEntry->z = (itemEntry->z * _screen->getHeight()) / scriptsRunningHeight;
				}

				// Adjust according to current scroll position
				itemEntry->x -= it->planeOffsetX;

				uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect));
				if (useInsetRect) {
					itemEntry->celRect.top = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inTop));
					itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft));
					itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)) + 1;
					itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)) + 1;
					if (view->isSci2Hires()) {
						_screen->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
						_screen->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
					}
					itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
					// TODO: maybe we should clip the cels rect with this, i'm not sure
					//  the only currently known usage is game menu of gk1
				} else {
					if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
						view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect);
					else
						view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect);

					Common::Rect nsRect = itemEntry->celRect;
					// Translate back to actual coordinate within scrollable plane
					nsRect.translate(it->planeOffsetX, 0);

					if (view->isSci2Hires()) {
						_screen->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
						_screen->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
					} else if (getSciVersion() == SCI_VERSION_2_1) {
						nsRect.top = (nsRect.top * scriptsRunningHeight) / _screen->getHeight();
						nsRect.left = (nsRect.left * scriptsRunningWidth) / _screen->getWidth();
						nsRect.bottom = (nsRect.bottom * scriptsRunningHeight) / _screen->getHeight();
						nsRect.right = (nsRect.right * scriptsRunningWidth) / _screen->getWidth();
					}

					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsLeft), nsRect.left);
					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsTop), nsRect.top);
					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsRight), nsRect.right);
					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsBottom), nsRect.bottom);
				}

				int16 screenHeight = _screen->getHeight();
				int16 screenWidth = _screen->getWidth();
				if (view->isSci2Hires()) {
					screenHeight = _screen->getDisplayHeight();
					screenWidth = _screen->getDisplayWidth();
				}

				if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= screenHeight)
					continue;

				if (itemEntry->celRect.right < 0 || itemEntry->celRect.left >= screenWidth)
					continue;

				Common::Rect clipRect, translatedClipRect;
				clipRect = itemEntry->celRect;
				if (view->isSci2Hires()) {
					clipRect.clip(it->upscaledPlaneClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top);
				} else {
					clipRect.clip(it->planeClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->planeRect.left, it->planeRect.top);
				}

				if (!clipRect.isEmpty()) {
					if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
						view->draw(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
					else
						view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
				}
			} else {
				// Most likely a text entry
				// This draws text the "SCI0-SCI11" way. In SCI2, text is prerendered in kCreateTextBitmap
				// TODO: rewrite this the "SCI2" way (i.e. implement the text buffer to draw inside kCreateTextBitmap)
				if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) {
					reg_t stringObject = readSelector(_segMan, itemEntry->object, SELECTOR(text));

					// The object in the text selector of the item can be either a raw string
					// or a Str object. In the latter case, we need to access the object's data
					// selector to get the raw string.
					if (_segMan->isHeapObject(stringObject))
						stringObject = readSelector(_segMan, stringObject, SELECTOR(data));

					Common::String text = _segMan->getString(stringObject);
					GfxFont *font = _cache->getFont(readSelectorValue(_segMan, itemEntry->object, SELECTOR(font)));
					bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed));
					uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore));

					itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight);
					itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth);

					uint16 startX = itemEntry->x + it->planeRect.left;
					uint16 curY = itemEntry->y + it->planeRect.top;
					const char *txt = text.c_str();
					// HACK. The plane sometimes doesn't contain the correct width. This
					// hack breaks the dialog options when speaking with Grace, but it's
					// the best we got up to now. This happens because of the unimplemented
					// kTextWidth function in SCI32.
					// TODO: Remove this once kTextWidth has been implemented.
					uint16 w = it->planeRect.width() >= 20 ? it->planeRect.width() : _screen->getWidth() - 10;
					int16 charCount;

					// Upscale the coordinates/width if the fonts are already upscaled
					if (_screen->fontIsUpscaled()) {
						startX = startX * _screen->getDisplayWidth() / _screen->getWidth();
						curY = curY * _screen->getDisplayHeight() / _screen->getHeight();
						w  = w * _screen->getDisplayWidth() / _screen->getWidth();
					}

					while (*txt) {
						charCount = GetLongest(txt, w, font);
						if (charCount == 0)
							break;

						uint16 curX = startX;

						for (int i = 0; i < charCount; i++) {
							unsigned char curChar = txt[i];
							font->draw(curChar, curY, curX, foreColor, dimmed);
							curX += font->getCharWidth(curChar);
						}

						curY += font->getHeight();
						txt += charCount;
						while (*txt == ' ')
							txt++; // skip over breaking spaces
					}

				}
			}
		}

		for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
			if (pictureIt->object == planeObject) {
				delete[] pictureIt->pictureCels;
				pictureIt->pictureCels = 0;
			}
		}
	}

	_screen->copyToScreen();

	g_sci->getEngineState()->_throttleTrigger = true;
}