From cfae0162008fb27dfd8e0e6c8aeab1721974c562 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Mon, 8 Jun 2009 20:46:21 +0000 Subject: Convert FWRenderer and OSRenderer to use Cine::Palette. Also fix some bugs that came up in testing of Cine::Palette. svn-id: r41386 --- engines/cine/gfx.cpp | 327 +++++++++++++-------------------------------------- engines/cine/gfx.h | 14 +-- engines/cine/pal.cpp | 85 +++---------- engines/cine/pal.h | 17 +-- 4 files changed, 108 insertions(+), 335 deletions(-) (limited to 'engines/cine') diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index d388a9e206..87e0e0aa5b 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -90,9 +90,9 @@ static const byte cursorPalette[] = { /*! \brief Initialize renderer */ -FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""), +FWRenderer::FWRenderer() : _background(NULL), _backupPal(), _cmd(""), _cmdY(0), _messageBg(0), _backBuffer(new byte[_screenSize]), - _activeLowPal(NULL), _changePal(0), _showCollisionPage(false) { + _activePal(), _changePal(0), _showCollisionPage(false) { assert(_backBuffer); @@ -104,21 +104,17 @@ FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""), */ FWRenderer::~FWRenderer() { delete[] _background; - delete[] _palette; delete[] _backBuffer; - delete[] _activeLowPal; } /* \brief Reset renderer state */ void FWRenderer::clear() { delete[] _background; - delete[] _palette; - delete[] _activeLowPal; _background = NULL; - _palette = NULL; - _activeLowPal = NULL; + _backupPal.clear(); + _activePal.clear(); memset(_backBuffer, 0, _screenSize); @@ -550,59 +546,39 @@ void FWRenderer::setCommand(Common::String cmd) { /*! \brief Refresh current palette */ void FWRenderer::refreshPalette() { - int i; - byte pal[16*4]; - - assert(_activeLowPal); - - for (i = 0; i < 16; i++) { - pal[i * 4 + 2] = ((_activeLowPal[i] & 0x007) >> 0) * 32; - pal[i * 4 + 1] = ((_activeLowPal[i] & 0x070) >> 4) * 32; - pal[i * 4 + 0] = ((_activeLowPal[i] & 0x700) >> 8) * 32; - pal[i * 4 + 3] = 0; - } - - g_system->setPalette(pal, 0, 16); + assert(_activePal.isValid() && !_activePal.empty()); + _activePal.setGlobalOSystemPalette(); _changePal = 0; } /*! \brief Load palette of current background */ void FWRenderer::reloadPalette() { - assert(_palette); - - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - } - - assert(_activeLowPal); - - memcpy(_activeLowPal, _palette, _lowPalSize * sizeof (uint16)); + assert(_backupPal.isValid() && !_backupPal.empty()); + _activePal = _backupPal; _changePal = 1; } /*! \brief Load background into renderer * \param bg Raw background data + * \todo Combine with OSRenderer's version of loadBg16 */ void FWRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { assert(idx == 0); - int i; if (!_background) { _background = new byte[_screenSize]; } - if (!_palette) { - _palette = new uint16[_lowPalSize]; - } - - assert(_background && _palette); + assert(_background); strcpy(_bgName, name); - for (i = 0; i < _lowPalSize; i++, bg += 2) { - _palette[i] = READ_BE_UINT16(bg); - } + // Load the 16 color palette + _backupPal.load(bg, kLowPalNumBytes, kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); + + // Jump over the palette data to the background data + bg += kLowPalNumBytes; gfxConvertSpriteToRaw(_background, bg, 160, 200); } @@ -668,25 +644,15 @@ const char *FWRenderer::getBgName(uint idx) const { * \param fHandle Savefile open for reading */ void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) { - int i; + byte buf[kLowPalNumBytes]; - if (!_palette) { - _palette = new uint16[_lowPalSize]; - } + // Load the active 16 color palette from file + fHandle.read(buf, kLowPalNumBytes); + _activePal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - } - - assert(_palette && _activeLowPal); - - for (i = 0; i < _lowPalSize; i++) { - _activeLowPal[i] = fHandle.readUint16BE(); - } - - for (i = 0; i < _lowPalSize; i++) { - _palette[i] = fHandle.readUint16BE(); - } + // Load the backup 16 color palette from file + fHandle.read(buf, kLowPalNumBytes); + _backupPal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); _changePal = 1; } @@ -695,58 +661,59 @@ void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) { * \param fHandle Savefile open for writing */ void FWRenderer::savePalette(Common::OutSaveFile &fHandle) { - int i; + byte buf[kLowPalNumBytes]; - assert(_palette && _activeLowPal); + // Make sure the active palette has the correct format and color count + assert(_activePal.colorFormat() == kLowPalFormat); + assert(_activePal.colorCount() == kLowPalNumColors); - for (i = 0; i < _lowPalSize; i++) { - fHandle.writeUint16BE(_activeLowPal[i]); - } + // Make sure the backup palette has the correct format and color count + assert(_backupPal.colorFormat() == kLowPalFormat); + assert(_backupPal.colorCount() == kLowPalNumColors); - for (i = 0; i < _lowPalSize; i++) { - fHandle.writeUint16BE(_palette[i]); - } + // Write the active palette to the file + _activePal.save(buf, sizeof(buf), CINE_BIG_ENDIAN); + fHandle.write(buf, kLowPalNumBytes); + + // Write the backup palette to the file + _backupPal.save(buf, sizeof(buf), CINE_BIG_ENDIAN); + fHandle.write(buf, kLowPalNumBytes); } /*! \brief Write active and backup palette to save * \param fHandle Savefile open for writing + * \todo Add support for saving the palette in the 16 color version of Operation Stealth. + * Possibly combine with FWRenderer's savePalette-method? */ void OSRenderer::savePalette(Common::OutSaveFile &fHandle) { - int i; + byte buf[kHighPalNumBytes]; - assert(_activeHiPal); + // Make sure the active palette has the correct format and color count + assert(_activePal.colorFormat() == kHighPalFormat); + assert(_activePal.colorCount() == kHighPalNumColors); // Write the active 256 color palette. - for (i = 0; i < _hiPalSize; i++) { - fHandle.writeByte(_activeHiPal[i]); - } + _activePal.save(buf, sizeof(buf), CINE_LITTLE_ENDIAN); + fHandle.write(buf, kHighPalNumBytes); // Write the active 256 color palette a second time. // FIXME: The backup 256 color palette should be saved here instead of the active one. - for (i = 0; i < _hiPalSize; i++) { - fHandle.writeByte(_activeHiPal[i]); - } + fHandle.write(buf, kHighPalNumBytes); } /*! \brief Restore active and backup palette from save * \param fHandle Savefile open for reading */ void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) { - int i; - - if (!_activeHiPal) { - _activeHiPal = new byte[_hiPalSize]; - } + byte buf[kHighPalNumBytes]; - assert(_activeHiPal); - - for (i = 0; i < _hiPalSize; i++) { - _activeHiPal[i] = fHandle.readByte(); - } + // Load the active 256 color palette from file + fHandle.read(buf, kHighPalNumBytes); + _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); // Jump over the backup 256 color palette. // FIXME: Load the backup 256 color palette and use it properly. - fHandle.seek(_hiPalSize, SEEK_CUR); + fHandle.seek(kHighPalNumBytes, SEEK_CUR); _changePal = 1; } @@ -754,10 +721,10 @@ void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) { /*! \brief Rotate active palette * \param a First color to rotate * \param b Last color to rotate - * \param c Possibly rotation step, must be equal to 1 at the moment + * \param c Possibly rotation step, must be 0 or 1 at the moment */ void FWRenderer::rotatePalette(int a, int b, int c) { - palRotate(_activeLowPal, a, b, c); + _activePal.rotateRight(a, b, c); refreshPalette(); } @@ -769,12 +736,11 @@ void FWRenderer::rotatePalette(int a, int b, int c) { * \param b Blue channel transformation */ void FWRenderer::transformPalette(int first, int last, int r, int g, int b) { - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16)); + if (!_activePal.isValid() || _activePal.empty()) { + _activePal = Cine::Palette(kLowPalFormat, kLowPalNumColors); } - transformPaletteRange(_activeLowPal, _palette, first, last, r, g, b); + _backupPal.saturatedAddColor(_activePal, first, last, r, g, b); refreshPalette(); } @@ -889,22 +855,16 @@ void FWRenderer::drawInputBox(const char *info, const char *input, int cursor, i } /*! \brief Fade to black + * \bug Operation Stealth sometimes seems to fade to black using + * transformPalette resulting in double fadeout */ void FWRenderer::fadeToBlack() { - // FIXME: _activeLowPal is invalid when starting Operation Stealth - // Adding this sanity check fixes a crash when the game - // starts, but I'm not sure if this is the best place to check it - if (!_activeLowPal) { - warning("_activeLowPal is invalid"); - return; - } - - assert(_activeLowPal); + assert(_activePal.isValid() && !_activePal.empty()); for (int i = 0; i < 8; i++) { - for (int j = 0; j < 16; j++) { - _activeLowPal[j] = transformColor(_activeLowPal[j], -1, -1, -1); - } + // Fade out the whole palette by 1/7th + // (Operation Stealth used 36 / 252, which is 1 / 7. Future Wars used 1 / 7 directly). + _activePal.saturatedAddNormalizedGray(_activePal, 0, _activePal.colorCount() - 1, -1, 7); refreshPalette(); g_system->updateScreen(); @@ -914,14 +874,13 @@ void FWRenderer::fadeToBlack() { /*! \brief Initialize Operation Stealth renderer */ -OSRenderer::OSRenderer() : _activeHiPal(NULL), _currentBg(0), _scrollBg(0), +OSRenderer::OSRenderer() : FWRenderer(), _currentBg(0), _scrollBg(0), _bgShift(0) { int i; for (i = 0; i < 9; i++) { _bgTable[i].bg = NULL; - _bgTable[i].lowPal = NULL; - _bgTable[i].hiPal = NULL; + _bgTable[i].pal.clear(); memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); } } @@ -929,29 +888,20 @@ OSRenderer::OSRenderer() : _activeHiPal(NULL), _currentBg(0), _scrollBg(0), /*! \brief Destroy Operation Stealth renderer */ OSRenderer::~OSRenderer() { - delete[] _activeHiPal; - for (int i = 0; i < 9; i++) { delete[] _bgTable[i].bg; - delete[] _bgTable[i].lowPal; - delete[] _bgTable[i].hiPal; + _bgTable[i].pal.clear(); } } /*! \brief Reset Operation Stealth renderer state */ void OSRenderer::clear() { - delete[] _activeHiPal; - _activeHiPal = NULL; - for (int i = 0; i < 9; i++) { delete[] _bgTable[i].bg; - delete[] _bgTable[i].lowPal; - delete[] _bgTable[i].hiPal; _bgTable[i].bg = NULL; - _bgTable[i].lowPal = NULL; - _bgTable[i].hiPal = NULL; + _bgTable[i].pal.clear(); memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); } @@ -1159,28 +1109,6 @@ void OSRenderer::renderOverlay(const Common::List::iterator &it) { } } -/*! \brief Refresh current palette - */ -void OSRenderer::refreshPalette() { - if (!_activeHiPal) { - FWRenderer::refreshPalette(); - return; - } - - int i; - byte pal[256*4]; - - for (i = 0; i < 256; i++) { - pal[i * 4 + 0] = _activeHiPal[i * 3 + 0]; - pal[i * 4 + 1] = _activeHiPal[i * 3 + 1]; - pal[i * 4 + 2] = _activeHiPal[i * 3 + 2]; - pal[i * 4 + 3] = 0; - } - - g_system->setPalette(pal, 0, 256); - _changePal = 0; -} - /*! \brief Load palette of current background */ void OSRenderer::reloadPalette() { @@ -1188,49 +1116,12 @@ void OSRenderer::reloadPalette() { // and 14, shift background has it right palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg]; - assert(bg->lowPal || bg->hiPal); - - if (bg->lowPal) { - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - } - - assert(_activeLowPal); + assert(bg->pal.isValid() && !(bg->pal.empty())); - delete[] _activeHiPal; - _activeHiPal = NULL; - - memcpy(_activeLowPal, bg->lowPal, _lowPalSize * sizeof (uint16)); - } else { - if (!_activeHiPal) { - _activeHiPal = new byte[_hiPalSize]; - } - - assert(_activeHiPal); - - delete[] _activeLowPal; - _activeLowPal = NULL; - - memcpy(_activeHiPal, bg->hiPal, _hiPalSize); - } + _activePal = bg->pal; _changePal = 1; } -/*! \brief Rotate active palette - * \param a First color to rotate - * \param b Last color to rotate - * \param c Possibly rotation step, must be equal to 1 at the moment - */ -void OSRenderer::rotatePalette(int a, int b, int c) { - if (_activeLowPal) { - FWRenderer::rotatePalette(a, b, c); - return; - } - - palRotate(_activeHiPal, a, b, c); - refreshPalette(); -} - /*! \brief Copy part of backup palette to active palette and transform * \param first First color to transform * \param last Last color to transform @@ -1241,28 +1132,12 @@ void OSRenderer::rotatePalette(int a, int b, int c) { void OSRenderer::transformPalette(int first, int last, int r, int g, int b) { palBg *bg = _bgShift ? &_bgTable[_scrollBg] : &_bgTable[_currentBg]; - if (!bg->lowPal) { - if (!_activeHiPal) { - _activeHiPal = new byte[_hiPalSize]; - memset(_activeHiPal, 0, _hiPalSize); - } - - delete[] _activeLowPal; - _activeLowPal = NULL; - - transformPaletteRange(_activeHiPal, bg->hiPal, first, last, r, g, b); - } else { - if (!_activeLowPal) { - _activeLowPal = new uint16[_lowPalSize]; - memset(_activeLowPal, 0, _lowPalSize * sizeof (uint16)); - } - - delete[] _activeHiPal; - _activeHiPal = NULL; - - transformPaletteRange(_activeLowPal, bg->lowPal, first, last, r, g, b); + // Initialize active palette to current background's palette format and size if they differ + if (_activePal.colorFormat() != bg->pal.colorFormat() || _activePal.colorCount() != bg->pal.colorCount()) { + _activePal = Cine::Palette(bg->pal.colorFormat(), bg->pal.colorCount()); } + bg->pal.saturatedAddColor(_activePal, first, last, r, g, b, kLowPalFormat); refreshPalette(); } @@ -1270,29 +1145,24 @@ void OSRenderer::transformPalette(int first, int last, int r, int g, int b) { * \param bg Raw background data * \param name Background filename * \param pos Background index + * \todo Combine with FWRenderer's version of loadBg16 */ void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { - int i; assert(idx < 9); if (!_bgTable[idx].bg) { _bgTable[idx].bg = new byte[_screenSize]; } - if (!_bgTable[idx].lowPal) { - _bgTable[idx].lowPal = new uint16[_lowPalSize]; - } - - assert(_bgTable[idx].bg && _bgTable[idx].lowPal); - - delete[] _bgTable[idx].hiPal; - _bgTable[idx].hiPal = NULL; + assert(_bgTable[idx].bg); strcpy(_bgTable[idx].name, name); - for (i = 0; i < _lowPalSize; i++, bg += 2) { - _bgTable[idx].lowPal[i] = READ_BE_UINT16(bg); - } + // Load the 16 color palette + _bgTable[idx].pal.load(bg, kLowPalNumBytes, kLowPalFormat, kLowPalNumColors, CINE_BIG_ENDIAN); + + // Jump over the palette data to the background data + bg += kLowPalNumBytes; gfxConvertSpriteToRaw(_bgTable[idx].bg, bg, 160, 200); } @@ -1317,18 +1187,11 @@ void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) { _bgTable[idx].bg = new byte[_screenSize]; } - if (!_bgTable[idx].hiPal) { - _bgTable[idx].hiPal = new byte[_hiPalSize]; - } - - assert(_bgTable[idx].bg && _bgTable[idx].hiPal); - - delete[] _bgTable[idx].lowPal; - _bgTable[idx].lowPal = NULL; + assert(_bgTable[idx].bg); strcpy(_bgTable[idx].name, name); - memcpy(_bgTable[idx].hiPal, bg, _hiPalSize); - memcpy(_bgTable[idx].bg, bg + _hiPalSize, _screenSize); + _bgTable[idx].pal.load(bg, kHighPalNumBytes, kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); + memcpy(_bgTable[idx].bg, bg + kHighPalNumBytes, _screenSize); } /*! \brief Load 256 color CT data as background into renderer @@ -1344,7 +1207,7 @@ void OSRenderer::loadCt256(const byte *ct, const char *name) { */ void OSRenderer::selectBg(unsigned int idx) { assert(idx < 9 && _bgTable[idx].bg); - assert(_bgTable[idx].lowPal || _bgTable[idx].hiPal); + assert(_bgTable[idx].pal.isValid() && !(_bgTable[idx].pal.empty())); _currentBg = idx; reloadPalette(); @@ -1393,11 +1256,8 @@ void OSRenderer::removeBg(unsigned int idx) { } delete[] _bgTable[idx].bg; - delete[] _bgTable[idx].lowPal; - delete[] _bgTable[idx].hiPal; _bgTable[idx].bg = NULL; - _bgTable[idx].lowPal = NULL; - _bgTable[idx].hiPal = NULL; + _bgTable[idx].pal.clear(); memset(_bgTable[idx].name, 0, sizeof (_bgTable[idx].name)); } @@ -1412,27 +1272,6 @@ const char *OSRenderer::getBgName(uint idx) const { return _bgTable[idx].name; } -/*! \brief Fade to black - * \bug Operation Stealth sometimes seems to fade to black using - * transformPalette resulting in double fadeout - */ -void OSRenderer::fadeToBlack() { - if (!_activeHiPal) { - FWRenderer::fadeToBlack(); - return; - } - - for (int i = 0; i < 8; i++) { - for (int j = 0; j < _hiPalSize; j++) { - _activeHiPal[j] = CLIP(_activeHiPal[j] - 32, 0, 255); - } - - refreshPalette(); - g_system->updateScreen(); - g_system->delayMillis(50); - } -} - void setMouseCursor(int cursor) { static int currentMouseCursor = -1; assert(cursor >= 0 && cursor < 3); diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index 0ed1626ab0..839f37a0b1 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -35,8 +35,7 @@ namespace Cine { */ struct palBg { byte *bg; ///< Background data - byte *hiPal; ///< 256 color palette - uint16 *lowPal; ///< 16 color palette + Cine::Palette pal; ///< Background color palette char name[15]; ///< Background filename }; @@ -46,10 +45,10 @@ struct palBg { * without calling drawFrame() all the time */ class FWRenderer : public Common::NonCopyable { +protected: private: byte *_background; ///< Current background char _bgName[13]; ///< Background filename - uint16 *_palette; ///< 16 color backup palette Common::String _cmd; ///< Player command string @@ -57,10 +56,10 @@ protected: static const int _screenSize = 320 * 200; ///< Screen size static const int _screenWidth = 320; ///< Screen width static const int _screenHeight = 200; ///< Screen height - static const int _lowPalSize = 16; ///< 16 color palette size byte *_backBuffer; ///< Screen backbuffer - uint16 *_activeLowPal; ///< Active 16 color palette + Cine::Palette _backupPal; ///< The backup color palette + Cine::Palette _activePal; ///< The active color palette int _changePal; ///< Load active palette to video backend on next frame bool _showCollisionPage; ///< Should we show the collision page instead of the back buffer? Used for debugging. @@ -132,13 +131,11 @@ class OSRenderer : public FWRenderer { private: // FIXME: Background table's size is probably 8 instead of 9. Check to make sure and correct if necessary. palBg _bgTable[9]; ///< Table of backgrounds loaded into renderer - byte *_activeHiPal; ///< Active 256 color palette unsigned int _currentBg; ///< Current background unsigned int _scrollBg; ///< Current scroll background unsigned int _bgShift; ///< Background shift protected: - static const int _hiPalSize = 256 * 3; ///< 256 color palette size void drawSprite(const objectStruct &obj); int drawChar(char character, int x, int y); @@ -169,14 +166,11 @@ public: void saveBgNames(Common::OutSaveFile &fHandle); const char *getBgName(uint idx = 0) const; - void refreshPalette(); void reloadPalette(); void restorePalette(Common::SeekableReadStream &fHandle); void savePalette(Common::OutSaveFile &fHandle); - void rotatePalette(int a, int b, int c); void transformPalette(int first, int last, int r, int g, int b); - void fadeToBlack(); }; void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy); diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp index 49edaef5e4..b3e3629239 100644 --- a/engines/cine/pal.cpp +++ b/engines/cine/pal.cpp @@ -103,65 +103,6 @@ void loadRelatedPalette(const char *fileName) { } } -void palRotate(uint16 *pal, byte a, byte b, byte c) { - assert(pal); - - if (c == 1) { - uint16 currentColor = pal[b]; - - for (int i = b; i > a; i--) { - pal[i] = pal[i - 1]; - } - - pal[a] = currentColor; - } -} - -void palRotate(byte *pal, byte a, byte b, byte c) { - assert(pal); - - if (c == 1) { - byte currentR = pal[3 * b + 0]; - byte currentG = pal[3 * b + 1]; - byte currentB = pal[3 * b + 2]; - - for (int i = b; i > a; i--) { - pal[3 * i + 0] = pal[3 * (i - 1) + 0]; - pal[3 * i + 1] = pal[3 * (i - 1) + 1]; - pal[3 * i + 2] = pal[3 * (i - 1) + 2]; - } - - pal[3 * a + 0] = currentR; - pal[3 * a + 1] = currentG; - pal[3 * a + 2] = currentB; - } -} - -uint16 transformColor(uint16 baseColor, int r, int g, int b) { - int8 oriR = CLIP( (baseColor & 0x007) + b, 0, 7); - int8 oriG = CLIP(((baseColor & 0x070) >> 4) + g, 0, 7); - int8 oriB = CLIP(((baseColor & 0x700) >> 8) + r, 0, 7); - - return oriR | (oriG << 4) | (oriB << 8); -} - -void transformPaletteRange(uint16 *dstPal, uint16 *srcPal, int startColor, int stopColor, int r, int g, int b) { - assert(srcPal && dstPal); - - for (int i = startColor; i <= stopColor; i++) - dstPal[i] = transformColor(srcPal[i], r, g, b); -} - -void transformPaletteRange(byte *dstPal, byte *srcPal, int startColor, int stopColor, int r, int g, int b) { - assert(srcPal && dstPal); - - for (int i = startColor; i <= stopColor; i++) { - dstPal[3 * i + 0] = CLIP(srcPal[3 * i + 0] + r * 36, 0, 252); - dstPal[3 * i + 1] = CLIP(srcPal[3 * i + 1] + g * 36, 0, 252); - dstPal[3 * i + 2] = CLIP(srcPal[3 * i + 2] + b * 36, 0, 252); - } -} - /*! \brief Shift byte to the left by given amount (Handles negative shifting amounts too, otherwise this would be trivial). */ byte shiftByteLeft(const byte value, const signed shiftLeft) { if (shiftLeft >= 0) @@ -198,13 +139,17 @@ int bytePos(const int bitPos, const int numBytes, const bool bigEndian) { } // a.k.a. palRotate -Palette &Palette::rotateRight(byte firstIndex, byte lastIndex) { - const Color lastColor = _colors[lastIndex]; +Palette &Palette::rotateRight(byte firstIndex, byte lastIndex, signed rotationAmount) { + assert(rotationAmount == 0 || rotationAmount == 1); + + if (rotationAmount == 1) { + const Color lastColor = _colors[lastIndex]; - for (int i = lastIndex; i > firstIndex; i--) - _colors[i] = _colors[i - 1]; + for (int i = lastIndex; i > firstIndex; i--) + _colors[i] = _colors[i - 1]; - _colors[firstIndex] = lastColor; + _colors[firstIndex] = lastColor; + } return *this; } @@ -277,18 +222,18 @@ Palette &Palette::saturatedAddColor(Palette& output, byte firstIndex, byte lastI Palette &Palette::saturatedAddColor(Palette& output, byte firstIndex, byte lastIndex, signed rSource, signed gSource, signed bSource, const Graphics::PixelFormat &sourceFormat) { // Convert the source color to the internal color format ensuring that no divide by zero will happen - const signed r = _format.rMax() * rSource / MAX(sourceFormat.rMax(), 1); - const signed g = _format.gMax() * gSource / MAX(sourceFormat.gMax(), 1); - const signed b = _format.bMax() * bSource / MAX(sourceFormat.bMax(), 1); + const signed r = ((signed) _format.rMax()) * rSource / MAX(sourceFormat.rMax(), 1); + const signed g = ((signed) _format.gMax()) * gSource / MAX(sourceFormat.gMax(), 1); + const signed b = ((signed) _format.bMax()) * bSource / MAX(sourceFormat.bMax(), 1); return saturatedAddColor(output, firstIndex, lastIndex, r, g, b); } Palette &Palette::saturatedAddNormalizedGray(Palette& output, byte firstIndex, byte lastIndex, int grayDividend, int grayDenominator) { assert(grayDenominator != 0); - const signed r = _format.rMax() * grayDividend / grayDenominator; - const signed g = _format.gMax() * grayDividend / grayDenominator; - const signed b = _format.bMax() * grayDividend / grayDenominator; + const signed r = ((signed) _format.rMax()) * grayDividend / grayDenominator; + const signed g = ((signed) _format.gMax()) * grayDividend / grayDenominator; + const signed b = ((signed) _format.bMax()) * grayDividend / grayDenominator; return saturatedAddColor(output, firstIndex, lastIndex, r, g, b); } diff --git a/engines/cine/pal.h b/engines/cine/pal.h index f59dee53df..4764d5a474 100644 --- a/engines/cine/pal.h +++ b/engines/cine/pal.h @@ -73,16 +73,8 @@ void loadPal(const char *fileName); void loadRelatedPalette(const char *fileName); -void palRotate(uint16 *pal, byte a, byte b, byte c); -void palRotate(byte *pal, byte a, byte b, byte c); -uint16 transformColor(uint16 baseColor, int r, int g, int b); -void transformPaletteRange(uint16 *srcPal, uint16 *dstPal, int startColor, int stopColor, int r, int g, int b); -void transformPaletteRange(byte *srcPal, byte *dstPal, int startColor, int stopColor, int r, int g, int b); - -// This class might be used for handling Cine-engine's palettes in the future. WIP! -// TODO: Document -// TODO: Make use of -// TODO: Test +// A class for handling Cine-engine's palettes. +// TODO: Test a bit more class Palette { public: struct Color { @@ -135,7 +127,10 @@ public: */ byte *save(byte *buf, const uint size, const Graphics::PixelFormat format, const uint numColors, const EndianType endian, const byte firstIndex = 0) const; - Palette &rotateRight(byte firstIndex, byte lastIndex); + /*! \brief Rotate the palette in color range [firstIndex, lastIndex] to the right by the specified rotation amount. + * \param rotationAmount Amount to rotate the sub-palette to the right. Only values 0 and 1 are currently supported! + */ + Palette &rotateRight(byte firstIndex, byte lastIndex, signed rotationAmount = 1); Palette &saturatedAddColor(Palette& output, byte firstIndex, byte lastIndex, signed r, signed g, signed b); /*! \brief Saturated add an RGB color in given color format to current palette's subset and save the modified colors in the given output palette. -- cgit v1.2.3 From f5b2e69522153c47438895ea80129ad5e3c9b952 Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Thu, 11 Jun 2009 18:32:35 +0000 Subject: Fix Operation Stealth's 2nd arcade sequence's revolving doors. - Now the doors actually do revolve when before they didn't. - The fix was to alias the 9th background with the collision page directly when loading collision page data. This way changes written to the 9th background go to the collision page and vice versa (And there were changes in the labyrinth). - Also converted _bgTable from a pure array to a Common::Array svn-id: r41453 --- engines/cine/bg.cpp | 1 - engines/cine/gfx.cpp | 37 +++++++++++++++---------------------- engines/cine/gfx.h | 26 +++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 26 deletions(-) (limited to 'engines/cine') diff --git a/engines/cine/bg.cpp b/engines/cine/bg.cpp index cc7e843c2b..08722c42e5 100644 --- a/engines/cine/bg.cpp +++ b/engines/cine/bg.cpp @@ -82,7 +82,6 @@ byte loadCtOS(const char *ctName) { ptr += 2; if (bpp == 8) { - memcpy(collisionPage, ptr + 256 * 3, 320 * 200); renderer->loadCt256(ptr, ctName); } else { gfxConvertSpriteToRaw(collisionPage, ptr + 32, 160, 200); diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index 87e0e0aa5b..ddc2d48152 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -874,35 +874,25 @@ void FWRenderer::fadeToBlack() { /*! \brief Initialize Operation Stealth renderer */ -OSRenderer::OSRenderer() : FWRenderer(), _currentBg(0), _scrollBg(0), +OSRenderer::OSRenderer() : FWRenderer(), _bgTable(), _currentBg(0), _scrollBg(0), _bgShift(0) { - int i; - for (i = 0; i < 9; i++) { - _bgTable[i].bg = NULL; - _bgTable[i].pal.clear(); - memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); - } + _bgTable.resize(9); // Resize the background table to its required size } /*! \brief Destroy Operation Stealth renderer */ OSRenderer::~OSRenderer() { - for (int i = 0; i < 9; i++) { - delete[] _bgTable[i].bg; - _bgTable[i].pal.clear(); + for (uint i = 0; i < _bgTable.size(); i++) { + _bgTable[i].clear(); } } /*! \brief Reset Operation Stealth renderer state */ void OSRenderer::clear() { - for (int i = 0; i < 9; i++) { - delete[] _bgTable[i].bg; - - _bgTable[i].bg = NULL; - _bgTable[i].pal.clear(); - memset(_bgTable[i].name, 0, sizeof (_bgTable[i].name)); + for (uint i = 0; i < _bgTable.size(); i++) { + _bgTable[i].clear(); } _currentBg = 0; @@ -1172,7 +1162,10 @@ void OSRenderer::loadBg16(const byte *bg, const char *name, unsigned int idx) { * \param name Background filename */ void OSRenderer::loadCt16(const byte *ct, const char *name) { - loadBg16(ct, name, 8); + // Make the 9th background point directly to the collision page + // and load the picture into it. + _bgTable[kCollisionPageBgIdxAlias].bg = collisionPage; + loadBg16(ct, name, kCollisionPageBgIdxAlias); } /*! \brief Load 256 color background into renderer @@ -1199,7 +1192,10 @@ void OSRenderer::loadBg256(const byte *bg, const char *name, unsigned int idx) { * \param name Background filename */ void OSRenderer::loadCt256(const byte *ct, const char *name) { - loadBg256(ct, name, 8); + // Make the 9th background point directly to the collision page + // and load the picture into it. + _bgTable[kCollisionPageBgIdxAlias].bg = collisionPage; + loadBg256(ct, name, kCollisionPageBgIdxAlias); } /*! \brief Select active background and load its palette @@ -1255,10 +1251,7 @@ void OSRenderer::removeBg(unsigned int idx) { _scrollBg = 0; } - delete[] _bgTable[idx].bg; - _bgTable[idx].bg = NULL; - _bgTable[idx].pal.clear(); - memset(_bgTable[idx].name, 0, sizeof (_bgTable[idx].name)); + _bgTable[idx].clear(); } void OSRenderer::saveBgNames(Common::OutSaveFile &fHandle) { diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index 839f37a0b1..f1503a4c46 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -31,12 +31,34 @@ namespace Cine { +extern byte *collisionPage; +static const int kCollisionPageBgIdxAlias = 8; + /*! \brief Background with palette */ struct palBg { byte *bg; ///< Background data Cine::Palette pal; ///< Background color palette char name[15]; ///< Background filename + + /** @brief Default constructor. */ + palBg() : bg(NULL), pal(), name() { + // Make sure the name is empty (Maybe this is not needed?) + memset(this->name, 0, sizeof(this->name)); + } + + /** @brief Clears the struct (Releases allocated memory etc). */ + void clear() { + // In Operation Stealth the 9th background is sometimes aliased to + // the collision page so we should take care not to double delete it + // (The collision page is deleted elsewhere). + if (this->bg != collisionPage) { + delete[] this->bg; + } + this->bg = NULL; + this->pal.clear(); + memset(this->name, 0, sizeof(this->name)); + } }; /*! \brief Future Wars renderer @@ -129,8 +151,7 @@ public: */ class OSRenderer : public FWRenderer { private: - // FIXME: Background table's size is probably 8 instead of 9. Check to make sure and correct if necessary. - palBg _bgTable[9]; ///< Table of backgrounds loaded into renderer + Common::Array _bgTable; ///< Table of backgrounds loaded into renderer (Maximum is 9) unsigned int _currentBg; ///< Current background unsigned int _scrollBg; ///< Current scroll background unsigned int _bgShift; ///< Background shift @@ -175,7 +196,6 @@ public: void gfxDrawSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy); -extern byte *collisionPage; extern FWRenderer *renderer; void setMouseCursor(int cursor); -- cgit v1.2.3 From 1da48cfd552556c9e8b4eeef20fa43bdb7994063 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Sat, 20 Jun 2009 10:52:55 +0000 Subject: fixed OPL 0xB0 register write. the return value of findNote() already includes the octave, no need to readd it. svn-id: r41704 --- engines/cine/sound.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines/cine') diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp index 164c5a9ca5..65b384ac7d 100644 --- a/engines/cine/sound.cpp +++ b/engines/cine/sound.cpp @@ -507,8 +507,6 @@ void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) { } int freq, note, oct; findNote(frequency, ¬e, &oct); - - note += oct * 12; if (ins->amDepth) { note = ins->amDepth; } -- cgit v1.2.3 From 49dd58de45db302214b65af5b296a21f84f02ebe Mon Sep 17 00:00:00 2001 From: Kari Salminen Date: Sat, 27 Jun 2009 12:26:26 +0000 Subject: Name Operation Stealth's global variables 251 and 252 and init them in main loop. These are used as a sort of a backup for the mouse position (x, y) variables 249 and 250. Future Wars's VAR_MOUSE_Y_MODE and Operation Stealth's VAR_MOUSE_X_POS_2ND (251) clash and that's possibly why executePlayerInput currently works incorrectly with Operation Stealth. More reverse engineering is needed... svn-id: r41915 --- engines/cine/cine.h | 8 ++++++-- engines/cine/main_loop.cpp | 2 ++ engines/cine/various.cpp | 12 ++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'engines/cine') diff --git a/engines/cine/cine.h b/engines/cine/cine.h index bf56e9189b..1031d6d449 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -127,11 +127,15 @@ extern CineEngine *g_cine; #define COPY_PROT_FAIL_PRC_NAME "L201.ANI" enum { - VAR_MOUSE_X_MODE = 253, + // Both FW and OS VAR_MOUSE_X_POS = 249, - VAR_MOUSE_Y_MODE = 251, VAR_MOUSE_Y_POS = 250, + // FW only + VAR_MOUSE_X_MODE = 253, + VAR_MOUSE_Y_MODE = 251, // OS only + VAR_MOUSE_X_POS_2ND = 251, // Many times used in conjunction with VAR_MOUSE_X_POS + VAR_MOUSE_Y_POS_2ND = 252, // Many times used in conjunction with VAR_MOUSE_Y_POS VAR_BYPASS_PROTECTION = 255, VAR_LOW_MEMORY = 0 }; diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index c6bca84e46..44e4e43a6c 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -288,6 +288,8 @@ void CineEngine::mainLoop(int bootScriptIdx) { globalVars[VAR_MOUSE_X_POS] = 0; globalVars[VAR_MOUSE_Y_POS] = 0; if (g_cine->getGameType() == Cine::GType_OS) { + globalVars[VAR_MOUSE_X_POS_2ND] = 0; + globalVars[VAR_MOUSE_Y_POS_2ND] = 0; globalVars[VAR_BYPASS_PROTECTION] = 0; // set to 1 to bypass the copy protection globalVars[VAR_LOW_MEMORY] = 0; // set to 1 to disable some animations, sounds etc. } diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 1ec558c217..7192afcd92 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -1095,8 +1095,8 @@ uint16 executePlayerInput(void) { // This fixes swimming at the bottom of the ocean after // having been thrown into it with the girl. if (g_cine->getGameType() == Cine::GType_OS) { - globalVars[251] = globalVars[VAR_MOUSE_X_POS]; - globalVars[252] = globalVars[VAR_MOUSE_Y_POS]; + globalVars[VAR_MOUSE_X_POS_2ND] = globalVars[VAR_MOUSE_X_POS]; + globalVars[VAR_MOUSE_Y_POS_2ND] = globalVars[VAR_MOUSE_Y_POS]; } return var_5E; @@ -1501,10 +1501,7 @@ void processSeqListElement(SeqListElement &element) { if (xMoveKeyb != kKeybMoveRight) { adder = -adder; } - // FIXME: In Operation Stealth's disassembly global variable 251 is used here - // but it's named as VAR_MOUSE_Y_MODE in ScummVM. Is it correct or a - // left over from Future Wars's reverse engineering? - globalVars[VAR_MOUSE_X_POS] = globalVars[251] = ptr1[4] + x + adder; + globalVars[VAR_MOUSE_X_POS] = globalVars[VAR_MOUSE_X_POS_2ND] = ptr1[4] + x + adder; } if (yMoveKeyb && allowPlayerInput) { @@ -1512,8 +1509,7 @@ void processSeqListElement(SeqListElement &element) { if (yMoveKeyb != kKeybMoveDown) { adder = -adder; } - // TODO: Name currently unnamed global variable 252 - globalVars[VAR_MOUSE_Y_POS] = globalVars[252] = ptr1[5] + y + adder; + globalVars[VAR_MOUSE_Y_POS] = globalVars[VAR_MOUSE_Y_POS_2ND] = ptr1[5] + y + adder; } if (globalVars[VAR_MOUSE_X_POS] || globalVars[VAR_MOUSE_Y_POS]) { -- cgit v1.2.3