aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/prince/graphics.cpp55
-rw-r--r--engines/prince/graphics.h11
-rw-r--r--engines/prince/hero.cpp3
-rw-r--r--engines/prince/hero.h1
-rw-r--r--engines/prince/object.h2
-rw-r--r--engines/prince/prince.cpp169
-rw-r--r--engines/prince/prince.h26
-rw-r--r--engines/prince/pscr.h2
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;