mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-28 20:55:19 +00:00
b7991b6ad8
palette when pausing the game in a mid-fade. The game can only be paused in mid-fade from the outside, and then the palette isn't dimmed/undimmed. svn-id: r34958
288 lines
8.2 KiB
C++
288 lines
8.2 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* Additional copyright for this file:
|
|
* Copyright (C) 1994-1998 Revolution Software Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*/
|
|
|
|
|
|
#include "common/system.h"
|
|
|
|
#include "sword2/sword2.h"
|
|
#include "sword2/defs.h"
|
|
#include "sword2/header.h"
|
|
#include "sword2/logic.h"
|
|
#include "sword2/resman.h"
|
|
#include "sword2/screen.h"
|
|
|
|
namespace Sword2 {
|
|
|
|
/**
|
|
* Start layer palette fading up
|
|
*/
|
|
|
|
void Screen::startNewPalette() {
|
|
// If the screen is still fading down then wait for black - could
|
|
// happen when everythings cached into a large memory model
|
|
waitForFade();
|
|
|
|
byte *screenFile = _vm->_resman->openResource(_thisScreen.background_layer_id);
|
|
|
|
memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(screenFile), PALTABLESIZE);
|
|
setPalette(0, 256, _vm->fetchPalette(screenFile), RDPAL_FADE);
|
|
|
|
// Indicating that it's a screen palette
|
|
_lastPaletteRes = 0;
|
|
|
|
_vm->_resman->closeResource(_thisScreen.background_layer_id);
|
|
fadeUp();
|
|
_thisScreen.new_palette = 0;
|
|
}
|
|
|
|
void Screen::setFullPalette(int32 palRes) {
|
|
// fudge for hut interior
|
|
// - unpausing should restore last palette as normal (could be screen
|
|
// palette or 'dark_palette_13')
|
|
// - but restoring the screen palette after 'dark_palette_13' should
|
|
// now work properly too!
|
|
|
|
// "Hut interior" refers to the watchman's hut in Marseille, and this
|
|
// is apparently needed for the palette to be restored properly when
|
|
// you turn the light off. (I didn't even notice the light switch!)
|
|
|
|
if (_vm->_logic->readVar(LOCATION) == 13) {
|
|
// unpausing
|
|
if (palRes == -1) {
|
|
// restore whatever palette was last set (screen
|
|
// palette or 'dark_palette_13')
|
|
palRes = _lastPaletteRes;
|
|
}
|
|
} else {
|
|
// check if we're just restoring the current screen palette
|
|
// because we might actually need to use a separate palette
|
|
// file anyway eg. for pausing & unpausing during the eclipse
|
|
|
|
// unpausing (fudged for location 13)
|
|
if (palRes == -1) {
|
|
// we really meant '0'
|
|
palRes = 0;
|
|
}
|
|
|
|
if (palRes == 0 && _lastPaletteRes)
|
|
palRes = _lastPaletteRes;
|
|
}
|
|
|
|
// If non-zero, set palette to this separate palette file. Otherwise,
|
|
// set palette to current screen palette.
|
|
|
|
if (palRes) {
|
|
byte *pal = _vm->_resman->openResource(palRes);
|
|
|
|
assert(_vm->_resman->fetchType(pal) == PALETTE_FILE);
|
|
|
|
pal += ResHeader::size();
|
|
|
|
// always set colour 0 to black because most background screen
|
|
// palettes have a bright colour 0 although it should come out
|
|
// as black in the game!
|
|
|
|
pal[0] = 0;
|
|
pal[1] = 0;
|
|
pal[2] = 0;
|
|
pal[3] = 0;
|
|
|
|
setPalette(0, 256, pal, RDPAL_INSTANT);
|
|
_vm->_resman->closeResource(palRes);
|
|
} else {
|
|
if (_thisScreen.background_layer_id) {
|
|
byte *data = _vm->_resman->openResource(_thisScreen.background_layer_id);
|
|
memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(data), PALTABLESIZE);
|
|
setPalette(0, 256, _vm->fetchPalette(data), RDPAL_INSTANT);
|
|
_vm->_resman->closeResource(_thisScreen.background_layer_id);
|
|
} else
|
|
error("setFullPalette(0) called, but no current screen available!");
|
|
}
|
|
|
|
if (palRes != CONTROL_PANEL_PALETTE)
|
|
_lastPaletteRes = palRes;
|
|
}
|
|
|
|
/**
|
|
* Matches a colour triplet to a palette index.
|
|
* @param r red colour component
|
|
* @param g green colour component
|
|
* @param b blue colour component
|
|
* @return the palette index of the closest matching colour in the palette
|
|
*/
|
|
|
|
// FIXME: This used to be inlined - probably a good idea - but the
|
|
// linker complained when I tried to use it in sprite.cpp.
|
|
|
|
uint8 Screen::quickMatch(uint8 r, uint8 g, uint8 b) {
|
|
return _paletteMatch[((int32)(r >> 2) << 12) + ((int32)(g >> 2) << 6) + (b >> 2)];
|
|
}
|
|
|
|
/**
|
|
* Sets the palette.
|
|
* @param startEntry the first colour entry to set
|
|
* @param noEntries the number of colour entries to set
|
|
* @param colourTable the new colour entries
|
|
* @param fadeNow whether to perform the change immediately or delayed
|
|
*/
|
|
|
|
void Screen::setPalette(int16 startEntry, int16 noEntries, byte *colourTable, uint8 fadeNow) {
|
|
assert(noEntries > 0);
|
|
|
|
memcpy(&_palette[4 * startEntry], colourTable, noEntries * 4);
|
|
|
|
if (fadeNow == RDPAL_INSTANT) {
|
|
setSystemPalette(_palette, startEntry, noEntries);
|
|
setNeedFullRedraw();
|
|
}
|
|
}
|
|
|
|
void Screen::dimPalette(bool dim) {
|
|
if (dim != _dimPalette) {
|
|
_dimPalette = dim;
|
|
setSystemPalette(_palette, 0, 256);
|
|
setNeedFullRedraw();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fades the palette up from black to the current palette.
|
|
* @param time the time it will take the palette to fade up
|
|
*/
|
|
|
|
int32 Screen::fadeUp(float time) {
|
|
if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
|
|
return RDERR_FADEINCOMPLETE;
|
|
|
|
_fadeTotalTime = (int32)(time * 1000);
|
|
_fadeStatus = RDFADE_UP;
|
|
_fadeStartTime = getTick();
|
|
|
|
return RD_OK;
|
|
}
|
|
|
|
/**
|
|
* Fades the palette down to black from the current palette.
|
|
* @param time the time it will take the palette to fade down
|
|
*/
|
|
|
|
int32 Screen::fadeDown(float time) {
|
|
if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
|
|
return RDERR_FADEINCOMPLETE;
|
|
|
|
_fadeTotalTime = (int32)(time * 1000);
|
|
_fadeStatus = RDFADE_DOWN;
|
|
_fadeStartTime = getTick();
|
|
|
|
return RD_OK;
|
|
}
|
|
|
|
/**
|
|
* Get the current fade status
|
|
* @return RDFADE_UP (fading up), RDFADE_DOWN (fading down), RDFADE_NONE
|
|
* (not faded), or RDFADE_BLACK (completely faded down)
|
|
*/
|
|
|
|
uint8 Screen::getFadeStatus() {
|
|
return _fadeStatus;
|
|
}
|
|
|
|
void Screen::waitForFade() {
|
|
while (getFadeStatus() != RDFADE_NONE && getFadeStatus() != RDFADE_BLACK && !_vm->shouldQuit()) {
|
|
updateDisplay();
|
|
_vm->_system->delayMillis(20);
|
|
}
|
|
}
|
|
|
|
void Screen::fadeServer() {
|
|
static int32 previousTime = 0;
|
|
byte fadePalette[256 * 4];
|
|
byte *newPalette = fadePalette;
|
|
int32 currentTime;
|
|
int16 fadeMultiplier;
|
|
int16 i;
|
|
|
|
// If we're not in the process of fading, do nothing.
|
|
if (getFadeStatus() != RDFADE_UP && getFadeStatus() != RDFADE_DOWN)
|
|
return;
|
|
|
|
// I don't know if this is necessary, but let's limit how often the
|
|
// palette is updated, just to be safe.
|
|
currentTime = getTick();
|
|
if (currentTime - previousTime <= 25)
|
|
return;
|
|
|
|
previousTime = currentTime;
|
|
|
|
if (getFadeStatus() == RDFADE_UP) {
|
|
if (currentTime >= _fadeStartTime + _fadeTotalTime) {
|
|
_fadeStatus = RDFADE_NONE;
|
|
newPalette = _palette;
|
|
} else {
|
|
fadeMultiplier = (int16)(((int32)(currentTime - _fadeStartTime) * 256) / _fadeTotalTime);
|
|
for (i = 0; i < 256; i++) {
|
|
newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
|
|
newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
|
|
newPalette[i * 4 + 2] = (_palette[i * 4 + 2] * fadeMultiplier) >> 8;
|
|
}
|
|
}
|
|
} else {
|
|
if (currentTime >= _fadeStartTime + _fadeTotalTime) {
|
|
_fadeStatus = RDFADE_BLACK;
|
|
memset(newPalette, 0, sizeof(fadePalette));
|
|
} else {
|
|
fadeMultiplier = (int16)(((int32)(_fadeTotalTime - (currentTime - _fadeStartTime)) * 256) / _fadeTotalTime);
|
|
for (i = 0; i < 256; i++) {
|
|
newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
|
|
newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
|
|
newPalette[i * 4 + 2] = (_palette[i * 4 + 2] * fadeMultiplier) >> 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
setSystemPalette(newPalette, 0, 256);
|
|
setNeedFullRedraw();
|
|
}
|
|
|
|
void Screen::setSystemPalette(const byte *colors, uint start, uint num) {
|
|
const byte *palette;
|
|
|
|
if (_dimPalette) {
|
|
byte pal[256 * 4];
|
|
|
|
for (uint i = start * 4; i < 4 * (start + num); i++)
|
|
pal[i] = colors[i] / 2;
|
|
|
|
palette = pal;
|
|
} else
|
|
palette = colors;
|
|
|
|
_vm->_system->setPalette(palette, start, num);
|
|
}
|
|
|
|
} // End of namespace Sword2
|