diff options
-rw-r--r-- | engines/prince/graphics.cpp | 55 | ||||
-rw-r--r-- | engines/prince/graphics.h | 11 | ||||
-rw-r--r-- | engines/prince/hero.cpp | 3 | ||||
-rw-r--r-- | engines/prince/hero.h | 1 | ||||
-rw-r--r-- | engines/prince/object.h | 2 | ||||
-rw-r--r-- | engines/prince/prince.cpp | 169 | ||||
-rw-r--r-- | engines/prince/prince.h | 26 | ||||
-rw-r--r-- | engines/prince/pscr.h | 2 |
8 files changed, 213 insertions, 56 deletions
diff --git a/engines/prince/graphics.cpp b/engines/prince/graphics.cpp index 679885f7b8..bc15faf9a9 100644 --- a/engines/prince/graphics.cpp +++ b/engines/prince/graphics.cpp @@ -73,7 +73,7 @@ void GraphicsMan::draw(uint16 posX, uint16 posY, const Graphics::Surface *s) { change(); } -void GraphicsMan::drawTransparent(int32 posX, int32 posY, const Graphics::Surface *s) { +void GraphicsMan::drawTransparentIntro(int32 posX, int32 posY, const Graphics::Surface *s) { for (int y = 0; y < s->h; y++) { for (int x = 0; x < s->w; x++) { byte pixel = *((byte*)s->getBasePtr(x, y)); @@ -89,19 +89,34 @@ void GraphicsMan::drawTransparent(int32 posX, int32 posY, const Graphics::Surfac change(); } -void GraphicsMan::drawMask(int32 posX, int32 posY, int32 width, int32 height, byte *maskData, const Graphics::Surface *originalRoomSurface) { - int maskWidth = width >> 3; +void GraphicsMan::drawTransparent(Graphics::Surface *frontScreen, DrawNode *drawNode) { + for (int y = 0; y < drawNode->s->h; y++) { + for (int x = 0; x < drawNode->s->w; x++) { + byte pixel = *((byte*)drawNode->s->getBasePtr(x, y)); + if (pixel != 255) { + if (x + drawNode->posX < frontScreen->w && x + drawNode->posX >= 0) { + if (y + drawNode->posY < frontScreen->h && y + drawNode->posY >= 0) { + *((byte*)frontScreen->getBasePtr(x + drawNode->posX, y + drawNode->posY)) = pixel; + } + } + } + } + } +} + +void GraphicsMan::drawMask(Graphics::Surface *frontScreen, DrawNode *drawNode) { + int maskWidth = drawNode->width >> 3; int maskPostion = 0; int maskCounter = 128; - for (int y = 0; y < height; y++) { + for (int y = 0; y < drawNode->height; y++) { int tempMaskPostion = maskPostion; - for (int x = 0; x < width; x++) { - if (x + posX < _frontScreen->w && x + posX >= 0) { - if (y + posY < _frontScreen->h && y + posY >= 0) { - if ((maskData[tempMaskPostion] & maskCounter) != 0) { - byte orgPixel = *((byte*)originalRoomSurface->getBasePtr(x + posX, y + posY)); - *((byte*)_frontScreen->getBasePtr(x + posX, y + posY)) = orgPixel; - //*((byte*)_frontScreen->getBasePtr(x + posX, y + posY)) = 0; // for debugging + for (int x = 0; x < drawNode->width; x++) { + if (x + drawNode->posX < frontScreen->w && x + drawNode->posX >= 0) { + if (y + drawNode->posY < frontScreen->h && y + drawNode->posY >= 0) { + if ((drawNode->data[tempMaskPostion] & maskCounter) != 0) { + byte orgPixel = *((byte*)drawNode->originalRoomSurface->getBasePtr(x + drawNode->posX, y + drawNode->posY)); + *((byte*)frontScreen->getBasePtr(x + drawNode->posX, y + drawNode->posY)) = orgPixel; + //*((byte*)frontScreen->getBasePtr(x + posX, y + posY)) = 0; // for debugging } } } @@ -114,24 +129,22 @@ void GraphicsMan::drawMask(int32 posX, int32 posY, int32 width, int32 height, by maskPostion += maskWidth; maskCounter = 128; } - change(); } -void GraphicsMan::drawAsShadow(int32 posX, int32 posY, const Graphics::Surface *s, byte *shadowTable) { - for (int y = 0; y < s->h; y++) { - for (int x = 0; x < s->w; x++) { - byte pixel = *((byte*)s->getBasePtr(x, y)); +void GraphicsMan::drawAsShadow(Graphics::Surface *frontScreen, DrawNode *drawNode) { + for (int y = 0; y < drawNode->s->h; y++) { + for (int x = 0; x < drawNode->s->w; x++) { + byte pixel = *((byte*)drawNode->s->getBasePtr(x, y)); if (pixel == kShadowColor) { - if (x + posX < _frontScreen->w && x + posX >= 0) { - if (y + posY < _frontScreen->h && y + posY >= 0) { - byte *background = (byte *)_frontScreen->getBasePtr(x + posX, y + posY); - *background = *(shadowTable + *background); + if (x + drawNode->posX < frontScreen->w && x + drawNode->posX >= 0) { + if (y + drawNode->posY < frontScreen->h && y + drawNode->posY >= 0) { + byte *background = (byte *)frontScreen->getBasePtr(x + drawNode->posX, y + drawNode->posY); + *background = *(drawNode->data + *background); } } } } } - change(); } void GraphicsMan::makeShadowTable(int brightness, byte *shadowPalette) { diff --git a/engines/prince/graphics.h b/engines/prince/graphics.h index e6293bbeee..dca2508838 100644 --- a/engines/prince/graphics.h +++ b/engines/prince/graphics.h @@ -29,6 +29,7 @@ namespace Prince { class PrinceEngine; +struct DrawNode; class GraphicsMan { @@ -44,9 +45,13 @@ public: void makeShadowTable(int brightness, byte *shadowTable); void draw(uint16 x, uint16 y, const Graphics::Surface *s); - void drawTransparent(int32 posX, int32 poxY, const Graphics::Surface *s); - void drawAsShadow(int32 posX, int32 poxY, const Graphics::Surface *s, byte *shadowTable); - void drawMask(int32 posX, int32 posY, int32 width, int32 height, byte *maskData, const Graphics::Surface *originalRoomSurface); + void drawTransparentIntro(int32 posX, int32 poxY, const Graphics::Surface *s); + //void drawAsShadow(int32 posX, int32 poxY, const Graphics::Surface *s, byte *shadowTable); + //void drawMask(int32 posX, int32 posY, int32 width, int32 height, byte *maskData, const Graphics::Surface *originalRoomSurface); + + static void drawTransparent(Graphics::Surface *frontScreen, DrawNode *drawNode); + static void drawAsShadow(Graphics::Surface *frontScreen, DrawNode *drawNode); + static void drawMask(Graphics::Surface *frontScreen, DrawNode *drawNode); Graphics::Surface *_frontScreen; Graphics::Surface *_backScreen; diff --git a/engines/prince/hero.cpp b/engines/prince/hero.cpp index 4b582d6cc6..22ddf645d8 100644 --- a/engines/prince/hero.cpp +++ b/engines/prince/hero.cpp @@ -35,7 +35,7 @@ Hero::Hero(PrinceEngine *vm, GraphicsMan *graph) : _vm(vm), _graph(graph) , _number(0), _visible(false), _state(MOVE), _middleX(0), _middleY(0) , _boreNum(1), _currHeight(0), _moveDelay(0), _shadMinus(0), _moveSetType(0) , _lastDirection(DOWN), _destDirection(DOWN), _talkTime(0), _boredomTime(0), _phase(0) - , _specAnim(0), _drawX(0), _drawY(0), _zoomFactor(0), _scaleValue(0) + , _specAnim(0), _drawX(0), _drawY(0), _drawZ(0), _zoomFactor(0), _scaleValue(0) , _shadZoomFactor(0), _shadScaleValue(0), _shadLineLen(0), _shadDrawX(0), _shadDrawY(0) , _frameXSize(0), _frameYSize(0), _scaledFrameXSize(0), _scaledFrameYSize(0) { @@ -205,6 +205,7 @@ void Hero::countDrawPosition() { //notfullSize _drawX = _middleX - _scaledFrameXSize / 2; _drawY = tempMiddleY + 1 - _scaledFrameYSize; + _drawZ = _drawY - 1; _vm->checkMasks(_drawX, _drawY - 1, _scaledFrameXSize, _scaledFrameYSize, _middleY); } else { //fullSize diff --git a/engines/prince/hero.h b/engines/prince/hero.h index 565212447b..5b8391c10c 100644 --- a/engines/prince/hero.h +++ b/engines/prince/hero.h @@ -145,6 +145,7 @@ public: int16 _scaledFrameYSize; int16 _drawX; int16 _drawY; + int16 _drawZ; int16 _lightX; // for hero's shadow int16 _lightY; diff --git a/engines/prince/object.h b/engines/prince/object.h index 5bc7c580da..ea1ad9dc0d 100644 --- a/engines/prince/object.h +++ b/engines/prince/object.h @@ -43,7 +43,7 @@ public: int32 _zoomInTime; bool loadFromStream(Common::SeekableReadStream &stream); - const Graphics::Surface *getSurface() const { return _surface; } + Graphics::Surface *getSurface() const { return _surface; } private: void loadSurface(Common::SeekableReadStream &stream); Graphics::Surface *_surface; diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp index b19ac29d6b..d85a5eadb9 100644 --- a/engines/prince/prince.cpp +++ b/engines/prince/prince.cpp @@ -389,7 +389,7 @@ bool PrinceEngine::playNextFrame() { const Graphics::Surface *s = _flicPlayer.decodeNextFrame(); if (s) { - _graph->drawTransparent(0, 0, s); + _graph->drawTransparentIntro(0, 0, s); _graph->change(); } else if (_flicLooped) { _flicPlayer.rewind(); @@ -793,7 +793,7 @@ void PrinceEngine::clsMasks() { } // InsertNakladki -void PrinceEngine::insertMasks(const Graphics::Surface *originalRoomSurface) { +void PrinceEngine::insertMasks(Graphics::Surface *originalRoomSurface) { for (uint i = 0; i < _maskList.size(); i++) { if (_maskList[i]._state == 1) { showMask(i, originalRoomSurface); @@ -802,6 +802,30 @@ void PrinceEngine::insertMasks(const Graphics::Surface *originalRoomSurface) { } // ShowNak +void PrinceEngine::showMask(int maskNr, Graphics::Surface *originalRoomSurface) { + if (_maskList[maskNr]._flags == 0) { + if (spriteCheck(_maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr]._x1, _maskList[maskNr]._y1)) { + int destX = _maskList[maskNr]._x1 - _picWindowX; + int destY = _maskList[maskNr]._y1 - _picWindowY; + DrawNode newDrawNode; + newDrawNode.posX = destX; + newDrawNode.posY = destY; + newDrawNode.posZ = _maskList[maskNr]._z; + newDrawNode.width = _maskList[maskNr]._width; + newDrawNode.height = _maskList[maskNr]._height; + newDrawNode.s = nullptr; + newDrawNode.originalRoomSurface = originalRoomSurface; + newDrawNode.data = _maskList[maskNr].getMask(); + newDrawNode.freeSurfaceSMemory = false; + newDrawNode.drawFunction = &_graph->drawMask; + _drawNodeList.push_back(newDrawNode); + //_graph->drawMask(destX, destY, _maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr].getMask(), originalRoomSurface); + } + } +} + +/* +// ShowNak void PrinceEngine::showMask(int maskNr, const Graphics::Surface *originalRoomSurface) { if (_maskList[maskNr]._flags == 0) { if (spriteCheck(_maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr]._x1, _maskList[maskNr]._y1)) { @@ -811,20 +835,44 @@ void PrinceEngine::showMask(int maskNr, const Graphics::Surface *originalRoomSur } } } - -void PrinceEngine::showSprite(const Graphics::Surface *spriteSurface, int destX, int destY) { +*/ +void PrinceEngine::showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ, bool freeSurfaceMemory) { if (spriteCheck(spriteSurface->w, spriteSurface->h, destX, destY)) { destX -= _picWindowX; destY -= _picWindowY; - _graph->drawTransparent(destX, destY, spriteSurface); + DrawNode newDrawNode; + newDrawNode.posX = destX; + newDrawNode.posY = destY; + newDrawNode.posZ = destZ; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.s = spriteSurface; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = nullptr; + newDrawNode.freeSurfaceSMemory = freeSurfaceMemory; + newDrawNode.drawFunction = &_graph->drawTransparent; + _drawNodeList.push_back(newDrawNode); + //_graph->drawTransparent(destX, destY, spriteSurface); } } -void PrinceEngine::showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY) { +void PrinceEngine::showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ, bool freeSurfaceMemory) { if (spriteCheck(shadowSurface->w, shadowSurface->h, destX, destY)) { destX -= _picWindowX; destY -= _picWindowY; - _graph->drawAsShadow(destX, destY, shadowSurface, _graph->_shadowTable70); + DrawNode newDrawNode; + newDrawNode.posX = destX; + newDrawNode.posY = destY; + newDrawNode.posZ = destZ; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.s = shadowSurface; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = _graph->_shadowTable70; + newDrawNode.freeSurfaceSMemory = freeSurfaceMemory; + newDrawNode.drawFunction = &_graph->drawAsShadow; + _drawNodeList.push_back(newDrawNode); + //_graph->drawAsShadow(destX, destY, shadowSurface, _graph->_shadowTable70); } } @@ -989,9 +1037,9 @@ void PrinceEngine::showBackAnims() { shadowZ = z; Graphics::Surface *backAnimSurface = _backAnimList[i].backAnims[activeSubAnim]._animData->getFrame(phaseFrameIndex); //still with memory leak - showSprite(backAnimSurface, x, y); - backAnimSurface->free(); - delete backAnimSurface; + showSprite(backAnimSurface, x, y, z, true); + //backAnimSurface->free(); + //delete backAnimSurface; } //ShowFrameCodeShadow @@ -1016,9 +1064,9 @@ void PrinceEngine::showBackAnims() { } Graphics::Surface *shadowSurface = _backAnimList[i].backAnims[activeSubAnim]._shadowData->getFrame(shadowPhaseFrameIndex); //still with memory leak - showSpriteShadow(shadowSurface, shadowX, shadowY); - shadowSurface->free(); - delete shadowSurface; + showSpriteShadow(shadowSurface, shadowX, shadowY, shadowZ, true); + //shadowSurface->free(); + //delete shadowSurface; } } } @@ -1057,12 +1105,24 @@ void PrinceEngine::showObjects() { // mov edx, d [esi.Obj_ZoomInAddr] } } - const Graphics::Surface *objSurface = _objList[i]->getSurface(); + Graphics::Surface *objSurface = _objList[i]->getSurface(); if (spriteCheck(objSurface->w, objSurface->h, _objList[i]->_x, _objList[i]->_y)) { if ((_objList[i]->_mask & 512) == 0) { // 0200h int destX = _objList[i]->_x - _picWindowX; int destY = _objList[i]->_y - _picWindowY; - _graph->drawTransparent(destX, destY, objSurface); + DrawNode newDrawNode; + newDrawNode.posX = destX; + newDrawNode.posY = destY; + newDrawNode.posZ = _objList[i]->_z; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.s = objSurface; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = nullptr; + newDrawNode.freeSurfaceSMemory = false; + newDrawNode.drawFunction = &_graph->drawTransparent; + _drawNodeList.push_back(newDrawNode); + //_graph->drawTransparent(destX, destY, objSurface); } else { // showBackSprite(); } @@ -1077,17 +1137,44 @@ void PrinceEngine::showObjects() { void PrinceEngine::showParallax() { if (!_pscrList.empty()) { for (uint i = 0; i < _pscrList.size(); i++) { - const Graphics::Surface *pscrSurface = _pscrList[i]->getSurface(); + Graphics::Surface *pscrSurface = _pscrList[i]->getSurface(); int x = _pscrList[i]->_x - (_pscrList[i]->_step * _picWindowX / 4); int y = _pscrList[i]->_y; - //int z = 1000; + int z = 1000; if (spriteCheck(pscrSurface->w, pscrSurface->h, x, y)) { - showSprite(pscrSurface, x, y); + showSprite(pscrSurface, x, y, z, false); } } } } +bool PrinceEngine::compareDrawNodes(DrawNode d1, DrawNode d2) { + if (d1.posZ < d2.posZ) { + return true; + } + return false; +} + +void PrinceEngine::runDrawNodes() { + Common::sort(_drawNodeList.begin(), _drawNodeList.end(), compareDrawNodes); + + for (uint i = 0; i < _drawNodeList.size(); i++) { + (*_drawNodeList[i].drawFunction)(_graph->_frontScreen, &_drawNodeList[i]); + } + _graph->change(); +} + + +void PrinceEngine::freeDrawNodes() { + for (uint i = 0; i < _drawNodeList.size(); i++) { + if (_drawNodeList[i].freeSurfaceSMemory) { + _drawNodeList[i].s->free(); + delete _drawNodeList[i].s; + } + } + _drawNodeList.clear(); +} + void PrinceEngine::drawScreen() { const Graphics::Surface *roomSurface = _roomBmp->getSurface(); Graphics::Surface visiblePart; @@ -1096,21 +1183,44 @@ void PrinceEngine::drawScreen() { _graph->draw(0, 0, &visiblePart); } + Graphics::Surface *mainHeroSurface; if (_mainHero->_visible) { - Graphics::Surface *mainHeroSurface = _mainHero->getSurface(); + mainHeroSurface = _mainHero->getSurface(); if (mainHeroSurface) { _mainHero->showHeroShadow(mainHeroSurface); if (_mainHero->_zoomFactor != 0) { Graphics::Surface *zoomedHeroSurface = _mainHero->zoomSprite(mainHeroSurface); - _graph->drawTransparent(_mainHero->_drawX, _mainHero->_drawY, zoomedHeroSurface); - zoomedHeroSurface->free(); - delete zoomedHeroSurface; + DrawNode newDrawNode; + newDrawNode.posX = _mainHero->_drawX; + newDrawNode.posY = _mainHero->_drawY; + newDrawNode.posZ = _mainHero->_drawZ; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.s = zoomedHeroSurface; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = nullptr; + newDrawNode.freeSurfaceSMemory = true; + newDrawNode.drawFunction = &_graph->drawTransparent; + _drawNodeList.push_back(newDrawNode); + //_graph->drawTransparent(_mainHero->_drawX, _mainHero->_drawY, zoomedHeroSurface); + //zoomedHeroSurface->free(); + //delete zoomedHeroSurface; } else { - _graph->drawTransparent(_mainHero->_drawX, _mainHero->_drawY, mainHeroSurface); + DrawNode newDrawNode; + newDrawNode.posX = _mainHero->_drawX; + newDrawNode.posY = _mainHero->_drawY; + newDrawNode.posZ = _mainHero->_drawZ; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.s = mainHeroSurface; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = nullptr; + newDrawNode.freeSurfaceSMemory = false; + newDrawNode.drawFunction = &_graph->drawTransparent; + _drawNodeList.push_back(newDrawNode); + //_graph->drawTransparent(_mainHero->_drawX, _mainHero->_drawY, mainHeroSurface); } } - mainHeroSurface->free(); - delete mainHeroSurface; } showBackAnims(); @@ -1123,6 +1233,15 @@ void PrinceEngine::drawScreen() { showParallax(); + runDrawNodes(); + + freeDrawNodes(); + + if (_mainHero->_visible) { + mainHeroSurface->free(); + delete mainHeroSurface; + } + clsMasks(); playNextFrame(); diff --git a/engines/prince/prince.h b/engines/prince/prince.h index d30b51432d..f888d9bb6b 100644 --- a/engines/prince/prince.h +++ b/engines/prince/prince.h @@ -179,6 +179,19 @@ struct Mask { } }; +struct DrawNode { + int posX; + int posY; + int posZ; + int32 width; + int32 height; + Graphics::Surface *s; + Graphics::Surface *originalRoomSurface; + byte *data; + bool freeSurfaceSMemory; + void (*drawFunction)(Graphics::Surface *, DrawNode *); +}; + struct DebugChannel { enum Type { @@ -250,8 +263,8 @@ public: static const int16 kMaxPicHeight = 480; void checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z); - void insertMasks(const Graphics::Surface *originalRoomSurface); - void showMask(int maskNr, const Graphics::Surface *originalRoomSurface); + void insertMasks(Graphics::Surface *originalRoomSurface); + void showMask(int maskNr, Graphics::Surface *originalRoomSurface); void clsMasks(); int testAnimNr; @@ -270,10 +283,13 @@ private: void showBackAnims(); void clearBackAnimList(); bool spriteCheck(int sprWidth, int sprHeight, int destX, int destY); - void showSprite(const Graphics::Surface *spriteSurface, int destX, int destY); - void showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY); + void showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ, bool freeSurfaceMemory); + void showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ, bool freeSurfaceMemory); void showObjects(); void showParallax(); + static bool compareDrawNodes(DrawNode d1, DrawNode d2); + void runDrawNodes(); + void freeDrawNodes(); void makeShadowTable(int brightness); uint32 getTextWidth(const char *s); @@ -305,6 +321,8 @@ private: Common::Array<Object *> _objList; Common::Array<Mask> _maskList; + Common::Array<DrawNode> _drawNodeList; + bool _flicLooped; void mainLoop(); diff --git a/engines/prince/pscr.h b/engines/prince/pscr.h index 3564a571e7..76add9602d 100644 --- a/engines/prince/pscr.h +++ b/engines/prince/pscr.h @@ -41,7 +41,7 @@ public: byte _len; bool loadFromStream(Common::SeekableReadStream &stream); - const Graphics::Surface *getSurface() const { return _surface; } + Graphics::Surface *getSurface() const { return _surface; } private: void loadSurface(Common::SeekableReadStream &stream); Graphics::Surface *_surface; |