From 27469a1896f08c6d32df1778dc7e9cce28c2bec4 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 20 Feb 2005 00:17:22 +0000 Subject: Patch #1121337 (CGA rendering in early LEC titles). Differences against patch: o Updated documentation o Fixed text colors o Implemented Hercules dithering Ditherers are based on loom ega and monkey ega, so for zak and mm they're wrong, i.e. these games look better than with original ditherers. TODO: Proper ditherers for zak & MM EGA ditherers for VGA SCUMM v5 games svn-id: r16816 --- scumm/actor.cpp | 6 +++ scumm/charset.cpp | 19 ++++++++++ scumm/charset.h | 3 +- scumm/gfx.cpp | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++--- scumm/gfx.h | 5 ++- scumm/input.cpp | 6 +++ scumm/palette.cpp | 22 +++++++++++ scumm/scumm.cpp | 43 ++++++++++++++++++++- scumm/scumm.h | 4 ++ scumm/vars.cpp | 6 +++ 10 files changed, 217 insertions(+), 8 deletions(-) (limited to 'scumm') diff --git a/scumm/actor.cpp b/scumm/actor.cpp index 316a3a116d..95b43a5d31 100644 --- a/scumm/actor.cpp +++ b/scumm/actor.cpp @@ -1400,6 +1400,12 @@ void Actor::setActorCostume(int c) { } else if (_vm->_features & GF_OLD_BUNDLE) { for (i = 0; i < 16; i++) palette[i] = i; + + // Make stuff more visible on CGA. Based on disassembly + if (_vm->_renderMode == Common::kRenderCGA) { + palette[6] = 5; + palette[7] = 15; + } } else { for (i = 0; i < 32; i++) palette[i] = 0xFF; diff --git a/scumm/charset.cpp b/scumm/charset.cpp index 7b34acc7ab..818c1b16d4 100644 --- a/scumm/charset.cpp +++ b/scumm/charset.cpp @@ -1160,6 +1160,8 @@ void CharsetRendererV3::setColor(byte color) _color &= 0x7f; } else _dropShadow = false; + + translateColor(); } void CharsetRendererV3::printChar(int chr) { @@ -1253,6 +1255,21 @@ void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int drawBits1(s, dst, charPtr, y, width, height); } +void CharsetRenderer::translateColor() { + // Based on disassembly + if (_vm->_renderMode == Common::kRenderCGA) { + static byte CGAtextColorMap[16] = {0, 3, 3, 3, 5, 5, 5, 15, + 15, 3, 3, 3, 5, 5, 15, 15}; + _color = CGAtextColorMap[_color & 0x0f]; + } + + if (_vm->_renderMode == Common::kRenderHerc) { + static byte HercTextColorMap[16] = {0, 15, 2, 15, 15, 5, 15, 15, + 8, 15, 15, 15, 15, 15, 15, 15}; + _color = HercTextColorMap[_color & 0x0f]; + } +} + void CharsetRendererClassic::printChar(int chr) { int width, height, origWidth, origHeight; @@ -1269,6 +1286,8 @@ void CharsetRendererClassic::printChar(int chr) { if (chr == '@') return; + translateColor(); + _vm->_charsetColorMap[1] = _color; int type = *_fontPtr; diff --git a/scumm/charset.h b/scumm/charset.h index e546d16b73..dbadc1a2c3 100644 --- a/scumm/charset.h +++ b/scumm/charset.h @@ -92,6 +92,7 @@ public: int getStringWidth(int a, const byte *str); void addLinebreaks(int a, byte *str, int pos, int maxwidth); + void translateColor(); virtual void setCurID(byte id) = 0; int getCurID() { return _curId; } @@ -99,7 +100,7 @@ public: virtual int getFontHeight() = 0; virtual int getCharWidth(byte chr) = 0; - virtual void setColor(byte color) { _color = color; } + virtual void setColor(byte color) { _color = color; translateColor(); } }; class CharsetRendererCommon : public CharsetRenderer { diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index 1156f16688..3709f2cbe5 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -188,6 +188,7 @@ Gdi::Gdi(ScummEngine *vm) { _compositeBuf = 0; _textSurface.pixels = 0; + _herculesBuf = 0; } void ScummEngine::initScreens(int b, int h) { @@ -225,11 +226,17 @@ void Gdi::init() { const int size = _vm->_screenWidth * _vm->_screenHeight; free(_compositeBuf); free(_textSurface.pixels); + free(_herculesBuf); _compositeBuf = (byte *)malloc(size); _textSurface.pixels = malloc(size); memset(_compositeBuf, CHARSET_MASK_TRANSPARENCY, size); memset(_textSurface.pixels, CHARSET_MASK_TRANSPARENCY, size); + if (_vm->_renderMode == Common::kRenderHerc) { + _herculesBuf = (byte *)malloc(Common::kHercW * Common::kHercH); + memset(_herculesBuf, CHARSET_MASK_TRANSPARENCY, Common::kHercW * Common::kHercH); + } + _textSurface.w = _vm->_screenWidth; _textSurface.h = _vm->_screenHeight; _textSurface.pitch = _vm->_screenWidth; @@ -474,8 +481,8 @@ void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int botto bottom = _vm->_screenTop + _vm->_screenHeight; // Convert the vertical coordinates to real screen coords - const int y = vs->topline + top - _vm->_screenTop; - const int height = bottom - top; + int y = vs->topline + top - _vm->_screenTop; + int height = bottom - top; // Compute screen etc. buffer pointers const byte *src = vs->getPixels(x, top); @@ -508,11 +515,105 @@ void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int botto dst += _vm->_screenWidth; text += _textSurface.pitch; } - - // Finally blit the whole thing to the screen - _vm->_system->copyRectToScreen(_compositeBuf + x + y * _vm->_screenWidth, _vm->_screenWidth, x, y, width, height); + + if (_vm->_renderMode == Common::kRenderCGA) + ditherCGA(_compositeBuf + x + y * _vm->_screenWidth, _vm->_screenWidth, x, y, width, height); + + if (_vm->_renderMode == Common::kRenderHerc) { + ditherHerc(_compositeBuf + x + y * _vm->_screenWidth, _herculesBuf, _vm->_screenWidth, &x, &y, &width, &height); + // center image on the screen + _vm->_system->copyRectToScreen(_herculesBuf + x + y * Common::kHercW, + Common::kHercW, x + (Common::kHercW - _vm->_screenWidth * 2) / 2, y, width, height); + } else { + // Finally blit the whole thing to the screen + _vm->_system->copyRectToScreen(_compositeBuf + x + y * _vm->_screenWidth, _vm->_screenWidth, x, y, width, height); + } +} + +// CGA +// indy3 loom maniac monkey1 zak +// +// Herc (720x350) +// maniac monkey1 zak +// +// EGA +// monkey2 loom maniac monkey1 atlantis indy3 zak loomcd + +// CGA dithers 4x4 square with direct substitutes +// Odd lines have colors swapped, so there will be checkered patterns. +// But apparently there is a mistake for 10th color. +void Gdi::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const { + byte *ptr; + int idx1, idx2; + static byte cgaDither[2][2][16] = { + {{0, 1, 0, 1, 2, 2, 0, 0, 3, 1, 3, 1, 3, 2, 1, 3}, + {0, 0, 1, 1, 0, 2, 2, 3, 0, 3, 1, 1, 3, 3, 1, 3}}, + {{0, 0, 1, 1, 0, 2, 2, 3, 0, 3, 1, 1, 3, 3, 1, 3}, + {0, 1, 0, 1, 2, 2, 0, 0, 3, 1, 1, 1, 3, 2, 1, 3}}}; + + for (int y1 = 0; y1 < height; y1++) { + ptr = dst + y1 * dstPitch; + + idx1 = (y + y1) % 2; + for (int x1 = 0; x1 < width; x1++) { + idx2 = (x + x1) % 2; + *ptr++ = cgaDither[idx1][idx2][*ptr & 0xF]; + } + } +} + +// Hercules dithering. It uses same dithering tables but output is 1bpp and +// it stretches in this way: +// aaaa0 +// aa aaaa1 +// bb bbbb0 Here 0 and 1 mean dithering table row number +// cc --> bbbb1 +// dd cccc0 +// cccc1 +// dddd0 +void Gdi::ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) const { + byte *srcptr, *dstptr; + int xo = *x, yo = *y, widtho = *width, heighto = *height; + int idx1, idx2, dsty = 0; + static byte cgaDither[2][2][16] = { + {{0, 1, 0, 1, 2, 2, 0, 0, 3, 1, 3, 1, 3, 2, 1, 3}, + {0, 0, 1, 1, 0, 2, 2, 3, 0, 3, 1, 1, 3, 3, 1, 3}}, + {{0, 0, 1, 1, 0, 2, 2, 3, 0, 3, 1, 1, 3, 3, 1, 3}, + {0, 1, 0, 1, 2, 2, 0, 0, 3, 1, 1, 1, 3, 2, 1, 3}}}; + + // calculate dsty + for (int y1 = 0; y1 < yo; y1++) { + dsty += 2; + if (y1 % 4 == 3) + dsty--; + } + *y = dsty; + *x *= 2; + *width *= 2; + *height = 0; + + for (int y1 = 0; y1 < heighto;) { + srcptr = src + y1 * srcPitch; + dstptr = hercbuf + dsty * Common::kHercW + xo * 2; + + if (dstptr >= hercbuf + Common::kHercW * Common::kHercH + widtho * 2) + debug("Gnaa"); + + idx1 = (dsty % 7) % 2; + for (int x1 = 0; x1 < widtho; x1++) { + idx2 = (xo + x1) % 2; + *dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] >> 1; + *dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] & 0x1; + srcptr++; + } + if (idx1 || dsty % 7 == 6) + y1++; + dsty++; + (*height)++; + } } + #pragma mark - #pragma mark --- Background buffers & charset mask --- #pragma mark - diff --git a/scumm/gfx.h b/scumm/gfx.h index 4762b3678c..6bac0b54fa 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -216,6 +216,7 @@ public: protected: byte *_compositeBuf; + byte *_herculesBuf; byte *_roomPalette; byte _decomp_shr, _decomp_mask; @@ -256,7 +257,9 @@ protected: /* Misc */ void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b); void updateDirtyScreen(VirtScreen *vs); - + void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const; + void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) const; + byte *getMaskBuffer(int x, int y, int z); int getZPlanes(const byte *smap_ptr, const byte *zplane_list[9], bool bmapImage) const; diff --git a/scumm/input.cpp b/scumm/input.cpp index f68745ef47..d7d1f1c25c 100644 --- a/scumm/input.cpp +++ b/scumm/input.cpp @@ -130,6 +130,12 @@ void ScummEngine::parseEvents() { case OSystem::EVENT_MOUSEMOVE: _mouse.x = event.mouse.x; _mouse.y = event.mouse.y; + + if (_renderMode == Common::kRenderHerc) { + _mouse.x -= (Common::kHercW - _screenWidth * 2) / 2; + _mouse.x /= 2; + _mouse.y = _mouse.y * 4 / 7; + } break; case OSystem::EVENT_LBUTTONDOWN: diff --git a/scumm/palette.cpp b/scumm/palette.cpp index b4f8ab8e43..9f0b0cd445 100644 --- a/scumm/palette.cpp +++ b/scumm/palette.cpp @@ -48,6 +48,28 @@ void ScummEngine::setupAmigaPalette() { setPalColor(15, 255, 255, 255); } +void ScummEngine::setupHercPalette() { + setPalColor( 0, 0, 0, 0); + setPalColor( 1, 0xAE, 0x69, 0x38); + + // Setup cursor palette + setPalColor( 7, 170, 170, 170); + setPalColor( 8, 85, 85, 85); + setPalColor(15, 255, 255, 255); +} + +void ScummEngine::setupCGAPalette() { + setPalColor( 0, 0, 0, 0); + setPalColor( 1, 0, 168, 168); + setPalColor( 2, 168, 0, 168); + setPalColor( 3, 168, 168, 168); + + // Setup cursor palette + setPalColor( 7, 170, 170, 170); + setPalColor( 8, 85, 85, 85); + setPalColor(15, 255, 255, 255); +} + void ScummEngine::setupEGAPalette() { setPalColor( 0, 0, 0, 0); setPalColor( 1, 0, 0, 170); diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index 395ae16e89..8fac59868a 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -998,6 +998,32 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS } _confirmExit = ConfMan.getBool("confirm_exit"); + if (ConfMan.hasKey("render_mode")) { + _renderMode = Common::parseRenderMode(ConfMan.get("render_mode").c_str()); + } else { + _renderMode = Common::kRenderDefault; + } + + // Do some render mode restirctions + switch (_renderMode) { + case Common::kRenderHerc: + if (_version > 2 && _gameId != GID_MONKEY_EGA) + _renderMode = Common::kRenderDefault; + break; + + case Common::kRenderCGA: + if (!(_features & GF_16COLOR)) + _renderMode = Common::kRenderDefault; + break; + + case Common::kRenderEGA: + _renderMode = Common::kRenderDefault; + break; + + default: + break; + } + _hexdumpScripts = false; _showStack = false; @@ -1019,6 +1045,11 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS } else if (_features & GF_NES) { _screenWidth = 256; _screenHeight = 240; + } else if (_renderMode == Common::kRenderHerc) { + _system->setGraphicsMode("1x"); + _features |= GF_DEFAULT_TO_1X_SCALER; + _screenWidth = 320; + _screenHeight = 200; } else { _screenWidth = 320; _screenHeight = 200; @@ -1109,7 +1140,13 @@ int ScummEngine::init(GameDetector &detector) { // Initialize backend _system->beginGFXTransaction(); initCommonGFX(detector); - _system->initSize(_screenWidth, _screenHeight); + if (_renderMode == Common::kRenderHerc) { + _system->initSize(Common::kHercW, Common::kHercH); + _features |= GF_DEFAULT_TO_1X_SCALER; + _system->setGraphicsMode("1x"); + } else { + _system->initSize(_screenWidth, _screenHeight); + } // FIXME: All this seems a dirty hack to me. We already // have this check in constructor @@ -1268,6 +1305,10 @@ void ScummEngine::scummInit() { _shadowPalette[i] = i; if ((_features & GF_AMIGA) || (_features & GF_ATARI_ST)) setupAmigaPalette(); + else if (_renderMode == Common::kRenderHerc) + setupHercPalette(); + else if (_renderMode == Common::kRenderCGA) + setupCGAPalette(); else setupEGAPalette(); } diff --git a/scumm/scumm.h b/scumm/scumm.h index 091635c8e9..56146d41fa 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -868,6 +868,8 @@ public: int _screenStartStrip, _screenEndStrip; int _screenTop; + Common::RenderMode _renderMode; + protected: ColorCycle _colorCycle[16]; // Palette cycles @@ -930,6 +932,8 @@ protected: const byte *getPalettePtr(int palindex, int room); void setupAmigaPalette(); + void setupHercPalette(); + void setupCGAPalette(); void setupEGAPalette(); void setupV1ManiacPalette(); void setupV1ZakPalette(); diff --git a/scumm/vars.cpp b/scumm/vars.cpp index 429c153962..4a8ced0de1 100644 --- a/scumm/vars.cpp +++ b/scumm/vars.cpp @@ -553,6 +553,12 @@ void ScummEngine::initScummVars() { VAR(VAR_VIDEOMODE) = 50; else if (_gameId == GID_MONKEY2 && (_features & GF_AMIGA)) VAR(VAR_VIDEOMODE) = 82; + else if (_renderMode == Common::kRenderCGA) + VAR(VAR_VIDEOMODE) = 4; + else if (_renderMode == Common::kRenderHerc) + VAR(VAR_VIDEOMODE) = 30; + else if (_renderMode == Common::kRenderEGA) + VAR(VAR_VIDEOMODE) = 13; else VAR(VAR_VIDEOMODE) = 19; if (_gameId == GID_LOOM && _features & GF_OLD_BUNDLE) { -- cgit v1.2.3