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_gfx.h"
|
|
|
|
#include "sci/gui/gui_screen.h"
|
|
|
|
#include "sci/gui/gui_view.h"
|
|
|
|
|
|
|
|
namespace Sci {
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
SciGUIview::SciGUIview(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, GUIResourceId resourceId)
|
2009-10-03 20:49:18 +00:00
|
|
|
: _system(system), _s(state), _gfx(gfx), _screen(screen), _resourceId(resourceId) {
|
|
|
|
assert(resourceId != -1);
|
|
|
|
initData(resourceId);
|
|
|
|
}
|
|
|
|
|
|
|
|
SciGUIview::~SciGUIview() {
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
void SciGUIview::initData(GUIResourceId resourceId) {
|
2009-10-03 20:49:18 +00:00
|
|
|
Resource *viewResource = _s->resMan->findResource(ResourceId(kResourceTypeView, resourceId), false);
|
|
|
|
if (!viewResource) {
|
|
|
|
error("view resource %d not found", resourceId);
|
|
|
|
}
|
|
|
|
_resourceData = viewResource->data;
|
|
|
|
|
|
|
|
byte *cellData, *loopData;
|
|
|
|
uint16 cellOffset;
|
|
|
|
sciViewCellInfo *cell;
|
|
|
|
uint16 cellCount = 0;
|
|
|
|
uint16 mirrorBits = 0;
|
|
|
|
uint16 palOffset = 0;
|
|
|
|
uint16 headerSize = 0;
|
|
|
|
uint16 loopSize = 0, cellSize = 0;
|
|
|
|
int loopNo, cellNo;
|
|
|
|
int16 version;
|
|
|
|
byte seekEntry;
|
|
|
|
|
|
|
|
_embeddedPal = false;
|
|
|
|
_loopCount = 0;
|
|
|
|
|
|
|
|
version = READ_LE_UINT16(_resourceData + 4);
|
|
|
|
switch (version) {
|
|
|
|
case 0: // View-format SCI1
|
|
|
|
// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
|
|
|
|
|
|
|
|
// bit 0x8000 of _resourceData[1] means palette is set
|
|
|
|
_loopCount = _resourceData[0];
|
|
|
|
mirrorBits = READ_LE_UINT16(_resourceData + 2);
|
|
|
|
palOffset = READ_LE_UINT16(_resourceData + 6);
|
|
|
|
|
|
|
|
if (palOffset && palOffset != 0x100) {
|
2009-10-04 05:20:56 +00:00
|
|
|
_gfx->CreatePaletteFromData(&_resourceData[palOffset], &_palette);
|
2009-10-03 20:49:18 +00:00
|
|
|
_embeddedPal = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
_loop = new sciViewLoopInfo[_loopCount];
|
|
|
|
for (loopNo = 0; loopNo < _loopCount; loopNo++) {
|
|
|
|
loopData = _resourceData + READ_LE_UINT16(_resourceData + 8 + loopNo * 2);
|
|
|
|
// CellCount:WORD Unknown:WORD CellOffset0:WORD CellOffset1:WORD...
|
|
|
|
|
|
|
|
cellCount = READ_LE_UINT16(loopData);
|
|
|
|
_loop[loopNo].cellCount = cellCount;
|
|
|
|
_loop[loopNo].mirrorFlag = mirrorBits & 1 ? true : false;
|
|
|
|
mirrorBits >>= 1;
|
|
|
|
|
|
|
|
// read cel info
|
|
|
|
_loop[loopNo].cell = new sciViewCellInfo[cellCount];
|
|
|
|
for (cellNo = 0; cellNo < cellCount; cellNo++) {
|
|
|
|
cellOffset = READ_LE_UINT16(loopData + 4 + cellNo * 2);
|
|
|
|
cellData = _resourceData + cellOffset;
|
|
|
|
|
|
|
|
cell = &_loop[loopNo].cell[cellNo];
|
|
|
|
cell->width = READ_LE_UINT16(cellData);
|
|
|
|
cell->height = READ_LE_UINT16(cellData + 2);
|
|
|
|
cell->displaceX = cellData[4];
|
|
|
|
cell->displaceY = cellData[5];
|
|
|
|
cell->clearKey = cellData[6];
|
|
|
|
cell->offsetRLE = cellOffset + 8;
|
|
|
|
cell->offsetLiteral = 0;
|
|
|
|
cell->rawBitmap = 0;
|
|
|
|
if (_loop[loopNo].mirrorFlag)
|
|
|
|
cell->displaceX = -cell->displaceX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: // View-format SCI1.1
|
|
|
|
// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
|
|
|
|
// HeaderSize:WORD LoopCount:WORD Version:WORD Unknown:WORD PaletteOffset:WORD
|
|
|
|
headerSize = READ_LE_UINT16(_resourceData + 0);
|
|
|
|
_loopCount = READ_LE_UINT16(_resourceData + 2);
|
|
|
|
palOffset = READ_LE_UINT16(_resourceData + 8);
|
|
|
|
|
|
|
|
loopData = _resourceData + headerSize;
|
|
|
|
loopSize = _resourceData[12];
|
|
|
|
cellSize = _resourceData[13];
|
|
|
|
|
|
|
|
if (palOffset) {
|
2009-10-04 05:20:56 +00:00
|
|
|
_gfx->CreatePaletteFromData(&_resourceData[palOffset], &_palette);
|
2009-10-03 20:49:18 +00:00
|
|
|
_embeddedPal = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
_loop = new sciViewLoopInfo[_loopCount];
|
|
|
|
for (loopNo = 0; loopNo < _loopCount; loopNo++) {
|
|
|
|
loopData = _resourceData + headerSize + (loopNo * loopSize);
|
|
|
|
|
|
|
|
seekEntry = loopData[2];
|
|
|
|
if (seekEntry != 255) {
|
|
|
|
loopData = _resourceData + headerSize + (seekEntry * loopNo);
|
|
|
|
}
|
|
|
|
|
|
|
|
cellCount = loopData[4];
|
|
|
|
_loop[loopNo].cellCount = cellCount;
|
|
|
|
_loop[loopNo].mirrorFlag = false;
|
|
|
|
|
|
|
|
cellData = _resourceData + READ_LE_UINT16(loopData + 14);
|
|
|
|
|
|
|
|
// read cel info
|
|
|
|
_loop[loopNo].cell = new sciViewCellInfo[cellCount];
|
|
|
|
for (cellNo = 0; cellNo < cellCount; cellNo++) {
|
|
|
|
cell = &_loop[loopNo].cell[cellNo];
|
|
|
|
cell->width = READ_LE_UINT16(cellData);
|
|
|
|
cell->height = READ_LE_UINT16(cellData + 2);
|
|
|
|
cell->displaceX = READ_LE_UINT16(cellData + 4);
|
|
|
|
cell->displaceY = READ_LE_UINT16(cellData + 6);
|
|
|
|
cell->clearKey = cellData[8];
|
|
|
|
cell->offsetRLE = READ_LE_UINT16(cellData + 24);
|
|
|
|
cell->offsetLiteral = READ_LE_UINT16(cellData + 28);
|
|
|
|
cell->rawBitmap = 0;
|
|
|
|
if (_loop[loopNo].mirrorFlag)
|
|
|
|
cell->displaceX = -cell->displaceX;
|
|
|
|
|
|
|
|
cellData += cellSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
GUIResourceId SciGUIview::getResourceId() {
|
2009-10-03 20:49:18 +00:00
|
|
|
return _resourceId;
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
int16 SciGUIview::getWidth(GUIViewLoopNo loopNo, GUIViewCellNo cellNo) {
|
2009-10-03 20:49:18 +00:00
|
|
|
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
|
2009-10-04 11:59:29 +00:00
|
|
|
if (cellNo >= _loop[loopNo].cellCount)
|
2009-10-03 20:49:18 +00:00
|
|
|
cellNo = 0;
|
|
|
|
return _loopCount ? _loop[loopNo].cell[cellNo].width : 0;
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
int16 SciGUIview::getHeight(GUIViewLoopNo loopNo, GUIViewCellNo cellNo) {
|
2009-10-03 20:49:18 +00:00
|
|
|
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
|
2009-10-04 11:59:29 +00:00
|
|
|
if (cellNo >= _loop[loopNo].cellCount)
|
2009-10-03 20:49:18 +00:00
|
|
|
cellNo = 0;
|
|
|
|
return _loopCount ? _loop[loopNo].cell[cellNo].height : 0;
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
sciViewCellInfo *SciGUIview::getCellInfo(GUIViewLoopNo loopNo, GUIViewCellNo cellNo) {
|
2009-10-04 15:34:43 +00:00
|
|
|
loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
|
2009-10-04 11:59:29 +00:00
|
|
|
if (cellNo >= _loop[loopNo].cellCount)
|
2009-10-03 20:49:18 +00:00
|
|
|
cellNo = 0;
|
|
|
|
return _loopCount ? &_loop[loopNo].cell[cellNo] : NULL;
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
sciViewLoopInfo *SciGUIview::getLoopInfo(GUIViewLoopNo loopNo) {
|
2009-10-04 15:34:43 +00:00
|
|
|
loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
|
|
|
|
return _loopCount ? &_loop[loopNo] : NULL;
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
void SciGUIview::getCellRect(GUIViewLoopNo loopNo, GUIViewCellNo cellNo, int16 x, int16 y, int16 z, Common::Rect *outRect) {
|
2009-10-04 15:34:43 +00:00
|
|
|
sciViewCellInfo *cellInfo = getCellInfo(loopNo, cellNo);
|
|
|
|
if (cellInfo) {
|
|
|
|
outRect->left = x + cellInfo->displaceX - (cellInfo->width >> 1);
|
|
|
|
outRect->right = outRect->left + cellInfo->width;
|
|
|
|
outRect->bottom = y + cellInfo->displaceY - z + 1;
|
|
|
|
outRect->top = outRect->bottom - cellInfo->height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
void SciGUIview::unpackView(GUIViewLoopNo loopNo, GUIViewCellNo cellNo, byte *outPtr, uint16 pixelCount) {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte *rlePtr = _resourceData + _loop[loopNo].cell[cellNo].offsetRLE;
|
|
|
|
byte *literalPtr = _resourceData + _loop[loopNo].cell[cellNo].offsetLiteral;
|
|
|
|
uint16 pixelNo = 0, brun;
|
|
|
|
byte b;
|
|
|
|
|
|
|
|
if (literalPtr == _resourceData) { // no extra literal data
|
|
|
|
while (pixelNo < pixelCount) {
|
|
|
|
b = *rlePtr++;
|
|
|
|
brun = b & 0x3F; // bytes run length on this step
|
|
|
|
switch (b & 0xC0) {
|
|
|
|
case 0: // copy bytes as-is
|
|
|
|
while (brun-- && pixelNo < pixelCount)
|
|
|
|
outPtr[pixelNo++] = *rlePtr++;
|
|
|
|
break;
|
|
|
|
case 0x80: // fill with color
|
|
|
|
memset(outPtr + pixelNo, *rlePtr++, MIN<uint16>(brun, pixelCount - pixelNo));
|
|
|
|
pixelNo += brun;
|
|
|
|
break;
|
|
|
|
case 0xC0: // fill with transparent
|
|
|
|
pixelNo += brun;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (pixelNo < pixelCount) {
|
|
|
|
b = *rlePtr++;
|
|
|
|
brun = b & 0x3F; // bytes run length on this step
|
|
|
|
switch (b & 0xC0) {
|
|
|
|
case 0: // copy bytes as-is
|
|
|
|
while (brun-- && pixelNo < pixelCount)
|
|
|
|
outPtr[pixelNo++] = *literalPtr++;
|
|
|
|
break;
|
|
|
|
case 0x80: // fill with color
|
|
|
|
memset(outPtr + pixelNo, *literalPtr++, MIN<uint16>(brun, pixelCount - pixelNo));
|
|
|
|
pixelNo += brun;
|
|
|
|
break;
|
|
|
|
case 0xC0: // fill with transparent
|
|
|
|
pixelNo += brun;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
byte *SciGUIview::getBitmap(GUIViewLoopNo loopNo, GUIViewCellNo cellNo) {
|
2009-10-03 20:49:18 +00:00
|
|
|
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
|
2009-10-04 11:59:29 +00:00
|
|
|
if (cellNo >= _loop[loopNo].cellCount)
|
2009-10-03 20:49:18 +00:00
|
|
|
cellNo = 0;
|
|
|
|
if (_loop[loopNo].cell[cellNo].rawBitmap)
|
|
|
|
return _loop[loopNo].cell[cellNo].rawBitmap;
|
|
|
|
|
|
|
|
uint16 width = _loop[loopNo].cell[cellNo].width;
|
|
|
|
uint16 height = _loop[loopNo].cell[cellNo].height;
|
|
|
|
// allocating memory to store cel's bitmap
|
|
|
|
assert(width * height <= 64000);
|
|
|
|
uint16 pixelCount = width * height;
|
|
|
|
_loop[loopNo].cell[cellNo].rawBitmap = new byte[pixelCount];
|
|
|
|
byte *pOut = _loop[loopNo].cell[cellNo].rawBitmap;
|
|
|
|
|
|
|
|
memset(pOut, _loop[loopNo].cell[cellNo].clearKey, pixelCount);
|
|
|
|
//if (g_sci->getPlatform() == Common::kPlatformAmiga)
|
|
|
|
// unpackViewAmiga(ptr, pOut, pixelCount);
|
|
|
|
//else
|
|
|
|
unpackView(loopNo, cellNo, pOut, pixelCount);
|
|
|
|
|
|
|
|
// mirroring the view if needed
|
|
|
|
if (_loop[loopNo].mirrorFlag) {
|
|
|
|
for (int i = 0; i < height; i++, pOut += width)
|
|
|
|
for (int j = 0; j < width / 2; j++)
|
|
|
|
SWAP(pOut[j], pOut[width - j - 1]);
|
|
|
|
}
|
|
|
|
return _loop[loopNo].cell[cellNo].rawBitmap;
|
|
|
|
}
|
|
|
|
|
2009-10-04 16:41:53 +00:00
|
|
|
void SciGUIview::draw(Common::Rect rect, Common::Rect clipRect, GUIViewLoopNo loopNo, GUIViewCellNo cellNo, byte priority, uint16 paletteNo) {
|
|
|
|
GUIPalette *palette = _embeddedPal ? &_palette : &_gfx->_sysPalette;
|
2009-10-03 20:49:18 +00:00
|
|
|
sciViewCellInfo *cellInfo = getCellInfo(loopNo, cellNo);
|
|
|
|
byte *bitmap = getBitmap(loopNo, cellNo);
|
|
|
|
int16 cellHeight = cellInfo->height, cellWidth = cellInfo->width;
|
|
|
|
int16 width, height;
|
|
|
|
byte clearKey = cellInfo->clearKey;
|
|
|
|
byte color;
|
|
|
|
byte drawMask = priority == 255 ? SCI_SCREEN_MASK_VISUAL : SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY;
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
// Merge view palette in...
|
|
|
|
if (_embeddedPal)
|
|
|
|
_gfx->SetPalette(&_palette, 1);
|
|
|
|
|
|
|
|
width = MIN(clipRect.width(), cellWidth);
|
|
|
|
height = MIN(clipRect.height(), cellHeight);
|
|
|
|
|
|
|
|
bitmap += (clipRect.top - rect.top) * cellWidth + (clipRect.left - rect.left);
|
|
|
|
_gfx->OffsetRect(clipRect);
|
|
|
|
|
|
|
|
for (y = clipRect.top; y < clipRect.top + height; y++, bitmap += cellWidth) {
|
|
|
|
for (x = 0; x < width; x++) {
|
|
|
|
color = bitmap[x];
|
|
|
|
if (color != clearKey && priority >= _screen->Get_Priority(clipRect.left + x, y))
|
|
|
|
_screen->Put_Pixel(clipRect.left + x, y, drawMask, palette->mapping[color], priority, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end of namespace Sci
|