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 {  | 
