Merge pull request #77 from lordhoto/indy4amiga
SCUMM: Implement proper Indy4 Amiga palette handling.
This commit is contained in:
commit
064ab0fd62
11 changed files with 481 additions and 93 deletions
|
@ -767,6 +767,13 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
|
|||
_textScreenID = vs->number;
|
||||
}
|
||||
|
||||
// We need to know the virtual screen we draw on for Indy 4 Amiga, since
|
||||
// it selects the palette map according to this. We furthermore can not
|
||||
// use _textScreenID here, since that will cause inventory graphics
|
||||
// glitches.
|
||||
if (_vm->_game.platform == Common::kPlatformAmiga && _vm->_game.id == GID_INDY4)
|
||||
_drawScreen = vs->number;
|
||||
|
||||
printCharIntern(is2byte, _charPtr, _origWidth, _origHeight, _width, _height, vs, ignoreCharsetMask);
|
||||
|
||||
_left += _origWidth;
|
||||
|
@ -917,12 +924,27 @@ void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, co
|
|||
numbits = 8;
|
||||
byte *cmap = _vm->_charsetColorMap;
|
||||
|
||||
// Indy4 Amiga always uses the room or verb palette map to match colors to
|
||||
// the currently setup palette, thus we need to select it over here too.
|
||||
// Done like the original interpreter.
|
||||
byte *amigaMap = 0;
|
||||
if (_vm->_game.platform == Common::kPlatformAmiga && _vm->_game.id == GID_INDY4) {
|
||||
if (_drawScreen == kVerbVirtScreen)
|
||||
amigaMap = _vm->_verbPalette;
|
||||
else
|
||||
amigaMap = _vm->_roomPalette;
|
||||
}
|
||||
|
||||
for (y = 0; y < height && y + drawTop < s.h; y++) {
|
||||
for (x = 0; x < width; x++) {
|
||||
color = (bits >> (8 - bpp)) & 0xFF;
|
||||
|
||||
if (color && y + drawTop >= 0)
|
||||
*dst = cmap[color];
|
||||
if (color && y + drawTop >= 0) {
|
||||
if (amigaMap)
|
||||
*dst = amigaMap[cmap[color]];
|
||||
else
|
||||
*dst = cmap[color];
|
||||
}
|
||||
dst++;
|
||||
bits <<= bpp;
|
||||
numbits -= bpp;
|
||||
|
|
|
@ -119,6 +119,9 @@ protected:
|
|||
int _offsX, _offsY;
|
||||
const byte *_charPtr;
|
||||
|
||||
// On which virtual screen will be drawn right now
|
||||
VirtScreenNumber _drawScreen;
|
||||
|
||||
public:
|
||||
CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
|
||||
|
||||
|
|
|
@ -545,6 +545,13 @@ void ClassicCostumeRenderer::proc3_ami(Codec1 &v1) {
|
|||
oldXpos = v1.x;
|
||||
oldScaleIndexX = _scaleIndexX;
|
||||
|
||||
// Indy4 Amiga always uses the room map to match colors to the currently
|
||||
// setup palette in the actor code in the original, thus we need to do this
|
||||
// mapping over here too.
|
||||
byte *amigaMap = 0;
|
||||
if (_vm->_game.platform == Common::kPlatformAmiga && _vm->_game.id == GID_INDY4)
|
||||
amigaMap = _vm->_roomPalette;
|
||||
|
||||
do {
|
||||
len = *src++;
|
||||
color = len >> v1.shr;
|
||||
|
@ -556,7 +563,10 @@ void ClassicCostumeRenderer::proc3_ami(Codec1 &v1) {
|
|||
masked = (y < 0 || y >= _out.h) || (v1.x < 0 || v1.x >= _out.w) || (v1.mask_ptr && (mask[0] & maskbit));
|
||||
|
||||
if (color && !masked) {
|
||||
*dst = _palette[color];
|
||||
if (amigaMap)
|
||||
*dst = amigaMap[_palette[color]];
|
||||
else
|
||||
*dst = _palette[color];
|
||||
}
|
||||
|
||||
if (_scaleX == 255 || v1.scaletable[_scaleIndexX] < _scaleX) {
|
||||
|
|
|
@ -609,7 +609,16 @@ void ScummEngine_v5::setBuiltinCursor(int idx) {
|
|||
for (i = 0; i < 1024; i++)
|
||||
WRITE_UINT16(_grabbedCursor + i * 2, 0xFF);
|
||||
} else {
|
||||
color = default_cursor_colors[idx];
|
||||
// Indy4 Amiga uses its own color set for the cursor image.
|
||||
// This is patchwork code to make the cursor flash in correct colors.
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
static const uint8 indy4AmigaColors[4] = {
|
||||
252, 252, 253, 254
|
||||
};
|
||||
color = indy4AmigaColors[idx];
|
||||
} else {
|
||||
color = default_cursor_colors[idx];
|
||||
}
|
||||
memset(_grabbedCursor, 0xFF, sizeof(_grabbedCursor));
|
||||
}
|
||||
|
||||
|
|
|
@ -1025,6 +1025,16 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
|
|||
if (rect.left > vs->w)
|
||||
return;
|
||||
|
||||
// Indy4 Amiga always uses the room or verb palette map to match colors to
|
||||
// the currently setup palette, thus we need to select it over here too.
|
||||
// Done like the original interpreter.
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
if (vs->number == kVerbVirtScreen)
|
||||
backColor = _verbPalette[backColor];
|
||||
else
|
||||
backColor = _roomPalette[backColor];
|
||||
}
|
||||
|
||||
// Convert 'rect' to local (virtual screen) coordinates
|
||||
rect.top -= vs->topline;
|
||||
rect.bottom -= vs->topline;
|
||||
|
@ -1235,6 +1245,16 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
|
|||
if ((vs = findVirtScreen(y)) == NULL)
|
||||
return;
|
||||
|
||||
// Indy4 Amiga always uses the room or verb palette map to match colors to
|
||||
// the currently setup palette, thus we need to select it over here too.
|
||||
// Done like the original interpreter.
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
if (vs->number == kVerbVirtScreen)
|
||||
color = _verbPalette[color];
|
||||
else
|
||||
color = _roomPalette[color];
|
||||
}
|
||||
|
||||
if (x > x2)
|
||||
SWAP(x, x2);
|
||||
|
||||
|
@ -1872,6 +1892,16 @@ bool Gdi::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width,
|
|||
}
|
||||
assertRange(0, offset, smapLen-1, "screen strip");
|
||||
|
||||
// Indy4 Amiga always uses the room or verb palette map to match colors to
|
||||
// the currently setup palette, thus we need to select it over here too.
|
||||
// Done like the original interpreter.
|
||||
if (_vm->_game.platform == Common::kPlatformAmiga && _vm->_game.id == GID_INDY4) {
|
||||
if (vs->number == kVerbVirtScreen)
|
||||
_roomPalette = _vm->_verbPalette;
|
||||
else
|
||||
_roomPalette = _vm->_roomPalette;
|
||||
}
|
||||
|
||||
return decompressBitmap(dstPtr, vs->pitch, smap_ptr + offset, height);
|
||||
}
|
||||
|
||||
|
|
|
@ -372,6 +372,140 @@ void ScummEngine::setPaletteFromPtr(const byte *ptr, int numcolor) {
|
|||
setDirtyColors(firstIndex, numcolor - 1);
|
||||
}
|
||||
|
||||
void ScummEngine::setAmigaPaletteFromPtr(const byte *ptr) {
|
||||
memcpy(_currentPalette, ptr, 768);
|
||||
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
_shadowPalette[i] = i;
|
||||
_colorUsedByCycle[i] = 0;
|
||||
}
|
||||
|
||||
_amigaFirstUsedColor = 80;
|
||||
for (; _amigaFirstUsedColor < 256; ++_amigaFirstUsedColor) {
|
||||
// We look for the first used color here. If all color components are
|
||||
// >= 252 the color seems to be unused. Check remapPaletteColor for
|
||||
// the same behavior.
|
||||
if (ptr[_amigaFirstUsedColor * 3 + 0] <= 251
|
||||
|| ptr[_amigaFirstUsedColor * 3 + 1] <= 251
|
||||
|| ptr[_amigaFirstUsedColor * 3 + 2] <= 251)
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
_amigaPalette[i * 3 + 0] = _currentPalette[(i + 16) * 3 + 0] >> 4;
|
||||
_amigaPalette[i * 3 + 1] = _currentPalette[(i + 16) * 3 + 1] >> 4;
|
||||
_amigaPalette[i * 3 + 2] = _currentPalette[(i + 16) * 3 + 2] >> 4;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
if (i < 16 || i >= _amigaFirstUsedColor) {
|
||||
mapRoomPalette(i);
|
||||
mapVerbPalette(i);
|
||||
} else {
|
||||
int idx = (i - 16) & 31;
|
||||
// We adjust our verb palette map from [0, 31] to [32, 63], since unlike
|
||||
// the original we set up the verb palette at colors [32, 63].
|
||||
// The original instead used two different palettes for the verb virtual
|
||||
// screen and all the rest.
|
||||
if (idx != 17) {
|
||||
_roomPalette[i] = idx;
|
||||
_verbPalette[i] = idx + 32;
|
||||
} else {
|
||||
// In all my tests it seems the colors 0 and 32 in
|
||||
// _amigaPalette are in fact black. Thus 17 is probably black.
|
||||
// For the room map the color 17 is 33 (17+16), for the verb
|
||||
// map it is 65 (17+32).
|
||||
_roomPalette[i] = 0;
|
||||
_verbPalette[i] = 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDirtyColors(0, 255);
|
||||
}
|
||||
|
||||
void ScummEngine::mapRoomPalette(int idx) {
|
||||
// For Color 33 (which is in fact 17+16) see the special case in
|
||||
// setAmigaPaletteFromPtr.
|
||||
if (idx >= 16 && idx < 48 && idx != 33)
|
||||
_roomPalette[idx] = idx - 16;
|
||||
else
|
||||
_roomPalette[idx] = remapRoomPaletteColor(_currentPalette[idx * 3 + 0] >> 4,
|
||||
_currentPalette[idx * 3 + 1] >> 4,
|
||||
_currentPalette[idx * 3 + 2] >> 4);
|
||||
}
|
||||
|
||||
static const uint8 amigaWeightTable[16] = {
|
||||
0, 1, 4, 9, 16, 25, 36, 49,
|
||||
64, 81, 100, 121, 144, 169, 196, 225
|
||||
};
|
||||
|
||||
int ScummEngine::remapRoomPaletteColor(int r, int g, int b) {
|
||||
int idx = 0;
|
||||
uint16 minValue = 0xFFFF;
|
||||
|
||||
const byte *pal = _amigaPalette;
|
||||
const byte *cycle = _colorUsedByCycle;
|
||||
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
if (!*cycle++ && i != 17) {
|
||||
int rD = ABS<int>(*pal++ - r);
|
||||
int gD = ABS<int>(*pal++ - g);
|
||||
int bD = ABS<int>(*pal++ - b);
|
||||
|
||||
const uint16 weight = amigaWeightTable[rD] + amigaWeightTable[gD] + amigaWeightTable[bD];
|
||||
if (weight < minValue) {
|
||||
minValue = weight;
|
||||
idx = i;
|
||||
}
|
||||
} else {
|
||||
pal += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void ScummEngine::mapVerbPalette(int idx) {
|
||||
// We adjust our verb palette map from [0, 31] to [32, 63], since unlike
|
||||
// the original we set up the verb palette at colors [32, 63].
|
||||
// The original instead used two different palettes for the verb virtual
|
||||
// screen and all the rest.
|
||||
// For Color 65 (which is in fact 17+32) see the special case in
|
||||
// setAmigaPaletteFromPtr.
|
||||
if (idx >= 48 && idx < 80 && idx != 65)
|
||||
_verbPalette[idx] = idx - 16;
|
||||
else
|
||||
_verbPalette[idx] = remapVerbPaletteColor(_currentPalette[idx * 3 + 0] >> 4,
|
||||
_currentPalette[idx * 3 + 1] >> 4,
|
||||
_currentPalette[idx * 3 + 2] >> 4) + 32;
|
||||
}
|
||||
|
||||
int ScummEngine::remapVerbPaletteColor(int r, int g, int b) {
|
||||
int idx = 0;
|
||||
uint16 minValue = 0xFFFF;
|
||||
|
||||
const byte *pal = _amigaPalette + 32 * 3;
|
||||
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
if (i != 17) {
|
||||
int rD = ABS<int>(*pal++ - r);
|
||||
int gD = ABS<int>(*pal++ - g);
|
||||
int bD = ABS<int>(*pal++ - b);
|
||||
|
||||
const uint16 weight = amigaWeightTable[rD] + amigaWeightTable[gD] + amigaWeightTable[bD];
|
||||
if (weight < minValue) {
|
||||
minValue = weight;
|
||||
idx = i;
|
||||
}
|
||||
} else {
|
||||
pal += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void ScummEngine::setDirtyColors(int min, int max) {
|
||||
if (_palDirtyMin > min)
|
||||
_palDirtyMin = min;
|
||||
|
@ -419,11 +553,26 @@ void ScummEngine::initCycl(const byte *ptr) {
|
|||
cycl->start = *ptr++;
|
||||
cycl->end = *ptr++;
|
||||
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
cycl->start = CLIP(cycl->start - 16, 0, 31);
|
||||
cycl->end = CLIP(cycl->end - 16, 0, 31);
|
||||
}
|
||||
|
||||
for (int i = cycl->start; i <= cycl->end; ++i) {
|
||||
_colorUsedByCycle[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
if (i >= 16 && i < _amigaFirstUsedColor)
|
||||
continue;
|
||||
|
||||
if (_colorUsedByCycle[_roomPalette[i]])
|
||||
mapRoomPalette(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScummEngine::stopCycle(int i) {
|
||||
|
@ -432,11 +581,23 @@ void ScummEngine::stopCycle(int i) {
|
|||
assertRange(0, i, 16, "stopCycle: cycle");
|
||||
if (i != 0) {
|
||||
_colorCycle[i - 1].delay = 0;
|
||||
cycl = &_colorCycle[i - 1];
|
||||
for (int j = cycl->start; j <= cycl->end && j < 32; ++j) {
|
||||
_shadowPalette[j] = j;
|
||||
_colorUsedByCycle[j] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, cycl = _colorCycle; i < 16; i++, cycl++)
|
||||
for (i = 0, cycl = _colorCycle; i < 16; i++, cycl++) {
|
||||
cycl->delay = 0;
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
for (int j = cycl->start; j <= cycl->end && j < 32; ++j) {
|
||||
_shadowPalette[j] = j;
|
||||
_colorUsedByCycle[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -512,14 +673,18 @@ void ScummEngine::cyclePalette() {
|
|||
setDirtyColors(cycl->start, cycl->end);
|
||||
moveMemInPalRes(cycl->start, cycl->end, cycl->flags & 2);
|
||||
|
||||
doCyclePalette(_currentPalette, cycl->start, cycl->end, 3, !(cycl->flags & 2));
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
doCyclePalette(_shadowPalette, cycl->start, cycl->end, 1, !(cycl->flags & 2));
|
||||
} else {
|
||||
doCyclePalette(_currentPalette, cycl->start, cycl->end, 3, !(cycl->flags & 2));
|
||||
|
||||
if (_shadowPalette) {
|
||||
if (_game.version >= 7) {
|
||||
for (j = 0; j < NUM_SHADOW_PALETTE; j++)
|
||||
if (_shadowPalette) {
|
||||
if (_game.version >= 7) {
|
||||
for (j = 0; j < NUM_SHADOW_PALETTE; j++)
|
||||
doCycleIndirectPalette(_shadowPalette + j * 256, cycl->start, cycl->end, !(cycl->flags & 2));
|
||||
} else {
|
||||
doCycleIndirectPalette(_shadowPalette, cycl->start, cycl->end, !(cycl->flags & 2));
|
||||
} else {
|
||||
doCycleIndirectPalette(_shadowPalette, cycl->start, cycl->end, !(cycl->flags & 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -733,62 +898,106 @@ void ScummEngine::setShadowPalette(int redScale, int greenScale, int blueScale,
|
|||
}
|
||||
|
||||
void ScummEngine::darkenPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor) {
|
||||
int max;
|
||||
if (_game.version >= 5 && _game.version <= 6 && _game.heversion <= 60) {
|
||||
max = 252;
|
||||
} else {
|
||||
max = 255;
|
||||
}
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
startColor = CLIP(startColor, 0, 255);
|
||||
|
||||
if (startColor <= endColor) {
|
||||
const byte *cptr;
|
||||
const byte *palptr;
|
||||
int color, idx, j;
|
||||
//bool remappedVerbColors = false;
|
||||
bool remappedRoomColors = false;
|
||||
bool cycleFlag = (blueScale >= 250 && greenScale >= 250 && redScale >= 250);
|
||||
|
||||
if (_game.heversion >= 90 || _game.version == 8) {
|
||||
palptr = _darkenPalette;
|
||||
} else {
|
||||
palptr = getPalettePtr(_curPalIndex, _roomResource);
|
||||
}
|
||||
for (j = startColor; j <= endColor; j++) {
|
||||
idx = (_game.heversion == 70) ? _HEV7ActorPalette[j] : j;
|
||||
cptr = palptr + idx * 3;
|
||||
const byte *palptr = getPalettePtr(_curPalIndex, _roomResource) + startColor * 3;
|
||||
|
||||
if (_game.heversion == 70)
|
||||
setDirtyColors(idx, idx);
|
||||
|
||||
// Original FOA Amiga version skips these colors
|
||||
// Fixes bug #1206994: "FOA AMIGA: Black cursor and text in Dig Site"
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
if (j < 16) {
|
||||
cptr += 3;
|
||||
continue;
|
||||
}
|
||||
for (int i = startColor; i <= endColor; ++i) {
|
||||
if (i >= 16 && i < 48) {
|
||||
if (cycleFlag)
|
||||
_colorUsedByCycle[i - 16] &= ~2;
|
||||
else
|
||||
_colorUsedByCycle[i - 16] |= 2;
|
||||
}
|
||||
|
||||
color = *cptr++;
|
||||
color = color * redScale / 0xFF;
|
||||
if (color > max)
|
||||
color = max;
|
||||
_currentPalette[idx * 3 + 0] = color;
|
||||
|
||||
color = *cptr++;
|
||||
color = color * greenScale / 0xFF;
|
||||
if (color > max)
|
||||
color = max;
|
||||
_currentPalette[idx * 3 + 1] = color;
|
||||
|
||||
color = *cptr++;
|
||||
color = color * blueScale / 0xFF;
|
||||
if (color > max)
|
||||
color = max;
|
||||
_currentPalette[idx * 3 + 2] = color;
|
||||
|
||||
if (_game.features & GF_16BIT_COLOR)
|
||||
_16BitPalette[idx] = get16BitColor(_currentPalette[idx * 3 + 0], _currentPalette[idx * 3 + 1], _currentPalette[idx * 3 + 2]);
|
||||
_currentPalette[i * 3 + 0] = (*palptr++ * redScale) >> 8;
|
||||
_currentPalette[i * 3 + 1] = (*palptr++ * greenScale) >> 8;
|
||||
_currentPalette[i * 3 + 2] = (*palptr++ * blueScale) >> 8;
|
||||
}
|
||||
|
||||
for (int i = startColor; i <= endColor; ++i) {
|
||||
// Colors 33 (17+16) and 65 (17+32) will never get changed. For
|
||||
// more information about these check setAmigaPaletteFromPtr.
|
||||
if (i >= 16 && i < 48 && i != 33) {
|
||||
remappedRoomColors = true;
|
||||
_amigaPalette[(i - 16) * 3 + 0] = _currentPalette[i * 3 + 0] >> 4;
|
||||
_amigaPalette[(i - 16) * 3 + 1] = _currentPalette[i * 3 + 1] >> 4;
|
||||
_amigaPalette[(i - 16) * 3 + 2] = _currentPalette[i * 3 + 2] >> 4;
|
||||
} else if (i >= 48 && i < 80 && i != 65) {
|
||||
//remappedVerbColors = true;
|
||||
_amigaPalette[(i - 16) * 3 + 0] = _currentPalette[i * 3 + 0] >> 4;
|
||||
_amigaPalette[(i - 16) * 3 + 1] = _currentPalette[i * 3 + 1] >> 4;
|
||||
_amigaPalette[(i - 16) * 3 + 2] = _currentPalette[i * 3 + 2] >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
if (i >= 16 && i < _amigaFirstUsedColor)
|
||||
continue;
|
||||
|
||||
bool inRange = (startColor <= i && i <= endColor);
|
||||
int idx = _roomPalette[i] + 16;
|
||||
bool mappedInRange = (startColor <= idx && idx <= endColor);
|
||||
|
||||
if (inRange != mappedInRange || (remappedRoomColors && cycleFlag))
|
||||
mapRoomPalette(i);
|
||||
}
|
||||
|
||||
setDirtyColors(startColor, endColor);
|
||||
} else {
|
||||
int max;
|
||||
if (_game.version >= 5 && _game.version <= 6 && _game.heversion <= 60) {
|
||||
max = 252;
|
||||
} else {
|
||||
max = 255;
|
||||
}
|
||||
|
||||
if (startColor <= endColor) {
|
||||
const byte *cptr;
|
||||
const byte *palptr;
|
||||
int color, idx, j;
|
||||
|
||||
if (_game.heversion >= 90 || _game.version == 8) {
|
||||
palptr = _darkenPalette;
|
||||
} else {
|
||||
palptr = getPalettePtr(_curPalIndex, _roomResource);
|
||||
}
|
||||
for (j = startColor; j <= endColor; j++) {
|
||||
idx = (_game.heversion == 70) ? _HEV7ActorPalette[j] : j;
|
||||
cptr = palptr + idx * 3;
|
||||
|
||||
if (_game.heversion == 70)
|
||||
setDirtyColors(idx, idx);
|
||||
|
||||
color = *cptr++;
|
||||
color = color * redScale / 0xFF;
|
||||
if (color > max)
|
||||
color = max;
|
||||
_currentPalette[idx * 3 + 0] = color;
|
||||
|
||||
color = *cptr++;
|
||||
color = color * greenScale / 0xFF;
|
||||
if (color > max)
|
||||
color = max;
|
||||
_currentPalette[idx * 3 + 1] = color;
|
||||
|
||||
color = *cptr++;
|
||||
color = color * blueScale / 0xFF;
|
||||
if (color > max)
|
||||
color = max;
|
||||
_currentPalette[idx * 3 + 2] = color;
|
||||
|
||||
if (_game.features & GF_16BIT_COLOR)
|
||||
_16BitPalette[idx] = get16BitColor(_currentPalette[idx * 3 + 0], _currentPalette[idx * 3 + 1], _currentPalette[idx * 3 + 2]);
|
||||
}
|
||||
if (_game.heversion != 70)
|
||||
setDirtyColors(startColor, endColor);
|
||||
}
|
||||
if (_game.heversion != 70)
|
||||
setDirtyColors(startColor, endColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1007,6 +1216,41 @@ void ScummEngine::setPalColor(int idx, int r, int g, int b) {
|
|||
_darkenPalette[idx * 3 + 2] = b;
|
||||
}
|
||||
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
// Colors 33 (17+16) and 65 (17+32) will never get changed. For
|
||||
// more information about these check setAmigaPaletteFromPtr.
|
||||
if (idx < 16 || idx >= _amigaFirstUsedColor) {
|
||||
mapRoomPalette(idx);
|
||||
mapVerbPalette(idx);
|
||||
} else if (idx >= 16 && idx < 48 && idx != 33) {
|
||||
_amigaPalette[(idx - 16) * 3 + 0] = _currentPalette[idx * 3 + 0] >> 4;
|
||||
_amigaPalette[(idx - 16) * 3 + 1] = _currentPalette[idx * 3 + 1] >> 4;
|
||||
_amigaPalette[(idx - 16) * 3 + 2] = _currentPalette[idx * 3 + 2] >> 4;
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
if (i >= 16 && i < _amigaFirstUsedColor)
|
||||
continue;
|
||||
|
||||
if (idx - 16 == _roomPalette[i])
|
||||
mapRoomPalette(i);
|
||||
}
|
||||
} else if (idx >= 48 && idx < 80 && idx != 65) {
|
||||
_amigaPalette[(idx - 16) * 3 + 0] = _currentPalette[idx * 3 + 0] >> 4;
|
||||
_amigaPalette[(idx - 16) * 3 + 1] = _currentPalette[idx * 3 + 1] >> 4;
|
||||
_amigaPalette[(idx - 16) * 3 + 2] = _currentPalette[idx * 3 + 2] >> 4;
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
if (i >= 16 && i < _amigaFirstUsedColor)
|
||||
continue;
|
||||
|
||||
// We do - 16 instead of - 48 like the original, since our
|
||||
// verb palette map is using [32, 63] instead of [0, 31].
|
||||
if (idx - 16 == _verbPalette[i])
|
||||
mapVerbPalette(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_game.features & GF_16BIT_COLOR)
|
||||
_16BitPalette[idx] = get16BitColor(r, g, b);
|
||||
|
||||
|
@ -1026,6 +1270,8 @@ void ScummEngine::setCurrentPalette(int palindex) {
|
|||
towns_setPaletteFromPtr(pals);
|
||||
#endif
|
||||
#endif
|
||||
} else if (_game.id == GID_INDY4 && _game.platform == Common::kPlatformAmiga) {
|
||||
setAmigaPaletteFromPtr(pals);
|
||||
} else {
|
||||
setPaletteFromPtr(pals);
|
||||
}
|
||||
|
@ -1081,42 +1327,74 @@ void ScummEngine::updatePalette() {
|
|||
if (_palDirtyMax == -1)
|
||||
return;
|
||||
|
||||
bool noir_mode = (_game.id == GID_SAMNMAX && readVar(0x8000));
|
||||
int first = _palDirtyMin;
|
||||
int num = _palDirtyMax - first + 1;
|
||||
int i;
|
||||
|
||||
byte palette_colors[3 * 256];
|
||||
byte *p = palette_colors;
|
||||
int first;
|
||||
int num;
|
||||
|
||||
for (i = _palDirtyMin; i <= _palDirtyMax; i++) {
|
||||
byte *data;
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
// Indy4 Amiga has a special palette handling scheme
|
||||
first = 0;
|
||||
num = 64;
|
||||
|
||||
if (_game.features & GF_SMALL_HEADER && _game.version > 2)
|
||||
data = _currentPalette + _shadowPalette[i] * 3;
|
||||
else
|
||||
data = _currentPalette + i * 3;
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
byte *data;
|
||||
|
||||
// Sam & Max film noir mode. Convert the colors to grayscale
|
||||
// before uploading them to the backend.
|
||||
if (i < 32)
|
||||
data = _amigaPalette + _shadowPalette[i] * 3;
|
||||
else
|
||||
data = _amigaPalette + i * 3;
|
||||
|
||||
if (noir_mode) {
|
||||
int r, g, b;
|
||||
byte brightness;
|
||||
*p++ = data[0] * 255 / 15;
|
||||
*p++ = data[1] * 255 / 15;
|
||||
*p++ = data[2] * 255 / 15;
|
||||
}
|
||||
|
||||
r = data[0];
|
||||
g = data[1];
|
||||
b = data[2];
|
||||
// Setup colors for the mouse cursor
|
||||
// Color values taken from Indy4 DOS
|
||||
static const uint8 mouseCursorPalette[] = {
|
||||
255, 255, 255,
|
||||
171, 171, 171,
|
||||
87, 87, 87
|
||||
};
|
||||
|
||||
brightness = (byte)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5);
|
||||
_system->getPaletteManager()->setPalette(mouseCursorPalette, 252, 3);
|
||||
} else {
|
||||
bool noir_mode = (_game.id == GID_SAMNMAX && readVar(0x8000));
|
||||
int i;
|
||||
|
||||
*p++ = brightness;
|
||||
*p++ = brightness;
|
||||
*p++ = brightness;
|
||||
} else {
|
||||
*p++ = data[0];
|
||||
*p++ = data[1];
|
||||
*p++ = data[2];
|
||||
first = _palDirtyMin;
|
||||
num = _palDirtyMax - first + 1;
|
||||
|
||||
for (i = _palDirtyMin; i <= _palDirtyMax; i++) {
|
||||
byte *data;
|
||||
|
||||
if (_game.features & GF_SMALL_HEADER && _game.version > 2)
|
||||
data = _currentPalette + _shadowPalette[i] * 3;
|
||||
else
|
||||
data = _currentPalette + i * 3;
|
||||
|
||||
// Sam & Max film noir mode. Convert the colors to grayscale
|
||||
// before uploading them to the backend.
|
||||
|
||||
if (noir_mode) {
|
||||
int r, g, b;
|
||||
byte brightness;
|
||||
|
||||
r = data[0];
|
||||
g = data[1];
|
||||
b = data[2];
|
||||
|
||||
brightness = (byte)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5);
|
||||
|
||||
*p++ = brightness;
|
||||
*p++ = brightness;
|
||||
*p++ = brightness;
|
||||
} else {
|
||||
*p++ = data[0];
|
||||
*p++ = data[1];
|
||||
*p++ = data[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1127,7 +1405,7 @@ void ScummEngine::updatePalette() {
|
|||
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
||||
if (_game.platform == Common::kPlatformFMTowns) {
|
||||
p = palette_colors;
|
||||
for (i = first; i < first + num; ++i) {
|
||||
for (int i = first; i < first + num; ++i) {
|
||||
_16BitPalette[i] = get16BitColor(p[0], p[1], p[2]);
|
||||
p += 3;
|
||||
}
|
||||
|
|
|
@ -552,6 +552,10 @@ void ScummEngine::resetRoomSubBlocks() {
|
|||
}
|
||||
}
|
||||
|
||||
// We need to setup the current palette before initCycl for Indy4 Amiga.
|
||||
if (_PALS_offs || _CLUT_offs)
|
||||
setCurrentPalette(0);
|
||||
|
||||
// Color cycling
|
||||
// HE 7.0 games load resources but don't use them.
|
||||
if (_game.version >= 4 && _game.heversion <= 62) {
|
||||
|
@ -570,9 +574,6 @@ void ScummEngine::resetRoomSubBlocks() {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_PALS_offs || _CLUT_offs)
|
||||
setCurrentPalette(0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1322,6 +1322,9 @@ void ScummEngine::saveOrLoad(Serializer *s) {
|
|||
if (_shadowPaletteSize) {
|
||||
s->saveLoadArrayOf(_shadowPalette, _shadowPaletteSize, 1, sleByte);
|
||||
// _roomPalette didn't show up until V21 save games
|
||||
// Note that we also save the room palette for Indy4 Amiga, since it
|
||||
// is used as palette map there too, but we do so slightly a bit
|
||||
// further down to group it with the other special palettes needed.
|
||||
if (s->getVersion() >= VER(21) && _game.version < 5)
|
||||
s->saveLoadArrayOf(_roomPalette, sizeof(_roomPalette), 1, sleByte);
|
||||
}
|
||||
|
@ -1348,6 +1351,20 @@ void ScummEngine::saveOrLoad(Serializer *s) {
|
|||
memset(_colorUsedByCycle, 0, sizeof(_colorUsedByCycle));
|
||||
}
|
||||
|
||||
// Indy4 Amiga specific palette tables were not saved before V85
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||
if (s->getVersion() >= 85) {
|
||||
s->saveLoadArrayOf(_roomPalette, 256, 1, sleByte);
|
||||
s->saveLoadArrayOf(_verbPalette, 256, 1, sleByte);
|
||||
s->saveLoadArrayOf(_amigaPalette, 3 * 64, 1, sleByte);
|
||||
} else {
|
||||
warning("Save with old Indiana Jones 4 Amiga palette handling detected");
|
||||
// We need to restore the internal state of the Amiga palette for Indy4
|
||||
// Amiga. This might lead to graphics glitches!
|
||||
setAmigaPaletteFromPtr(_currentPalette);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Save/load more global object state
|
||||
//
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace Scumm {
|
|||
* only saves/loads those which are valid for the version of the savegame
|
||||
* which is being loaded/saved currently.
|
||||
*/
|
||||
#define CURRENT_VER 84
|
||||
#define CURRENT_VER 85
|
||||
|
||||
/**
|
||||
* An auxillary macro, used to specify savegame versions. We use this instead
|
||||
|
|
|
@ -290,6 +290,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
|
|||
#endif
|
||||
_shadowPalette = NULL;
|
||||
_shadowPaletteSize = 0;
|
||||
_verbPalette = NULL;
|
||||
memset(_currentPalette, 0, sizeof(_currentPalette));
|
||||
memset(_darkenPalette, 0, sizeof(_darkenPalette));
|
||||
memset(_HEV7ActorPalette, 0, sizeof(_HEV7ActorPalette));
|
||||
|
@ -610,6 +611,7 @@ ScummEngine::~ScummEngine() {
|
|||
_textSurface.free();
|
||||
|
||||
free(_shadowPalette);
|
||||
free(_verbPalette);
|
||||
|
||||
free(_palManipPalette);
|
||||
free(_palManipIntermediatePal);
|
||||
|
@ -1408,6 +1410,10 @@ void ScummEngine::resetScumm() {
|
|||
_16BitPalette = (uint16 *)calloc(512, sizeof(uint16));
|
||||
#endif
|
||||
|
||||
// Indy4 Amiga needs another palette map for the verb area.
|
||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4 && !_verbPalette)
|
||||
_verbPalette = (uint8 *)calloc(256, 1);
|
||||
|
||||
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
||||
if (_game.platform == Common::kPlatformFMTowns) {
|
||||
delete _townsScreen;
|
||||
|
|
|
@ -970,6 +970,7 @@ protected:
|
|||
void setCurrentPalette(int pal);
|
||||
void setRoomPalette(int pal, int room);
|
||||
void setPCEPaletteFromPtr(const byte *ptr);
|
||||
void setAmigaPaletteFromPtr(const byte *ptr);
|
||||
virtual void setPaletteFromPtr(const byte *ptr, int numcolor = -1);
|
||||
|
||||
virtual void setPalColor(int index, int r, int g, int b);
|
||||
|
@ -1065,6 +1066,9 @@ public:
|
|||
uint16 _hePaletteSlot;
|
||||
uint16 *_16BitPalette;
|
||||
|
||||
// Indy4 Amiga specific
|
||||
byte *_verbPalette;
|
||||
|
||||
protected:
|
||||
int _shadowPaletteSize;
|
||||
byte _currentPalette[3 * 256];
|
||||
|
@ -1085,6 +1089,14 @@ protected:
|
|||
bool _enable_gs;
|
||||
bool _copyProtection;
|
||||
|
||||
// Indy4 Amiga specific
|
||||
uint16 _amigaFirstUsedColor;
|
||||
byte _amigaPalette[3 * 64];
|
||||
void mapRoomPalette(int idx);
|
||||
int remapRoomPaletteColor(int r, int g, int b);
|
||||
void mapVerbPalette(int idx);
|
||||
int remapVerbPaletteColor(int r, int g, int b);
|
||||
|
||||
public:
|
||||
uint16 _extraBoxFlags[65];
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue