diff options
-rw-r--r-- | scumm/charset.cpp | 15 | ||||
-rw-r--r-- | scumm/cursor.cpp | 4 | ||||
-rw-r--r-- | scumm/debugger.cpp | 2 | ||||
-rw-r--r-- | scumm/gfx.cpp | 19 | ||||
-rw-r--r-- | scumm/gfx.h | 110 | ||||
-rw-r--r-- | scumm/verbs.cpp | 6 |
6 files changed, 130 insertions, 26 deletions
diff --git a/scumm/charset.cpp b/scumm/charset.cpp index 8f9b6465c7..8295941e55 100644 --- a/scumm/charset.cpp +++ b/scumm/charset.cpp @@ -970,15 +970,16 @@ void CharsetRendererV3::printChar(int chr) { w++; h++; } - + 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); - useMask = (vs->number == 0 && !_ignoreCharsetMask); + useMask = (vs->number == kMainVirtScreen && !_ignoreCharsetMask); _vm->markRectAsDirty(vs->number, _left, _left + w, drawTop, drawTop + h, 0); - if (vs->number == 0) + + if (vs->number == kMainVirtScreen) _hasMask = true; drawBits1(vs, dest_ptr, char_ptr, mask_ptr, drawTop, 8, 8); @@ -1084,9 +1085,9 @@ void CharsetRendererClassic::printChar(int chr) { _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height + offsY, 0); - if (vs->number != 0) + if (vs->number != kMainVirtScreen) _blitAlso = false; - if (vs->number == 0 && !_ignoreCharsetMask) + if (vs->number == kMainVirtScreen && !_ignoreCharsetMask) _hasMask = true; @@ -1134,7 +1135,7 @@ void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *sr int maskpos; int color; byte numbits, bits; - bool useMask = (vs->number == 0 && !_ignoreCharsetMask); + bool useMask = (vs->number == kMainVirtScreen && !_ignoreCharsetMask); assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8); bits = *src++; @@ -1176,7 +1177,7 @@ void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src int y, x; int maskpos; byte bits = 0; - bool useMask = (vs->number == 0 && !_ignoreCharsetMask); + bool useMask = (vs->number == kMainVirtScreen && !_ignoreCharsetMask); for (y = 0; y < height && y + drawTop < vs->height; y++) { maskmask = revBitMask[_left & 7]; diff --git a/scumm/cursor.cpp b/scumm/cursor.cpp index 9a8ae5a4fa..674b7150f9 100644 --- a/scumm/cursor.cpp +++ b/scumm/cursor.cpp @@ -130,10 +130,10 @@ void ScummEngine::useIm01Cursor(const byte *im, int w, int h) { drawBox(0, 0, w - 1, h - 1, 0xFF); - vs->alloctwobuffers = false; + vs->hasTwoBuffers = false; gdi.disableZBuffer(); gdi.drawBitmap(im, vs, _screenStartStrip, 0, w, h, 0, w / 8, 0); - vs->alloctwobuffers = true; + vs->hasTwoBuffers = true; gdi.enableZBuffer(); grabCursor(vs->screenPtr + vs->xstart, w, h); diff --git a/scumm/debugger.cpp b/scumm/debugger.cpp index d20634773b..568b51cbd9 100644 --- a/scumm/debugger.cpp +++ b/scumm/debugger.cpp @@ -630,7 +630,7 @@ static void hlineColor(ScummEngine *scumm, int x1, int x2, int y, byte color) { x2 = right - 1; - ptr = vs->screenPtr + x1 + y * scumm->_screenWidth; + ptr = vs->screenPtr + x1 + y * vs->width; while (x1++ <= x2) { *ptr++ = color; diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index 93511842e9..9b974699a7 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -216,7 +216,7 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int number, int top, int vs->width = width; vs->topline = top; vs->height = height; - vs->alloctwobuffers = twobufs; + vs->hasTwoBuffers = twobufs; vs->scrollable = scrollable; vs->xstart = 0; vs->backBuf = NULL; @@ -573,7 +573,7 @@ void ScummEngine::restoreCharsetBg() { void ScummEngine::restoreBG(Common::Rect rect, byte backColor) { VirtScreen *vs; int topline, height, width; - byte *backbuff, *bgbak; + byte *backbuff; bool lightsOn; if (rect.top < 0) @@ -602,7 +602,6 @@ void ScummEngine::restoreBG(Common::Rect rect, byte backColor) { int offset = (rect.top - topline) * vs->width + vs->xstart + rect.left; backbuff = vs->screenPtr + offset; - bgbak = vs->backBuf + offset; height = rect.height(); width = rect.width(); @@ -610,8 +609,8 @@ void ScummEngine::restoreBG(Common::Rect rect, byte backColor) { // Check whether lights are turned on or not lightsOn = (_features & GF_NEW_OPCODES) || (vs->number != kMainVirtScreen) || (VAR(VAR_CURRENT_LIGHTS) & LIGHTMODE_screen); - if (vs->alloctwobuffers && _currentRoom != 0 && lightsOn ) { - blit(backbuff, bgbak, width, height); + if (vs->hasTwoBuffers && _currentRoom != 0 && lightsOn ) { + blit(backbuff, vs->backBuf + offset, width, height); if (vs->number == kMainVirtScreen && _charset->_hasMask && height) { byte *mask; // Note: At first sight it may look as if this could @@ -939,6 +938,10 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi _vertStripNextInc = height * vs->width - 1; sx = x; + // FIXME / TODO: This is the only place vs->scrollable is ever checked, and + // I think we can simply remove the condition and always use xstart - it + // should always be 0 for any non-scrolling virtual screen, after all. + assert(vs->scrollable || !vs->xstart); if (vs->scrollable) sx -= vs->xstart / 8; @@ -951,7 +954,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi // if (_vm->_version == 2) { - if (vs->alloctwobuffers) + if (vs->hasTwoBuffers) bgbak_ptr = vs->backBuf + (y * _numStrips + x) * 8; else bgbak_ptr = vs->screenPtr + (y * _numStrips + x) * 8; @@ -1074,7 +1077,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi vs->bdirty[sx] = bottom; backbuff_ptr = vs->screenPtr + (y * _numStrips + x) * 8; - if (vs->alloctwobuffers) + if (vs->hasTwoBuffers) bgbak_ptr = vs->backBuf + (y * _numStrips + x) * 8; else bgbak_ptr = backbuff_ptr; @@ -1097,7 +1100,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi mask_ptr = getMaskBuffer(x, y); CHECK_HEAP; - if (vs->alloctwobuffers) { + if (vs->hasTwoBuffers) { if (_vm->hasCharsetMask(sx * 8, y, (sx + 1) * 8, bottom)) { if (flag & dbClear || !lightsOn) clear8ColWithMasking(backbuff_ptr, height, mask_ptr); diff --git a/scumm/gfx.h b/scumm/gfx.h index 1aaca41b49..0f381ef3bb 100644 --- a/scumm/gfx.h +++ b/scumm/gfx.h @@ -55,19 +55,119 @@ enum VirtScreenNumber { kUnkVirtScreen = 3 // ?? Not sure what this one is good for... }; -/** Virtual screen areas */ +/** + * In all Scumm games, one to four virtual screen (or 'windows') together make + * up the content of the actual screen. Thinking of virtual screens as fixed + * size, fixed location windows might help understanding them. Typical, in all + * scumm games there is either one single virtual screen covering the entire + * real screen (mostly in all newer games, e.g. Sam & Max, and all V7+ games). + * The classic setup consists of three virtual screens: one at the top of the + * screen, where all conversation texts are printed; then the main one (which + * I like calling 'the stage', since all the actors are doing their stuff + * there), and finally the lower part of the real screen is taken up by the + * verb area. + * Finally, in V5 games and some V6 games, it's almost the same as in the + * original games, except that there is no separate conversation area. + * + * If you now wonder what the last screen is/was good for: I am not 100% sure, + * but it appears that it was used by the original engine to display stuff + * like the pause message, or questions ("Do you really want to restart?"). + * It seems that it is not used at all by ScummVM, so we probably could just + * get rid of it and save a couple kilobytes of RAM. + * + * Each of these virtual screens has a fixed number or id (see also the + * VirtScreenNumber enum). + */ struct VirtScreen { + /** + * The unique id of this screen (correponds to its position in the + * ScummEngine:virtscr array). + */ VirtScreenNumber number; + + /** + * Vertical position of the virtual screen. Tells how much the virtual + * screen is shifted along the y axis relative to the real screen. + * If you wonder why there is no horizontal position: there is none, + * because all virtual screens are always exactly as wide as the + * real screen. This might change in the future to allow smooth + * horizontal scrolling in V7-V8 games. + */ uint16 topline; - uint16 width, height; - byte alloctwobuffers; + + /** Width of the virtual screen (currently always identical to _screenWidth). */ + uint16 width; + + /** Height of the virtual screen. */ + uint16 height; + + /** + * Flag indicating that this virtual screen allows (horizontal) scrolling. + * This is always only true for the main screen (stage)! After all, verbs + * and the conversation text box don't have to scroll. + * @todo Get rid of this, there is only one place where it is used, + * and there it is trivial to remove the usage. + */ bool scrollable; + + /** + * Horizontal scroll offset, tells how far the screen is scrolled to the + * right. Only used for the main screen. + */ uint16 xstart; - uint16 tdirty[80]; - uint16 bdirty[80]; + + /** + * Flag indicating which tells whether this screen has a back buffer or + * not. This is yet another feature which is only used by the main screen. + * Strictly spoken one could remove this variable and replace checks + * on it with checks on backBuf. But since some code needs to temporarily + * disable the backBuf (so it can abuse drawBitmap; see drawVerbBitmap() + * and useIm01Cursor()), we keep it (at least for now). + */ + bool hasTwoBuffers; + + /** + * Pointer to the screen's data buffer. This is where the content of + * the screen is stored. Just as one would expect :-). + */ byte *screenPtr; + + /** + * Pointer to the screen's back buffer, if it has one (see also + * the hasTwoBuffers member). + * The backBuf is used by drawBitmap to store the background graphics of + * the active room. This eases redrawing: whenever a portion of the screen + * has to be redrawn, first a copy from the backBuf content to screenPtr is + * performed. Then, any objects/actors in that area are redrawn atop that. + */ byte *backBuf; + /** + * Array containing for each visible strip of this virtual screen the + * coordinate at which the dirty region of that strip starts. + * 't' stands for 'top' - the top coordinate of the dirty region. + * This together with bdirty is used to do efficient redrawing of + * the screen. + */ + uint16 tdirty[80]; + + /** + * Array containing for each visible strip of this virtual screen the + * coordinate at which the dirty region of that strip end. + * 'b' stands for 'bottom' - the bottom coordinate of the dirty region. + * This together with tdirty is used to do efficient redrawing of + * the screen. + */ + uint16 bdirty[80]; + + /** + * Convenience method to set the whole tdirty and bdirty arrays to one + * specific value each. This is mostly used to mark every as dirty in + * a single step, like so: + * vs->setDirtyRange(0, vs->height); + * or to mark everything as clean, like so: + * vs->setDirtyRange(0, 0); + */ void setDirtyRange(int top, int bottom) { for (int i = 0; i < 80; i++) { tdirty[i] = top; diff --git a/scumm/verbs.cpp b/scumm/verbs.cpp index 6891fc3a54..15fceedf1f 100644 --- a/scumm/verbs.cpp +++ b/scumm/verbs.cpp @@ -449,8 +449,8 @@ void ScummEngine::drawVerbBitmap(int verb, int x, int y) { gdi.disableZBuffer(); - twobufs = vs->alloctwobuffers; - vs->alloctwobuffers = 0; + twobufs = vs->hasTwoBuffers; + vs->hasTwoBuffers = 0; xstrip = x / 8; ydiff = y - vs->topline; @@ -499,7 +499,7 @@ void ScummEngine::drawVerbBitmap(int verb, int x, int y) { gdi.enableZBuffer(); - vs->alloctwobuffers = twobufs; + vs->hasTwoBuffers = twobufs; } int ScummEngine::getVerbSlot(int id, int mode) const { |