aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/view.cpp
diff options
context:
space:
mode:
authorTony Puccinelli2010-08-10 23:21:08 +0000
committerTony Puccinelli2010-08-10 23:21:08 +0000
commit682807f0e916b189c69b60765418ee1ccc327cbf (patch)
treee8b220b934f6b14d4dac290181fce0c1b209579a /engines/sci/graphics/view.cpp
parent83f1531cb8fa5ba43c246143ecdde2cb1d140a8e (diff)
parentfffec23a02cc88ed8daba0a3b50007b7e220c075 (diff)
downloadscummvm-rg350-682807f0e916b189c69b60765418ee1ccc327cbf.tar.gz
scummvm-rg350-682807f0e916b189c69b60765418ee1ccc327cbf.tar.bz2
scummvm-rg350-682807f0e916b189c69b60765418ee1ccc327cbf.zip
merged trunk into branch, reverted Cruise Singleton changes
svn-id: r51961
Diffstat (limited to 'engines/sci/graphics/view.cpp')
-rw-r--r--engines/sci/graphics/view.cpp483
1 files changed, 286 insertions, 197 deletions
diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp
index 2ba14fbd8f..1c865f6bcf 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -28,6 +28,7 @@
#include "sci/engine/state.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/coordadjuster.h"
#include "sci/graphics/view.h"
namespace Sci {
@@ -35,6 +36,7 @@ namespace Sci {
GfxView::GfxView(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId)
: _resMan(resMan), _screen(screen), _palette(palette), _resourceId(resourceId) {
assert(resourceId != -1);
+ _coordAdjuster = g_sci->_gfxCoordAdjuster;
initData(resourceId);
}
@@ -62,6 +64,7 @@ void GfxView::initData(GuiResourceId resourceId) {
error("view resource %d not found", resourceId);
}
_resourceData = _resource->data;
+ _resourceSize = _resource->size;
byte *celData, *loopData;
uint16 celOffset;
@@ -75,12 +78,32 @@ void GfxView::initData(GuiResourceId resourceId) {
byte seekEntry;
bool isEGA = false;
bool isCompressed = true;
+ ViewType curViewType = _resMan->getViewType();
_loopCount = 0;
_embeddedPal = false;
_EGAmapping = NULL;
+ _isSci2Hires = false;
+ _isScaleable = true;
+
+ // we adjust inside getCelRect for SCI0EARLY (that version didn't have the +1 when calculating bottom)
+ _adjustForSci0Early = getSciVersion() == SCI_VERSION_0_EARLY ? -1 : 0;
+
+ // If we find an SCI1/SCI1.1 view (not amiga), we switch to that type for
+ // EGA. This could get used to make view patches for EGA games, where the
+ // new views include more colors. Users could manually adjust old views to
+ // make them look better (like removing dithered colors that aren't caught
+ // by our undithering or even improve the graphics overall).
+ if (curViewType == kViewEga) {
+ if (_resourceData[1] == 0x80) {
+ curViewType = kViewVga;
+ } else {
+ if (READ_LE_UINT16(_resourceData + 4) == 1)
+ curViewType = kViewVga11;
+ }
+ }
- switch (_resMan->getViewType()) {
+ switch (curViewType) {
case kViewEga: // View-format SCI0 (and Amiga 16 colors)
isEGA = true;
case kViewAmiga: // View-format Amiga (32 colors)
@@ -95,19 +118,21 @@ void GfxView::initData(GuiResourceId resourceId) {
palOffset = READ_LE_UINT16(_resourceData + 6);
if (palOffset && palOffset != 0x100) {
- // Some SCI0/SCI01 games also have an offset set. It seems that it points to a 16-byte mapping table
- // but on those games using that mapping will actually screw things up.
- // On the other side: vga sci1 games have this pointing to a VGA palette
- // and ega sci1 games have this pointing to a 8x16 byte mapping table that needs to get applied then
+ // Some SCI0/SCI01 games also have an offset set. It seems that it
+ // points to a 16-byte mapping table but on those games using that
+ // mapping will actually screw things up. On the other side: VGA
+ // SCI1 games have this pointing to a VGA palette and EGA SCI1 games
+ // have this pointing to a 8x16 byte mapping table that needs to get
+ // applied then.
if (!isEGA) {
- _palette->createFromData(&_resourceData[palOffset], &_viewPalette);
+ _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette);
_embeddedPal = true;
} else {
// Only use the EGA-mapping, when being SCI1
if (getSciVersion() >= SCI_VERSION_1_EGA) {
_EGAmapping = &_resourceData[palOffset];
for (EGAmapNr = 0; EGAmapNr < SCI_VIEW_EGAMAPPING_COUNT; EGAmapNr++) {
- if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE)!=0)
+ if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE) != 0)
break;
_EGAmapping += SCI_VIEW_EGAMAPPING_SIZE;
}
@@ -141,8 +166,8 @@ void GfxView::initData(GuiResourceId resourceId) {
// For EGA
// Width:WORD Height:WORD DisplaceX:BYTE DisplaceY:BYTE ClearKey:BYTE EGAData starts now directly
cel = &_loop[loopNo].cel[celNo];
- cel->width = READ_LE_UINT16(celData);
- cel->height = READ_LE_UINT16(celData + 2);
+ cel->scriptWidth = cel->width = READ_LE_UINT16(celData);
+ cel->scriptHeight = cel->height = READ_LE_UINT16(celData + 2);
cel->displaceX = (signed char)celData[4];
cel->displaceY = celData[5];
cel->clearKey = celData[6];
@@ -168,13 +193,30 @@ void GfxView::initData(GuiResourceId resourceId) {
break;
case kViewVga11: // View-format SCI1.1+
- // HeaderSize:WORD LoopCount:BYTE Unknown:BYTE Version:WORD Unknown:WORD PaletteOffset:WORD
- headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so its added
+ // HeaderSize:WORD LoopCount:BYTE Flags:BYTE Version:WORD Unknown:WORD PaletteOffset:WORD
+ headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so it's added
assert(headerSize >= 16);
_loopCount = _resourceData[2];
assert(_loopCount);
+ _isSci2Hires = _resourceData[5] == 1 ? true : false;
palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8);
- // FIXME: After LoopCount there is another byte and its set for view 50 within Laura Bow 2 CD, check what it means
+ // flags is actually a bit-mask
+ // it seems it was only used for some early sci1.1 games (or even just laura bow 2)
+ // later interpreters dont support it at all anymore
+ // we assume that if flags is 0h the view does not support flags and default to scaleable
+ // if it's 1h then we assume that the view is not to be scaled
+ // if it's 40h then we assume that the view is scaleable
+ switch (_resourceData[3]) {
+ case 1:
+ _isScaleable = false;
+ break;
+ case 0x40:
+ case 0:
+ break; // don't do anything, we already have _isScaleable set
+ default:
+ error("unsupported flags byte inside sci1.1 view");
+ break;
+ }
loopData = _resourceData + headerSize;
loopSize = _resourceData[12];
@@ -183,7 +225,7 @@ void GfxView::initData(GuiResourceId resourceId) {
assert(celSize >= 32);
if (palOffset) {
- _palette->createFromData(&_resourceData[palOffset], &_viewPalette);
+ _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette);
_embeddedPal = true;
}
@@ -210,8 +252,8 @@ void GfxView::initData(GuiResourceId resourceId) {
_loop[loopNo].cel = new CelInfo[celCount];
for (celNo = 0; celNo < celCount; celNo++) {
cel = &_loop[loopNo].cel[celNo];
- cel->width = READ_SCI11ENDIAN_UINT16(celData);
- cel->height = READ_SCI11ENDIAN_UINT16(celData + 2);
+ cel->scriptWidth = cel->width = READ_SCI11ENDIAN_UINT16(celData);
+ cel->scriptHeight = cel->height = READ_SCI11ENDIAN_UINT16(celData + 2);
cel->displaceX = READ_SCI11ENDIAN_UINT16(celData + 4);
cel->displaceY = READ_SCI11ENDIAN_UINT16(celData + 6);
@@ -221,6 +263,9 @@ void GfxView::initData(GuiResourceId resourceId) {
cel->offsetEGA = 0;
cel->offsetRLE = READ_SCI11ENDIAN_UINT32(celData + 24);
cel->offsetLiteral = READ_SCI11ENDIAN_UINT32(celData + 28);
+ // GK1-hires content is actually uncompressed, we need to swap both so that we process it as such
+ if ((cel->offsetRLE) && (!cel->offsetLiteral))
+ SWAP(cel->offsetRLE, cel->offsetLiteral);
cel->rawBitmap = 0;
if (_loop[loopNo].mirrorFlag)
@@ -229,6 +274,29 @@ void GfxView::initData(GuiResourceId resourceId) {
celData += celSize;
}
}
+#ifdef ENABLE_SCI32
+ // adjust width/height returned to scripts
+ switch (getSciVersion()) {
+ case SCI_VERSION_2:
+ if (_isSci2Hires) {
+ for (loopNo = 0; loopNo < _loopCount; loopNo++) {
+ for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++) {
+ _screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight);
+ }
+ }
+ }
+ break;
+
+ case SCI_VERSION_2_1:
+ for (loopNo = 0; loopNo < _loopCount; loopNo++) {
+ for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++) {
+ _coordAdjuster->fromDisplayToScript(_loop[loopNo].cel[celNo].scriptHeight, _loop[loopNo].cel[celNo].scriptWidth);
+ }
+ }
+ default:
+ break;
+ }
+#endif
break;
default:
@@ -236,65 +304,72 @@ void GfxView::initData(GuiResourceId resourceId) {
}
}
-GuiResourceId GfxView::getResourceId() {
+GuiResourceId GfxView::getResourceId() const {
return _resourceId;
}
-int16 GfxView::getWidth(int16 loopNo, int16 celNo) {
- loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
- celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
- return _loopCount ? _loop[loopNo].cel[celNo].width : 0;
+int16 GfxView::getWidth(int16 loopNo, int16 celNo) const {
+ return _loopCount ? getCelInfo(loopNo, celNo)->width : 0;
}
-int16 GfxView::getHeight(int16 loopNo, int16 celNo) {
- loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
- celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
- return _loopCount ? _loop[loopNo].cel[celNo].height : 0;
+int16 GfxView::getHeight(int16 loopNo, int16 celNo) const {
+ return _loopCount ? getCelInfo(loopNo, celNo)->height : 0;
}
-CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) {
+const CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) const {
+ assert(_loopCount);
loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
- return _loopCount ? &_loop[loopNo].cel[celNo] : NULL;
+ return &_loop[loopNo].cel[celNo];
}
-LoopInfo *GfxView::getLoopInfo(int16 loopNo) {
+uint16 GfxView::getCelCount(int16 loopNo) const {
+ assert(_loopCount);
loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1);
- return _loopCount ? &_loop[loopNo] : NULL;
+ return _loop[loopNo].celCount;
}
-void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect *outRect) {
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- if (celInfo) {
- outRect->left = x + celInfo->displaceX - (celInfo->width >> 1);
- outRect->right = outRect->left + celInfo->width;
- outRect->bottom = y + celInfo->displaceY - z + 1;
- outRect->top = outRect->bottom - celInfo->height;
- }
+Palette *GfxView::getPalette() {
+ return _embeddedPal ? &_viewPalette : NULL;
}
-void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect *outRect) {
+bool GfxView::isSci2Hires() {
+ return _isSci2Hires;
+}
+
+bool GfxView::isScaleable() {
+ return _isScaleable;
+}
+
+void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const {
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ outRect.left = x + celInfo->displaceX - (celInfo->width >> 1);
+ outRect.right = outRect.left + celInfo->width;
+ outRect.bottom = y + celInfo->displaceY - z + 1 + _adjustForSci0Early;
+ outRect.top = outRect.bottom - celInfo->height;
+}
+
+void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const {
int16 scaledDisplaceX, scaledDisplaceY;
int16 scaledWidth, scaledHeight;
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- if (celInfo) {
- // Scaling displaceX/Y, Width/Height
- scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7;
- scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7;
- scaledWidth = (celInfo->width * scaleX) >> 7;
- scaledHeight = (celInfo->height * scaleY) >> 7;
- scaledWidth = CLIP<int16>(scaledWidth, 0, _screen->getWidth());
- scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight());
-
- outRect->left = x + scaledDisplaceX - (scaledWidth >> 1);
- outRect->right = outRect->left + scaledWidth;
- outRect->bottom = y + scaledDisplaceY - z + 1;
- outRect->top = outRect->bottom - scaledHeight;
- }
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+
+ // Scaling displaceX/Y, Width/Height
+ scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7;
+ scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7;
+ scaledWidth = (celInfo->width * scaleX) >> 7;
+ scaledHeight = (celInfo->height * scaleY) >> 7;
+ scaledWidth = CLIP<int16>(scaledWidth, 0, _screen->getWidth());
+ scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight());
+
+ outRect.left = x + scaledDisplaceX - (scaledWidth >> 1);
+ outRect.right = outRect.left + scaledWidth;
+ outRect.bottom = y + scaledDisplaceY - z + 1;
+ outRect.top = outRect.bottom - scaledHeight;
}
void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) {
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
byte *rlePtr;
byte *literalPtr;
uint32 pixelNo = 0, runLength;
@@ -309,78 +384,42 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou
memset(outPtr + pixelNo, pixel & 0x0F, MIN<uint32>(runLength, pixelCount - pixelNo));
pixelNo += runLength;
}
- return;
- }
-
- rlePtr = _resourceData + celInfo->offsetRLE;
- if (!celInfo->offsetLiteral) { // no additional literal data
- if (_resMan->isAmiga32color()) {
- // decompression for amiga views
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- if (pixel & 0x07) { // fill with color
- runLength = pixel & 0x07;
- pixel = pixel >> 3;
- while (runLength-- && pixelNo < pixelCount) {
- outPtr[pixelNo++] = pixel;
- }
- } else { // fill with transparent
- runLength = pixel >> 3;
- pixelNo += runLength;
- }
- }
- return;
- } else {
- // decompression for data that has just one combined stream
- while (pixelNo < pixelCount) {
- pixel = *rlePtr++;
- runLength = pixel & 0x3F;
- switch (pixel & 0xC0) {
- case 0: // copy bytes as-is
- while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *rlePtr++;
- break;
- case 0x80: // fill with color
- memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
- pixelNo += runLength;
- break;
- case 0xC0: // fill with transparent
- pixelNo += runLength;
- break;
- }
- }
- return;
- }
} else {
- literalPtr = _resourceData + celInfo->offsetLiteral;
- if (celInfo->offsetRLE) {
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) {
- // Crazy-Ass compression for SCI1.1+ Mac
+ // We fill the buffer with transparent pixels, so that we can later skip
+ // over pixels to automatically have them transparent
+ // Also some RLE compressed cels are possibly ending with the last
+ // non-transparent pixel (is this even possible with the current code?)
+ memset(outPtr, _loop[loopNo].cel[celNo].clearKey, pixelCount);
+
+ rlePtr = _resourceData + celInfo->offsetRLE;
+ if (!celInfo->offsetLiteral) { // no additional literal data
+ if (_resMan->isAmiga32color()) {
+ // decompression for amiga views
while (pixelNo < pixelCount) {
- uint32 pixelLine = pixelNo;
- runLength = *rlePtr++;
- pixelNo += runLength;
- runLength = *rlePtr++;
- while (runLength-- && pixelNo < pixelCount) {
- outPtr[pixelNo] = *literalPtr++;
- if (outPtr[pixelNo] == 255)
- outPtr[pixelNo] = 0;
- pixelNo++;
+ pixel = *rlePtr++;
+ if (pixel & 0x07) { // fill with color
+ runLength = pixel & 0x07;
+ pixel = pixel >> 3;
+ while (runLength-- && pixelNo < pixelCount) {
+ outPtr[pixelNo++] = pixel;
+ }
+ } else { // fill with transparent
+ runLength = pixel >> 3;
+ pixelNo += runLength;
}
- pixelNo = pixelLine + celInfo->width;
}
} else {
- // decompression for data that has separate rle and literal streams
+ // decompression for data that has just one combined stream
while (pixelNo < pixelCount) {
pixel = *rlePtr++;
runLength = pixel & 0x3F;
switch (pixel & 0xC0) {
case 0: // copy bytes as-is
while (runLength-- && pixelNo < pixelCount)
- outPtr[pixelNo++] = *literalPtr++;
+ outPtr[pixelNo++] = *rlePtr++;
break;
case 0x80: // fill with color
- memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
+ memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
pixelNo += runLength;
break;
case 0xC0: // fill with transparent
@@ -390,15 +429,53 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou
}
}
} else {
- // literal stream only, so no compression
- memcpy(outPtr, literalPtr, pixelCount);
+ literalPtr = _resourceData + celInfo->offsetLiteral;
+ if (celInfo->offsetRLE) {
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) {
+ // compression for SCI1.1+ Mac
+ while (pixelNo < pixelCount) {
+ uint32 pixelLine = pixelNo;
+ runLength = *rlePtr++;
+ pixelNo += runLength;
+ runLength = *rlePtr++;
+ while (runLength-- && pixelNo < pixelCount) {
+ outPtr[pixelNo] = *literalPtr++;
+ if (outPtr[pixelNo] == 255)
+ outPtr[pixelNo] = 0;
+ pixelNo++;
+ }
+ pixelNo = pixelLine + celInfo->width;
+ }
+ } else {
+ // decompression for data that has separate rle and literal streams
+ while (pixelNo < pixelCount) {
+ pixel = *rlePtr++;
+ runLength = pixel & 0x3F;
+ switch (pixel & 0xC0) {
+ case 0: // copy bytes as-is
+ while (runLength-- && pixelNo < pixelCount)
+ outPtr[pixelNo++] = *literalPtr++;
+ break;
+ case 0x80: // fill with color
+ memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo));
+ pixelNo += runLength;
+ break;
+ case 0xC0: // fill with transparent
+ pixelNo += runLength;
+ break;
+ }
+ }
+ }
+ } else {
+ // literal stream only, so no compression
+ memcpy(outPtr, literalPtr, pixelCount);
+ pixelNo = pixelCount;
+ }
}
- return;
}
- error("Unable to decompress view");
}
-byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
+const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1);
if (_loop[loopNo].cel[celNo].rawBitmap)
@@ -411,9 +488,7 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
_loop[loopNo].cel[celNo].rawBitmap = new byte[pixelCount];
byte *pBitmap = _loop[loopNo].cel[celNo].rawBitmap;
- // Some RLE compressed cels end with the last non-transparent pixel, thats why we fill it up here
- // FIXME: change this to fill the remaining bytes within unpackCel()
- memset(pBitmap, _loop[loopNo].cel[celNo].clearKey, pixelCount);
+ // unpack the actual cel bitmap data
unpackCel(loopNo, celNo, pBitmap, pixelCount);
if (!_resMan->isVGA()) {
@@ -429,17 +504,21 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) {
return _loop[loopNo].cel[celNo].rawBitmap;
}
-// Called after unpacking an EGA cel, this will try to undither (parts) of the cel if the dithering in here
-// matches dithering used by the current picture
+/**
+ * Called after unpacking an EGA cel, this will try to undither (parts) of the
+ * cel if the dithering in here matches dithering used by the current picture.
+ */
void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte clearKey) {
int16 *unditherMemorial = _screen->unditherGetMemorial();
- // It makes no sense to go further, if no memorial data from current picture is available
+ // It makes no sense to go further, if no memorial data from current picture
+ // is available
if (!unditherMemorial)
return;
// Makes no sense to process bitmaps that are 3 pixels wide or less
- if (width <= 3) return;
+ if (width <= 3)
+ return;
// If EGA mapping is used for this view, dont do undithering as well
if (_EGAmapping)
@@ -453,7 +532,8 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
memset(&bitmapMemorial, 0, sizeof(bitmapMemorial));
- // Count all seemingly dithered pixel-combinations as soon as at least 4 pixels are adjacent
+ // Count all seemingly dithered pixel-combinations as soon as at least 4
+ // pixels are adjacent
curPtr = bitmapPtr;
for (y = 0; y < height; y++) {
color1 = curPtr[0]; color2 = (curPtr[1] << 4) | curPtr[2];
@@ -466,17 +546,20 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
}
}
- // Now compare both memorial tables to find out matching dithering-combinations
+ // Now compare both memorial tables to find out matching
+ // dithering-combinations
bool unditherTable[SCI_SCREEN_UNDITHERMEMORIAL_SIZE];
byte color, unditherCount = 0;
memset(&unditherTable, false, sizeof(unditherTable));
for (color = 0; color < 255; color++) {
if ((bitmapMemorial[color] > 5) && (unditherMemorial[color] > 200)) {
- // match found, check if colorKey is contained -> if so, we ignore of course
+ // match found, check if colorKey is contained -> if so, we ignore
+ // of course
color1 = color & 0x0F; color2 = color >> 4;
if ((color1 != clearKey) && (color2 != clearKey) && (color1 != color2)) {
// so set this and the reversed color-combination for undithering
- unditherTable[color] = true; unditherTable[(color1 << 4) | color2] = true;
+ unditherTable[color] = true;
+ unditherTable[(color1 << 4) | color2] = true;
unditherCount++;
}
}
@@ -493,8 +576,9 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
for (x = 1; x < width; x++) {
color = (color << 4) | curPtr[1];
if (unditherTable[color]) {
- // some color with black? turn colors around otherwise it wont be the right color at all
- if ((color & 0xF0)==0)
+ // Some color with black? Turn colors around, otherwise it won't
+ // be the right color at all.
+ if ((color & 0xF0) == 0)
color = (color << 4) | (color >> 4);
curPtr[0] = color; curPtr[1] = color;
}
@@ -504,15 +588,15 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl
}
}
-void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) {
- Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- byte *bitmap = getBitmap(loopNo, celNo);
- int16 celHeight = celInfo->height, celWidth = celInfo->width;
- int16 width, height;
- byte clearKey = celInfo->clearKey;
- byte color;
- byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
+void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated,
+ int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) {
+ const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ const byte *bitmap = getBitmap(loopNo, celNo);
+ const int16 celHeight = celInfo->height;
+ const int16 celWidth = celInfo->width;
+ const byte clearKey = celInfo->clearKey;
+ const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
int x, y;
if (_embeddedPal) {
@@ -520,24 +604,27 @@ void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRe
_palette->set(&_viewPalette, false);
}
- width = MIN(clipRect.width(), celWidth);
- height = MIN(clipRect.height(), celHeight);
+ const int16 width = MIN(clipRect.width(), celWidth);
+ const int16 height = MIN(clipRect.height(), celHeight);
bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left);
if (!_EGAmapping) {
for (y = 0; y < height; y++, bitmap += celWidth) {
for (x = 0; x < width; x++) {
- color = bitmap[x];
+ const byte color = bitmap[x];
if (color != clearKey) {
+ const int x2 = clipRectTranslated.left + x;
+ const int y2 = clipRectTranslated.top + y;
if (!upscaledHires) {
- if (priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y))
- _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0);
+ if (priority >= _screen->getPriority(x2, y2))
+ _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
} else {
- // UpscaledHires means view is hires and is supposed to get drawn onto lowres screen
- // FIXME(?): we can't read priority directly with the hires coordinates. may not be needed at all
- // in kq6
- _screen->putPixelOnDisplay(clipRectTranslated.left + x, clipRectTranslated.top + y, palette->mapping[color]);
+ // UpscaledHires means view is hires and is supposed to
+ // get drawn onto lowres screen.
+ // FIXME(?): we can't read priority directly with the
+ // hires coordinates. may not be needed at all in kq6
+ _screen->putPixelOnDisplay(x2, y2, palette->mapping[color]);
}
}
}
@@ -546,30 +633,34 @@ void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRe
byte *EGAmapping = _EGAmapping + (EGAmappingNr * SCI_VIEW_EGAMAPPING_SIZE);
for (y = 0; y < height; y++, bitmap += celWidth) {
for (x = 0; x < width; x++) {
- color = EGAmapping[bitmap[x]];
- if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y))
- _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, color, priority, 0);
+ const byte color = EGAmapping[bitmap[x]];
+ const int x2 = clipRectTranslated.left + x;
+ const int y2 = clipRectTranslated.top + y;
+ if (color != clearKey && priority >= _screen->getPriority(x2, y2))
+ _screen->putPixel(x2, y2, drawMask, color, priority, 0);
}
}
}
}
-// We don't fully follow sierra sci here, I did the scaling algo myself and it's definitely not pixel-perfect
-// with the one sierra is using. It shouldn't matter because the scaled cel rect is definitely the same as in sierra sci
-void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) {
- Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
- CelInfo *celInfo = getCelInfo(loopNo, celNo);
- byte *bitmap = getBitmap(loopNo, celNo);
- int16 celHeight = celInfo->height, celWidth = celInfo->width;
- byte clearKey = celInfo->clearKey;
- byte color;
- byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
- int x, y;
- uint16 scalingX[320];
- uint16 scalingY[200];
+/**
+ * We don't fully follow sierra sci here, I did the scaling algo myself and it
+ * is definitely not pixel-perfect with the one sierra is using. It shouldn't
+ * matter because the scaled cel rect is definitely the same as in sierra sci.
+ */
+void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated,
+ int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) {
+ const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
+ const CelInfo *celInfo = getCelInfo(loopNo, celNo);
+ const byte *bitmap = getBitmap(loopNo, celNo);
+ const int16 celHeight = celInfo->height;
+ const int16 celWidth = celInfo->width;
+ const byte clearKey = celInfo->clearKey;
+ const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY;
+ uint16 scalingX[640];
+ uint16 scalingY[480];
int16 scaledWidth, scaledHeight;
- int16 pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo;
- uint16 offsetX, offsetY;
+ int pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo;
if (_embeddedPal) {
// Merge view palette in...
@@ -582,65 +673,63 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect
scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight());
// Do we really need to do this?!
- memset(scalingX, 0, sizeof(scalingX));
- memset(scalingY, 0, sizeof(scalingY));
+ //memset(scalingX, 0, sizeof(scalingX));
+ //memset(scalingY, 0, sizeof(scalingY));
// Create height scaling table
pixelNo = 0;
scaledPixel = scaledPixelNo = prevScaledPixelNo = 0;
while (pixelNo < celHeight) {
scaledPixelNo = scaledPixel >> 7;
- if (prevScaledPixelNo < scaledPixelNo)
- memset(&scalingY[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo);
- scalingY[scaledPixelNo] = pixelNo;
- prevScaledPixelNo = scaledPixelNo + 1;
+ assert(scaledPixelNo < ARRAYSIZE(scalingY));
+ for (; prevScaledPixelNo <= scaledPixelNo; prevScaledPixelNo++)
+ scalingY[prevScaledPixelNo] = pixelNo;
pixelNo++;
scaledPixel += scaleY;
}
+ pixelNo--;
scaledPixelNo++;
- if (scaledPixelNo < scaledHeight)
- memset(&scalingY[scaledPixelNo], pixelNo - 1, scaledHeight - scaledPixelNo);
+ for (; scaledPixelNo < scaledHeight; scaledPixelNo++)
+ scalingY[scaledPixelNo] = pixelNo;
// Create width scaling table
pixelNo = 0;
scaledPixel = scaledPixelNo = prevScaledPixelNo = 0;
while (pixelNo < celWidth) {
scaledPixelNo = scaledPixel >> 7;
- if (prevScaledPixelNo < scaledPixelNo)
- memset(&scalingX[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo);
- scalingX[scaledPixelNo] = pixelNo;
- prevScaledPixelNo = scaledPixelNo + 1;
+ assert(scaledPixelNo < ARRAYSIZE(scalingX));
+ for (; prevScaledPixelNo <= scaledPixelNo; prevScaledPixelNo++)
+ scalingX[prevScaledPixelNo] = pixelNo;
pixelNo++;
scaledPixel += scaleX;
}
+ pixelNo--;
scaledPixelNo++;
- if (scaledPixelNo < scaledWidth)
- memset(&scalingX[scaledPixelNo], pixelNo - 1, scaledWidth - scaledPixelNo);
+ for (; scaledPixelNo < scaledWidth; scaledPixelNo++)
+ scalingX[scaledPixelNo] = pixelNo;
scaledWidth = MIN(clipRect.width(), scaledWidth);
scaledHeight = MIN(clipRect.height(), scaledHeight);
- offsetY = clipRect.top - rect.top;
- offsetX = clipRect.left - rect.left;
+ const int16 offsetY = clipRect.top - rect.top;
+ const int16 offsetX = clipRect.left - rect.left;
- for (y = 0; y < scaledHeight; y++) {
- for (x = 0; x < scaledWidth; x++) {
- color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]];
- if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) {
- _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0);
+ // Happens in SQ6, first room
+ if (offsetX < 0 || offsetY < 0)
+ return;
+
+ assert(scaledHeight + offsetY <= ARRAYSIZE(scalingY));
+ assert(scaledWidth + offsetX <= ARRAYSIZE(scalingX));
+ for (int y = 0; y < scaledHeight; y++) {
+ for (int x = 0; x < scaledWidth; x++) {
+ const byte color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]];
+ const int x2 = clipRectTranslated.left + x;
+ const int y2 = clipRectTranslated.top + y;
+ if (color != clearKey && priority >= _screen->getPriority(x2, y2)) {
+ _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0);
}
}
}
}
-uint16 GfxView::getCelCount(int16 loopNo) {
- if ((loopNo < 0) || (loopNo >= _loopCount))
- return 0;
- return _loop[loopNo].celCount;
-}
-
-Palette *GfxView::getPalette() {
- return _embeddedPal ? &_viewPalette : &_palette->_sysPalette;
-}
-
} // End of namespace Sci