aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorathrxx2016-01-09 21:57:47 +0100
committerathrxx2018-11-14 17:22:21 +0100
commit16ead6f58a041adaa7fedb9f08d8435fff24f3ae (patch)
tree48bf87116d4831a24e9ee82499b9902671da5ee8 /engines
parente4e5e68f0dbec85bb28157e094a95ef33440a2ba (diff)
downloadscummvm-rg350-16ead6f58a041adaa7fedb9f08d8435fff24f3ae.tar.gz
scummvm-rg350-16ead6f58a041adaa7fedb9f08d8435fff24f3ae.tar.bz2
scummvm-rg350-16ead6f58a041adaa7fedb9f08d8435fff24f3ae.zip
KYRA: add 16bit mode required for EOB II FM-TOWNS
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/detection_tables.h81
-rw-r--r--engines/kyra/kyra_v1.h1
-rw-r--r--engines/kyra/screen.cpp366
-rw-r--r--engines/kyra/screen.h41
-rw-r--r--engines/kyra/screen_eob.cpp293
-rw-r--r--engines/kyra/screen_eob.h6
6 files changed, 585 insertions, 203 deletions
diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
index 43dc0cc881..0b45977d22 100644
--- a/engines/kyra/detection_tables.h
+++ b/engines/kyra/detection_tables.h
@@ -22,45 +22,46 @@
namespace {
-#define FLAGS(x, y, z, a, b, c, d, e, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, id }
-#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, e, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, id }
-
-#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_KYRA1)
-#define KYRA1_OLDFLOPPY_FLAGS FLAGS(false, false, false, true, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, false, true, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
-#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, false, Kyra::GI_KYRA1)
-
-#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_KYRA2)
-#define KYRA2_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_KYRA2)
-
-#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, false, true, true, Kyra::GI_KYRA3)
-#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, false, true, false, Kyra::GI_KYRA3)
-#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, true, false, Kyra::GI_KYRA3)
-
-#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_LOL)
-#define LOL_PC9801_FLAGS FLAGS(false, false, false, false, true, true, false, false, Kyra::GI_LOL)
-#define LOL_FMTOWNS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_LOL)
-#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, false, Kyra::GI_LOL)
-#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
-
-#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_EOB1)
-#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_EOB2)
+#define EOB2_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_EOB2)
+#define FLAGS(x, y, z, a, b, c, d, e, f, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, f, id }
+#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, e, f, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, f, id }
+
+#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, false, true, Kyra::GI_KYRA1)
+#define KYRA1_OLDFLOPPY_FLAGS FLAGS(false, false, false, true, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, false, true, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, false, Kyra::GI_KYRA1)
+#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, false, false, Kyra::GI_KYRA1)
+
+#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, false, true, Kyra::GI_KYRA2)
+#define KYRA2_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, false, Kyra::GI_KYRA2)
+
+#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, false, false, true, true, Kyra::GI_KYRA3)
+#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, false, false, true, false, Kyra::GI_KYRA3)
+#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, true, false, Kyra::GI_KYRA3)
+
+#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, false, true, Kyra::GI_LOL)
+#define LOL_PC9801_FLAGS FLAGS(false, false, false, false, true, true, false, false, false, Kyra::GI_LOL)
+#define LOL_FMTOWNS_FLAGS FLAGS(false, false, false, false, true, false, false, false, false, Kyra::GI_LOL)
+#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2)
+
+#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_EOB1)
+#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_EOB2)
#define GAMEOPTION_KYRA3_AUDIENCE GUIO_GAMEOPTIONS1
#define GAMEOPTION_KYRA3_SKIP GUIO_GAMEOPTIONS2
@@ -1685,7 +1686,7 @@ const KYRAGameDescription adGameDescs[] = {
},
#endif // ENABLE_EOB
- { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0) }
+ { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) }
};
const PlainGameDescriptor gameList[] = {
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index bbbd59a4b8..9fdddb89a9 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -122,6 +122,7 @@ struct GameFlags {
bool isOldFloppy : 1;
bool useHiRes : 1;
bool use16ColorMode : 1;
+ bool useHiColorMode : 1;
bool useDigSound : 1;
bool useInstallerPackage : 1;
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index bce45b2514..a0cab913b9 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -58,6 +58,13 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co
_renderMode = Common::kRenderDefault;
_sjisMixedFontMode = false;
+ _useHiColorScreen = _vm->gameFlags().useHiColorMode;
+ _screenPageSize = SCREEN_PAGE_SIZE;
+ _16bitPalette = 0;
+ _16bitConversionPalette = 0;
+ _16bitShadingLevel = 0;
+ _bytesPerPixel = 1;
+
_currentFont = FID_8_FNT;
_paletteChanged = true;
_curDim = 0;
@@ -76,6 +83,8 @@ Screen::~Screen() {
delete _internFadePalette;
delete[] _decodeShapeBuffer;
delete[] _animBlockPtr;
+ delete[] _16bitPalette;
+ delete[] _16bitConversionPalette;
for (uint i = 0; i < _palettes.size(); ++i)
delete _palettes[i];
@@ -127,7 +136,17 @@ bool Screen::init() {
_sjisInvisibleColor = (_vm->game() == GI_KYRA1) ? 0x80 : 0xF6;
_sjisMixedFontMode = !_use16ColorMode;
- for (int i = 0; i < SCREEN_OVLS_NUM; ++i) {
+ if (!_sjisOverlayPtrs[0]) {
+ // We alway assume 2 bytes per pixel here when the backend is in hicolor mode, since this is the surface that is passed to the backend.
+ // We do this regardsless of the paramater sent to enableHiColorMode() so as not to have to change the backend color mode.
+ // Conversions from 8bit to 16bit have to take place when copying data to this surface here.
+ int bpp = _useHiColorScreen ? 2 : 1;
+ _sjisOverlayPtrs[0] = new uint8[SCREEN_OVL_SJIS_SIZE * bpp];
+ assert(_sjisOverlayPtrs[0]);
+ memset(_sjisOverlayPtrs[0], _sjisInvisibleColor, SCREEN_OVL_SJIS_SIZE * bpp);
+ }
+
+ for (int i = 1; i < SCREEN_OVLS_NUM; ++i) {
if (!_sjisOverlayPtrs[i]) {
_sjisOverlayPtrs[i] = new uint8[SCREEN_OVL_SJIS_SIZE];
assert(_sjisOverlayPtrs[i]);
@@ -147,27 +166,7 @@ bool Screen::init() {
_curPage = 0;
- Common::Array<uint8> realPages;
- for (int i = 0; i < SCREEN_PAGE_NUM; i++) {
- if (Common::find(realPages.begin(), realPages.end(), _pageMapping[i]) == realPages.end())
- realPages.push_back(_pageMapping[i]);
- }
-
- int numPages = realPages.size();
- uint32 bufferSize = numPages * SCREEN_PAGE_SIZE;
-
- uint8 *pagePtr = new uint8[bufferSize];
- memset(pagePtr, 0, bufferSize);
-
- memset(_pagePtrs, 0, sizeof(_pagePtrs));
- for (int i = 0; i < SCREEN_PAGE_NUM; i++) {
- if (_pagePtrs[_pageMapping[i]]) {
- _pagePtrs[i] = _pagePtrs[_pageMapping[i]];
- } else {
- _pagePtrs[i] = pagePtr;
- pagePtr += SCREEN_PAGE_SIZE;
- }
- }
+ enableHiColorMode(false);
memset(_shapePages, 0, sizeof(_shapePages));
@@ -223,6 +222,7 @@ bool Screen::init() {
_charOffset = 0;
for (int i = 0; i < ARRAYSIZE(_textColorsMap); ++i)
_textColorsMap[i] = i;
+ _textColorsMap16bit[0] = _textColorsMap16bit[1] = 0;
_decodeShapeBuffer = NULL;
_decodeShapeBufferSize = 0;
_animBlockPtr = NULL;
@@ -249,8 +249,9 @@ bool Screen::enableScreenDebug(bool enable) {
}
void Screen::setResolution() {
- byte palette[3*256];
- _system->getPaletteManager()->grabPalette(palette, 0, 256);
+ byte palette[3 * 256];
+ if (!_useHiColorScreen)
+ _system->getPaletteManager()->grabPalette(palette, 0, 256);
int width = 320, height = 200;
@@ -268,9 +269,49 @@ void Screen::setResolution() {
width = 320;
}
- initGraphics(width, height);
+ if (_useHiColorScreen) {
+ Graphics::PixelFormat px(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ Common::List<Graphics::PixelFormat> tryModes = _system->getSupportedFormats();
+ for (Common::List<Graphics::PixelFormat>::iterator g = tryModes.begin(); g != tryModes.end(); ++g) {
+ if (g->bytesPerPixel != 2 || g->aBits()) {
+ g = tryModes.reverse_erase(g);
+ } else if (*g == px) {
+ tryModes.clear();
+ tryModes.push_back(px);
+ break;
+ }
+ }
+ initGraphics(width, height, tryModes);
+ if (_system->getScreenFormat().bytesPerPixel != 2)
+ error("Required graphics mode not supported by platform.");
+
+ } else {
+ initGraphics(width, height);
+ _system->getPaletteManager()->setPalette(palette, 0, 256);
+ }
+}
+
+void Screen::enableHiColorMode(bool enabled) {
+ if (_useHiColorScreen && enabled) {
+ if (!_16bitPalette)
+ _16bitPalette = new uint16[1024];
+ memset(_16bitPalette, 0, 1024 * sizeof(uint16));
+ delete[] _16bitConversionPalette;
+ _16bitConversionPalette = 0;
+ _bytesPerPixel = 2;
+ } else {
+ if (_useHiColorScreen) {
+ if (!_16bitConversionPalette)
+ _16bitConversionPalette = new uint16[256];
+ memset(_16bitConversionPalette, 0, 256 * sizeof(uint16));
+ }
+
+ delete[] _16bitPalette;
+ _16bitPalette = 0;
+ _bytesPerPixel = 1;
+ }
- _system->getPaletteManager()->setPalette(palette, 0, 256);
+ resetPagePtrsAndBuffers(SCREEN_PAGE_SIZE * _bytesPerPixel);
}
void Screen::updateScreen() {
@@ -386,22 +427,22 @@ void Screen::updateDirtyRectsOvl() {
if (_forceFullUpdate) {
const byte *src = getCPagePtr(0);
byte *dst = _sjisOverlayPtrs[0];
-
scale2x(dst, 640, src, SCREEN_W, SCREEN_W, SCREEN_H);
mergeOverlay(0, 0, 640, 400);
- _system->copyRectToScreen(dst, 640, 0, 0, 640, 400);
+ _system->copyRectToScreen(dst, _useHiColorScreen ? 1280 : 640, 0, 0, 640, 400);
} else {
const byte *page0 = getCPagePtr(0);
byte *ovl0 = _sjisOverlayPtrs[0];
+ int dstBpp = _useHiColorScreen ? 2 : 1;
Common::List<Common::Rect>::iterator it;
for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) {
- byte *dst = ovl0 + it->top * 1280 + (it->left<<1);
- const byte *src = page0 + it->top * SCREEN_W + it->left;
+ byte *dst = ovl0 + it->top * 1280 * dstBpp + (it->left << dstBpp);
+ const byte *src = page0 + it->top * SCREEN_W * _bytesPerPixel + it->left * _bytesPerPixel;
scale2x(dst, 640, src, SCREEN_W, it->width(), it->height());
mergeOverlay(it->left<<1, it->top<<1, it->width()<<1, it->height()<<1);
- _system->copyRectToScreen(dst, 640, it->left<<1, it->top<<1, it->width()<<1, it->height()<<1);
+ _system->copyRectToScreen(dst, _useHiColorScreen ? 1280 : 640, it->left << 1, it->top << 1, it->width() << 1, it->height() << 1);
}
}
@@ -410,18 +451,31 @@ void Screen::updateDirtyRectsOvl() {
}
void Screen::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) {
+ int srcBpp = _bytesPerPixel;
+ int dstBpp = _useHiColorScreen ? 2 : 1;
+
byte *dstL1 = dst;
- byte *dstL2 = dst + dstPitch;
+ byte *dstL2 = dst + dstPitch * dstBpp;
- int dstAdd = dstPitch * 2 - w * 2;
- int srcAdd = srcPitch - w;
+ int dstAdd = (dstPitch * 2 - w * 2) * dstBpp;
+ int srcAdd = (srcPitch - w) * srcBpp;
+ int dstInc = 2 * dstBpp;
while (h--) {
- for (int x = 0; x < w; ++x, dstL1 += 2, dstL2 += 2) {
- uint16 col = *src++;
- col |= col << 8;
- *(uint16 *)(dstL1) = col;
- *(uint16 *)(dstL2) = col;
+ for (int x = 0; x < w; x++, src += srcBpp, dstL1 += dstInc, dstL2 += dstInc) {
+ if (dstBpp == 1) {
+ uint16 col = *src;
+ col |= col << 8;
+ *(uint16 *)(dstL1) = *(uint16 *)(dstL2) = col;
+ } else if (dstBpp == srcBpp) {
+ uint32 col = *(const uint16 *)src;
+ col |= col << 16;
+ *(uint32 *)(dstL1) = *(uint32 *)(dstL2) = col;
+ } else if (dstBpp == 2) {
+ uint32 col = _16bitConversionPalette[*src];
+ col |= col << 16;
+ *(uint32 *)(dstL1) = *(uint32 *)(dstL2) = col;
+ }
}
dstL1 += dstAdd; dstL2 += dstAdd;
src += srcAdd;
@@ -429,18 +483,24 @@ void Screen::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int
}
void Screen::mergeOverlay(int x, int y, int w, int h) {
- byte *dst = _sjisOverlayPtrs[0] + y * 640 + x;
+ int bpp = _useHiColorScreen ? 2 : 1;
+ byte *dst = _sjisOverlayPtrs[0] + y * 640 * bpp + x * bpp;
const byte *src = _sjisOverlayPtrs[1] + y * 640 + x;
+ uint16 *p16 = _16bitPalette ? _16bitPalette : (_16bitConversionPalette ? _16bitConversionPalette : 0);
int add = 640 - w;
while (h--) {
- for (x = 0; x < w; ++x, ++dst) {
+ for (x = 0; x < w; ++x, dst += bpp) {
byte col = *src++;
- if (col != _sjisInvisibleColor)
- *dst = col;
+ if (col != _sjisInvisibleColor) {
+ if (bpp == 2)
+ *(uint16*)dst = p16[col];
+ else
+ *dst = col;
+ }
}
- dst += add;
+ dst += add * bpp;
src += add;
}
}
@@ -468,6 +528,35 @@ void Screen::setScreenDim(int dim) {
_curDimIndex = dim;
}
+void Screen::resetPagePtrsAndBuffers(int pageSize) {
+ _screenPageSize = pageSize;
+
+ delete[] _pagePtrs[0];
+ memset(_pagePtrs, 0, sizeof(_pagePtrs));
+
+ Common::Array<uint8> realPages;
+ for (int i = 0; i < SCREEN_PAGE_NUM; i++) {
+ if (Common::find(realPages.begin(), realPages.end(), _pageMapping[i]) == realPages.end())
+ realPages.push_back(_pageMapping[i]);
+ }
+
+ int numPages = realPages.size();
+ uint32 bufferSize = numPages * _screenPageSize;
+
+ uint8 *pagePtr = new uint8[bufferSize];
+ memset(pagePtr, 0, bufferSize);
+
+ memset(_pagePtrs, 0, sizeof(_pagePtrs));
+ for (int i = 0; i < SCREEN_PAGE_NUM; i++) {
+ if (_pagePtrs[_pageMapping[i]]) {
+ _pagePtrs[i] = _pagePtrs[_pageMapping[i]];
+ } else {
+ _pagePtrs[i] = pagePtr;
+ pagePtr += _screenPageSize;
+ }
+ }
+}
+
uint8 *Screen::getPagePtr(int pageNum) {
assert(pageNum < SCREEN_PAGE_NUM);
return _pagePtrs[pageNum];
@@ -489,7 +578,7 @@ void Screen::clearPage(int pageNum) {
assert(pageNum < SCREEN_PAGE_NUM);
if (pageNum == 0 || pageNum == 1)
_forceFullUpdate = true;
- memset(getPagePtr(pageNum), 0, SCREEN_PAGE_SIZE);
+ memset(getPagePtr(pageNum), 0, _screenPageSize);
clearOverlayPage(pageNum);
}
@@ -503,7 +592,7 @@ int Screen::setCurPage(int pageNum) {
void Screen::clearCurPage() {
if (_curPage == 0 || _curPage == 1)
_forceFullUpdate = true;
- memset(getPagePtr(_curPage), 0, SCREEN_PAGE_SIZE);
+ memset(getPagePtr(_curPage), 0, _screenPageSize);
clearOverlayPage(_curPage);
}
@@ -670,9 +759,13 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {
color &= 0x03;
} else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) {
color &= 0x0F;
+ }
+
+ if (_bytesPerPixel == 2) {
+ *(uint16*)(&_pagePtrs[pageNum][y * SCREEN_W * 2 + x * 2]) = _16bitPalette[color];
+ } else {
+ _pagePtrs[pageNum][y * SCREEN_W + x] = color;
}
-
- _pagePtrs[pageNum][y * SCREEN_W + x] = color;
}
void Screen::fadeFromBlack(int delay, const UpdateFunctor *upFunc) {
@@ -707,6 +800,8 @@ void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upF
if (upFunc && upFunc->isValid())
(*upFunc)();
+ else if (_useHiColorScreen)
+ updateScreen();
else
_system->updateScreen();
@@ -821,6 +916,22 @@ void Screen::setScreenPalette(const Palette &pal) {
}
_paletteChanged = true;
+
+ if (_useHiColorScreen) {
+ if (_16bitPalette)
+ memcpy(_16bitPalette, pal.getData(), 512);
+
+ // Generate 16bit palette for the 8bit/16 bit conversion in scale2x()
+ if (_16bitConversionPalette) {
+ Graphics::PixelFormat pixelFormat = _system->getScreenFormat();
+ for (int i = 0; i < 256; ++i)
+ _16bitConversionPalette[i] = pixelFormat.RGBToColor(screenPal[i * 3], screenPal[i * 3 + 1], screenPal[i * 3 + 2]);
+ // The whole Surface has to be converted again after each palette chance
+ _forceFullUpdate = true;
+ }
+ return;
+ }
+
_system->getPaletteManager()->setPalette(screenPal, 0, pal.getNumColors());
}
@@ -908,8 +1019,8 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
h = SCREEN_H - y2;
}
- const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W + x1;
- uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W + x2;
+ const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel;
+ uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W * _bytesPerPixel + x2 * _bytesPerPixel;
if (src == dst)
return;
@@ -921,18 +1032,24 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag
if (flags & CR_NO_P_CHECK) {
while (h--) {
- memmove(dst, src, w);
- src += SCREEN_W;
- dst += SCREEN_W;
+ memmove(dst, src, w * _bytesPerPixel);
+ src += SCREEN_W * _bytesPerPixel;
+ dst += SCREEN_W * _bytesPerPixel;
}
} else {
while (h--) {
for (int i = 0; i < w; ++i) {
- if (src[i])
- dst[i] = src[i];
+ if (_bytesPerPixel == 2) {
+ uint px = *(const uint16*)&src[i << 1];
+ if (px)
+ *(uint16*)&dst[i << 1] = px;
+ } else {
+ if (src[i])
+ dst[i] = src[i];
+ }
}
- src += SCREEN_W;
- dst += SCREEN_W;
+ src += SCREEN_W * _bytesPerPixel;
+ dst += SCREEN_W * _bytesPerPixel;
}
}
}
@@ -960,14 +1077,14 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *
uint8 *pagePtr = getPagePtr(pageNum);
for (int i = y; i < y + h; ++i)
- memcpy(dest + (i - y) * w, pagePtr + i * SCREEN_W + x, w);
+ memcpy(dest + (i - y) * w * _bytesPerPixel, pagePtr + i * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel, w * _bytesPerPixel);
}
void Screen::copyPage(uint8 srcPage, uint8 dstPage) {
uint8 *src = getPagePtr(srcPage);
uint8 *dst = getPagePtr(dstPage);
if (src != dst)
- memcpy(dst, src, SCREEN_W * SCREEN_H);
+ memcpy(dst, src, SCREEN_W * SCREEN_H * _bytesPerPixel);
copyOverlayRegion(0, 0, 0, 0, SCREEN_W, SCREEN_H, srcPage, dstPage);
if (dstPage == 0 || dstPage == 1)
@@ -994,7 +1111,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint
if (w < 0 || h < 0)
return;
- uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W + x;
+ uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel;
if (pageNum == 0 || pageNum == 1)
addDirtyRect(x, y, w, h);
@@ -1002,9 +1119,9 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint
clearOverlayRect(pageNum, x, y, w, h);
while (h--) {
- memcpy(dst, src, w);
- dst += SCREEN_W;
- src += w;
+ memcpy(dst, src, w * _bytesPerPixel);
+ dst += SCREEN_W * _bytesPerPixel;
+ src += w * _bytesPerPixel;
}
}
@@ -1066,10 +1183,11 @@ void Screen::shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPag
void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum, bool xored) {
assert(x2 < SCREEN_W && y2 < SCREEN_H);
+ uint16 color16 = 0;
if (pageNum == -1)
pageNum = _curPage;
- uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W + x1;
+ uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel;
if (pageNum == 0 || pageNum == 1)
addDirtyRect(x1, y1, x2-x1+1, y2-y1+1);
@@ -1083,9 +1201,11 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
color &= 0x03;
} else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) {
color &= 0x0F;
- }
+ } else if (_bytesPerPixel == 2)
+ color16 = shade16bitColor(_16bitPalette[color]);
if (xored) {
+ // no 16 bit support for this (unneeded)
for (; y1 <= y2; ++y1) {
for (int x = x1; x <= x2; ++x)
dst[x] ^= color;
@@ -1093,8 +1213,14 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,
}
} else {
for (; y1 <= y2; ++y1) {
- memset(dst, color, x2 - x1 + 1);
- dst += SCREEN_W;
+ if (_bytesPerPixel == 2) {
+ uint16 *ptr = (uint16*)dst;
+ for (int i = 0; i < x2 - x1 + 1; i++)
+ *ptr++ = color16;
+ } else {
+ memset(dst, color, x2 - x1 + 1);
+ }
+ dst += SCREEN_W * _bytesPerPixel;
}
}
}
@@ -1151,7 +1277,7 @@ void Screen::drawClippedLine(int x1, int y1, int x2, int y2, int color) {
}
void Screen::drawLine(bool vertical, int x, int y, int length, int color) {
- uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W + x;
+ uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel;
if (_use16ColorMode) {
color &= 0x0F;
@@ -1160,19 +1286,30 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) {
color &= 0x03;
} else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) {
color &= 0x0F;
- }
+ } else if (_bytesPerPixel == 2)
+ color = shade16bitColor(_16bitPalette[color]);
if (vertical) {
assert((y + length) <= SCREEN_H);
int currLine = 0;
while (currLine < length) {
- *ptr = color;
- ptr += SCREEN_W;
+ if (_bytesPerPixel == 2)
+ *(uint16*)ptr = color;
+ else
+ *ptr = color;
+ ptr += SCREEN_W * _bytesPerPixel;
currLine++;
}
} else {
assert((x + length) <= SCREEN_W);
- memset(ptr, color, length);
+ if (_bytesPerPixel == 2) {
+ for (int i = 0; i < length; i++) {
+ *(uint16*)ptr = color;
+ ptr += 2;
+ }
+ } else {
+ memset(ptr, color, length);
+ }
}
if (_curPage == 0 || _curPage == 1)
@@ -1189,14 +1326,25 @@ void Screen::setAnimBlockPtr(int size) {
_animBlockSize = size;
}
-void Screen::setTextColor(const uint8 *cmap, int a, int b) {
- memcpy(&_textColorsMap[a], cmap, b-a+1);
+void Screen::setTextColor(const uint8 *cmap8, int a, int b) {
+ memcpy(&_textColorsMap[a], cmap8, (b - a + 1));
+ // We need to update the color tables of all fonts, we
+ // setup so far here.
+ for (int i = 0; i < FID_NUM; ++i) {
+ if (_fonts[i])
+ _fonts[i]->setColorMap(_textColorsMap);
+ }
+}
+void Screen::setTextColor16bit(const uint16 *cmap16) {
+ assert(cmap16);
+ _textColorsMap16bit[0] = cmap16[0];
+ _textColorsMap16bit[1] = cmap16[1];
// We need to update the color tables of all fonts, we
// setup so far here.
for (int i = 0; i < FID_NUM; ++i) {
if (_fonts[i])
- _fonts[i]->setColorMap(_textColorsMap);
+ _fonts[i]->set16bitColorMap(_textColorsMap16bit);
}
}
@@ -1281,10 +1429,17 @@ int Screen::getTextWidth(const char *str) {
}
void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2) {
- uint8 cmap[2];
- cmap[0] = color2;
- cmap[1] = color1;
- setTextColor(cmap, 0, 1);
+ uint16 cmap16[2];
+ if (_16bitPalette) {
+ cmap16[0] = color2 ? shade16bitColor(_16bitPalette[color2]) : 0xFFFF;
+ cmap16[1] = _16bitPalette[color1];
+ setTextColor16bit(cmap16);
+ }
+
+ uint8 cmap8[2];
+ cmap8[0] = color2;
+ cmap8[1] = color1;
+ setTextColor(cmap8, 0, 1);
FontId curFont = _currentFont;
@@ -1360,11 +1515,12 @@ void Screen::drawChar(uint16 c, int x, int y) {
return;
}
- destPage += (y * 2) * 640 + (x * 2);
+ int bpp = (_currentFont == Screen::FID_SJIS_FNT) ? 1 : 2;
+ destPage += (y * 2) * 640 * bpp + (x * 2 * bpp);
- fnt->drawChar(c, destPage, 640);
+ fnt->drawChar(c, destPage, 640, bpp);
} else {
- fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W + x, SCREEN_W);
+ fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel, SCREEN_W, _bytesPerPixel);
}
if (_curPage == 0 || _curPage == 1)
@@ -2846,6 +3002,18 @@ int16 Screen::encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size_to) {
return (to - toPtr);
}
+uint16 Screen::shade16bitColor(uint16 col) {
+ uint8 r = (col & 0x1f);
+ uint8 g = (col & 0x3E0) >> 5;
+ uint8 b = (col & 0x7C00) >> 10;
+
+ r = (r > _16bitShadingLevel) ? r - _16bitShadingLevel : 0;
+ g = (g > _16bitShadingLevel) ? g - _16bitShadingLevel : 0;
+ b = (b > _16bitShadingLevel) ? b - _16bitShadingLevel : 0;
+
+ return (b << 10) | (g << 5) | r;
+}
+
void Screen::hideMouse() {
++_mouseLockCount;
CursorMan.showMouse(false);
@@ -3072,7 +3240,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette
uint8 *srcPtr = srcData + 10 + palSize;
uint8 *dstData = getPagePtr(dstPage);
- memset(dstData, 0, SCREEN_PAGE_SIZE);
+ memset(dstData, 0, _screenPageSize);
if (dstPage == 0 || tempPage == 0)
_forceFullUpdate = true;
@@ -3117,7 +3285,7 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {
debugC(3, kDebugLevelScreen, "Screen::loadPalette('%s', %p)", filename, (const void *)&pal);
- const int maxCols = pal.getNumColors();
+ const int maxCols = _16bitPalette ? 256 : pal.getNumColors();
int numCols = 0;
if (_isAmiga) {
@@ -3133,8 +3301,15 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {
numCols /= Palette::kVGABytesPerColor;
pal.loadVGAPalette(*stream, 0, numCols);
} else {
- numCols = stream->size() / Palette::kVGABytesPerColor;
- pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols));
+ if (_bytesPerPixel == 2) {
+ numCols = stream->size() / 2;
+ pal.loadHiColorPalette(*stream, 0, numCols);
+ } else if (!_16bitPalette) {
+ numCols = stream->size() / Palette::kVGABytesPerColor;
+ pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols));
+ } else {
+ error("Screen::loadPalette(): Failed to load file '%s' with invalid size %d in HiColor mode", filename, stream->size());
+ }
}
if (numCols > maxCols)
@@ -3407,7 +3582,7 @@ int DOSFont::getCharWidth(uint16 c) const {
return _widthTable[c];
}
-void DOSFont::drawChar(uint16 c, byte *dst, int pitch) const {
+void DOSFont::drawChar(uint16 c, byte *dst, int pitch, int) const {
if (c >= _numGlyphs)
return;
@@ -3549,7 +3724,7 @@ int AMIGAFont::getCharWidth(uint16 c) const {
return _chars[c].width;
}
-void AMIGAFont::drawChar(uint16 c, byte *dst, int pitch) const {
+void AMIGAFont::drawChar(uint16 c, byte *dst, int pitch, int) const {
if (c >= 255)
return;
@@ -3624,7 +3799,7 @@ void SJISFont::setColorMap(const uint8 *src) {
}
}
-void SJISFont::drawChar(uint16 c, byte *dst, int pitch) const {
+void SJISFont::drawChar(uint16 c, byte *dst, int pitch, int) const {
uint8 color1, color2;
if (_is16Color) {
@@ -3672,6 +3847,19 @@ void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int col
*pos++ = stream.readByte() & 0x3F;
}
+void Palette::loadHiColorPalette(Common::ReadStream &stream, int startIndex, int colors) {
+ uint16 *pos = (uint16*)(_palData + startIndex * 2);
+
+ Graphics::PixelFormat currentFormat = g_system->getScreenFormat();
+ Graphics::PixelFormat originalFormat(2, 5, 5, 5, 0, 5, 10, 0, 0);
+
+ for (int i = 0; i < colors; i++) {
+ uint8 r, g, b;
+ originalFormat.colorToRGB(stream.readUint16LE(), r, g, b);
+ *pos++ = currentFormat.RGBToColor(r, g, b);
+ }
+}
+
void Palette::loadEGAPalette(Common::ReadStream &stream, int startIndex, int colors) {
assert(startIndex + colors <= 16);
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index 0b287aa8bc..bac93ae49c 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -94,6 +94,11 @@ public:
virtual void setColorMap(const uint8 *src) = 0;
/**
+ * Sets a text 16bit palette map. Only used in in EOB II FM-Towns. The map contains 2 entries.
+ */
+ virtual void set16bitColorMap(const uint16 *src) {}
+
+ /**
* Draws a specific character.
*
* TODO/FIXME: Replace this with a nicer API. Currently
@@ -101,7 +106,7 @@ public:
* We use this API, since it's hard to assure dirty rect
* handling from outside Screen.
*/
- virtual void drawChar(uint16 c, byte *dst, int pitch) const = 0;
+ virtual void drawChar(uint16 c, byte *dst, int pitch, int bpp) const = 0;
};
/**
@@ -120,7 +125,7 @@ public:
int getWidth() const { return _width; }
int getCharWidth(uint16 c) const;
void setColorMap(const uint8 *src) { _colorMap = src; }
- void drawChar(uint16 c, byte *dst, int pitch) const;
+ void drawChar(uint16 c, byte *dst, int pitch, int) const;
private:
void unload();
@@ -153,8 +158,9 @@ public:
int getHeight() const { return _height; }
int getWidth() const { return _width; }
int getCharWidth(uint16 c) const;
- void setColorMap(const uint8 *src) { _colorMap = src; }
- void drawChar(uint16 c, byte *dst, int pitch) const;
+ void setColorMap(const uint8 *src) { _colorMap8bit = src; }
+ void set16bitColorMap(const uint16 *src) { _colorMap16bit = src; }
+ void drawChar(uint16 c, byte *dst, int pitch, int bpp) const;
private:
void unload();
@@ -163,7 +169,8 @@ private:
uint16 *_bitmapOffsets;
int _width, _height;
- const uint8 *_colorMap;
+ const uint8 *_colorMap8bit;
+ const uint16 *_colorMap16bit;
int _numGlyphs;
@@ -187,7 +194,7 @@ public:
int getWidth() const { return _width; }
int getCharWidth(uint16 c) const;
void setColorMap(const uint8 *src) {}
- void drawChar(uint16 c, byte *dst, int pitch) const;
+ void drawChar(uint16 c, byte *dst, int pitch, int) const;
private:
void unload();
@@ -221,7 +228,7 @@ public:
int getWidth() const;
int getCharWidth(uint16 c) const;
void setColorMap(const uint8 *src);
- virtual void drawChar(uint16 c, byte *dst, int pitch) const;
+ virtual void drawChar(uint16 c, byte *dst, int pitch, int) const;
protected:
void unload();
@@ -276,6 +283,11 @@ public:
void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors);
/**
+ * Load a HiColor palette from the given stream.
+ */
+ void loadHiColorPalette(Common::ReadStream &stream, int startIndex, int colors);
+
+ /**
* Load a EGA palette from the given stream.
*/
void loadEGAPalette(Common::ReadStream &stream, int startIndex, int colors);
@@ -423,6 +435,7 @@ public:
// init
virtual bool init();
virtual void setResolution();
+ virtual void enableHiColorMode(bool enabled);
void updateScreen();
@@ -499,6 +512,7 @@ public:
virtual void setTextColorMap(const uint8 *cmap) = 0;
void setTextColor(const uint8 *cmap, int a, int b);
+ void setTextColor16bit(const uint16 *cmap16);
const ScreenDim *getScreenDim(int dim) const;
void modifyScreenDim(int dim, int x, int y, int w, int h);
@@ -570,7 +584,10 @@ public:
// RPG specific, this does not belong here
void crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
+ void set16bitShadingLevel(int lvl) { _16bitShadingLevel = lvl; }
+
protected:
+ void resetPagePtrsAndBuffers(int pageSize);
uint8 *getPagePtr(int pageNum);
virtual void updateDirtyRects();
void updateDirtyRectsAmiga();
@@ -602,8 +619,11 @@ protected:
bool _useSJIS;
bool _use16ColorMode;
bool _useHiResEGADithering;
+ bool _useHiColorScreen;
bool _isAmiga;
Common::RenderMode _renderMode;
+ int _bytesPerPixel;
+ int _screenPageSize;
uint8 _sjisInvisibleColor;
bool _sjisMixedFontMode;
@@ -612,8 +632,15 @@ protected:
Common::Array<Palette *> _palettes;
Palette *_internFadePalette;
+ uint16 shade16bitColor(uint16 col);
+
+ uint16 *_16bitPalette;
+ uint16 *_16bitConversionPalette;
+ uint8 _16bitShadingLevel;
+
Font *_fonts[FID_NUM];
uint8 _textColorsMap[16];
+ uint16 _textColorsMap16bit[2];
uint8 *_decodeShapeBuffer;
int _decodeShapeBufferSize;
diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp
index 6553ffa76c..88c53fdb7b 100644
--- a/engines/kyra/screen_eob.cpp
+++ b/engines/kyra/screen_eob.cpp
@@ -46,6 +46,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,
_gfxX = _gfxY = 0;
_gfxCol = 0;
_dsTempPage = 0;
+ _convertHiColorBuffer = 0;
_dsDiv = 0;
_dsRem = 0;
_dsScaleTrans = 0;
@@ -60,6 +61,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,
Screen_EoB::~Screen_EoB() {
delete[] _dsTempPage;
+ delete[] _convertHiColorBuffer;
delete[] _cgaScaleTable;
delete[] _egaDitheringTable;
delete[] _egaDitheringTempPage;
@@ -74,6 +76,9 @@ bool Screen_EoB::init() {
_dsTempPage = new uint8[12000];
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ _convertHiColorBuffer = new uint8[SCREEN_H * SCREEN_W];
+ }
if (_vm->gameFlags().useHiRes && _renderMode == Common::kRenderEGA) {
_useHiResEGADithering = true;
_egaDitheringTable = new uint8[256];
@@ -120,11 +125,12 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : _cursorColorKey;
int scaleFactor = _useHiResEGADithering ? 2 : 1;
+ int bpp = _useHiColorScreen ? 2 : 1;
- uint8 *cursor = new uint8[mouseW * scaleFactor * mouseH * scaleFactor];
+ uint8 *cursor = new uint8[mouseW * scaleFactor * bpp * mouseH * scaleFactor];
// We use memset and copyBlockToPage instead of fillRect to make sure that the
// color key 0xFF doesn't get converted into EGA color
- memset(cursor, colorKey, mouseW * scaleFactor * mouseH * scaleFactor);
+ memset(cursor, colorKey, mouseW * scaleFactor * bpp * mouseH * scaleFactor);
copyBlockToPage(6, 0, 0, mouseW * scaleFactor, mouseH * scaleFactor, cursor);
drawShape(6, shape, 0, 0, 0, 2, ovl);
CursorMan.showMouse(false);
@@ -156,8 +162,13 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov
}
}
}
+
+ // Convert color key to 16 bit after drawing the mouse cursor.
+ // The cursor has been converted to 16 bit in scale2x().
+ colorKey = _16bitConversionPalette ? _16bitConversionPalette[colorKey] : colorKey;
+ Graphics::PixelFormat pixelFormat = _system->getScreenFormat();
- CursorMan.replaceCursor(cursor, mouseW * scaleFactor, mouseH * scaleFactor, x, y, colorKey);
+ CursorMan.replaceCursor(cursor, mouseW * scaleFactor, mouseH * scaleFactor, x, y, colorKey, false, &pixelFormat);
if (isMouseVisible())
CursorMan.showMouse(true);
delete[] cursor;
@@ -217,9 +228,13 @@ void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int te
}
}
- if (convertToPage == -1) {
+ if (convertToPage == -1)
return;
- } else if (convertToPage == 2 && _renderMode == Common::kRenderCGA) {
+
+ if (_16bitPalette)
+ convertToHiColor(destPage);
+
+ if (convertToPage == 2 && _renderMode == Common::kRenderCGA) {
convertPage(destPage, 4, cgaMapping);
copyRegion(0, 0, 0, 0, 320, 200, 4, 2, Screen::CR_NO_P_CHECK);
} else if (convertToPage == 0) {
@@ -262,7 +277,10 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping)
}
void Screen_EoB::setScreenPalette(const Palette &pal) {
- if (_useHiResEGADithering && pal.getNumColors() != 16) {
+ if (_bytesPerPixel == 2) {
+ for (int i = 0; i < 4; i++)
+ createFadeTable16bit((const uint16*)(pal.getData()), &_16bitPalette[i * 256], 0, i * 53);
+ }else if (_useHiResEGADithering && pal.getNumColors() != 16) {
generateEGADitheringTable(pal);
} else if (_renderMode == Common::kRenderEGA && pal.getNumColors() == 16) {
_screenPalette->copy(pal);
@@ -297,7 +315,26 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco
if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)
encode8bit = false;
- if (_renderMode == Common::kRenderCGA) {
+ if (_bytesPerPixel == 2) {
+ shapesize = h * (w << 3) + 4;
+ shp = new uint8[shapesize];
+ memset(shp, 0, shapesize);
+ uint8 *dst = shp;
+
+ *dst++ = 0;
+ *dst++ = (h & 0xFF);
+ *dst++ = (w & 0xFF);
+ *dst++ = (h & 0xFF);
+
+ w <<= 3;
+
+ for (int i = 0; i < h; ++i) {
+ memcpy(dst, src, w);
+ srcLineStart += SCREEN_W;
+ src = srcLineStart;
+ dst += w;
+ }
+ } else if (_renderMode == Common::kRenderCGA) {
if (cgaMapping)
generateCGADitheringTables(cgaMapping);
shapesize = h * (w << 2) + 4;
@@ -485,7 +522,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
}
va_end(args);
- dst += (_dsX1 << 3);
+ dst += (_dsX1 << (2 + _bytesPerPixel));
int16 dX = x - (_dsX1 << 3);
int16 dY = y;
int16 dW = _dsX2 - _dsX1;
@@ -506,7 +543,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
int pixelStep = (flags & 1) ? -1 : 1;
- if (pixelsPerByte == 1) {
+ if (pixelsPerByte < 2) {
uint16 marginLeft = 0;
uint16 marginRight = 0;
@@ -557,7 +594,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
marginRight = w2 - marginLeft - width;
}
- dst += (dY * SCREEN_W + dX);
+ dst += (dY * SCREEN_W * _bytesPerPixel + dX * _bytesPerPixel);
uint8 *dstL = dst;
if (pageNum == 0 || pageNum == 1)
@@ -567,36 +604,45 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
int16 xpos = (int16) marginLeft;
if (flags & 1) {
- for (int i = 0; i < w2; i++) {
- if (*src++ == 0) {
- i += (*src - 1);
- src += (*src - 1);
+ if (pixelsPerByte == 1) {
+ for (int i = 0; i < w2; i++) {
+ if (*src++ == 0) {
+ i += (*src - 1);
+ src += (*src - 1);
+ }
}
+ } else {
+ src += w2;
}
src--;
}
const uint8 *src2 = src;
if (xpos) {
- do {
- uint8 val = (flags & 1) ? *(src - 1) : *src;
- while (val && xpos) {
- src += pixelStep;
- xpos--;
- val = (flags & 1) ? *(src - 1) : *src;
- }
+ if (pixelsPerByte == 1) {
+ do {
+ uint8 val = (flags & 1) ? *(src - 1) : *src;
+ while (val && xpos) {
+ src += pixelStep;
+ xpos--;
+ val = (flags & 1) ? *(src - 1) : *src;
+ }
- val = (flags & 1) ? *(src - 1) : *src;
- if (!val) {
- src += pixelStep;
- uint8 bt = (flags & 1) ? src[1] : src[0];
- src += pixelStep;
- xpos = xpos - bt;
- }
- } while (xpos > 0);
+ val = (flags & 1) ? *(src - 1) : *src;
+ if (!val) {
+ src += pixelStep;
+ uint8 bt = (flags & 1) ? src[1] : src[0];
+ src += pixelStep;
+ xpos = xpos - bt;
+ }
+ } while (xpos > 0);
+ } else {
+ src += (xpos * pixelStep);
+ xpos = 0;
+ }
}
- dst -= xpos;
+ dst -= xpos * _bytesPerPixel;
xpos += width;
while (xpos > 0) {
@@ -606,37 +652,45 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
if (m) {
drawShapeSetPixel(dst, c);
- dst++;
+ dst += _bytesPerPixel;
xpos--;
- } else {
+ } else if (pixelsPerByte) {
uint8 len = (flags & 1) ? src[1] : src[0];
- dst += len;
+ dst += len * _bytesPerPixel;
xpos -= len;
src += pixelStep;
+ } else {
+ dst += _bytesPerPixel;
+ xpos--;
}
}
xpos += marginRight;
if (xpos) {
do {
- uint8 val = (flags & 1) ? *(src - 1) : *src;
- while (val && xpos) {
- src += pixelStep;
- xpos--;
- val = (flags & 1) ? *(src - 1) : *src;
- }
+ if (pixelsPerByte == 1) {
+ uint8 val = (flags & 1) ? *(src - 1) : *src;
+ while (val && xpos) {
+ src += pixelStep;
+ xpos--;
+ val = (flags & 1) ? *(src - 1) : *src;
+ }
- val = (flags & 1) ? *(src - 1) : *src;
- if (!val) {
- src += pixelStep;
- uint8 bt = (flags & 1) ? src[1] : src[0];
- src += pixelStep;
- xpos = xpos - bt;
+ val = (flags & 1) ? *(src - 1) : *src;
+ if (!val) {
+ src += pixelStep;
+ uint8 bt = (flags & 1) ? src[1] : src[0];
+ src += pixelStep;
+ xpos = xpos - bt;
+ }
+ } else {
+ src += (xpos * pixelStep);
+ xpos = 0;
}
} while (xpos > 0);
}
- dstL += SCREEN_W;
+ dstL += SCREEN_W * _bytesPerPixel;
dst = dstL;
if (flags & 1)
src = src2 + 1;
@@ -704,7 +758,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
if (d < width)
width = d;
- dst += (dY * SCREEN_W + dX);
+ dst += (dY * SCREEN_W * _bytesPerPixel + dX * _bytesPerPixel);
if (pageNum == 0 || pageNum == 1)
addDirtyRect(rX, rY, rW, rH);
@@ -753,11 +807,11 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
uint8 col = (pixelsPerByte == 2) ? pal[(in >> shift) & pixelPackingMask] : (*dst & ((trans >> shift) & (pixelPackingMask))) | pal[(in >> shift) & pixelPackingMask];
if (col || pixelsPerByte == 4)
drawShapeSetPixel(dst, col);
- dst++;
+ dst += _bytesPerPixel;
shift = ((shift - (pixelStep * pixelPacking)) & 7);
}
src += lineSrcStep;
- dst += pitch;
+ dst += (pitch * _bytesPerPixel);
}
}
}
@@ -1167,11 +1221,11 @@ void Screen_EoB::setFadeTable(const uint8 *table) {
_dsShapeFadingTable = table;
}
-void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
+void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
if (!palData)
return;
- uint8 *src = palData + 3 * rootColor;
+ const uint8 *src = palData + 3 * rootColor;
uint8 r = *src++;
uint8 g = *src++;
uint8 b = *src;
@@ -1189,7 +1243,7 @@ void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, ui
tmp = (uint16)((*src - b) * weight) << 1;
tb = *src++ - ((tmp >> 8) & 0xFF);
- uint8 *d = palData + 3;
+ const uint8 *d = palData + 3;
uint16 v = 0xFFFF;
uint8 col = rootColor;
@@ -1210,6 +1264,65 @@ void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, ui
}
}
+void Screen_EoB::createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16 rootColor, uint8 weight) {
+ uint8 r8 = (rootColor & 0x1f);
+ uint8 g8 = (rootColor & 0x3E0) >> 5;
+ uint8 b8 = (rootColor & 0x7C00) >> 10;
+
+ int root_r = r8 << 4;
+ int root_g = g8 << 4;
+ int root_b = b8 << 4;
+
+ *dst++ = palData[0];
+
+ for (uint8 i = 1; i; i++) {
+ r8 = (palData[i] & 0x1f);
+ g8 = (palData[i] & 0x3E0) >> 5;
+ b8 = (palData[i] & 0x7C00) >> 10;
+
+ int red = r8 << 4;
+ int green = g8 << 4;
+ int blue = b8 << 4;
+
+ if (red > root_r) {
+ red -= weight;
+ if (root_r > red)
+ red = root_r;
+ } else {
+ red += weight;
+ if (root_r < red)
+ red = root_r;
+ }
+
+ if (green > root_g) {
+ green -= weight;
+ if (root_g > green)
+ green = root_g;
+ } else {
+ green += weight;
+ if (root_g < green)
+ green = root_g;
+ }
+
+ if (blue > root_b) {
+ blue -= weight;
+ if (root_b > blue)
+ blue = root_b;
+ } else {
+ blue += weight;
+ if (root_b < blue)
+ blue = root_b;
+ }
+
+ r8 = red >> 4;
+ g8 = green >> 4;
+ b8 = blue >> 4;
+
+ *dst++ = (b8 << 10) | (g8 << 5) | r8;
+ }
+
+}
+
const uint16 *Screen_EoB::getCGADitheringTable(int index) {
return !(index & ~1) ? _cgaDitheringTables[index] : 0;
}
@@ -1218,6 +1331,40 @@ const uint8 *Screen_EoB::getEGADitheringTable() {
return _egaDitheringTable;
}
+void Screen_EoB::convertToHiColor(int page) {
+ if (!_16bitPalette)
+ return;
+ uint16 *dst = (uint16 *)getCPagePtr(page);
+ memcpy(_convertHiColorBuffer, dst, SCREEN_H * SCREEN_W);
+ uint8 *src = _convertHiColorBuffer;
+ for (int s = SCREEN_H * SCREEN_W; s; --s)
+ *dst++ = _16bitPalette[*src++];
+}
+
+void Screen_EoB::shadeRect(int x1, int y1, int x2, int y2, int shadingLevel) {
+ if (!_16bitPalette)
+ return;
+
+ int l = _16bitShadingLevel;
+ _16bitShadingLevel = shadingLevel;
+
+ if (_curPage == 0 || _curPage == 1)
+ addDirtyRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+
+ uint16 *dst = (uint16*)(getPagePtr(_curPage) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel);
+
+ for (; y1 < y2; ++y1) {
+ uint16 *ptr = dst;
+ for (int i = 0; i < x2 - x1; i++) {
+ *ptr = shade16bitColor(*ptr);
+ ptr++;
+ }
+ dst += SCREEN_W;
+ }
+
+ _16bitShadingLevel = l;
+}
+
void Screen_EoB::updateDirtyRects() {
if (!_useHiResEGADithering) {
Screen::updateDirtyRects();
@@ -1260,7 +1407,10 @@ void Screen_EoB::ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW
}
void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col) {
- if ((_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) {
+ if (_bytesPerPixel == 2) {
+ *(uint16*)dst = _16bitPalette[(_dsShapeFadingLevel << 8) + col];
+ return;
+ } else if ((_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) {
if (_dsBackgroundFading) {
if (_dsShapeFadingLevel) {
col = *dst;
@@ -1485,7 +1635,7 @@ int OldDOSFont::getCharWidth(uint16 c) const {
return _width;
}
-void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {
+void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch, int bpp) const {
static const uint8 renderMaskTable6[] = { 0xFC, 0x00, 0x7E, 0x00, 0x3F, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01, 0xF8 };
static const uint8 renderMaskTable8[] = { 0xFF, 0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE };
@@ -1536,24 +1686,28 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {
}
}
+ pitch *= bpp;
const uint8 *src = &_data[_bitmapOffsets[c]];
uint8 *dst2 = dst + pitch;
int w = (_width - 1) >> 3;
- pitch -= _width;
+ pitch -= _width * bpp;
- uint8 color1 = _colorMap[1];
- uint8 color2 = _colorMap[0];
+ uint16 color1 = _colorMap8bit[1];
+ uint16 color2 = _colorMap8bit[0];
- static const uint16 cgaColorMask[] = { 0, 0x5555, 0xAAAA, 0xFFFF };
- uint16 cgaMask1 = cgaColorMask[color1 & 3];
- uint16 cgaMask2 = cgaColorMask[color2 & 3];
-
- if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) {
+ if (bpp == 2) {
+ color1 = _colorMap16bit[1];
+ color2 = _colorMap16bit[0];
+ } else if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) {
color1 &= 0x0F;
color2 &= 0x0F;
}
+ static const uint16 cgaColorMask[] = { 0, 0x5555, 0xAAAA, 0xFFFF };
+ uint16 cgaMask1 = cgaColorMask[color1 & 3];
+ uint16 cgaMask2 = cgaColorMask[color2 & 3];
+
int cH = _height;
while (cH--) {
int cW = w;
@@ -1607,12 +1761,19 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {
}
if (s & i) {
- if (color1)
+ if (bpp == 2)
+ *(uint16*)dst = color1;
+ else if (color1)
*dst = color1;
- } else if (color2) {
- *dst = color2;
+ } else {
+ if (bpp == 2) {
+ if (color2 != 0xFFFF)
+ *(uint16*)dst = color2;
+ } else if (color2) {
+ *dst = color2;
+ }
}
- dst++;
+ dst += bpp;
}
if (cW)
diff --git a/engines/kyra/screen_eob.h b/engines/kyra/screen_eob.h
index 42c7e59e28..7c2a31e9d3 100644
--- a/engines/kyra/screen_eob.h
+++ b/engines/kyra/screen_eob.h
@@ -76,11 +76,14 @@ public:
int getRectSize(int w, int h);
void setFadeTable(const uint8 *table);
- void createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight);
+ void createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight);
+ void createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16 rootColor, uint8 weight);
const uint16 *getCGADitheringTable(int index);
const uint8 *getEGADitheringTable();
+ void convertToHiColor(int page);
+ void shadeRect(int x1, int y1, int x2, int y2, int shadingLevel);
private:
void updateDirtyRects();
void ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW, int srcH, int colorKey = -1);
@@ -106,6 +109,7 @@ private:
uint8 _shapeOverlay[16];
uint8 *_dsTempPage;
+ uint8 *_convertHiColorBuffer;
uint16 *_cgaDitheringTables[2];
const uint8 *_cgaMappingDefault;