SCI: More proper handling of scaling and global scaling in SCI32

This fixes several scaling related problems in QFG4 and SQ6
This commit is contained in:
Filippos Karapetis 2013-01-11 00:45:10 +02:00
parent cf3890b79a
commit 81d614e63a
2 changed files with 47 additions and 2 deletions

View File

@ -349,6 +349,36 @@ void GfxFrameout::deletePlaneLine(reg_t object, reg_t hunkId) {
}
}
// Adapted from GfxAnimate::applyGlobalScaling()
void GfxFrameout::applyGlobalScaling(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 celHeight) {
// Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
int16 maxScale = readSelectorValue(_segMan, itemEntry->object, SELECTOR(maxScale));
int16 maxCelHeight = (maxScale * celHeight) >> 7;
reg_t globalVar2 = g_sci->getEngineState()->variables[VAR_GLOBAL][2]; // current room object
int16 vanishingY = readSelectorValue(_segMan, globalVar2, SELECTOR(vanishingY));
int16 fixedPortY = planeRect.bottom - vanishingY;
int16 fixedEntryY = itemEntry->y - vanishingY;
if (!fixedEntryY)
fixedEntryY = 1;
if ((celHeight == 0) || (fixedPortY == 0))
error("global scaling panic");
itemEntry->scaleY = (maxCelHeight * fixedEntryY) / fixedPortY;
itemEntry->scaleY = (itemEntry->scaleY * maxScale) / celHeight;
// Make sure that the calculated value is sane
if (itemEntry->scaleY < 1 /*|| itemEntry->scaleY > 128*/)
itemEntry->scaleY = 128;
itemEntry->scaleX = itemEntry->scaleY;
// and set objects scale selectors
//writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleX), itemEntry->scaleX);
//writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleY), itemEntry->scaleY);
}
void GfxFrameout::kernelAddScreenItem(reg_t object) {
// Ignore invalid items
if (!_segMan->isObject(object)) {
@ -390,8 +420,14 @@ void GfxFrameout::kernelUpdateScreenItem(reg_t object) {
itemEntry->priority = itemEntry->y;
itemEntry->signal = readSelectorValue(_segMan, object, SELECTOR(signal));
itemEntry->scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX));
itemEntry->scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY));
itemEntry->scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal));
if (itemEntry->scaleSignal == 1) {
itemEntry->scaleX = readSelectorValue(_segMan, object, SELECTOR(scaleX));
itemEntry->scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY));
} else {
itemEntry->scaleX = 128;
itemEntry->scaleY = 128;
}
itemEntry->visible = true;
// Check if the entry can be hidden
@ -699,6 +735,14 @@ void GfxFrameout::kernelFrameout() {
// 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
if (itemEntry->scaleSignal != 0 && itemEntry->scaleSignal != 1)
error("Unknown scale signal: %d", itemEntry->scaleSignal);
// TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY)
if (itemEntry->scaleSignal == 1 && itemEntry->scaleX == itemEntry->scaleY)
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);

View File

@ -113,6 +113,7 @@ public:
void kernelAddPlane(reg_t object);
void kernelUpdatePlane(reg_t object);
void kernelDeletePlane(reg_t object);
void applyGlobalScaling(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 celHeight);
void kernelAddScreenItem(reg_t object);
void kernelUpdateScreenItem(reg_t object);
void kernelDeleteScreenItem(reg_t object);