mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 14:18:37 +00:00
c122d83c0e
svn-id: r25935
1399 lines
30 KiB
C++
1399 lines
30 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2006 The ScummVM project
|
|
*
|
|
* 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$
|
|
*
|
|
*/
|
|
|
|
#include "common/file.h"
|
|
|
|
#include "parallaction/graphics.h"
|
|
#include "parallaction/parser.h"
|
|
#include "parallaction/parallaction.h"
|
|
#include "parallaction/inventory.h"
|
|
#include "parallaction/disk.h"
|
|
#include "parallaction/zone.h"
|
|
|
|
|
|
extern OSystem *g_system;
|
|
|
|
namespace Parallaction {
|
|
|
|
|
|
byte * _maskBackup;
|
|
byte * _pathBackup;
|
|
|
|
|
|
|
|
uint16 _bgLayers[4];
|
|
|
|
//
|
|
// proportional font glyphs width
|
|
//
|
|
const byte _glyphWidths[126] = {
|
|
0x04, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x04, 0x04, 0x06, 0x06, 0x03, 0x05, 0x03, 0x05,
|
|
0x06, 0x06, 0x06, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x03, 0x05, 0x04, 0x05, 0x05,
|
|
0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x07, 0x05, 0x06, 0x05, 0x08, 0x07,
|
|
0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x03, 0x04, 0x05, 0x05, 0x06, 0x06, 0x05,
|
|
0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x06, 0x07, 0x05, 0x05, 0x05, 0x05, 0x02, 0x05, 0x05, 0x07,
|
|
0x08, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04,
|
|
0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, 0x06, 0x05, 0x05, 0x05, 0x05
|
|
};
|
|
|
|
Cnv Graphics::_font;
|
|
bool Graphics::_proportionalFont = false;
|
|
Point Graphics::_labelPosition[2] = { { 0, 0 }, { 0, 0 } };
|
|
StaticCnv Graphics::_mouseComposedArrow;
|
|
byte * Graphics::_buffers[];
|
|
|
|
#define PALETTE_BACKUP PALETTE_SIZE
|
|
|
|
PaletteFxRange _palettefx[6];
|
|
byte _palette[PALETTE_SIZE] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
byte _black_palette[PALETTE_SIZE] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
|
|
#define BALLOON_WIDTH 12
|
|
#define BALLOON_HEIGHT 10
|
|
|
|
byte _resBalloon[2][BALLOON_WIDTH*BALLOON_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 Graphics::drawBalloon(int16 left, int16 top, uint16 width, uint16 height, uint16 winding) {
|
|
// printf("Graphics::drawBalloon(%i, %i, %i, %i, %i)...", left, top, width, height, winding);
|
|
|
|
width+=5;
|
|
floodFill(0, left, top, left+width, top+height, kBitFront);
|
|
floodFill(1, left+1, top+2, left+width-1, top+height-1, kBitFront);
|
|
|
|
winding = (winding == 0 ? 1 : 0);
|
|
byte *s = _resBalloon[winding];
|
|
byte *d = _buffers[kBitFront] + (left + width/2 - 5) + (top + height - 1) * SCREEN_WIDTH;
|
|
|
|
for (uint16 i = 0; i < BALLOON_HEIGHT; i++) {
|
|
for (uint16 j = 0; j < BALLOON_WIDTH; j++) {
|
|
if (*s != 2) *d = *s;
|
|
d++;
|
|
s++;
|
|
}
|
|
|
|
d += (SCREEN_WIDTH - BALLOON_WIDTH);
|
|
}
|
|
|
|
// printf("done\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// palette management
|
|
//
|
|
|
|
void Graphics::setPalette(byte *palette) {
|
|
// printf("setPalette()\n");
|
|
// memcpy(_palette, palette, PALETTE_SIZE);
|
|
|
|
byte syspal[PALETTE_COLORS*4];
|
|
|
|
for (uint32 i = 0; i < PALETTE_COLORS; i++) {
|
|
syspal[i*4] = (palette[i*3] << 2) | (palette[i*3] >> 4);
|
|
syspal[i*4+1] = (palette[i*3+1] << 2) | (palette[i*3+1] >> 4);
|
|
syspal[i*4+2] = (palette[i*3+2] << 2) | (palette[i*3+2] >> 4);
|
|
syspal[i*4+3] = 0;
|
|
}
|
|
|
|
g_system->setPalette(syspal, 0, PALETTE_COLORS);
|
|
g_system->updateScreen();
|
|
return;
|
|
}
|
|
|
|
void Graphics::getBlackPalette(byte *palette) {
|
|
memcpy(palette, _black_palette, PALETTE_SIZE);
|
|
return;
|
|
}
|
|
|
|
void Graphics::palUnk0(byte *palette) {
|
|
#if 0
|
|
for (uint16 i = 0; i < PALETTE_SIZE; i++) {
|
|
palette[PALETTE_BACKUP+i] = _palette[i]/2;
|
|
}
|
|
#endif
|
|
Graphics::setPalette(palette);
|
|
|
|
return;
|
|
}
|
|
|
|
void Graphics::buildBWPalette(byte *palette) {
|
|
|
|
for (uint16 i = 0; i < PALETTE_COLORS; i++) {
|
|
byte max;
|
|
|
|
if (_palette[i*3+1] > _palette[i*3+2]) {
|
|
max = _palette[i*3+1];
|
|
} else {
|
|
max = _palette[i*3+2];
|
|
}
|
|
|
|
if (_palette[i*3] > max) {
|
|
max = _palette[i*3];
|
|
} else {
|
|
if (_palette[i*3+1] > _palette[i*3+2]) {
|
|
max = _palette[i*3+1];
|
|
} else {
|
|
max = _palette[i*3+2];
|
|
}
|
|
}
|
|
|
|
palette[i*3] = max;
|
|
palette[i*3+1] = max;
|
|
palette[i*3+2] = max;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void Graphics::fadePalette(byte *palette) {
|
|
|
|
for (uint16 i = 0; i < PALETTE_SIZE; i++)
|
|
if (palette[i] < _palette[i]) palette[i]++;
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
void Graphics::quickFadePalette(byte *palette) {
|
|
|
|
for (uint16 i = 0; i < PALETTE_SIZE; i++) {
|
|
if (palette[i] == _palette[i]) continue;
|
|
palette[i] += (palette[i] < _palette[i] ? 4 : -4);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// palette Animation
|
|
//
|
|
// FIXME: the effect is different from the original
|
|
//
|
|
void Graphics::animatePalette(byte *palette) {
|
|
// printf("Graphics::animatePalette()\n");
|
|
|
|
byte tmp[3];
|
|
|
|
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
|
|
|
|
if (_palettefx[i]._flags & 2) { // forward
|
|
|
|
tmp[0] = _palette[_palettefx[i]._first * 3];
|
|
tmp[1] = _palette[_palettefx[i]._first * 3 + 1];
|
|
tmp[2] = _palette[_palettefx[i]._first * 3 + 2];
|
|
|
|
memmove(palette+_palettefx[i]._first*3, _palette+(_palettefx[i]._first+1)*3, (_palettefx[i]._last - _palettefx[i]._first)*3);
|
|
|
|
palette[_palettefx[i]._last * 3] = tmp[0];
|
|
palette[_palettefx[i]._last * 3 + 1] = tmp[1];
|
|
palette[_palettefx[i]._last * 3 + 2] = tmp[2];
|
|
|
|
} else { // backward
|
|
|
|
tmp[0] = _palette[_palettefx[i]._last * 3];
|
|
tmp[1] = _palette[_palettefx[i]._last * 3 + 1];
|
|
tmp[2] = _palette[_palettefx[i]._last * 3 + 2];
|
|
|
|
memmove(palette+(_palettefx[i]._first+1)*3, _palette+_palettefx[i]._first*3, (_palettefx[i]._last - _palettefx[i]._first)*3);
|
|
|
|
palette[_palettefx[i]._first * 3] = tmp[0];
|
|
palette[_palettefx[i]._first * 3 + 1] = tmp[1];
|
|
palette[_palettefx[i]._first * 3 + 2] = tmp[2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Graphics::updateScreen() {
|
|
// printf("Graphics::updateScreen()\n");
|
|
g_system->copyRectToScreen(_buffers[kBitFront], SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
g_system->updateScreen();
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::swapBuffers() {
|
|
byte *temp = _buffers[kBitFront];
|
|
_buffers[kBitFront] = _buffers[kBitBack];
|
|
_buffers[kBitBack] = temp;
|
|
updateScreen();
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// graphic primitives
|
|
//
|
|
void Graphics::clearScreen(Graphics::Buffers buffer) {
|
|
memset(_buffers[buffer], 0, SCREEN_WIDTH*SCREEN_HEIGHT);
|
|
|
|
if (buffer == kBitFront) updateScreen();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::copyScreen(Graphics::Buffers srcbuffer, Graphics::Buffers dstbuffer) {
|
|
memcpy(_buffers[dstbuffer], _buffers[srcbuffer], SCREEN_WIDTH*SCREEN_HEIGHT);
|
|
|
|
if (dstbuffer == kBitFront) updateScreen();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::copyRect(Graphics::Buffers srcbuffer, uint16 sx, uint16 sy, Graphics::Buffers dstbuffer, uint16 dx, uint16 dy, uint16 w, uint16 h) {
|
|
|
|
byte *s = _buffers[srcbuffer] + (sx + sy * SCREEN_WIDTH);
|
|
byte *d = _buffers[dstbuffer] + (dx + dy * SCREEN_WIDTH);
|
|
|
|
for (uint16 i = 0; i < h; i++) {
|
|
memcpy(d, s, w);
|
|
|
|
s += SCREEN_WIDTH;
|
|
d += SCREEN_WIDTH;
|
|
}
|
|
|
|
if (dstbuffer == kBitFront) updateScreen();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
void Graphics::floodFill(byte color, uint16 left, uint16 top, uint16 right, uint16 bottom, Graphics::Buffers buffer) {
|
|
// printf("Graphics::floodFill(%i, %i, %i, %i, %i)\n", color, left, top, right, bottom);
|
|
|
|
byte *d = _buffers[buffer] + (left + top * SCREEN_WIDTH);
|
|
uint16 w = right - left + 1;
|
|
uint16 h = bottom - top + 1;
|
|
|
|
for (uint16 i = 0; i < h; i++) {
|
|
memset(d, color, w);
|
|
|
|
d += SCREEN_WIDTH;
|
|
}
|
|
|
|
if (buffer == kBitFront) updateScreen();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::flatBlit(uint16 w, uint16 h, int16 x, int16 y, byte *data, Graphics::Buffers buffer) {
|
|
debugC(9, kDebugGraphics, "Graphics::flatBlit(%i, %i, %i, %i)", w, h, x, y);
|
|
|
|
// source coordinates
|
|
int16 left = 0, top = 0;
|
|
int16 right = w, bottom = h;
|
|
|
|
if (x + w > SCREEN_WIDTH)
|
|
right = SCREEN_WIDTH - x;
|
|
if (y + h > SCREEN_HEIGHT)
|
|
bottom = SCREEN_HEIGHT - y;
|
|
|
|
if (x < 0) { // partially left clipped
|
|
left = -x;
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0) { // partially top clipped
|
|
top = -y;
|
|
y = 0;
|
|
}
|
|
|
|
if (left > right || top > bottom || x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; // fully clipped
|
|
|
|
byte *s = data + left + top * w;
|
|
byte *d = _buffers[buffer] + x + y * SCREEN_WIDTH;
|
|
|
|
debugC(9, kDebugGraphics, "Graphics::flatBlit CLIPPED (%i, %i, %i, %i) -> (%i, %i) %p %p", left, top, right, bottom, x, y, (const void*)s, (const void*)d);
|
|
|
|
for (uint16 i = top; i < bottom; i++) {
|
|
for (uint16 j = left; j < right; j++) {
|
|
if (*s != 0) *d = *s;
|
|
s++;
|
|
d++;
|
|
}
|
|
|
|
s += (w - right + left);
|
|
d += (SCREEN_WIDTH - right + left);
|
|
}
|
|
|
|
debugC(9, kDebugGraphics, "Graphics::flatBlit BLITTED");
|
|
|
|
if (buffer == kBitFront) updateScreen();
|
|
|
|
debugC(9, kDebugGraphics, "Graphics::flatBlit DONE");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
void Graphics::blit(uint16 w, uint16 h, int16 x, int16 y, uint16 z, byte *data, Graphics::Buffers buffer, Graphics::Buffers mask) {
|
|
// printf("Graphics::blit(%i, %i, %i, %i, %i)\n", w, h, x, y, z);
|
|
|
|
int16 left = 0, top = 0;
|
|
int16 right = w, bottom = h;
|
|
|
|
if (x + w > SCREEN_WIDTH) right = SCREEN_WIDTH - x;
|
|
if (y + h > SCREEN_HEIGHT) bottom = SCREEN_HEIGHT - y;
|
|
|
|
if (x < 0) { // partially left clipped
|
|
left = -x;
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0) { // partially top clipped
|
|
top = -y;
|
|
y = 0;
|
|
}
|
|
|
|
if (left > right || top > bottom || x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; // fully clipped
|
|
|
|
byte *s = data + left + top * w;
|
|
byte *d = _buffers[buffer] + x + y * SCREEN_WIDTH;
|
|
|
|
for (uint16 i = top; i < bottom; i++) {
|
|
|
|
uint16 r = x % 4;
|
|
byte *m = _buffers[mask] + x/4 + (y + i - top)*SCREENMASK_WIDTH;
|
|
|
|
for (uint16 j = left; j < right; j++) {
|
|
if (*s != 0) {
|
|
uint16 v = ((3 << (r << 1)) & *m) >> (r << 1);
|
|
if (z >= v) *d = *s;
|
|
}
|
|
|
|
r++;
|
|
if (r==4) m++;
|
|
r &= 0x3;
|
|
|
|
s++;
|
|
d++;
|
|
}
|
|
|
|
s += (w - right + left);
|
|
d += (SCREEN_WIDTH - right + left);
|
|
}
|
|
|
|
if (buffer == kBitFront) updateScreen();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
void jobDisplayLabel(void *parm, Job *j) {
|
|
|
|
ZoneLabel *label = (ZoneLabel*)parm;
|
|
debugC(1, kDebugJobs, "jobDisplayLabel (%p)", (const void*) label);
|
|
|
|
if (label->_cnv._width == 0)
|
|
return;
|
|
_vm->_graphics->flatBlitCnv(&label->_cnv, Graphics::_labelPosition[0]._x, Graphics::_labelPosition[0]._y, Graphics::kBitBack, label->_cnv._data1);
|
|
|
|
return;
|
|
}
|
|
|
|
void jobEraseLabel(void *parm, Job *j) {
|
|
ZoneLabel *label = (ZoneLabel*)parm;
|
|
|
|
debugC(1, kDebugJobs, "jobEraseLabel (%p)", (const void*) label);
|
|
|
|
int16 _si, _di;
|
|
|
|
if (_vm->_activeItem._id != 0) {
|
|
_si = _mousePos._x + 16 - label->_cnv._width/2;
|
|
_di = _mousePos._y + 34;
|
|
} else {
|
|
_si = _mousePos._x + 8 - label->_cnv._width/2;
|
|
_di = _mousePos._y + 21;
|
|
}
|
|
|
|
if (_si < 0) _si = 0;
|
|
if (_di > 190) _di = 190;
|
|
|
|
if (label->_cnv._width + _si > SCREEN_WIDTH)
|
|
_si = SCREEN_WIDTH - label->_cnv._width;
|
|
|
|
|
|
_vm->_graphics->restoreBackground(Graphics::_labelPosition[1]._x, Graphics::_labelPosition[1]._y, label->_cnv._width, label->_cnv._height);
|
|
|
|
Graphics::_labelPosition[1]._x = Graphics::_labelPosition[0]._x;
|
|
Graphics::_labelPosition[1]._y = Graphics::_labelPosition[0]._y;
|
|
Graphics::_labelPosition[0]._x = _si;
|
|
Graphics::_labelPosition[0]._y = _di;
|
|
|
|
return;
|
|
}
|
|
|
|
void Graphics::initMouse(uint16 arg_0) {
|
|
|
|
loadPointer(&_mouseComposedArrow);
|
|
|
|
byte temp[16*16];
|
|
memcpy(temp, _mouseArrow, 16*16);
|
|
|
|
uint16 k = 0;
|
|
for (uint16 i = 0; i < 4; i++) {
|
|
for (uint16 j = 0; j < 64; j++) _mouseArrow[k++] = temp[i + j * 4];
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void Graphics::setMousePointer(int16 index) {
|
|
|
|
if (index == kCursorArrow) { // standard mouse pointer
|
|
|
|
StaticCnv cnv;
|
|
|
|
cnv._width = 16;
|
|
cnv._height = 16;
|
|
cnv._data0 = _mouseArrow;
|
|
|
|
g_system->setMouseCursor(_mouseArrow, 16, 16, 0, 0, 0);
|
|
g_system->showMouse(true);
|
|
|
|
} else {
|
|
|
|
// FIXME: standard mouse arrow must be combined with item
|
|
// but it is not at the moment
|
|
|
|
// inventory item pointer
|
|
StaticCnv mouse_pointer;
|
|
memcpy(&mouse_pointer, &_mouseComposedArrow, sizeof(StaticCnv));
|
|
byte *v8 = mouse_pointer._data0;
|
|
|
|
// FIXME: target offseting is not clear
|
|
extractInventoryGraphics(index, v8 + 7 + 32 * 7);
|
|
|
|
g_system->setMouseCursor(v8, 32, 32, 0, 0, 0);
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Cnv management
|
|
//
|
|
void Graphics::flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Graphics::Buffers buffer, byte *unused) {
|
|
flatBlit(cnv->_width, cnv->_height, x, y, cnv->_data0, buffer);
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::blitCnv(StaticCnv *cnv, int16 x, int16 y, uint16 z, Graphics::Buffers buffer, Graphics::Buffers mask) {
|
|
blit(cnv->_width, cnv->_height, x, y, z, cnv->_data0, buffer, mask);
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::backupCnvBackground(StaticCnv *cnv, int16 x, int16 y) {
|
|
|
|
byte *s = _buffers[kBit2] + x + y * SCREEN_WIDTH;
|
|
byte *d = cnv->_data2;
|
|
|
|
for (uint16 i = 0; i < cnv->_height ; i++) {
|
|
memcpy(d, s, cnv->_width);
|
|
|
|
s += SCREEN_WIDTH;
|
|
d += cnv->_width;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::backupCnvBackgroundTransparent(StaticCnv *cnv, int16 x, int16 y) {
|
|
|
|
byte *t = cnv->_data0;
|
|
byte *s = _buffers[kBitBack] + x + y * SCREEN_WIDTH;
|
|
byte *d = cnv->_data2;
|
|
|
|
for (uint16 i = 0; i < cnv->_height ; i++) {
|
|
for (uint16 j = 0; j < cnv->_width ; j++) {
|
|
*d = (*t) ? *s : 0;
|
|
|
|
d++;
|
|
t++;
|
|
s++;
|
|
}
|
|
|
|
s += (SCREEN_WIDTH - cnv->_width);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// restores a cnv backup on the background
|
|
//
|
|
//
|
|
void Graphics::restoreCnvBackground(StaticCnv *cnv, int16 x, int16 y) {
|
|
|
|
byte *temp = cnv->_data0;
|
|
cnv->_data0 = cnv->_data2;
|
|
|
|
flatBlitCnv(cnv, x, y, kBitBack, cnv->_data1);
|
|
flatBlitCnv(cnv, x, y, kBit2, cnv->_data1);
|
|
|
|
cnv->_data0 = temp;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// strings
|
|
//
|
|
void Graphics::displayString(uint16 x, uint16 y, const char *text) {
|
|
if (text == NULL)
|
|
return;
|
|
|
|
uint16 len = strlen(text);
|
|
StaticCnv tmp;
|
|
|
|
for (uint16 i = 0; i < len; i++) {
|
|
byte c = mapChar(text[i]);
|
|
|
|
tmp._width = _font._width;
|
|
tmp._height = _font._height;
|
|
tmp._data0 = _font._array[c];
|
|
|
|
flatBlitCnv(&tmp, x, y, kBitFront, NULL);
|
|
|
|
x += (_proportionalFont ? _glyphWidths[(int)c] : 8);
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::displayBalloonString(uint16 x, uint16 y, const char *text, byte color) {
|
|
|
|
uint16 len = strlen(text);
|
|
|
|
for (uint16 i = 0; i < len; i++) {
|
|
|
|
byte c = mapChar(text[i]);
|
|
uint16 w = _proportionalFont ? _glyphWidths[(int)c] : 8;
|
|
byte *s = _font._array[c];
|
|
byte *d = _buffers[kBitFront] + x + y*SCREEN_WIDTH;
|
|
|
|
// printf("%i\n", text[i]);
|
|
|
|
for (uint16 j = 0; j < _font._height; j++) {
|
|
for (uint16 k = 0; k < w; k++) {
|
|
*d = (*s) ? 1 : color;
|
|
d++;
|
|
s++;
|
|
}
|
|
|
|
s += (8 - w);
|
|
d += (SCREEN_WIDTH - w);
|
|
}
|
|
|
|
x += w;
|
|
}
|
|
|
|
updateScreen();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
bool Graphics::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, byte color) {
|
|
// printf("Graphics::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, maxwidth, color);
|
|
|
|
uint16 lines = 0;
|
|
bool rv = false;
|
|
uint16 linewidth = 0;
|
|
|
|
_proportionalFont = true;
|
|
uint16 rx = x + 10;
|
|
uint16 ry = y + 4;
|
|
|
|
char token[40];
|
|
|
|
while (strlen(text) > 0) {
|
|
|
|
text = parseNextToken(text, token, 40, " ");
|
|
linewidth += getStringWidth(token);
|
|
|
|
if (linewidth > maxwidth) {
|
|
// 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);
|
|
}
|
|
if (!scumm_stricmp(token, "%p")) {
|
|
rv = true;
|
|
} else
|
|
displayBalloonString(rx, ry, token, color);
|
|
|
|
rx += getStringWidth(token) + getStringWidth(" ");
|
|
linewidth += getStringWidth(" ");
|
|
|
|
text = Common::ltrim(text);
|
|
}
|
|
|
|
// printf("done\n");
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 Graphics::getStringWidth(const char *text) {
|
|
if (text == NULL) return 0;
|
|
|
|
uint16 len = strlen(text);
|
|
|
|
if (_proportionalFont == 0) {
|
|
// fixed font
|
|
return len*8;
|
|
}
|
|
|
|
// proportional font
|
|
uint16 w = 0;
|
|
for (uint16 i = 0; i < len; i++) {
|
|
byte c = mapChar(text[i]);
|
|
w += _glyphWidths[(int)c];
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
|
|
void Graphics::getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height) {
|
|
|
|
uint16 lines = 0;
|
|
uint16 w = 0;
|
|
*width = 0;
|
|
|
|
_proportionalFont = true;
|
|
|
|
char token[40];
|
|
|
|
while (strlen(text) != 0) {
|
|
|
|
text = parseNextToken(text, token, 40, " ");
|
|
w += getStringWidth(token);
|
|
|
|
if (w > maxwidth) {
|
|
w -= getStringWidth(token);
|
|
lines++;
|
|
if (w > *width)
|
|
*width = w;
|
|
|
|
w = getStringWidth(token);
|
|
}
|
|
|
|
w += getStringWidth(" ");
|
|
text = Common::ltrim(text);
|
|
}
|
|
|
|
if (*width < w) *width = w;
|
|
*width += 10;
|
|
|
|
*height = lines * 10 + 20;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::setFont(const char* name) {
|
|
if (_font._array != NULL)
|
|
freeCnv(&_font);
|
|
|
|
loadFont(name, &_font);
|
|
}
|
|
|
|
|
|
// backups background mask
|
|
//
|
|
//
|
|
void Graphics::backupBackgroundMask(Graphics::Buffers mask) {
|
|
|
|
byte *s = _buffers[mask];
|
|
byte *d = _maskBackup;
|
|
|
|
memcpy(d, s, SCREENMASK_WIDTH*SCREEN_HEIGHT);
|
|
|
|
return;
|
|
}
|
|
|
|
// restores background mask
|
|
//
|
|
//
|
|
void Graphics::restoreBackgroundMask(Graphics::Buffers mask) {
|
|
|
|
byte *s = _maskBackup;
|
|
byte *d = _buffers[mask];
|
|
|
|
memcpy(d, s, SCREENMASK_WIDTH*SCREEN_HEIGHT);
|
|
|
|
return;
|
|
}
|
|
|
|
// backups background path
|
|
//
|
|
//
|
|
void Graphics::backupBackgroundPath(Graphics::Buffers path) {
|
|
|
|
byte *s = _buffers[path];
|
|
byte *d = _pathBackup;
|
|
|
|
memcpy(d, s, SCREENPATH_WIDTH*SCREEN_HEIGHT);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// restores background path
|
|
//
|
|
void Graphics::restoreBackgroundPath(Graphics::Buffers path) {
|
|
|
|
byte *s = _pathBackup;
|
|
byte *d = _buffers[path];
|
|
|
|
memcpy(d, s, SCREENPATH_WIDTH*SCREEN_HEIGHT);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// decompress a graphics block
|
|
//
|
|
uint16 Graphics::decompressChunk(byte *src, byte *dst, uint16 size) {
|
|
|
|
uint16 written = 0;
|
|
uint16 read = 0;
|
|
uint16 len = 0;
|
|
|
|
for (; written != size; written += len) {
|
|
|
|
len = src[read];
|
|
read++;
|
|
|
|
if (len <= 127) {
|
|
// copy run
|
|
|
|
len++;
|
|
memcpy(dst+written, src+read, len);
|
|
read += len;
|
|
|
|
} else {
|
|
// expand run
|
|
|
|
len = 257 - len;
|
|
memset(dst+written, src[read], len);
|
|
read++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return read;
|
|
}
|
|
|
|
void Graphics::restoreBackground(int16 left, int16 top, uint16 width, uint16 height) {
|
|
// printf("restoreBackground(%i, %i, %i, %i)\n", left, top, width, height);
|
|
|
|
if (left < 0) left = 0;
|
|
if (top < 0) top = 0;
|
|
|
|
if (left >= SCREEN_WIDTH) return;
|
|
if (top >= SCREEN_HEIGHT) return;
|
|
|
|
if (left+width >= SCREEN_WIDTH) width = SCREEN_WIDTH - left;
|
|
if (top+height >= SCREEN_HEIGHT) height = SCREEN_HEIGHT - top;
|
|
|
|
copyRect(kBit2, left, top, kBitBack, left, top, width, height);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::makeCnvFromString(StaticCnv *cnv, char *text) {
|
|
// printf("makeCnvFromString('%s')\n", text);
|
|
|
|
uint16 len = strlen(text);
|
|
|
|
cnv->_width = _font._width * len;
|
|
cnv->_height = _font._height;
|
|
|
|
// printf("%i x %i\n", cnv->_width, cnv->_height);
|
|
|
|
cnv->_data0 = (byte*)memAlloc(cnv->_width * cnv->_height);
|
|
|
|
for (uint16 i = 0; i < len; i++) {
|
|
byte c = mapChar(text[i]);
|
|
|
|
byte *s = _font._array[c];
|
|
byte *d = cnv->_data0 + _font._width * i;
|
|
|
|
for (uint16 j = 0; j < _font._height; j++) {
|
|
memcpy(d, s, 8);
|
|
|
|
s += 8;
|
|
d += cnv->_width;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// internal character mapping
|
|
//
|
|
byte Graphics::mapChar(byte c) {
|
|
|
|
if (c == 0xA5) return 0x5F;
|
|
if (c == 0xDF) return 0x60;
|
|
|
|
if (c > 0x7F) return c - 0x7F;
|
|
|
|
return c - 0x20;
|
|
}
|
|
|
|
|
|
//
|
|
// loads a cnv from an external file
|
|
//
|
|
void Graphics::loadExternalCnv(const char *filename, Cnv *cnv) {
|
|
// printf("Graphics::loadExternalCnv(%s)...", filename);
|
|
|
|
char path[PATH_LEN];
|
|
|
|
sprintf(path, "%s.cnv", filename);
|
|
|
|
Common::File stream;
|
|
|
|
if (!stream.open(path))
|
|
errorFileNotFound(path);
|
|
|
|
cnv->_count = stream.readByte();
|
|
cnv->_width = stream.readByte();
|
|
cnv->_height = stream.readByte();
|
|
|
|
cnv->_array = (byte**)memAlloc(cnv->_count * sizeof(byte*));
|
|
|
|
uint16 size = cnv->_width*cnv->_height;
|
|
for (uint16 i = 0; i < cnv->_count; i++) {
|
|
cnv->_array[i] = (byte*)memAlloc(size);
|
|
stream.read(cnv->_array[i], size);
|
|
}
|
|
|
|
stream.close();
|
|
|
|
// printf("done\n");
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Graphics::loadExternalStaticCnv(const char *filename, StaticCnv *cnv) {
|
|
|
|
char path[PATH_LEN];
|
|
|
|
sprintf(path, "%s.cnv", filename);
|
|
|
|
Common::File stream;
|
|
|
|
if (!stream.open(path))
|
|
errorFileNotFound(path);
|
|
|
|
cnv->_width = cnv->_height = 0;
|
|
|
|
stream.skip(1);
|
|
cnv->_width = stream.readByte();
|
|
cnv->_height = stream.readByte();
|
|
|
|
uint16 size = cnv->_width*cnv->_height;
|
|
|
|
cnv->_data0 = (byte*)memAlloc(size);
|
|
stream.read(cnv->_data0, size);
|
|
|
|
stream.close();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Graphics::loadStaticCnv(const char *filename, StaticCnv *cnv) {
|
|
// printf("Graphics::loadStaticCnv(%s)\n", filename);
|
|
|
|
char path[PATH_LEN];
|
|
|
|
strcpy(path, filename);
|
|
if (!_vm->_archive.openArchivedFile(path)) {
|
|
sprintf(path, "%s.pp", filename);
|
|
if (!_vm->_archive.openArchivedFile(path))
|
|
errorFileNotFound(path);
|
|
}
|
|
|
|
_vm->_archive.skip(1);
|
|
cnv->_width = _vm->_archive.readByte();
|
|
cnv->_height = _vm->_archive.readByte();
|
|
|
|
uint16 compressedsize = _vm->_archive.size() - 3;
|
|
byte *compressed = (byte*)memAlloc(compressedsize);
|
|
|
|
uint16 size = cnv->_width*cnv->_height;
|
|
cnv->_data0 = (byte*)memAlloc(size);
|
|
|
|
_vm->_archive.read(compressed, compressedsize);
|
|
_vm->_archive.closeArchivedFile();
|
|
|
|
decompressChunk(compressed, cnv->_data0, size);
|
|
memFree(compressed);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Graphics::loadCnv(const char *filename, Cnv *cnv) {
|
|
// printf("Graphics::loadCnv(%s)\n", filename);
|
|
|
|
char path[PATH_LEN];
|
|
|
|
strcpy(path, filename);
|
|
if (!_vm->_archive.openArchivedFile(path)) {
|
|
sprintf(path, "%s.pp", filename);
|
|
if (!_vm->_archive.openArchivedFile(path))
|
|
errorFileNotFound(path);
|
|
}
|
|
|
|
cnv->_count = _vm->_archive.readByte();
|
|
cnv->_width = _vm->_archive.readByte();
|
|
cnv->_height = _vm->_archive.readByte();
|
|
|
|
uint16 framesize = cnv->_width*cnv->_height;
|
|
|
|
cnv->_array = (byte**)memAlloc(cnv->_count * sizeof(byte*));
|
|
|
|
uint32 size = _vm->_archive.size() - 3;
|
|
|
|
byte *buf = (byte*)memAlloc(size);
|
|
_vm->_archive.read(buf, size);
|
|
|
|
byte *s = buf;
|
|
|
|
for (uint16 i = 0; i < cnv->_count; i++) {
|
|
cnv->_array[i] = (byte*)memAlloc(framesize);
|
|
uint16 read = decompressChunk(s, cnv->_array[i], framesize);
|
|
|
|
// printf("frame %i decompressed: %i --> %i\n", i, read, framesize);
|
|
|
|
s += read;
|
|
}
|
|
|
|
_vm->_archive.closeArchivedFile();
|
|
|
|
memFree(buf);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Graphics::freeCnv(Cnv *cnv) {
|
|
// printf("Graphics::freeCnv()\n");
|
|
|
|
if (!cnv) return;
|
|
|
|
for (uint16 _si = 0; _si < cnv->_count; _si++) {
|
|
memFree(cnv->_array[_si]);
|
|
}
|
|
memFree(cnv->_array);
|
|
cnv->_array = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void Graphics::freeStaticCnv(StaticCnv *cnv) {
|
|
// printf("free_static_cnv()\n");
|
|
|
|
if (!cnv) return;
|
|
|
|
if (!cnv || !cnv->_data0) return;
|
|
memFree(cnv->_data0);
|
|
cnv->_data0 = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// slides (background images) are stored compressed by scanline in a rle fashion
|
|
//
|
|
// the uncompressed data must then be unpacked to get:
|
|
// * color data [bits 0-5]
|
|
// * mask data [bits 6-7] (z buffer)
|
|
// * path data [bit 8] (walkable areas)
|
|
//
|
|
|
|
|
|
void unpackBackgroundScanline(byte *src, byte *screen, byte *mask, byte *path) {
|
|
|
|
// update mask, path and screen
|
|
for (uint16 i = 0; i < SCREEN_WIDTH; i++) {
|
|
path[i/8] |= ((src[i] & 0x80) >> 7) << (i & 7);
|
|
mask[i/4] |= ((src[i] & 0x60) >> 5) << ((i & 3) << 1);
|
|
screen[i] = src[i] & 0x1F;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Graphics::loadBackground(const char *filename, Graphics::Buffers buffer) {
|
|
// printf("Graphics::loadBackground(%s)\n", filename);
|
|
|
|
if (!_vm->_archive.openArchivedFile(filename))
|
|
errorFileNotFound(filename);
|
|
|
|
// byte palette[PALETTE_SIZE];
|
|
byte v150[4];
|
|
_vm->_archive.read(_palette, PALETTE_SIZE);
|
|
_vm->_archive.read(&v150, 4);
|
|
|
|
byte tempfx[sizeof(PaletteFxRange)*6];
|
|
_vm->_archive.read(&tempfx, sizeof(PaletteFxRange)*6);
|
|
|
|
// setPalette(palette);
|
|
|
|
uint16 _si;
|
|
for (_si = 0; _si < 4; _si++) {
|
|
byte _al = v150[_si];
|
|
_bgLayers[_si] = _al;
|
|
}
|
|
|
|
Common::MemoryReadStream sread(tempfx, sizeof(PaletteFxRange)*6);
|
|
for (_si = 0; _si < 6; _si++) {
|
|
_palettefx[_si]._timer = sread.readUint16BE();
|
|
_palettefx[_si]._step = sread.readUint16BE();
|
|
_palettefx[_si]._flags = sread.readUint16BE();
|
|
_palettefx[_si]._first = sread.readByte();
|
|
_palettefx[_si]._last = sread.readByte();
|
|
}
|
|
|
|
#if 0
|
|
uint16 v147;
|
|
for (v147 = 0; v147 < PALETTE_SIZE; v147++) {
|
|
byte _al = _palette[v147];
|
|
_palette[PALETTE_SIZE+v147] = _al / 2;
|
|
}
|
|
#endif
|
|
|
|
memset(_buffers[kPath0], 0, SCREENPATH_WIDTH*SCREEN_HEIGHT);
|
|
memset(_buffers[kMask0], 0, SCREENMASK_WIDTH*SCREEN_HEIGHT);
|
|
|
|
byte *v4 = (byte*)memAlloc(SCREEN_SIZE);
|
|
_vm->_archive.read(v4, SCREEN_SIZE);
|
|
|
|
byte v144[SCREEN_WIDTH];
|
|
|
|
byte *s = v4;
|
|
for (uint16 i = 0; i < SCREEN_HEIGHT; i++) {
|
|
s += decompressChunk(s, v144, SCREEN_WIDTH);
|
|
unpackBackgroundScanline(v144, _buffers[buffer]+SCREEN_WIDTH*i, _buffers[kMask0]+SCREENMASK_WIDTH*i, _buffers[kPath0]+SCREENPATH_WIDTH*i);
|
|
}
|
|
|
|
memFree(v4);
|
|
_vm->_archive.closeArchivedFile();
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// read background path and mask from a file
|
|
//
|
|
// mask and path are normally combined (via OR) into the background picture itself
|
|
// read the comment on the top of this file for more
|
|
//
|
|
void Graphics::loadMaskAndPath(const char *filename) {
|
|
|
|
if (!_vm->_archive.openArchivedFile(filename))
|
|
errorFileNotFound(filename);
|
|
|
|
byte v4[4];
|
|
_vm->_archive.read(v4, 4);
|
|
_vm->_archive.read(_buffers[kPath0], SCREENPATH_WIDTH*SCREEN_HEIGHT);
|
|
_vm->_archive.read(_buffers[kMask0], SCREENMASK_WIDTH*SCREEN_HEIGHT);
|
|
|
|
for (uint16 _si = 0; _si < 4; _si++) _bgLayers[_si] = v4[_si];
|
|
|
|
_vm->_archive.closeArchivedFile();
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::copyRect(Graphics::Buffers dstbuffer, uint16 x, uint16 y, uint16 w, uint16 h, byte *src, uint16 pitch) {
|
|
|
|
byte *d = _buffers[dstbuffer] + x + SCREEN_WIDTH * y;
|
|
byte *s = src;
|
|
|
|
for (uint16 _si = 0; _si < h; _si++) {
|
|
memcpy(d, s, w);
|
|
|
|
s += pitch;
|
|
d += SCREEN_WIDTH;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void Graphics::drawBorder(Graphics::Buffers buffer, uint16 x, uint16 y, uint16 w, uint16 h, byte color) {
|
|
|
|
byte *d = _buffers[buffer] + x + SCREEN_WIDTH * y;
|
|
|
|
memset(d, color, w);
|
|
|
|
for (uint16 i = 0; i < h; i++) {
|
|
d[i * SCREEN_WIDTH] = color;
|
|
d[i * SCREEN_WIDTH + w - 1] = color;
|
|
}
|
|
|
|
d = _buffers[buffer] + x + SCREEN_WIDTH * (y + h - 1);
|
|
memset(d, color, w);
|
|
|
|
return;
|
|
}
|
|
|
|
void Graphics::grabRect(Graphics::Buffers srcbuffer, byte *dst, uint16 x, uint16 y, uint16 w, uint16 h, uint16 pitch) {
|
|
|
|
byte *s = _buffers[srcbuffer] + x + SCREEN_WIDTH * y;
|
|
|
|
for (uint16 i = 0; i < h; i++) {
|
|
memcpy(dst, s, w);
|
|
|
|
s += SCREEN_WIDTH;
|
|
dst += pitch;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Graphics::maskOpNot(uint16 x, uint16 y, uint16 unused, Graphics::Buffers mask) {
|
|
|
|
uint16 _ax = x + y * SCREEN_WIDTH;
|
|
_buffers[mask][_ax >> 2] &= ~(3 << ((_ax & 3) << 1));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void Graphics::maskClearRectangle(uint16 left, uint16 top, uint16 right, uint16 bottom, Graphics::Buffers mask) {
|
|
|
|
uint16 _di = left/4 + top*80;
|
|
|
|
for (uint16 _si = top; _si < bottom; _si++) {
|
|
memset(&_buffers[mask][_di], 0, (right - left)/4+1);
|
|
_di += 80;
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// HACK
|
|
// this routine is only invoked from the 'intgrotta scenario'
|
|
//
|
|
void Graphics::intGrottaHackMask() {
|
|
memset(_buffers[kMask0] + 3600, 0, 3600);
|
|
_bgLayers[1] = 500;
|
|
return;
|
|
}
|
|
|
|
uint16 Graphics::queryPath(uint16 x, uint16 y) {
|
|
|
|
byte *v6 = _buffers[kPath0];
|
|
|
|
byte _al = v6[y*40 + x/8];
|
|
byte _dl = 1 << (x % 8);
|
|
|
|
return _al & _dl;
|
|
|
|
}
|
|
|
|
int16 Graphics::queryMask(int16 v) {
|
|
|
|
for (uint16 _si = 0; _si < 3; _si++) {
|
|
if (_bgLayers[_si+1] > v) return _si;
|
|
}
|
|
|
|
return 3;
|
|
}
|
|
|
|
void Graphics::initBuffers() {
|
|
|
|
_buffers[kBitFront] = (byte*)memAlloc(SCREEN_SIZE);
|
|
_buffers[kBitBack] = (byte*)memAlloc(SCREEN_SIZE);
|
|
_buffers[kBit2] = (byte*)memAlloc(SCREEN_SIZE);
|
|
_buffers[kBit3] = (byte*)memAlloc(SCREEN_SIZE); // this buffer is also used by menu so it must stay this size
|
|
|
|
_buffers[kMask0] = (byte*)memAlloc(SCREENMASK_WIDTH * SCREEN_HEIGHT);
|
|
_buffers[kPath0] = (byte*)memAlloc(SCREENPATH_WIDTH * SCREEN_HEIGHT);
|
|
|
|
_maskBackup = (byte*)memAlloc(SCREENMASK_WIDTH * SCREEN_HEIGHT);
|
|
_pathBackup = (byte*)memAlloc(SCREENPATH_WIDTH * SCREEN_HEIGHT);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
Graphics::Graphics(Parallaction* vm) :
|
|
_vm(vm) {
|
|
|
|
g_system->beginGFXTransaction();
|
|
|
|
g_system->initSize(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
|
|
g_system->endGFXTransaction();
|
|
|
|
initBuffers();
|
|
|
|
byte palette[PALETTE_SIZE];
|
|
getBlackPalette(palette);
|
|
setPalette(palette);
|
|
|
|
initMouse( 0 );
|
|
|
|
_font._array = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
Graphics::~Graphics() {
|
|
|
|
memFree(_buffers[kMask0]);
|
|
memFree(_buffers[kPath0]);
|
|
|
|
memFree(_buffers[kBitFront]);
|
|
memFree(_buffers[kBitBack]);
|
|
memFree(_buffers[kBit2]);
|
|
memFree(_buffers[kBit3]);
|
|
|
|
freeCnv(&_font);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
} // namespace Parallaction
|