Пример #1
0
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);
	}
}
Пример #2
0
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);
	}
}
Пример #3
0
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;
}