diff options
Diffstat (limited to 'engines/sci/graphics')
-rw-r--r-- | engines/sci/graphics/maciconbar.cpp | 10 | ||||
-rw-r--r-- | engines/sci/graphics/palette.cpp | 156 | ||||
-rw-r--r-- | engines/sci/graphics/palette.h | 7 | ||||
-rw-r--r-- | engines/sci/graphics/ports.cpp | 9 | ||||
-rw-r--r-- | engines/sci/graphics/screen.cpp | 53 | ||||
-rw-r--r-- | engines/sci/graphics/screen.h | 5 | ||||
-rw-r--r-- | engines/sci/graphics/transitions.cpp | 19 |
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); |