aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/screen_eob.cpp
diff options
context:
space:
mode:
authorathrxx2011-12-11 01:57:03 +0100
committerJohannes Schickel2011-12-26 16:18:10 +0100
commit540d081a6fd4daa31f746ddf30ccc91fb88ea04b (patch)
tree2cea9f7050e84e45aad6043d450d1af2a7e33c72 /engines/kyra/screen_eob.cpp
parent9feb674e1189f115e3a7d2cd052efd9ef3e5fba4 (diff)
downloadscummvm-rg350-540d081a6fd4daa31f746ddf30ccc91fb88ea04b.tar.gz
scummvm-rg350-540d081a6fd4daa31f746ddf30ccc91fb88ea04b.tar.bz2
scummvm-rg350-540d081a6fd4daa31f746ddf30ccc91fb88ea04b.zip
KYRA: (EOB) - initial code base commit
Diffstat (limited to 'engines/kyra/screen_eob.cpp')
-rw-r--r--engines/kyra/screen_eob.cpp965
1 files changed, 965 insertions, 0 deletions
diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp
new file mode 100644
index 0000000000..eb5a52477b
--- /dev/null
+++ b/engines/kyra/screen_eob.cpp
@@ -0,0 +1,965 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#if !defined(ENABLE_EOB)
+#include "kyra/screen.h"
+#endif
+
+#ifdef ENABLE_EOB
+
+#include "kyra/eobcommon.h"
+#include "kyra/resource.h"
+
+#include "common/system.h"
+
+#include "graphics/cursorman.h"
+
+namespace Kyra {
+
+Screen_Eob::Screen_Eob(EobCoreEngine *vm, OSystem *system) : Screen(vm, system) {
+ _shapeFadeMode[0] = _shapeFadeMode[1] = 0;
+ _shapeFadeInternal = 0;
+ _fadeData = 0;
+ _fadeDataIndex = 0;
+ _dsX1 = _dsX2 = _dsY1 = _dsY2 = 0;
+ _customDimTable = 0;
+ _dsTempPage = 0;
+}
+
+Screen_Eob::~Screen_Eob() {
+ delete[] _fadeData;
+ delete[] _customDimTable;
+ delete[] _dsTempPage;
+}
+
+bool Screen_Eob::init() {
+ if (Screen::init()) {
+ _customDimTable = new ScreenDim*[_screenDimTableCount];
+ memset(_customDimTable, 0, sizeof(ScreenDim *)* _screenDimTableCount);
+
+ _fadeData = _vm->resource()->fileData("FADING.DAT", 0);
+
+ if (!_fadeData) {
+ _fadeData = new uint8[0x700];
+ memset(_fadeData, 0, 0x700);
+ uint8 *pal = _vm->resource()->fileData("palette1.pal", 0); // EGA: palette0.pal
+ for (int i = 0; i < 7; i++)
+ createFadeTable(pal, &_fadeData[i << 8], 18, (i + 1) * 36);
+ delete[] pal;
+ }
+
+ _dsTempPage = new uint8[6000];
+
+ return true;
+ }
+ return false;
+}
+
+void Screen_Eob::setScreenDim(int dim) {
+ assert(dim < _screenDimTableCount);
+ _curDim = _customDimTable[dim] ? (const ScreenDim *)_customDimTable[dim] : &_screenDimTable[dim];
+ _curDimIndex = dim;
+}
+
+const ScreenDim *Screen_Eob::getScreenDim(int dim) {
+ assert(dim < _screenDimTableCount);
+ return _customDimTable[dim] ? (const ScreenDim *)_customDimTable[dim] : &_screenDimTable[dim];
+}
+
+void Screen_Eob::modifyScreenDim(int dim, int x, int y, int w, int h) {
+ delete _customDimTable[dim];
+ _customDimTable[dim] = new ScreenDim;
+ memcpy(_customDimTable[dim], &_screenDimTable[dim], sizeof(ScreenDim));
+ _customDimTable[dim]->sx = x;
+ _customDimTable[dim]->sy = y;
+ _customDimTable[dim]->w = w;
+ _customDimTable[dim]->h = h;
+ if (dim == _curDimIndex)
+ setScreenDim(dim);
+}
+
+void Screen_Eob::setClearScreenDim(int dim) {
+ setScreenDim(dim);
+ clearCurDim();
+}
+
+void Screen_Eob::clearCurDim() {
+ fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _curDim->unkA);
+}
+
+void Screen_Eob::setMouseCursor(int x, int y, const byte *shape) {
+ if (!shape)
+ return;
+ int mouseW = shape[2] << 3;
+ int mouseH = shape[3];
+ uint8 *cursor = new uint8[mouseW * mouseH];
+ fillRect(0, 0, mouseW, mouseH, _cursorColorKey, 8);
+ drawShape(8, shape, 0, 0, 0);
+ CursorMan.showMouse(false);
+ copyRegionToBuffer(8, 0, 0, mouseW, mouseH, cursor);
+ CursorMan.replaceCursor(cursor, mouseW, mouseH, x, y, _cursorColorKey);
+ if (isMouseVisible())
+ CursorMan.showMouse(true);
+ delete[] cursor;
+
+ // makes sure that the cursor is drawn
+ // we do not use Screen::updateScreen here
+ // so we can be sure that changes to page 0
+ // are NOT updated on the real screen here
+ _system->updateScreen();
+}
+
+void Screen_Eob::loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size) {
+ s->read(_pagePtrs[pageNum], size);
+}
+
+void Screen_Eob::printShadedText(const char *string, int x, int y, int col1, int col2) {
+ printText(string, x - 1, y, 12, col2);
+ printText(string, x, y + 1, 12, 0);
+ printText(string, x - 1, y + 1, 12, 0);
+ printText(string, x, y, col1, 0);
+}
+
+void Screen_Eob::loadEobBitmap(const char *file, int tempPage, int destPage) {
+ loadEobCpsFileToPage(file, 0, tempPage, destPage, -1);
+ _curPage = 2;
+}
+
+void Screen_Eob::loadEobCpsFileToPage(const char *file, const uint8 *ditheringData, int tempPage, int destPage, int copyToPage) {
+ char tmp[13];
+ sprintf(tmp, "%s.CPS", file);
+
+ Common::SeekableReadStream *s = _vm->resource()->createReadStream(tmp);
+ bool loadAlternative = false;
+ if (s) {
+ // This additional check is necessary since some localized versions of EOB II seem to contain invalid (size zero) cps files
+ if (s->size())
+ loadBitmap(tmp, tempPage, destPage, 0);
+ else
+ loadAlternative = true;
+
+ delete s;
+ } else {
+ loadAlternative = true;
+ }
+
+ if (loadAlternative) {
+ tmp[0] = 'X';
+ s = _vm->resource()->createReadStream(tmp);
+ if (!s)
+ error("Screen_Eob::loadEobCpsFileToPage(): CPS file loading failed.");
+ s->seek(768);
+ loadFileDataToPage(s, destPage, 64000);
+ delete s;
+ }
+
+ if (copyToPage == -1) {
+ return;
+ } else if (copyToPage == 0) {
+ copyPage(destPage, 2);
+ copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
+ } else {
+ copyPage(destPage, copyToPage);
+ }
+}
+
+uint8 *Screen_Eob::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool flag) {
+ uint8 *shp = 0;
+ uint16 shapesize = 0;
+
+ uint8 *srcPage = getPagePtr(_curPage) + y * 320 + (x << 3);
+ uint8 *src = srcPage;
+
+ if (flag) {
+ uint16 h1 = h;
+ while (h1--) {
+ uint8 *lineEnd = src + (w << 3);
+ do {
+ if (!*src++) {
+ shapesize++;
+ uint8 *startZeroPos = src;
+ while (src != lineEnd && *src == 0)
+ src++;
+
+ uint16 numZero = src - startZeroPos + 1;
+ if (numZero >> 8)
+ shapesize += 2;
+ }
+ shapesize++;
+ } while (src != lineEnd);
+
+ srcPage += 320;
+ src = srcPage;
+ }
+
+ shapesize += 4;
+
+ shp = new uint8[shapesize];
+ memset (shp, 0, shapesize);
+ uint8 *dst = shp;
+
+ *dst++ = 0;
+ *dst++ = (h & 0xff);
+ *dst++ = (w & 0xff);
+ *dst++ = (h & 0xff);
+
+ srcPage = getPagePtr(_curPage) + y * 320 + (x << 3);
+ src = srcPage;
+
+ h1 = h;
+ while (h1--) {
+ uint8 *lineEnd = src + (w << 3);
+ do {
+ uint8 val = *src++;
+ if (!val) {
+ *dst++ = val;
+ uint8 *startZeroPos = src;
+ while (src != lineEnd && *src == 0)
+ src++;
+
+ uint16 numZero = src - startZeroPos + 1;
+ if (numZero >> 8) {
+ numZero -= 0xff;
+ *dst++ = 0xff;
+ *dst++ = 0;
+ }
+ val = (numZero & 0xff);
+ }
+ *dst++ = val;
+ } while (src != lineEnd);
+
+ srcPage += 320;
+ src = srcPage;
+ }
+
+ } else {
+ uint8 nib = 0, col = 0;
+ uint8 *colorMap = new uint8[0x100];
+ memset (colorMap, 0xff, 0x100);
+
+ shapesize = h * (w << 2) + 0x14;
+ shp = new uint8[shapesize];
+ memset (shp, 0, shapesize);
+ uint8 *dst = shp;
+
+ *dst++ = 1;
+ *dst++ = (h & 0xff);
+ *dst++ = (w & 0xff);
+ *dst++ = (h & 0xff);
+ memset (dst, 0xff, 0x10);
+
+ uint8 *pal = dst;
+ dst += 0x10;
+
+ srcPage = getPagePtr(_curPage) + y * 320 + (x << 3);
+ src = srcPage;
+ nib = col = 0;
+
+ uint16 h1 = h;
+ while (h1--) {
+ uint16 w1 = w << 3;
+ while (w1--) {
+ uint8 s = *src++;
+ uint8 c = colorMap[s];
+ if (c == 0xff) {
+ if (col < 0x10) {
+ *pal++ = s;
+ c = colorMap[s] = col++;
+ if (!col)
+ c = 0;
+ } else {
+ c = 0;
+ }
+ }
+
+ if(++nib & 1) {
+ *dst = c << 4;
+ } else {
+ *dst++ |= c;
+ }
+ }
+ srcPage += 320;
+ src = srcPage;
+ }
+ delete [] colorMap;
+ }
+
+ return shp;
+}
+
+void Screen_Eob::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) {
+ uint8 *dst = getPagePtr(pageNum);
+ const uint8 *src = shapeData;
+
+ if (!src)
+ return;
+
+ va_list args;
+ va_start(args, flags);
+ uint8 *ovl = (flags & 2) ? va_arg(args, uint8*) : 0;
+ va_end(args);
+
+ if (sd != -1) {
+ const ScreenDim *dm = getScreenDim(sd);
+ setShapeFrame(dm->sx, dm->sy, dm->sx + dm->w, dm->sy + dm->h);
+ x += (_dsX1 << 3);
+ y += _dsY1;
+ }
+
+ dst += (_dsX1 << 3);
+ int16 dX = x - (_dsX1 << 3);
+ int16 dY = y;
+ int16 dW = _dsX2 - _dsX1;
+ uint8 flag = *src++;
+
+ uint16 dH = *src++;
+ uint16 width = (*src++) << 3;
+ src++;
+
+ int rX = x;
+ int rY = y;
+ int rW = width + 8;
+ int rH = dH;
+
+ uint16 w2 = width;
+ int d = dY - _dsY1;
+
+ int pixelStep = (flags & 1) ? -1 : 1;
+
+ if (flag) {
+ const uint8 *pal = ovl ? ovl : src;
+ src += 16;
+
+ if (d < 0) {
+ d = -d;
+ if (d >= dH)
+ return;
+ src += (d * (width >> 1));
+ d = dY + dH - _dsY1;
+ if (d >=0) {
+ dH = d;
+ dY = _dsY1;
+ d = _dsY2 - dY;
+ }
+ } else {
+ d = _dsY2 - dY;
+ }
+
+ if (d < 1)
+ return;
+
+ if (d < dH)
+ dH = d;
+
+ int16 cnt1 = 0;
+ int16 cnt2 = 0;
+ int16 dXbit1 = dX & 1;
+
+ if (dX < 0) {
+ width += dX;
+ d = -dX;
+ if ((flags & 1))
+ src -= (d >> 1);
+ else
+ src += (d >> 1);
+
+ if (d >= w2)
+ return;
+
+ dX = 0;
+ cnt1++;
+ }
+
+ d = (dW << 3) - dX;
+
+ if (d < 1)
+ return;
+
+ if (d < width) {
+ width = d;
+ cnt2++;
+ }
+
+ dst += (dY * 320 + dX);
+
+ if (pageNum == 0 || pageNum == 1)
+ addDirtyRect(rX, rY, rW, rH);
+
+ int w3 = w2;
+ dY = 320 - width;
+ width >>= 1;
+ w2 >>= 1;
+ if ((flags & 1))
+ src += (w2 - 1);
+
+ int16 w1shr = width;
+
+ if (cnt1 && (dXbit1 & 1)) {
+ w1shr++;
+ w2++;
+ if (!cnt2)
+ dY += 2;
+ }
+
+ if (cnt2 && (dXbit1 & 1))
+ w1shr++;
+
+ int lineSrcStep = (w2 - w1shr);
+ if ((flags & 1))
+ lineSrcStep = w3 - lineSrcStep;
+
+ while (dH--) {
+ int16 hpos = width;
+ uint8 col = 0;
+ uint8 b = 0;
+ uint8 nextloop = 0;
+
+ if (cnt1 && dXbit1) {
+ if (!hpos)
+ return;
+ b = *src;
+ src += pixelStep;
+ nextloop = 2;
+ } else {
+ nextloop = hpos ? 1 : 3;
+ }
+
+ while (nextloop) {
+ switch (nextloop) {
+ case 1:
+ b = *src;
+ src += pixelStep;
+ col = pal[(flags & 1) ? (b & 0x0f) : (b >> 4)];
+ if (col)
+ drawShapeSetPixel(dst, col);
+ dst++;
+
+ case 2:
+ col = pal[(flags & 1) ? (b >> 4) : (b & 0x0f)];
+
+ if (!col) {
+ nextloop = 4;
+ break;
+ }
+
+ drawShapeSetPixel(dst++, col);
+ nextloop = --hpos ? 1 : 3;
+ break;
+
+ case 3:
+ if (cnt2 && dXbit1) {
+ col = pal[(flags & 1) ? (*src & 0x0f) : (*src >> 4)];
+ src += pixelStep;
+ if (col)
+ drawShapeSetPixel(dst, col);
+ dst++;
+ }
+
+ src += lineSrcStep;
+ dst += dY;
+ nextloop = 0;
+ break;
+
+ case 4:
+ dst++;
+ nextloop = --hpos ? 1 : 3;
+ break;
+ }
+ }
+ }
+ } else {
+ uint16 marginLeft = 0;
+ uint16 marginRight = 0;
+
+ if (d < 0) {
+ dH += d;
+ if (dH <= 0)
+ return;
+ d = -d;
+
+ for (int ii = 0; ii < d; ii++) {
+ marginLeft = width;
+ int i = 0;
+ do {
+ for (i = 0; i < marginLeft; i++)
+ if (!*src++)
+ break;
+
+ if (!*(src-1) || i < marginLeft)
+ marginLeft = ++marginLeft - *src++;
+ else
+ marginLeft = 0;
+
+ } while (marginLeft);
+ }
+ dY = _dsY1;
+ }
+
+ d = _dsY2 - dY;
+
+ if (d < 1)
+ return;
+
+ if (d < dH)
+ dH = d;
+
+ marginLeft = 0;
+
+ if (dX < 0) {
+ width += dX;
+ marginLeft = -dX;
+
+ if (marginLeft >= w2)
+ return;
+
+ dX = 0;
+ }
+
+ marginRight = 0;
+ d = (dW << 3) - dX;
+
+ if (d < 1)
+ return;
+
+ if (d < width) {
+ width = d;
+ marginRight = w2 - marginLeft - width;
+ }
+
+ dst += (y * 320 + dX);
+ uint8 * dstL = dst;
+
+ if (pageNum == 0 || pageNum == 1)
+ addDirtyRect(rX, rY, rW, rH);
+
+ while (dH--) {
+ int16 xpos = (int16) marginLeft;
+
+ if (xpos) {
+ do {
+ while (*src && xpos) {
+ src++;
+ xpos--;
+ }
+
+ if (!*src) {
+ uint8 bt = *++src;
+ src++;
+ xpos = xpos - bt;
+ }
+ } while (xpos > 0);
+ }
+
+ dst -= xpos;
+ xpos += width;
+
+ while (xpos > 0) {
+ uint8 c = *src++;
+
+ if (c) {
+ drawShapeSetPixel(dst++, c);
+ xpos--;
+ } else {
+ dst += *src;
+ xpos -= *src++;
+ }
+ }
+ xpos += marginRight;
+
+ if (xpos) {
+ do {
+ while (*src && xpos) {
+ src++;
+ xpos--;
+ }
+
+ if (!*src) {
+ uint8 bt = *++src;
+ src++;
+ xpos = xpos - bt;
+ }
+ } while (xpos > 0);
+ }
+
+ dstL += 320;
+ dst = dstL;
+ }
+ }
+}
+
+void Screen_Eob::drawShapeSetPixel(uint8 * dst, uint8 c) {
+ if (_shapeFadeMode[0]) {
+ if (_shapeFadeMode[1]) {
+ c = *dst;
+ } else {
+ _shapeFadeInternal &= 7;
+ c = *(dst + _shapeFadeInternal++);
+ }
+ }
+
+ if (_shapeFadeMode[1]) {
+ uint8 cnt = _shapeFadeMode[1];
+ while (cnt--)
+ c = _fadeData[_fadeDataIndex + c];
+ }
+
+ *dst = c;
+}
+
+const uint8 *Screen_Eob::scaleShape(const uint8 *shapeData, int steps) {
+ setShapeFadeMode(1, steps ? true : false);
+
+ while (shapeData && steps--)
+ shapeData = scaleShapeStep(shapeData);
+
+ return shapeData;
+}
+
+const uint8 *Screen_Eob::scaleShapeStep(const uint8 *shp) {
+ uint8 *d = _dsTempPage;
+ *d++ = *shp++;
+
+ uint16 h = (*shp++) + 1;
+ d[0] = d[2] = (h << 1) / 3;
+ d++;
+
+ uint16 w = *shp++;
+ uint16 w2 = w << 2;
+ uint16 t = ((w << 1) % 3) ? 1 : 0;
+ *d++ = ((w << 1) / 3) + t;
+
+ shp++;
+ d++;
+
+ int i = 0;
+ while (i < 16) {
+ if (!shp[i]) {
+ i = -i;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= 0)
+ i = 0;
+ else
+ i = -i;
+
+ _dsScaleTmp = (i << 4) | (i & 0x0f);
+ memcpy(d, shp, 16);
+ d += 16;
+ shp += 16;
+
+ _dsDiv = w2 / 3;
+ _dsRem = w2 % 3;
+
+ do {
+ scaleShapeProcessLine(d, shp);
+ if (!--h)
+ break;
+ scaleShapeProcessLine(d, shp);
+ if (!--h)
+ break;
+ shp += w2;
+ } while (--h);
+
+ return (const uint8 *) _dsTempPage;
+}
+
+void Screen_Eob::replaceShapePalette(uint8 *shp, const uint8 *pal) {
+ if (*shp != 1)
+ return;
+ shp += 4;
+ memcpy(shp, pal, 16);
+}
+
+void Screen_Eob::applyShapeOverlay(uint8 *shp, int ovlIndex) {
+ if (*shp != 1)
+ return;
+ shp += 4;
+ uint8 *ovl = getFadeTable(ovlIndex);
+ for (int i = 0; i < 16; i++)
+ shp[i] = ovl[shp[i]];
+}
+
+void Screen_Eob::scaleShapeProcessLine(uint8 *&dst, const uint8 *&src) {
+ for (int i = 0; i < _dsDiv; i++) {
+ *dst++ = *src++;
+ *dst++ = READ_BE_UINT16(src) >> 4;
+ src += 2;
+ }
+
+ if (_dsRem == 1) {
+ *dst++ = *src++;
+ *dst++ = _dsScaleTmp;
+
+ } if (_dsRem == 2) {
+ *dst++ = (src[0] & 0xf0) | (src[1] >> 4);
+ src += 2;
+ *dst++ = _dsScaleTmp;
+ *dst++ = _dsScaleTmp;
+ *dst++ = _dsScaleTmp;
+ }
+}
+
+void Screen_Eob::fadeTextColor(Palette *pal, int color1, int rate) {
+ uint8 *col = pal->getData();
+
+ for (bool loop = true; loop; ) {
+ loop = true;
+ uint32 end = _system->getMillis() + 16;
+
+ loop = false;
+ for (int ii = 0; ii < 3; ii++) {
+ uint8 c = col[color1 * 3 + ii];
+ if (c > rate) {
+ col[color1 * 3 + ii] -= rate;
+ loop = true;
+ } else if (c) {
+ col[color1 * 3 + ii] = 0;
+ loop = true;
+ }
+ }
+
+ if (loop) {
+ setScreenPalette(*pal);
+ updateScreen();
+ uint32 cur = _system->getMillis();
+ if (end > cur)
+ _system->delayMillis(end - cur);
+ }
+ }
+}
+
+bool Screen_Eob::delayedFadePalStep(Palette *fadePal, Palette *destPal, int rate) {
+ bool res = false;
+
+ uint8 *s = fadePal->getData();
+ uint8 *d = destPal->getData();
+
+ for (int i = 0; i < 765; i++) {
+ int fadeVal = *s++;
+ int dstCur = *d;
+ int diff = ABS(fadeVal - dstCur);
+
+ if (diff == 0) {
+ d++;
+ continue;
+ }
+
+ res = true;
+ diff = MIN(diff, rate);
+
+ if (dstCur < fadeVal)
+ *d += diff;
+ else
+ *d -= diff;
+ d++;
+ }
+
+ return res;
+}
+
+void Screen_Eob::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {
+ if (!palData)
+ return;
+
+ uint8 *src = palData + 3 * rootColor;
+ uint8 r = *src++;
+ uint8 g = *src++;
+ uint8 b = *src;
+ uint8 tr, tg, tb;
+ src = palData + 3;
+
+ *dst++ = 0;
+ weight >>= 1;
+
+ for (uint8 i = 1; i; i++) {
+ uint16 tmp = (uint16)((*src - r) * weight) << 1;
+ tr = *src++ - ((tmp >> 8) & 0xff);
+ tmp = (uint16)((*src - g) * weight) << 1;
+ tg = *src++ - ((tmp >> 8) & 0xff);
+ tmp = (uint16)((*src - b) * weight) << 1;
+ tb = *src++ - ((tmp >> 8) & 0xff);
+
+ uint8 * d = palData + 3;
+ uint16 v = 0xffff;
+ uint8 col = rootColor;
+
+ for (uint8 ii = 1; ii; ii++) {
+ int a = *d++ - tr;
+ int t = a * a;
+ a = *d++ - tg;
+ t += (a * a);
+ a = *d++ - tb;
+ t += (a * a);
+
+ if (t <= v && (ii == rootColor || ii != i)) {
+ v = t;
+ col = ii ;
+ }
+ }
+ *dst++ = col;
+ }
+}
+
+OldDOSFont::OldDOSFont() {
+ _data = 0;
+ _width = _height = _numGlyphs = 0;
+ _bitmapOffsets = 0;
+}
+
+bool OldDOSFont::load(Common::SeekableReadStream &file) {
+ unload();
+
+ _data = new uint8[file.size()];
+ assert(_data);
+
+ file.read(_data, file.size());
+ if (file.err())
+ return false;
+
+ if (file.size() - 2 != READ_LE_UINT16(_data))
+ return false;
+
+ _width = _data[0x103];
+ _height = _data[0x102];
+ _numGlyphs = 255;
+
+ _bitmapOffsets = (uint16 *)(_data + 2);
+
+ for (int i = 0; i < _numGlyphs; ++i)
+ _bitmapOffsets[i] = READ_LE_UINT16(&_bitmapOffsets[i]);
+
+ return true;
+}
+
+int OldDOSFont::getCharWidth(uint16 c) const {
+ if (c >= _numGlyphs)
+ return 0;
+ return _width;
+}
+
+void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) 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 };
+
+ if (_width != 8 && _width != 6)
+ error("EOB font rendering not implemented for other font widths than 6 and 8.");
+
+ if (_width == 6) {
+ switch (c) {
+ case 0x81:
+ case 0x9a:
+ c = 0x5d;
+ break;
+ case 0x84:
+ case 0x8e:
+ c = 0x5b;
+ break;
+ case 0x94:
+ case 0x99:
+ c = 0x40;
+ case 0xe1:
+ // TODO: recheck this: no conversion for 'ß' ?
+ break;
+ }
+ } else if (_width == 8){
+ switch (c) {
+ case 0x81:
+ case 0x9a:
+ case 0x5d:
+ c = 0x1d;
+ break;
+ case 0x84:
+ case 0x5b:
+ c = 0x1e;
+ break;
+ case 0x94:
+ case 0x40:
+ c = 0x1f;
+ break;
+ case 0x8e:
+ c = 0x1b;
+ break;
+ case 0x99:
+ c = 0x1c;
+ break;
+ case 0xe1:
+ c = 0x19;
+ break;
+ }
+ }
+
+ const uint8 *src = &_data[_bitmapOffsets[c]];
+
+ int w = (_width - 1) >> 3;
+ pitch -= _width;
+
+ uint8 color1 = _colorMap[1];
+ uint8 color2 = _colorMap[0];
+
+ int cH = _height;
+ while (cH--) {
+ int cW = w;
+ const uint8 *mtbl = _width == 8 ? renderMaskTable8 : renderMaskTable6;
+
+ for (bool runWidthLoop = true; runWidthLoop; ) {
+ uint8 s = *src++;
+ uint8 m = *mtbl++;
+
+ for (uint8 i = 0x80; i; i >>= 1) {
+ if (!(m & i)) {
+ runWidthLoop = false;
+ break;
+ }
+
+ if (s & i) {
+ if (color1)
+ *dst = color1;
+ } else if (color2) {
+ *dst = color2;
+ }
+ dst++;
+ }
+
+ if (cW)
+ cW--;
+ else
+ runWidthLoop = false;
+ }
+
+ dst += pitch;
+ }
+}
+
+void OldDOSFont::unload() {
+ delete[] _data;
+ _data = 0;
+ _width = _height = _numGlyphs = 0;
+ _bitmapOffsets = 0;
+}
+
+} // End of namespace Kyra
+
+#endif // ENABLE_EOB