KYRA: add 16bit mode required for EOB II FM-TOWNS

This commit is contained in:
athrxx 2016-01-09 21:57:47 +01:00
parent e4e5e68f0d
commit 16ead6f58a
6 changed files with 581 additions and 199 deletions

View file

@ -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 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, 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 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, 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 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, 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 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, 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 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, Kyra::GI_EOB1)
#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_EOB2)
#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[] = {

View file

@ -122,6 +122,7 @@ struct GameFlags {
bool isOldFloppy : 1;
bool useHiRes : 1;
bool use16ColorMode : 1;
bool useHiColorMode : 1;
bool useDigSound : 1;
bool useInstallerPackage : 1;

View file

@ -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);
}
}
_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;
}
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) {
byte *dstL1 = dst;
byte *dstL2 = dst + dstPitch;
int srcBpp = _bytesPerPixel;
int dstBpp = _useHiColorScreen ? 2 : 1;
int dstAdd = dstPitch * 2 - w * 2;
int srcAdd = srcPitch - w;
byte *dstL1 = dst;
byte *dstL2 = dst + dstPitch * dstBpp;
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);

View file

@ -93,6 +93,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.
*
@ -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();
@ -275,6 +282,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.
*/
@ -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;

View file

@ -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];
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];
if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) {
color1 &= 0x0F;
color2 &= 0x0F;
}
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)

View file

@ -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;