diff options
Diffstat (limited to 'engines/parallaction/graphics.cpp')
| -rw-r--r-- | engines/parallaction/graphics.cpp | 784 |
1 files changed, 228 insertions, 556 deletions
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index 58fb02a750..c19d6ae5e5 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -33,6 +33,11 @@ namespace Parallaction { +// this is the size of the receiving buffer for unpacked frames, +// since BRA uses some insanely big animations. +#define MAXIMUM_UNPACKED_BITMAP_SIZE 640*401 + + void Gfx::registerVar(const Common::String &name, int32 initialValue) { if (_vars.contains(name)) { warning("Variable '%s' already registered, ignoring initial value.\n", name.c_str()); @@ -64,10 +69,6 @@ int32 Gfx::getVar(const Common::String &name) { #define LABEL_TRANSPARENT_COLOR 0xFF -#define BALLOON_TRANSPARENT_COLOR 2 - - -int16 Gfx::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 }; void halfbritePixel(int x, int y, int color, void *data) { byte *buffer = (byte*)data; @@ -152,6 +153,13 @@ void Palette::setEntry(uint index, int red, int green, int blue) { _data[index*3+2] = blue & 0xFF; } +void Palette::getEntry(uint index, int &red, int &green, int &blue) { + assert(index < _colors); + red = _data[index*3]; + green = _data[index*3+1]; + blue = _data[index*3+2]; +} + void Palette::makeGrayscale() { byte v; for (uint16 i = 0; i < _colors; i++) { @@ -238,37 +246,6 @@ void Palette::rotate(uint first, uint last, bool forward) { } -#define BALLOON_TAIL_WIDTH 12 -#define BALLOON_TAIL_HEIGHT 10 - - -byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = { - { - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - }, - { - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02 - } -}; - void Gfx::setPalette(Palette pal) { byte sysPal[256*4]; @@ -292,7 +269,7 @@ void Gfx::animatePalette() { PaletteFxRange *range; for (uint16 i = 0; i < 4; i++) { - range = &_backgroundInfo.ranges[i]; + range = &_backgroundInfo->ranges[i]; if ((range->_flags & 1) == 0) continue; // animated palette range->_timer += range->_step * 2; // update timer @@ -337,10 +314,14 @@ void Gfx::setProjectorProgram(int16 *data) { } void Gfx::drawInventory() { - +/* if ((_engineFlags & kEngineInventory) == 0) { return; } +*/ + if (_vm->_input->_inputMode != Input::kInputModeInventory) { + return; + } Common::Rect r; _vm->_inventoryRenderer->getRect(r); @@ -356,21 +337,19 @@ void Gfx::drawItems() { Graphics::Surface *surf = g_system->lockScreen(); for (uint i = 0; i < _numItems; i++) { - blt(_items[i].rect, _items[i].data->getData(_items[i].frame), surf, LAYER_FOREGROUND, _items[i].transparentColor); + drawGfxObject(_items[i].data, *surf, false); } g_system->unlockScreen(); } void Gfx::drawBalloons() { - if (_numBalloons == 0) { + if (_balloons.size() == 0) { return; } Graphics::Surface *surf = g_system->lockScreen(); - for (uint i = 0; i < _numBalloons; i++) { - Common::Rect r(_balloons[i].surface.w, _balloons[i].surface.h); - r.moveTo(_balloons[i].x, _balloons[i].y); - blt(r, (byte*)_balloons[i].surface.getBasePtr(0, 0), surf, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR); + for (uint i = 0; i < _balloons.size(); i++) { + drawGfxObject(_balloons[i], *surf, false); } g_system->unlockScreen(); } @@ -380,29 +359,37 @@ void Gfx::clearScreen() { } void Gfx::beginFrame() { - - int32 oldBackgroundMode = _varBackgroundMode; - _varBackgroundMode = getVar("background_mode"); - - if (oldBackgroundMode != _varBackgroundMode) { - switch (_varBackgroundMode) { - case 1: - _bitmapMask.free(); - break; - case 2: - _bitmapMask.create(_backgroundInfo.width, _backgroundInfo.height, 1); - byte *data = (byte*)_bitmapMask.pixels; - for (uint y = 0; y < _bitmapMask.h; y++) { - for (uint x = 0; x < _bitmapMask.w; x++) { - *data++ = _backgroundInfo.mask.getValue(x, y); + _skipBackground = (_backgroundInfo->bg.pixels == 0); // don't render frame if background is missing + + if (!_skipBackground) { + int32 oldBackgroundMode = _varBackgroundMode; + _varBackgroundMode = getVar("background_mode"); + if (oldBackgroundMode != _varBackgroundMode) { + switch (_varBackgroundMode) { + case 1: + _bitmapMask.free(); + break; + case 2: + _bitmapMask.create(_backgroundInfo->width, _backgroundInfo->height, 1); + byte *data = (byte*)_bitmapMask.pixels; + for (uint y = 0; y < _bitmapMask.h; y++) { + for (uint x = 0; x < _bitmapMask.w; x++) { + *data++ = _backgroundInfo->mask.getValue(x, y); + } } + break; } - break; } } + _varDrawPathZones = getVar("draw_path_zones"); + if (_varDrawPathZones == 1 && _vm->getGameType() != GType_BRA) { + setVar("draw_path_zones", 0); + _varDrawPathZones = 0; + warning("Path zones are supported only in Big Red Adventure"); + } - if (_vm->_screenWidth >= _backgroundInfo.width) { + if (_skipBackground || (_vm->_screenWidth >= _backgroundInfo->width)) { _varScrollX = 0; } else { _varScrollX = getVar("scroll_x"); @@ -427,24 +414,38 @@ int32 Gfx::getRenderMode(const char *type) { void Gfx::updateScreen() { - // background may not cover the whole screen, so adjust bulk update size - uint w = MIN(_vm->_screenWidth, (int32)_backgroundInfo.width); - uint h = MIN(_vm->_screenHeight, (int32)_backgroundInfo.height); - - byte *backgroundData = 0; - uint16 backgroundPitch = 0; - switch (_varBackgroundMode) { - case 1: - backgroundData = (byte*)_backgroundInfo.bg.getBasePtr(_varScrollX, 0); - backgroundPitch = _backgroundInfo.bg.pitch; - break; - case 2: - backgroundData = (byte*)_bitmapMask.getBasePtr(_varScrollX, 0); - backgroundPitch = _bitmapMask.pitch; - break; + if (!_skipBackground) { + // background may not cover the whole screen, so adjust bulk update size + uint w = MIN(_vm->_screenWidth, (int32)_backgroundInfo->width); + uint h = MIN(_vm->_screenHeight, (int32)_backgroundInfo->height); + + byte *backgroundData = 0; + uint16 backgroundPitch = 0; + switch (_varBackgroundMode) { + case 1: + backgroundData = (byte*)_backgroundInfo->bg.getBasePtr(_varScrollX, 0); + backgroundPitch = _backgroundInfo->bg.pitch; + break; + case 2: + backgroundData = (byte*)_bitmapMask.getBasePtr(_varScrollX, 0); + backgroundPitch = _bitmapMask.pitch; + break; + } + g_system->copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo->x, _backgroundInfo->y, w, h); } - g_system->copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo.x, _backgroundInfo.y, w, h); + if (_varDrawPathZones == 1) { + Graphics::Surface *surf = g_system->lockScreen(); + ZoneList::iterator b = _vm->_location._zones.begin(); + ZoneList::iterator e = _vm->_location._zones.end(); + for (; b != e; b++) { + ZonePtr z = *b; + if (z->_type & kZonePath) { + surf->frameRect(Common::Rect(z->_left, z->_top, z->_right, z->_bottom), 2); + } + } + g_system->unlockScreen(); + } _varRenderMode = _varAnimRenderMode; @@ -498,17 +499,17 @@ void Gfx::patchBackground(Graphics::Surface &surf, int16 x, int16 y, bool mask) Common::Rect r(surf.w, surf.h); r.moveTo(x, y); - uint16 z = (mask) ? _backgroundInfo.getLayer(y) : LAYER_FOREGROUND; - blt(r, (byte*)surf.pixels, &_backgroundInfo.bg, z, 0); + uint16 z = (mask) ? _backgroundInfo->getLayer(y) : LAYER_FOREGROUND; + blt(r, (byte*)surf.pixels, &_backgroundInfo->bg, z, 0); } void Gfx::fillBackground(const Common::Rect& r, byte color) { - _backgroundInfo.bg.fillRect(r, color); + _backgroundInfo->bg.fillRect(r, color); } void Gfx::invertBackground(const Common::Rect& r) { - byte *d = (byte*)_backgroundInfo.bg.getBasePtr(r.left, r.top); + byte *d = (byte*)_backgroundInfo->bg.getBasePtr(r.left, r.top); for (int i = 0; i < r.height(); i++) { for (int j = 0; j < r.width(); j++) { @@ -516,146 +517,7 @@ void Gfx::invertBackground(const Common::Rect& r) { d++; } - d += (_backgroundInfo.bg.pitch - r.width()); - } - -} - -// this is the maximum size of an unpacked frame in BRA -byte _unpackedBitmap[640*401]; - -#if 0 -void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) { - - byte *d = _unpackedBitmap; - - while (size > 0) { - - uint8 p = *data++; - size--; - uint8 color = p & 0xF; - uint8 repeat = (p & 0xF0) >> 4; - if (repeat == 0) { - repeat = *data++; - size--; - } - - memset(d, color, repeat); - d += repeat; - } - - blt(r, _unpackedBitmap, surf, z, transparentColor); -} -#endif -void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) { - - byte *d = _unpackedBitmap; - uint pixelsLeftInLine = r.width(); - - while (size > 0) { - uint8 p = *data++; - size--; - uint8 color = p & 0xF; - uint8 repeat = (p & 0xF0) >> 4; - if (repeat == 0) { - repeat = *data++; - size--; - } - if (repeat == 0) { - // end of line - repeat = pixelsLeftInLine; - pixelsLeftInLine = r.width(); - } else { - pixelsLeftInLine -= repeat; - } - - memset(d, color, repeat); - d += repeat; - } - - blt(r, _unpackedBitmap, surf, z, transparentColor); -} - - -void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) { - - Common::Point dp; - Common::Rect q(r); - - Common::Rect clipper(surf->w, surf->h); - - q.clip(clipper); - if (!q.isValidRect()) return; - - dp.x = q.left; - dp.y = q.top; - - q.translate(-r.left, -r.top); - - byte *s = data + q.left + q.top * r.width(); - byte *d = (byte*)surf->getBasePtr(dp.x, dp.y); - - uint sPitch = r.width() - q.width(); - uint dPitch = surf->w - q.width(); - - - if (_varRenderMode == 2) { - - for (uint16 i = 0; i < q.height(); i++) { - - for (uint16 j = 0; j < q.width(); j++) { - if (*s != transparentColor) { - if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) { - byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i); - if (z >= v) *d = 5; - } else { - *d = 5; - } - } - - s++; - d++; - } - - s += sPitch; - d += dPitch; - } - - } else { - if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) { - - for (uint16 i = 0; i < q.height(); i++) { - - for (uint16 j = 0; j < q.width(); j++) { - if (*s != transparentColor) { - byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i); - if (z >= v) *d = *s; - } - - s++; - d++; - } - - s += sPitch; - d += dPitch; - } - - } else { - - for (uint16 i = q.top; i < q.bottom; i++) { - for (uint16 j = q.left; j < q.right; j++) { - if (*s != transparentColor) - *d = *s; - - s++; - d++; - } - - s += sPitch; - d += dPitch; - } - - } + d += (_backgroundInfo->bg.pitch - r.width()); } } @@ -669,10 +531,9 @@ void setupLabelSurface(Graphics::Surface &surf, uint w, uint h) { surf.fillRect(Common::Rect(w,h), LABEL_TRANSPARENT_COLOR); } -Label *Gfx::renderFloatingLabel(Font *font, char *text) { +uint Gfx::renderFloatingLabel(Font *font, char *text) { - Label *label = new Label; - Graphics::Surface *cnv = &label->_cnv; + Graphics::Surface *cnv = new Graphics::Surface; uint w, h; @@ -698,80 +559,38 @@ Label *Gfx::renderFloatingLabel(Font *font, char *text) { drawText(font, cnv, 0, 0, text, 0); } - return label; -} + GfxObj *obj = new GfxObj(kGfxObjTypeLabel, new SurfaceToFrames(cnv), "floatingLabel"); + obj->transparentKey = LABEL_TRANSPARENT_COLOR; + obj->layer = LAYER_FOREGROUND; -uint Gfx::createLabel(Font *font, const char *text, byte color) { - assert(_numLabels < MAX_NUM_LABELS); - - Label *label = new Label; - Graphics::Surface *cnv = &label->_cnv; - - uint w, h; - - if (_vm->getPlatform() == Common::kPlatformAmiga) { - w = font->getStringWidth(text) + 2; - h = font->height() + 2; - - setupLabelSurface(*cnv, w, h); - - drawText(font, cnv, 0, 2, text, 0); - drawText(font, cnv, 2, 0, text, color); - } else { - w = font->getStringWidth(text); - h = font->height(); - - setupLabelSurface(*cnv, w, h); - - drawText(font, cnv, 0, 0, text, color); - } - - uint id = _numLabels; - _labels[id] = label; - _numLabels++; + uint id = _labels.size(); + _labels.insert_at(id, obj); return id; } -void Gfx::showLabel(uint id, int16 x, int16 y) { - assert(id < _numLabels); - _labels[id]->_visible = true; +void Gfx::showFloatingLabel(uint label) { + assert(label < _labels.size()); - if (x == CENTER_LABEL_HORIZONTAL) { - x = CLIP<int16>((_vm->_screenWidth - _labels[id]->_cnv.w) / 2, 0, _vm->_screenWidth/2); - } - - if (y == CENTER_LABEL_VERTICAL) { - y = CLIP<int16>((_vm->_screenHeight - _labels[id]->_cnv.h) / 2, 0, _vm->_screenHeight/2); - } + hideFloatingLabel(); - _labels[id]->_pos.x = x; - _labels[id]->_pos.y = y; -} + _labels[label]->x = -1000; + _labels[label]->y = -1000; + _labels[label]->setFlags(kGfxObjVisible); -void Gfx::hideLabel(uint id) { - assert(id < _numLabels); - _labels[id]->_visible = false; + _floatingLabel = label; } -void Gfx::freeLabels() { - for (uint i = 0; i < _numLabels; i++) { - delete _labels[i]; +void Gfx::hideFloatingLabel() { + if (_floatingLabel != NO_FLOATING_LABEL) { + _labels[_floatingLabel]->clearFlags(kGfxObjVisible); } - _numLabels = 0; + _floatingLabel = NO_FLOATING_LABEL; } -void Gfx::setFloatingLabel(Label *label) { - _floatingLabel = label; - - if (_floatingLabel) { - _floatingLabel->resetPosition(); - } -} - void Gfx::updateFloatingLabel() { - if (!_floatingLabel) { + if (_floatingLabel == NO_FLOATING_LABEL) { return; } @@ -780,113 +599,115 @@ void Gfx::updateFloatingLabel() { Common::Point cursor; _vm->_input->getCursorPos(cursor); + Common::Rect r; + _labels[_floatingLabel]->getRect(0, r); + if (_vm->_input->_activeItem._id != 0) { - _si = cursor.x + 16 - _floatingLabel->_cnv.w/2; + _si = cursor.x + 16 - r.width()/2; _di = cursor.y + 34; } else { - _si = cursor.x + 8 - _floatingLabel->_cnv.w/2; + _si = cursor.x + 8 - r.width()/2; _di = cursor.y + 21; } if (_si < 0) _si = 0; if (_di > 190) _di = 190; - if (_floatingLabel->_cnv.w + _si > _vm->_screenWidth) - _si = _vm->_screenWidth - _floatingLabel->_cnv.w; + if (r.width() + _si > _vm->_screenWidth) + _si = _vm->_screenWidth - r.width(); - _floatingLabel->_pos.x = _si; - _floatingLabel->_pos.y = _di; + _labels[_floatingLabel]->x = _si; + _labels[_floatingLabel]->y = _di; } -void Gfx::drawLabels() { - if ((!_floatingLabel) && (_numLabels == 0)) { - return; - } - updateFloatingLabel(); - Graphics::Surface* surf = g_system->lockScreen(); - for (uint i = 0; i < _numLabels; i++) { - if (_labels[i]->_visible) { - Common::Rect r(_labels[i]->_cnv.w, _labels[i]->_cnv.h); - r.moveTo(_labels[i]->_pos); - blt(r, (byte*)_labels[i]->_cnv.getBasePtr(0, 0), surf, LAYER_FOREGROUND, LABEL_TRANSPARENT_COLOR); - } - } - if (_floatingLabel) { - Common::Rect r(_floatingLabel->_cnv.w, _floatingLabel->_cnv.h); - r.moveTo(_floatingLabel->_pos); - blt(r, (byte*)_floatingLabel->_cnv.getBasePtr(0, 0), surf, LAYER_FOREGROUND, LABEL_TRANSPARENT_COLOR); - } +uint Gfx::createLabel(Font *font, const char *text, byte color) { + assert(_labels.size() < MAX_NUM_LABELS); - g_system->unlockScreen(); -} + Graphics::Surface *cnv = new Graphics::Surface; -Label::Label() { - resetPosition(); - _visible = false; -} + uint w, h; -Label::~Label() { - free(); -} + if (_vm->getPlatform() == Common::kPlatformAmiga) { + w = font->getStringWidth(text) + 2; + h = font->height() + 2; -void Label::free() { - _cnv.free(); - resetPosition(); -} + setupLabelSurface(*cnv, w, h); -void Label::resetPosition() { - _pos.x = -1000; - _pos.y = -1000; -} + drawText(font, cnv, 0, 2, text, 0); + drawText(font, cnv, 2, 0, text, color); + } else { + w = font->getStringWidth(text); + h = font->height(); + setupLabelSurface(*cnv, w, h); -void Gfx::getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height) { + drawText(font, cnv, 0, 0, text, color); + } - uint16 lines = 0; - uint16 w = 0; - *width = 0; + GfxObj *obj = new GfxObj(kGfxObjTypeLabel, new SurfaceToFrames(cnv), "label"); + obj->transparentKey = LABEL_TRANSPARENT_COLOR; + obj->layer = LAYER_FOREGROUND; - uint16 blankWidth = font->getStringWidth(" "); - uint16 tokenWidth = 0; + int id = _labels.size(); - char token[MAX_TOKEN_LEN]; + _labels.insert_at(id, obj); - while (strlen(text) != 0) { + return id; +} - text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true); - tokenWidth = font->getStringWidth(token); +void Gfx::showLabel(uint id, int16 x, int16 y) { + assert(id < _labels.size()); + _labels[id]->setFlags(kGfxObjVisible); - w += tokenWidth; + Common::Rect r; + _labels[id]->getRect(0, r); - if (!scumm_stricmp(token, "%p")) { - lines++; - } else { - if (w > maxwidth) { - w -= tokenWidth; - lines++; - if (w > *width) - *width = w; + if (x == CENTER_LABEL_HORIZONTAL) { + x = CLIP<int16>((_vm->_screenWidth - r.width()) / 2, 0, _vm->_screenWidth/2); + } - w = tokenWidth; - } - } + if (y == CENTER_LABEL_VERTICAL) { + y = CLIP<int16>((_vm->_screenHeight - r.height()) / 2, 0, _vm->_screenHeight/2); + } - w += blankWidth; - text = Common::ltrim(text); + _labels[id]->x = x; + _labels[id]->y = y; +} + +void Gfx::hideLabel(uint id) { + assert(id < _labels.size()); + _labels[id]->clearFlags(kGfxObjVisible); +} + +void Gfx::freeLabels() { + for (uint i = 0; i < _labels.size(); i++) { + delete _labels[i]; } + _labels.clear(); + _floatingLabel = NO_FLOATING_LABEL; +} - if (*width < w) *width = w; - *width += 10; +void Gfx::drawLabels() { + if (_labels.size() == 0) { + return; + } - *height = lines * 10 + 20; + updateFloatingLabel(); - return; + Graphics::Surface* surf = g_system->lockScreen(); + + for (uint i = 0; i < _labels.size(); i++) { + drawGfxObject(_labels[i], *surf, false); + } + + g_system->unlockScreen(); } + void Gfx::copyRect(const Common::Rect &r, Graphics::Surface &src, Graphics::Surface &dst) { byte *s = (byte*)src.getBasePtr(r.left, r.top); @@ -903,7 +724,7 @@ void Gfx::copyRect(const Common::Rect &r, Graphics::Surface &src, Graphics::Surf } void Gfx::grabBackground(const Common::Rect& r, Graphics::Surface &dst) { - copyRect(r, _backgroundInfo.bg, dst); + copyRect(r, _backgroundInfo->bg, dst); } @@ -917,17 +738,20 @@ Gfx::Gfx(Parallaction* vm) : setPalette(_palette); - _numBalloons = 0; _numItems = 0; - _numLabels = 0; - _floatingLabel = 0; + _floatingLabel = NO_FLOATING_LABEL; _screenX = 0; _screenY = 0; + _backgroundInfo = 0; + _halfbrite = false; _hbCircleRadius = 0; + _unpackedBitmap = new byte[MAXIMUM_UNPACKED_BITMAP_SIZE]; + assert(_unpackedBitmap); + registerVar("background_mode", 1); _varBackgroundMode = 1; @@ -937,26 +761,39 @@ Gfx::Gfx(Parallaction* vm) : registerVar("anim_render_mode", 1); registerVar("misc_render_mode", 1); + registerVar("draw_path_zones", 0); + + if ((_vm->getGameType() == GType_BRA) && (_vm->getPlatform() == Common::kPlatformPC)) { + // this loads the backup palette needed by the PC version of BRA (see setBackground()). + BackgroundInfo paletteInfo; + _disk->loadSlide(paletteInfo, "pointer"); + _backupPal.clone(paletteInfo.palette); + } + return; } Gfx::~Gfx() { - freeBackground(); + delete _backgroundInfo; + + freeLabels(); + + delete []_unpackedBitmap; return; } -int Gfx::setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor) { +int Gfx::setItem(GfxObj* frames, uint16 x, uint16 y, byte transparentColor) { int id = _numItems; _items[id].data = frames; - _items[id].x = x; - _items[id].y = y; - - _items[id].transparentColor = transparentColor; + _items[id].data->x = x; + _items[id].data->y = y; + _items[id].data->layer = LAYER_FOREGROUND; + _items[id].data->transparentKey = transparentColor; _numItems++; @@ -965,223 +802,58 @@ int Gfx::setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor) { void Gfx::setItemFrame(uint item, uint16 f) { assert(item < _numItems); - _items[item].frame = f; - _items[item].data->getRect(f, _items[item].rect); - _items[item].rect.moveTo(_items[item].x, _items[item].y); -} - -Gfx::Balloon* Gfx::getBalloon(uint id) { - assert(id < _numBalloons); - return &_balloons[id]; -} - -int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) { - assert(_numBalloons < 5); - - int id = _numBalloons; - - Gfx::Balloon *balloon = &_balloons[id]; - - int16 real_h = (winding == -1) ? h : h + 9; - balloon->surface.create(w, real_h, 1); - balloon->surface.fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR); - - Common::Rect r(w, h); - balloon->surface.fillRect(r, 0); - balloon->outerBox = r; - - r.grow(-borderThickness); - balloon->surface.fillRect(r, 1); - balloon->innerBox = r; - - if (winding != -1) { - // draws tail - // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill. - winding = (winding == 0 ? 1 : 0); - Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT); - s.moveTo(r.width()/2 - 5, r.bottom - 1); - blt(s, _resBalloonTail[winding], &balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR); - } - - _numBalloons++; - - return id; -} - -int Gfx::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) { - - int16 w, h; - - getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); - - int id = createBalloon(w+5, h, winding, 1); - Gfx::Balloon *balloon = &_balloons[id]; - - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH); - - balloon->x = x; - balloon->y = y; - - return id; -} - -int Gfx::setDialogueBalloon(char *text, uint16 winding, byte textColor) { - - int16 w, h; - - getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); - - int id = createBalloon(w+5, h, winding, 1); - Gfx::Balloon *balloon = &_balloons[id]; - - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH); - - balloon->x = _dialogueBalloonX[id]; - balloon->y = 10; - - if (id > 0) { - balloon->y += _balloons[id - 1].y + _balloons[id - 1].outerBox.height(); - } - - - return id; + _items[item].data->frame = f; + _items[item].data->setFlags(kGfxObjVisible); } -void Gfx::setBalloonText(uint id, char *text, byte textColor) { - Gfx::Balloon *balloon = getBalloon(id); - balloon->surface.fillRect(balloon->innerBox, 1); - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH); -} +GfxObj* Gfx::registerBalloon(Frames *frames, const char *text) { -int Gfx::setLocationBalloon(char *text, bool endGame) { + GfxObj *obj = new GfxObj(kGfxObjTypeBalloon, frames, text); - int16 w, h; + obj->layer = LAYER_FOREGROUND; + obj->frame = 0; + obj->setFlags(kGfxObjVisible); - getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h); + _balloons.push_back(obj); - int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR); - Gfx::Balloon *balloon = &_balloons[id]; - drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, 0, MAX_BALLOON_WIDTH); - - balloon->x = 5; - balloon->y = 5; - - return id; + return obj; } -int Gfx::hitTestDialogueBalloon(int x, int y) { - - Common::Point p; - - for (uint i = 0; i < _numBalloons; i++) { - p.x = x - _balloons[i].x; - p.y = y - _balloons[i].y; - - if (_balloons[i].innerBox.contains(p)) - return i; +void Gfx::destroyBalloons() { + for (uint i = 0; i < _balloons.size(); i++) { + delete _balloons[i]; } - - return -1; -} - - -void Gfx::freeBalloons() { - for (uint i = 0; i < _numBalloons; i++) { - _balloons[i].surface.free(); - } - _numBalloons = 0; + _balloons.clear(); } void Gfx::freeItems() { _numItems = 0; } -void Gfx::hideDialogueStuff() { - freeItems(); - freeBalloons(); -} - -void Gfx::drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color) { - byte *dst = (byte*)surf->getBasePtr(x, y); - font->setColor(color); - font->drawString(dst, surf->w, text); -} - -void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) { - - uint16 lines = 0; - uint16 linewidth = 0; - - uint16 rx = 10; - uint16 ry = 4; - - uint16 blankWidth = font->getStringWidth(" "); - uint16 tokenWidth = 0; - - char token[MAX_TOKEN_LEN]; - - if (wrapwidth == -1) - wrapwidth = _vm->_screenWidth; - - while (strlen(text) > 0) { - - text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true); - - if (!scumm_stricmp(token, "%p")) { - lines++; - rx = 10; - ry = 4 + lines*10; // y - - strcpy(token, "> ......."); - strncpy(token+2, _password, strlen(_password)); - tokenWidth = font->getStringWidth(token); - } else { - tokenWidth = font->getStringWidth(token); - - linewidth += tokenWidth; +void Gfx::setBackground(uint type, BackgroundInfo *info) { + delete _backgroundInfo; + _backgroundInfo = info; - if (linewidth > wrapwidth) { - // wrap line - lines++; - rx = 10; // x - ry = 4 + lines*10; // y - linewidth = tokenWidth; - } - - if (!scumm_stricmp(token, "%s")) { - sprintf(token, "%d", _score); + if (type == kBackgroundLocation) { + // The PC version of BRA needs the entries 20-31 of the palette to be constant, but + // the background resource files are screwed up. The right colors come from an unused + // bitmap (pointer.bmp). Nothing is known about the Amiga version so far. + if ((_vm->getGameType() == GType_BRA) && (_vm->getPlatform() == Common::kPlatformPC)) { + int r, g, b; + for (uint i = 16; i < 32; i++) { + _backupPal.getEntry(i, r, g, b); + _backgroundInfo->palette.setEntry(i, r, g, b); } - } - drawText(font, surf, rx, ry, token, color); - - rx += tokenWidth + blankWidth; - linewidth += blankWidth; - - text = Common::ltrim(text); - } - -} - -void Gfx::freeBackground() { - _backgroundInfo.free(); -} - -void Gfx::setBackground(uint type, const char* name, const char* mask, const char* path) { - - freeBackground(); - - if (type == kBackgroundLocation) { - _disk->loadScenery(_backgroundInfo, name, mask, path); - setPalette(_backgroundInfo.palette); - _palette.clone(_backgroundInfo.palette); + setPalette(_backgroundInfo->palette); + _palette.clone(_backgroundInfo->palette); } else { - _disk->loadSlide(_backgroundInfo, name); - setPalette(_backgroundInfo.palette); + for (uint i = 0; i < 6; i++) + _backgroundInfo->ranges[i]._flags = 0; // disable palette cycling for slides + setPalette(_backgroundInfo->palette); } - } } // namespace Parallaction |
