aboutsummaryrefslogtreecommitdiff
path: root/queen
diff options
context:
space:
mode:
authorGregory Montoir2003-10-01 20:23:29 +0000
committerGregory Montoir2003-10-01 20:23:29 +0000
commit9c301608daaebab809fcffe900d1e77dca6b519f (patch)
tree7e0fde04969a79cab2d2e77bd1a33ac22e4a5f2f /queen
parente78b1aeb44ea222b0d4f32c404cc4480bad9d51c (diff)
downloadscummvm-rg350-9c301608daaebab809fcffe900d1e77dca6b519f.tar.gz
scummvm-rg350-9c301608daaebab809fcffe900d1e77dca6b519f.tar.bz2
scummvm-rg350-9c301608daaebab809fcffe900d1e77dca6b519f.zip
added Bob functions to Graphics class
svn-id: r10528
Diffstat (limited to 'queen')
-rw-r--r--queen/graphics.cpp419
-rw-r--r--queen/graphics.h105
2 files changed, 503 insertions, 21 deletions
diff --git a/queen/graphics.cpp b/queen/graphics.cpp
index cdf8b48b70..6cf9a82371 100644
--- a/queen/graphics.cpp
+++ b/queen/graphics.cpp
@@ -21,11 +21,14 @@
#include "queen/graphics.h"
+
QueenGraphics::QueenGraphics(QueenResource *resource)
:_resource(resource) {
memset(_frames, 0, sizeof(_frames));
- memset(_banks, 0, sizeof(_banks));
+ memset(_banks, 0, sizeof(_banks));
+ memset(_sortedBobs, 0, sizeof(_sortedBobs));
+
}
@@ -56,25 +59,27 @@ void QueenGraphics::bankLoad(const char *bankname, uint32 bankslot) {
debug(5, "Loaded bank '%s' in slot %d, %d entries", bankname, bankslot, entries);
}
+
void QueenGraphics::bankUnpack(uint32 srcframe, uint32 dstframe, uint32 bankslot) {
uint8 *p = _banks[bankslot].data + _banks[bankslot].indexes[srcframe];
- ObjectFrame *pof = &_frames[dstframe];
- delete[] pof->data;
+ BobFrame *pbf = &_frames[dstframe];
+ delete[] pbf->data;
- pof->width = READ_LE_UINT16(p + 0);
- pof->height = READ_LE_UINT16(p + 2);
- pof->xhotspot = READ_LE_UINT16(p + 4);
- pof->yhotspot = READ_LE_UINT16(p + 6);
+ pbf->width = READ_LE_UINT16(p + 0);
+ pbf->height = READ_LE_UINT16(p + 2);
+ pbf->xhotspot = READ_LE_UINT16(p + 4);
+ pbf->yhotspot = READ_LE_UINT16(p + 6);
- uint32 size = pof->width * pof->height;
- pof->data = new uint8[ size ];
- memcpy(pof->data, p, size);
+ uint32 size = pbf->width * pbf->height;
+ pbf->data = new uint8[ size ];
+ memcpy(pbf->data, p, size);
debug(5, "Unpacked frame %d from bank slot %d to frame slot %d", srcframe, bankslot, dstframe);
}
+
void QueenGraphics::bankOverpack(uint32 srcframe, uint32 dstframe, uint32 bankslot) {
uint8 *p = _banks[bankslot].data + _banks[bankslot].indexes[srcframe];
@@ -93,6 +98,7 @@ void QueenGraphics::bankOverpack(uint32 srcframe, uint32 dstframe, uint32 banksl
debug(5, "Overpacked frame %d from bank slot %d to frame slot %d", srcframe, bankslot, dstframe);
}
+
void QueenGraphics::bankErase(uint32 bankslot) {
delete[] _banks[bankslot].data;
@@ -101,3 +107,396 @@ void QueenGraphics::bankErase(uint32 bankslot) {
debug(5, "Erased bank in slot %d", bankslot);
}
+
+void QueenGraphics::bobAnimString(uint32 bobnum, uint8* animBuf) {
+
+ BobSlot *pbs = &_bobs[bobnum];
+ pbs->active = true;
+ pbs->animating = true;
+ pbs->anim.string.buffer = animBuf;
+ pbs->anim.string.curPos = animBuf;
+ pbs->frameNum = READ_LE_UINT16(animBuf);
+ pbs->anim.speed = READ_LE_UINT16(animBuf + 2) / 4;
+}
+
+
+void QueenGraphics::bobAnimNormal(uint32 bobnum, uint16 firstFrame, uint16 lastFrame, uint16 speed, bool rebound, bool xflip) {
+
+ BobSlot *pbs = &_bobs[bobnum];
+ pbs->active = true;
+ pbs->animating = true;
+ pbs->frameNum = firstFrame;
+ pbs->anim.speed = speed;
+ pbs->anim.speedBak = speed;
+ pbs->anim.string.buffer = NULL;
+ pbs->anim.normal.firstFrame = firstFrame;
+ pbs->anim.normal.lastFrame = lastFrame;
+ pbs->anim.normal.rebound = rebound;
+ pbs->frameDir = 1;
+ pbs->xflip = xflip;
+}
+
+
+void QueenGraphics::bobMove(uint32 bobnum, uint16 endx, uint16 endy, int16 speed) {
+
+ BobSlot *pbs = &_bobs[bobnum];
+
+ pbs->active = true;
+ pbs->moving = true;
+
+ pbs->endx = endx;
+ pbs->endy = endy;
+
+ // FIXME: can speed be negative or =0 ? the original sources does the check
+ pbs->speed = (speed < 1) ? 1 : speed;
+
+ int16 dx = endx - pbs->x;
+ if (dx < 0) {
+ pbs->dx = -dx;
+ pbs->xdir = -1;
+ }
+ else {
+ pbs->dx = dx;
+ pbs->xdir = 1;
+ }
+ int16 dy = endy - pbs->y;
+ if (dy < 0) {
+ pbs->dy = -dy;
+ pbs->ydir = -1;
+ }
+ else {
+ pbs->dy = dy;
+ pbs->ydir = 1;
+ }
+
+ if (pbs->dx > pbs->dy) {
+ pbs->total = pbs->dy / 2;
+ pbs->xmajor = true;
+ }
+ else {
+ pbs->total = pbs->dx / 2;
+ pbs->xmajor = false;
+ }
+
+ // move one step along line to avoid glitching
+ pbs->moveOneStep();
+}
+
+
+void BobSlot::moveOneStep() {
+
+ if(xmajor) {
+ if(x == endx) {
+ y = endy;
+ moving = false;
+ }
+ else {
+ x += xdir;
+ total += dy;
+ if(total > dx) {
+ y += ydir;
+ total -= dx;
+ }
+ }
+ }
+ else {
+ if(y == endy) {
+ x = endx;
+ moving = false;
+ }
+ else {
+ y += ydir;
+ total += dx;
+ if(total > dy) {
+ x += xdir;
+ total -= dy;
+ }
+ }
+ }
+}
+
+
+void BobSlot::animOneStep() {
+
+ if (anim.string.buffer != NULL) {
+ --anim.speed;
+ if(anim.speed == 0) {
+ anim.string.curPos += 4;
+ uint16 nextFrame = READ_LE_UINT16(anim.string.curPos);
+ if (nextFrame == 0) {
+ anim.string.curPos = anim.string.buffer;
+ frameNum = READ_LE_UINT16(anim.string.curPos);
+ }
+ else {
+ frameNum = nextFrame;
+ }
+ anim.speed = READ_LE_UINT16(anim.string.curPos + 2) / 4;
+
+ // FIXME: handle that when QueenSound class is ready
+ // play memory sfx and move on to next frame
+ if(frameNum > 500) {
+ frameNum -= 500;
+ // _sound->sfxplay(NULLstr);
+ }
+ }
+ }
+ else {
+ // normal looping animation
+ --anim.speed;
+ if(anim.speed == 0) {
+ anim.speed = anim.speedBak;
+
+ uint16 nextFrame = frameNum + frameDir;
+ if (nextFrame > anim.normal.lastFrame || nextFrame < anim.normal.firstFrame) {
+ if (anim.normal.rebound) {
+ frameDir *= -1;
+ }
+ else {
+ frameNum = anim.normal.lastFrame - 1;
+ }
+ frameNum += frameDir;
+ }
+ }
+ }
+}
+
+
+void QueenGraphics::bobDraw(uint32 bobnum, uint16 x, uint16 y, uint16 scale, bool xflip, const Box& box) {
+
+ uint16 w, h;
+ uint8 *src;
+
+ BobFrame *pbf = &_frames[bobnum];
+ if(scale >= 0 && scale < 100) {
+ bobShrink(pbf, scale);
+ src = _shrinkBuffer.data;
+ w = _shrinkBuffer.width;
+ h = _shrinkBuffer.height;
+ }
+ else {
+ src = pbf->data;
+ w = pbf->width;
+ h = pbf->height;
+ }
+
+ if(w != 0 && h != 0 && box.intersects(x, y, w, h)) {
+
+ uint16 x_skip = 0;
+ uint16 y_skip = 0;
+ uint16 w_new = w;
+ uint16 h_new = h;
+
+ // compute bounding box intersection with frame
+ if (x < box.x1) {
+ x_skip = box.x1 - x;
+ w_new -= x_skip;
+ x = box.x1;
+ }
+
+ if (y < box.y1) {
+ y_skip = box.y1 - y;
+ h_new -= y_skip;
+ y = box.y1;
+ }
+
+ if (x + w_new > box.x2 + 1) {
+ w_new = box.x2 - x + 1;
+ }
+
+ if (y + h_new > box.y2 + 1) {
+ h_new = box.y2 - y + 1;
+ }
+
+ uint16 j;
+ for (j = 0; j < h_new; ++j) {
+ memset(_ulines[y + j], 2, w_new / 16);
+ }
+
+ src += w * y_skip;
+ if (!xflip) {
+ src += x_skip;
+// _display->blit(hidden, x, y, 320, src, w_new, h_new, w, xflip, true);
+ }
+ else {
+ src += w - w_new - x_skip;
+ x += w_new - 1;
+// _display->blit(hidden, x, y, 320, src, x_new, h_new, w, xflip, true);
+ }
+ }
+
+}
+
+
+void QueenGraphics::bobDrawInventoryItem(uint32 bobnum, uint16 x, uint16 y) {
+ if (bobnum == 0) {
+ // clear panel area
+ uint8 *p = _panel + y * 320 + x;
+ for(uint32 j = 0; j < 32; ++j) {
+ for(uint32 i = 0; i < 32; ++i) {
+ *p++ = INK_BG_PANEL;
+ }
+ p += 320 - 32;
+ }
+ }
+ else {
+ BobFrame *pbf = &_frames[bobnum];
+// _display->blit(panel, x, y, 320, pbf->data, pbf->width, pbf->height, false, false);
+ }
+}
+
+
+void QueenGraphics::bobPaste(uint32 bobnum, uint16 x, uint16 y) {
+
+ BobFrame *pbf = &_frames[bobnum];
+// _display->blit(backdrop, x, y, 640, pbf->data, pbf->width, pbf->height, pbf->width, false, true);
+ frameErase(bobnum);
+}
+
+
+void QueenGraphics::bobShrink(const BobFrame* pbf, uint16 percentage) {
+
+ // computing new size, rounding to upper value
+ uint16 new_w = (pbf->width * percentage + 50) / 100;
+ uint16 new_h = (pbf->height * percentage + 50) / 100;
+
+ if (new_w != 0 && new_h != 0) {
+
+ _shrinkBuffer.width = new_w;
+ _shrinkBuffer.height = new_h;
+
+ uint32 shrinker = (100 << 0x10) / percentage;
+ uint16 x_scale = shrinker >> 0x10;
+ uint16 y_scale = x_scale * pbf->width;
+ shrinker &= 0xFFFF;
+
+ uint8* src = pbf->data;
+ uint8* dst = _shrinkBuffer.data;
+
+ for (uint32 y_count = 0; new_h != 0; --new_h) {
+
+ uint8 *p = src;
+ for (uint32 x_count = 0; new_w != 0; --new_w) {
+ *dst++ = *p;
+ p += x_scale;
+ x_count += shrinker;
+ if (x_count > 0xFFFF) {
+ ++p;
+ x_count &= 0xFFFF;
+ }
+ }
+
+ src += y_scale;
+ y_count += shrinker;
+ if (y_count > 0xFFFF) {
+ src += pbf->width;
+ y_count &= 0xFFFF;
+ }
+ }
+ }
+}
+
+
+void QueenGraphics::bobClear(uint32 bobnum) {
+
+ BobSlot *pbs = &_bobs[bobnum];
+
+ pbs->active = 0;
+ pbs->xflip = false;
+ pbs->anim.string.buffer = NULL;
+ pbs->moving = false;
+ pbs->scale = 100;
+ pbs->box.x1 = 0;
+ pbs->box.y1 = 0;
+ pbs->box.y1 = 319;
+ pbs->box.y2 = (bobnum == 16) ? 199 : 149; // FIXME: does bob number 16 really used ?
+}
+
+
+void QueenGraphics::bobSortAll() {
+
+ int32 _sorted = 0;
+
+ // animate/move the bobs
+ for (int32 i = 0; i < ARRAYSIZE(_bobs); ++i) {
+
+ BobSlot *pbs = &_bobs[i];
+ if (pbs->active) {
+ _sortedBobs[_sorted] = pbs;
+ ++_sorted;
+
+ if (pbs->animating) {
+ pbs->animOneStep();
+ }
+ if (pbs->moving) {
+ for (uint32 j = 0; pbs->moving && j < pbs->speed; ++j) {
+ pbs->moveOneStep();
+ }
+ }
+ }
+ }
+
+ _sortedBobs[_sorted] = 0;
+
+ // bubble sort the bobs
+ for (int32 index = 0; index < _sorted - 1; ++index) {
+ int32 smallest = index;
+ for (int32 compare = index + 1; compare <= _sorted - 1; ++compare) {
+ if (_sortedBobs[compare]->y < _sortedBobs[compare]->y) {
+ smallest = compare;
+ }
+ }
+ if (index != smallest) {
+ SWAP(_sortedBobs[index], _sortedBobs[smallest]);
+ }
+ }
+
+}
+
+
+void QueenGraphics::bobDrawAll() {
+
+ for (BobSlot *pbs = _sortedBobs[0]; pbs; ++pbs) {
+ if (pbs->active) {
+
+ BobFrame *pbf = &_frames[ pbs->frameNum ];
+ uint16 xh, yh, x, y;
+
+ xh = pbf->xhotspot;
+ yh = pbf->yhotspot;
+
+ if (pbs->xflip) {
+ xh = pbf->width - xh;
+ }
+
+ // adjusts hot spots when object is scaled
+ if (pbs->scale != 100) {
+ xh = (xh * pbs->scale) / 100;
+ yh = (yh * pbs->scale) / 100;
+ }
+
+ // adjusts position to hot-spot and screen scroll
+ x = pbs->x - xh; // - _display->scrollx;
+ y = pbs->y - yh;
+
+ bobDraw(pbs->frameNum, x, y, pbs->scale, pbs->xflip, pbs->box);
+ }
+ }
+}
+
+
+void QueenGraphics::bobClearAll() {
+
+ for(int32 i = 0; i < ARRAYSIZE(_bobs); ++i) {
+ bobClear(i);
+ }
+}
+
+
+void QueenGraphics::frameErase(uint32 fslot) {
+
+ BobFrame *pbf = &_frames[fslot];
+ pbf->width = 0;
+ pbf->height = 0;
+ delete[] pbf->data;
+
+}
diff --git a/queen/graphics.h b/queen/graphics.h
index 0cd8ea95fb..7091224878 100644
--- a/queen/graphics.h
+++ b/queen/graphics.h
@@ -28,12 +28,69 @@
#define MAX_BANK_SIZE 110
#define MAX_FRAMES_NUMBER 256
#define MAX_BANKS_NUMBER 18
+#define MAX_BOBS_NUMBER 64
-struct ObjectFrame {
- uint16 width, height;
- uint16 xhotspot, yhotspot;
- uint8 *data;
+struct BobFrame {
+ uint16 width, height;
+ uint16 xhotspot, yhotspot;
+ uint8 *data;
+};
+
+// FIXME: share that with logic.h (ObjectData) ?
+struct Box {
+ uint16 x1, y1, x2, y2;
+
+ bool intersects(uint16 x, uint16 y, uint16 w, uint16 h) const {
+ return (x + w > x1) && (y + h > y1) && (x <= x2) && (y <= y2);
+ }
+};
+
+
+struct BobSlot {
+ bool active;
+ uint16 x, y; //! current position
+ Box box; //! bounding box
+ bool xflip;
+ uint16 scale; //! shrinking percentage
+ uint16 frameNum; //! associated BobFrame
+ uint8 frameDir; //! 'direction' for the next frame (-1, 1)
+
+ //! animation stuff
+ bool animating;
+ struct {
+ uint16 speed, speedBak;
+
+ //! string based animation
+ struct {
+ uint8* buffer;
+ uint8* curPos;
+ } string;
+
+ //! normal moving animation
+ struct {
+ bool rebound;
+ uint16 firstFrame, lastFrame;
+ } normal;
+
+ } anim;
+
+ bool moving;
+ uint16 speed; //! moving speed
+ bool xmajor; //! move along x axis instead of y
+ int8 xdir, ydir; //! moving direction
+ uint16 endx, endy; //! destination point
+ uint16 dx, dy;
+ uint16 total;
+
+ void moveOneStep();
+ void animOneStep();
+};
+
+
+//! Inks indexes
+enum {
+ INK_BG_PANEL = 0xE2
};
@@ -42,11 +99,26 @@ public:
QueenGraphics(QueenResource *resource);
- void bankLoad(const char *bankname, uint32 bankslot);
- void bankUnpack(uint32 srcframe, uint32 dstframe, uint32 bankslot);
- void bankOverpack(uint32 srcframe, uint32 dstframe, uint32 bankslot);
- void bankErase(uint32 bankslot);
-
+ void bankLoad(const char *bankname, uint32 bankslot); // loadbank()
+ void bankUnpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); // unpackbank()
+ void bankOverpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); // overpackbank()
+ void bankErase(uint32 bankslot); // erase()
+
+ void bobAnimString(uint32 bobnum, uint8* animBuf); // stringanim()
+ void bobAnimNormal(uint32 bobnum, uint16 firstFrame, uint16 lastFrame, uint16 speed, bool rebound, bool xflip); // makeanim()
+ void bobMove(uint32 bobnum, uint16 endx, uint16 endy, int16 speed); // movebob()
+ void bobDraw(uint32 bobnum, uint16 x, uint16 y, uint16 scale, bool xflip, const Box& box); // bob()
+ void bobDrawInventoryItem(uint32 bobnum, uint16 x, uint16 y); // invbob()
+ void bobPaste(uint32 bobnum, uint16 x, uint16 y); // bobpaste()
+ void bobShrink(const BobFrame* pbf, uint16 percentage); // shrinkbob()
+ void bobClear(uint32 bobnum); // clearbob()
+ void bobSortAll(); // sortbobs()
+ void bobDrawAll(); // drawbobs()
+ void bobClearAll(); // clearallbobs()
+
+ void frameErase(uint32 fslot);
+
+
private:
struct PackedBank {
@@ -54,8 +126,19 @@ private:
uint8 *data;
};
- ObjectFrame _frames[MAX_FRAMES_NUMBER];
- PackedBank _banks[MAX_BANKS_NUMBER];
+ struct ShrunkBobFrame {
+ uint16 width;
+ uint16 height;
+ uint8 data[60000]; // FIXME: original buffer size, maybe it can be smaller
+ };
+
+ BobFrame _frames[MAX_FRAMES_NUMBER]; //! unbanked bob frames
+ PackedBank _banks[MAX_BANKS_NUMBER]; //! banked bob frames
+ BobSlot _bobs[MAX_BOBS_NUMBER];
+ BobSlot* _sortedBobs[MAX_BOBS_NUMBER + 1]; //! bobs displayed
+ ShrunkBobFrame _shrinkBuffer;
+ uint8 _ulines[201][20];
+ uint8 _panel[320 * 50]; // FIXME: rather in QueenDisplay ?
QueenResource *_resource;