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
This commit is contained in:
Martin Kiewitz 2010-02-02 16:25:35 +00:00
parent b0208e7306
commit 714665f9d9
7 changed files with 333 additions and 120 deletions

View File

@ -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

View File

@ -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<FrameoutEntry *> 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<reg_t> _screenItems;
Common::Array<reg_t> _planes;
int16 _highPlanePri;
};
} // End of namespace Sci
#endif

View File

@ -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;
}
}
_frameout->kernelDeletePlane(object);
}
// Recalculate highPlanePri
_highPlanePri = 0;
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();
}

View File

@ -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<reg_t> _screenItems;
Common::Array<reg_t> _planes;
byte _highPlanePri;
};
} // End of namespace Sci

View File

@ -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);

View File

@ -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);

View File

@ -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 \