2009-10-03 20:49:18 +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.
|
|
|
|
*
|
|
|
|
* 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 "sci/sci.h"
|
|
|
|
#include "sci/engine/state.h"
|
|
|
|
#include "sci/tools.h"
|
|
|
|
#include "sci/gui/gui_screen.h"
|
2009-10-06 16:14:40 +00:00
|
|
|
#include "sci/gui/gui_palette.h"
|
2009-10-03 20:49:18 +00:00
|
|
|
#include "sci/gui/gui_gfx.h"
|
|
|
|
#include "sci/gui/gui_picture.h"
|
|
|
|
|
|
|
|
namespace Sci {
|
|
|
|
|
2009-10-06 16:14:40 +00:00
|
|
|
SciGuiPicture::SciGuiPicture(EngineState *state, SciGuiGfx *gfx, SciGuiScreen *screen, SciGuiPalette *palette, GuiResourceId resourceId)
|
|
|
|
: _s(state), _gfx(gfx), _screen(screen), _palette(palette), _resourceId(resourceId) {
|
2009-10-03 20:49:18 +00:00
|
|
|
assert(resourceId != -1);
|
|
|
|
initData(resourceId);
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
SciGuiPicture::~SciGuiPicture() {
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::initData(GuiResourceId resourceId) {
|
2009-10-03 20:49:18 +00:00
|
|
|
_resource = _s->resMan->findResource(ResourceId(kResourceTypePic, resourceId), false);
|
|
|
|
if (!_resource) {
|
|
|
|
error("picture resource %d not found", resourceId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
GuiResourceId SciGuiPicture::getResourceId() {
|
2009-10-03 20:49:18 +00:00
|
|
|
return _resourceId;
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::draw(uint16 style, bool addToFlag, int16 EGApaletteNo) {
|
2009-10-03 20:49:18 +00:00
|
|
|
_style = style;
|
|
|
|
_addToFlag = addToFlag;
|
|
|
|
_EGApaletteNo = EGApaletteNo;
|
|
|
|
_priority = 0;
|
|
|
|
|
|
|
|
if (READ_LE_UINT16(_resource->data) == 0x26) {
|
2009-10-06 06:50:31 +00:00
|
|
|
// SCI 1.1 VGA picture
|
|
|
|
drawSci11Vga();
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-10-06 06:50:31 +00:00
|
|
|
// EGA or Amiga vector data
|
2009-10-03 20:49:18 +00:00
|
|
|
drawVectorData(_resource->data, _resource->size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::reset() {
|
2009-10-03 20:49:18 +00:00
|
|
|
int16 x, y;
|
2009-10-06 14:00:35 +00:00
|
|
|
for (y = _gfx->GetPort()->top; y < _screen->_height; y++) {
|
2009-10-03 20:49:18 +00:00
|
|
|
for (x = 0; x < _screen->_width; x++) {
|
2009-10-05 07:38:05 +00:00
|
|
|
_screen->putPixel(x, y, SCI_SCREEN_MASK_ALL, 255, 0, 0);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-06 06:50:31 +00:00
|
|
|
void SciGuiPicture::drawSci11Vga() {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte *inbuffer = _resource->data;
|
|
|
|
int size = _resource->size;
|
|
|
|
int has_view = READ_LE_UINT16(inbuffer + 4);
|
|
|
|
int vector_data_ptr = READ_LE_UINT16(inbuffer + 16);
|
|
|
|
int vector_size = size - vector_data_ptr;
|
|
|
|
int palette_data_ptr = READ_LE_UINT16(inbuffer + 28);
|
|
|
|
int view_data_ptr = READ_LE_UINT16(inbuffer + 32);
|
|
|
|
int view_size = palette_data_ptr - view_data_ptr;
|
|
|
|
int view_rle_ptr = READ_LE_UINT16(inbuffer + view_data_ptr + 24);
|
|
|
|
int view_pixel_ptr = READ_LE_UINT16(inbuffer + view_data_ptr + 28);
|
|
|
|
byte *view = NULL;
|
2009-10-05 07:10:01 +00:00
|
|
|
GuiPalette palette;
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
// Create palette and set it
|
2009-10-06 16:14:40 +00:00
|
|
|
_palette->createFromData(inbuffer + palette_data_ptr, &palette);
|
|
|
|
_palette->set(&palette, 2);
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
// display Cel-data
|
|
|
|
if (has_view) {
|
|
|
|
view = (byte *)malloc(size*2); // is there a way to know how much decoded view-data there will be?
|
|
|
|
if (!view) return;
|
|
|
|
memcpy(view, inbuffer + view_data_ptr, 8);
|
|
|
|
decodeRLE(inbuffer + view_rle_ptr, inbuffer + view_pixel_ptr, view + 8, view_size - 8);
|
|
|
|
drawCel(0, 0, view, size * 2);
|
|
|
|
free(view);
|
|
|
|
}
|
|
|
|
|
|
|
|
// process vector data
|
|
|
|
drawVectorData(inbuffer + vector_data_ptr, vector_size);
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::decodeRLE(byte *rledata, byte *pixeldata, byte *outbuffer, int size) {
|
2009-10-03 20:49:18 +00:00
|
|
|
int pos = 0;
|
|
|
|
byte nextbyte;
|
|
|
|
byte *rd = rledata;
|
|
|
|
byte *ob = outbuffer;
|
|
|
|
byte *pd = pixeldata;
|
|
|
|
|
|
|
|
while (pos < size) {
|
|
|
|
nextbyte = *(rd++);
|
|
|
|
*(ob++) = nextbyte;
|
|
|
|
pos ++;
|
|
|
|
switch (nextbyte&0xC0) {
|
|
|
|
case 0x40 :
|
|
|
|
case 0x00 :
|
|
|
|
memcpy(ob, pd, nextbyte);
|
|
|
|
pd += nextbyte;
|
|
|
|
ob += nextbyte;
|
|
|
|
pos += nextbyte;
|
|
|
|
break;
|
|
|
|
case 0xC0 :
|
|
|
|
break;
|
|
|
|
case 0x80 :
|
|
|
|
nextbyte = *(pd++);
|
|
|
|
*(ob++) = nextbyte;
|
|
|
|
pos ++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::drawCel(int16 x, int16 y, byte *pdata, int size) {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte* pend = pdata + size;
|
|
|
|
uint16 width = READ_LE_UINT16(pdata + 0);
|
|
|
|
uint16 height = READ_LE_UINT16(pdata + 2);
|
|
|
|
signed char dx = *(pdata + 4);
|
|
|
|
signed char dy = *(pdata + 5);
|
|
|
|
byte priority = _addToFlag ? _priority : 0;
|
2009-10-06 06:50:31 +00:00
|
|
|
byte clearColor = *(pdata + 6);
|
2009-10-03 20:49:18 +00:00
|
|
|
if (dx || dy || width != 320)
|
2009-10-06 06:50:31 +00:00
|
|
|
warning("embedded picture cel has width=%d dx=%d dy=%d", width, dx, dy);
|
2009-10-03 20:49:18 +00:00
|
|
|
byte *ptr = pdata + 8; // offset to data
|
2009-10-06 06:50:31 +00:00
|
|
|
byte byte, runLength;
|
|
|
|
uint16 lasty;
|
2009-10-03 20:49:18 +00:00
|
|
|
|
2009-10-06 14:00:35 +00:00
|
|
|
y += _gfx->GetPort()->top;
|
2009-10-03 20:49:18 +00:00
|
|
|
|
2009-10-06 14:00:35 +00:00
|
|
|
lasty = MIN<int16>(height + y, _gfx->GetPort()->rect.bottom) + _gfx->GetPort()->top;
|
2009-10-06 06:50:31 +00:00
|
|
|
|
|
|
|
switch (_s->resMan->getViewType()) {
|
|
|
|
case kViewVga:
|
|
|
|
case kViewVga11:
|
|
|
|
while (y < lasty && ptr < pend) {
|
|
|
|
byte = *ptr++;
|
|
|
|
runLength = byte & 0x3F; // bytes run length on this step
|
|
|
|
switch (byte & 0xC0) {
|
|
|
|
case 0: // copy bytes as-is but skip transparent ones
|
|
|
|
while (runLength-- && y < lasty && ptr < pend) {
|
|
|
|
if ((byte = *ptr++) != clearColor && priority >= _screen->getPriority(x, y))
|
|
|
|
_screen->putPixel(x, y, 3, byte, priority, 0);
|
|
|
|
x++;
|
|
|
|
if (x >= _screen->_width) {
|
|
|
|
x -= _screen->_width; y++;
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
2009-10-06 06:50:31 +00:00
|
|
|
break;
|
|
|
|
case 0x80: // fill with color
|
|
|
|
byte = *ptr++;
|
|
|
|
while (runLength-- && y < lasty) {
|
|
|
|
if (priority >= _screen->getPriority(x, y)) {
|
|
|
|
_screen->putPixel(x, y, 3, byte, priority, 0);
|
|
|
|
}
|
|
|
|
x++;
|
|
|
|
if (x >= _screen->_width) {
|
|
|
|
x -= _screen->_width; y++;
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
2009-10-06 06:50:31 +00:00
|
|
|
break;
|
|
|
|
case 0xC0: // fill with transparent - skip
|
|
|
|
x += runLength;
|
2009-10-03 20:49:18 +00:00
|
|
|
if (x >= _screen->_width) {
|
|
|
|
x -= _screen->_width; y++;
|
|
|
|
}
|
2009-10-06 06:50:31 +00:00
|
|
|
break;
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
2009-10-06 06:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case kViewAmiga:
|
|
|
|
while (y < lasty && ptr < pend) {
|
|
|
|
byte = *ptr++;
|
|
|
|
if (byte & 0x07) {
|
|
|
|
runLength = byte & 0x07;
|
|
|
|
byte = byte >> 3;
|
|
|
|
while (runLength-- && y < lasty) {
|
|
|
|
if (priority >= _screen->getPriority(x, y)) {
|
|
|
|
_screen->putPixel(x, y, 3, byte, priority, 0);
|
|
|
|
}
|
|
|
|
x++;
|
|
|
|
if (x >= _screen->_width) {
|
|
|
|
x -= _screen->_width; y++;
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
2009-10-06 06:50:31 +00:00
|
|
|
} else {
|
|
|
|
runLength = byte >> 3;
|
|
|
|
x += runLength;
|
2009-10-03 20:49:18 +00:00
|
|
|
if (x >= _screen->_width) {
|
|
|
|
x -= _screen->_width; y++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-06 06:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
error("Unsupported picture viewtype");
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum {
|
|
|
|
PIC_OP_SET_COLOR = 0xf0,
|
|
|
|
PIC_OP_DISABLE_VISUAL = 0xf1,
|
|
|
|
PIC_OP_SET_PRIORITY = 0xf2,
|
|
|
|
PIC_OP_DISABLE_PRIORITY = 0xf3,
|
|
|
|
PIC_OP_SHORT_PATTERNS = 0xf4,
|
|
|
|
PIC_OP_MEDIUM_LINES = 0xf5,
|
|
|
|
PIC_OP_LONG_LINES = 0xf6,
|
|
|
|
PIC_OP_SHORT_LINES = 0xf7,
|
|
|
|
PIC_OP_FILL = 0xf8,
|
|
|
|
PIC_OP_SET_PATTERN = 0xf9,
|
|
|
|
PIC_OP_ABSOLUTE_PATTERN = 0xfa,
|
|
|
|
PIC_OP_SET_CONTROL = 0xfb,
|
|
|
|
PIC_OP_DISABLE_CONTROL = 0xfc,
|
|
|
|
PIC_OP_MEDIUM_PATTERNS = 0xfd,
|
|
|
|
PIC_OP_OPX = 0xfe,
|
|
|
|
PIC_OP_TERMINATE = 0xff
|
|
|
|
};
|
|
|
|
#define PIC_OP_FIRST PIC_OP_SET_COLOR
|
|
|
|
|
|
|
|
enum {
|
2009-10-05 20:21:59 +00:00
|
|
|
PIC_OPX_EGA_SET_PALETTE_ENTRIES = 0,
|
|
|
|
PIC_OPX_EGA_SET_PALETTE = 1,
|
|
|
|
PIC_OPX_EGA_MONO0 = 2,
|
|
|
|
PIC_OPX_EGA_MONO1 = 3,
|
|
|
|
PIC_OPX_EGA_MONO2 = 4,
|
|
|
|
PIC_OPX_EGA_MONO3 = 5,
|
|
|
|
PIC_OPX_EGA_MONO4 = 6,
|
|
|
|
PIC_OPX_EGA_EMBEDDED_VIEW = 7,
|
|
|
|
PIC_OPX_EGA_SET_PRIORITY_TABLE = 8
|
2009-10-03 20:49:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
2009-10-05 20:21:59 +00:00
|
|
|
PIC_OPX_VGA_SET_PALETTE_ENTRIES = 0,
|
|
|
|
PIC_OPX_VGA_EMBEDDED_VIEW = 1,
|
|
|
|
PIC_OPX_VGA_SET_PALETTE = 2,
|
|
|
|
PIC_OPX_VGA_PRIORITY_TABLE_EQDIST = 3,
|
|
|
|
PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT = 4
|
2009-10-03 20:49:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define PIC_EGAPALETTE_COUNT 4
|
|
|
|
#define PIC_EGAPALETTE_SIZE 40
|
|
|
|
#define PIC_EGAPALETTE_TOTALSIZE PIC_EGAPALETTE_COUNT*PIC_EGAPALETTE_SIZE
|
2009-10-06 06:50:31 +00:00
|
|
|
#define PIC_EGAPRIORITY_SIZE PIC_EGAPALETTE_SIZE
|
2009-10-03 20:49:18 +00:00
|
|
|
|
2009-10-04 11:59:29 +00:00
|
|
|
static const byte vector_defaultEGApalette[PIC_EGAPALETTE_SIZE] = {
|
2009-10-03 20:49:18 +00:00
|
|
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
|
|
|
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x88,
|
|
|
|
0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x88,
|
|
|
|
0x88, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
|
|
|
0x08, 0x91, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x88
|
|
|
|
};
|
|
|
|
|
2009-10-06 06:50:31 +00:00
|
|
|
static const byte vector_defaultEGApriority[PIC_EGAPRIORITY_SIZE] = {
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
|
|
|
|
};
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::drawVectorData(byte *data, int dataSize) {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte pic_op;
|
|
|
|
byte pic_color = 0, pic_priority = 0x0F, pic_control = 0x0F;
|
|
|
|
int16 x = 0, y = 0, oldx, oldy;
|
|
|
|
byte EGApalettes[PIC_EGAPALETTE_TOTALSIZE] = {0};
|
2009-10-05 20:02:29 +00:00
|
|
|
byte *EGApalette = &EGApalettes[_EGApaletteNo];
|
2009-10-06 06:50:31 +00:00
|
|
|
byte EGApriority[PIC_EGAPRIORITY_SIZE] = {0};
|
2009-10-05 20:19:07 +00:00
|
|
|
bool isEGA = false;
|
2009-10-03 20:49:18 +00:00
|
|
|
int curPos = 0;
|
|
|
|
uint16 size;
|
|
|
|
byte byte;
|
|
|
|
int i;
|
2009-10-05 07:10:01 +00:00
|
|
|
GuiPalette palette;
|
2009-10-03 20:49:18 +00:00
|
|
|
int16 pattern_Code = 0, pattern_Texture = 0;
|
|
|
|
|
2009-10-04 11:59:29 +00:00
|
|
|
memset(&palette, 0, sizeof(palette));
|
|
|
|
|
2009-10-03 20:49:18 +00:00
|
|
|
if (_EGApaletteNo >= PIC_EGAPALETTE_COUNT)
|
|
|
|
_EGApaletteNo = 0;
|
|
|
|
|
2009-10-06 06:50:31 +00:00
|
|
|
if (_s->resMan->getViewType() == kViewEga) {
|
2009-10-05 20:19:07 +00:00
|
|
|
isEGA = true;
|
2009-10-06 06:50:31 +00:00
|
|
|
// setup default mapping tables
|
|
|
|
for (i = 0; i < PIC_EGAPALETTE_TOTALSIZE; i += PIC_EGAPALETTE_SIZE)
|
|
|
|
memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette));
|
|
|
|
memcpy(&EGApriority, &vector_defaultEGApriority, sizeof(vector_defaultEGApriority));
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
// Drawing
|
|
|
|
while (curPos < dataSize) {
|
2009-10-05 07:48:43 +00:00
|
|
|
//warning("%X at %d", data[curPos], curPos);
|
2009-10-03 20:49:18 +00:00
|
|
|
switch (pic_op = data[curPos++]) {
|
|
|
|
case PIC_OP_SET_COLOR:
|
2009-10-05 22:42:41 +00:00
|
|
|
pic_color = data[curPos++];
|
|
|
|
if (isEGA) {
|
|
|
|
pic_color = EGApalette[pic_color];
|
|
|
|
pic_color ^= pic_color << 4;
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
break;
|
|
|
|
case PIC_OP_DISABLE_VISUAL:
|
|
|
|
pic_color = 0xFF;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_SET_PRIORITY:
|
|
|
|
pic_priority = data[curPos++];
|
2009-10-06 06:50:31 +00:00
|
|
|
if (isEGA) {
|
|
|
|
pic_priority = EGApriority[pic_color];
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
break;
|
|
|
|
case PIC_OP_DISABLE_PRIORITY:
|
|
|
|
pic_priority = 255;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_SET_CONTROL:
|
|
|
|
pic_control = data[curPos++];
|
|
|
|
break;
|
|
|
|
case PIC_OP_DISABLE_CONTROL:
|
|
|
|
pic_control = 255;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_SHORT_LINES: // short line
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
oldx = x; oldy = y;
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoords(data, curPos, x, y);
|
2009-10-06 21:23:24 +00:00
|
|
|
_gfx->drawLine(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_MEDIUM_LINES: // medium line
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
oldx = x; oldy = y;
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoordsMed(data, curPos, x, y);
|
2009-10-06 21:23:24 +00:00
|
|
|
_gfx->drawLine(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_LONG_LINES: // long line
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
2009-10-06 17:17:12 +00:00
|
|
|
oldx = x; oldy = y;
|
2009-10-03 20:49:18 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-06 21:23:24 +00:00
|
|
|
_gfx->drawLine(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_FILL: //fill
|
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
|
|
|
_gfx->Pic_Fill(x, y, pic_color, pic_priority, pic_control);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_SET_PATTERN:
|
|
|
|
pattern_Code = data[curPos++];
|
|
|
|
break;
|
|
|
|
case PIC_OP_SHORT_PATTERNS:
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
|
|
|
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoords(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_MEDIUM_PATTERNS:
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
|
|
|
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoordsMed(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_ABSOLUTE_PATTERN:
|
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-06 13:30:20 +00:00
|
|
|
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_OPX: // Extended functions
|
2009-10-05 20:19:07 +00:00
|
|
|
if (isEGA) {
|
2009-10-03 20:49:18 +00:00
|
|
|
switch (pic_op = data[curPos++]) {
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_SET_PALETTE_ENTRIES:
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
byte = data[curPos++];
|
|
|
|
if (byte >= PIC_EGAPALETTE_TOTALSIZE) {
|
|
|
|
error("picture trying to write to invalid EGA-palette");
|
|
|
|
}
|
|
|
|
EGApalettes[byte] = data[curPos++];
|
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_SET_PALETTE:
|
2009-10-03 20:49:18 +00:00
|
|
|
byte = data[curPos++];
|
2009-10-05 20:02:29 +00:00
|
|
|
if (byte >= PIC_EGAPALETTE_COUNT) {
|
2009-10-05 21:47:28 +00:00
|
|
|
error("picture trying to write to invalid palette %d", (int)byte);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
byte *= PIC_EGAPALETTE_SIZE;
|
|
|
|
for (i = 0; i < PIC_EGAPALETTE_SIZE; i++) {
|
|
|
|
EGApalettes[byte + i] = data[curPos++];
|
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_MONO0:
|
2009-10-03 20:49:18 +00:00
|
|
|
curPos += 41;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_MONO1:
|
|
|
|
case PIC_OPX_EGA_MONO3:
|
2009-10-03 20:49:18 +00:00
|
|
|
curPos++;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_MONO2:
|
|
|
|
case PIC_OPX_EGA_MONO4:
|
2009-10-03 20:49:18 +00:00
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_EMBEDDED_VIEW:
|
2009-10-03 20:49:18 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
|
|
|
size = READ_LE_UINT16(data + curPos); curPos += 2;
|
|
|
|
drawCel(x, y, data + curPos, size);
|
|
|
|
curPos += size;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_SET_PRIORITY_TABLE:
|
2009-10-03 20:49:18 +00:00
|
|
|
//FIXME
|
|
|
|
//g_sci->PriBands(ptr);
|
|
|
|
curPos += 14;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Unsupported sci1 extended pic-operation %X", pic_op);
|
|
|
|
}
|
2009-10-05 20:19:07 +00:00
|
|
|
} else {
|
|
|
|
switch (pic_op = data[curPos++]) {
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_SET_PALETTE_ENTRIES:
|
2009-10-05 20:19:07 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
curPos++; // skip commands
|
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_SET_PALETTE:
|
2009-10-05 20:19:07 +00:00
|
|
|
curPos += 256 + 4; // Skip over mapping and timestamp
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
palette.colors[i].used = data[curPos++];
|
|
|
|
palette.colors[i].r = data[curPos++]; palette.colors[i].g = data[curPos++]; palette.colors[i].b = data[curPos++];
|
|
|
|
}
|
2009-10-06 16:14:40 +00:00
|
|
|
_palette->set(&palette, 2);
|
2009-10-05 20:19:07 +00:00
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_EMBEDDED_VIEW: // draw cel
|
2009-10-05 20:19:07 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
|
|
|
size = READ_LE_UINT16(data + curPos); curPos += 2;
|
|
|
|
drawCel(x, y, data + curPos, size);
|
|
|
|
curPos += size;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_PRIORITY_TABLE_EQDIST:
|
2009-10-05 20:19:07 +00:00
|
|
|
//FIXME
|
|
|
|
//g_sci->InitPri(READ_LE_UINT16(ptr), READ_LE_UINT16(ptr + 2));
|
2009-10-06 06:50:31 +00:00
|
|
|
debug(5, "DrawPic::InitPri %d %d",
|
2009-10-05 20:19:07 +00:00
|
|
|
READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2));
|
|
|
|
curPos += 4;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT:
|
2009-10-05 20:19:07 +00:00
|
|
|
//FIXME
|
|
|
|
//g_sci->PriBands(ptr);
|
|
|
|
curPos += 14;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Unsupported sci1 extended pic-operation %X", pic_op);
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_TERMINATE:
|
|
|
|
_priority = pic_priority;
|
2009-10-05 21:38:51 +00:00
|
|
|
// Dithering EGA pictures
|
|
|
|
if (isEGA) {
|
|
|
|
_screen->dither();
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
return;
|
|
|
|
default:
|
|
|
|
error("Unsupported pic-operation %X", pic_op);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
error("picture vector data without terminator");
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
bool SciGuiPicture::vectorIsNonOpcode(byte byte) {
|
2009-10-03 20:49:18 +00:00
|
|
|
if (byte >= PIC_OP_FIRST)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y) {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte byte = data[curPos++];
|
|
|
|
x = data[curPos++] + ((byte & 0xF0) << 4);
|
|
|
|
y = data[curPos++] + ((byte & 0x0F) << 8);
|
|
|
|
if (_style & PIC_STYLE_MIRRORED) x = 319 - x;
|
|
|
|
}
|
|
|
|
|
2009-10-06 17:17:12 +00:00
|
|
|
void SciGuiPicture::vectorGetRelCoords(byte *data, int &curPos, int16 &x, int16 &y) {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte byte = data[curPos++];
|
|
|
|
if (byte & 0x80) {
|
2009-10-06 17:17:12 +00:00
|
|
|
x -= ((byte >> 4) & 7) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-10-06 17:17:12 +00:00
|
|
|
x += (byte >> 4) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
if (byte & 0x08) {
|
2009-10-06 17:17:12 +00:00
|
|
|
y -= (byte & 7);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-10-06 17:17:12 +00:00
|
|
|
y += (byte & 7);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-06 17:17:12 +00:00
|
|
|
void SciGuiPicture::vectorGetRelCoordsMed(byte *data, int &curPos, int16 &x, int16 &y) {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte byte = data[curPos++];
|
|
|
|
if (byte & 0x80) {
|
2009-10-06 17:17:12 +00:00
|
|
|
y -= (byte & 0x7F);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-10-06 17:17:12 +00:00
|
|
|
y += byte;
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
byte = data[curPos++];
|
|
|
|
if (byte & 0x80) {
|
2009-10-06 17:17:12 +00:00
|
|
|
x -= (128 - (byte & 0x7F)) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-10-06 17:17:12 +00:00
|
|
|
x += byte * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-05 07:10:01 +00:00
|
|
|
void SciGuiPicture::vectorGetPatternTexture(byte *data, int &curPos, int16 pattern_Code, int16 &pattern_Texture) {
|
2009-10-03 20:49:18 +00:00
|
|
|
if (pattern_Code & SCI_PATTERN_CODE_USE_TEXTURE) {
|
|
|
|
pattern_Texture = (data[curPos++] >> 1) & 0x7f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-07 12:47:53 +00:00
|
|
|
#if 0
|
|
|
|
void SciGuiGfx::Pic_Fill(int16 x, int16 y, byte color, byte prio, byte control) {
|
|
|
|
|
|
|
|
void SciGuiPicture::vectorFloodFillRecursive(byte *data, int &curPos, int16 &x, int16 &y) {
|
|
|
|
|
|
|
|
void FILL_FUNCTION_RECURSIVE(gfxr_pic_t *pic, int old_xl, int old_xr, int y, int dy, byte *bounds,
|
|
|
|
int legalcolor, int legalmask, int color, int priority, int drawenable, int sci_titlebar_size) {
|
|
|
|
int linewidth = pic->mode->scaleFactor * 320;
|
|
|
|
int miny = pic->mode->scaleFactor * sci_titlebar_size;
|
|
|
|
int maxy = pic->mode->scaleFactor * 200;
|
|
|
|
int xl, xr;
|
|
|
|
int oldytotal = y * linewidth;
|
|
|
|
|
|
|
|
do {
|
|
|
|
int ytotal = oldytotal + (linewidth * dy);
|
|
|
|
int xcont;
|
|
|
|
int state;
|
|
|
|
|
|
|
|
y += dy;
|
|
|
|
|
|
|
|
if (y < miny || y >= maxy) {
|
|
|
|
error("ABRT on failed initial assertion!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
# define proj_xl_bound 0
|
|
|
|
# define proj_xr_bound 319
|
|
|
|
|
|
|
|
// Now we have the projected limits, get the real ones:
|
|
|
|
|
|
|
|
xl = (old_xl > proj_xl_bound) ? old_xl : proj_xl_bound;
|
|
|
|
if (!IS_BOUNDARY(xl, y + 1, bounds[ytotal + xl])) { // go left as far as possible
|
|
|
|
while (xl > proj_xl_bound && (!IS_BOUNDARY(xl - 1, y + 1, bounds[ytotal + xl - 1])))
|
|
|
|
--xl;
|
|
|
|
} else // go right until the fillable area starts
|
|
|
|
while (xl < proj_xr_bound && (IS_BOUNDARY(xl, y + 1, bounds[ytotal + xl])))
|
|
|
|
++xl;
|
|
|
|
|
|
|
|
|
|
|
|
if ((xl > proj_xr_bound)
|
|
|
|
|| (xl > old_xr)) {
|
|
|
|
error("ABRT because xl > xr_bound");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xr = (xl > old_xl) ? xl : old_xl;
|
|
|
|
while (xr < proj_xr_bound && (!IS_BOUNDARY(xr + 1, y + 1, bounds[ytotal + xr + 1])))
|
|
|
|
++xr;
|
|
|
|
|
|
|
|
PRINT_DEBUG1("%d> -> ", xr);
|
|
|
|
|
|
|
|
if (IS_BOUNDARY(xl, y + 1, bounds[ytotal + xl])) {
|
|
|
|
error("ABRT because xl illegal");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawenable & GFX_MASK_VISUAL)
|
|
|
|
memset(pic->visual_map->index_data + ytotal + xl, color, xr - xl + 1);
|
|
|
|
|
|
|
|
if (drawenable & GFX_MASK_PRIORITY)
|
|
|
|
memset(pic->priority_map->index_data + ytotal + xl, priority, xr - xl + 1);
|
|
|
|
|
|
|
|
|
|
|
|
// Check whether we need to recurse on branches in the same direction
|
|
|
|
state = 0;
|
|
|
|
xcont = xr + 1;
|
|
|
|
while (xcont <= old_xr) {
|
|
|
|
if (IS_BOUNDARY(xcont, y + 1, bounds[ytotal + xcont]))
|
|
|
|
state = xcont;
|
|
|
|
else if (state) { // recurse
|
|
|
|
vectorFloodFillRecursive(pic, state, xcont, y - dy, dy, bounds, legalcolor,
|
|
|
|
legalmask, color, priority, drawenable, sci_titlebar_size);
|
|
|
|
state = 0;
|
|
|
|
}
|
|
|
|
++xcont;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether we need to recurse on backward branches:
|
|
|
|
// left
|
|
|
|
if (xl < old_xl - 1) {
|
|
|
|
state = 0;
|
|
|
|
for (xcont = old_xl - 1; xcont >= xl; xcont--) {
|
|
|
|
if (IS_BOUNDARY(xcont, y, bounds[oldytotal + xcont]))
|
|
|
|
state = xcont;
|
|
|
|
else if (state) { // recurse
|
|
|
|
vectorFloodFillRecursive(pic, xcont, state, y, -dy, bounds,
|
|
|
|
legalcolor, legalmask, color, priority, drawenable,
|
|
|
|
sci_titlebar_size);
|
|
|
|
state = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// right
|
|
|
|
if (xr > old_xr + 1) {
|
|
|
|
state = 0;
|
|
|
|
for (xcont = old_xr + 1; xcont <= xr; xcont++) {
|
|
|
|
if (IS_BOUNDARY(xcont, y, bounds[oldytotal + xcont]))
|
|
|
|
state = xcont;
|
|
|
|
else if (state) { // recurse
|
|
|
|
vectorFloodFillRecursive(pic, state, xcont, y, -dy, bounds,
|
|
|
|
legalcolor, legalmask, color, priority, drawenable,
|
|
|
|
sci_titlebar_size);
|
|
|
|
state = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
oldytotal = ytotal;
|
|
|
|
old_xl = xl;
|
|
|
|
old_xr = xr;
|
|
|
|
|
|
|
|
} while (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SciGuiPicture::vectorFloodFillRecursive(gfxr_pic_t *pic, int x_320, int y_200, int color, int priority, int control, int drawenable,
|
|
|
|
int sci_titlebar_size) {
|
|
|
|
int linewidth = pic->mode->scaleFactor * 320;
|
|
|
|
int x, y;
|
|
|
|
int xl, xr;
|
|
|
|
int ytotal;
|
|
|
|
int bitmask;
|
|
|
|
byte *bounds = NULL;
|
|
|
|
int legalcolor, legalmask;
|
|
|
|
int original_drawenable = drawenable; // Backup, since we need the unmodified value
|
|
|
|
// for filling the aux and control map
|
|
|
|
|
|
|
|
// Restrict drawenable not to restrict itself to zero
|
|
|
|
if (pic->control_map->index_data[y_200 * 320 + x_320] != 0)
|
|
|
|
drawenable &= ~GFX_MASK_CONTROL;
|
|
|
|
|
|
|
|
if (color == 0xff)
|
|
|
|
drawenable &= ~GFX_MASK_VISUAL;
|
|
|
|
|
|
|
|
if (priority == 0) {
|
|
|
|
drawenable &= ~GFX_MASK_PRIORITY;
|
|
|
|
original_drawenable &= ~GFX_MASK_PRIORITY;
|
|
|
|
}
|
|
|
|
|
|
|
|
AUXBUF_FILL(pic, x_320, y_200, original_drawenable, (drawenable & GFX_MASK_CONTROL) ? control : 0,
|
|
|
|
sci_titlebar_size);
|
|
|
|
|
|
|
|
x = x_320;
|
|
|
|
y = y_200;
|
|
|
|
|
|
|
|
ytotal = y * linewidth;
|
|
|
|
|
|
|
|
if (!drawenable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (drawenable & GFX_MASK_VISUAL) {
|
|
|
|
bounds = pic->visual_map->index_data;
|
|
|
|
legalmask = 0x0ff0;
|
|
|
|
legalcolor = 0xff;
|
|
|
|
} else if (drawenable & GFX_MASK_PRIORITY) {
|
|
|
|
bounds = pic->priority_map->index_data;
|
|
|
|
legalcolor = 0;
|
|
|
|
legalmask = 0x0f0f;
|
|
|
|
} else {
|
|
|
|
legalcolor = 0;
|
|
|
|
legalmask = 0x0f0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bounds || IS_BOUNDARY(x, y, bounds[ytotal + x]))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (bounds) {
|
|
|
|
xl = x;
|
|
|
|
while (xl > proj_xl_bound && (!IS_BOUNDARY(xl - 1, y, bounds[ytotal + xl -1])))
|
|
|
|
--xl;
|
|
|
|
|
|
|
|
while (x < proj_xr_bound && (!IS_BOUNDARY(x + 1, y, bounds[ytotal + x + 1])))
|
|
|
|
++x;
|
|
|
|
xr = x;
|
|
|
|
|
|
|
|
if (drawenable & GFX_MASK_VISUAL)
|
|
|
|
memset(pic->visual_map->index_data + ytotal + xl, color, xr - xl + 1);
|
|
|
|
|
|
|
|
if (drawenable & GFX_MASK_PRIORITY)
|
|
|
|
memset(pic->priority_map->index_data + ytotal + xl, priority, xr - xl + 1);
|
|
|
|
|
|
|
|
vectorFloodFillRecursive(pic, xl, xr, y, -1, bounds, legalcolor, legalmask, color, priority, drawenable,
|
|
|
|
sci_titlebar_size);
|
|
|
|
vectorFloodFillRecursive(pic, xl, xr, y, + 1, bounds, legalcolor, legalmask, color, priority, drawenable,
|
|
|
|
sci_titlebar_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-10-04 21:26:33 +00:00
|
|
|
} // End of namespace Sci
|