From 714665f9d9bde9bf337160276c50b662a5501442 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 2 Feb 2010 16:25:35 +0000 Subject: SCI: some sort of priority support for sci32 (not working right, but at least the menu in gk1 now correctly shows up) svn-id: r47814 --- engines/sci/graphics/frameout.cpp | 216 ++++++++++++++++++++++++++++++++++++++ engines/sci/graphics/frameout.h | 75 +++++++++++++ engines/sci/graphics/gui32.cpp | 118 +++------------------ engines/sci/graphics/gui32.h | 12 +-- engines/sci/graphics/picture.cpp | 23 +++- engines/sci/graphics/picture.h | 8 +- engines/sci/module.mk | 1 + 7 files changed, 333 insertions(+), 120 deletions(-) create mode 100644 engines/sci/graphics/frameout.cpp create mode 100644 engines/sci/graphics/frameout.h diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp new file mode 100644 index 0000000000..09251d0ce2 --- /dev/null +++ b/engines/sci/graphics/frameout.cpp @@ -0,0 +1,216 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/stack.h" +#include "graphics/primitives.h" + +#include "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/engine/selector.h" +#include "sci/engine/vm.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/view.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/picture.h" +#include "sci/graphics/frameout.h" + +namespace Sci { + +GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCache *cache, GfxScreen *screen, GfxPalette *palette) + : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette) { +} + +GfxFrameout::~GfxFrameout() { +} + +void GfxFrameout::kernelAddPlane(reg_t object) { + _planes.push_back(object); + int16 planePri = GET_SEL32V(_segMan, object, priority) & 0xFFFF; + if (planePri > _highPlanePri) + _highPlanePri = planePri; +} + +void GfxFrameout::kernelUpdatePlane(reg_t object) { +} + +void GfxFrameout::kernelDeletePlane(reg_t object) { + for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { + if (_planes[planeNr] == object) { + _planes.remove_at(planeNr); + break; + } + } + + // Recalculate highPlanePri + _highPlanePri = 0; + + for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { + int16 planePri = GET_SEL32V(_segMan, _planes[planeNr], priority) & 0xFFFF; + if (planePri > _highPlanePri) + _highPlanePri = planePri; + } +} + +void GfxFrameout::kernelAddScreenItem(reg_t object) { + _screenItems.push_back(object); + warning("addScreenItem %X:%X (%s)", object.segment, object.offset, _segMan->getObjectName(object)); +} + +void GfxFrameout::kernelDeleteScreenItem(reg_t object) { + for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) { + if (_screenItems[itemNr] == object) { + _screenItems.remove_at(itemNr); + return; + } + } +} + +int16 GfxFrameout::kernelGetHighPlanePri() { + return _highPlanePri; +} + +bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) { + return (entry1->priority == entry2->priority) ? (entry1->y < entry2->y) : (entry1->priority < entry2->priority); +} + +void GfxFrameout::kernelFrameout() { + int16 itemCount = 0; + reg_t planeObject; + GuiResourceId planePictureNr; + SciGuiPicture *planePicture = 0; + int16 planePictureCels; + int16 planePictureCel; + int16 planePriority; + int16 planeTop, planeLeft; + + reg_t itemObject; + reg_t itemPlane; + + FrameoutEntry *itemData; + FrameoutList itemList; + FrameoutEntry *itemEntry; + + // Allocate enough space for all screen items + itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry)); + + for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { + planeObject = _planes[planeNr]; + planePriority = GET_SEL32V(_segMan, planeObject, priority); + + if (planePriority == -1) // Plane currently not meant to be shown + continue; + + planePictureNr = GET_SEL32V(_segMan, planeObject, picture); + if (planePictureNr != 0xFFFF) { + planePicture = new SciGuiPicture(_resMan, 0, _screen, _palette, planePictureNr, false); + planePictureCels = planePicture->getSci32celCount(); + } + + planeTop = GET_SEL32V(_segMan, planeObject, top); + planeLeft = GET_SEL32V(_segMan, planeObject, left); + + // Fill our itemlist for this plane + itemCount = 0; + itemEntry = itemData; + for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) { + itemObject = _screenItems[itemNr]; + itemPlane = GET_SEL32(_segMan, itemObject, plane); + if (planeObject == itemPlane) { + // Found an item on current plane + itemEntry->viewId = GET_SEL32V(_segMan, itemObject, view); + itemEntry->loopNo = GET_SEL32V(_segMan, itemObject, loop); + itemEntry->celNo = GET_SEL32V(_segMan, itemObject, cel); + itemEntry->x = GET_SEL32V(_segMan, itemObject, x); + itemEntry->y = GET_SEL32V(_segMan, itemObject, y); + itemEntry->z = GET_SEL32V(_segMan, itemObject, z); + itemEntry->priority = GET_SEL32V(_segMan, itemObject, priority); + itemEntry->scaleX = GET_SEL32V(_segMan, itemObject, scaleX); + itemEntry->scaleY = GET_SEL32V(_segMan, itemObject, scaleY); + + itemEntry->x += planeLeft; + itemEntry->y += planeTop; + + itemList.push_back(itemEntry); + itemEntry++; + itemCount++; + } + } + + // Now sort our itemlist + Common::sort(itemList.begin(), itemList.end(), sortHelper); + + // Now display itemlist + planePictureCel = 0; + + itemEntry = itemData; + FrameoutList::iterator listIterator = itemList.begin(); + FrameoutList::iterator listEnd = itemList.end(); + while (listIterator != listEnd) { + itemEntry = *listIterator; + if (planePicture) { + while ((planePictureCel <= itemEntry->priority) && (planePictureCel < planePictureCels)) { + planePicture->drawSci32Vga(planePictureCel); + planePictureCel++; + } + } + if (itemEntry->viewId != 0xFFFF) { + View *view = _cache->getView(itemEntry->viewId); + + 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); + + if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) { + listIterator++; + continue; + } + + if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= _screen->getWidth()) { + listIterator++; + continue; + } + + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) + view->draw(itemEntry->celRect, itemEntry->celRect, itemEntry->celRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, false); + else + view->drawScaled(itemEntry->celRect, itemEntry->celRect, itemEntry->celRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); + } + listIterator++; + } + if (planePicture) { + while (planePictureCel < planePictureCels) { + planePicture->drawSci32Vga(planePictureCel); + planePictureCel++; + } + delete planePicture; + planePicture = 0; + } + } + free(itemData); +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h new file mode 100644 index 0000000000..bd5c13b2da --- /dev/null +++ b/engines/sci/graphics/frameout.h @@ -0,0 +1,75 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCI_GRAPHICS_FRAMEOUT_H +#define SCI_GRAPHICS_FRAMEOUT_H + +namespace Sci { + +struct FrameoutEntry { + reg_t object; + GuiResourceId viewId; + int16 loopNo; + int16 celNo; + int16 x, y, z; + int16 priority; + uint16 scaleSignal; + int16 scaleX; + int16 scaleY; + Common::Rect celRect; +}; +typedef Common::List FrameoutList; + +class GfxCache; +class Screen; +class SciPalette; +class GfxFrameout { +public: + GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCache *cache, GfxScreen *screen, GfxPalette *palette); + ~GfxFrameout(); + + void kernelAddPlane(reg_t object); + void kernelUpdatePlane(reg_t object); + void kernelDeletePlane(reg_t object); + void kernelAddScreenItem(reg_t object); + void kernelDeleteScreenItem(reg_t object); + int16 kernelGetHighPlanePri(); + void kernelFrameout(); + +private: + SegManager *_segMan; + ResourceManager *_resMan; + GfxCache *_cache; + GfxPalette *_palette; + GfxScreen *_screen; + + Common::Array _screenItems; + Common::Array _planes; + int16 _highPlanePri; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp index d5cf1700a2..61add8a8cd 100644 --- a/engines/sci/graphics/gui32.cpp +++ b/engines/sci/graphics/gui32.cpp @@ -37,6 +37,7 @@ #include "sci/graphics/cursor.h" #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" +#include "sci/graphics/frameout.h" #include "sci/graphics/picture.h" #include "sci/graphics/robot.h" #include "sci/graphics/view.h" @@ -44,9 +45,10 @@ namespace Sci { SciGui32::SciGui32(EngineState *state, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, Cursor *cursor) - : _s(state), _screen(screen), _palette(palette), _cache(cache), _cursor(cursor), _highPlanePri(0) { + : _s(state), _screen(screen), _palette(palette), _cache(cache), _cursor(cursor) { _compare = new GfxCompare(_s->_segMan, _s->_kernel, _cache, _screen); + _frameout = new GfxFrameout(_s->_segMan, _s->resMan, _cache, _screen, _palette); } SciGui32::~SciGui32() { @@ -214,128 +216,32 @@ void SciGui32::moveCursor(Common::Point pos) { void SciGui32::setCursorZone(Common::Rect zone) { _cursor->setMoveZone(zone); } - void SciGui32::addScreenItem(reg_t object) { - _screenItems.push_back(object); - warning("addScreenItem %X:%X (%s)", object.segment, object.offset, _s->_segMan->getObjectName(object)); + _frameout->kernelAddScreenItem(object); } void SciGui32::deleteScreenItem(reg_t object) { - for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) { - if (_screenItems[itemNr] == object) { - _screenItems.remove_at(itemNr); - return; - } - } + _frameout->kernelDeleteScreenItem(object); } void SciGui32::addPlane(reg_t object) { - _planes.push_back(object); - byte planePri = GET_SEL32V(_s->_segMan, object, priority) & 0xFF; - if (planePri > _highPlanePri) - _highPlanePri = planePri; + _frameout->kernelAddPlane(object); } void SciGui32::updatePlane(reg_t object) { + _frameout->kernelUpdatePlane(object); } void SciGui32::deletePlane(reg_t object) { - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - if (_planes[planeNr] == object) { - _planes.remove_at(planeNr); - break; - } - } - - // Recalculate highPlanePri - _highPlanePri = 0; + _frameout->kernelDeletePlane(object); +} - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - byte planePri = GET_SEL32V(_s->_segMan, _planes[planeNr], priority) & 0xFF; - if (planePri > _highPlanePri) - _highPlanePri = planePri; - } +int16 SciGui32::getHighPlanePri() { + return _frameout->kernelGetHighPlanePri(); } void SciGui32::frameOut() { - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - reg_t planeObj = _planes[planeNr]; - int16 priority = GET_SEL32V(_s->_segMan, planeObj, priority); - - if (priority == -1) - continue; - - int16 picNum = GET_SEL32V(_s->_segMan, planeObj, picture); - if (picNum > -1) { - SciGuiPicture *picture = new SciGuiPicture(_s->resMan, 0, _screen, _palette, picNum, false); - - picture->draw(100, false, false, 0); - delete picture; - //_gfx->drawPicture(picNum, 100, false, false, 0); - } - - // FIXME: This code doesn't currently work properly because of the way we set up the - // view port. We are starting at 10 pixels from the top automatically. The offset should - // be based on the plane's top in SCI32 instead. Here we would be adding 10 to 10 and - // therefore drawing too low. We would need to draw each picture at the correct offset - // which doesn't currently happen. - int16 planeTop = GET_SEL32V(_s->_segMan, planeObj, top); - int16 planeLeft = GET_SEL32V(_s->_segMan, planeObj, left); - - for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) { - reg_t viewObj = _screenItems[itemNr]; - reg_t planeOfItem = GET_SEL32(_s->_segMan, viewObj, plane); - if (planeOfItem == _planes[planeNr]) { - uint16 viewId = GET_SEL32V(_s->_segMan, viewObj, view); - uint16 loopNo = GET_SEL32V(_s->_segMan, viewObj, loop); - uint16 celNo = GET_SEL32V(_s->_segMan, viewObj, cel); - uint16 x = GET_SEL32V(_s->_segMan, viewObj, x); - uint16 y = GET_SEL32V(_s->_segMan, viewObj, y); - uint16 z = GET_SEL32V(_s->_segMan, viewObj, z); - priority = GET_SEL32V(_s->_segMan, viewObj, priority); - uint16 scaleX = GET_SEL32V(_s->_segMan, viewObj, scaleX); - uint16 scaleY = GET_SEL32V(_s->_segMan, viewObj, scaleY); - //int16 signal = GET_SEL32V(_s->_segMan, viewObj, signal); - - // FIXME: See above - x += planeLeft; - y += planeTop; - - // Theoretically, leftPos and topPos should be sane - // Apparently, sometimes they're not, therefore I'm adding some sanity checks here so that - // the hack underneath does not try and draw cels outside the screen coordinates - if (x >= _screen->getWidth()) { - continue; - } - - if (y >= _screen->getHeight()) { - continue; - } - - if (viewId != 0xffff) { - Common::Rect celRect; - View *view = _cache->getView(viewId); - - if ((scaleX == 128) && (scaleY == 128)) - view->getCelRect(loopNo, celNo, x, y, z, &celRect); - else - view->getCelScaledRect(loopNo, celNo, x, y, z, scaleX, scaleY, &celRect); - - if (celRect.top < 0 || celRect.top >= _screen->getHeight()) - continue; - - if (celRect.left < 0 || celRect.left >= _screen->getWidth()) - continue; - - if ((scaleX == 128) && (scaleY == 128)) - view->draw(celRect, celRect, celRect, loopNo, celNo, 255, 0, false); - else - view->drawScaled(celRect, celRect, celRect, loopNo, celNo, 255, scaleX, scaleY); - //_gfx->drawCel(view, loopNo, celNo, celRect, priority, 0, scaleX, scaleY); - } - } - } - } + _frameout->kernelFrameout(); _screen->copyToScreen(); } diff --git a/engines/sci/graphics/gui32.h b/engines/sci/graphics/gui32.h index e57c972af7..a6f32618a9 100644 --- a/engines/sci/graphics/gui32.h +++ b/engines/sci/graphics/gui32.h @@ -30,12 +30,12 @@ namespace Sci { -class Screen; -class SciPalette; class Cursor; +class GfxScreen; +class GfxPalette; class GfxCache; class GfxCompare; -class Text; +class GfxFrameout; class SciGui32 { public: @@ -69,7 +69,7 @@ public: void addPlane(reg_t object); void updatePlane(reg_t object); void deletePlane(reg_t object); - byte getHighPlanePri() { return _highPlanePri; } + int16 getHighPlanePri(); void frameOut(); void globalToLocal(int16 *x, int16 *y, reg_t planeObj); void localToGlobal(int16 *x, int16 *y, reg_t planeObj); @@ -88,11 +88,9 @@ protected: GfxPalette *_palette; GfxCache *_cache; GfxCompare *_compare; + GfxFrameout *_frameout; private: - Common::Array _screenItems; - Common::Array _planes; - byte _highPlanePri; }; } // End of namespace Sci diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index 96683ba344..a2dc25f797 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -117,7 +117,12 @@ void SciGuiPicture::drawSci11Vga() { } #ifdef ENABLE_SCI32 -void SciGuiPicture::drawSci32Vga() { +int16 SciGuiPicture::getSci32celCount() { + byte *inbuffer = _resource->data; + return inbuffer[2]; +} + +void SciGuiPicture::drawSci32Vga(int16 celNo) { byte *inbuffer = _resource->data; int size = _resource->size; int header_size = READ_LE_UINT16(inbuffer); @@ -128,9 +133,19 @@ void SciGuiPicture::drawSci32Vga() { int cel_relXpos, cel_relYpos; Palette palette; - // Create palette and set it - _palette->createFromData(inbuffer + palette_data_ptr, &palette); - _palette->set(&palette, true); + // HACK + _mirroredFlag = false; + _addToFlag = false; + + if ((celNo == -1) || (celNo == 0)) { + // Create palette and set it + _palette->createFromData(inbuffer + palette_data_ptr, &palette); + _palette->set(&palette, true); + } + if (celNo != -1) { + cel_headerPos += 42 * celNo; + celCount = 1; + } while (celCount > 0) { cel_RlePos = READ_LE_UINT16(inbuffer + cel_headerPos + 24); diff --git a/engines/sci/graphics/picture.h b/engines/sci/graphics/picture.h index 38dc17fed0..85c2696533 100644 --- a/engines/sci/graphics/picture.h +++ b/engines/sci/graphics/picture.h @@ -44,13 +44,15 @@ public: GuiResourceId getResourceId(); void draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo); +#ifdef ENABLE_SCI32 + int16 getSci32celCount(); + void drawSci32Vga(int16 celNo = -1); +#endif + private: void initData(GuiResourceId resourceId); void reset(); void drawSci11Vga(); -#ifdef ENABLE_SCI32 - void drawSci32Vga(); -#endif void drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 callerX, int16 callerY, bool hasSci32Header); void drawVectorData(byte *data, int size); bool vectorIsNonOpcode(byte pixel); diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 23e1606078..c6ecf07f2c 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -39,6 +39,7 @@ MODULE_OBJS := \ graphics/controls.o \ graphics/cursor.o \ graphics/font.o \ + graphics/frameout.o \ graphics/gui.o \ graphics/menu.o \ graphics/paint16.o \ -- cgit v1.2.3