From 0a42a7d6257cedfe461ef65de565b8007e3a0c72 Mon Sep 17 00:00:00 2001 From: athrxx Date: Wed, 15 Jun 2011 22:01:24 +0200 Subject: SCUMM: hopefully fix 16bit mode support for SCUMM FM-TOWNS games and LOOM PCE on Android This mostly reverts 5b7754e3f095eb8a469dd4b7de5a6379f8e13c27. Instead, we try to use other 16bit modes after 555 fails. --- engines/scumm/cursor.cpp | 24 +++++++++------------- engines/scumm/gfx.cpp | 2 +- engines/scumm/gfx.h | 4 ++-- engines/scumm/gfx_towns.cpp | 34 ++++++++++++++----------------- engines/scumm/palette.cpp | 20 +++++++----------- engines/scumm/saveload.cpp | 2 +- engines/scumm/scumm.cpp | 49 ++++++++++++++++++++++++++++----------------- engines/scumm/scumm.h | 2 +- 8 files changed, 68 insertions(+), 69 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp index 8676c857ea..a8adb4d5c5 100644 --- a/engines/scumm/cursor.cpp +++ b/engines/scumm/cursor.cpp @@ -114,21 +114,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 } @@ -555,7 +551,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); @@ -581,14 +577,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; diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 1b913e16b4..98d447fdaf 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -661,7 +661,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; diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h index 6da07efd18..54ce724da1 100644 --- a/engines/scumm/gfx.h +++ b/engines/scumm/gfx.h @@ -443,7 +443,7 @@ public: // 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); @@ -490,7 +490,7 @@ private: int _height; int _width; int _pitch; - int _bpp; + Graphics::PixelFormat _pixelFormat; int _numDirtyRects; Common::List _dirtyRects; diff --git a/engines/scumm/gfx_towns.cpp b/engines/scumm/gfx_towns.cpp index cdccd3e193..3c96be8b9c 100644 --- a/engines/scumm/gfx_towns.cpp +++ b/engines/scumm/gfx_towns.cpp @@ -50,10 +50,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; @@ -197,8 +197,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]; @@ -247,7 +247,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; @@ -267,7 +267,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; @@ -449,20 +449,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) { @@ -498,17 +498,13 @@ void TownsScreen::updateOutputBuffer() { void TownsScreen::outputToScreen() { for (Common::List::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 diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp index 3e8c35cfd8..51ba2195d7 100644 --- a/engines/scumm/palette.cpp +++ b/engines/scumm/palette.cpp @@ -48,11 +48,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() { @@ -222,12 +218,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); @@ -1016,7 +1010,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 @@ -1119,7 +1113,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]); diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 19834cb35d..2be032d496 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -1489,7 +1489,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); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 97dd68af7c..d4983397e4 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -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; @@ -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; @@ -1154,17 +1155,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 tryModes = _system->getSupportedFormats(); + // Try default 555 mode first + tryModes.push_front(_outputPixelFormat); + + for (Common::List::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"); @@ -1182,6 +1193,8 @@ Common::Error ScummEngine::init() { } } + _outputPixelFormat = _system->getScreenFormat(); + setupScumm(); readIndexFile(); @@ -1290,7 +1303,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 @@ -1371,7 +1384,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)); @@ -1380,8 +1393,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 diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 6e75f47d77..5700271911 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -897,7 +897,7 @@ public: Common::RenderMode _renderMode; uint8 _bytesPerPixel; - uint8 _bytesPerPixelOutput; + Graphics::PixelFormat _outputPixelFormat; protected: ColorCycle _colorCycle[16]; // Palette cycles -- cgit v1.2.3