diff options
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/graphics/maciconbar.cpp | 6 | ||||
-rw-r--r-- | engines/sci/graphics/palette.cpp | 156 | ||||
-rw-r--r-- | engines/sci/graphics/palette.h | 7 | ||||
-rw-r--r-- | engines/sci/graphics/screen.cpp | 28 | ||||
-rw-r--r-- | engines/sci/graphics/screen.h | 3 | ||||
-rw-r--r-- | engines/sci/graphics/transitions.cpp | 20 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 33 | ||||
-rw-r--r-- | engines/sci/sci.h | 9 |
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; }; |