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;
|
_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);
|
printCharIntern(is2byte, _charPtr, _origWidth, _origHeight, _width, _height, vs, ignoreCharsetMask);
|
||||||
|
|
||||||
_left += _origWidth;
|
_left += _origWidth;
|
||||||
|
@ -917,12 +924,27 @@ void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, co
|
||||||
numbits = 8;
|
numbits = 8;
|
||||||
byte *cmap = _vm->_charsetColorMap;
|
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 (y = 0; y < height && y + drawTop < s.h; y++) {
|
||||||
for (x = 0; x < width; x++) {
|
for (x = 0; x < width; x++) {
|
||||||
color = (bits >> (8 - bpp)) & 0xFF;
|
color = (bits >> (8 - bpp)) & 0xFF;
|
||||||
|
|
||||||
if (color && y + drawTop >= 0)
|
if (color && y + drawTop >= 0) {
|
||||||
*dst = cmap[color];
|
if (amigaMap)
|
||||||
|
*dst = amigaMap[cmap[color]];
|
||||||
|
else
|
||||||
|
*dst = cmap[color];
|
||||||
|
}
|
||||||
dst++;
|
dst++;
|
||||||
bits <<= bpp;
|
bits <<= bpp;
|
||||||
numbits -= bpp;
|
numbits -= bpp;
|
||||||
|
|
|
@ -119,6 +119,9 @@ protected:
|
||||||
int _offsX, _offsY;
|
int _offsX, _offsY;
|
||||||
const byte *_charPtr;
|
const byte *_charPtr;
|
||||||
|
|
||||||
|
// On which virtual screen will be drawn right now
|
||||||
|
VirtScreenNumber _drawScreen;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
|
CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
|
||||||
|
|
||||||
|
|
|
@ -545,6 +545,13 @@ void ClassicCostumeRenderer::proc3_ami(Codec1 &v1) {
|
||||||
oldXpos = v1.x;
|
oldXpos = v1.x;
|
||||||
oldScaleIndexX = _scaleIndexX;
|
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 {
|
do {
|
||||||
len = *src++;
|
len = *src++;
|
||||||
color = len >> v1.shr;
|
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));
|
masked = (y < 0 || y >= _out.h) || (v1.x < 0 || v1.x >= _out.w) || (v1.mask_ptr && (mask[0] & maskbit));
|
||||||
|
|
||||||
if (color && !masked) {
|
if (color && !masked) {
|
||||||
*dst = _palette[color];
|
if (amigaMap)
|
||||||
|
*dst = amigaMap[_palette[color]];
|
||||||
|
else
|
||||||
|
*dst = _palette[color];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_scaleX == 255 || v1.scaletable[_scaleIndexX] < _scaleX) {
|
if (_scaleX == 255 || v1.scaletable[_scaleIndexX] < _scaleX) {
|
||||||
|
|
|
@ -609,7 +609,16 @@ void ScummEngine_v5::setBuiltinCursor(int idx) {
|
||||||
for (i = 0; i < 1024; i++)
|
for (i = 0; i < 1024; i++)
|
||||||
WRITE_UINT16(_grabbedCursor + i * 2, 0xFF);
|
WRITE_UINT16(_grabbedCursor + i * 2, 0xFF);
|
||||||
} else {
|
} 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));
|
memset(_grabbedCursor, 0xFF, sizeof(_grabbedCursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1025,6 +1025,16 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
|
||||||
if (rect.left > vs->w)
|
if (rect.left > vs->w)
|
||||||
return;
|
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
|
// Convert 'rect' to local (virtual screen) coordinates
|
||||||
rect.top -= vs->topline;
|
rect.top -= vs->topline;
|
||||||
rect.bottom -= 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)
|
if ((vs = findVirtScreen(y)) == NULL)
|
||||||
return;
|
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)
|
if (x > x2)
|
||||||
SWAP(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");
|
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);
|
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);
|
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) {
|
void ScummEngine::setDirtyColors(int min, int max) {
|
||||||
if (_palDirtyMin > min)
|
if (_palDirtyMin > min)
|
||||||
_palDirtyMin = min;
|
_palDirtyMin = min;
|
||||||
|
@ -419,11 +553,26 @@ void ScummEngine::initCycl(const byte *ptr) {
|
||||||
cycl->start = *ptr++;
|
cycl->start = *ptr++;
|
||||||
cycl->end = *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) {
|
for (int i = cycl->start; i <= cycl->end; ++i) {
|
||||||
_colorUsedByCycle[i] = 1;
|
_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) {
|
void ScummEngine::stopCycle(int i) {
|
||||||
|
@ -432,11 +581,23 @@ void ScummEngine::stopCycle(int i) {
|
||||||
assertRange(0, i, 16, "stopCycle: cycle");
|
assertRange(0, i, 16, "stopCycle: cycle");
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
_colorCycle[i - 1].delay = 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, cycl = _colorCycle; i < 16; i++, cycl++)
|
for (i = 0, cycl = _colorCycle; i < 16; i++, cycl++) {
|
||||||
cycl->delay = 0;
|
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);
|
setDirtyColors(cycl->start, cycl->end);
|
||||||
moveMemInPalRes(cycl->start, cycl->end, cycl->flags & 2);
|
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 (_shadowPalette) {
|
||||||
if (_game.version >= 7) {
|
if (_game.version >= 7) {
|
||||||
for (j = 0; j < NUM_SHADOW_PALETTE; j++)
|
for (j = 0; j < NUM_SHADOW_PALETTE; j++)
|
||||||
doCycleIndirectPalette(_shadowPalette + j * 256, cycl->start, cycl->end, !(cycl->flags & 2));
|
doCycleIndirectPalette(_shadowPalette + j * 256, cycl->start, cycl->end, !(cycl->flags & 2));
|
||||||
} else {
|
} else {
|
||||||
doCycleIndirectPalette(_shadowPalette, cycl->start, cycl->end, !(cycl->flags & 2));
|
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) {
|
void ScummEngine::darkenPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor) {
|
||||||
int max;
|
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||||
if (_game.version >= 5 && _game.version <= 6 && _game.heversion <= 60) {
|
startColor = CLIP(startColor, 0, 255);
|
||||||
max = 252;
|
|
||||||
} else {
|
|
||||||
max = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startColor <= endColor) {
|
//bool remappedVerbColors = false;
|
||||||
const byte *cptr;
|
bool remappedRoomColors = false;
|
||||||
const byte *palptr;
|
bool cycleFlag = (blueScale >= 250 && greenScale >= 250 && redScale >= 250);
|
||||||
int color, idx, j;
|
|
||||||
|
|
||||||
if (_game.heversion >= 90 || _game.version == 8) {
|
const byte *palptr = getPalettePtr(_curPalIndex, _roomResource) + startColor * 3;
|
||||||
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)
|
for (int i = startColor; i <= endColor; ++i) {
|
||||||
setDirtyColors(idx, idx);
|
if (i >= 16 && i < 48) {
|
||||||
|
if (cycleFlag)
|
||||||
// Original FOA Amiga version skips these colors
|
_colorUsedByCycle[i - 16] &= ~2;
|
||||||
// Fixes bug #1206994: "FOA AMIGA: Black cursor and text in Dig Site"
|
else
|
||||||
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
_colorUsedByCycle[i - 16] |= 2;
|
||||||
if (j < 16) {
|
|
||||||
cptr += 3;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
color = *cptr++;
|
_currentPalette[i * 3 + 0] = (*palptr++ * redScale) >> 8;
|
||||||
color = color * redScale / 0xFF;
|
_currentPalette[i * 3 + 1] = (*palptr++ * greenScale) >> 8;
|
||||||
if (color > max)
|
_currentPalette[i * 3 + 2] = (*palptr++ * blueScale) >> 8;
|
||||||
color = max;
|
}
|
||||||
_currentPalette[idx * 3 + 0] = color;
|
|
||||||
|
for (int i = startColor; i <= endColor; ++i) {
|
||||||
color = *cptr++;
|
// Colors 33 (17+16) and 65 (17+32) will never get changed. For
|
||||||
color = color * greenScale / 0xFF;
|
// more information about these check setAmigaPaletteFromPtr.
|
||||||
if (color > max)
|
if (i >= 16 && i < 48 && i != 33) {
|
||||||
color = max;
|
remappedRoomColors = true;
|
||||||
_currentPalette[idx * 3 + 1] = color;
|
_amigaPalette[(i - 16) * 3 + 0] = _currentPalette[i * 3 + 0] >> 4;
|
||||||
|
_amigaPalette[(i - 16) * 3 + 1] = _currentPalette[i * 3 + 1] >> 4;
|
||||||
color = *cptr++;
|
_amigaPalette[(i - 16) * 3 + 2] = _currentPalette[i * 3 + 2] >> 4;
|
||||||
color = color * blueScale / 0xFF;
|
} else if (i >= 48 && i < 80 && i != 65) {
|
||||||
if (color > max)
|
//remappedVerbColors = true;
|
||||||
color = max;
|
_amigaPalette[(i - 16) * 3 + 0] = _currentPalette[i * 3 + 0] >> 4;
|
||||||
_currentPalette[idx * 3 + 2] = color;
|
_amigaPalette[(i - 16) * 3 + 1] = _currentPalette[i * 3 + 1] >> 4;
|
||||||
|
_amigaPalette[(i - 16) * 3 + 2] = _currentPalette[i * 3 + 2] >> 4;
|
||||||
if (_game.features & GF_16BIT_COLOR)
|
}
|
||||||
_16BitPalette[idx] = get16BitColor(_currentPalette[idx * 3 + 0], _currentPalette[idx * 3 + 1], _currentPalette[idx * 3 + 2]);
|
}
|
||||||
|
|
||||||
|
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;
|
_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)
|
if (_game.features & GF_16BIT_COLOR)
|
||||||
_16BitPalette[idx] = get16BitColor(r, g, b);
|
_16BitPalette[idx] = get16BitColor(r, g, b);
|
||||||
|
|
||||||
|
@ -1026,6 +1270,8 @@ void ScummEngine::setCurrentPalette(int palindex) {
|
||||||
towns_setPaletteFromPtr(pals);
|
towns_setPaletteFromPtr(pals);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
} else if (_game.id == GID_INDY4 && _game.platform == Common::kPlatformAmiga) {
|
||||||
|
setAmigaPaletteFromPtr(pals);
|
||||||
} else {
|
} else {
|
||||||
setPaletteFromPtr(pals);
|
setPaletteFromPtr(pals);
|
||||||
}
|
}
|
||||||
|
@ -1081,42 +1327,74 @@ void ScummEngine::updatePalette() {
|
||||||
if (_palDirtyMax == -1)
|
if (_palDirtyMax == -1)
|
||||||
return;
|
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 palette_colors[3 * 256];
|
||||||
byte *p = palette_colors;
|
byte *p = palette_colors;
|
||||||
|
int first;
|
||||||
|
int num;
|
||||||
|
|
||||||
for (i = _palDirtyMin; i <= _palDirtyMax; i++) {
|
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
||||||
byte *data;
|
// Indy4 Amiga has a special palette handling scheme
|
||||||
|
first = 0;
|
||||||
|
num = 64;
|
||||||
|
|
||||||
if (_game.features & GF_SMALL_HEADER && _game.version > 2)
|
for (int i = 0; i < 64; ++i) {
|
||||||
data = _currentPalette + _shadowPalette[i] * 3;
|
byte *data;
|
||||||
else
|
|
||||||
data = _currentPalette + i * 3;
|
|
||||||
|
|
||||||
// Sam & Max film noir mode. Convert the colors to grayscale
|
if (i < 32)
|
||||||
// before uploading them to the backend.
|
data = _amigaPalette + _shadowPalette[i] * 3;
|
||||||
|
else
|
||||||
|
data = _amigaPalette + i * 3;
|
||||||
|
|
||||||
if (noir_mode) {
|
*p++ = data[0] * 255 / 15;
|
||||||
int r, g, b;
|
*p++ = data[1] * 255 / 15;
|
||||||
byte brightness;
|
*p++ = data[2] * 255 / 15;
|
||||||
|
}
|
||||||
|
|
||||||
r = data[0];
|
// Setup colors for the mouse cursor
|
||||||
g = data[1];
|
// Color values taken from Indy4 DOS
|
||||||
b = data[2];
|
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;
|
first = _palDirtyMin;
|
||||||
*p++ = brightness;
|
num = _palDirtyMax - first + 1;
|
||||||
*p++ = brightness;
|
|
||||||
} else {
|
for (i = _palDirtyMin; i <= _palDirtyMax; i++) {
|
||||||
*p++ = data[0];
|
byte *data;
|
||||||
*p++ = data[1];
|
|
||||||
*p++ = data[2];
|
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
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
||||||
if (_game.platform == Common::kPlatformFMTowns) {
|
if (_game.platform == Common::kPlatformFMTowns) {
|
||||||
p = palette_colors;
|
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]);
|
_16BitPalette[i] = get16BitColor(p[0], p[1], p[2]);
|
||||||
p += 3;
|
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
|
// Color cycling
|
||||||
// HE 7.0 games load resources but don't use them.
|
// HE 7.0 games load resources but don't use them.
|
||||||
if (_game.version >= 4 && _game.heversion <= 62) {
|
if (_game.version >= 4 && _game.heversion <= 62) {
|
||||||
|
@ -570,9 +574,6 @@ void ScummEngine::resetRoomSubBlocks() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_PALS_offs || _CLUT_offs)
|
|
||||||
setCurrentPalette(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1322,6 +1322,9 @@ void ScummEngine::saveOrLoad(Serializer *s) {
|
||||||
if (_shadowPaletteSize) {
|
if (_shadowPaletteSize) {
|
||||||
s->saveLoadArrayOf(_shadowPalette, _shadowPaletteSize, 1, sleByte);
|
s->saveLoadArrayOf(_shadowPalette, _shadowPaletteSize, 1, sleByte);
|
||||||
// _roomPalette didn't show up until V21 save games
|
// _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)
|
if (s->getVersion() >= VER(21) && _game.version < 5)
|
||||||
s->saveLoadArrayOf(_roomPalette, sizeof(_roomPalette), 1, sleByte);
|
s->saveLoadArrayOf(_roomPalette, sizeof(_roomPalette), 1, sleByte);
|
||||||
}
|
}
|
||||||
|
@ -1348,6 +1351,20 @@ void ScummEngine::saveOrLoad(Serializer *s) {
|
||||||
memset(_colorUsedByCycle, 0, sizeof(_colorUsedByCycle));
|
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
|
// 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
|
* only saves/loads those which are valid for the version of the savegame
|
||||||
* which is being loaded/saved currently.
|
* 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
|
* An auxillary macro, used to specify savegame versions. We use this instead
|
||||||
|
|
|
@ -290,6 +290,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
|
||||||
#endif
|
#endif
|
||||||
_shadowPalette = NULL;
|
_shadowPalette = NULL;
|
||||||
_shadowPaletteSize = 0;
|
_shadowPaletteSize = 0;
|
||||||
|
_verbPalette = NULL;
|
||||||
memset(_currentPalette, 0, sizeof(_currentPalette));
|
memset(_currentPalette, 0, sizeof(_currentPalette));
|
||||||
memset(_darkenPalette, 0, sizeof(_darkenPalette));
|
memset(_darkenPalette, 0, sizeof(_darkenPalette));
|
||||||
memset(_HEV7ActorPalette, 0, sizeof(_HEV7ActorPalette));
|
memset(_HEV7ActorPalette, 0, sizeof(_HEV7ActorPalette));
|
||||||
|
@ -610,6 +611,7 @@ ScummEngine::~ScummEngine() {
|
||||||
_textSurface.free();
|
_textSurface.free();
|
||||||
|
|
||||||
free(_shadowPalette);
|
free(_shadowPalette);
|
||||||
|
free(_verbPalette);
|
||||||
|
|
||||||
free(_palManipPalette);
|
free(_palManipPalette);
|
||||||
free(_palManipIntermediatePal);
|
free(_palManipIntermediatePal);
|
||||||
|
@ -1408,6 +1410,10 @@ void ScummEngine::resetScumm() {
|
||||||
_16BitPalette = (uint16 *)calloc(512, sizeof(uint16));
|
_16BitPalette = (uint16 *)calloc(512, sizeof(uint16));
|
||||||
#endif
|
#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
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
||||||
if (_game.platform == Common::kPlatformFMTowns) {
|
if (_game.platform == Common::kPlatformFMTowns) {
|
||||||
delete _townsScreen;
|
delete _townsScreen;
|
||||||
|
|
|
@ -970,6 +970,7 @@ protected:
|
||||||
void setCurrentPalette(int pal);
|
void setCurrentPalette(int pal);
|
||||||
void setRoomPalette(int pal, int room);
|
void setRoomPalette(int pal, int room);
|
||||||
void setPCEPaletteFromPtr(const byte *ptr);
|
void setPCEPaletteFromPtr(const byte *ptr);
|
||||||
|
void setAmigaPaletteFromPtr(const byte *ptr);
|
||||||
virtual void setPaletteFromPtr(const byte *ptr, int numcolor = -1);
|
virtual void setPaletteFromPtr(const byte *ptr, int numcolor = -1);
|
||||||
|
|
||||||
virtual void setPalColor(int index, int r, int g, int b);
|
virtual void setPalColor(int index, int r, int g, int b);
|
||||||
|
@ -1065,6 +1066,9 @@ public:
|
||||||
uint16 _hePaletteSlot;
|
uint16 _hePaletteSlot;
|
||||||
uint16 *_16BitPalette;
|
uint16 *_16BitPalette;
|
||||||
|
|
||||||
|
// Indy4 Amiga specific
|
||||||
|
byte *_verbPalette;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _shadowPaletteSize;
|
int _shadowPaletteSize;
|
||||||
byte _currentPalette[3 * 256];
|
byte _currentPalette[3 * 256];
|
||||||
|
@ -1085,6 +1089,14 @@ protected:
|
||||||
bool _enable_gs;
|
bool _enable_gs;
|
||||||
bool _copyProtection;
|
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:
|
public:
|
||||||
uint16 _extraBoxFlags[65];
|
uint16 _extraBoxFlags[65];
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue