aboutsummaryrefslogtreecommitdiff
path: root/scumm/gfx.cpp
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/gfx.cpp
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/gfx.cpp')
-rw-r--r--scumm/gfx.cpp111
1 files changed, 106 insertions, 5 deletions
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 -