aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorMatthew Hoops2011-02-17 13:13:30 -0500
committerMatthew Hoops2011-02-17 13:38:23 -0500
commit266806d8925330ec0d9e020fafffd74a2cb272e6 (patch)
treed53d8b4365d819573093fb89262947e62f98d8d7 /engines/sci
parentb5d1c669158951d4ea1633d3c10c58729d28fda5 (diff)
downloadscummvm-rg350-266806d8925330ec0d9e020fafffd74a2cb272e6.tar.gz
scummvm-rg350-266806d8925330ec0d9e020fafffd74a2cb272e6.tar.bz2
scummvm-rg350-266806d8925330ec0d9e020fafffd74a2cb272e6.zip
SCI: Fix Mac icon bar palettes
The Mac icon bar uses a palette from the executable and keeps those entries in the palette constantly. In addition, we're now performing gamma correction on the Mac-based colors so that they are in the same gamma as SCI. The color matching now works with this and using the same color finding as the Mac Palette Manager.
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/graphics/maciconbar.cpp6
-rw-r--r--engines/sci/graphics/palette.cpp156
-rw-r--r--engines/sci/graphics/palette.h7
-rw-r--r--engines/sci/graphics/screen.cpp28
-rw-r--r--engines/sci/graphics/screen.h3
-rw-r--r--engines/sci/graphics/transitions.cpp20
-rw-r--r--engines/sci/sci.cpp33
-rw-r--r--engines/sci/sci.h9
8 files changed, 196 insertions, 66 deletions
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index 2ce17ab531..81e863db34 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -81,11 +81,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..7a7f79b7af 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);
+}
+
+void GfxPalette::copySysPaletteToScreen() {
+ // just copy palette to system
+ byte bpal[4 * 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 * 4 ] = convertMacGammaToSCIGamma(_macClut[i * 3 ]);
+ bpal[i * 4 + 1] = convertMacGammaToSCIGamma(_macClut[i * 3 + 1]);
+ bpal[i * 4 + 2] = convertMacGammaToSCIGamma(_macClut[i * 3 + 2]);
+ } else if (_sysPalette.colors[i].used != 0) {
+ // Otherwise, copy to the screen
+ bpal[i * 4 ] = CLIP(_sysPalette.colors[i].r * _sysPalette.intensity[i] / 100, 0, 255);
+ bpal[i * 4 + 1] = CLIP(_sysPalette.colors[i].g * _sysPalette.intensity[i] / 100, 0, 255);
+ bpal[i * 4 + 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[4 * 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 * 4];
+ _sysPalette.colors[i].g = bpal[i * 4 + 1];
+ _sysPalette.colors[i].b = bpal[i * 4 + 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/screen.cpp b/engines/sci/graphics/screen.cpp
index 896ac0db22..6a045f1e8b 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -509,34 +509,6 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
}
}
-void GfxScreen::getPalette(Palette *pal) {
- // just copy palette to system
- byte bpal[4 * 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 * 4];
- pal->colors[i].g = bpal[i * 4 + 1];
- pal->colors[i].b = bpal[i * 4 + 2];
- }
-}
-
-void GfxScreen::setPalette(Palette *pal) {
- // just copy palette to system
- byte bpal[4 * 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 * 4] = CLIP(pal->colors[i].r * pal->intensity[i] / 100, 0, 255);
- bpal[i * 4 + 1] = CLIP(pal->colors[i].g * pal->intensity[i] / 100, 0, 255);
- bpal[i * 4 + 2] = CLIP(pal->colors[i].b * pal->intensity[i] / 100, 0, 255);
- bpal[i * 4 + 3] = 100;
- }
- g_system->getPaletteManager()->setPalette(bpal, 0, 256);
-}
-
void GfxScreen::setVerticalShakePos(uint16 shakePos) {
if (!_upscaledHires)
g_system->setShakePos(shakePos);
diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h
index b6898b905a..1d6b127adc 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);
diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp
index b7b2bfb38e..e741f66fde 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,11 +311,18 @@ 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 * 4 + 0] = oldPalette[colorNr * 4] * stepNr / 100;
- workPalette[colorNr * 4 + 1] = oldPalette[colorNr * 4 + 1] * stepNr / 100;
- workPalette[colorNr * 4 + 2] = oldPalette[colorNr * 4 + 2] * stepNr / 100;
+ for (colorNr = 1; colorNr < tillColorNr; colorNr++) {
+ if (_palette->colorIsFromMacClut(colorNr)) {
+ workPalette[colorNr * 4 + 0] = oldPalette[colorNr * 4];
+ workPalette[colorNr * 4 + 1] = oldPalette[colorNr * 4 + 1];
+ workPalette[colorNr * 4 + 2] = oldPalette[colorNr * 4 + 2];
+ } else {
+ workPalette[colorNr * 4 + 0] = oldPalette[colorNr * 4] * stepNr / 100;
+ workPalette[colorNr * 4 + 1] = oldPalette[colorNr * 4 + 1] * stepNr / 100;
+ workPalette[colorNr * 4 + 2] = oldPalette[colorNr * 4 + 2] * stepNr / 100;
+ }
}
+
g_system->getPaletteManager()->setPalette(workPalette + 4, 1, 254);
g_sci->getEngineState()->wait(2);
}
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index c69e35df6d..7147b17b82 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -261,6 +261,9 @@ Common::Error SciEngine::run() {
syncSoundSettings();
syncIngameAudioOptions();
+ // Load our Mac executable here for icon bar palettes and high-res fonts
+ loadMacExecutable();
+
// Initialize all graphics related subsystems
initGraphics();
@@ -857,4 +860,34 @@ void SciEngine::syncIngameAudioOptions() {
}
}
+void SciEngine::loadMacExecutable() {
+ if (getPlatform() != Common::kPlatformMacintosh || getSciVersion() < SCI_VERSION_1_EARLY || getSciVersion() > SCI_VERSION_1_1)
+ return;
+
+ Common::String filename;
+
+ switch (getGameId()) {
+ case GID_KQ6:
+ filename = "King's Quest VI";
+ break;
+ case GID_FREDDYPHARKAS:
+ filename = "Freddy Pharkas";
+ break;
+ default:
+ break;
+ }
+
+ if (filename.empty())
+ return;
+
+ if (!_macExecutable.open(filename) || !_macExecutable.hasResFork()) {
+ // KQ6/Freddy require the executable to load their icon bar palettes
+ if (hasMacIconBar())
+ error("Could not load Mac resource fork '%s'", filename.c_str());
+
+ // TODO: Show some sort of warning dialog saying they can't get any
+ // high-res Mac fonts, when we get to that point ;)
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 9404425af6..b3e398325f 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -27,6 +27,7 @@
#define SCI_H
#include "engines/engine.h"
+#include "common/macresman.h"
#include "common/util.h"
#include "common/random.h"
#include "sci/engine/vm_types.h" // for Selector
@@ -323,6 +324,8 @@ public:
DebugState _debugState;
+ Common::MacResManager *getMacExecutable() { return &_macExecutable; }
+
private:
/**
* Initializes a SCI game
@@ -349,6 +352,11 @@ private:
*/
void exitGame();
+ /**
+ * Loads the Mac executable for SCI1 games
+ */
+ void loadMacExecutable();
+
void initStackBaseWithSelector(Selector selector);
bool gameHasFanMadePatch();
@@ -366,6 +374,7 @@ private:
reg_t _gameSuperClassAddress; // Address of the super class of the game object
Console *_console;
Common::RandomSource _rng;
+ Common::MacResManager _macExecutable;
};