aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/graphics')
-rw-r--r--engines/sci/graphics/maciconbar.cpp10
-rw-r--r--engines/sci/graphics/palette.cpp156
-rw-r--r--engines/sci/graphics/palette.h7
-rw-r--r--engines/sci/graphics/ports.cpp9
-rw-r--r--engines/sci/graphics/screen.cpp53
-rw-r--r--engines/sci/graphics/screen.h5
-rw-r--r--engines/sci/graphics/transitions.cpp19
7 files changed, 185 insertions, 74 deletions
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index 2ce17ab531..77491aa995 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -29,6 +29,7 @@
#include "sci/engine/state.h"
#include "sci/graphics/maciconbar.h"
#include "sci/graphics/palette.h"
+#include "sci/graphics/screen.h"
#include "common/memstream.h"
#include "common/system.h"
@@ -58,7 +59,8 @@ void GfxMacIconBar::drawIcons() {
Graphics::Surface *surf = pict->decodeImage(stream, pal);
remapColors(surf, pal);
- g_system->copyRectToScreen((byte *)surf->pixels, surf->pitch, lastX, 200, MIN<uint32>(surf->w, 320 - lastX), surf->h);
+ g_system->copyRectToScreen((byte *)surf->pixels, surf->pitch, lastX,
+ g_sci->_gfxScreen->getHeight() + 2, MIN<uint32>(surf->w, 320 - lastX), surf->h);
lastX += surf->w;
surf->free();
@@ -81,11 +83,7 @@ void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
byte g = palette[color * 4 + 1];
byte b = palette[color * 4 + 2];
- // For black, make sure the index is 0
- if (r == 0 && g == 0 && b == 0)
- *pixels++ = 0;
- else
- *pixels++ = g_sci->_gfxPalette->kernelFindColor(r, g, b);
+ *pixels++ = g_sci->_gfxPalette->findMacIconBarColor(r, g, b);
}
}
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index b27b5f35a7..534890315c 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -69,6 +69,9 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMergi
_useMerging = useMerging;
palVaryInit();
+
+ _macClut = 0;
+ loadMacIconBarPalette();
#ifdef ENABLE_SCI32
_clutTable = 0;
@@ -79,6 +82,8 @@ GfxPalette::~GfxPalette() {
if (_palVaryResourceId != -1)
palVaryRemoveTimer();
+ delete[] _macClut;
+
#ifdef ENABLE_SCI32
unloadClut();
#endif
@@ -171,39 +176,42 @@ void GfxPalette::createFromData(byte *data, int bytesLeft, Palette *paletteOut)
// Will try to set amiga palette by using "spal" file. If not found, we return false
bool GfxPalette::setAmiga() {
Common::File file;
- int curColor, byte1, byte2;
if (file.open("spal")) {
- for (curColor = 0; curColor < 32; curColor++) {
- byte1 = file.readByte();
- byte2 = file.readByte();
- if ((byte1 == EOF) || (byte2 == EOF))
+ for (int curColor = 0; curColor < 32; curColor++) {
+ byte byte1 = file.readByte();
+ byte byte2 = file.readByte();
+
+ if (file.eos())
error("Amiga palette file ends prematurely");
+
_sysPalette.colors[curColor].used = 1;
_sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11;
_sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11;
_sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11;
}
- file.close();
+
// Directly set the palette, because setOnScreen() wont do a thing for amiga
- _screen->setPalette(&_sysPalette);
+ copySysPaletteToScreen();
return true;
}
+
return false;
}
// Called from picture class, some amiga sci1 games set half of the palette
void GfxPalette::modifyAmigaPalette(byte *data) {
- int16 curColor, curPos = 0;
- byte byte1, byte2;
- for (curColor = 0; curColor < 16; curColor++) {
- byte1 = data[curPos++];
- byte2 = data[curPos++];
+ int16 curPos = 0;
+
+ for (int curColor = 0; curColor < 16; curColor++) {
+ byte byte1 = data[curPos++];
+ byte byte2 = data[curPos++];
_sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11;
_sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11;
_sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11;
}
- _screen->setPalette(&_sysPalette);
+
+ copySysPaletteToScreen();
}
static byte blendColors(byte c1, byte c2) {
@@ -297,19 +305,20 @@ bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) {
newPalette->mapping[i] = i;
}
}
+
// We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls
return paletteChanged;
}
bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
uint16 res;
- int i,j;
bool paletteChanged = false;
- // colors 0 (black) and 255 (white) are not affected by merging
- for (i = 1; i < 255; i++) {
- if (!newPalette->colors[i].used)// color is not used - so skip it
+ for (int i = 1; i < 255; i++) {
+ // skip unused colors
+ if (!newPalette->colors[i].used)
continue;
+
// forced palette merging or dest color is not used yet
if (force || (!_sysPalette.colors[i].used)) {
_sysPalette.colors[i].used = newPalette->colors[i].used;
@@ -322,6 +331,7 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
newPalette->mapping[i] = i;
continue;
}
+
// is the same color already at the same position? -> match it directly w/o lookup
// this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would
// otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes)
@@ -329,14 +339,18 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
newPalette->mapping[i] = i;
continue;
}
+
// check if exact color could be matched
res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b);
if (res & 0x8000) { // exact match was found
newPalette->mapping[i] = res & 0xFF;
continue;
}
+
+ int j = 1;
+
// no exact match - see if there is an unused color
- for (j = 1; j < 256; j++)
+ for (; j < 256; j++) {
if (!_sysPalette.colors[j].used) {
_sysPalette.colors[j].used = newPalette->colors[i].used;
_sysPalette.colors[j].r = newPalette->colors[i].r;
@@ -346,6 +360,8 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
paletteChanged = true;
break;
}
+ }
+
// if still no luck - set an approximate color
if (j == 256) {
newPalette->mapping[i] = res & 0xFF;
@@ -355,6 +371,7 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) {
if (!forceRealMerge)
_sysPalette.timestamp = g_system->getMillis() * 60 / 1000;
+
return paletteChanged;
}
@@ -404,11 +421,36 @@ void GfxPalette::setOnScreen() {
// We dont change palette at all times for amiga
if (_resMan->isAmiga32color())
return;
- _screen->setPalette(&_sysPalette);
- // Redraw the Mac SCI1.1 Icon bar every palette change
- if (g_sci->_gfxMacIconBar)
- g_sci->_gfxMacIconBar->drawIcons();
+ copySysPaletteToScreen();
+}
+
+static byte convertMacGammaToSCIGamma(int comp) {
+ return (byte)sqrt(comp * 255.0f);
+}
+
+void GfxPalette::copySysPaletteToScreen() {
+ // just copy palette to system
+ byte bpal[3 * 256];
+
+ // Get current palette, update it and put back
+ g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
+
+ for (int16 i = 0; i < 256; i++) {
+ if (colorIsFromMacClut(i)) {
+ // If we've got a Mac CLUT, override the SCI palette with its non-black colors
+ bpal[i * 3 ] = convertMacGammaToSCIGamma(_macClut[i * 3 ]);
+ bpal[i * 3 + 1] = convertMacGammaToSCIGamma(_macClut[i * 3 + 1]);
+ bpal[i * 3 + 2] = convertMacGammaToSCIGamma(_macClut[i * 3 + 2]);
+ } else if (_sysPalette.colors[i].used != 0) {
+ // Otherwise, copy to the screen
+ bpal[i * 3 ] = CLIP(_sysPalette.colors[i].r * _sysPalette.intensity[i] / 100, 0, 255);
+ bpal[i * 3 + 1] = CLIP(_sysPalette.colors[i].g * _sysPalette.intensity[i] / 100, 0, 255);
+ bpal[i * 3 + 2] = CLIP(_sysPalette.colors[i].b * _sysPalette.intensity[i] / 100, 0, 255);
+ }
+ }
+
+ g_system->getPaletteManager()->setPalette(bpal, 0, 256);
}
bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) {
@@ -420,6 +462,7 @@ bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) {
set(&palette, force);
return true;
}
+
return false;
}
@@ -565,7 +608,16 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) {
}
void GfxPalette::kernelSyncScreenPalette() {
- _screen->getPalette(&_sysPalette);
+ // just copy palette to system
+ byte bpal[3 * 256];
+
+ // Get current palette, update it and put back
+ g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
+ for (int16 i = 1; i < 255; i++) {
+ _sysPalette.colors[i].r = bpal[i * 3];
+ _sysPalette.colors[i].g = bpal[i * 3 + 1];
+ _sysPalette.colors[i].b = bpal[i * 3 + 2];
+ }
}
// palVary
@@ -795,6 +847,64 @@ void GfxPalette::palVaryProcess(int signal, bool setPalette) {
}
}
+byte GfxPalette::findMacIconBarColor(byte r, byte g, byte b) {
+ // Find the best color for use with the Mac icon bar
+
+ // For black, always use 0
+ if (r == 0 && g == 0 && b == 0)
+ return 0;
+
+ byte found = 0xFF;
+ uint diff = 0xFFFFFFFF;
+
+ for (uint16 i = 1; i < 255; i++) {
+ int dr = _macClut[i * 3 ] - r;
+ int dg = _macClut[i * 3 + 1] - g;
+ int db = _macClut[i * 3 + 2] - b;
+
+ // Use the largest difference. This is what the Mac Palette Manager does.
+ uint cdiff = MAX<int>(ABS(dr), ABS(dg));
+ cdiff = MAX<int>(cdiff, ABS(db));
+
+ if (cdiff == 0)
+ return i;
+ else if (cdiff < diff) {
+ found = i;
+ diff = cdiff;
+ }
+ }
+
+ return found;
+}
+
+void GfxPalette::loadMacIconBarPalette() {
+ if (!g_sci->hasMacIconBar())
+ return;
+
+ Common::SeekableReadStream *clutStream = g_sci->getMacExecutable()->getResource(MKID_BE('clut'), 150);
+
+ if (!clutStream)
+ error("Could not find clut 150 for the Mac icon bar");
+
+ clutStream->readUint32BE(); // seed
+ clutStream->readUint16BE(); // flags
+ uint16 colorCount = clutStream->readUint16BE() + 1;
+ _macClut = new byte[colorCount * 3];
+
+ for (uint16 i = 0; i < colorCount; i++) {
+ clutStream->readUint16BE();
+ _macClut[i * 3 ] = clutStream->readUint16BE() >> 8;
+ _macClut[i * 3 + 1] = clutStream->readUint16BE() >> 8;
+ _macClut[i * 3 + 2] = clutStream->readUint16BE() >> 8;
+ }
+
+ delete clutStream;
+}
+
+bool GfxPalette::colorIsFromMacClut(byte index) {
+ return index != 0 && _macClut && (_macClut[index * 3] != 0 || _macClut[index * 3 + 1] != 0 || _macClut[index * 3 + 1] != 0);
+}
+
#ifdef ENABLE_SCI32
bool GfxPalette::loadClut(uint16 clutId) {
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index 84334a4a61..317401ac1f 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -56,6 +56,7 @@ public:
void getSys(Palette *pal);
void setOnScreen();
+ void copySysPaletteToScreen();
void drewPicture(GuiResourceId pictureId);
@@ -88,6 +89,9 @@ public:
virtual void saveLoadWithSerializer(Common::Serializer &s);
void palVarySaveLoadPalette(Common::Serializer &s, Palette *palette);
+ byte findMacIconBarColor(byte r, byte g, byte b);
+ bool colorIsFromMacClut(byte index);
+
#ifdef ENABLE_SCI32
bool loadClut(uint16 clutId);
byte matchClutColor(uint16 color);
@@ -119,6 +123,9 @@ private:
uint16 _palVaryTicks;
int _palVaryPaused;
int _palVarySignal;
+
+ void loadMacIconBarPalette();
+ byte *_macClut;
#ifdef ENABLE_SCI32
byte *_clutTable;
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 87f0c3d6a2..57c76126c0 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -106,7 +106,10 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te
offTop = 26;
break;
default:
- offTop = 10;
+ // For Mac games running with a height of 190, we do not have a menu bar
+ // so the top offset should be 0.
+ if (_screen->getHeight() == 190)
+ offTop = 0;
break;
}
@@ -575,10 +578,6 @@ void GfxPorts::priorityBandsInit(int16 bandCount, int16 top, int16 bottom) {
int16 y;
int32 bandSize;
- // This code is for 320x200 games only
- if (_screen->getHeight() != 200)
- return;
-
if (bandCount != -1)
_priorityBandCount = bandCount;
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 1a17be8ec8..b019853a2b 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -64,7 +64,7 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
_height = 480;
} else {
_width = 320;
- _height = 200;
+ _height = getLowResScreenHeight();
}
// Japanese versions of games use hi-res font on upscaled version of the game.
@@ -132,10 +132,12 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) {
if (g_sci->hasMacIconBar()) {
// For SCI1.1 Mac games with the custom icon bar, we need to expand the screen
// to accommodate for the icon bar. Of course, both KQ6 and QFG1 VGA differ in size.
+ // We add 2 to the height of the icon bar to add a buffer between the screen and the
+ // icon bar (as did the original interpreter).
if (g_sci->getGameId() == GID_KQ6)
- initGraphics(_displayWidth, _displayHeight + 26, _displayWidth > 320);
+ initGraphics(_displayWidth, _displayHeight + 26 + 2, _displayWidth > 320);
else if (g_sci->getGameId() == GID_FREDDYPHARKAS)
- initGraphics(_displayWidth, _displayHeight + 28, _displayWidth > 320);
+ initGraphics(_displayWidth, _displayHeight + 28 + 2, _displayWidth > 320);
else
error("Unknown SCI1.1 Mac game");
} else
@@ -509,33 +511,6 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
}
}
-void GfxScreen::getPalette(Palette *pal) {
- // just copy palette to system
- byte bpal[3 * 256];
- // Get current palette, update it and put back
- g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
- for (int16 i = 1; i < 255; i++) {
- pal->colors[i].r = bpal[i * 3];
- pal->colors[i].g = bpal[i * 3 + 1];
- pal->colors[i].b = bpal[i * 3 + 2];
- }
-}
-
-void GfxScreen::setPalette(Palette *pal) {
- // just copy palette to system
- byte bpal[3 * 256];
- // Get current palette, update it and put back
- g_system->getPaletteManager()->grabPalette(bpal, 0, 256);
- for (int16 i = 0; i < 256; i++) {
- if (!pal->colors[i].used)
- continue;
- bpal[i * 3] = CLIP(pal->colors[i].r * pal->intensity[i] / 100, 0, 255);
- bpal[i * 3 + 1] = CLIP(pal->colors[i].g * pal->intensity[i] / 100, 0, 255);
- bpal[i * 3 + 2] = CLIP(pal->colors[i].b * pal->intensity[i] / 100, 0, 255);
- }
- g_system->getPaletteManager()->setPalette(bpal, 0, 256);
-}
-
void GfxScreen::setVerticalShakePos(uint16 shakePos) {
if (!_upscaledHires)
g_system->setShakePos(shakePos);
@@ -742,4 +717,22 @@ int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) {
return oldPicNotValid;
}
+uint16 GfxScreen::getLowResScreenHeight() {
+ // Some Mac SCI1/1.1 games only take up 190 rows and do not
+ // have the menu bar.
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
+ switch (g_sci->getGameId()) {
+ case GID_FREDDYPHARKAS:
+ case GID_KQ5:
+ case GID_KQ6:
+ return 190;
+ default:
+ break;
+ }
+ }
+
+ // Everything else is 200
+ return 200;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index b6898b905a..fc1f38ed41 100644
--- a/engines/sci/graphics/screen.h
+++ b/engines/sci/graphics/screen.h
@@ -106,9 +106,6 @@ public:
void bitsGetRect(byte *memoryPtr, Common::Rect *destRect);
void bitsRestore(byte *memoryPtr);
- void getPalette(Palette *pal);
- void setPalette(Palette *pal);
-
void scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight, byte bytesPerPixel = 1);
void adjustToUpscaledCoordinates(int16 &y, int16 &x);
@@ -184,6 +181,8 @@ private:
// This defines whether or not the font we're drawing is already scaled
// to the screen size (and we therefore should not upscale it ourselves).
bool _fontIsUpscaled;
+
+ uint16 getLowResScreenHeight();
};
} // End of namespace Sci
diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp
index 5e14778c0c..e025a2f9ab 100644
--- a/engines/sci/graphics/transitions.cpp
+++ b/engines/sci/graphics/transitions.cpp
@@ -271,9 +271,8 @@ void GfxTransitions::doTransition(int16 number, bool blackoutFlag) {
}
void GfxTransitions::setNewPalette(bool blackoutFlag) {
- if (!blackoutFlag)
- if (_isVGA)
- _palette->setOnScreen();
+ if (!blackoutFlag && _isVGA)
+ _palette->setOnScreen();
}
void GfxTransitions::setNewScreen(bool blackoutFlag) {
@@ -312,10 +311,16 @@ void GfxTransitions::fadeOut() {
g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256);
for (stepNr = 100; stepNr >= 0; stepNr -= 10) {
- for (colorNr = 1; colorNr < tillColorNr; colorNr++){
- workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100;
- workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100;
- workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100;
+ for (colorNr = 1; colorNr < tillColorNr; colorNr++) {
+ if (_palette->colorIsFromMacClut(colorNr)) {
+ workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3];
+ workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1];
+ workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2];
+ } else {
+ workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100;
+ workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100;
+ workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100;
+ }
}
g_system->getPaletteManager()->setPalette(workPalette + 3, 1, 254);
g_sci->getEngineState()->wait(2);