Skip to content

Commit

Permalink
SCUMM: hopefully fix 16bit mode support for SCUMM FM-TOWNS games and …
Browse files Browse the repository at this point in the history
…LOOM PCE on Android

This mostly reverts 5b7754e. Instead, we try to use other 16bit modes  after 555 fails.
  • Loading branch information
athrxx committed Jun 15, 2011
1 parent e2b3e39 commit d19b9ba
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 69 deletions.
24 changes: 10 additions & 14 deletions engines/scumm/cursor.cpp
Expand Up @@ -117,21 +117,17 @@ void ScummEngine_v6::setCursorTransparency(int a) {
void ScummEngine::updateCursor() {
int transColor = (_game.heversion >= 80) ? 5 : 255;
#ifdef USE_RGB_COLOR
if (_bytesPerPixelOutput == 2) {
Graphics::PixelFormat format = _system->getScreenFormat();
CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
_cursor.hotspotX, _cursor.hotspotY,
(_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor),
(_game.heversion == 70 ? 2 : 1),
&format);
} else {
#endif
Graphics::PixelFormat format = _system->getScreenFormat();
CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
_cursor.hotspotX, _cursor.hotspotY,
(_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor),
(_game.heversion == 70 ? 2 : 1),
&format);
#else
CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
_cursor.hotspotX, _cursor.hotspotY,
(_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor),
(_game.heversion == 70 ? 2 : 1));
#ifdef USE_RGB_COLOR
}
#endif
}

