SCI: Break the huge kernelFrameOut function into several smaller ones

Also, prefix more class variables with underscores
This commit is contained in:
Filippos Karapetis 2011-11-17 22:08:36 +02:00
parent 10e14367ec
commit b400e142af
2 changed files with 175 additions and 137 deletions

View File

@ -56,8 +56,8 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd
: _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) {
_coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster;
scriptsRunningWidth = 320;
scriptsRunningHeight = 200;
_scriptsRunningWidth = 320;
_scriptsRunningHeight = 200;
}
GfxFrameout::~GfxFrameout() {
@ -80,11 +80,11 @@ void GfxFrameout::kernelAddPlane(reg_t object) {
// The above can be 0 in SCI3 (e.g. Phantasmagoria 2)
if (tmpRunningWidth > 0 && tmpRunningHeight > 0) {
scriptsRunningWidth = tmpRunningWidth;
scriptsRunningHeight = tmpRunningHeight;
_scriptsRunningWidth = tmpRunningWidth;
_scriptsRunningHeight = tmpRunningHeight;
}
_coordAdjuster->setScriptsResolution(scriptsRunningWidth, scriptsRunningHeight);
_coordAdjuster->setScriptsResolution(_scriptsRunningWidth, _scriptsRunningHeight);
}
newPlane.object = object;
@ -122,10 +122,10 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) {
it->planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right));
Common::Rect screenRect(_screen->getWidth(), _screen->getHeight());
it->planeRect.top = (it->planeRect.top * screenRect.height()) / scriptsRunningHeight;
it->planeRect.left = (it->planeRect.left * screenRect.width()) / scriptsRunningWidth;
it->planeRect.bottom = (it->planeRect.bottom * screenRect.height()) / scriptsRunningHeight;
it->planeRect.right = (it->planeRect.right * screenRect.width()) / scriptsRunningWidth;
it->planeRect.top = (it->planeRect.top * screenRect.height()) / _scriptsRunningHeight;
it->planeRect.left = (it->planeRect.left * screenRect.width()) / _scriptsRunningWidth;
it->planeRect.bottom = (it->planeRect.bottom * screenRect.height()) / _scriptsRunningHeight;
it->planeRect.right = (it->planeRect.right * screenRect.width()) / _scriptsRunningWidth;
// We get negative left in kq7 in scrolling rooms
if (it->planeRect.left < 0) {
@ -189,10 +189,10 @@ void GfxFrameout::kernelDeletePlane(reg_t object) {
planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right));
Common::Rect screenRect(_screen->getWidth(), _screen->getHeight());
planeRect.top = (planeRect.top * screenRect.height()) / scriptsRunningHeight;
planeRect.left = (planeRect.left * screenRect.width()) / scriptsRunningWidth;
planeRect.bottom = (planeRect.bottom * screenRect.height()) / scriptsRunningHeight;
planeRect.right = (planeRect.right * screenRect.width()) / scriptsRunningWidth;
planeRect.top = (planeRect.top * screenRect.height()) / _scriptsRunningHeight;
planeRect.left = (planeRect.left * screenRect.width()) / _scriptsRunningWidth;
planeRect.bottom = (planeRect.bottom * screenRect.height()) / _scriptsRunningHeight;
planeRect.right = (planeRect.right * screenRect.width()) / _scriptsRunningWidth;
planeRect.clip(screenRect); // we need to do this, at least in gk1 on cemetary we get bottom right -> 201, 321
// FIXME: The code above incorrectly added 1 pixel to the plane's
// bottom and right, so probably the plane clipping code is no
@ -332,37 +332,149 @@ void GfxFrameout::sortPlanes() {
Common::sort(_planes.begin(), _planes.end(), planeSortHelper);
}
int16 GfxFrameout::upscaleHorizontalCoordinate(int16 coordinate) {
return ((coordinate * _screen->getWidth()) / _scriptsRunningWidth);
}
int16 GfxFrameout::upscaleVerticalCoordinate(int16 coordinate) {
return ((coordinate * _screen->getHeight()) / _scriptsRunningHeight);
}
Common::Rect GfxFrameout::upscaleRect(Common::Rect &rect) {
rect.top = (rect.top * _scriptsRunningHeight) / _screen->getHeight();
rect.left = (rect.left * _scriptsRunningWidth) / _screen->getWidth();
rect.bottom = (rect.bottom * _scriptsRunningHeight) / _screen->getHeight();
rect.right = (rect.right * _scriptsRunningWidth) / _screen->getWidth();
return rect;
}
void GfxFrameout::showVideo() {
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);
}
}
void GfxFrameout::createPlaneItemList(reg_t planeObject, 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->picStartY = pictureIt->startY;
picEntry->priority = planePicture->getSci32celPriority(pictureCelNr);
itemList.push_back(picEntry);
picEntry++;
}
}
}
// Now sort our itemlist
Common::sort(itemList.begin(), itemList.end(), sortHelper);
}
bool GfxFrameout::isPictureOutOfView(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 planeOffsetX, int16 planeOffsetY) {
// Out of view horizontally (sanity checks)
int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x;
int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo);
int16 planeStartX = planeOffsetX;
int16 planeEndX = planeStartX + planeRect.width();
if (pictureCelEndX < planeStartX)
return true;
if (pictureCelStartX > planeEndX)
return true;
// Out of view vertically (sanity checks)
int16 pictureCelStartY = itemEntry->picStartY + itemEntry->y;
int16 pictureCelEndY = pictureCelStartY + itemEntry->picture->getSci32celHeight(itemEntry->celNo);
int16 planeStartY = planeOffsetY;
int16 planeEndY = planeStartY + planeRect.height();
if (pictureCelEndY < planeStartY)
return true;
if (pictureCelStartY > planeEndY)
return true;
return false;
}
void GfxFrameout::drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int16 planeOffsetY, bool planePictureMirrored) {
int16 pictureOffsetX = planeOffsetX;
int16 pictureX = itemEntry->x;
if ((planeOffsetX) || (itemEntry->picStartX)) {
if (planeOffsetX <= itemEntry->picStartX) {
pictureX += itemEntry->picStartX - planeOffsetX;
pictureOffsetX = 0;
} else {
pictureOffsetX = planeOffsetX - itemEntry->picStartX;
}
}
int16 pictureOffsetY = planeOffsetY;
int16 pictureY = itemEntry->y;
if ((planeOffsetY) || (itemEntry->picStartY)) {
if (planeOffsetY <= itemEntry->picStartY) {
pictureY += itemEntry->picStartY - planeOffsetY;
pictureOffsetY = 0;
} else {
pictureOffsetY = planeOffsetY - itemEntry->picStartY;
}
}
itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, pictureOffsetY, planePictureMirrored);
// warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);
}
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);
}
showVideo();
return;
}
@ -396,43 +508,7 @@ void GfxFrameout::kernelFrameout() {
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->picStartY = pictureIt->startY;
picEntry->priority = planePicture->getSci32celPriority(pictureCelNr);
itemList.push_back(picEntry);
picEntry++;
}
}
}
// Now sort our itemlist
Common::sort(itemList.begin(), itemList.end(), sortHelper);
createPlaneItemList(planeObject, itemList);
// warning("Plane %s", _segMan->getObjectName(planeObject));
@ -441,56 +517,13 @@ void GfxFrameout::kernelFrameout() {
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);
itemEntry->picStartY = ((itemEntry->picStartY * _screen->getHeight()) / scriptsRunningHeight);
// Out of view horizontally (sanity checks)
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;
// Out of view vertically (sanity checks)
int16 pictureCelStartY = itemEntry->picStartY + itemEntry->y;
int16 pictureCelEndY = pictureCelStartY + itemEntry->picture->getSci32celHeight(itemEntry->celNo);
int16 planeStartY = it->planeOffsetY;
int16 planeEndY = planeStartY + it->planeRect.height();
if (pictureCelEndY < planeStartY)
continue;
if (pictureCelStartY > planeEndY)
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;
}
}
int16 pictureOffsetY = it->planeOffsetY;
int16 pictureY = itemEntry->y;
if ((it->planeOffsetY) || (itemEntry->picStartY)) {
if (it->planeOffsetY <= itemEntry->picStartY) {
pictureY += itemEntry->picStartY - it->planeOffsetY;
pictureOffsetY = 0;
} else {
pictureOffsetY = it->planeOffsetY - itemEntry->picStartY;
}
}
itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, pictureOffsetY, it->planePictureMirrored);
// warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);
itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x);
itemEntry->y = upscaleVerticalCoordinate(itemEntry->y);
itemEntry->picStartX = upscaleHorizontalCoordinate(itemEntry->picStartX);
itemEntry->picStartY = upscaleVerticalCoordinate(itemEntry->picStartY);
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;
@ -499,9 +532,9 @@ void GfxFrameout::kernelFrameout() {
view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
view->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;
itemEntry->x = upscaleHorizontalCoordinate(itemEntry->x);
itemEntry->y = upscaleVerticalCoordinate(itemEntry->y);
itemEntry->z = upscaleVerticalCoordinate(itemEntry->z);
}
// Adjust according to current scroll position
@ -538,10 +571,7 @@ void GfxFrameout::kernelFrameout() {
view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
view->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();
nsRect = upscaleRect(nsRect);
}
if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {

View File

@ -104,6 +104,14 @@ public:
void clear();
private:
void showVideo();
void createPlaneItemList(reg_t planeObject, FrameoutList &itemList);
bool isPictureOutOfView(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 planeOffsetX, int16 planeOffsetY);
void drawPicture(FrameoutEntry *itemEntry, int16 planeOffsetX, int16 planeOffsetY, bool planePictureMirrored);
int16 upscaleHorizontalCoordinate(int16 coordinate);
int16 upscaleVerticalCoordinate(int16 coordinate);
Common::Rect upscaleRect(Common::Rect &rect);
SegManager *_segMan;
ResourceManager *_resMan;
GfxCoordAdjuster32 *_coordAdjuster;
@ -118,8 +126,8 @@ private:
void sortPlanes();
uint16 scriptsRunningWidth;
uint16 scriptsRunningHeight;
uint16 _scriptsRunningWidth;
uint16 _scriptsRunningHeight;
};
} // End of namespace Sci