diff options
-rw-r--r-- | NEWS | 22 | ||||
-rw-r--r-- | TODO | 9 | ||||
-rw-r--r-- | scumm/akos.cpp | 23 | ||||
-rw-r--r-- | scumm/base-costume.h | 1 | ||||
-rw-r--r-- | scumm/bomp.cpp | 8 | ||||
-rw-r--r-- | scumm/charset.cpp | 85 | ||||
-rw-r--r-- | scumm/charset.h | 5 | ||||
-rw-r--r-- | scumm/costume.cpp | 9 | ||||
-rw-r--r-- | scumm/gfx.cpp | 200 | ||||
-rw-r--r-- | scumm/gfx.h | 11 | ||||
-rw-r--r-- | scumm/nut_renderer.cpp | 71 | ||||
-rw-r--r-- | scumm/nut_renderer.h | 7 | ||||
-rw-r--r-- | scumm/scumm.cpp | 4 | ||||
-rw-r--r-- | scumm/verbs.cpp | 2 |
14 files changed, 151 insertions, 306 deletions
@@ -2,20 +2,26 @@ For a more comprehensive changelog for the latest experimental CVS code, see: http://scummvm.sourceforge.net/daily/ChangeLog 0.?? + New Games: + - Added SAGA engine (for the games and "I Have No Mouth and I Must Scream" + and "Inherit the Earth") + General: - Added support for FLAC (losless) encoded audio files - Added an 'On Screen Display' to the SDL backend - - Rewrote the backend API partially + - Partially rewrote the backend API - Comments in config files are preserved now - - Updated AdvMame scalers based on scale2x 2.0 - AdvMame3x looks nicer now - - Added MMX i386 assembler HQ2x and HQ3x scalers - - Alt-x and Ctrl-z quit keys disabled in favour of Ctrl-q on non - Mac OS X unices (including Linux) + - Updated AdvMame scalers based on scale2x 2.0 - AdvMame3x looks nicer now, + and AdvMame2x is MMX accelerated + - Added MMX i386 assembler versions of the HQ2x and HQ3x scalers + - Alt-x and Ctrl-z quit keys disabled in favour of Ctrl-q on unix like + operating systems, like Linux (exception: Mac OS X still uses Cmd-q) SCUMM: - Old zak256 target removed, use zakTowns instead - - Added support for the special container file format used in mac version - (thus you do not have to use rescumm anymore) + - Added support for the special container file format used in the macintosh + versions of some games (thus you do not have to use rescumm anymore) + - Partially rewrote the text engine, fixing various bugs Queen: - Various fixes [TODO: Somebody of the Queen team please fill this in] @@ -43,7 +49,7 @@ For a more comprehensive changelog for the latest experimental CVS code, see: same file handle, e.g. in the Sam & Max intro when using monster.sog. SCUMM: - - Many SCUMM game engine fixes. + - As usual: many SCUMM game engine fixes. - Added graphics decoders for 3DO Humongous Entertainment games - Numerous Humongous Entertainment games fixes - Fixed bug in Full Throttle, so battle difficulty matches original @@ -230,15 +230,6 @@ SCUMM details * V7-8 games: Implement smooth horizontal scrolling (instead of scrolling in increments of 8 pixels). See bug #629417. -* COMI (maybe V7 games, too?): "Fix" CHARSET_1 behaviour when the room scrolls. - In particular, when text is drawn via CHARSET_1 and then scrolling takes - place, the text scrolls, too - but it really should stay fixed. There are - several ways to do this that I can think of. One would be to use an overlay - screen (i.e. use virtscreen 3, which isn't used at all currently) to draw - the text; then "compose" that screen over the main screen. - Or constantly (well, at least whenever the camera moves) redraw the text. - That would require buffering the text; maybe the blast text code could be - reused for this... * Add tool and support for compress *.la* file resources (ex. sounds) to fit on small devices * Fix codec44 for nut fonts diff --git a/scumm/akos.cpp b/scumm/akos.cpp index 5cf8344375..d3a9fdd851 100644 --- a/scumm/akos.cpp +++ b/scumm/akos.cpp @@ -385,7 +385,7 @@ void AkosRenderer::codec1_genericDecode() { return; } } else { - masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && ((mask[0] | mask[v1.imgbufoffs]) & maskbit)); + masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && (*mask & maskbit)); if (color && !masked && !skip_column) { pcolor = palette[color]; @@ -781,8 +781,7 @@ byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) { v1.destptr = _outptr + v1.y * _outwidth + v1.x; - v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, 0); - v1.imgbufoffs = _vm->gdi._imgBufOffs[_zbuf]; + v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, _zbuf); codec1_genericDecode(); @@ -847,9 +846,7 @@ byte AkosRenderer::codec5(int xmoveCur, int ymoveCur) { } bdd.y = _actorY + ymoveCur; - if (_zbuf != 0) { - bdd.maskPtr = _vm->getMaskBuffer(0, 0, _zbuf); - } + bdd.maskPtr = _vm->getMaskBuffer(0, 0, _zbuf); _vm->drawBomp(bdd, !_mirror); _vm->_bompActorPalettePtr = NULL; @@ -930,7 +927,7 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in int32 numskip_before, int32 numskip_after, byte transparency, int maskLeft, int maskTop, int zBuf) { byte *tmp_buf = akos16.buffer; int maskpitch; - byte *maskptr = 0, *charsetMask = 0; + byte *maskptr; const byte maskbit = revBitMask[maskLeft & 7]; if (dir < 0) { @@ -946,19 +943,13 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in maskpitch = _numStrips; - charsetMask = _vm->getMaskBuffer(maskLeft, maskTop, 0); - if (zBuf != 0) - maskptr = _vm->getMaskBuffer(maskLeft, maskTop, zBuf); + maskptr = _vm->getMaskBuffer(maskLeft, maskTop, zBuf); assert(t_height > 0); assert(t_width > 0); while (t_height--) { akos16DecodeLine(tmp_buf, t_width, dir); - bompApplyMask(akos16.buffer, charsetMask, maskbit, t_width, transparency); - if (maskptr) { - bompApplyMask(akos16.buffer, maskptr, maskbit, t_width, transparency); - maskptr += maskpitch; - } + bompApplyMask(akos16.buffer, maskptr, maskbit, t_width, transparency); bool HE7Check = (_vm->_heversion == 70); bompApplyShadow(_shadow_mode, _shadow_table, akos16.buffer, dest, t_width, transparency, HE7Check); @@ -966,7 +957,7 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in akos16SkipData(numskip_after); } dest += pitch; - charsetMask += maskpitch; + maskptr += maskpitch; } } diff --git a/scumm/base-costume.h b/scumm/base-costume.h index 533e77523a..cb75d11200 100644 --- a/scumm/base-costume.h +++ b/scumm/base-costume.h @@ -97,7 +97,6 @@ protected: int skip_width; byte *destptr; const byte *mask_ptr; - int imgbufoffs; } v1; public: diff --git a/scumm/bomp.cpp b/scumm/bomp.cpp index 89daf4061d..17ead8a804 100644 --- a/scumm/bomp.cpp +++ b/scumm/bomp.cpp @@ -199,7 +199,6 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) { const byte *src; byte *dst; byte *mask = 0; - byte *charset_mask; Common::Rect clip; byte *scalingYPtr = bd.scalingYPtr; byte skip_y_bits = 0x80; @@ -234,10 +233,7 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) { const byte maskbit = revBitMask[(bd.x + clip.left) & 7]; - // Always mask against the charset mask - charset_mask = getMaskBuffer(bd.x + clip.left, bd.y, 0); - - // Also mask against any additionally imposed mask + // Mask against any additionally imposed mask if (bd.maskPtr) { mask = bd.maskPtr + (bd.y * gdi._numStrips) + ((bd.x + clip.left) / 8); } @@ -310,7 +306,6 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) { // Replace the parts of the line which are masked with the transparency color if (bd.maskPtr) bompApplyMask(line_ptr, mask, maskbit, width, 255); - bompApplyMask(line_ptr, charset_mask, maskbit, width, 255); // Apply custom color map, if available if (_bompActorPalettePtr) @@ -324,7 +319,6 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) { // Advance to the next line pos_y++; mask += gdi._numStrips; - charset_mask += gdi._numStrips; dst += bd.outwidth; } } diff --git a/scumm/charset.cpp b/scumm/charset.cpp index 43b9b6cdd4..528d25edde 100644 --- a/scumm/charset.cpp +++ b/scumm/charset.cpp @@ -944,7 +944,7 @@ void CharsetRendererV3::setColor(byte color) void CharsetRendererV3::printChar(int chr) { // Indy3 / Zak256 / Loom VirtScreen *vs; - byte *char_ptr, *dest_ptr, *mask_ptr; + byte *char_ptr, *dest_ptr; int width, height; int drawTop; @@ -972,8 +972,6 @@ void CharsetRendererV3::printChar(int chr) { drawTop = _top - vs->topline; char_ptr = _fontPtr + chr * 8; - dest_ptr = vs->screenPtr + vs->xstart + drawTop * vs->width + _left; - mask_ptr = _vm->getMaskBuffer(_left, drawTop, 0); _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height); @@ -981,8 +979,13 @@ void CharsetRendererV3::printChar(int chr) { _hasMask = true; _textScreenID = vs->number; } + if (_ignoreCharsetMask || !vs->hasTwoBuffers) { + dest_ptr = vs->screenPtr + vs->xstart + drawTop * vs->width + _left; + } else { + dest_ptr = (byte *)_vm->gdi._textSurface.pixels + drawTop * _vm->gdi._textSurface.pitch + _left; + } - drawBits1(vs, dest_ptr, char_ptr, mask_ptr, drawTop, 8, 8); + drawBits1(vs, dest_ptr, char_ptr, drawTop, 8, 8); if (_str.left > _left) _str.left = _left; @@ -1085,24 +1088,29 @@ void CharsetRendererClassic::printChar(int chr) { _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height + offsY); + byte *dst; + byte *back; + if (!_ignoreCharsetMask) { _hasMask = true; _textScreenID = vs->number; } + if (_ignoreCharsetMask || !vs->hasTwoBuffers) { + dst = vs->screenPtr + vs->xstart + drawTop * vs->width + _left; + } else { + dst = (byte *)_vm->gdi._textSurface.pixels + drawTop * _vm->gdi._textSurface.pitch + _left; + } - byte *mask = _vm->getMaskBuffer(_left, drawTop, 0); - byte *dst = vs->screenPtr + vs->xstart + drawTop * vs->width + _left; - - byte *back = dst; + back = dst; if (_blitAlso && vs->hasTwoBuffers) { dst = vs->backBuf + vs->xstart + drawTop * vs->width + _left; } if (is2byte) { - drawBits1(vs, dst, charPtr, mask, drawTop, origWidth, origHeight); + drawBits1(vs, dst, charPtr, drawTop, origWidth, origHeight); } else { byte bpp = *_fontPtr; - drawBitsN(vs, dst, charPtr, mask, bpp, drawTop, origWidth, origHeight); + drawBitsN(vs, dst, charPtr, bpp, drawTop, origWidth, origHeight); } if (_blitAlso && vs->hasTwoBuffers) { @@ -1128,30 +1136,21 @@ void CharsetRendererClassic::printChar(int chr) { _top -= offsY; } -void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte *mask, byte bpp, int drawTop, int width, int height) { - byte maskmask; +void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) { int y, x; - int maskpos; int color; byte numbits, bits; - bool useMask = (vs->number == kMainVirtScreen && !_ignoreCharsetMask); assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8); bits = *src++; numbits = 8; for (y = 0; y < height && y + drawTop < vs->height; y++) { - maskmask = revBitMask[_left & 7]; - maskpos = 0; - for (x = 0; x < width; x++) { color = (bits >> (8 - bpp)) & 0xFF; if (color && y + drawTop >= 0) { *dst = _vm->_charsetColorMap[color]; - if (useMask) { - mask[maskpos] |= maskmask; - } } dst++; bits <<= bpp; @@ -1160,28 +1159,16 @@ void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *sr bits = *src++; numbits = 8; } - maskmask >>= 1; - if (maskmask == 0) { - maskmask = 0x80; - maskpos++; - } } dst += vs->width - width; - mask += _vm->gdi._numStrips; } } -void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src, byte *mask, int drawTop, int width, int height) { - byte maskmask; +void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src, int drawTop, int width, int height) { int y, x; - int maskpos; byte bits = 0; - bool useMask = (vs->number == kMainVirtScreen && !_ignoreCharsetMask); for (y = 0; y < height && y + drawTop < vs->height; y++) { - maskmask = revBitMask[_left & 7]; - maskpos = 0; - for (x = 0; x < width; x++) { if ((x % 8) == 0) bits = *src++; @@ -1192,30 +1179,11 @@ void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src *(dst + vs->width + 1) = _shadowColor; } *dst = _color; - if (useMask) { - mask[maskpos] |= maskmask; - if (_dropShadow) { - mask[maskpos + _vm->gdi._numStrips] |= maskmask; - if (maskmask == 1) { - mask[maskpos + 1] |= 0x80; - mask[maskpos + _vm->gdi._numStrips + 1] |= 0x80; - } else { - mask[maskpos] |= (maskmask >> 1); - mask[maskpos + _vm->gdi._numStrips] |= (maskmask >> 1); - } - } - } } dst++; - maskmask >>= 1; - if (maskmask == 0) { - maskmask = 0x80; - maskpos++; - } } dst += vs->width - width; - mask += _vm->gdi._numStrips; } } @@ -1293,12 +1261,23 @@ void CharsetRendererNut::printChar(int chr) { shadow.right = _left + width + 2; shadow.bottom = _top + height + 2; + Graphics::Surface s; if (!_ignoreCharsetMask) { _hasMask = true; _textScreenID = kMainVirtScreen; } + if (_ignoreCharsetMask) { + VirtScreen *vs = &_vm->virtscr[kMainVirtScreen]; + s.pixels = vs->screenPtr + vs->xstart + _vm->_screenTop * vs->width; + s.w = vs->width; + s.h = vs->height; + s.pitch = vs->width; + s.bytesPerPixel = 1; + } else { + s = _vm->gdi._textSurface; + } - _current->drawShadowChar(chr, _left, _top, _color, !_ignoreCharsetMask, _curId != 3); + _current->drawShadowChar(s, chr, _left, _top, _color, _curId != 3); _vm->markRectAsDirty(kMainVirtScreen, shadow); if (_str.left > _left) diff --git a/scumm/charset.h b/scumm/charset.h index 7ad92fd974..116d4e3dfe 100644 --- a/scumm/charset.h +++ b/scumm/charset.h @@ -69,7 +69,6 @@ public: void restoreCharsetBg(); void clearCharsetMask(); - bool hasCharsetMask(int left, int top, int right, int bottom); virtual void printChar(int chr) = 0; @@ -88,7 +87,7 @@ class CharsetRendererCommon : public CharsetRenderer { protected: byte *_fontPtr; - void drawBits1(VirtScreen *vs, byte *dst, const byte *src, byte *mask, int drawTop, int width, int height); + void drawBits1(VirtScreen *vs, byte *dst, const byte *src, int drawTop, int width, int height); public: CharsetRendererCommon(ScummEngine *vm) : CharsetRenderer(vm) {} @@ -102,7 +101,7 @@ class CharsetRendererClassic : public CharsetRendererCommon { protected: int getCharWidth(byte chr); - void drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte *mask, byte bpp, int drawTop, int width, int height); + void drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height); public: CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {} diff --git a/scumm/costume.cpp b/scumm/costume.cpp index d51909a7fb..617ac078ad 100644 --- a/scumm/costume.cpp +++ b/scumm/costume.cpp @@ -284,8 +284,7 @@ byte CostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) { v1.destptr = _outptr + v1.y * _outwidth + v1.x; - v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, 0); - v1.imgbufoffs = _vm->gdi._imgBufOffs[_zbuf]; + v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, _zbuf); CHECK_HEAP @@ -350,7 +349,7 @@ static const int v1MMActorPalatte2[25] = { }; #define MASK_AT(xoff) \ - (mask && (mask[((v1.x + xoff) / 8) + v1.imgbufoffs] & revBitMask[(v1.x + xoff) & 7])) + (mask && (mask[((v1.x + xoff) / 8)] & revBitMask[(v1.x + xoff) & 7])) #define LINE(c,p) \ pcolor = (color >> c) & 3; \ if (pcolor) { \ @@ -467,7 +466,7 @@ void CostumeRenderer::proc3() { do { if (_scaleY == 255 || *scaleytab++ < _scaleY) { - masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && ((mask[0] | mask[v1.imgbufoffs]) & maskbit)); + masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && (mask[0] & maskbit)); if (color && !masked) { // FIXME: Fully implement _shadow_mode.in Sam & Max @@ -536,7 +535,7 @@ void CostumeRenderer::proc3_ami() { len = *src++; do { if (_scaleY == 255 || cost_scaleTable[_scaleIndexY] < _scaleY) { - masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && ((mask[0] | mask[v1.imgbufoffs]) & maskbit)); + masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && (mask[0] & maskbit)); if (color && v1.x >= 0 && v1.x < _outwidth && !masked) { *dst = _palette[color]; diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index 2b97944b04..2717796fba 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -156,49 +156,12 @@ static const TransitionEffect transitionEffects[5] = { }; #endif -static inline void copy8PixelsWithMasking(byte *dst, const byte *src, byte maskbits) { - if (!(maskbits & 0x80)) - dst[0] = src[0]; - if (!(maskbits & 0x40)) - dst[1] = src[1]; - if (!(maskbits & 0x20)) - dst[2] = src[2]; - if (!(maskbits & 0x10)) - dst[3] = src[3]; - if (!(maskbits & 0x08)) - dst[4] = src[4]; - if (!(maskbits & 0x04)) - dst[5] = src[5]; - if (!(maskbits & 0x02)) - dst[6] = src[6]; - if (!(maskbits & 0x01)) - dst[7] = src[7]; -} - -static inline void clear8PixelsWithMasking(byte *dst, const byte color, byte maskbits) { - if (!(maskbits & 0x80)) - dst[0] = color; - if (!(maskbits & 0x40)) - dst[1] = color; - if (!(maskbits & 0x20)) - dst[2] = color; - if (!(maskbits & 0x10)) - dst[3] = color; - if (!(maskbits & 0x08)) - dst[4] = color; - if (!(maskbits & 0x04)) - dst[5] = color; - if (!(maskbits & 0x02)) - dst[6] = color; - if (!(maskbits & 0x01)) - dst[7] = color; -} - #pragma mark - #pragma mark --- Virtual Screens --- #pragma mark - +#define CHARSET_MASK_TRANSPARENCY 254 Gdi::Gdi(ScummEngine *vm) { memset(this, 0, sizeof(*this)); @@ -206,6 +169,9 @@ Gdi::Gdi(ScummEngine *vm) { _roomPalette = vm->_roomPalette; if ((vm->_features & GF_AMIGA) && (vm->_version >= 4)) _roomPalette += 16; + + _compositeBuf = 0; + _textSurface.pixels = 0; } void ScummEngine::initScreens(int b, int h) { @@ -235,8 +201,26 @@ void ScummEngine::initScreens(int b, int h) { _screenB = b; _screenH = h; + + gdi.init(); +} + +void Gdi::init() { + const int size = _vm->_screenWidth * _vm->_screenHeight; + free(_compositeBuf); + free(_textSurface.pixels); + _compositeBuf = (byte *)malloc(size); + _textSurface.pixels = malloc(size); + memset(_compositeBuf, CHARSET_MASK_TRANSPARENCY, size); + memset(_textSurface.pixels, CHARSET_MASK_TRANSPARENCY, size); + + _textSurface.w = _vm->_screenWidth; + _textSurface.h = _vm->_screenHeight; + _textSurface.pitch = _vm->_screenWidth; + _textSurface.bytesPerPixel = 1; } + void ScummEngine::initVirtScreen(VirtScreenNumber slot, int number, int top, int width, int height, bool twobufs, bool scrollable) { VirtScreen *vs = &virtscr[slot]; @@ -246,7 +230,7 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int number, int top, int assert(slot >= 0 && slot < 4); if (_version >= 7) { - if (slot == 0 && (_roomHeight != 0)) + if (slot == kMainVirtScreen && (_roomHeight != 0)) height = _roomHeight; } @@ -431,8 +415,7 @@ void Gdi::updateDirtyScreen(VirtScreen *vs) { * specified by top/bottom coordinate in the virtual screen. */ void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom) { - byte *ptr; - int height; + const int height = bottom - top; if (bottom <= top) return; @@ -442,11 +425,33 @@ void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int botto assert(top >= 0 && bottom <= vs->height); // Paranoia checks - height = bottom - top; // We don't clip height and width here, rather we rely on the backend to // perform any needed clipping. - ptr = vs->screenPtr + (x + vs->xstart) + top * vs->width; - _vm->_system->copyRectToScreen(ptr, vs->width, x, vs->topline + top - _vm->_screenTop, width, height); + const int y = vs->topline + top - _vm->_screenTop; + const byte *src = vs->screenPtr + (x + vs->xstart) + top * vs->width; + + assert(_textSurface.pixels); + assert(_compositeBuf); + Common::Rect r(x, y, x+width, y+height); + r.clip(Common::Rect(_textSurface.w, _textSurface.h)); + // TODO: is this enough clipping? + + byte *dst = _compositeBuf + x + y * _vm->_screenWidth; + const byte *text = (byte *)_textSurface.pixels + x + y * _textSurface.pitch; + + for (int h = 0; h < r.height(); ++h) { + for (int w = 0; w < r.width(); ++w) { + if (text[w] == CHARSET_MASK_TRANSPARENCY) + dst[w] = src[w]; + else + dst[w] = text[w]; + } + src += vs->width; + dst += _vm->_screenWidth; + text += _textSurface.pitch; + } + + _vm->_system->copyRectToScreen(_compositeBuf + x + y * _vm->_screenWidth, _vm->_screenWidth, x, y, width, height); } #pragma mark - @@ -633,14 +638,12 @@ void ScummEngine::restoreBG(Common::Rect rect, byte backColor) { // be optimized to (rect.right - rect.left) / 8 and // thus to width / 8, but that's not the case since // we are dealing with integer math here. - const int mask_width = ((rect.right + 7) / 8) - (rect.left / 8); - - byte *mask = getMaskBuffer(rect.left, rect.top, 0); - - do { - memset(mask, 0, mask_width); - mask += gdi._numStrips; - } while (--height); + const int mask_width = rect.width(); + byte *mask = (byte *)gdi._textSurface.pixels + gdi._textSurface.pitch * rect.top + rect.left; + while (height--) { + memset(mask, CHARSET_MASK_TRANSPARENCY, mask_width); + mask += gdi._textSurface.pitch; + } } } else { while (height--) { @@ -663,9 +666,7 @@ void CharsetRenderer::restoreCharsetBg() { // restoreBG(), but was changed to only restore those parts which are // currently covered by the charset mask. - // Loop over first three virtual screens VirtScreen *vs = &_vm->virtscr[_textScreenID]; - if (!vs->height) return; @@ -677,27 +678,8 @@ void CharsetRenderer::restoreCharsetBg() { const byte *backBuf = vs->backBuf + vs->xstart; if (vs->number == kMainVirtScreen) { - // Restore from back buffer, but only those parts which are - // currently covered by the charset mask. In addition, we - // clean out the charset mask - - const int mask_width = _vm->gdi._numStrips; - byte *mask = _vm->getMaskBuffer(0, 0, 0); - assert(vs->width == 8 * _vm->gdi._numStrips); - - int height = vs->height; - while (height--) { - for (int w = 0; w < mask_width; ++w) { - const byte maskbits = mask[w]; - if (maskbits) { - copy8PixelsWithMasking(screenBuf + w*8, backBuf + w*8, ~maskbits); - mask[w] = 0; - } - } - screenBuf += vs->width; - backBuf += vs->width; - mask += _vm->gdi._numStrips; - } + // Clean out the charset mask + memset(_vm->gdi._textSurface.pixels, CHARSET_MASK_TRANSPARENCY, _vm->gdi._textSurface.pitch * _vm->gdi._textSurface.h); } else { // Restore from back buffer _vm->blit(screenBuf, backBuf, vs->width, vs->height); @@ -713,10 +695,6 @@ void CharsetRenderer::clearCharsetMask() { memset(_vm->getResourceAddress(rtBuffer, 9), 0, _vm->gdi._imgBufOffs[1]); } -bool CharsetRenderer::hasCharsetMask(int left, int top, int right, int bottom) { - return _hasMask; -} - byte *ScummEngine::getMaskBuffer(int x, int y, int z) { return gdi.getMaskBuffer(x / 8, y, z) + _screenStartStrip; } @@ -1170,21 +1148,12 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi } } - mask_ptr = getMaskBuffer(x, y); - CHECK_HEAP; if (vs->hasTwoBuffers) { - if (_vm->_charset->hasCharsetMask(sx * 8, y, (sx + 1) * 8, bottom)) { - if (flag & dbClear || !lightsOn) - clear8ColWithMasking(backbuff_ptr, height, mask_ptr); - else - draw8ColWithMasking(backbuff_ptr, bgbak_ptr, height, mask_ptr); - } else { - if (flag & dbClear || !lightsOn) - clear8Col(backbuff_ptr, height); - else - draw8Col(backbuff_ptr, bgbak_ptr, height); - } + if (flag & dbClear || !lightsOn) + clear8Col(backbuff_ptr, height); + else + draw8Col(backbuff_ptr, bgbak_ptr, height); } CHECK_HEAP; @@ -1304,17 +1273,13 @@ void Gdi::resetBackground(int top, int bottom, int strip) { vs->bdirty[strip] = bottom; offs = top * vs->width + vs->xstart + strip * 8; - byte *mask_ptr = _vm->getMaskBuffer(strip * 8, top, 0); bgbak_ptr = vs->backBuf + offs; backbuff_ptr = vs->screenPtr + offs; numLinesToProcess = bottom - top; if (numLinesToProcess) { if (_vm->isLightOn()) { - if (_vm->_charset->hasCharsetMask(strip * 8, top, (strip + 1) * 8, bottom)) - draw8ColWithMasking(backbuff_ptr, bgbak_ptr, numLinesToProcess, mask_ptr); - else - draw8Col(backbuff_ptr, bgbak_ptr, numLinesToProcess); + draw8Col(backbuff_ptr, bgbak_ptr, numLinesToProcess); } else { clear8Col(backbuff_ptr, numLinesToProcess); } @@ -1654,47 +1619,6 @@ bool Gdi::decompressBitmap(byte *bgbak_ptr, const byte *src, int numLinesToProce return useOrDecompress; } -void Gdi::draw8ColWithMasking(byte *dst, const byte *src, int height, byte *mask) { - byte maskbits; - - do { - maskbits = *mask; - if (maskbits) { - copy8PixelsWithMasking(dst, src, maskbits); - } else { -#if defined(SCUMM_NEED_ALIGNMENT) - memcpy(dst, src, 8); -#else - ((uint32 *)dst)[0] = ((const uint32 *)src)[0]; - ((uint32 *)dst)[1] = ((const uint32 *)src)[1]; -#endif - } - src += _vm->_screenWidth; - dst += _vm->_screenWidth; - mask += _numStrips; - } while (--height); -} - -void Gdi::clear8ColWithMasking(byte *dst, int height, byte *mask) { - byte maskbits; - - do { - maskbits = *mask; - if (maskbits) { - clear8PixelsWithMasking(dst, 0, maskbits); - } else { -#if defined(SCUMM_NEED_ALIGNMENT) - memset(dst, 0, 8); -#else - ((uint32 *)dst)[0] = 0; - ((uint32 *)dst)[1] = 0; -#endif - } - dst += _vm->_screenWidth; - mask += _numStrips; - } while (--height); -} - void Gdi::draw8Col(byte *dst, const byte *src, int height) { do { #if defined(SCUMM_NEED_ALIGNMENT) diff --git a/scumm/gfx.h b/scumm/gfx.h index 8c445f42a3..0bee946897 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -24,6 +24,7 @@ #define GFX_H #include "common/rect.h" +#include "graphics/surface.h" namespace Scumm { @@ -217,7 +218,11 @@ public: Gdi(ScummEngine *vm); + Graphics::Surface _textSurface; + protected: + byte *_compositeBuf; + byte *_roomPalette; byte _decomp_shr, _decomp_mask; byte _transparentColor; @@ -251,9 +256,7 @@ protected: void decodeStrip3DO(byte *dst, const byte *src, int height, byte transpCheck); void decodeStripHE(byte *dst, const byte *src, int height, byte transpCheck); - void draw8ColWithMasking(byte *dst, const byte *src, int height, byte *mask); void draw8Col(byte *dst, const byte *src, int height); - void clear8ColWithMasking(byte *dst, int height, byte *mask); void clear8Col(byte *dst, int height); void decompressMaskImgOr(byte *dst, const byte *src, int height); void decompressMaskImg(byte *dst, const byte *src, int height); @@ -261,9 +264,11 @@ protected: void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b); void updateDirtyScreen(VirtScreen *vs); - byte *getMaskBuffer(int x, int y, int z = 0); + byte *getMaskBuffer(int x, int y, int z); public: + void init(); + void drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height, int stripnr, int numstrip, byte flag, StripTable *table = 0); void drawBitmapV2Helper(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height, diff --git a/scumm/nut_renderer.cpp b/scumm/nut_renderer.cpp index 56e597e0bf..e991dca2c0 100644 --- a/scumm/nut_renderer.cpp +++ b/scumm/nut_renderer.cpp @@ -239,16 +239,13 @@ int NutRenderer::getCharHeight(byte c) { return _chars[c].height; } -void NutRenderer::drawShadowChar(int c, int x, int y, byte color, bool useMask, bool showShadow) { - debug(8, "NutRenderer::drawShadowChar('%c', %d, %d, %d, %d, %d) called", c, x, y, (int)color, useMask, showShadow); +void NutRenderer::drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow) { + debug(8, "NutRenderer::drawShadowChar('%c', %d, %d, %d, %d) called", c, x, y, (int)color, showShadow); if (!_loaded) { warning("NutRenderer::drawShadowChar() Font is not loaded"); return; } - VirtScreen *vs = &_vm->virtscr[kMainVirtScreen]; - byte *dst, *mask = NULL; - // HACK: we draw the character a total of 7 times: 6 times shifted // and in black for the shadow, and once in the right color and position. // This way we achieve the exact look as the original CMI had. However, @@ -268,18 +265,10 @@ void NutRenderer::drawShadowChar(int c, int x, int y, byte color, bool useMask, y += offsetY[i]; color = cTable[i]; - if (y >= vs->height || x >= vs->width) { - continue; - } - - dst = vs->screenPtr + y * vs->width + x + vs->xstart; - if (useMask) - mask = _vm->getMaskBuffer(x, y, 0); - if (c >= 256 && _vm->_CJKMode) - draw2byte(dst, mask, c, x, y - _vm->_screenTop, color); + draw2byte(s, c, x, y, color); else - drawChar(dst, mask, (byte)c, x, y - _vm->_screenTop, color); + drawChar(s, (byte)c, x, y, color); x -= offsetX[i]; y -= offsetY[i]; @@ -318,15 +307,13 @@ void NutRenderer::drawFrame(byte *dst, int c, int x, int y) { } } -void NutRenderer::drawChar(byte *dst, byte *mask, byte c, int x, int y, byte color) { - const int width = MIN(_chars[c].width, _vm->_screenWidth - x); - const int height = MIN(_chars[c].height, _vm->_screenHeight - y); +void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color) { + byte *dst = (byte *)s.pixels + y * s.pitch + x; + const int width = MIN(_chars[c].width, s.w - x); + const int height = MIN(_chars[c].height, s.h - y); const byte *src = _chars[c].src; const int srcPitch = _chars[c].width; - byte maskmask; - int maskpos; - const int minX = x < 0 ? -x : 0; const int minY = y < 0 ? -y : 0; @@ -336,75 +323,47 @@ void NutRenderer::drawChar(byte *dst, byte *mask, byte c, int x, int y, byte col if (minY) { src += minY * srcPitch; - dst += minY * _vm->_screenWidth; - if (mask) - mask += minY * _vm->gdi._numStrips; + dst += minY * s.pitch; } for (int ty = minY; ty < height; ty++) { - maskmask = revBitMask[(x + minX) & 7]; - maskpos = (x%8 + minX) / 8; for (int tx = minX; tx < width; tx++) { if (src[tx] != 0) { dst[tx] = color; - if (mask) - mask[maskpos] |= maskmask; - } - maskmask >>= 1; - if (maskmask == 0) { - maskmask = 0x80; - maskpos++; } } src += srcPitch; - dst += _vm->_screenWidth; - if (mask) - mask += _vm->gdi._numStrips; + dst += s.pitch; } } -void NutRenderer::draw2byte(byte *dst, byte *mask, int c, int x, int y, byte color) { +void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) { if (!_loaded) { debug(2, "NutRenderer::draw2byte() Font is not loaded"); return; } + byte *dst = (byte *)s.pixels + y * s.pitch + x; const int width = _vm->_2byteWidth; - const int height = MIN(_vm->_2byteHeight, _vm->_screenHeight - y); + const int height = MIN(_vm->_2byteHeight, s.h - y); byte *src = _vm->get2byteCharPtr(c); byte bits = 0; - byte maskmask; - int maskpos; - if (height <= 0 || width <= 0) { return; } for (int ty = 0; ty < height; ty++) { - maskmask = revBitMask[x & 7]; - maskpos = 0; for (int tx = 0; tx < width; tx++) { if ((tx & 7) == 0) bits = *src++; - if (x + tx < 0 || x + tx >= _vm->_screenWidth || y + ty < 0) + if (x + tx < 0 || x + tx >= s.w || y + ty < 0) continue; if (bits & revBitMask[tx & 7]) { dst[tx] = color; - if (mask) { - mask[maskpos] |= maskmask; - } - } - - maskmask >>= 1; - if (maskmask == 0) { - maskmask = 0x80; - maskpos++; } } - dst += _vm->_screenWidth; - if (mask) - mask += _vm->gdi._numStrips; + dst += s.pitch; } } diff --git a/scumm/nut_renderer.h b/scumm/nut_renderer.h index c9bbec2269..b0e232e7c4 100644 --- a/scumm/nut_renderer.h +++ b/scumm/nut_renderer.h @@ -22,6 +22,7 @@ #define NUT_RENDERER_H #include "common/file.h" +#include "graphics/surface.h" namespace Scumm { @@ -43,8 +44,8 @@ protected: int32 decodeCodec44(byte *dst, const byte *src, uint32 length); - void drawChar(byte *dst, byte *mask, byte c, int x, int y, byte color); - void draw2byte(byte *dst, byte *mask, int c, int x, int y, byte color); + void drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color); + void draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color); public: NutRenderer(ScummEngine *vm); @@ -54,7 +55,7 @@ public: bool loadFont(const char *filename); void drawFrame(byte *dst, int c, int x, int y); - void drawShadowChar(int c, int x, int y, byte color, bool useMask, bool showShadow); + void drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow); int getCharWidth(byte c); int getCharHeight(byte c); diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index c559ea1ace..aec7d7848f 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -2652,13 +2652,13 @@ void ScummEngine::initRoomSubBlocks() { // Transparent color if (_features & GF_OLD_BUNDLE) - gdi._transparentColor = 255; // TODO - FIXME + gdi._transparentColor = 255; else { ptr = findResourceData(MKID('TRNS'), roomptr); if (ptr) gdi._transparentColor = ptr[0]; else if (_version == 8) - gdi._transparentColor = 5; // FIXME + gdi._transparentColor = 5; else gdi._transparentColor = 255; } diff --git a/scumm/verbs.cpp b/scumm/verbs.cpp index 5b1d66aa88..12665e7ca1 100644 --- a/scumm/verbs.cpp +++ b/scumm/verbs.cpp @@ -419,8 +419,6 @@ void ScummEngine::drawVerb(int verb, int mode) { } void ScummEngine::restoreVerbBG(int verb) { - if (_version >= 7) - return; VerbSlot *vs; |