mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-19 16:18:45 +00:00
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:
parent
cf3890b79a
commit
81d614e63a
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user