aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorEugene Sandulenko2005-02-20 00:17:22 +0000
committerEugene Sandulenko2005-02-20 00:17:22 +0000
commit27469a1896f08c6d32df1778dc7e9cce28c2bec4 (patch)
tree173e32cafae393fd7bcf2d7eb4e81932c5cd2b95 /scumm
parent3184c2de34c89a1b380fffa9f9ac83f53dc062d7 (diff)
downloadscummvm-rg350-27469a1896f08c6d32df1778dc7e9cce28c2bec4.tar.gz
scummvm-rg350-27469a1896f08c6d32df1778dc7e9cce28c2bec4.tar.bz2
scummvm-rg350-27469a1896f08c6d32df1778dc7e9cce28c2bec4.zip
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
Diffstat (limited to 'scumm')
-rw-r--r--scumm/actor.cpp6
-rw-r--r--scumm/charset.cpp19
-rw-r--r--scumm/charset.h3
-rw-r--r--scumm/gfx.cpp111
-rw-r--r--scumm/gfx.h5
-rw-r--r--scumm/input.cpp6
-rw-r--r--scumm/palette.cpp22
-rw-r--r--scumm/scumm.cpp43
-rw-r--r--scumm/scumm.h4
-rw-r--r--scumm/vars.cpp6
10 files changed, 217 insertions, 8 deletions
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) {