2007-05-30 21:56:52 +00:00
|
|
|
/* 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.
|
2007-01-14 21:29:12 +00:00
|
|
|
*
|
|
|
|
* 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$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-04-07 10:02:59 +00:00
|
|
|
#include "common/system.h"
|
2007-01-14 21:29:12 +00:00
|
|
|
#include "common/file.h"
|
2007-12-15 20:56:05 +00:00
|
|
|
#include "graphics/primitives.h"
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
#include "parallaction/parallaction.h"
|
2007-05-13 14:38:05 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
namespace Parallaction {
|
2007-05-13 14:56:44 +00:00
|
|
|
|
2007-08-09 18:02:37 +00:00
|
|
|
|
2007-12-15 20:56:05 +00:00
|
|
|
void halfbritePixel(int x, int y, int color, void *data) {
|
|
|
|
byte *buffer = (byte*)data;
|
|
|
|
buffer[x + y * _vm->_screenWidth] &= ~0x20;
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawCircleLine(int xCenter, int yCenter, int x, int y, int color, void (*plotProc)(int, int, int, void *), void *data){
|
|
|
|
Graphics::drawLine(xCenter + x, yCenter + y, xCenter - x, yCenter + y, color, plotProc, data);
|
|
|
|
Graphics::drawLine(xCenter + x, yCenter - y, xCenter - x, yCenter - y, color, plotProc, data);
|
|
|
|
Graphics::drawLine(xCenter + y, yCenter + x, xCenter - y, yCenter + x, color, plotProc, data);
|
|
|
|
Graphics::drawLine(xCenter + y, yCenter - x, xCenter - y, yCenter - x, color, plotProc, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawCircle(int xCenter, int yCenter, int radius, int color, void (*plotProc)(int, int, int, void *), void *data) {
|
|
|
|
int x = 0;
|
|
|
|
int y = radius;
|
|
|
|
int p = 1 - radius;
|
|
|
|
|
|
|
|
/* Plot first set of points */
|
|
|
|
drawCircleLine(xCenter, yCenter, x, y, color, plotProc, data);
|
|
|
|
|
|
|
|
while (x < y) {
|
|
|
|
x++;
|
|
|
|
if (p < 0)
|
|
|
|
p += 2*x + 1;
|
|
|
|
else {
|
|
|
|
y--;
|
|
|
|
p += 2 * (x-y) + 1;
|
|
|
|
}
|
|
|
|
drawCircleLine(xCenter, yCenter, x, y, color, plotProc, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-08-09 18:02:37 +00:00
|
|
|
|
|
|
|
Palette::Palette() {
|
|
|
|
|
|
|
|
int gameType = _vm->getGameType();
|
|
|
|
|
|
|
|
if (gameType == GType_Nippon) {
|
|
|
|
_colors = 32;
|
|
|
|
_hb = (_vm->getPlatform() == Common::kPlatformAmiga);
|
|
|
|
} else
|
|
|
|
if (gameType == GType_BRA) {
|
|
|
|
_colors = 256;
|
|
|
|
_hb = false;
|
|
|
|
} else
|
|
|
|
error("can't create palette for id = '%i'", gameType);
|
|
|
|
|
|
|
|
_size = _colors * 3;
|
|
|
|
|
|
|
|
makeBlack();
|
2007-08-09 21:32:26 +00:00
|
|
|
}
|
2007-08-09 18:02:37 +00:00
|
|
|
|
|
|
|
Palette::Palette(const Palette &pal) {
|
2007-08-11 12:26:17 +00:00
|
|
|
clone(pal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Palette::clone(const Palette &pal) {
|
2007-08-09 18:02:37 +00:00
|
|
|
_colors = pal._colors;
|
|
|
|
_hb = pal._hb;
|
|
|
|
_size = pal._size;
|
|
|
|
memcpy(_data, pal._data, _size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Palette::makeBlack() {
|
|
|
|
memset(_data, 0, _size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Palette::setEntry(uint index, int red, int green, int blue) {
|
|
|
|
assert(index < _colors);
|
|
|
|
|
|
|
|
if (red >= 0)
|
|
|
|
_data[index*3] = red & 0xFF;
|
|
|
|
|
|
|
|
if (green >= 0)
|
|
|
|
_data[index*3+1] = green & 0xFF;
|
|
|
|
|
|
|
|
if (blue >= 0)
|
|
|
|
_data[index*3+2] = blue & 0xFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Palette::makeGrayscale() {
|
|
|
|
byte v;
|
|
|
|
for (uint16 i = 0; i < _colors; i++) {
|
|
|
|
v = MAX(_data[i*3+1], _data[i*3+2]);
|
|
|
|
v = MAX(v, _data[i*3]);
|
|
|
|
setEntry(i, v, v, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Palette::fadeTo(const Palette& target, uint step) {
|
|
|
|
|
|
|
|
if (step == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (uint16 i = 0; i < _size; i++) {
|
|
|
|
if (_data[i] == target._data[i]) continue;
|
|
|
|
|
|
|
|
if (_data[i] < target._data[i])
|
|
|
|
_data[i] = CLIP(_data[i] + step, (uint)0, (uint)target._data[i]);
|
|
|
|
else
|
|
|
|
_data[i] = CLIP(_data[i] - step, (uint)target._data[i], (uint)255);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint Palette::fillRGBA(byte *rgba) {
|
|
|
|
|
|
|
|
byte r, g, b;
|
2007-12-15 20:56:05 +00:00
|
|
|
byte *hbPal = rgba + _colors * 4;
|
2007-08-09 18:02:37 +00:00
|
|
|
|
|
|
|
for (uint32 i = 0; i < _colors; i++) {
|
|
|
|
r = (_data[i*3] << 2) | (_data[i*3] >> 4);
|
|
|
|
g = (_data[i*3+1] << 2) | (_data[i*3+1] >> 4);
|
|
|
|
b = (_data[i*3+2] << 2) | (_data[i*3+2] >> 4);
|
|
|
|
|
|
|
|
rgba[i*4] = r;
|
|
|
|
rgba[i*4+1] = g;
|
|
|
|
rgba[i*4+2] = b;
|
|
|
|
rgba[i*4+3] = 0;
|
|
|
|
|
|
|
|
if (_hb) {
|
|
|
|
hbPal[i*4] = r >> 1;
|
|
|
|
hbPal[i*4+1] = g >> 1;
|
|
|
|
hbPal[i*4+2] = b >> 1;
|
|
|
|
hbPal[i*4+3] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((_hb) ? 2 : 1) * _colors;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Palette::rotate(uint first, uint last, bool forward) {
|
|
|
|
|
|
|
|
byte tmp[3];
|
|
|
|
|
|
|
|
if (forward) { // forward
|
|
|
|
|
|
|
|
tmp[0] = _data[first * 3];
|
|
|
|
tmp[1] = _data[first * 3 + 1];
|
|
|
|
tmp[2] = _data[first * 3 + 2];
|
|
|
|
|
|
|
|
memmove(_data+first*3, _data+(first+1)*3, (last - first)*3);
|
|
|
|
|
|
|
|
_data[last * 3] = tmp[0];
|
|
|
|
_data[last * 3 + 1] = tmp[1];
|
|
|
|
_data[last * 3 + 2] = tmp[2];
|
|
|
|
|
|
|
|
} else { // backward
|
|
|
|
|
|
|
|
tmp[0] = _data[last * 3];
|
|
|
|
tmp[1] = _data[last * 3 + 1];
|
|
|
|
tmp[2] = _data[last * 3 + 2];
|
|
|
|
|
|
|
|
memmove(_data+(first+1)*3, _data+first*3, (last - first)*3);
|
|
|
|
|
|
|
|
_data[first * 3] = tmp[0];
|
|
|
|
_data[first * 3 + 1] = tmp[1];
|
|
|
|
_data[first * 3 + 2] = tmp[2];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
#define BALLOON_TAIL_WIDTH 12
|
|
|
|
#define BALLOON_TAIL_HEIGHT 10
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-06 15:40:12 +00:00
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = {
|
2007-01-14 21:29:12 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2007-03-13 19:59:45 +00:00
|
|
|
void Gfx::drawBalloon(const Common::Rect& r, uint16 winding) {
|
2007-03-12 20:41:25 +00:00
|
|
|
// printf("Gfx::drawBalloon(%i, %i, %i, %i, %i)...", left, top, width, height, winding);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-13 23:30:36 +00:00
|
|
|
Common::Rect q = r;
|
|
|
|
|
2007-08-06 15:40:12 +00:00
|
|
|
// draws balloon
|
2007-03-13 23:30:36 +00:00
|
|
|
q.right += 5;
|
|
|
|
floodFill(kBitFront, q, 0);
|
2007-08-06 15:40:12 +00:00
|
|
|
q.grow(-1);
|
2007-03-13 23:30:36 +00:00
|
|
|
floodFill(kBitFront, q, 1);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-06 15:40:12 +00:00
|
|
|
// draws tail
|
|
|
|
// TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill.
|
2007-01-14 21:29:12 +00:00
|
|
|
winding = (winding == 0 ? 1 : 0);
|
2007-08-08 18:33:55 +00:00
|
|
|
Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT);
|
|
|
|
s.moveTo(r.left + (r.width()+5)/2 - 5, r.bottom - 1);
|
2007-11-21 20:04:14 +00:00
|
|
|
flatBlit(s, _resBalloonTail[winding], _buffers[kBitFront], 2);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-08-07 13:54:29 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-04-21 12:51:40 +00:00
|
|
|
|
2007-08-09 18:02:37 +00:00
|
|
|
void Gfx::setPalette(Palette pal) {
|
|
|
|
byte sysPal[256*4];
|
2007-04-21 12:51:40 +00:00
|
|
|
|
2007-08-09 18:02:37 +00:00
|
|
|
uint n = pal.fillRGBA(sysPal);
|
|
|
|
g_system->setPalette(sysPal, 0, n);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-03-28 20:12:00 +00:00
|
|
|
void Gfx::setBlackPalette() {
|
|
|
|
Palette pal;
|
|
|
|
setPalette(pal);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
|
2007-08-09 18:02:37 +00:00
|
|
|
|
|
|
|
|
2007-03-28 20:12:00 +00:00
|
|
|
void Gfx::animatePalette() {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-10-15 19:00:46 +00:00
|
|
|
// avoid forcing setPalette when not needed
|
|
|
|
bool done = false;
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
for (uint16 i = 0; i < 4; i++) {
|
|
|
|
|
|
|
|
if ((_palettefx[i]._flags & 1) == 0) continue; // animated palette
|
|
|
|
|
|
|
|
_palettefx[i]._timer += _palettefx[i]._step * 2; // update timer
|
|
|
|
|
|
|
|
if (_palettefx[i]._timer < 0x4000) continue; // check timeout
|
|
|
|
|
|
|
|
_palettefx[i]._timer = 0; // reset timer
|
|
|
|
|
2007-08-09 18:02:37 +00:00
|
|
|
_palette.rotate(_palettefx[i]._first, _palettefx[i]._last, (_palettefx[i]._flags & 2) != 0);
|
2007-10-15 19:00:46 +00:00
|
|
|
|
|
|
|
done = true;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-10-15 19:00:46 +00:00
|
|
|
if (done) {
|
|
|
|
setPalette(_palette);
|
|
|
|
}
|
2007-03-28 20:12:00 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-04-21 12:51:40 +00:00
|
|
|
void Gfx::setHalfbriteMode(bool enable) {
|
|
|
|
if (_vm->getPlatform() != Common::kPlatformAmiga) return;
|
|
|
|
if (enable == _halfbrite) return;
|
2007-03-28 20:12:00 +00:00
|
|
|
|
2007-12-15 20:56:05 +00:00
|
|
|
_halfbrite = !_halfbrite;
|
2007-03-28 20:12:00 +00:00
|
|
|
|
2007-12-15 20:56:05 +00:00
|
|
|
if (!enable) {
|
|
|
|
_hbCircleRadius = 0;
|
|
|
|
}
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-12-15 20:56:05 +00:00
|
|
|
#define HALFBRITE_CIRCLE_RADIUS 48
|
|
|
|
void Gfx::setProjectorPos(int x, int y) {
|
|
|
|
_hbCircleRadius = HALFBRITE_CIRCLE_RADIUS;
|
|
|
|
_hbCirclePos.x = x + _hbCircleRadius;
|
|
|
|
_hbCirclePos.y = y + _hbCircleRadius;
|
2007-04-21 12:51:40 +00:00
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-12-15 20:56:05 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
void Gfx::drawInventory() {
|
|
|
|
|
|
|
|
if ((_engineFlags & kEngineInventory) == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::Rect r;
|
|
|
|
_vm->_inventoryRenderer->getRect(r);
|
|
|
|
byte *data = _vm->_inventoryRenderer->getData();
|
|
|
|
|
|
|
|
g_system->copyRectToScreen(data, r.width(), r.left, r.top, r.width(), r.height());
|
|
|
|
}
|
|
|
|
|
2007-11-22 21:19:44 +00:00
|
|
|
void Gfx::drawItems() {
|
|
|
|
if (_numItems == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Graphics::Surface *surf = g_system->lockScreen();
|
|
|
|
for (uint i = 0; i < _numItems; i++) {
|
|
|
|
flatBlit(_items[i].rect, _items[i].data->getData(_items[i].frame), surf, 0);
|
|
|
|
}
|
|
|
|
g_system->unlockScreen();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gfx::drawBalloons() {
|
|
|
|
if (_numBalloons == 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);
|
|
|
|
flatBlit(r, (byte*)_balloons[i].surface.getBasePtr(0, 0), surf, 2);
|
|
|
|
}
|
|
|
|
g_system->unlockScreen();
|
|
|
|
}
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
void Gfx::updateScreen() {
|
2007-12-15 20:56:05 +00:00
|
|
|
if (_halfbrite) {
|
|
|
|
Graphics::Surface *surf = g_system->lockScreen();
|
|
|
|
byte *src = (byte*)_buffers[kBitFront]->pixels;
|
|
|
|
byte *dst = (byte*)surf->pixels;
|
|
|
|
for (int i = 0; i < surf->w*surf->h; i++) {
|
|
|
|
*dst++ = *src++ | 0x20;
|
|
|
|
}
|
|
|
|
if (_hbCircleRadius > 0) {
|
|
|
|
drawCircle(_hbCirclePos.x, _hbCirclePos.y, _hbCircleRadius, 0, &halfbritePixel, surf->pixels);
|
|
|
|
}
|
|
|
|
g_system->unlockScreen();
|
|
|
|
} else {
|
|
|
|
g_system->copyRectToScreen((const byte*)_buffers[kBitFront]->pixels, _buffers[kBitFront]->pitch, _screenX, _screenY, _vm->_screenWidth, _vm->_screenHeight);
|
|
|
|
}
|
2007-11-19 20:46:28 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
drawInventory();
|
2007-11-22 21:19:44 +00:00
|
|
|
|
|
|
|
drawItems();
|
|
|
|
drawBalloons();
|
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
drawLabel();
|
2007-11-19 20:46:28 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
g_system->updateScreen();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
void Gfx::swapBuffers() {
|
2007-08-06 13:22:21 +00:00
|
|
|
Graphics::Surface *temp = _buffers[kBitFront];
|
2007-01-14 21:29:12 +00:00
|
|
|
_buffers[kBitFront] = _buffers[kBitBack];
|
|
|
|
_buffers[kBitBack] = temp;
|
|
|
|
updateScreen();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// graphic primitives
|
|
|
|
//
|
2007-03-12 20:41:25 +00:00
|
|
|
void Gfx::clearScreen(Gfx::Buffers buffer) {
|
2007-08-06 13:22:21 +00:00
|
|
|
memset(_buffers[buffer]->pixels, 0, _vm->_screenSize);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
if (buffer == kBitFront) updateScreen();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
void Gfx::copyScreen(Gfx::Buffers srcbuffer, Gfx::Buffers dstbuffer) {
|
2007-08-06 13:22:21 +00:00
|
|
|
memcpy(_buffers[dstbuffer]->pixels, _buffers[srcbuffer]->pixels, _vm->_screenSize);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-13 23:30:36 +00:00
|
|
|
void Gfx::floodFill(Gfx::Buffers buffer, const Common::Rect& r, byte color) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-06 13:22:21 +00:00
|
|
|
byte *d = (byte*)_buffers[buffer]->getBasePtr(r.left, r.top);
|
2007-03-13 23:30:36 +00:00
|
|
|
uint16 w = r.width() + 1;
|
|
|
|
uint16 h = r.height() + 1;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
for (uint16 i = 0; i < h; i++) {
|
|
|
|
memset(d, color, w);
|
|
|
|
|
2007-08-12 08:37:46 +00:00
|
|
|
d += _backgroundWidth;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-11-01 21:56:14 +00:00
|
|
|
void Gfx::invertRect(Gfx::Buffers buffer, const Common::Rect& r) {
|
|
|
|
|
|
|
|
byte *d = (byte*)_buffers[buffer]->getBasePtr(r.left, r.top);
|
|
|
|
|
|
|
|
for (int i = 0; i < r.height(); i++) {
|
|
|
|
for (int j = 0; j < r.width(); j++) {
|
|
|
|
*d ^= 0x1F;
|
|
|
|
d++;
|
|
|
|
}
|
|
|
|
|
|
|
|
d += (_buffers[buffer]->pitch - r.width());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
void Gfx::flatBlit(const Common::Rect& r, byte *data, Graphics::Surface *surf, byte transparentColor) {
|
2007-03-14 21:53:34 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
Common::Point dp;
|
|
|
|
Common::Rect q(r);
|
2007-03-14 21:53:34 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
Common::Rect clipper(surf->w, surf->h);
|
2007-03-14 21:53:34 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
q.clip(clipper);
|
|
|
|
if (!q.isValidRect()) return;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
dp.x = q.left;
|
|
|
|
dp.y = q.top;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
q.translate(-r.left, -r.top);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-14 21:09:56 +00:00
|
|
|
byte *s = data + q.left + q.top * r.width();
|
2007-11-21 20:04:14 +00:00
|
|
|
byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
uint sPitch = r.width() - q.width();
|
2007-11-21 20:04:14 +00:00
|
|
|
uint dPitch = surf->w - q.width();
|
2007-08-06 19:19:59 +00:00
|
|
|
|
2007-03-14 21:09:56 +00:00
|
|
|
for (uint16 i = q.top; i < q.bottom; i++) {
|
|
|
|
for (uint16 j = q.left; j < q.right; j++) {
|
2007-08-08 18:33:55 +00:00
|
|
|
if (*s != transparentColor)
|
|
|
|
*d = *s;
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
s++;
|
|
|
|
d++;
|
|
|
|
}
|
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
s += sPitch;
|
|
|
|
d += dPitch;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
void Gfx::blit(const Common::Rect& r, uint16 z, byte *data, Graphics::Surface *surf) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-14 21:53:34 +00:00
|
|
|
Common::Point dp;
|
2007-03-14 21:09:56 +00:00
|
|
|
Common::Rect q(r);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
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);
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-14 21:09:56 +00:00
|
|
|
byte *s = data + q.left + q.top * r.width();
|
2007-11-21 20:04:14 +00:00
|
|
|
byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
uint sPitch = r.width() - q.width();
|
2007-11-21 20:04:14 +00:00
|
|
|
uint dPitch = surf->w - q.width();
|
2007-08-06 19:19:59 +00:00
|
|
|
|
2007-08-06 19:13:51 +00:00
|
|
|
for (uint16 i = 0; i < q.height(); i++) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-06 19:13:51 +00:00
|
|
|
for (uint16 j = 0; j < q.width(); j++) {
|
2007-01-14 21:29:12 +00:00
|
|
|
if (*s != 0) {
|
2007-08-06 19:13:51 +00:00
|
|
|
byte v = _depthMask->getValue(dp.x + j, dp.y + i);
|
2007-01-14 21:29:12 +00:00
|
|
|
if (z >= v) *d = *s;
|
|
|
|
}
|
|
|
|
|
|
|
|
s++;
|
|
|
|
d++;
|
|
|
|
}
|
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
s += sPitch;
|
|
|
|
d += dPitch;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
void Gfx::setLabel(Label *label) {
|
|
|
|
_label = label;
|
|
|
|
|
|
|
|
if (_label) {
|
|
|
|
_label->resetPosition();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gfx::drawLabel() {
|
|
|
|
if (!_label || !_label->_text) {
|
2007-09-02 18:34:11 +00:00
|
|
|
return;
|
2007-11-21 20:04:14 +00:00
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
int16 _si, _di;
|
|
|
|
|
|
|
|
Common::Point cursor;
|
|
|
|
_vm->getCursorPos(cursor);
|
|
|
|
|
|
|
|
if (_vm->_activeItem._id != 0) {
|
|
|
|
_si = cursor.x + 16 - _label->_cnv.w/2;
|
|
|
|
_di = cursor.y + 34;
|
|
|
|
} else {
|
|
|
|
_si = cursor.x + 8 - _label->_cnv.w/2;
|
|
|
|
_di = cursor.y + 21;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_si < 0) _si = 0;
|
|
|
|
if (_di > 190) _di = 190;
|
|
|
|
|
|
|
|
if (_label->_cnv.w + _si > _vm->_screenWidth)
|
|
|
|
_si = _vm->_screenWidth - _label->_cnv.w;
|
|
|
|
|
|
|
|
_label->_pos.x = _si;
|
|
|
|
_label->_pos.y = _di;
|
|
|
|
|
|
|
|
Common::Rect r(_label->_cnv.w, _label->_cnv.h);
|
|
|
|
r.moveTo(_label->_pos);
|
|
|
|
|
|
|
|
Graphics::Surface* surf = g_system->lockScreen();
|
|
|
|
flatBlit(r, (byte*)_label->_cnv.getBasePtr(0, 0), surf, 0);
|
|
|
|
g_system->unlockScreen();
|
2007-09-02 18:34:11 +00:00
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Cnv management
|
|
|
|
//
|
2007-08-25 20:34:10 +00:00
|
|
|
void Gfx::flatBlitCnv(Frames *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) {
|
2007-07-01 19:28:32 +00:00
|
|
|
|
2007-08-07 15:08:45 +00:00
|
|
|
Graphics::Surface scnv;
|
2007-08-25 20:34:10 +00:00
|
|
|
Common::Rect r;
|
2007-07-01 19:28:32 +00:00
|
|
|
|
2007-08-25 20:34:10 +00:00
|
|
|
cnv->getRect(frame, r);
|
|
|
|
|
|
|
|
scnv.w = r.width();
|
|
|
|
scnv.h = r.height();
|
|
|
|
scnv.pixels = cnv->getData(frame);
|
2007-07-01 19:28:32 +00:00
|
|
|
|
|
|
|
flatBlitCnv(&scnv, x, y, buffer);
|
|
|
|
}
|
|
|
|
|
2007-08-07 15:08:45 +00:00
|
|
|
void Gfx::flatBlitCnv(Graphics::Surface *cnv, int16 x, int16 y, Gfx::Buffers buffer) {
|
|
|
|
Common::Rect r(cnv->w, cnv->h);
|
2007-03-14 21:09:56 +00:00
|
|
|
r.moveTo(x, y);
|
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
flatBlit(r, (byte*)cnv->pixels, _buffers[buffer], 0);
|
2007-01-14 21:29:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-07 15:08:45 +00:00
|
|
|
void Gfx::blitCnv(Graphics::Surface *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer) {
|
|
|
|
Common::Rect r(cnv->w, cnv->h);
|
2007-03-14 21:09:56 +00:00
|
|
|
r.moveTo(x, y);
|
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
blit(r, z, (byte*)cnv->pixels, _buffers[buffer]);
|
2007-01-14 21:29:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
void Gfx::backupDoorBackground(DoorData *data, int16 x, int16 y) {
|
2007-08-06 13:22:21 +00:00
|
|
|
byte *s = (byte*)_buffers[kBit2]->getBasePtr(x, y);
|
2007-08-25 20:34:10 +00:00
|
|
|
Common::Rect r;
|
|
|
|
data->_cnv->getRect(0, r);
|
|
|
|
copyRect(r.width(), r.height(), data->_background, r.width(), s,_backgroundWidth);
|
2007-01-14 21:29:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
void Gfx::backupGetBackground(GetData *data, int16 x, int16 y) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-22 21:51:33 +00:00
|
|
|
byte *t = (byte*)data->_cnv->getData(0);
|
2007-08-06 13:22:21 +00:00
|
|
|
byte *s = (byte*)_buffers[kBitBack]->getBasePtr(x, y);
|
2007-03-12 19:58:10 +00:00
|
|
|
byte *d = data->_backup;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-22 21:51:33 +00:00
|
|
|
Common::Rect r;
|
|
|
|
data->_cnv->getRect(0, r);
|
|
|
|
|
|
|
|
uint pitch = _backgroundWidth - r.width();
|
2007-08-06 19:19:59 +00:00
|
|
|
|
2007-11-22 21:51:33 +00:00
|
|
|
for (uint16 i = 0; i < r.height(); i++) {
|
|
|
|
for (uint16 j = 0; j < r.width(); j++) {
|
2007-01-14 21:29:12 +00:00
|
|
|
*d = (*t) ? *s : 0;
|
|
|
|
|
|
|
|
d++;
|
|
|
|
t++;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
s += pitch;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-08-04 18:58:50 +00:00
|
|
|
//
|
|
|
|
// restores background according to specified frame
|
|
|
|
//
|
2007-08-08 18:33:55 +00:00
|
|
|
void Gfx::restoreDoorBackground(const Common::Rect& r, byte *data, byte* background) {
|
2007-08-04 18:58:50 +00:00
|
|
|
|
2007-08-08 18:33:55 +00:00
|
|
|
byte *t = data;
|
2007-08-04 18:58:50 +00:00
|
|
|
byte *s = background;
|
2007-08-06 13:22:21 +00:00
|
|
|
byte *d0 = (byte*)_buffers[kBitBack]->getBasePtr(r.left, r.top);
|
|
|
|
byte *d1 = (byte*)_buffers[kBit2]->getBasePtr(r.left, r.top);
|
2007-08-04 18:58:50 +00:00
|
|
|
|
2007-08-12 08:37:46 +00:00
|
|
|
uint pitch = _backgroundWidth - r.width();
|
2007-08-06 19:19:59 +00:00
|
|
|
|
2007-08-04 18:58:50 +00:00
|
|
|
for (uint16 i = 0; i < r.height() ; i++) {
|
|
|
|
for (uint16 j = 0; j < r.width() ; j++) {
|
|
|
|
if (*t) {
|
|
|
|
*d0 = *s;
|
|
|
|
*d1 = *s;
|
|
|
|
}
|
|
|
|
|
|
|
|
d0++;
|
|
|
|
d1++;
|
|
|
|
t++;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
2007-08-06 19:19:59 +00:00
|
|
|
d0 += pitch;
|
|
|
|
d1 += pitch;
|
2007-08-04 18:58:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
//
|
2007-03-12 19:58:10 +00:00
|
|
|
// copies a rectangular bitmap on the background
|
2007-01-14 21:29:12 +00:00
|
|
|
//
|
2007-08-04 18:58:50 +00:00
|
|
|
void Gfx::restoreGetBackground(const Common::Rect& r, byte *data) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-21 20:04:14 +00:00
|
|
|
flatBlit(r, data, _buffers[kBitBack], 0);
|
|
|
|
flatBlit(r, data, _buffers[kBit2], 0);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-04-23 17:22:47 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-07-02 07:32:06 +00:00
|
|
|
void Gfx::displayString(uint16 x, uint16 y, const char *text, byte color) {
|
2007-08-06 13:22:21 +00:00
|
|
|
byte *dst = (byte*)_buffers[kBitFront]->getBasePtr(x, y);
|
2008-01-04 21:24:51 +00:00
|
|
|
if (_fontShadow) {
|
|
|
|
dst = (byte*)_buffers[kBitFront]->getBasePtr(x-2, y+2);
|
|
|
|
_font->setColor(0);
|
|
|
|
_font->drawString(dst, _vm->_screenWidth, text);
|
|
|
|
}
|
|
|
|
|
|
|
|
dst = (byte*)_buffers[kBitFront]->getBasePtr(x, y);
|
2007-07-02 07:32:06 +00:00
|
|
|
_font->setColor(color);
|
2007-07-26 18:30:27 +00:00
|
|
|
_font->drawString(dst, _vm->_screenWidth, text);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-05-06 09:31:45 +00:00
|
|
|
void Gfx::displayCenteredString(uint16 y, const char *text) {
|
2007-07-26 18:30:27 +00:00
|
|
|
uint16 x = (_vm->_screenWidth - getStringWidth(text)) / 2;
|
2007-07-02 07:32:06 +00:00
|
|
|
displayString(x, y, text, 1);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-07-26 18:30:27 +00:00
|
|
|
bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, int16 wrapwidth) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
uint16 lines = 0;
|
|
|
|
bool rv = false;
|
|
|
|
uint16 linewidth = 0;
|
|
|
|
|
|
|
|
uint16 rx = x + 10;
|
|
|
|
uint16 ry = y + 4;
|
|
|
|
|
|
|
|
char token[40];
|
|
|
|
|
2007-07-26 18:30:27 +00:00
|
|
|
if (wrapwidth == -1)
|
|
|
|
wrapwidth = _vm->_screenWidth;
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
while (strlen(text) > 0) {
|
|
|
|
|
2007-07-08 13:39:23 +00:00
|
|
|
text = parseNextToken(text, token, 40, " ", true);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-10-13 21:49:38 +00:00
|
|
|
if (!scumm_stricmp(token, "%p")) {
|
2007-01-14 21:29:12 +00:00
|
|
|
lines++;
|
2007-10-13 21:49:38 +00:00
|
|
|
rx = x + 10;
|
2007-01-14 21:29:12 +00:00
|
|
|
ry = y + 4 + lines*10; // y
|
|
|
|
|
2007-10-13 21:49:38 +00:00
|
|
|
strcpy(token, "> .......");
|
|
|
|
strncpy(token+2, _password, strlen(_password));
|
2007-01-14 21:29:12 +00:00
|
|
|
rv = true;
|
2007-10-13 21:49:38 +00:00
|
|
|
} else {
|
|
|
|
|
|
|
|
linewidth += getStringWidth(token);
|
|
|
|
|
|
|
|
if (linewidth > wrapwidth) {
|
|
|
|
// wrap line
|
|
|
|
lines++;
|
|
|
|
rx = x + 10; // x
|
|
|
|
ry = y + 4 + lines*10; // y
|
|
|
|
linewidth = getStringWidth(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!scumm_stricmp(token, "%s")) {
|
|
|
|
sprintf(token, "%d", _score);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
displayString(rx, ry, token, color);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
rx += getStringWidth(token) + getStringWidth(" ");
|
|
|
|
linewidth += getStringWidth(" ");
|
|
|
|
|
2007-02-14 00:36:06 +00:00
|
|
|
text = Common::ltrim(text);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
uint16 Gfx::getStringWidth(const char *text) {
|
2007-04-16 20:16:18 +00:00
|
|
|
return _font->getStringWidth(text);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
void Gfx::getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
uint16 lines = 0;
|
|
|
|
uint16 w = 0;
|
|
|
|
*width = 0;
|
|
|
|
|
|
|
|
char token[40];
|
|
|
|
|
|
|
|
while (strlen(text) != 0) {
|
|
|
|
|
2007-07-08 13:39:23 +00:00
|
|
|
text = parseNextToken(text, token, 40, " ", true);
|
2007-01-14 21:29:12 +00:00
|
|
|
w += getStringWidth(token);
|
|
|
|
|
2007-10-13 21:49:38 +00:00
|
|
|
if (!scumm_stricmp(token, "%p")) {
|
2007-01-14 21:29:12 +00:00
|
|
|
lines++;
|
2007-10-13 21:49:38 +00:00
|
|
|
} else {
|
|
|
|
if (w > maxwidth) {
|
|
|
|
w -= getStringWidth(token);
|
|
|
|
lines++;
|
|
|
|
if (w > *width)
|
|
|
|
*width = w;
|
|
|
|
|
|
|
|
w = getStringWidth(token);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
w += getStringWidth(" ");
|
2007-02-14 00:36:06 +00:00
|
|
|
text = Common::ltrim(text);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*width < w) *width = w;
|
|
|
|
*width += 10;
|
|
|
|
|
|
|
|
*height = lines * 10 + 20;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-11 17:25:57 +00:00
|
|
|
void Gfx::setFont(Font *font) {
|
|
|
|
assert(font);
|
|
|
|
_font = font;
|
2008-01-04 21:24:51 +00:00
|
|
|
setFontShadow(false);
|
2007-02-27 19:39:33 +00:00
|
|
|
}
|
|
|
|
|
2008-01-04 21:24:51 +00:00
|
|
|
void Gfx::setFontShadow(bool enable) {
|
|
|
|
_fontShadow = enable && (_vm->getPlatform() == Common::kPlatformAmiga);
|
|
|
|
}
|
2007-02-27 19:39:33 +00:00
|
|
|
|
2007-03-13 19:59:45 +00:00
|
|
|
void Gfx::restoreBackground(const Common::Rect& r) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-13 19:59:45 +00:00
|
|
|
int16 left = r.left;
|
|
|
|
int16 top = r.top;
|
|
|
|
int16 width = r.width();
|
|
|
|
int16 height = r.height();
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
if (left < 0) left = 0;
|
|
|
|
if (top < 0) top = 0;
|
|
|
|
|
2007-08-12 08:37:46 +00:00
|
|
|
if (left >= _backgroundWidth) return;
|
|
|
|
if (top >= _backgroundHeight) return;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-12 08:37:46 +00:00
|
|
|
if (left+width >= _backgroundWidth) width = _backgroundWidth - left;
|
|
|
|
if (top+height >= _backgroundHeight) height = _backgroundHeight - top;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-03-13 23:30:36 +00:00
|
|
|
Common::Rect q(width, height);
|
|
|
|
q.moveTo(left, top);
|
|
|
|
|
2007-08-12 08:37:46 +00:00
|
|
|
copyRect(kBitBack, q, (byte*)_buffers[kBit2]->getBasePtr(q.left, q.top), _backgroundWidth);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-12 08:47:45 +00:00
|
|
|
|
2007-08-06 20:07:57 +00:00
|
|
|
void Gfx::setBackground(Graphics::Surface *surface) {
|
|
|
|
_buffers[kBit2] = surface;
|
2007-08-12 08:26:20 +00:00
|
|
|
|
2007-08-12 08:47:45 +00:00
|
|
|
initBuffers(surface->w, surface->h);
|
2007-08-06 20:07:57 +00:00
|
|
|
copyScreen(kBit2, kBitBack);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-08-06 22:03:17 +00:00
|
|
|
void Gfx::setMask(MaskBuffer *buffer) {
|
2007-08-06 19:39:00 +00:00
|
|
|
_depthMask = buffer;
|
2007-03-04 10:57:30 +00:00
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-08 18:33:55 +00:00
|
|
|
void Gfx::copyRect(uint width, uint height, byte *dst, uint dstPitch, byte *src, uint srcPitch) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-08 18:33:55 +00:00
|
|
|
for (uint16 _si = 0; _si < height; _si++) {
|
|
|
|
memcpy(dst, src, width);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-08 18:33:55 +00:00
|
|
|
src += srcPitch;
|
|
|
|
dst += dstPitch;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-08-08 18:33:55 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-08 18:33:55 +00:00
|
|
|
void Gfx::copyRect(Gfx::Buffers dstbuffer, const Common::Rect& r, byte *src, uint16 pitch) {
|
|
|
|
byte *d = (byte*)_buffers[dstbuffer]->getBasePtr(r.left, r.top);
|
2007-08-12 08:37:46 +00:00
|
|
|
copyRect(r.width(), r.height(), d, _backgroundWidth, src, pitch);
|
2007-08-08 18:33:55 +00:00
|
|
|
return;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-13 23:30:36 +00:00
|
|
|
void Gfx::grabRect(byte *dst, const Common::Rect& r, Gfx::Buffers srcbuffer, uint16 pitch) {
|
2007-08-06 13:22:21 +00:00
|
|
|
byte *s = (byte*)_buffers[srcbuffer]->getBasePtr(r.left, r.top);
|
2007-08-12 08:37:46 +00:00
|
|
|
copyRect(r.width(), r.height(), dst, pitch, s, _backgroundWidth);
|
2007-01-14 21:29:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-07-26 18:30:27 +00:00
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
int16 Gfx::queryMask(int16 v) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
for (uint16 _si = 0; _si < 3; _si++) {
|
|
|
|
if (_bgLayers[_si+1] > v) return _si;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
Gfx::Gfx(Parallaction* vm) :
|
2007-01-14 21:29:12 +00:00
|
|
|
_vm(vm) {
|
|
|
|
|
|
|
|
g_system->beginGFXTransaction();
|
2007-07-26 18:30:27 +00:00
|
|
|
g_system->initSize(_vm->_screenWidth, _vm->_screenHeight);
|
2007-08-12 12:52:38 +00:00
|
|
|
_vm->initCommonGFX(_vm->getGameType() == GType_BRA);
|
2007-01-14 21:29:12 +00:00
|
|
|
g_system->endGFXTransaction();
|
|
|
|
|
2007-08-06 20:07:57 +00:00
|
|
|
_buffers[kBit2] = 0;
|
2007-08-06 19:39:00 +00:00
|
|
|
_depthMask = 0;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-12 13:06:42 +00:00
|
|
|
_buffers[kBitFront] = 0;
|
|
|
|
_buffers[kBitBack] = 0;
|
|
|
|
|
2007-08-12 08:47:45 +00:00
|
|
|
initBuffers(_vm->_screenWidth, _vm->_screenHeight);
|
|
|
|
|
2007-08-09 18:02:37 +00:00
|
|
|
setPalette(_palette);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-22 21:19:44 +00:00
|
|
|
_numBalloons = 0;
|
|
|
|
_numItems = 0;
|
2007-11-21 20:04:14 +00:00
|
|
|
_label = 0;
|
|
|
|
|
2007-08-12 08:26:20 +00:00
|
|
|
_screenX = 0;
|
|
|
|
_screenY = 0;
|
|
|
|
|
2007-04-15 08:32:28 +00:00
|
|
|
_bgLayers[0] = _bgLayers[1] = _bgLayers[2] = _bgLayers[3] = 0;
|
|
|
|
|
2007-04-01 14:35:33 +00:00
|
|
|
memset(_palettefx, 0, sizeof(_palettefx));
|
|
|
|
|
2007-04-21 12:51:40 +00:00
|
|
|
_halfbrite = false;
|
2007-12-15 20:56:05 +00:00
|
|
|
_hbCircleRadius = 0;
|
2007-04-21 12:51:40 +00:00
|
|
|
|
2007-03-18 10:38:31 +00:00
|
|
|
_font = NULL;
|
2008-01-04 21:24:51 +00:00
|
|
|
_fontShadow = false;
|
2007-02-27 19:39:33 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-12 20:41:25 +00:00
|
|
|
Gfx::~Gfx() {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-08-12 08:47:45 +00:00
|
|
|
freeBuffers();
|
2007-08-06 20:07:57 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-08-12 08:47:45 +00:00
|
|
|
void Gfx::initBuffers(int w, int h) {
|
|
|
|
|
|
|
|
_backgroundWidth = w;
|
|
|
|
_backgroundHeight = h;
|
|
|
|
|
|
|
|
if (!_buffers[kBitFront]) {
|
|
|
|
_buffers[kBitFront] = new Graphics::Surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_buffers[kBitBack]) {
|
|
|
|
_buffers[kBitBack] = new Graphics::Surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_buffers[kBitFront]->w != w || _buffers[kBitFront]->h != h) {
|
|
|
|
_buffers[kBitFront]->create(w, h, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_buffers[kBitBack]->w != w || _buffers[kBitBack]->h != h) {
|
|
|
|
_buffers[kBitBack]->create(w, h, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gfx::freeBuffers() {
|
|
|
|
|
|
|
|
if (_buffers[kBitFront]) {
|
|
|
|
_buffers[kBitFront]->free();
|
|
|
|
delete _buffers[kBitFront];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_buffers[kBitBack]) {
|
|
|
|
_buffers[kBitBack]->free();
|
|
|
|
delete _buffers[kBitBack];
|
|
|
|
}
|
|
|
|
|
|
|
|
_buffers[kBitFront] = 0;
|
|
|
|
_buffers[kBitBack] = 0;
|
|
|
|
}
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-11-22 21:19:44 +00:00
|
|
|
void Gfx::setItem(Frames* frames, uint16 x, uint16 y) {
|
|
|
|
_items[_numItems].data = frames;
|
|
|
|
_items[_numItems].x = x;
|
|
|
|
_items[_numItems].y = y;
|
|
|
|
_numItems++;
|
|
|
|
}
|
|
|
|
|
|
|
|
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::createBalloon(char *text, uint16 maxwidth, uint16 winding) {
|
|
|
|
assert(_numBalloons < 5);
|
|
|
|
|
|
|
|
Gfx::Balloon *balloon = &_balloons[_numBalloons];
|
|
|
|
_numBalloons++;
|
|
|
|
|
|
|
|
int16 w, h;
|
|
|
|
getStringExtent(text, maxwidth, &w, &h);
|
|
|
|
|
|
|
|
balloon->surface.create(w + 5, h + 9, 1);
|
|
|
|
balloon->surface.fillRect(Common::Rect(w + 5, h + 9), 2);
|
|
|
|
|
|
|
|
Common::Rect r(w + 5, h);
|
|
|
|
balloon->surface.fillRect(r, 0);
|
|
|
|
r.grow(-1);
|
|
|
|
balloon->surface.fillRect(r, 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);
|
|
|
|
flatBlit(s, _resBalloonTail[winding], &balloon->surface, 2);
|
|
|
|
|
|
|
|
return balloon;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Gfx::setDialogueBalloon(char *text, uint16 x, uint16 y, uint16 maxwidth, uint16 winding, byte textColor) {
|
|
|
|
|
|
|
|
Common::Rect rect;
|
|
|
|
|
|
|
|
setFont(_vm->_dialogueFont);
|
|
|
|
Gfx::Balloon *balloon = createBalloon(text, maxwidth, winding);
|
|
|
|
drawWrappedText(&balloon->surface, text, textColor, maxwidth);
|
|
|
|
|
|
|
|
balloon->x = x;
|
|
|
|
balloon->y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gfx::freeBalloons() {
|
|
|
|
for (uint i = 0; i < _numBalloons; i++) {
|
|
|
|
_balloons[i].surface.free();
|
|
|
|
}
|
|
|
|
_numBalloons = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gfx::freeItems() {
|
|
|
|
_numItems = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gfx::hideDialogueStuff() {
|
|
|
|
freeItems();
|
|
|
|
freeBalloons();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gfx::drawText(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);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Gfx::drawWrappedText(Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) {
|
|
|
|
|
|
|
|
uint16 lines = 0;
|
|
|
|
bool rv = false;
|
|
|
|
uint16 linewidth = 0;
|
|
|
|
|
|
|
|
uint16 rx = 10;
|
|
|
|
uint16 ry = 4;
|
|
|
|
|
|
|
|
char token[40];
|
|
|
|
|
|
|
|
if (wrapwidth == -1)
|
|
|
|
wrapwidth = _vm->_screenWidth;
|
|
|
|
|
|
|
|
while (strlen(text) > 0) {
|
|
|
|
|
|
|
|
text = parseNextToken(text, token, 40, " ", true);
|
|
|
|
|
|
|
|
if (!scumm_stricmp(token, "%p")) {
|
|
|
|
lines++;
|
|
|
|
rx = 10;
|
|
|
|
ry = 4 + lines*10; // y
|
|
|
|
|
|
|
|
strcpy(token, "> .......");
|
|
|
|
strncpy(token+2, _password, strlen(_password));
|
|
|
|
rv = true;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
linewidth += getStringWidth(token);
|
|
|
|
|
|
|
|
if (linewidth > wrapwidth) {
|
|
|
|
// wrap line
|
|
|
|
lines++;
|
|
|
|
rx = 10; // x
|
|
|
|
ry = 4 + lines*10; // y
|
|
|
|
linewidth = getStringWidth(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!scumm_stricmp(token, "%s")) {
|
|
|
|
sprintf(token, "%d", _score);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
drawText(surf, rx, ry, token, color);
|
|
|
|
|
|
|
|
rx += getStringWidth(token) + getStringWidth(" ");
|
|
|
|
linewidth += getStringWidth(" ");
|
|
|
|
|
|
|
|
text = Common::ltrim(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
} // namespace Parallaction
|