aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2005-02-20 00:17:22 +0000
committerEugene Sandulenko2005-02-20 00:17:22 +0000
commit27469a1896f08c6d32df1778dc7e9cce28c2bec4 (patch)
tree173e32cafae393fd7bcf2d7eb4e81932c5cd2b95
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
-rw-r--r--NEWS1
-rw-r--r--README1
-rw-r--r--base/gameDetector.cpp10
-rw-r--r--common/util.cpp42
-rw-r--r--common/util.h32
-rw-r--r--doc/05_01.tex1
-rw-r--r--gui/options.cpp30
-rw-r--r--gui/options.h1
-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
18 files changed, 333 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 428b806165..0cb4b231e8 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ For a more comprehensive changelog for the latest experimental CVS code, see:
SCUMM
- Added support for Mac Humongous Entertainment titles
- Added support for multiple filenames/versions using a single target
+ - Implemeted CGA and Hercules render modes in early LEC titles
<PORT #1 NEWS>
- ...
diff --git a/README b/README
index 652672a471..91f5832ebb 100644
--- a/README
+++ b/README
@@ -364,6 +364,7 @@ arguments - see the next section.
--native-mt32 True Roland MT-32 (disable GM emulation)
--output-rate=RATE Select output sample rate in Hz (e.g. 22050)
--aspect-ratio Enable aspect ratio correction
+ --render-mode=MODE Enable additional render modes (cga, ega, hercules)
--alt-intro Use alternative intro for CD versions of Beneath a
Steel Sky and Flight of the Amazon Queen
diff --git a/base/gameDetector.cpp b/base/gameDetector.cpp
index 44e823ef65..cd3b599460 100644
--- a/base/gameDetector.cpp
+++ b/base/gameDetector.cpp
@@ -96,6 +96,7 @@ static const char USAGE_STRING[] =
" --native-mt32 True Roland MT-32 (disable GM emulation)\n"
" --output-rate=RATE Select output sample rate in Hz (e.g. 22050)\n"
" --aspect-ratio Enable aspect ratio correction\n"
+ " --render-mode=MODE Enable additional render modes (cga, ega, hercules)\n"
"\n"
#if !defined(DISABLE_SKY) || !defined(DISABLE_QUEEN)
" --alt-intro Use alternative intro for CD versions of Beneath a\n"
@@ -122,6 +123,7 @@ GameDetector::GameDetector() {
ConfMan.registerDefault("fullscreen", false);
ConfMan.registerDefault("aspect_ratio", false);
ConfMan.registerDefault("gfx_mode", "normal");
+ ConfMan.registerDefault("render_mode", "default");
// Sound & Music
ConfMan.registerDefault("music_volume", 192);
@@ -478,6 +480,14 @@ void GameDetector::parseCommandLine(int argc, char **argv) {
ConfMan.set("aspect_ratio", cmdValue, kTransientDomain);
END_OPTION
+ DO_LONG_OPTION("render-mode")
+ int renderMode = Common::parseRenderMode(option);
+ if (renderMode == Common::kRenderDefault)
+ goto ShowHelpAndExit;
+
+ ConfMan.set("render_mode", option, kTransientDomain);
+ END_OPTION
+
DO_LONG_OPTION("savepath")
// TODO: Verify whether the path is valid
ConfMan.set("savepath", option, kTransientDomain);
diff --git a/common/util.cpp b/common/util.cpp
index eb63e16a68..f4d5c91779 100644
--- a/common/util.cpp
+++ b/common/util.cpp
@@ -219,5 +219,47 @@ const char *getPlatformDescription(Platform id) {
}
+#pragma mark -
+
+
+const RenderModeDescription g_renderModes[] = {
+ {"hercules", "Hercules", kRenderHerc},
+ {"cga", "CGA", kRenderCGA},
+ {"ega", "EGA", kRenderEGA},
+ {0, 0, kRenderDefault}
+};
+
+RenderMode parseRenderMode(const String &str) {
+ if (str.isEmpty())
+ return kRenderDefault;
+
+ const char *s = str.c_str();
+ const RenderModeDescription *l = g_renderModes;
+ for (; l->code; ++l) {
+ if (!scumm_stricmp(l->code, s))
+ return l->id;
+ }
+
+ return kRenderDefault;
+}
+
+const char *getRenderModeCode(RenderMode id) {
+ const RenderModeDescription *l = g_renderModes;
+ for (; l->code; ++l) {
+ if (l->id == id)
+ return l->code;
+ }
+ return 0;
+}
+
+const char *getRenderModeDescription(RenderMode id) {
+ const RenderModeDescription *l = g_renderModes;
+ for (; l->code; ++l) {
+ if (l->id == id)
+ return l->description;
+ }
+ return 0;
+}
+
} // End of namespace Common
diff --git a/common/util.h b/common/util.h
index 8813fc9d8b..173f2bf835 100644
--- a/common/util.h
+++ b/common/util.h
@@ -147,12 +147,42 @@ struct PlatformDescription {
extern const PlatformDescription g_platforms[];
-
/** Convert a string containing a platform name into a Platform enum value. */
extern Platform parsePlatform(const String &str);
extern const char *getPlatformCode(Platform id);
extern const char *getPlatformDescription(Platform id);
+/**
+ * List of render modes. It specifies which original graphics mode
+ * to use. Some targets used postprocessing dithering routines for
+ * reducing color depth of final image which let it to be rendered on
+ * such low-level adapters as CGA or Hercules.
+ */
+enum RenderMode {
+ kRenderDefault = -1,
+ kRenderEGA = 1,
+ kRenderCGA = 2,
+ kRenderHerc = 3
+};
+
+enum HerculesDimesnions {
+ kHercW = 720,
+ kHercH = 350
+};
+
+struct RenderModeDescription {
+ const char *code;
+ const char *description;
+ Common::RenderMode id;
+};
+
+extern const RenderModeDescription g_renderModes[];
+
+/** Convert a string containing a render mode name into a RenderingMode enum value. */
+extern RenderMode parseRenderMode(const String &str);
+extern const char *getRenderModeCode(RenderMode id);
+extern const char *getRenderModeDescription(RenderMode id);
+
} // End of namespace Common
diff --git a/doc/05_01.tex b/doc/05_01.tex
index ca15fa915f..93bb87a7d4 100644
--- a/doc/05_01.tex
+++ b/doc/05_01.tex
@@ -39,6 +39,7 @@ Usage: scummvm [OPTIONS]... [GAME]\\
--native-mt32 &True Roland MT-32 (disable GM emulation)\\
--output-rate=RATE &Select output sample rate in Hz (e.g. 22050)\\
--aspect-ratio &Enable aspect ratio correction\\
+ --render-mode=MODE &Enable additional render modes (cga, ega, hercules)\\
\\
--alt-intro &Use alternative intro for CD versions of Beneath a\\
&Steel Sky and Flight of the Amazon Queen\\
diff --git a/gui/options.cpp b/gui/options.cpp
index da2fc3c084..41dbcae9ea 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -75,7 +75,7 @@ OptionsDialog::OptionsDialog(const String &domain, int x, int y, int w, int h)
: Dialog(x, y, w, h),
_domain(domain),
_enableGraphicSettings(false),
- _gfxPopUp(0), _fullscreenCheckbox(0), _aspectCheckbox(0),
+ _gfxPopUp(0), _renderModePopUp(0), _fullscreenCheckbox(0), _aspectCheckbox(0),
_enableAudioSettings(false),
_multiMidiCheckbox(0), _mt32Checkbox(0), _subCheckbox(0),
_enableVolumeSettings(false),
@@ -108,6 +108,19 @@ void OptionsDialog::open() {
}
}
+ _renderModePopUp->setSelected(0);
+
+ if (ConfMan.hasKey("render_mode", _domain)) {
+ const Common::RenderModeDescription *p = Common::g_renderModes;
+ const Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get("render_mode", _domain));
+ int sel = 0;
+ for (int i = 0; p->code; ++p, ++i) {
+ if (renderMode == p->id)
+ sel = i + 2;
+ }
+ _renderModePopUp->setSelected(sel);
+ }
+
#ifndef _WIN32_WCE
// Fullscreen setting
_fullscreenCheckbox->setState(ConfMan.getBool("fullscreen", _domain));
@@ -167,10 +180,14 @@ void OptionsDialog::close() {
if ((int32)_gfxPopUp->getSelectedTag() >= 0)
ConfMan.set("gfx_mode", _gfxPopUp->getSelectedString(), _domain);
+
+ if ((int32)_renderModePopUp->getSelectedTag() >= 0)
+ ConfMan.set("render_mode", _renderModePopUp->getSelectedString(), _domain);
} else {
ConfMan.removeKey("fullscreen", _domain);
ConfMan.removeKey("aspect_ratio", _domain);
ConfMan.removeKey("gfx_mode", _domain);
+ ConfMan.removeKey("render_mode", _domain);
}
}
@@ -240,6 +257,7 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) {
_enableGraphicSettings = enabled;
_gfxPopUp->setEnabled(enabled);
+ _renderModePopUp->setEnabled(enabled);
#ifndef _WIN32_WCE
_fullscreenCheckbox->setEnabled(enabled);
_aspectCheckbox->setEnabled(enabled);
@@ -282,6 +300,16 @@ int OptionsDialog::addGraphicControls(GuiObject *boss, int yoffset) {
gm++;
}
+ // RenderMode popup
+ _renderModePopUp = new PopUpWidget(boss, x-5, yoffset, w+5, kLineHeight, "Render mode: ", 100);
+ yoffset += 16;
+ _renderModePopUp->appendEntry("<default>");
+ _renderModePopUp->appendEntry("");
+ const Common::RenderModeDescription *rm = Common::g_renderModes;
+ for (; rm->code; ++rm) {
+ _renderModePopUp->appendEntry(rm->description, rm->id);
+ }
+
// Fullscreen checkbox
_fullscreenCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Fullscreen mode");
yoffset += 16;
diff --git a/gui/options.h b/gui/options.h
index 5b2e34ccea..497e216ed5 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -71,6 +71,7 @@ private:
PopUpWidget *_gfxPopUp;
CheckboxWidget *_fullscreenCheckbox;
CheckboxWidget *_aspectCheckbox;
+ PopUpWidget *_renderModePopUp;
//
// Audio controls
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) {