Expand Down Expand Up @@ -558,7 +554,7 @@ void ScummEngine_v5::setBuiltinCursor(int idx) {
uint16 color;
const uint16 *src = _cursorImages[_currentCursor];

if (_bytesPerPixelOutput == 2) {
if (_outputPixelFormat.bytesPerPixel == 2) {
if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine) {
byte r, g, b;
colorPCEToRGB(default_pce_cursor_colors[idx], &r, &g, &b);
Expand All @@ -584,14 +580,14 @@ void ScummEngine_v5::setBuiltinCursor(int idx) {
_cursor.width = 16 * _textSurfaceMultiplier;
_cursor.height = 16 * _textSurfaceMultiplier;

int scl = _bytesPerPixelOutput * _textSurfaceMultiplier;
int scl = _outputPixelFormat.bytesPerPixel * _textSurfaceMultiplier;

for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
if (src[i] & (1 << j)) {
byte *dst1 = _grabbedCursor + 16 * scl * i * _textSurfaceMultiplier + (15 - j) * scl;
byte *dst2 = (_textSurfaceMultiplier == 2) ? dst1 + 16 * scl : dst1;
if (_bytesPerPixelOutput == 2) {
if (_outputPixelFormat.bytesPerPixel == 2) {
for (int b = 0; b < scl; b += 2) {
*((uint16*)dst1) = *((uint16*)dst2) = color;
dst1 += 2;
Expand Down
2 changes: 1 addition & 1 deletion engines/scumm/gfx.cpp
Expand Up @@ -657,7 +657,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
return;
} else
#endif
if (_bytesPerPixelOutput == 2) {
if (_outputPixelFormat.bytesPerPixel == 2) {
const byte *srcPtr = (const byte *)src;
const byte *textPtr = (byte *)_textSurface.getBasePtr(x * m, y * m);
byte *dstPtr = _compositeBuf;
Expand Down
4 changes: 2 additions & 2 deletions engines/scumm/gfx.h
Expand Up @@ -429,7 +429,7 @@ class Gdi16Bit : public Gdi {
// switching graphics layers on and off).
class TownsScreen {
public:
TownsScreen(OSystem *system, int width, int height, int bpp);
TownsScreen(OSystem *system, int width, int height, Graphics::PixelFormat &format);
~TownsScreen();

void setupLayer(int layer, int width, int height, int numCol, void *srcPal = 0);
Expand Down Expand Up @@ -476,7 +476,7 @@ class TownsScreen {
int _height;
int _width;
int _pitch;
int _bpp;
Graphics::PixelFormat _pixelFormat;

int _numDirtyRects;
Common::List<Common::Rect> _dirtyRects;
Expand Down
34 changes: 15 additions & 19 deletions engines/scumm/gfx_towns.cpp
Expand Up @@ -53,10 +53,10 @@ void ScummEngine::towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, in

if (vs->number == kMainVirtScreen || _game.id == GID_INDY3 || _game.id == GID_ZAK) {
for (int h = 0; h < height; ++h) {
if (_bytesPerPixelOutput == 2) {
if (_outputPixelFormat.bytesPerPixel == 2) {
for (int w = 0; w < width; ++w) {
*(uint16*)dst1 = _16BitPalette[*src1++];
dst1 += _bytesPerPixelOutput;
dst1 += _outputPixelFormat.bytesPerPixel;
}

src1 += sp1;
Expand Down Expand Up @@ -200,8 +200,8 @@ const uint8 ScummEngine::_townsLayer2Mask[] = {
#define DIRTY_RECTS_MAX 20
#define FULL_REDRAW (DIRTY_RECTS_MAX + 1)

TownsScreen::TownsScreen(OSystem *system, int width, int height, int bpp) :
_system(system), _width(width), _height(height), _bpp(bpp), _pitch(width * bpp) {
TownsScreen::TownsScreen(OSystem *system, int width, int height, Graphics::PixelFormat &format) :
_system(system), _width(width), _height(height), _pixelFormat(format), _pitch(width * format.bytesPerPixel) {
memset(&_layers[0], 0, sizeof(TownsScreenLayer));
memset(&_layers[1], 0, sizeof(TownsScreenLayer));
_outBuffer = new byte[_pitch * _height];
Expand Down Expand Up @@ -250,7 +250,7 @@ void TownsScreen::setupLayer(int layer, int width, int height, int numCol, void
l->pitch = width * l->bpp;
l->palette = (uint8*)pal;

if (l->palette && _bpp == 1)
if (l->palette && _pixelFormat.bytesPerPixel == 1)
warning("TownsScreen::setupLayer(): Layer palette usage requires 16 bit graphics setting.\nLayer palette will be ignored.");

delete[] l->pixels;
Expand All @@ -270,7 +270,7 @@ void TownsScreen::setupLayer(int layer, int width, int height, int numCol, void
l->bltInternY[i] = l->pixels + (i / l->scaleH) * l->pitch;

delete[] l->bltTmpPal;
l->bltTmpPal = (l->bpp == 1 && _bpp == 2) ? new uint16[l->numCol] : 0;
l->bltTmpPal = (l->bpp == 1 && _pixelFormat.bytesPerPixel == 2) ? new uint16[l->numCol] : 0;

l->enabled = true;
_layers[0].onBottom = true;
Expand Down Expand Up @@ -452,20 +452,20 @@ void TownsScreen::updateOutputBuffer() {
if (!l->enabled || !l->ready)
continue;

uint8 *dst = _outBuffer + r->top * _pitch + r->left * _bpp;
int ptch = _pitch - (r->right - r->left + 1) * _bpp;
uint8 *dst = _outBuffer + r->top * _pitch + r->left * _pixelFormat.bytesPerPixel;
int ptch = _pitch - (r->right - r->left + 1) * _pixelFormat.bytesPerPixel;

if (_bpp == 2 && l->bpp == 1) {
if (_pixelFormat.bytesPerPixel == 2 && l->bpp == 1) {
for (int ic = 0; ic < l->numCol; ic++)
l->bltTmpPal[ic] = calc16BitColor(&l->palette[ic * 3]);
}

for (int y = r->top; y <= r->bottom; ++y) {
if (l->bpp == _bpp && l->scaleW == 1 && l->onBottom && l->numCol & 0xff00) {
memcpy(dst, &l->bltInternY[y][l->bltInternX[r->left]], (r->right + 1 - r->left) * _bpp);
if (l->bpp == _pixelFormat.bytesPerPixel && l->scaleW == 1 && l->onBottom && l->numCol & 0xff00) {
memcpy(dst, &l->bltInternY[y][l->bltInternX[r->left]], (r->right + 1 - r->left) * _pixelFormat.bytesPerPixel);
dst += _pitch;

} else if (_bpp == 2) {
} else if (_pixelFormat.bytesPerPixel == 2) {
for (int x = r->left; x <= r->right; ++x) {
uint8 *src = &l->bltInternY[y][l->bltInternX[x]];
if (l->bpp == 1) {
Expand Down Expand Up @@ -501,17 +501,13 @@ void TownsScreen::updateOutputBuffer() {

void TownsScreen::outputToScreen() {
for (Common::List<Common::Rect>::iterator i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i)
_system->copyRectToScreen(_outBuffer + i->top * _pitch + i->left * _bpp, _pitch, i->left, i->top, i->right - i->left + 1, i->bottom - i->top + 1);
_system->copyRectToScreen(_outBuffer + i->top * _pitch + i->left * _pixelFormat.bytesPerPixel, _pitch, i->left, i->top, i->right - i->left + 1, i->bottom - i->top + 1);
_dirtyRects.clear();
_numDirtyRects = 0;
}

uint16 TownsScreen::calc16BitColor(const uint8 *palEntry) {
uint16 ar = (palEntry[0] & 0xf8) << 7;
uint16 ag = (palEntry[1] & 0xf8) << 2;
uint16 ab = (palEntry[2] >> 3);
uint16 col = ar | ag | ab;
return col;
uint16 TownsScreen::calc16BitColor(const uint8 *palEntry) {
return _pixelFormat.RGBToColor(palEntry[0], palEntry[1], palEntry[2]);
}

#undef DIRTY_RECTS_MAX
Expand Down
20 changes: 7 additions & 13 deletions engines/scumm/palette.cpp
Expand Up @@ -51,11 +51,7 @@ uint8 *ScummEngine::getHEPaletteSlot(uint16 palSlot) {
}

uint16 ScummEngine::get16BitColor(uint8 r, uint8 g, uint8 b) {
uint16 ar = (r >> 3) << 10;
uint16 ag = (g >> 3) << 5;
uint16 ab = (b >> 3) << 0;
uint16 col = ar | ag | ab;
return col;
return _outputPixelFormat.RGBToColor(r, g, b);
}

void ScummEngine::resetPalette() {
Expand Down Expand Up @@ -225,12 +221,10 @@ void ScummEngine::resetPalette() {
if (_game.id == GID_INDY4 || _game.id == GID_MONKEY2)
_townsClearLayerFlag = 0;
#ifdef USE_RGB_COLOR
else if (_bytesPerPixelOutput == 2) {
if (_game.id == GID_LOOM)
towns_setTextPaletteFromPtr(tableTownsLoomPalette);
else if (_game.version == 3)
towns_setTextPaletteFromPtr(tableTownsV3Palette);
}
else if (_game.id == GID_LOOM)
towns_setTextPaletteFromPtr(tableTownsLoomPalette);
else if (_game.version == 3)
towns_setTextPaletteFromPtr(tableTownsV3Palette);
#endif

_townsScreen->toggleLayers(_townsActiveLayerFlags);
Expand Down Expand Up @@ -1022,7 +1016,7 @@ void ScummEngine::setCurrentPalette(int palindex) {
setPCEPaletteFromPtr(pals);
#ifdef USE_RGB_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
} else if (_game.platform == Common::kPlatformFMTowns && _bytesPerPixelOutput == 2) {
} else if (_game.platform == Common::kPlatformFMTowns) {
towns_setPaletteFromPtr(pals);
#endif
#endif
Expand Down Expand Up @@ -1125,7 +1119,7 @@ void ScummEngine::updatePalette() {

#ifdef USE_RGB_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && _bytesPerPixelOutput == 2) {
if (_game.platform == Common::kPlatformFMTowns) {
p = palette_colors;
for (i = first; i < first + num; ++i) {
_16BitPalette[i] = get16BitColor(p[0], p[1], p[2]);
Expand Down
2 changes: 1 addition & 1 deletion engines/scumm/saveload.cpp
Expand Up @@ -1493,7 +1493,7 @@ void ScummEngine_v5::saveOrLoad(Serializer *s) {

// Reset cursors for old FM-Towns savegames saved with 256 color setting.
// Otherwise the cursor will be messed up when displayed in the new hi color setting.
if (_game.platform == Common::kPlatformFMTowns && _bytesPerPixelOutput == 2 && s->isLoading() && s->getVersion() < VER(82)) {
if (_game.platform == Common::kPlatformFMTowns && _outputPixelFormat.bytesPerPixel == 2 && s->isLoading() && s->getVersion() < VER(82)) {
if (_game.id == GID_LOOM) {
redefineBuiltinCursorFromChar(1, 1);
redefineBuiltinCursorHotspot(1, 0, 0);
Expand Down
49 changes: 31 additions & 18 deletions engines/scumm/scumm.cpp
Expand Up @@ -260,7 +260,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_switchRoomEffect2 = 0;
_switchRoomEffect = 0;

_bytesPerPixelOutput = _bytesPerPixel = 1;
_bytesPerPixel = 1;
_doEffect = false;
_snapScroll = false;
_currentLights = 0;
Expand Down Expand Up @@ -545,18 +545,19 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_screenHeight = 200;
}

_bytesPerPixelOutput = _bytesPerPixel = (_game.features & GF_16BIT_COLOR) ? 2 : 1;
_bytesPerPixel = (_game.features & GF_16BIT_COLOR) ? 2 : 1;
uint8 sizeMult = _bytesPerPixel;

#ifdef USE_RGB_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns)
_bytesPerPixelOutput = 2;
sizeMult = 2;
#endif
#endif

// Allocate gfx compositing buffer (not needed for V7/V8 games).
if (_game.version < 7)
_compositeBuf = (byte *)malloc(_screenWidth * _screenHeight * _bytesPerPixelOutput);
_compositeBuf = (byte *)malloc(_screenWidth * _screenHeight * sizeMult);
else
_compositeBuf = 0;

Expand Down Expand Up @@ -1156,17 +1157,27 @@ Common::Error ScummEngine::init() {
#endif
) {
#ifdef USE_RGB_COLOR
Graphics::PixelFormat format = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
initGraphics(screenWidth, screenHeight, screenWidth > 320, &format);
if (format != _system->getScreenFormat()) {
if (_game.platform == Common::kPlatformFMTowns && _game.version == 3) {
warning("Your ScummVM build does not support the type of 16bit color mode required by this target.\nStarting game in 8bit color mode...\nYou may experience color glitches");
_bytesPerPixelOutput = 1;
initGraphics(screenWidth, screenHeight, (screenWidth > 320));
} else {
return Common::kUnsupportedColorMode;
}
_outputPixelFormat = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
Common::List<Graphics::PixelFormat> tryModes = _system->getSupportedFormats();
// Try default 555 mode first
tryModes.push_front(_outputPixelFormat);

for (Common::List<Graphics::PixelFormat>::iterator g = tryModes.begin(); g != tryModes.end(); ++g) {
if (g->bytesPerPixel != 2 || g->aBits())
continue;
_outputPixelFormat = *g;
initGraphics(screenWidth, screenHeight, screenWidth > 320, &_outputPixelFormat);
// athrxx-06/15/2011: To avoid regressions I add support for other modes than 555 only
// for FM-TOWNS games and for LOOM PCE atm.
// TODO: Someone knowledgeable about HE games might check whether other modes can be
// supported for these games, too. Quick tests with SPYOZON indicate that this should
// not be a problem.
if (*g == _system->getScreenFormat() || (_game.platform != Common::kPlatformFMTowns && _game.platform != Common::kPlatformPCEngine))
break;
}

if (_outputPixelFormat != _system->getScreenFormat())
return Common::kUnsupportedColorMode;
#else
if (_game.platform == Common::kPlatformFMTowns && _game.version == 3) {
warning("Starting game without the required 16bit color support.\nYou may experience color glitches");
Expand All @@ -1184,6 +1195,8 @@ Common::Error ScummEngine::init() {
}
}

_outputPixelFormat = _system->getScreenFormat();

setupScumm();

readIndexFile();
Expand Down Expand Up @@ -1296,7 +1309,7 @@ void ScummEngine::setupScumm() {
_res->setHeapThreshold(400000, maxHeapThreshold);

free(_compositeBuf);
_compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier * _bytesPerPixelOutput);
_compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier * _outputPixelFormat.bytesPerPixel);
}

#ifdef ENABLE_SCUMM_7_8
Expand Down Expand Up @@ -1377,7 +1390,7 @@ void ScummEngine::resetScumm() {
#ifdef USE_RGB_COLOR
if (_game.features & GF_16BIT_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|| (_game.platform == Common::kPlatformFMTowns && _bytesPerPixelOutput == 2)
|| (_game.platform == Common::kPlatformFMTowns)
#endif
)
_16BitPalette = (uint16 *)calloc(512, sizeof(uint16));
Expand All @@ -1386,8 +1399,8 @@ void ScummEngine::resetScumm() {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
delete _townsScreen;
_townsScreen = new TownsScreen(_system, _screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, _bytesPerPixelOutput);
_townsScreen->setupLayer(0, _screenWidth, _screenHeight, (_bytesPerPixelOutput == 2) ? 32767 : 256);
_townsScreen = new TownsScreen(_system, _screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, _outputPixelFormat);
_townsScreen->setupLayer(0, _screenWidth, _screenHeight, (_outputPixelFormat.bytesPerPixel == 2) ? 32767 : 256);
_townsScreen->setupLayer(1, _screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, 16, _textPalette);
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion engines/scumm/scumm.h
Expand Up @@ -971,7 +971,7 @@ class ScummEngine : public Engine {

Common::RenderMode _renderMode;
uint8 _bytesPerPixel;
uint8 _bytesPerPixelOutput;
Graphics::PixelFormat _outputPixelFormat;

protected:
ColorCycle _colorCycle[16]; // Palette cycles
Expand Down

0 comments on commit d19b9ba

Please sign in to comment.