diff options
Diffstat (limited to 'engines')
49 files changed, 1474 insertions, 739 deletions
diff --git a/engines/cine/pal.h b/engines/cine/pal.h index 4764d5a474..26513eb5a1 100644 --- a/engines/cine/pal.h +++ b/engines/cine/pal.h @@ -36,7 +36,8 @@ namespace Cine {  #define kLowPalNumBytes ((kLowPalNumColors) * (kLowPalBytesPerColor))  /*! \brief Low resolution (9-bit) color format used in Cine's 16-color modes. */ -static const Graphics::PixelFormat kLowPalFormat  = {kLowPalBytesPerColor, 5, 5, 5, 8, 8, 4, 0, 0}; +	static const Graphics::PixelFormat kLowPalFormat(kLowPalBytesPerColor, 5, 5, 5, 8, 8, 4, 0, 0); +  // Constants related to kHighPalFormat  #define kHighPalBytesPerColor 3 @@ -44,10 +45,10 @@ static const Graphics::PixelFormat kLowPalFormat  = {kLowPalBytesPerColor, 5, 5,  #define kHighPalNumBytes ((kHighPalNumColors) * (kHighPalBytesPerColor))  /*! \brief High resolution (24-bit) color format used in Cine's 256-color modes. */ -static const Graphics::PixelFormat kHighPalFormat = {kHighPalBytesPerColor, 0, 0, 0, 8, 0, 8, 16, 0}; +static const Graphics::PixelFormat kHighPalFormat(kHighPalBytesPerColor, 0, 0, 0, 8, 0, 8, 16, 0);  /*! \brief The color format used by OSystem's setPalette-function. */ -static const Graphics::PixelFormat kSystemPalFormat = {4, 0, 0, 0, 8, 0, 8, 16, 0}; +static const Graphics::PixelFormat kSystemPalFormat(4, 0, 0, 0, 8, 0, 8, 16, 0);  /*! \brief Endian types. Used at least by Palette class's load and save functions.   * TODO: Move somewhere more general as this is definitely not Cine-engine specific diff --git a/engines/engine.cpp b/engines/engine.cpp index 0847e27246..eb46add82f 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -125,11 +125,21 @@ void initCommonGFX(bool defaultTo1XScaler) {  		g_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));  } -void initGraphics(int width, int height, bool defaultTo1xScaler) { +void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics::PixelFormat *format) { +  	g_system->beginGFXTransaction();  		initCommonGFX(defaultTo1xScaler); +#ifdef ENABLE_RGB_COLOR +		if (format) +			g_system->initSize(width, height, format); +		else {  +			Graphics::PixelFormat Format = g_system->getSupportedFormats().front(); +			g_system->initSize(width, height, &Format); +		} +#else  		g_system->initSize(width, height); +#endif  	OSystem::TransactionError gfxError = g_system->endGFXTransaction(); @@ -150,6 +160,15 @@ void initGraphics(int width, int height, bool defaultTo1xScaler) {  	}  	// Just show warnings then these occur: +#ifdef ENABLE_RGB_COLOR +	if (gfxError & OSystem::kTransactionFormatNotSupported) { +		Common::String message = "Could not initialize color format."; + +		GUI::MessageDialog dialog(message); +		dialog.runModal(); +	} +#endif +  	if (gfxError & OSystem::kTransactionModeSwitchFailed) {  		Common::String message = "Could not switch to video mode: '";  		message += ConfMan.get("gfx_mode"); @@ -169,6 +188,14 @@ void initGraphics(int width, int height, bool defaultTo1xScaler) {  		dialog.runModal();  	}  } +void initGraphics(int width, int height, bool defaultTo1xScaler, const Common::List<Graphics::PixelFormat> &formatList) { +	Graphics::PixelFormat format = Graphics::findCompatibleFormat(g_system->getSupportedFormats(),formatList); +	initGraphics(width,height,defaultTo1xScaler,&format); +} +void initGraphics(int width, int height, bool defaultTo1xScaler) { +	Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); +	initGraphics(width,height,defaultTo1xScaler,&format); +}  void GUIErrorMessage(const Common::String msg) {  	g_system->setWindowCaption("Error"); diff --git a/engines/engine.h b/engines/engine.h index ff3ce6c326..cd39c0065d 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -29,6 +29,7 @@  #include "common/error.h"  #include "common/fs.h"  #include "common/str.h" +#include "graphics/pixelformat.h"  class OSystem; @@ -58,8 +59,14 @@ void initCommonGFX(bool defaultTo1XScaler);   *   * Errors out when backend is not able to switch to the specified   * mode. + * + * Defaults to 256 color paletted mode if no graphics format is provided. + * Uses the backend's preferred format if graphics format pointer is NULL. + * Finds the best compatible format if a list of graphics formats is provided.   */  void initGraphics(int width, int height, bool defaultTo1xScaler); +void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics::PixelFormat *format); +void initGraphics(int width, int height, bool defaultTo1xScaler, const Common::List<Graphics::PixelFormat> &formatList);  /**   * Initializes graphics and shows error message. diff --git a/engines/gob/video_v6.cpp b/engines/gob/video_v6.cpp index c51b027bad..5468f7c89d 100644 --- a/engines/gob/video_v6.cpp +++ b/engines/gob/video_v6.cpp @@ -25,6 +25,7 @@  #include "common/endian.h"  #include "common/savefile.h" +#include "graphics/conversion.h"  #include "graphics/dither.h"  #include "gob/gob.h" @@ -45,8 +46,8 @@ void Video_v6::setPrePalette() {  	for (int i = 0; i < 256; i++) {  		byte r, g, b; -		Graphics::PaletteLUT::YUV2RGB(fpal[i * 3 + 0], fpal[i * 3 + 1], fpal[i * 3 + 2], -		                              r, g, b); +		Graphics::YUV2RGB(fpal[i * 3 + 0], fpal[i * 3 + 1], fpal[i * 3 + 2], +		                  r, g, b);  		tpal[i * 3 + 0] = r >> 2;  		tpal[i * 3 + 1] = g >> 2; diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp index 647eaa913b..1e54f0e79b 100644 --- a/engines/groovie/graphics.cpp +++ b/engines/groovie/graphics.cpp @@ -31,8 +31,8 @@ namespace Groovie {  GraphicsMan::GraphicsMan(GroovieEngine *vm) :  	_vm(vm), _changed(false), _fading(0) {  	// Create the game surfaces -	_foreground.create(640, 320, 1); -	_background.create(640, 320, 1); +	_foreground.create(640, 320, _vm->_pixelFormat.bytesPerPixel); +	_background.create(640, 320, _vm->_pixelFormat.bytesPerPixel);  }  GraphicsMan::~GraphicsMan() { diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 9381b5b47c..bb4e142196 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -70,7 +70,20 @@ GroovieEngine::~GroovieEngine() {  Common::Error GroovieEngine::run() {  	// Initialize the graphics -	initGraphics(640, 480, true); +	switch (_gameDescription->version) { +	case kGroovieV2: +		// Request the mode with the highest precision available +		initGraphics(640, 480, true, NULL); + +		// Save the enabled mode as it can be both an RGB mode or CLUT8 +		_pixelFormat = _system->getScreenFormat(); +		_mode8bit = (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8()); +		break; +	case kGroovieT7G: +		initGraphics(640, 480, true); +		_pixelFormat = Graphics::PixelFormat::createFormatCLUT8(); +		break; +	}  	// Create debugger. It requires GFX to be initialized  	_debugger = new Debugger(this); @@ -204,13 +217,18 @@ Common::Error GroovieEngine::run() {  			case Common::EVENT_LBUTTONDOWN:  				// Send the event to the scripts -				_script.setMouseClick(); +				_script.setMouseClick(1);  				// Continue the script execution to handle  				// the click  				_waitingForInput = false;  				break; +			case Common::EVENT_RBUTTONDOWN: +				// Send the event to the scripts (to skip the video) +				_script.setMouseClick(2); +				break; +  			case Common::EVENT_QUIT:  				quitGame();  				break; diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index a137193adf..bf57ae77de 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -85,6 +85,8 @@ protected:  public:  	void waitForInput(); +	Graphics::PixelFormat _pixelFormat; +	bool _mode8bit;  	Script _script;  	ResMan *_resMan;  	GrvCursorMan *_grvCursorMan; diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp index dcb8eafcb8..538b1b7111 100644 --- a/engines/groovie/roq.cpp +++ b/engines/groovie/roq.cpp @@ -29,6 +29,12 @@  #include "groovie/groovie.h"  #include "groovie/roq.h" +#include "graphics/jpeg.h" + +#ifdef ENABLE_RGB_COLOR +// Required for the YUV to RGB conversion +#include "graphics/conversion.h" +#endif  #include "sound/mixer.h"  namespace Groovie { @@ -43,50 +49,52 @@ ROQPlayer::ROQPlayer(GroovieEngine *vm) :  	_currBuf = new Graphics::Surface();  	_prevBuf = new Graphics::Surface(); -	byte pal[256 * 4]; +	if (_vm->_mode8bit) { +		byte pal[256 * 4];  #ifdef DITHER -	byte pal3[256 * 3]; -	// Initialize to a black palette -	for (int i = 0; i < 256 * 3; i++) { -		pal3[i] = 0; -	} - -	// Build a basic color palette -	for (int r = 0; r < 4; r++) { -		for (int g = 0; g < 4; g++) { -			for (int b = 0; b < 4; b++) { -				byte col = (r << 4) | (g << 2) | (b << 0); -				pal3[3 * col + 0] = r << 6; -				pal3[3 * col + 1] = g << 6; -				pal3[3 * col + 2] = b << 6; +		byte pal3[256 * 3]; +		// Initialize to a black palette +		for (int i = 0; i < 256 * 3; i++) { +			pal3[i] = 0; +		} + +		// Build a basic color palette +		for (int r = 0; r < 4; r++) { +			for (int g = 0; g < 4; g++) { +				for (int b = 0; b < 4; b++) { +					byte col = (r << 4) | (g << 2) | (b << 0); +					pal3[3 * col + 0] = r << 6; +					pal3[3 * col + 1] = g << 6; +					pal3[3 * col + 2] = b << 6; +				}  			}  		} -	} -	// Initialize the dithering algorithm -	_paletteLookup = new Graphics::PaletteLUT(8, Graphics::PaletteLUT::kPaletteYUV); -	_paletteLookup->setPalette(pal3, Graphics::PaletteLUT::kPaletteRGB, 8); -	for (int i = 0; (i < 64) && !_vm->shouldQuit(); i++) { -		debug("Groovie::ROQ: Building palette table: %02d/63", i); -		_paletteLookup->buildNext(); -	} +		// Initialize the dithering algorithm +		_paletteLookup = new Graphics::PaletteLUT(8, Graphics::PaletteLUT::kPaletteYUV); +		_paletteLookup->setPalette(pal3, Graphics::PaletteLUT::kPaletteRGB, 8); +		for (int i = 0; (i < 64) && !_vm->shouldQuit(); i++) { +			debug("Groovie::ROQ: Building palette table: %02d/63", i); +			_paletteLookup->buildNext(); +		} -	// Prepare the palette to show -	for (int i = 0; i < 256; i++) { -		pal[(i * 4) + 0] = pal3[(i * 3) + 0]; -		pal[(i * 4) + 1] = pal3[(i * 3) + 1]; -		pal[(i * 4) + 2] = pal3[(i * 3) + 2]; -	} -#else -	// Set a grayscale palette -	for (int i = 0; i < 256; i++) { -		pal[(i * 4) + 0] = i; -		pal[(i * 4) + 1] = i; -		pal[(i * 4) + 2] = i; -	} -#endif +		// Prepare the palette to show +		for (int i = 0; i < 256; i++) { +			pal[(i * 4) + 0] = pal3[(i * 3) + 0]; +			pal[(i * 4) + 1] = pal3[(i * 3) + 1]; +			pal[(i * 4) + 2] = pal3[(i * 3) + 2]; +		} +#else // !DITHER +		// Set a grayscale palette +		for (int i = 0; i < 256; i++) { +			pal[(i * 4) + 0] = i; +			pal[(i * 4) + 1] = i; +			pal[(i * 4) + 2] = i; +		} +#endif // DITHER -	_syst->setPalette(pal, 0, 256); +		_syst->setPalette(pal, 0, 256); +	}  }  ROQPlayer::~ROQPlayer() { @@ -152,22 +160,39 @@ void ROQPlayer::buildShowBuf() {  	for (int line = 0; line < _showBuf.h; line++) {  		byte *out = (byte *)_showBuf.getBasePtr(0, line); -		byte *in = (byte *)_prevBuf->getBasePtr(0, line / _scaleY); +		byte *in = (byte *)_currBuf->getBasePtr(0, line / _scaleY);  		for (int x = 0; x < _showBuf.w; x++) { +			if (_vm->_mode8bit) {  #ifdef DITHER -			*out = _dither->dither(*in, *(in + 1), *(in + 2), x); +				*out = _dither->dither(*in, *(in + 1), *(in + 2), x);  #else -			// Just use the luminancy component -			*out = *in; -#endif -			out++; +				// Just use the luminancy component +				*out = *in; +#endif // DITHER +#ifdef ENABLE_RGB_COLOR +			} else { +				// Do the format conversion (YUV -> RGB -> Screen format) +				byte r, g, b; +				Graphics::YUV2RGB(*in, *(in + 1), *(in + 2), r, g, b); +				// FIXME: this is fixed to 16bit +				*(uint16 *)out = (uint16)_vm->_pixelFormat.RGBToColor(r, g, b); +#endif // ENABLE_RGB_COLOR +			} + +			// Skip to the next pixel +			out += _vm->_pixelFormat.bytesPerPixel;  			if (!(x % _scaleX)) -				in += _prevBuf->bytesPerPixel; +				in += _currBuf->bytesPerPixel;  		}  #ifdef DITHER  		_dither->nextLine();  #endif  	} + +	// Swap buffers +	Graphics::Surface *tmp = _prevBuf; +	_prevBuf = _currBuf; +	_currBuf = tmp;  }  bool ROQPlayer::playFrameInternal() { @@ -180,7 +205,7 @@ bool ROQPlayer::playFrameInternal() {  	}  	if (_dirty) { -		// Build the show buffer from the previous (back) buffer +		// Build the show buffer from the current buffer  		buildShowBuf();  	} @@ -189,7 +214,7 @@ bool ROQPlayer::playFrameInternal() {  	if (_dirty) {  		// Update the screen -		_syst->copyRectToScreen((byte *)_showBuf.getBasePtr(0, 0), _showBuf.w, 0, (_syst->getHeight() - _showBuf.h) / 2, _showBuf.pitch, _showBuf.h); +		_syst->copyRectToScreen((byte *)_showBuf.getBasePtr(0, 0), _showBuf.pitch, 0, (_syst->getHeight() - _showBuf.h) / 2, _showBuf.w, _showBuf.h);  		_syst->updateScreen();  		// Clear the dirty flag @@ -240,19 +265,15 @@ bool ROQPlayer::processBlock() {  	case 0x1002: // Quad codebook definition  		ok = processBlockQuadCodebook(blockHeader);  		break; -	case 0x1011: { // Quad vector quantised video frame +	case 0x1011: // Quad vector quantised video frame  		ok = processBlockQuadVector(blockHeader);  		_dirty = true;  		endframe = true; - -		// Swap buffers -		Graphics::Surface *tmp = _prevBuf; -		_prevBuf = _currBuf; -		_currBuf = tmp;  		break; -	}  	case 0x1012: // Still image (JPEG)  		ok = processBlockStill(blockHeader); +		_dirty = true; +		endframe = true;  		break;  	case 0x1013: // Hang  		assert(blockHeader.size == 0 && blockHeader.param == 0); @@ -317,7 +338,19 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {  		// Allocate new buffers  		_currBuf->create(width, height, 3);  		_prevBuf->create(width, height, 3); -		_showBuf.create(width * _scaleX, height * _scaleY, 1); +		_showBuf.create(width * _scaleX, height * _scaleY, _vm->_pixelFormat.bytesPerPixel); + +		// Clear the buffers with black YUV values +		byte *ptr1 = (byte *)_currBuf->getBasePtr(0, 0); +		byte *ptr2 = (byte *)_prevBuf->getBasePtr(0, 0); +		for (int i = 0; i < width * height; i++) { +			*ptr1++ = 0; +			*ptr1++ = 128; +			*ptr1++ = 128; +			*ptr2++ = 0; +			*ptr2++ = 128; +			*ptr2++ = 128; +		}  #ifdef DITHER  		// Reset the dithering algorithm with the new width @@ -456,10 +489,23 @@ void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, in  bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) {  	debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing still (JPEG) block"); -	warning("Groovie::ROQ: JPEG frame (unimplemented)"); -	memset(_prevBuf->getBasePtr(0, 0), 0, _prevBuf->w * _prevBuf->h * _prevBuf->bytesPerPixel); +	warning("Groovie::ROQ: JPEG frame (unfinshed)"); + +	Graphics::JPEG *jpg = new Graphics::JPEG(); +	jpg->read(_file); +	byte *y = (byte *)jpg->getComponent(1)->getBasePtr(0, 0); +	byte *u = (byte *)jpg->getComponent(2)->getBasePtr(0, 0); +	byte *v = (byte *)jpg->getComponent(3)->getBasePtr(0, 0); + +	byte *ptr = (byte *)_currBuf->getBasePtr(0, 0); +	for (int i = 0; i < _currBuf->w * _currBuf->h; i++) { +		*ptr++ = *y++; +		*ptr++ = *u++; +		*ptr++ = *v++; +	} +	memcpy(_prevBuf->getBasePtr(0, 0), _currBuf->getBasePtr(0, 0), _prevBuf->w * _prevBuf->h * 3); -	_file->skip(blockHeader.size); +	delete jpg;  	return true;  } diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index 5ee58184f2..97d8d24f77 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -102,6 +102,7 @@ Script::Script(GroovieEngine *vm, EngineVersion version) :  	_hotspotSlot = (uint16)-1;  	_oldInstruction = (uint16)-1; +	_videoSkipAddress = 0;  }  Script::~Script() { @@ -235,8 +236,8 @@ void Script::step() {  	(this->*op)();  } -void Script::setMouseClick() { -	_eventMouseClicked = true; +void Script::setMouseClick(uint8 button) { +	_eventMouseClicked = button;  }  void Script::setKbdChar(uint8 c) { @@ -359,7 +360,7 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {  	    Common::isDebugChannelEnabled(kGroovieDebugAll)) {  		rect.translate(0, -80);  		_vm->_graphicsMan->_foreground.frameRect(rect, 250); -		_vm->_system->copyRectToScreen((byte*)_vm->_graphicsMan->_foreground.getBasePtr(0, 0), 640, 0, 80, 640, 320); +		_vm->_system->copyRectToScreen((byte*)_vm->_graphicsMan->_foreground.getBasePtr(0, 0), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320);  		_vm->_system->updateScreen();  	} @@ -530,7 +531,6 @@ void Script::o_videofromref() {			// 0x09  bool Script::playvideofromref(uint32 fileref) {  	// It isn't the current video, open it  	if (fileref != _videoRef) { -  		// Debug bitflags  		debugScript(1, false, "Play video 0x%04X (bitflags:", fileref);  		for (int i = 15; i >= 0; i--) { @@ -559,6 +559,21 @@ bool Script::playvideofromref(uint32 fileref) {  		}  		_bitflags = 0; + +		// Reset the clicked mouse events +		_eventMouseClicked = 0; +	} + +	// Check if the user wants to skip the video +	if ((_eventMouseClicked == 2) && (_videoSkipAddress != 0)) { +		// Jump to the given address +		_currentInstruction = _videoSkipAddress; + +		// Reset the skip address +		_videoSkipAddress = 0; + +		// End the playback +		return true;  	}  	// Video available, play one frame @@ -573,7 +588,7 @@ bool Script::playvideofromref(uint32 fileref) {  			_videoRef = 0;  			// Clear the input events while playing the video -			_eventMouseClicked = false; +			_eventMouseClicked = 0;  			_eventKbdChar = 0;  			// Newline @@ -604,8 +619,8 @@ void Script::o_inputloopstart() {	//0x0B  	_inputLoopAddress = _currentInstruction - 1;  	// Save the current mouse state for the whole loop -	_mouseClicked = _eventMouseClicked; -	_eventMouseClicked = false; +	_mouseClicked = (_eventMouseClicked == 1); +	_eventMouseClicked = 0;  	// Save the current pressed character for the whole loop  	_kbdChar = _eventKbdChar; @@ -1535,20 +1550,19 @@ void Script::o_stub59() {  	debugScript(1, true, "STUB59: 0x%04X 0x%02X", val1, val2);  } -void Script::o2_playsong(){ +void Script::o2_playsong() {  	uint32 fileref = readScript32bits();  	debugScript(1, true, "PlaySong(0x%08X): Play xmidi file", fileref);  	_vm->_musicPlayer->playSong(fileref); -  } -void Script::o2_setbackgroundsong(){ +void Script::o2_setbackgroundsong() {  	uint32 fileref = readScript32bits();  	debugScript(1, true, "SetBackgroundSong(0x%08X)", fileref);  	_vm->_musicPlayer->setBackgroundSong(fileref);  } -void Script::o2_videofromref(){ +void Script::o2_videofromref() {  	uint32 fileref = readScript32bits();  	// Show the debug information just when starting the playback @@ -1556,6 +1570,7 @@ void Script::o2_videofromref(){  		debugScript(1, true, "VIDEOFROMREF(0x%08X) (Not fully imp): Play video file from ref", fileref);  		debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%08X via 0x09", fileref);  	} +  	// Play the video  	if (!playvideofromref(fileref)) {  		// Move _currentInstruction back @@ -1563,7 +1578,7 @@ void Script::o2_videofromref(){  	}  } -void Script::o2_vdxtransition(){ +void Script::o2_vdxtransition() {  	uint32 fileref = readScript32bits();  	// Show the debug information just when starting the playback @@ -1587,11 +1602,21 @@ void Script::o2_vdxtransition(){  	}  } -void Script::o2_stub52(){ +void Script::o2_setvideoskip() { +	_videoSkipAddress = readScript16bits(); +	debugScript(1, true, "SetVideoSkip (0x%04X)", _videoSkipAddress); +} + +void Script::o2_stub52() {  	uint8 arg = readScript8bits();  	debugScript(1, true, "STUB52 (0x%02X)", arg);  } +void Script::o2_setscriptend() { +	uint16 arg = readScript16bits(); +	debugScript(1, true, "SetScriptEnd (0x%04X)", arg); +} +  Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = {  	&Script::o_nop, // 0x00  	&Script::o_nop, @@ -1692,11 +1717,11 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {  	&Script::o_invalid, // 0x00  	&Script::o_nop,  	&Script::o2_playsong, -	&Script::o_bf9on, -	&Script::o_palfadeout, // 0x04 -	&Script::o_bf8on, -	&Script::o_bf6on, -	&Script::o_bf7on, +	&Script::o_nop, +	&Script::o_nop, // 0x04 +	&Script::o_nop, +	&Script::o_nop, +	&Script::o_nop,  	&Script::o2_setbackgroundsong, // 0x08  	&Script::o2_videofromref,  	&Script::o_bf5on, @@ -1719,7 +1744,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {  	&Script::o_xor_obfuscate,  	&Script::o2_vdxtransition, // 0x1C  	&Script::o_swap, -	&Script::o_nop8, +	&Script::o_invalid,  	&Script::o_inc,  	&Script::o_dec, // 0x20  	&Script::o_strcmpnejmp_var, @@ -1729,10 +1754,10 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {  	&Script::o_add,  	&Script::o_videofromstring1,  	&Script::o_videofromstring2, -	&Script::o_nop16, // 0x28 -	&Script::o_stopmidi, -	&Script::o_endscript, +	&Script::o_invalid, // 0x28  	&Script::o_nop, +	&Script::o_endscript, +	&Script::o_invalid,  	&Script::o_sethotspottop, // 0x2C  	&Script::o_sethotspotbottom,  	&Script::o_loadgame, @@ -1759,22 +1784,22 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {  	&Script::o_returnscript,  	&Script::o_sethotspotright, // 0x44  	&Script::o_sethotspotleft, -	&Script::o_nop, -	&Script::o_nop, -	&Script::o_nop8, // 0x48 -	&Script::o_nop, -	&Script::o_nop16, -	&Script::o_nop8, -	&Script::o_getcd, // 0x4C -	&Script::o_playcd, +	&Script::o_invalid, +	&Script::o_invalid, +	&Script::o_invalid, // 0x48 +	&Script::o_invalid,  	&Script::o_nop16, +	&Script::o_invalid, +	&Script::o_invalid, // 0x4C +	&Script::o_invalid, +	&Script::o_invalid,  	&Script::o_nop16,  	&Script::o_nop16, // 0x50 -	&Script::o_nop16, +	&Script::o2_setvideoskip,  	&Script::o2_stub52,  	&Script::o_hotspot_outrect, -	&Script::o_nop, // 0x54 -	&Script::o_nop16, +	&Script::o_invalid, // 0x54 +	&Script::o2_setscriptend,  	&Script::o_stub56,  	&Script::o_invalid,  	&Script::o_invalid, // 0x58 diff --git a/engines/groovie/script.h b/engines/groovie/script.h index e9e0be69ec..9e35d6fcde 100644 --- a/engines/groovie/script.h +++ b/engines/groovie/script.h @@ -58,7 +58,7 @@ public:  	void directGameLoad(int slot);  	void step(); -	void setMouseClick(); +	void setMouseClick(uint8 button);  	void setKbdChar(uint8 c);  	Common::String &getContext(); @@ -96,7 +96,7 @@ private:  	// Input  	bool _mouseClicked; -	bool _eventMouseClicked; +	uint8 _eventMouseClicked;  	uint8 _kbdChar;  	uint8 _eventKbdChar;  	uint16 _inputLoopAddress; @@ -115,6 +115,7 @@ private:  	Common::SeekableReadStream *_videoFile;  	uint32 _videoRef;  	uint16 _bitflags; +	uint16 _videoSkipAddress;  	// Debugging  	Debugger *_debugger; @@ -228,7 +229,9 @@ private:  	void o2_setbackgroundsong();  	void o2_videofromref();  	void o2_vdxtransition(); +	void o2_setvideoskip();  	void o2_stub52(); +	void o2_setscriptend();  };  } // End of Groovie namespace diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index 0b1387074c..b71152822c 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -27,18 +27,19 @@  #include "common/system.h"  #include "graphics/cursorman.h"  #include "graphics/primitives.h" +#include "graphics/surface.h"  #include "sci/sci.h"  #include "sci/gfx/gfx_driver.h"  #include "sci/gfx/gfx_tools.h" +  namespace Sci { -GfxDriver::GfxDriver(int xfact, int yfact, int bytespp) { +GfxDriver::GfxDriver(int xfact, int yfact, Graphics::PixelFormat format) {  	int i; -	Graphics::PixelFormat format = { bytespp, 0, 0, 0, 0, 0, 0, 0, 0 }; -	_mode = gfx_new_mode(xfact, yfact, format, new Palette(256), 0); +	_mode = gfx_new_mode(xfact, yfact, format, format.bytesPerPixel == 1 ? new Palette(256) : 0, 0);  	_mode->xsize = xfact * 320;  	_mode->ysize = yfact * 200; @@ -51,14 +52,15 @@ GfxDriver::GfxDriver(int xfact, int yfact, int bytespp) {  	// create the visual buffers  	for (i = 0; i < 2; i++) {  		_visual[i] = NULL; -		_visual[i] = new byte[_mode->xsize * _mode->ysize]; +		_visual[i] = new byte[_mode->xsize * _mode->ysize * _mode->bytespp];  		if (!_visual[i]) {  			error("Out of memory: Could not allocate visual buffers! (%dx%d)\n", _mode->xsize, _mode->ysize);  		} -		memset(_visual[i], 0, _mode->xsize * _mode->ysize); +		memset(_visual[i], 0, _mode->xsize * _mode->ysize * _mode->bytespp);  	} -	_mode->palette->name = "global"; +	if (_mode->palette) +		_mode->palette->name = "global";  }  GfxDriver::~GfxDriver() { @@ -77,10 +79,12 @@ GfxDriver::~GfxDriver() {  // Drawing operations +template<int COPY_BYTES, typename SIZETYPE, int EXTRA_BYTE_OFFSET>  static void drawProc(int x, int y, int c, void *data) {  	GfxDriver *drv = (GfxDriver *)data;  	byte *p = drv->getVisual0(); -	p[y * 320* drv->getMode()->xfact + x] = c; +	SIZETYPE col = c << (EXTRA_BYTE_OFFSET * 8); +	memcpy(p + (y * 320* drv->getMode()->xfact + x) * COPY_BYTES, &col, COPY_BYTES);  }  int GfxDriver::drawLine(Common::Point start, Common::Point end, gfx_color_t color,  @@ -91,6 +95,28 @@ int GfxDriver::drawLine(Common::Point start, Common::Point end, gfx_color_t colo  	int xsize = _mode->xsize;  	int ysize = _mode->ysize; +	void (*modeDrawProc)(int,int,int,void*); +	switch (_mode->bytespp) { +	case 1: +		modeDrawProc = drawProc<1, uint8, 0>; +		break; +	case 2: +		modeDrawProc = drawProc<2, uint16, 0>; +		break; +	case 3: +#ifdef SCUMM_BIG_ENDIAN +		modeDrawProc = drawProc<3, uint32, 1>; +#else +		modeDrawProc = drawProc<3, uint32, 0>; +#endif +		break; +	case 4: +		modeDrawProc = drawProc<4, uint32, 0>; +		break; +	default: +		error("Invalid mode->bytespp=%d", _mode->bytespp); +	} +  	if (color.mask & GFX_MASK_VISUAL) {  		Common::Point nstart, nend; @@ -102,7 +128,7 @@ int GfxDriver::drawLine(Common::Point start, Common::Point end, gfx_color_t colo  				nend.x = CLIP<int16>(end.x + xc, 0, xsize - 1);  				nend.y = CLIP<int16>(end.y + yc, 0, ysize - 1); -				Graphics::drawLine(nstart.x, nstart.y, nend.x, nend.y, scolor, drawProc, this); +				Graphics::drawLine(nstart.x, nstart.y, nend.x, nend.y, scolor, modeDrawProc, this);  				if (color.mask & GFX_MASK_PRIORITY) {  					gfx_draw_line_pixmap_i(_priority[0], nstart, nend, color.priority); @@ -118,7 +144,8 @@ int GfxDriver::drawFilledRect(rect_t rect, gfx_color_t color1, gfx_color_t color  	gfx_rectangle_fill_t shade_mode) {  	if (color1.mask & GFX_MASK_VISUAL) {  		for (int i = rect.y; i < rect.y + rect.height; i++) { -			memset(_visual[0] + i * _mode->xsize + rect.x, color1.visual.parent_index, rect.width); +			memset(_visual[0] + (i * _mode->xsize + rect.x) * _mode->bytespp, +			       color1.visual.parent_index, rect.width * _mode->bytespp);  		}  	} @@ -138,8 +165,10 @@ int GfxDriver::drawPixmap(gfx_pixmap_t *pxm, int priority, rect_t src, rect_t de  		return GFX_ERROR;  	} -	gfx_crossblit_pixmap(_mode, pxm, priority, src, dest, _visual[bufnr], _mode->xsize, -	                     _priority[bufnr]->index_data, _priority[bufnr]->index_width, 1, 0); +	gfx_crossblit_pixmap(_mode, pxm, priority, src, dest, _visual[bufnr], +	                     _mode->xsize * _mode->bytespp, +	                     _priority[bufnr]->index_data, +	                     _priority[bufnr]->index_width, 1, 0);  	return GFX_OK;  } @@ -161,7 +190,9 @@ int GfxDriver::grabPixmap(rect_t src, gfx_pixmap_t *pxm, gfx_map_mask_t map) {  		pxm->width = src.width;  		pxm->height = src.height;  		for (int i = 0; i < src.height; i++) { -			memcpy(pxm->data + i * src.width, _visual[0] + (i + src.y) * _mode->xsize + src.x, src.width); +			memcpy(pxm->data + i * src.width * _mode->bytespp, +			       _visual[0] + _mode->bytespp * ((i + src.y) * _mode->xsize + src.x), +			       src.width * _mode->bytespp);  		}  		break; @@ -193,17 +224,18 @@ int GfxDriver::update(rect_t src, Common::Point dest, gfx_buffer_t buffer) {  	switch (buffer) {  	case GFX_BUFFER_BACK:  		for (int i = 0; i < src.height; i++) { -			memcpy(_visual[0] + (dest.y + i) * _mode->xsize + dest.x, -			       _visual[1] + (src.y + i) * _mode->xsize + src.x, src.width); +			memcpy(_visual[0] + _mode->bytespp * ( (dest.y + i) * _mode->xsize + dest.x), +			       _visual[1] + _mode->bytespp * ( (src.y + i) * _mode->xsize + src.x), src.width * _mode->bytespp );  		}  		if ((src.x == dest.x) && (src.y == dest.y))  			gfx_copy_pixmap_box_i(_priority[0], _priority[1], src);  		break; -	case GFX_BUFFER_FRONT: -		g_system->copyRectToScreen(_visual[0] + src.x + src.y * _mode->xsize, _mode->xsize, dest.x, dest.y, src.width, src.height); +	case GFX_BUFFER_FRONT: { +		g_system->copyRectToScreen(_visual[0] + _mode->bytespp * (src.x + src.y * _mode->xsize), _mode->xsize * _mode->bytespp, dest.x, dest.y, src.width, src.height);  		g_system->updateScreen();  		break; +	}  	default:  		error("Invalid buffer %d in update", buffer);  		return GFX_ERROR; @@ -213,7 +245,7 @@ int GfxDriver::update(rect_t src, Common::Point dest, gfx_buffer_t buffer) {  }  int GfxDriver::setStaticBuffer(gfx_pixmap_t *pic, gfx_pixmap_t *priority) { -	memcpy(_visual[1], pic->data, _mode->xsize * _mode->ysize); +	memcpy(_visual[1], pic->data, _mode->xsize * _mode->ysize * _mode->bytespp);  	gfx_copy_pixmap_box_i(_priority[1], priority, gfx_rect(0, 0, _mode->xsize, _mode->ysize));  	return GFX_OK; diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h index f7cbd0b6c2..cc8a5208d4 100644 --- a/engines/sci/gfx/gfx_driver.h +++ b/engines/sci/gfx/gfx_driver.h @@ -29,6 +29,8 @@  #include "sci/gfx/gfx_system.h"  #include "sci/uinput.h" +#include "graphics/pixelformat.h" +  namespace Sci {  enum gfx_buffer_t { @@ -85,7 +87,7 @@ public:  	 * 						not be set, or GFX_FATAL if the graphics target  	 * 						is unuseable.  	 */ -	GfxDriver(int xfact, int yfact, int bytespp); +	GfxDriver(int xfact, int yfact, Graphics::PixelFormat mode);  	/**  	 * Uninitializes the current graphics mode. diff --git a/engines/sci/gfx/gfx_pixmap_scale.cpp b/engines/sci/gfx/gfx_pixmap_scale.cpp index 034efafe8d..41e6102cbd 100644 --- a/engines/sci/gfx/gfx_pixmap_scale.cpp +++ b/engines/sci/gfx/gfx_pixmap_scale.cpp @@ -70,14 +70,11 @@ void _gfx_xlate_pixmap_unfiltered(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale  	// Calculate all colors  	for (i = 0; i < pxm->colors_nr(); i++) {  		int col; -  		const PaletteEntry& color = pxm->palette->getColor(i);  		if (mode->palette)  			col = color.parent_index;  		else { -			col = mode->red_mask & ((EXTEND_COLOR(color.r)) >> mode->red_shift); -			col |= mode->green_mask & ((EXTEND_COLOR(color.g)) >> mode->green_shift); -			col |= mode->blue_mask & ((EXTEND_COLOR(color.b)) >> mode->blue_shift); +			col = mode->format.ARGBToColor(0, color.r, color.g, color.b);  			col |= alpha_ormask;  		}  		result_colors[i] = col; diff --git a/engines/sci/gfx/gfx_resmgr.cpp b/engines/sci/gfx/gfx_resmgr.cpp index 5619a896cf..a5596d1e4a 100644 --- a/engines/sci/gfx/gfx_resmgr.cpp +++ b/engines/sci/gfx/gfx_resmgr.cpp @@ -269,7 +269,8 @@ void GfxResManager::setStaticPalette(Palette *newPalette)  	_staticPalette = newPalette;  	_staticPalette->name = "static palette"; -	_staticPalette->mergeInto(_driver->getMode()->palette); +	if (_driver->getMode()->palette) +		_staticPalette->mergeInto(_driver->getMode()->palette);  }  #if 0 @@ -320,7 +321,8 @@ gfx_mode_t mode_1x1_color_index = { /* Fake 1x1 mode */  	/* palette */ NULL,  	/* color masks */ 0, 0, 0, 0, -	/* color shifts */ 0, 0, 0, 0 +	/* color shifts */ 0, 0, 0, 0, +	Graphics::PixelFormat()  };  gfxr_pic_t *GfxResManager::getPic(int num, int maps, int flags, int default_palette, bool scaled) { diff --git a/engines/sci/gfx/gfx_system.h b/engines/sci/gfx/gfx_system.h index 20c92efa2d..0f5292aedf 100644 --- a/engines/sci/gfx/gfx_system.h +++ b/engines/sci/gfx/gfx_system.h @@ -30,6 +30,7 @@  #include "common/rect.h"  #include "sci/tools.h"  #include "sci/gfx/palette.h" +#include "graphics/pixelformat.h"  namespace Sci { @@ -74,8 +75,10 @@ struct gfx_mode_t {  	 */  	Palette *palette; +	// TODO: remove those  	uint32 red_mask, green_mask, blue_mask, alpha_mask;  	short red_shift, green_shift, blue_shift, alpha_shift; +	Graphics::PixelFormat format;  }; diff --git a/engines/sci/gfx/gfx_tools.cpp b/engines/sci/gfx/gfx_tools.cpp index e3d35ecb14..9e81ec1a8a 100644 --- a/engines/sci/gfx/gfx_tools.cpp +++ b/engines/sci/gfx/gfx_tools.cpp @@ -49,6 +49,7 @@ gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &form  	mode->xfact = xfact;  	mode->yfact = yfact;  	mode->bytespp = format.bytesPerPixel; +	mode->format = format;  	// FIXME: I am not sure whether the following assignments are quite right.  	// The only code using these are the built-in scalers of the SCI engine. @@ -60,10 +61,10 @@ gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &form  		mode->green_mask = format.ARGBToColor(0, 0, 0xFF, 0);  		mode->blue_mask = format.ARGBToColor(0, 0, 0, 0xFF);  		mode->alpha_mask = format.ARGBToColor(0xFF, 0, 0, 0); -		mode->red_shift = format.rLoss; -		mode->green_shift = format.gLoss; -		mode->blue_shift = format.bLoss; -		mode->alpha_shift = format.aLoss; +		mode->red_shift = format.rShift; +		mode->green_shift = format.gShift; +		mode->blue_shift = format.bShift; +		mode->alpha_shift = format.aShift;  	} else {  		mode->red_mask = mode->green_mask = mode->blue_mask = 0;  		mode->alpha_mask = 0; diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index 94bb6e0443..b3a1be68d1 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -404,8 +404,9 @@ static void init_aux_pixmap(gfx_pixmap_t **pixmap) {  	(*pixmap)->palette = new Palette(default_colors, DEFAULT_COLORS_NR);  } -int gfxop_init(int version, GfxState *state, gfx_options_t *options, ResourceManager *resManager, -			   int xfact, int yfact, gfx_color_mode_t bpp) { +int gfxop_init(int version, GfxState *state, +				gfx_options_t *options, ResourceManager *resManager, +				Graphics::PixelFormat mode, int xfact, int yfact) {  	//int color_depth = bpp ? bpp : 1;  	//int initialized = 0; @@ -421,7 +422,7 @@ int gfxop_init(int version, GfxState *state, gfx_options_t *options, ResourceMan  	state->pic_port_bounds = gfx_rect(0, 10, 320, 190);  	state->_dirtyRects.clear(); -	state->driver = new GfxDriver(xfact, yfact, bpp); +	state->driver = new GfxDriver(xfact, yfact, mode);  	state->gfxResMan = new GfxResManager(state->options, state->driver, resManager); @@ -1131,8 +1132,10 @@ static int _gfxop_set_pointer(GfxState *state, gfx_pixmap_t *pxm, Common::Point  	// may change when a new PIC is loaded. The cursor has to be regenerated  	// from this pxm at that point. (An alternative might be to ensure the  	// cursor only uses colours in the static part of the palette?) -	if (pxm && pxm->palette) +	if (pxm && state->driver->getMode()->palette) { +		assert(pxm->palette);  		pxm->palette->mergeInto(state->driver->getMode()->palette); +	}  	state->driver->setPointer(pxm, hotspot);  	return GFX_OK; @@ -1736,7 +1739,7 @@ int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette) {  	if (state->driver->getMode()->xfact == 1 && state->driver->getMode()->yfact == 1) {  		state->pic_unscaled = state->pic;  	} else { -		state->pic = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, false); +		state->pic_unscaled = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, false);  	}  	if (!state->pic || !state->pic_unscaled) { diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h index b9a16d4a27..ec0a810224 100644 --- a/engines/sci/gfx/operations.h +++ b/engines/sci/gfx/operations.h @@ -138,17 +138,16 @@ struct GfxState {   * @param[in] state			The state to initialize   * @param[in] xfact			Horizontal scale factor   * @param[in] yfact			Vertical scale factors - * @param[in] bpp			Bytes per pixel to initialize with, or 0 - * 							(GFX_COLOR_MODE_AUTO) to auto-detect + * @param[in] mode			Graphics mode to use   * @param[in] options		Rendering options   * @param[in] resManager	Resource manager to use   * @return					GFX_OK on success, GFX_ERROR if that particular mode   * 							is unavailable, or GFX_FATAL if the graphics driver   * 							is unable to provide any useful graphics support   */ -int gfxop_init(int version, GfxState *state, gfx_options_t *options, -	ResourceManager *resManager, int xfact = 1, int yfact = 1, -	gfx_color_mode_t bpp = GFX_COLOR_MODE_INDEX); +int gfxop_init(int version, GfxState *state,  +		gfx_options_t *options, ResourceManager *resManager, +		Graphics::PixelFormat mode, int xfact = 1, int yfact = 1);  /**   * Deinitializes a currently active driver. diff --git a/engines/sci/gfx/res_pic.cpp b/engines/sci/gfx/res_pic.cpp index e7b34976b0..6c35ad314e 100644 --- a/engines/sci/gfx/res_pic.cpp +++ b/engines/sci/gfx/res_pic.cpp @@ -1548,7 +1548,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size,  				view->index_height = CLIP<int>(view->index_height, 0, portBounds.height());  				// Set up mode structure for resizing the view -				Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1byte/p, which handles masks and the rest for us +				Graphics::PixelFormat format(1, 0, 0, 0, 0, 0, 0, 0, 0); // 1byte/p, which handles masks and the rest for us  				gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_width / 320,  				           pic->visual_map->index_height / 200, format, view->palette, 0); @@ -1654,7 +1654,7 @@ void gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size,  		view->palette = pic->visual_map->palette->getref();  		// Set up mode structure for resizing the view -		Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1 byte/p, which handles masks and the rest for us +		Graphics::PixelFormat format(1, 0, 0, 0, 0, 0, 0, 0, 0); // 1 byte/p, which handles masks and the rest for us  		gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_width / 320, pic->visual_map->index_height / 200, format, view->palette, 0);  		gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 53e3e7ab9c..596895d1cb 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -111,7 +111,13 @@ SciEngine::~SciEngine() {  }  Common::Error SciEngine::run() { +	Graphics::PixelFormat gfxmode; +#ifdef ENABLE_RGB_COLOR +	initGraphics(320, 200, false, NULL); +#else  	initGraphics(320, 200, false); +#endif +	gfxmode = _system->getScreenFormat();  	// Create debugger console. It requires GFX to be initialized  	_console = new Console(this); @@ -190,7 +196,7 @@ Common::Error SciEngine::run() {  	// Default config ends  #endif -	if (gfxop_init(_resmgr->sciVersion(), &gfx_state, &gfx_options, _resmgr)) { +	if (gfxop_init(_resmgr->sciVersion(), &gfx_state, &gfx_options, _resmgr, gfxmode, 1, 1)) {  		warning("Graphics initialization failed. Aborting...");  		return Common::kUnknownError;  	} diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 3033904357..9dab776b67 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -2451,7 +2451,7 @@ void ScummEngine_v71he::postProcessAuxQueue() {  					uint8 *dst2 = pvs->getBackPixels(0, pvs->topline);  					switch (comp) {  					case 1: -						Wiz::copyAuxImage(dst1, dst2, axfd + 10, pvs->w, pvs->h, x, y, w, h); +						Wiz::copyAuxImage(dst1, dst2, axfd + 10, pvs->pitch, pvs->h, x, y, w, h, _bitDepth);  						break;  					default:  						error("unimplemented compression type %d", comp); @@ -2551,9 +2551,10 @@ void Actor::saveLoadWithSerializer(Serializer *ser) {  		MKLINE(Actor, _flip, sleByte, VER(32)),  		MKLINE(Actor, _heSkipLimbs, sleByte, VER(32)), -		// Actor palette grew from 64 to 256 bytes +		// Actor palette grew from 64 to 256 bytes and switched to uint16 in HE games  		MKARRAY_OLD(Actor, _palette[0], sleByte, 64, VER(8), VER(9)), -		MKARRAY(Actor, _palette[0], sleByte, 256, VER(10)), +		MKARRAY_OLD(Actor, _palette[0], sleByte, 256, VER(10), VER(79)), +		MKARRAY(Actor, _palette[0], sleUint16, 256, VER(80)),  		MK_OBSOLETE(Actor, _mask, sleByte, VER(8), VER(9)),  		MKLINE(Actor, _shadowMode, sleByte, VER(8)), diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h index 3f67d42a50..c3edd24a39 100644 --- a/engines/scumm/actor.h +++ b/engines/scumm/actor.h @@ -157,7 +157,7 @@ protected:  	}; -	byte _palette[256]; +	uint16 _palette[256];  	int _elevation;  	uint16 _facing;  	uint16 _targetFacing; diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp index ab7db2c4a7..f4bb8a2c8b 100644 --- a/engines/scumm/akos.cpp +++ b/engines/scumm/akos.cpp @@ -289,7 +289,7 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {  	} while ((uint16)mask);  } -void AkosRenderer::setPalette(byte *new_palette) { +void AkosRenderer::setPalette(uint16 *new_palette) {  	uint size, i;  	size = _vm->getResourceDataSize(akpl); @@ -299,22 +299,23 @@ void AkosRenderer::setPalette(byte *new_palette) {  	if (size > 256)  		error("akos_setPalette: %d is too many colors", size); -	if (_vm->_game.heversion >= 99 && _paletteNum) { -		for (i = 0; i < size; i++) -			_palette[i] = (byte)_vm->_hePalettes[_paletteNum * 1024 + 768 + akpl[i]]; -	} else if ((_vm->_game.features & GF_16BIT_COLOR) && rgbs) { -		for (i = 0; i < size; i++) { -			if (new_palette[i] == 0xFF) { -				uint8 col = akpl[i]; -				uint8 r = rgbs[col * 3 + 0]; -				uint8 g = rgbs[col * 3 + 1]; -				uint8 b = rgbs[col * 3 + 2]; - -				_palette[i] = _vm->remapPaletteColor(r, g, b, -1); -			} else { -				_palette[i] = new_palette[i]; +	if (_vm->_game.features & GF_16BIT_COLOR) { +		if (_paletteNum) { +			for (i = 0; i < size; i++) +				_palette[i] = READ_LE_UINT16(_vm->_hePalettes + _paletteNum * _vm->_hePaletteSlot + 768 + akpl[i] * 2); +		} else if (rgbs) { +			for (i = 0; i < size; i++) { +				if (new_palette[i] == 0xFF) { +					uint8 col = akpl[i]; +					_palette[i] = _vm->get16BitColor(rgbs[col * 3 + 0], rgbs[col * 3 + 1], rgbs[col * 3 + 2]); +				} else { +					_palette[i] = new_palette[i]; +				}  			}  		} +	} else if (_vm->_game.heversion >= 99 && _paletteNum) { +		for (i = 0; i < size; i++) +			_palette[i] = (byte)_vm->_hePalettes[_paletteNum * _vm->_hePaletteSlot + 768 + akpl[i]];  	} else {  		for (i = 0; i < size; i++) {  			_palette[i] = new_palette[i] != 0xFF ? new_palette[i] : akpl[i]; @@ -545,7 +546,7 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {  	byte *dst;  	byte len, maskbit;  	int y; -	uint color, height, pcolor; +	uint16 color, height, pcolor;  	const byte *scaleytab;  	bool masked;  	bool skip_column = false; @@ -589,7 +590,11 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {  						} else if (_shadow_mode == 2) {  							error("codec1_spec2"); // TODO  						} else if (_shadow_mode == 3) { -							if (_vm->_game.heversion >= 90) { +							if (_vm->_game.features & GF_16BIT_COLOR) { +								uint16 srcColor = (pcolor >> 1) & 0x7DEF; +								uint16 dstColor = (READ_UINT16(dst) >> 1) & 0x7DEF; +								pcolor = srcColor + dstColor; +							} else if (_vm->_game.heversion >= 90) {  								pcolor = (pcolor << 8) + *dst;  								pcolor = xmap[pcolor];  							} else if (pcolor < 8) { @@ -597,7 +602,11 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {  								pcolor = _shadow_table[pcolor];  							}  						} -						*dst = pcolor; +						if (_vm->_bitDepth == 2) { +							WRITE_UINT16(dst, pcolor); +						} else { +							*dst = pcolor; +						}  					}  				}  				dst += _out.pitch; @@ -617,7 +626,7 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {  					if (v1.x < 0 || v1.x >= v1.boundsRect.right)  						return;  					maskbit = revBitMask(v1.x & 7); -					v1.destptr += v1.scaleXstep; +					v1.destptr += v1.scaleXstep * _vm->_bitDepth;  					skip_column = false;  				} else  					skip_column = true; @@ -987,7 +996,7 @@ byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) {  	if (_draw_bottom < rect.bottom)  		_draw_bottom = rect.bottom; -	v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x; +	v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x * _vm->_bitDepth;  	codec1_genericDecode(v1); @@ -1056,7 +1065,12 @@ byte AkosRenderer::codec5(int xmoveCur, int ymoveCur) {  	bdd.shadowMode = _shadow_mode;  	bdd.shadowPalette = _vm->_shadowPalette; -	bdd.actorPalette = _useBompPalette ? _palette : 0; +	bdd.actorPalette = 0; +	if (_useBompPalette) { +		for (uint i = 0; i < 256; i++) +			bdd.actorPalette[i] = _palette[i]; + 	} +  	bdd.mirror = !_mirror;  	drawBomp(bdd); @@ -1176,6 +1190,8 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in  }  byte AkosRenderer::codec16(int xmoveCur, int ymoveCur) { +	assert(_vm->_bitDepth == 1); +  	Common::Rect clip;  	int32 minx, miny, maxw, maxh;  	int32 skip_x, skip_y, cur_x, cur_y; @@ -1278,7 +1294,7 @@ byte AkosRenderer::codec16(int xmoveCur, int ymoveCur) {  	int32 numskip_before = skip_x + (skip_y * _width);  	int32 numskip_after = _width - cur_x; -	byte *dst = (byte *)_out.pixels + width_unk + height_unk * _out.pitch; +	byte *dst = (byte *)_out.pixels + height_unk * _out.pitch + width_unk * _vm->_bitDepth;  	akos16Decompress(dst, _out.pitch, _srcptr, cur_x, out_height, dir, numskip_before, numskip_after, transparency, clip.left, clip.top, _zbuf);  	return 0; @@ -1335,18 +1351,27 @@ byte AkosRenderer::codec32(int xmoveCur, int ymoveCur) {  		_draw_bottom = dst.bottom;  	const uint8 *palPtr = NULL; -	if (_vm->_game.heversion >= 99) { -		palPtr = _vm->_hePalettes + 1792; +	if (_vm->_game.features & GF_16BIT_COLOR) { +		palPtr = _vm->_hePalettes + _vm->_hePaletteSlot + 768; +		if (_paletteNum) { +			palPtr = _vm->_hePalettes + _paletteNum * _vm->_hePaletteSlot + 768; +		} else if (rgbs) { +			for (uint i = 0; i < 256; i++) +				WRITE_LE_UINT16(_palette + i, _vm->get16BitColor(rgbs[i * 3 + 0], rgbs[i * 3 + 1], rgbs[i * 3 + 2])); +			palPtr = (uint8 *)_palette; +		} +	} else if (_vm->_game.heversion >= 99) { +		palPtr = _vm->_hePalettes + _vm->_hePaletteSlot + 768;  	} -	byte *dstPtr = (byte *)_out.pixels + dst.left + dst.top * _out.pitch; +	byte *dstPtr = (byte *)_out.pixels + dst.top * _out.pitch + dst.left * _vm->_bitDepth;  	if (_shadow_mode == 3) { -		Wiz::decompressWizImage<kWizXMap>(dstPtr, _out.pitch, _srcptr, src, 0, palPtr, xmap); +		Wiz::decompressWizImage<kWizXMap>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, palPtr, xmap, _vm->_bitDepth);  	} else {  		if (palPtr != NULL) { -			Wiz::decompressWizImage<kWizRMap>(dstPtr, _out.pitch, _srcptr, src, 0, palPtr); +			Wiz::decompressWizImage<kWizRMap>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, palPtr, NULL, _vm->_bitDepth);  		} else { -			Wiz::decompressWizImage<kWizCopy>(dstPtr, _out.pitch, _srcptr, src, 0); +			Wiz::decompressWizImage<kWizCopy>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, NULL, NULL, _vm->_bitDepth);  		}  	}  #endif diff --git a/engines/scumm/akos.h b/engines/scumm/akos.h index be532b804d..9f4f09d4dc 100644 --- a/engines/scumm/akos.h +++ b/engines/scumm/akos.h @@ -60,7 +60,7 @@ protected:  	uint16 _codec;  	// actor _palette -	byte _palette[256]; +	uint16 _palette[256];  	bool _useBompPalette;  	// pointer to various parts of the costume resource @@ -107,7 +107,7 @@ public:  	int16 _actorHitX, _actorHitY;  	bool _actorHitResult; -	void setPalette(byte *_palette); +	void setPalette(uint16 *_palette);  	void setFacing(const Actor *a);  	void setCostume(int costume, int shadow); diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp index 795abb8685..ef706afaac 100644 --- a/engines/scumm/base-costume.cpp +++ b/engines/scumm/base-costume.cpp @@ -40,7 +40,7 @@ byte BaseCostumeRenderer::drawCostume(const VirtScreen &vs, int numStrips, const  		_out.pixels = vs.getPixels(0, 0);  	_actorX += _vm->_virtscr[kMainVirtScreen].xstart & 7; -	_out.w = _out.pitch; +	_out.w = _out.pitch / _vm->_bitDepth;  	_out.pixels = (byte *)_out.pixels - (_vm->_virtscr[kMainVirtScreen].xstart & 7);  	_numStrips = numStrips; diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h index 59ca3ded1f..d41d795e34 100644 --- a/engines/scumm/base-costume.h +++ b/engines/scumm/base-costume.h @@ -145,7 +145,7 @@ public:  	}  	virtual ~BaseCostumeRenderer() {} -	virtual void setPalette(byte *palette) = 0; +	virtual void setPalette(uint16 *palette) = 0;  	virtual void setFacing(const Actor *a) = 0;  	virtual void setCostume(int costume, int shadow) = 0; diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 193fc434e4..d6dfa4c5bb 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -819,9 +819,9 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,  			byte imagePalette[256];  			memset(imagePalette, 0, sizeof(imagePalette));  			memcpy(imagePalette, _vm->_charsetColorMap, 4); -			Wiz::copyWizImage(dstPtr, charPtr, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen, 0, imagePalette); +			Wiz::copyWizImage(dstPtr, charPtr, vs->pitch, kDstScreen, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen, 0, imagePalette, NULL, _vm->_bitDepth);  		} else { -			Wiz::copyWizImage(dstPtr, charPtr, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen); +			Wiz::copyWizImage(dstPtr, charPtr, vs->pitch, kDstScreen, vs->w, vs->h, _left, _top, origWidth, origHeight, &rScreen, 0, NULL, NULL, _vm->_bitDepth);  		}  		if (_blitAlso && vs->hasTwoBuffers) { diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp index 57b793d579..6923c27b38 100644 --- a/engines/scumm/costume.cpp +++ b/engines/scumm/costume.cpp @@ -791,7 +791,7 @@ byte ClassicCostumeRenderer::drawLimb(const Actor *a, int limb) {  } -void NESCostumeRenderer::setPalette(byte *palette) { +void NESCostumeRenderer::setPalette(uint16 *palette) {  	// TODO  } @@ -874,17 +874,20 @@ void ClassicCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask)  	} while (mask&0xFFFF);  } -void ClassicCostumeRenderer::setPalette(byte *palette) { +void ClassicCostumeRenderer::setPalette(uint16 *palette) {  	int i;  	byte color;  	if (_loaded._format == 0x57) { -		memcpy(_palette, palette, 13); +		for (i = 0; i < 13; i++) +			_palette[i] = palette[i];  	} else if (_vm->_game.features & GF_OLD_BUNDLE) {  		if (_vm->getCurrentLights() & LIGHTMODE_actor_use_colors) { -			memcpy(_palette, palette, 16); +			for (i = 0; i < 16; i++) +				_palette[i] = palette[i];  		} else { -			memset(_palette, 8, 16); +			for (i = 0; i < 16; i++) +				_palette[i] = 8;  			_palette[12] = 0;  		}  		_palette[_loaded._palette[0]] = _palette[0]; diff --git a/engines/scumm/costume.h b/engines/scumm/costume.h index 8e1910abcf..929eb8c451 100644 --- a/engines/scumm/costume.h +++ b/engines/scumm/costume.h @@ -98,7 +98,7 @@ protected:  public:  	ClassicCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {} -	void setPalette(byte *palette); +	void setPalette(uint16 *palette);  	void setFacing(const Actor *a);  	void setCostume(int costume, int shadow); @@ -120,7 +120,7 @@ protected:  public:  	NESCostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {} -	void setPalette(byte *palette); +	void setPalette(uint16 *palette);  	void setFacing(const Actor *a);  	void setCostume(int costume, int shadow); @@ -135,7 +135,7 @@ protected:  public:  	C64CostumeRenderer(ScummEngine *vm) : BaseCostumeRenderer(vm), _loaded(vm) {} -	void setPalette(byte *palette) {} +	void setPalette(uint16 *palette) {}  	void setFacing(const Actor *a) {}  	void setCostume(int costume, int shadow); diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp index 64829114ca..66ac68bd95 100644 --- a/engines/scumm/cursor.cpp +++ b/engines/scumm/cursor.cpp @@ -111,11 +111,20 @@ void ScummEngine_v6::setCursorTransparency(int a) {  }  void ScummEngine::updateCursor() { -	const int transColor = (_game.heversion >= 80) ? 5 : 255; +	int transColor = (_game.heversion >= 80) ? 5 : 255; +#ifdef ENABLE_RGB_COLOR +	Graphics::PixelFormat format = _system->getScreenFormat(); +	CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height, +							_cursor.hotspotX, _cursor.hotspotY, +							(_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor), +							(_game.heversion == 70 ? 2 : 1), +							&format); +#else  	CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,  							_cursor.hotspotX, _cursor.hotspotY,  							(_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor),  							(_game.heversion == 70 ? 2 : 1)); +#endif  }  void ScummEngine_v6::grabCursor(int x, int y, int w, int h) { @@ -138,7 +147,7 @@ void ScummEngine::setCursorFromBuffer(const byte *ptr, int width, int height, in  	uint size;  	byte *dst; -	size = width * height; +	size = width * height * _bitDepth;  	if (size > sizeof(_grabbedCursor))  		error("grabCursor: grabbed cursor too big"); @@ -148,8 +157,8 @@ void ScummEngine::setCursorFromBuffer(const byte *ptr, int width, int height, in  	dst = _grabbedCursor;  	for (; height; height--) { -		memcpy(dst, ptr, width); -		dst += width; +		memcpy(dst, ptr, width * _bitDepth); +		dst += width * _bitDepth;  		ptr += pitch;  	} @@ -166,8 +175,13 @@ void ScummEngine_v70he::setDefaultCursor() {  	static const byte palette[] = {0,    0,    0,    0,  								   0xff, 0xff, 0xff, 0,  								   0,    0,    0,    0}; - -	memset(_grabbedCursor, 5, sizeof(_grabbedCursor)); +	 +	if (_bitDepth == 2) { +		for (i = 0; i < 1024; i++) +			WRITE_UINT16(_grabbedCursor + i * 2, 5); +	} else { +		memset(_grabbedCursor, 5, sizeof(_grabbedCursor)); +	}  	_cursor.hotspotX = _cursor.hotspotY = 2;  	src = default_he_cursor; @@ -180,10 +194,16 @@ void ScummEngine_v70he::setDefaultCursor() {  		for (j = 0; j < 32; j++) {  			switch ((p & (0x3 << 14)) >> 14) {  				case 1: -					_grabbedCursor[32 * i + j] = 0xfe; +					if (_bitDepth == 2) +						WRITE_UINT16(_grabbedCursor + 64 * i + j * 2, get16BitColor(palette[4], palette[5], palette[6])); +					else +						_grabbedCursor[32 * i + j] = 0xfe;  					break;  				case 2: -					_grabbedCursor[32 * i + j] = 0xfd; +					if (_bitDepth == 2) +						WRITE_UINT16(_grabbedCursor + 64 * i + j * 2, get16BitColor(palette[0], palette[1], palette[2])); +					else +						_grabbedCursor[32 * i + j] = 0xfd;  					break;  				default:  					break; @@ -195,9 +215,11 @@ void ScummEngine_v70he::setDefaultCursor() {  		}  	} -	// Since white color position is not guaranteed -	// we setup our own palette if supported by backend -	CursorMan.replaceCursorPalette(palette, 0xfd, 3); +	if (_bitDepth == 1) { +		// Since white color position is not guaranteed +		// we setup our own palette if supported by backend +		CursorMan.replaceCursorPalette(palette, 0xfd, 3); +	}  	updateCursor();  } diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index fa5d2011b0..1802d0d39c 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -43,12 +43,12 @@ extern "C" void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height  namespace Scumm { -static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h); -static void fill(byte *dst, int dstPitch, byte color, int w, int h); +static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h, uint8 bitDepth); +static void fill(byte *dst, int dstPitch, uint16 color, int w, int h, uint8 bitDepth);  #ifndef USE_ARM_GFX_ASM -static void copy8Col(byte *dst, int dstPitch, const byte *src, int height); +static void copy8Col(byte *dst, int dstPitch, const byte *src, int height, uint8 bitDepth);  #endif -static void clear8Col(byte *dst, int dstPitch, int height); +static void clear8Col(byte *dst, int dstPitch, int height, uint8 bitDepth);  static void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height);  static void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h); @@ -231,6 +231,9 @@ GdiV2::~GdiV2() {  	free(_roomStrips);  } +Gdi16Bit::Gdi16Bit(ScummEngine *vm) : Gdi(vm) { +} +  void Gdi::init() {  	_numStrips = _vm->_screenWidth / 8; @@ -341,8 +344,8 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int  	vs->hasTwoBuffers = twobufs;  	vs->xstart = 0;  	vs->backBuf = NULL; -	vs->bytesPerPixel = 1; -	vs->pitch = width; +	vs->bytesPerPixel = (_game.features & GF_16BIT_COLOR) ? 2 : 1; +	vs->pitch = width * vs->bytesPerPixel;  	if (_game.version >= 7) {  		// Increase the pitch by one; needed to accomodate the extra screen @@ -586,7 +589,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i  		vsPitch = _screenWidth * m - width * m;  	} else { -		vsPitch = vs->pitch - width; +		vsPitch = vs->pitch - width * vs->bytesPerPixel;  	} @@ -612,36 +615,49 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i  #else  		// We blit four pixels at a time, for improved performance.  		const uint32 *src32 = (const uint32 *)src; -		const uint32 *text32 = (const uint32 *)text;  		uint32 *dst32 = (uint32 *)_compositeBuf;  		vsPitch >>= 2; -		const int textPitch = (_textSurface.pitch - width * m) >> 2; -		for (int h = height * m; h > 0; --h) { -			for (int w = width*m; w > 0; w-=4) { -				uint32 temp = *text32++; - -				// Generate a byte mask for those text pixels (bytes) with -				// value CHARSET_MASK_TRANSPARENCY. In the end, each byte -				// in mask will be either equal to 0x00 or 0xFF. -				// Doing it this way avoids branches and bytewise operations, -				// at the cost of readability ;). -				uint32 mask = temp ^ CHARSET_MASK_TRANSPARENCY_32; -				mask = (((mask & 0x7f7f7f7f) + 0x7f7f7f7f) | mask) & 0x80808080; -				mask = ((mask >> 7) + 0x7f7f7f7f) ^ 0x80808080; - -				// The following line is equivalent to this code: -				//   *dst32++ = (*src32++ & mask) | (temp & ~mask); -				// However, some compilers can generate somewhat better -				// machine code for this equivalent statement: -				*dst32++ = ((temp ^ *src32++) & mask) ^ temp; + +		if (_bitDepth == 2) { +			// Sprites always seem to be used for subtitles in 16Bit color HE games, and not +			// the charset renderer, so charset masking isn't required. +			for (int h = height * m; h > 0; --h) { +				for (int w = width * m; w > 0; w -= 4) { +					*dst32++ = *src32++; +					*dst32++ = *src32++; +				} +				src32 += vsPitch; +			} +		} else { +			const uint32 *text32 = (const uint32 *)text; +			const int textPitch = (_textSurface.pitch - width * m) >> 2; +			for (int h = height * m; h > 0; --h) { +				for (int w = width * m; w > 0; w -= 4) { +					uint32 temp = *text32++; + +					// Generate a byte mask for those text pixels (bytes) with +					// value CHARSET_MASK_TRANSPARENCY. In the end, each byte +					// in mask will be either equal to 0x00 or 0xFF. +					// Doing it this way avoids branches and bytewise operations, +					// at the cost of readability ;). +					uint32 mask = temp ^ CHARSET_MASK_TRANSPARENCY_32; +					mask = (((mask & 0x7f7f7f7f) + 0x7f7f7f7f) | mask) & 0x80808080; +					mask = ((mask >> 7) + 0x7f7f7f7f) ^ 0x80808080; + +					// The following line is equivalent to this code: +					//   *dst32++ = (*src32++ & mask) | (temp & ~mask); +					// However, some compilers can generate somewhat better +					// machine code for this equivalent statement: +					*dst32++ = ((temp ^ *src32++) & mask) ^ temp; +				} +				src32 += vsPitch; +				text32 += textPitch;  			} -			src32 += vsPitch; -			text32 += textPitch;  		}  #endif  		src = _compositeBuf; -		pitch = width; +		pitch = width * vs->bytesPerPixel;  		if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {  			ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height); @@ -986,13 +1002,13 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {  		return;  	if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) { -		blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height); +		blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height, vs->bytesPerPixel);  		if (vs->number == kMainVirtScreen && _charset->_hasMask) {  			byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop); -			fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height); +			fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height, _textSurface.bytesPerPixel);  		}  	} else { -		fill(screenBuf, vs->pitch, backColor, width, height); +		fill(screenBuf, vs->pitch, backColor, width, height, vs->bytesPerPixel);  	}  } @@ -1021,7 +1037,7 @@ void ScummEngine::restoreCharsetBg() {  			if (vs->number != kMainVirtScreen) {  				// Restore from back buffer  				const byte *backBuf = vs->getBackPixels(0, 0); -				blit(screenBuf, vs->pitch, backBuf, vs->pitch, vs->w, vs->h); +				blit(screenBuf, vs->pitch, backBuf, vs->pitch, vs->w, vs->h, vs->bytesPerPixel);  			}  		} else {  			// Clear area @@ -1057,34 +1073,42 @@ byte *Gdi::getMaskBuffer(int x, int y, int z) {  #pragma mark --- Misc ---  #pragma mark - -static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) { +static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h, uint8 bitDepth) {  	assert(w > 0);  	assert(h > 0);  	assert(src != NULL);  	assert(dst != NULL); -	if (w == srcPitch && w == dstPitch) { -		memcpy(dst, src, w*h); +	if ((w * bitDepth == srcPitch) && (w * bitDepth == dstPitch)) { +		memcpy(dst, src, w * h * bitDepth);  	} else {  		do { -			memcpy(dst, src, w); +			memcpy(dst, src, w * bitDepth);  			dst += dstPitch;  			src += srcPitch;  		} while (--h);  	}  } -static void fill(byte *dst, int dstPitch, byte color, int w, int h) { +static void fill(byte *dst, int dstPitch, uint16 color, int w, int h, uint8 bitDepth) {  	assert(h > 0);  	assert(dst != NULL); -	if (w == dstPitch) { -		memset(dst, color, w*h); -	} else { +	if (bitDepth == 2) {  		do { -			memset(dst, color, w); +			for (int i = 0; i < w; i++) +				WRITE_UINT16(dst + i * 2, color);  			dst += dstPitch;  		} while (--h); +	} else { +		if (w == dstPitch) { +			memset(dst, color, w * h); +		} else { +			do { +				memset(dst, color, w); +				dst += dstPitch; +			} while (--h); +		}  	}  } @@ -1094,14 +1118,18 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h) {  #else -static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) { +static void copy8Col(byte *dst, int dstPitch, const byte *src, int height, uint8 bitDepth) {  	do {  #if defined(SCUMM_NEED_ALIGNMENT) -		memcpy(dst, src, 8); +		memcpy(dst, src, 8 * bitDepth);  #else  		((uint32 *)dst)[0] = ((const uint32 *)src)[0];  		((uint32 *)dst)[1] = ((const uint32 *)src)[1]; +		if (bitDepth == 2) { +			((uint32 *)dst)[2] = ((const uint32 *)src)[2]; +			((uint32 *)dst)[3] = ((const uint32 *)src)[3]; +		}  #endif  		dst += dstPitch;  		src += dstPitch; @@ -1110,13 +1138,17 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) {  #endif /* USE_ARM_GFX_ASM */ -static void clear8Col(byte *dst, int dstPitch, int height) { +static void clear8Col(byte *dst, int dstPitch, int height, uint8 bitDepth) {  	do {  #if defined(SCUMM_NEED_ALIGNMENT) -		memset(dst, 0, 8); +		memset(dst, 0, 8 * bitDepth);  #else  		((uint32 *)dst)[0] = 0;  		((uint32 *)dst)[1] = 0; +		if (bitDepth == 2) { +			((uint32 *)dst)[2] = 0; +			((uint32 *)dst)[3] = 0; +		}  #endif  		dst += dstPitch;  	} while (--height); @@ -1181,41 +1213,41 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {  	if (color == -1) {  		if (vs->number != kMainVirtScreen)  			error("can only copy bg to main window"); -		blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height); +		blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);  		if (_charset->_hasMask) {  			byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier); -			fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier); +			fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);  		}  	} else if (_game.heversion >= 72) {  		// Flags are used for different methods in HE games  		uint32 flags = color;  		if ((flags & 0x2000) || (flags & 0x4000000)) { -			blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height); +			blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);  		} else if ((flags & 0x4000) || (flags & 0x2000000)) { -			blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height); +			blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->bytesPerPixel);  		} else if ((flags & 0x8000) || (flags & 0x1000000)) {  			flags &= (flags & 0x1000000) ? 0xFFFFFF : 0x7FFF; -			fill(backbuff, vs->pitch, flags, width, height); -			fill(bgbuff, vs->pitch, flags, width, height); +			fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel); +			fill(bgbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);  		} else { -			fill(backbuff, vs->pitch, flags, width, height); +			fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);  		}  	} else if (_game.heversion >= 60) {  		// Flags are used for different methods in HE games  		uint16 flags = color;  		if (flags & 0x2000) { -			blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height); +			blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->bytesPerPixel);  		} else if (flags & 0x4000) { -			blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height); +			blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->bytesPerPixel);  		} else if (flags & 0x8000) {  			flags &= 0x7FFF; -			fill(backbuff, vs->pitch, flags, width, height); -			fill(bgbuff, vs->pitch, flags, width, height); +			fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel); +			fill(bgbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);  		} else { -			fill(backbuff, vs->pitch, flags, width, height); +			fill(backbuff, vs->pitch, flags, width, height, vs->bytesPerPixel);  		}  	} else { -		fill(backbuff, vs->pitch, color, width, height); +		fill(backbuff, vs->pitch, color, width, height, vs->bytesPerPixel);  	}  } @@ -1253,7 +1285,7 @@ void ScummEngine_v5::drawFlashlight() {  										_flashlight.y, _flashlight.y + _flashlight.h, USAGE_BIT_DIRTY);  		if (_flashlight.buffer) { -			fill(_flashlight.buffer, vs->pitch, 0, _flashlight.w, _flashlight.h); +			fill(_flashlight.buffer, vs->pitch, 0, _flashlight.w, _flashlight.h, vs->bytesPerPixel);  		}  		_flashlight.isDrawn = false;  	} @@ -1300,7 +1332,7 @@ void ScummEngine_v5::drawFlashlight() {  	_flashlight.buffer = vs->getPixels(_flashlight.x, _flashlight.y);  	bgbak = vs->getBackPixels(_flashlight.x, _flashlight.y); -	blit(_flashlight.buffer, vs->pitch, bgbak, vs->pitch, _flashlight.w, _flashlight.h); +	blit(_flashlight.buffer, vs->pitch, bgbak, vs->pitch, _flashlight.w, _flashlight.h, vs->bytesPerPixel);  	// Round the corners. To do so, we simply hard-code a set of nicely  	// rounded corners. @@ -1609,7 +1641,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const  		warning("Gdi::drawBitmap, strip drawn to %d below window bottom %d", y + height, vs->h);  	} -	_vertStripNextInc = height * vs->pitch - 1; +	_vertStripNextInc = height * vs->pitch - 1 * vs->bytesPerPixel;  	_objectMode = (flag & dbObjectMode) == dbObjectMode;  	prepareDrawBitmap(ptr, vs, x, y, width, height, stripnr, numstrip); @@ -1642,9 +1674,9 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const  		// In the case of a double buffered virtual screen, we draw to  		// the backbuffer, otherwise to the primary surface memory.  		if (vs->hasTwoBuffers) -			dstPtr = vs->backBuf + y * vs->pitch + x * 8; +			dstPtr = vs->backBuf + y * vs->pitch + (x * 8 * vs->bytesPerPixel);  		else -			dstPtr = (byte *)vs->pixels + y * vs->pitch + x * 8; +			dstPtr = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->bytesPerPixel);  		transpStrip = drawStrip(dstPtr, vs, x, y, width, height, stripnr, smap_ptr); @@ -1653,11 +1685,11 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const  			transpStrip = true;  		if (vs->hasTwoBuffers) { -			byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + x * 8; +			byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->bytesPerPixel);  			if (lightsOn) -				copy8Col(frontBuf, vs->pitch, dstPtr, height); +				copy8Col(frontBuf, vs->pitch, dstPtr, height, vs->bytesPerPixel);  			else -				clear8Col(frontBuf, vs->pitch, height); +				clear8Col(frontBuf, vs->pitch, height, vs->bytesPerPixel);  		}  		decodeMask(x, y, width, height, stripnr, numzbuf, zplane_list, transpStrip, flag, tmsk_ptr); @@ -1885,7 +1917,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {  		drawStripHE(dst, vs->pitch, bmap_ptr, vs->w, vs->h, true);  		break;  	case 150: -		fill(dst, vs->pitch, *bmap_ptr, vs->w, vs->h); +		fill(dst, vs->pitch, *bmap_ptr, vs->w, vs->h, vs->bytesPerPixel);  		break;  	default:  		// Alternative russian freddi3 uses badly formatted bitmaps @@ -1941,12 +1973,12 @@ void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y,  	assert(bmap_ptr);  	byte code = *bmap_ptr++; -	int scrX = _vm->_screenStartStrip * 8; +	int scrX = _vm->_screenStartStrip * 8 * _vm->_bitDepth;  	if (code == 8 || code == 9) {  		Common::Rect rScreen(0, 0, vs->w, vs->h);  		byte *dst = (byte *)_vm->_virtscr[kMainVirtScreen].backBuf + scrX; -		Wiz::copyWizImage(dst, bmap_ptr, vs->w, vs->h, x - scrX, y, w, h, &rScreen); +		Wiz::copyWizImage(dst, bmap_ptr, vs->pitch, kDstScreen, vs->w, vs->h, x - scrX, y, w, h, &rScreen, 0, 0, 0, _vm->_bitDepth);  	}  	Common::Rect rect1(x, y, x + w, y + h); @@ -1996,7 +2028,7 @@ void ScummEngine_v70he::restoreBackgroundHE(Common::Rect rect, int dirtybit) {  	assert(rw <= _screenWidth && rw > 0);  	assert(rh <= _screenHeight && rh > 0); -	blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh); +	blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh, vs->bytesPerPixel);  	markRectAsDirty(kMainVirtScreen, rect, dirtybit);  }  #endif @@ -2026,15 +2058,15 @@ void Gdi::resetBackground(int top, int bottom, int strip) {  	if (bottom > vs->bdirty[strip])  		vs->bdirty[strip] = bottom; -	bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8; -	backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8; +	bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->bytesPerPixel; +	backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->bytesPerPixel;  	numLinesToProcess = bottom - top;  	if (numLinesToProcess) {  		if (_vm->isLightOn()) { -			copy8Col(backbuff_ptr, vs->pitch, bgbak_ptr, numLinesToProcess); +			copy8Col(backbuff_ptr, vs->pitch, bgbak_ptr, numLinesToProcess, vs->bytesPerPixel);  		} else { -			clear8Col(backbuff_ptr, vs->pitch, numLinesToProcess); +			clear8Col(backbuff_ptr, vs->pitch, numLinesToProcess, vs->bytesPerPixel);  		}  	}  } @@ -2785,12 +2817,12 @@ void Gdi::drawStripHE(byte *dst, int dstPitch, const byte *src, int width, int h  	int x = width;  	while (1) {  		if (!transpCheck || color != _transparentColor) -			*dst = _roomPalette[color]; -		dst++; +			writeRoomColor(dst, color); +		dst += _vm->_bitDepth;  		--x;  		if (x == 0) {  			x = width; -			dst += dstPitch - width; +			dst += dstPitch - width * _vm->_bitDepth;  			--height;  			if (height == 0)  				return; @@ -2874,8 +2906,8 @@ void Gdi::drawStripComplex(byte *dst, int dstPitch, const byte *src, int height,  		do {  			FILL_BITS;  			if (!transpCheck || color != _transparentColor) -				*dst = _roomPalette[color] + _paletteMod; -			dst++; +				writeRoomColor(dst, color); +			dst += _vm->_bitDepth;  		againPos:  			if (!READ_BIT) { @@ -2896,13 +2928,13 @@ void Gdi::drawStripComplex(byte *dst, int dstPitch, const byte *src, int height,  					do {  						if (!--x) {  							x = 8; -							dst += dstPitch - 8; +							dst += dstPitch - 8 * _vm->_bitDepth;  							if (!--height)  								return;  						}  						if (!transpCheck || color != _transparentColor) -							*dst = _roomPalette[color] + _paletteMod; -						dst++; +							writeRoomColor(dst, color); +						dst += _vm->_bitDepth;  					} while (--reps);  					bits >>= 8;  					bits |= (*src++) << (cl - 8); @@ -2910,7 +2942,7 @@ void Gdi::drawStripComplex(byte *dst, int dstPitch, const byte *src, int height,  				}  			}  		} while (--x); -		dst += dstPitch - 8; +		dst += dstPitch - 8 * _vm->_bitDepth;  	} while (--height);  } @@ -2926,8 +2958,8 @@ void Gdi::drawStripBasicH(byte *dst, int dstPitch, const byte *src, int height,  		do {  			FILL_BITS;  			if (!transpCheck || color != _transparentColor) -				*dst = _roomPalette[color] + _paletteMod; -			dst++; +				writeRoomColor(dst, color); +			dst += _vm->_bitDepth;  			if (!READ_BIT) {  			} else if (!READ_BIT) {  				FILL_BITS; @@ -2942,7 +2974,7 @@ void Gdi::drawStripBasicH(byte *dst, int dstPitch, const byte *src, int height,  				color += inc;  			}  		} while (--x); -		dst += dstPitch - 8; +		dst += dstPitch - 8 * _vm->_bitDepth;  	} while (--height);  } @@ -2959,7 +2991,7 @@ void Gdi::drawStripBasicV(byte *dst, int dstPitch, const byte *src, int height,  		do {  			FILL_BITS;  			if (!transpCheck || color != _transparentColor) -				*dst = _roomPalette[color] + _paletteMod; +				writeRoomColor(dst, color);  			dst += dstPitch;  			if (!READ_BIT) {  			} else if (!READ_BIT) { @@ -3027,7 +3059,7 @@ void Gdi::drawStripRaw(byte *dst, int dstPitch, const byte *src, int height, con  			for (x = 0; x < 8; x ++) {  				byte color = *src++;  				if (!transpCheck || color != _transparentColor) -					dst[x] = _roomPalette[color] + _paletteMod; +					writeRoomColor(dst + x * _vm->_bitDepth, color);  			}  			dst += dstPitch;  		} while (--height); @@ -3150,6 +3182,14 @@ void Gdi::unkDecode11(byte *dst, int dstPitch, const byte *src, int height) cons  #undef NEXT_ROW  #undef READ_BIT_256 +void Gdi16Bit::writeRoomColor(byte *dst, byte color) const { +	WRITE_UINT16(dst, READ_LE_UINT16(_vm->_hePalettes + 2048 + color * 2)); +} + +void Gdi::writeRoomColor(byte *dst, byte color) const { +	*dst = _roomPalette[color] + _paletteMod; +} +  #pragma mark -  #pragma mark --- Transition effects --- diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h index e4c1054450..0910d9bc59 100644 --- a/engines/scumm/gfx.h +++ b/engines/scumm/gfx.h @@ -155,11 +155,11 @@ struct VirtScreen : Graphics::Surface {  	}  	byte *getPixels(int x, int y) const { -		return (byte *)pixels + xstart + y * pitch + x; +		return (byte *)pixels + y * pitch + (xstart + x) * bytesPerPixel;  	}  	byte *getBackPixels(int x, int y) const { -		return (byte *)backBuf + xstart + y * pitch + x; +		return (byte *)backBuf + y * pitch + (xstart + x) * bytesPerPixel;  	}  }; @@ -215,6 +215,7 @@ protected:  	void drawStrip3DO(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const;  	void drawStripHE(byte *dst, int dstPitch, const byte *src, int width, int height, const bool transpCheck) const; +	virtual void writeRoomColor(byte *dst, byte color) const;  	/* Mask decompressors */  	void decompressTMSK(byte *dst, const byte *tmsk, const byte *src, int height) const; @@ -361,6 +362,13 @@ public:  	virtual void roomChanged(byte *roomptr);  }; +class Gdi16Bit : public Gdi { +protected: +	virtual void writeRoomColor(byte *dst, byte color) const; +public: +	Gdi16Bit(ScummEngine *vm); +}; +  } // End of namespace Scumm  #endif diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp index 2ca17161db..47b25c57d1 100644 --- a/engines/scumm/he/animation_he.cpp +++ b/engines/scumm/he/animation_he.cpp @@ -66,6 +66,32 @@ int MoviePlayer::load(const char *filename, int flags, int image) {  	return 0;  } +void MoviePlayer::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) { +	uint h = getHeight(); +	uint w = getWidth(); + +	byte *src = _videoFrameBuffer; + +	if (_vm->_game.features & GF_16BIT_COLOR) { +		dst += y * pitch + x * 2; +		do { +			for (uint i = 0; i < w; i++) { +				uint16 col = READ_LE_UINT16(_vm->_hePalettes + _vm->_hePaletteSlot + 768 + src[i] * 2); +				WRITE_UINT16(dst + i * 2, col); +			} +			dst += pitch; +			src += w; +		} while (--h); +	} else { +		dst += y * pitch + x; +		do { +			memcpy(dst, src, w); +			dst += pitch; +			src += w; +		} while (--h); +	} +} +  void MoviePlayer::handleNextFrame() {  	if (!isVideoLoaded()) {  		return; @@ -80,14 +106,14 @@ void MoviePlayer::handleNextFrame() {  		assert(dstPtr);  		uint8 *dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);  		assert(dst); -		copyFrameToBuffer(dst, 0, 0, _vm->_screenWidth); +		copyFrameToBuffer(dst, 0, 0, _vm->_screenWidth * _vm->_bitDepth);  	} else if (_flags & 1) { -		copyFrameToBuffer(pvs->getBackPixels(0, 0), 0, 0, _vm->_screenWidth); +		copyFrameToBuffer(pvs->getBackPixels(0, 0), 0, 0, pvs->pitch);  		Common::Rect imageRect(getWidth(), getHeight());  		_vm->restoreBackgroundHE(imageRect);  	} else { -		copyFrameToBuffer(pvs->getPixels(0, 0), 0, 0, _vm->_screenWidth); +		copyFrameToBuffer(pvs->getPixels(0, 0), 0, 0, pvs->pitch);  		Common::Rect imageRect(getWidth(), getHeight());  		_vm->markRectAsDirty(kMainVirtScreen, imageRect); diff --git a/engines/scumm/he/animation_he.h b/engines/scumm/he/animation_he.h index cf5d054ead..0adba35d53 100644 --- a/engines/scumm/he/animation_he.h +++ b/engines/scumm/he/animation_he.h @@ -54,6 +54,7 @@ public:  	int getImageNum();  	int load(const char *filename, int flags, int image = 0); +	void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);  	void handleNextFrame();  protected: diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h index 9e905b0e79..2f7f539ee3 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -458,6 +458,7 @@ protected:  	uint8 *getHEPaletteIndex(int palSlot);  	int getHEPaletteColor(int palSlot, int color);  	int getHEPaletteSimilarColor(int palSlot, int red, int green, int start, int end); +	int getHEPalette16BitColorComponent(int component, int type);  	int getHEPaletteColorComponent(int palSlot, int color, int component);  	void setHEPaletteColor(int palSlot, uint8 color, uint8 r, uint8 g, uint8 b);  	void setHEPaletteFromPtr(int palSlot, const uint8 *palData); @@ -466,7 +467,7 @@ protected:  	void setHEPaletteFromRoom(int palSlot, int resId, int state);  	void restoreHEPalette(int palSlot);  	void copyHEPalette(int dstPalSlot, int srcPalSlot); -	void copyHEPaletteColor(int palSlot, uint8 dstColor, uint8 srcColor); +	void copyHEPaletteColor(int palSlot, uint8 dstColor, uint16 srcColor);  protected:  	/* HE version 90 script opcodes */ diff --git a/engines/scumm/he/palette_he.cpp b/engines/scumm/he/palette_he.cpp index 7fe04f223e..ff29f9ecd0 100644 --- a/engines/scumm/he/palette_he.cpp +++ b/engines/scumm/he/palette_he.cpp @@ -40,7 +40,7 @@ void ScummEngine_v71he::remapHEPalette(const uint8 *src, uint8 *dst) {  	src += 30;  	if (_game.heversion >= 99) { -		palPtr = _hePalettes + 1024 + 30; +		palPtr = _hePalettes + _hePaletteSlot + 30;  	} else {  		palPtr = _currentPalette + 30;  	} @@ -75,9 +75,9 @@ void ScummEngine_v71he::remapHEPalette(const uint8 *src, uint8 *dst) {  uint8 *ScummEngine_v90he::getHEPaletteIndex(int palSlot) {  	if (palSlot) {  		assert(palSlot >= 1 && palSlot <= _numPalettes); -		return _hePalettes + palSlot * 1024; +		return _hePalettes + palSlot * _hePaletteSlot;  	} else { -		return _hePalettes + 1024; +		return _hePalettes + _hePaletteSlot;  	}  } @@ -86,7 +86,7 @@ int ScummEngine_v90he::getHEPaletteSimilarColor(int palSlot, int red, int green,  	assertRange(0, start, 255, "start palette slot");  	assertRange(0, end, 255, "pend alette slot"); -	uint8 *pal = _hePalettes + palSlot * 1024 + start * 3; +	uint8 *pal = _hePalettes + palSlot * _hePaletteSlot + start * 3;  	int bestsum = 0x7FFFFFFF;  	int bestitem = start; @@ -107,39 +107,83 @@ int ScummEngine_v90he::getHEPaletteSimilarColor(int palSlot, int red, int green,  	return bestitem;  } +int ScummEngine_v90he::getHEPalette16BitColorComponent(int component, int type) { +	uint16 col; +	if (type == 2) { +		col = (((component & 0xFFFF) >>  0) & 0x1F) << 3;; +	} else if (type == 1) { +		col = (((component & 0xFFFF) >>  5) & 0x1F) << 3; +	} else { +		col = (((component & 0xFFFF) >> 10) & 0x1F) << 3; +	} +	return col; +} +  int ScummEngine_v90he::getHEPaletteColorComponent(int palSlot, int color, int component) {  	assertRange(1, palSlot, _numPalettes, "palette");  	assertRange(0, color, 255, "palette slot"); -	return _hePalettes[palSlot * 1024 + color * 3 + component % 3]; +	return _hePalettes[palSlot * _hePaletteSlot + color * 3 + component % 3];  }  int ScummEngine_v90he::getHEPaletteColor(int palSlot, int color) {  	assertRange(1, palSlot, _numPalettes, "palette");  	assertRange(0, color, 255, "palette slot"); -	return _hePalettes[palSlot * 1024 + 768 + color]; +	if (_game.features & GF_16BIT_COLOR) +		return READ_LE_UINT16(_hePalettes + palSlot * _hePaletteSlot + 768 + color * 2); +	else +		return _hePalettes[palSlot * _hePaletteSlot + 768 + color];  }  void ScummEngine_v90he::setHEPaletteColor(int palSlot, uint8 color, uint8 r, uint8 g, uint8 b) {  	debug(7, "setHEPaletteColor(%d, %d, %d, %d, %d)", palSlot, color, r, g, b);  	assertRange(1, palSlot, _numPalettes, "palette"); -	uint8 *p = _hePalettes + palSlot * 1024 + color * 3; + +	uint8 *p = _hePalettes + palSlot * _hePaletteSlot + color * 3;  	*(p + 0) = r;  	*(p + 1) = g;  	*(p + 2) = b; -	_hePalettes[palSlot * 1024 + 768 + color] = color; +	if (_game.features & GF_16BIT_COLOR) { +		WRITE_LE_UINT16(_hePalettes + palSlot * _hePaletteSlot + 768 + color * 2, get16BitColor(r, g, b)); +	} else { +		_hePalettes[palSlot * _hePaletteSlot + 768 + color] = color; +	}  }  void ScummEngine_v90he::setHEPaletteFromPtr(int palSlot, const uint8 *palData) {  	assertRange(1, palSlot, _numPalettes, "palette"); -	uint8 *pc = _hePalettes + palSlot * 1024; + +	uint8 *pc = _hePalettes + palSlot * _hePaletteSlot;  	uint8 *pi = pc + 768; -	for (int i = 0; i < 256; ++i) { -		*pc++ = *palData++; -		*pc++ = *palData++; -		*pc++ = *palData++; -		*pi++ = i; +	if (_game.features & GF_16BIT_COLOR) { +		for (int i = 0; i < 256; ++i) { +			uint8 r = *pc++ = *palData++; +			uint8 g = *pc++ = *palData++; +			uint8 b = *pc++ = *palData++; +			WRITE_LE_UINT16(pi, get16BitColor(r, g, b)); pi += 2; +		} +	} else { +		for (int i = 0; i < 256; ++i) { +			*pc++ = *palData++; +			*pc++ = *palData++; +			*pc++ = *palData++; +			*pi++ = i; +		} +	} + +	int i; +	uint8 *palPtr = _hePalettes + palSlot * _hePaletteSlot + 768; +	if (_game.features & GF_16BIT_COLOR) { +		for (i = 0; i < 10; ++i) +			WRITE_LE_UINT16(palPtr + i * 2, i); +		for (i = 246; i < 256; ++i) +			WRITE_LE_UINT16(palPtr + i * 2, i); +	} else { +		for (i = 0; i < 10; ++i) +			*(palPtr + i) = i; +		for (i = 246; i < 256; ++i) +			*(palPtr + i) = i;  	}  } @@ -178,8 +222,9 @@ void ScummEngine_v90he::setHEPaletteFromRoom(int palSlot, int resId, int state)  void ScummEngine_v90he::restoreHEPalette(int palSlot) {  	debug(7, "restoreHEPalette(%d)", palSlot);  	assertRange(1, palSlot, _numPalettes, "palette"); +  	if (palSlot != 1) { -		memcpy(_hePalettes + palSlot * 1024, _hePalettes + 1024, 1024); +		memcpy(_hePalettes + palSlot * _hePaletteSlot, _hePalettes + _hePaletteSlot, _hePaletteSlot);  	}  } @@ -187,18 +232,27 @@ void ScummEngine_v90he::copyHEPalette(int dstPalSlot, int srcPalSlot) {  	debug(7, "copyHEPalette(%d, %d)", dstPalSlot, srcPalSlot);  	assert(dstPalSlot >= 1 && dstPalSlot <= _numPalettes);  	assert(srcPalSlot >= 1 && srcPalSlot <= _numPalettes); +  	if (dstPalSlot != srcPalSlot) { -		memcpy(_hePalettes + dstPalSlot * 1024, _hePalettes + srcPalSlot * 1024, 1024); +		memcpy(_hePalettes + dstPalSlot * _hePaletteSlot, _hePalettes + srcPalSlot * _hePaletteSlot, _hePaletteSlot);  	}  } -void ScummEngine_v90he::copyHEPaletteColor(int palSlot, uint8 dstColor, uint8 srcColor) { +void ScummEngine_v90he::copyHEPaletteColor(int palSlot, uint8 dstColor, uint16 srcColor) {  	debug(7, "copyHEPaletteColor(%d, %d, %d)", palSlot, dstColor, srcColor);  	assertRange(1, palSlot, _numPalettes, "palette"); -	uint8 *dstPal = _hePalettes + palSlot * 1024 + dstColor * 3; -	uint8 *srcPal = _hePalettes + 1024 + srcColor * 3; -	memcpy(dstPal, srcPal, 3); -	_hePalettes[palSlot * 1024 + 768 + dstColor] = srcColor; + +	uint8 *dstPal = _hePalettes + palSlot * _hePaletteSlot + dstColor * 3; +	uint8 *srcPal = _hePalettes + _hePaletteSlot + srcColor * 3; +	if (_game.features & GF_16BIT_COLOR) { +		dstPal[0] = (srcColor >> 10) << 3; +		dstPal[1] = (srcColor >>  5) << 3; +		dstPal[2] = (srcColor >>  0) << 3; +		WRITE_LE_UINT16(_hePalettes + palSlot * _hePaletteSlot + 768 + dstColor * 2, srcColor); +	} else { +		memcpy(dstPal, srcPal, 3); +		_hePalettes[palSlot * _hePaletteSlot + 768 + dstColor] = srcColor; +	}  }  void ScummEngine_v99he::setPaletteFromPtr(const byte *ptr, int numcolor) { @@ -211,7 +265,7 @@ void ScummEngine_v99he::setPaletteFromPtr(const byte *ptr, int numcolor) {  	assertRange(0, numcolor, 256, "setPaletteFromPtr: numcolor"); -	dest = _hePalettes + 1024; +	dest = _hePalettes + _hePaletteSlot;  	for (i = 0; i < numcolor; i++) {  		r = *ptr++; @@ -222,48 +276,63 @@ void ScummEngine_v99he::setPaletteFromPtr(const byte *ptr, int numcolor) {  			*dest++ = r;  			*dest++ = g;  			*dest++ = b; -			_hePalettes[1792 + i] = i; + +			if (_game.features & GF_16BIT_COLOR) { +				WRITE_LE_UINT16(_hePalettes + 2048 + i * 2, get16BitColor(r, g, b)); +			} else { +				_hePalettes[1792 + i] = i; +			}  		} else {  			dest += 3;  		}  	} -	memcpy(_hePalettes, _hePalettes + 1024, 768); - -	for (i = 0; i < 10; ++i) -		_hePalettes[1792 + i] = i; -	for (i = 246; i < 256; ++i) -		_hePalettes[1792 + i] = i; +	memcpy(_hePalettes, _hePalettes + _hePaletteSlot, 768); +	if (_game.features & GF_16BIT_COLOR) { +		for (i = 0; i < 10; ++i) +			WRITE_LE_UINT16(_hePalettes + 2048 + i * 2, i); +		for (i = 246; i < 256; ++i) +			WRITE_LE_UINT16(_hePalettes + 2048 + i * 2, i); +	} else { +		for (i = 0; i < 10; ++i) +			_hePalettes[1792 + i] = i; +		for (i = 246; i < 256; ++i) +			_hePalettes[1792 + i] = i; +	}  	setDirtyColors(0, numcolor - 1);  }  void ScummEngine_v99he::darkenPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor) {  	uint8 *src, *dst; -	int color, j; +	int j, r, g, b;  	src = _hePalettes + startColor * 3; -	dst = _hePalettes + 1024 + startColor * 3; +	dst = _hePalettes + _hePaletteSlot + startColor * 3;  	for (j = startColor; j <= endColor; j++) { -		color = *src++; -		color = color * redScale / 0xFF; -		if (color > 255) -			color = 255; -		*dst++ = color; - -		color = *src++; -		color = color * greenScale / 0xFF; -		if (color > 255) -			color = 255; -		*dst++ = color; - -		color = *src++; -		color = color * blueScale / 0xFF; -		if (color > 255) -			color = 255; -		*dst++ = color; - -		_hePalettes[1792 + j] = j; +		r = *src++; +		r = r * redScale / 0xFF; +		if (r > 255) +			r = 255; +		*dst++ = r; + +		g = *src++; +		g = g * greenScale / 0xFF; +		if (g > 255) +			g = 255; +		*dst++ = g; + +		b = *src++; +		b = b * blueScale / 0xFF; +		if (b > 255) +			b = 255; +		*dst++ = b; + +		if (_game.features & GF_16BIT_COLOR) { +			WRITE_LE_UINT16(_hePalettes + 2048 + j * 2, get16BitColor(r, g, b)); +		} else { +			_hePalettes[1792 + j] = j; +		}  		setDirtyColors(j, endColor);  	}  } @@ -274,26 +343,39 @@ void ScummEngine_v99he::copyPalColor(int dst, int src) {  	if ((uint) dst >= 256 || (uint) src >= 256)  		error("copyPalColor: invalid values, %d, %d", dst, src); -	dp = &_hePalettes[1024 + dst * 3]; -	sp = &_hePalettes[1024 + src * 3]; +	dp = &_hePalettes[_hePaletteSlot + dst * 3]; +	sp = &_hePalettes[_hePaletteSlot + src * 3];  	dp[0] = sp[0];  	dp[1] = sp[1];  	dp[2] = sp[2]; -	_hePalettes[1792 + dst] = dst; + +	if (_game.features & GF_16BIT_COLOR) { +		WRITE_LE_UINT16(_hePalettes + 2048 + dst * 2, get16BitColor(sp[0], sp[1], sp[2])); +	} else { +		_hePalettes[1792 + dst] = dst; +	}  	setDirtyColors(dst, dst);  }  void ScummEngine_v99he::setPalColor(int idx, int r, int g, int b) { -	_hePalettes[1024 + idx * 3 + 0] = r; -	_hePalettes[1024 + idx * 3 + 1] = g; -	_hePalettes[1024 + idx * 3 + 2] = b; -	_hePalettes[1792 + idx] = idx; +	_hePalettes[_hePaletteSlot + idx * 3 + 0] = r; +	_hePalettes[_hePaletteSlot + idx * 3 + 1] = g; +	_hePalettes[_hePaletteSlot + idx * 3 + 2] = b; + +	if (_game.features & GF_16BIT_COLOR) { +		WRITE_LE_UINT16(_hePalettes + 2048 + idx * 2, get16BitColor(r, g, b)); +	} else { +		_hePalettes[1792 + idx] = idx; +	}  	setDirtyColors(idx, idx);  }  void ScummEngine_v99he::updatePalette() { +	if (_game.features & GF_16BIT_COLOR) +		return; +  	if (_palDirtyMax == -1)  		return; diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp index 44a38401ce..49e490a8ec 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -1576,7 +1576,10 @@ void ScummEngine_v100he::o100_roomOps() {  	case 130:  		a = pop();  		b = pop(); -		copyPalColor(a, b); +		if (_game.features & GF_16BIT_COLOR) +			copyHEPaletteColor(1, a, b); +		else +			copyPalColor(a, b);  		break;  	case 131:		// SO_ROOM_FADE @@ -2153,8 +2156,9 @@ void ScummEngine_v100he::o100_systemOps() {  }  void ScummEngine_v100he::o100_cursorCommand() { -	int a, i; +	int a, b, i;  	int args[16]; +  	byte subOp = fetchScriptByte();  	switch (subOp) { @@ -2169,12 +2173,12 @@ void ScummEngine_v100he::o100_cursorCommand() {  	case 0x80:  	case 0x81:  		a = pop(); -		_wiz->loadWizCursor(a); +		_wiz->loadWizCursor(a, 0);  		break;  	case 0x82: -		pop(); +		b = pop();  		a = pop(); -		_wiz->loadWizCursor(a); +		_wiz->loadWizCursor(a, b);  		break;  	case 0x86:		// SO_CURSOR_ON Turn cursor on  		_cursor.state = 1; @@ -2577,7 +2581,8 @@ void ScummEngine_v100he::o100_getWizData() {  }  void ScummEngine_v100he::o100_getPaletteData() { -	int b, c, d, e; +	int c, d, e; +	int r, g, b;  	int palSlot, color;  	byte subOp = fetchScriptByte(); @@ -2586,7 +2591,10 @@ void ScummEngine_v100he::o100_getPaletteData() {  	case 13:  		c = pop();  		b = pop(); -		push(getHEPaletteColorComponent(1, b, c)); +		if (_game.features & GF_16BIT_COLOR) +			push(getHEPalette16BitColorComponent(b, c)); +		else +			push(getHEPaletteColorComponent(1, b, c));  		break;  	case 20:  		color = pop(); @@ -2597,20 +2605,26 @@ void ScummEngine_v100he::o100_getPaletteData() {  		e = pop();  		d = pop();  		palSlot = pop(); -		pop(); -		c = pop();  		b = pop(); -		push(getHEPaletteSimilarColor(palSlot, b, c, d, e)); +		g = pop(); +		r = pop(); +		push(getHEPaletteSimilarColor(palSlot, r, g, d, e));  		break;  	case 53: -		pop(); -		c = pop(); -		c = MAX(0, c); -		c = MIN(c, 255);  		b = pop();  		b = MAX(0, b);  		b = MIN(b, 255); -		push(getHEPaletteSimilarColor(1, b, c, 10, 245)); +		g = pop(); +		g = MAX(0, g); +		g = MIN(g, 255); +		r = pop(); +		r = MAX(0, r); +		r = MIN(r, 255); +		if (_game.features & GF_16BIT_COLOR) { +			push(get16BitColor(r, g, b)); +		} else { +			push(getHEPaletteSimilarColor(1, r, g, 10, 245)); +		}  		break;  	case 73:  		c = pop(); diff --git a/engines/scumm/he/script_v60he.cpp b/engines/scumm/he/script_v60he.cpp index 7c109b1dcd..92848ce981 100644 --- a/engines/scumm/he/script_v60he.cpp +++ b/engines/scumm/he/script_v60he.cpp @@ -122,6 +122,8 @@ int ScummEngine_v60he::convertFilePath(byte *dst, int dstSize) {  	} else if (dst[0] == '.' && dst[1] == '/') { // Game Data Path  		// The default game data path is set to './' by ScummVM  		r = 2; +	} else if (dst[2] == 'b' && dst[5] == 'k') { // Backyard Basketball INI +		r = 13;  	} else if (dst[0] == '*' && dst[1] == '/') { // Save Game Path (HE72 - HE100)  		// The default save game path is set to '*/' by ScummVM  		r = 2; diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp index 1d73f0da76..0c2c01d419 100644 --- a/engines/scumm/he/script_v72he.cpp +++ b/engines/scumm/he/script_v72he.cpp @@ -1484,6 +1484,7 @@ void ScummEngine_v72he::o72_readFile() {  		fetchScriptByte();  		size = pop();  		slot = pop(); +		assert(_hInFileTable[slot]);  		val = readFileToArray(slot, size);  		push(val);  		break; @@ -1573,7 +1574,7 @@ void ScummEngine_v72he::o72_rename() {  }  void ScummEngine_v72he::o72_getPixel() { -	byte area; +	uint16 area;  	int y = pop();  	int x = pop(); @@ -1588,11 +1589,17 @@ void ScummEngine_v72he::o72_getPixel() {  	switch (subOp) {  	case 9: // HE 100  	case 218: -		area = *vs->getBackPixels(x, y - vs->topline); +		if (_game.features & GF_16BIT_COLOR) +			area = READ_UINT16(vs->getBackPixels(x, y - vs->topline)); +		else +			area = *vs->getBackPixels(x, y - vs->topline);  		break;  	case 8: // HE 100  	case 219: -		area = *vs->getPixels(x, y - vs->topline); +		if (_game.features & GF_16BIT_COLOR) +			area = READ_UINT16(vs->getPixels(x, y - vs->topline)); +		else +			area = *vs->getPixels(x, y - vs->topline);  		break;  	default:  		error("o72_getPixel: default case %d", subOp); @@ -1805,9 +1812,7 @@ void ScummEngine_v72he::o72_readINI() {  	switch (subOp) {  	case 43: // HE 100  	case 6: // number -		if (!strcmp((char *)option, "NoFontsInstalled")) { -			push(1); -		} else if (!strcmp((char *)option, "NoPrinting")) { +		if (!strcmp((char *)option, "NoPrinting")) {  			push(1);  		} else if (!strcmp((char *)option, "TextOn")) {  			push(ConfMan.getBool("subtitles")); diff --git a/engines/scumm/he/script_v80he.cpp b/engines/scumm/he/script_v80he.cpp index 5b10944899..dd44180fa0 100644 --- a/engines/scumm/he/script_v80he.cpp +++ b/engines/scumm/he/script_v80he.cpp @@ -243,7 +243,7 @@ void ScummEngine_v80he::o80_writeConfigFile() {  }  void ScummEngine_v80he::o80_cursorCommand() { -	int a, i; +	int a, b, i;  	int args[16];  	byte subOp = fetchScriptByte(); @@ -252,12 +252,12 @@ void ScummEngine_v80he::o80_cursorCommand() {  	case 0x13:  	case 0x14:  		a = pop(); -		_wiz->loadWizCursor(a); +		_wiz->loadWizCursor(a, 0);  		break;  	case 0x3C: -		pop(); +		b = pop();  		a = pop(); -		_wiz->loadWizCursor(a); +		_wiz->loadWizCursor(a, b);  		break;  	case 0x90:		// SO_CURSOR_ON Turn cursor on  		_cursor.state = 1; diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp index be20a229f0..e302af1144 100644 --- a/engines/scumm/he/script_v90he.cpp +++ b/engines/scumm/he/script_v90he.cpp @@ -1255,7 +1255,7 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {  void ScummEngine_v90he::o90_getWizData() {  	byte filename[4096]; -	int state, resId; +	int resId, state, type;  	int32 w, h;  	int32 x, y; @@ -1319,9 +1319,10 @@ void ScummEngine_v90he::o90_getWizData() {  		push(computeWizHistogram(resId, state, x, y, w, h));  		break;  	case 139: -		pop(); -		pop(); -		push(0); +		type = pop(); +		state = pop(); +		resId = pop(); +		push(_wiz->getWizImageData(resId, state, type));  		break;  	case 141:  		pop(); @@ -2101,7 +2102,8 @@ void ScummEngine_v90he::o90_getObjectData() {  }  void ScummEngine_v90he::o90_getPaletteData() { -	int b, c, d, e; +	int c, d, e; +	int r, g, b;  	int palSlot, color;  	byte subOp = fetchScriptByte(); @@ -2111,10 +2113,10 @@ void ScummEngine_v90he::o90_getPaletteData() {  		e = pop();  		d = pop();  		palSlot = pop(); -		pop(); -		c = pop();  		b = pop(); -		push(getHEPaletteSimilarColor(palSlot, b, c, d, e)); +		g = pop(); +		r = pop(); +		push(getHEPaletteSimilarColor(palSlot, r, g, d, e));  		break;  	case 52:  		c = pop(); @@ -2130,17 +2132,27 @@ void ScummEngine_v90he::o90_getPaletteData() {  	case 132:  		c = pop();  		b = pop(); -		push(getHEPaletteColorComponent(1, b, c)); +		if (_game.features & GF_16BIT_COLOR) +			push(getHEPalette16BitColorComponent(b, c)); +		else +			push(getHEPaletteColorComponent(1, b, c));  		break;  	case 217: -		pop(); -		c = pop(); -		c = MAX(0, c); -		c = MIN(c, 255);  		b = pop();  		b = MAX(0, b);  		b = MIN(b, 255); -		push(getHEPaletteSimilarColor(1, b, c, 10, 245)); +		g = pop(); +		g = MAX(0, g); +		g = MIN(g, 255); +		r = pop(); +		r = MAX(0, r); +		r = MIN(r, 255); + +		if (_game.features & GF_16BIT_COLOR) { +			push(get16BitColor(r, g, b)); +		} else { +			push(getHEPaletteSimilarColor(1, r, g, 10, 245)); +		}  		break;  	default:  		error("o90_getPaletteData: Unknown case %d", subOp); diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp index 549877090c..b00294cb96 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -254,7 +254,9 @@ bool Wiz::polygonContains(const WizPolygon &pol, int x, int y) {  	return r;  } -void Wiz::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch) { +void Wiz::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, uint8 bitDepth) { +	assert(bitDepth == 1); +  	Common::Rect dstRect(srcx, srcy, srcx + srcw, srcy + srch);  	dstRect.clip(dstw, dsth); @@ -263,8 +265,8 @@ void Wiz::copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int  	if (rh <= 0 || rw <= 0)  		return; -	uint8 *dst1Ptr = dst1 + dstRect.left + dstRect.top * dstw; -	uint8 *dst2Ptr = dst2 + dstRect.left + dstRect.top * dstw; +	uint8 *dst1Ptr = dst1 + dstRect.top * dstw + dstRect.left; +	uint8 *dst2Ptr = dst2 + dstRect.top * dstw + dstRect.left;  	const uint8 *dataPtr = src;  	while (rh--) { @@ -353,12 +355,24 @@ static bool calcClipRects(int dst_w, int dst_h, int src_x, int src_y, int src_w,  	return srcRect.isValidRect() && dstRect.isValidRect();  } -void Wiz::copy16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) { -	// TODO: Compressed 16 bits in 555 format +void Wiz::writeColor(uint8 *dstPtr, int dstType, uint16 color) { +	switch (dstType) { +	case kDstScreen: +		WRITE_UINT16(dstPtr, color); +		break; +	case kDstMemory: +	case kDstResource: +		WRITE_LE_UINT16(dstPtr, color); +		break; +	default: +		error("writeColor: Unknown dstType %d", dstType); +	} +} +void Wiz::copy16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *xmapPtr) {  	Common::Rect r1, r2;  	if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) { -		dst += r2.top * dstw + r2.left; +		dst += r2.top * dstPitch + r2.left * 2;  		if (flags & kWIFFlipY) {  			const int dy = (srcy < 0) ? srcy : (srch - r1.height());  			r1.translate(0, dy); @@ -368,17 +382,17 @@ void Wiz::copy16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, in  			r1.translate(dx, 0);  		}  		if (xmapPtr) { -			decompress16BitWizImage<kWizXMap>(dst, dstw, src, r1, flags, palPtr, xmapPtr); +			decompress16BitWizImage<kWizXMap>(dst, dstPitch, dstType, src, r1, flags, xmapPtr);  		} else { -			decompress16BitWizImage<kWizCopy>(dst, dstw, src, r1, flags); +			decompress16BitWizImage<kWizCopy>(dst, dstPitch, dstType, src, r1, flags);  		}  	}  } -void Wiz::copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) { +void Wiz::copyWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth) {  	Common::Rect r1, r2;  	if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) { -		dst += r2.left + r2.top * dstw; +		dst += r2.top * dstPitch + r2.left * bitDepth;  		if (flags & kWIFFlipY) {  			const int dy = (srcy < 0) ? srcy : (srch - r1.height());  			r1.translate(0, dy); @@ -388,11 +402,11 @@ void Wiz::copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int src  			r1.translate(dx, 0);  		}  		if (xmapPtr) { -			decompressWizImage<kWizXMap>(dst, dstw, src, r1, flags, palPtr, xmapPtr); +			decompressWizImage<kWizXMap>(dst, dstPitch, dstType, src, r1, flags, palPtr, xmapPtr, bitDepth);  		} else if (palPtr) { -			decompressWizImage<kWizRMap>(dst, dstw, src, r1, flags, palPtr); +			decompressWizImage<kWizRMap>(dst, dstPitch, dstType, src, r1, flags, palPtr, NULL, bitDepth);  		} else { -			decompressWizImage<kWizCopy>(dst, dstw, src, r1, flags); +			decompressWizImage<kWizCopy>(dst, dstPitch, dstType, src, r1, flags, NULL, NULL, bitDepth);  		}  	}  } @@ -431,13 +445,100 @@ static void decodeWizMask(uint8 *&dst, uint8 &mask, int w, int maskType) {  	}  } -void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP) { +void Wiz::copyMaskWizImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr) {  	Common::Rect srcRect, dstRect;  	if (!calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, srcRect, dstRect)) {  		return;  	} -	dstw = dstw / 8; -	dst += dstRect.top * dstw + dstRect.left / 8; +	dst += dstRect.top * dstPitch + dstRect.left * 2; +	if (flags & kWIFFlipY) { +		const int dy = (srcy < 0) ? srcy : (srch - srcRect.height()); +		srcRect.translate(0, dy); +	} +	if (flags & kWIFFlipX) { +		const int dx = (srcx < 0) ? srcx : (srcw - srcRect.width()); +		srcRect.translate(dx, 0); +	} + +	const uint8 *dataPtr, *dataPtrNext; +	const uint8 *maskPtr, *maskPtrNext; +	uint8 code, *dstPtr, *dstPtrNext; +	int h, w, dstInc; + +	dataPtr = src; +	dstPtr = dst; +	maskPtr = mask; + +	// Skip over the first 'srcRect->top' lines in the data +	dataPtr += dstRect.top * dstPitch + dstRect.left * 2; + +	h = dstRect.height(); +	w = dstRect.width(); +	if (h <= 0 || w <= 0) +		return; + +	dstInc = 2; +	if (flags & kWIFFlipX) { +		dstPtr += (w - 1) * 2; +		dstInc = -2; +	} + +	while (h--) { +		w = dstRect.width(); +		uint16 lineSize = READ_LE_UINT16(maskPtr); maskPtr += 2; +		dataPtrNext = dataPtr + dstPitch; +		dstPtrNext = dstPtr + dstPitch; +		maskPtrNext = maskPtr + lineSize; +		if (lineSize != 0) { +			while (w > 0) { +				code = *maskPtr++; +				if (code & 1) { +					code >>= 1; +					dataPtr += dstInc * code; +					dstPtr += dstInc * code; +					w -= code; +				} else if (code & 2) { +					code = (code >> 2) + 1; +					w -= code; +					if (w < 0) { +						code += w; +					} +					while (code--) { +						if (*maskPtr != 5) +							write16BitColor<kWizCopy>(dstPtr, dataPtr, dstType, palPtr); +						dataPtr += 2; +						dstPtr += dstInc; +					} +					maskPtr++; +				} else { +					code = (code >> 2) + 1; +					w -= code; +					if (w < 0) { +						code += w; +					} +					while (code--) { +						if (*maskPtr != 5) +							write16BitColor<kWizCopy>(dstPtr, dataPtr, dstType, palPtr); +						dataPtr += 2; +						dstPtr += dstInc; +						maskPtr++; +					} +				} +			} +		} +		dataPtr = dataPtrNext; +		dstPtr = dstPtrNext; +		maskPtr = maskPtrNext; +	} +} + +void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstPitch, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP) { +	Common::Rect srcRect, dstRect; +	if (!calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, srcRect, dstRect)) { +		return; +	} +	dstPitch /= 8; +	dst += dstRect.top * dstPitch + dstRect.left / 8;  	const uint8 *dataPtr, *dataPtrNext;  	uint8 code, mask, *dstPtr, *dstPtrNext; @@ -462,7 +563,7 @@ void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth,  		w = srcRect.width();  		mask = revBitMask(dstRect.left & 7);  		off = READ_LE_UINT16(dataPtr); dataPtr += 2; -		dstPtrNext = dstPtr + dstw; +		dstPtrNext = dstPtr + dstPitch;  		dataPtrNext = dataPtr + off;  		if (off != 0) {  			while (w > 0) { @@ -520,7 +621,7 @@ void Wiz::copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth,  	}  } -void Wiz::copyRawWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor) { +void Wiz::copyRawWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor, uint8 bitDepth) {  	Common::Rect r1, r2;  	if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {  		if (flags & kWIFFlipX) { @@ -537,19 +638,17 @@ void Wiz::copyRawWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int  		}  		int h = r1.height();  		int w = r1.width(); -		src += r1.left + r1.top * srcw; -		dst += r2.left + r2.top * dstw; +		src += r1.top * srcw + r1.left; +		dst += r2.top * dstPitch + r2.left * bitDepth;  		if (palPtr) { -			decompressRawWizImage<kWizRMap>(dst, dstw, src, srcw, w, h, transColor, palPtr); +			decompressRawWizImage<kWizRMap>(dst, dstPitch, dstType, src, srcw, w, h, transColor, palPtr, bitDepth);  		} else { -			decompressRawWizImage<kWizCopy>(dst, dstw, src, srcw, w, h, transColor); +			decompressRawWizImage<kWizCopy>(dst, dstPitch, dstType, src, srcw, w, h, transColor, NULL, bitDepth);  		}  	}  } -void Wiz::copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor) { -	// TODO: RAW 16 bits in 555 format - +void Wiz::copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, int transColor) {  	Common::Rect r1, r2;  	if (calcClipRects(dstw, dsth, srcx, srcy, srcw, srch, rect, r1, r2)) {  		if (flags & kWIFFlipX) { @@ -567,37 +666,44 @@ void Wiz::copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth,  		int h = r1.height();  		int w = r1.width();  		src += (r1.top * srcw + r1.left) * 2; -		dst += r2.top * dstw + r2.left; +		dst += r2.top * dstPitch + r2.left * 2;  		while (h--) { -			for (int i = 0; i < w; ++i) { +			for (int i = 0; i < w; ++ i) {  				uint16 col = READ_LE_UINT16(src + 2 * i); -				uint8 r = ((col >> 10) & 0x1F) << 3; -				uint8 g = ((col >>  5) & 0x1F) << 3; -				uint8 b = ((col >>  0) & 0x1F) << 3; -				uint8 color = _vm->convert16BitColor(col, r, g, b); -  				if (transColor == -1 || transColor != col) { -					dst[i] = color; +					writeColor(dst + i * 2, dstType, col);  				}  			}  			src += srcw * 2; -			dst += dstw; +			dst += dstPitch;  		}  	}  }  template <int type> -void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) { +void Wiz::write16BitColor(uint8 *dstPtr, const uint8 *dataPtr, int dstType, const uint8 *xmapPtr) { +	uint16 col = READ_LE_UINT16(dataPtr); +	if (type == kWizXMap) { +		uint16 srcColor = (col >> 1) & 0x7DEF; +		uint16 dstColor = (READ_UINT16(dstPtr) >> 1) & 0x7DEF; +		uint16 newColor = srcColor + dstColor; +		writeColor(dstPtr, dstType, newColor); +	} +	if (type == kWizCopy) { +		writeColor(dstPtr, dstType, col); +	} +} + +template <int type> +void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *xmapPtr) {  	const uint8 *dataPtr, *dataPtrNext; -	uint8 code, *dstPtr, *dstPtrNext; +	uint8 code; +	uint8 *dstPtr, *dstPtrNext;  	int h, w, xoff, dstInc;  	if (type == kWizXMap) {  		assert(xmapPtr != 0);  	} -	if (type == kWizRMap) { -		assert(palPtr != 0); -	}  	dstPtr = dst;  	dataPtr = src; @@ -616,10 +722,10 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co  		dstPtr += (h - 1) * dstPitch;  		dstPitch = -dstPitch;  	} -	dstInc = 1; +	dstInc = 2;  	if (flags & kWIFFlipX) { -		dstPtr += w - 1; -		dstInc = -1; +		dstPtr += (w - 1) * 2; +		dstInc = -2;  	}  	while (h--) { @@ -658,21 +764,10 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co  						code += w;  					}  					while (code--) { -						uint16 col = READ_LE_UINT16(dataPtr); -						uint8 r = ((col >> 10) & 0x1F) << 3; -						uint8 g = ((col >>  5) & 0x1F) << 3; -						uint8 b = ((col >>  0) & 0x1F) << 3; -						col = _vm->convert16BitColor(col, r, g, b); - -						if (type == kWizXMap) { -							*dstPtr = xmapPtr[col * 256 + *dstPtr]; -						} -						if (type == kWizCopy) { -							*dstPtr = col; -						} +						write16BitColor<type>(dstPtr, dataPtr, dstType, xmapPtr);  						dstPtr += dstInc;  					} -					dataPtr+= 2; +					dataPtr += 2;  				} else {  					code = (code >> 2) + 1;  					if (xoff > 0) { @@ -689,18 +784,7 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co  						code += w;  					}  					while (code--) { -						uint16 col = READ_LE_UINT16(dataPtr); -						uint8 r = ((col >> 10) & 0x1F) << 3; -						uint8 g = ((col >>  5) & 0x1F) << 3; -						uint8 b = ((col >>  0) & 0x1F) << 3; -						col = _vm->convert16BitColor(col, r, g, b); - -						if (type == kWizXMap) { -							*dstPtr = xmapPtr[col * 256 + *dstPtr]; -						} -						if (type == kWizCopy) { -							*dstPtr = col; -						} +						write16BitColor<type>(dstPtr, dataPtr, dstType, xmapPtr);  						dataPtr += 2;  						dstPtr += dstInc;  					} @@ -713,7 +797,36 @@ void Wiz::decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, co  }  template <int type> -void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr) { +void Wiz::write8BitColor(uint8 *dstPtr, const uint8 *dataPtr, int dstType, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth) { +	if (bitDepth == 2) { +		if (type == kWizXMap) { +			uint16 color = READ_LE_UINT16(palPtr + *dataPtr * 2); +			uint16 srcColor = (color >> 1) & 0x7DEF; +			uint16 dstColor = (READ_UINT16(dstPtr) >> 1) & 0x7DEF; +			uint16 newColor = srcColor + dstColor; +			writeColor(dstPtr, dstType, newColor); +		} +		if (type == kWizRMap) { +			writeColor(dstPtr, dstType, READ_LE_UINT16(palPtr + *dataPtr * 2)); +		} +		if (type == kWizCopy) { +			writeColor(dstPtr, dstType, *dataPtr); +		} +	} else { +		if (type == kWizXMap) { +			*dstPtr = xmapPtr[*dataPtr * 256 + *dstPtr]; +		} +		if (type == kWizRMap) { +			*dstPtr = palPtr[*dataPtr]; +		} +		if (type == kWizCopy) { +			*dstPtr = *dataPtr; +		} +	} +} + +template <int type> +void Wiz::decompressWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth) {  	const uint8 *dataPtr, *dataPtrNext;  	uint8 code, *dstPtr, *dstPtrNext;  	int h, w, xoff, dstInc; @@ -742,10 +855,10 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C  		dstPtr += (h - 1) * dstPitch;  		dstPitch = -dstPitch;  	} -	dstInc = 1; +	dstInc = bitDepth;  	if (flags & kWIFFlipX) { -		dstPtr += w - 1; -		dstInc = -1; +		dstPtr += (w - 1) * bitDepth; +		dstInc = -bitDepth;  	}  	while (h--) { @@ -784,15 +897,7 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C  						code += w;  					}  					while (code--) { -						if (type == kWizXMap) { -							*dstPtr = xmapPtr[*dataPtr * 256 + *dstPtr]; -						} -						if (type == kWizRMap) { -							*dstPtr = palPtr[*dataPtr]; -						} -						if (type == kWizCopy) { -							*dstPtr = *dataPtr; -						} +						write8BitColor<type>(dstPtr, dataPtr, dstType, palPtr, xmapPtr, bitDepth);  						dstPtr += dstInc;  					}  					dataPtr++; @@ -812,15 +917,8 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C  						code += w;  					}  					while (code--) { -						if (type == kWizXMap) { -							*dstPtr = xmapPtr[*dataPtr++ * 256 + *dstPtr]; -						} -						if (type == kWizRMap) { -							*dstPtr = palPtr[*dataPtr++]; -						} -						if (type == kWizCopy) { -							*dstPtr = *dataPtr++; -						} +						write8BitColor<type>(dstPtr, dataPtr, dstType, palPtr, xmapPtr, bitDepth); +						dataPtr++;  						dstPtr += dstInc;  					}  				} @@ -832,12 +930,12 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C  }  // NOTE: These templates are used outside this file. We don't want the compiler to optimize them away, so we need to explicitely instantiate them. -template void Wiz::decompressWizImage<kWizXMap>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr); -template void Wiz::decompressWizImage<kWizRMap>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr); -template void Wiz::decompressWizImage<kWizCopy>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr); +template void Wiz::decompressWizImage<kWizXMap>(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth); +template void Wiz::decompressWizImage<kWizRMap>(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth); +template void Wiz::decompressWizImage<kWizCopy>(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth);  template <int type> -void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr) { +void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr, uint8 bitDepth) {  	if (type == kWizRMap) {  		assert(palPtr != 0);  	} @@ -850,10 +948,18 @@ void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, const uint8 *src, int  			uint8 col = src[i];  			if (transColor == -1 || transColor != col) {  				if (type == kWizRMap) { -					dst[i] = palPtr[col]; +					if (bitDepth == 2) { +						writeColor(dst + i * 2, dstType, READ_LE_UINT16(palPtr + col * 2)); +					} else { +						dst[i] = palPtr[col]; +					}  				}  				if (type == kWizCopy) { -					dst[i] = col; +					if (bitDepth == 2) { +						writeColor(dst + i * 2, dstType, col); +					} else { +						dst[i] = col; +					}  				}  			}  		} @@ -943,7 +1049,7 @@ uint16 Wiz::getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint  	}  	if (bitDepth == 2) -		return (READ_LE_UINT16(data) & 1) ? color : READ_LE_UINT16(data + 1); +		return (READ_LE_UINT16(data) & 1) ? color : READ_LE_UINT16(data + 2);  	else  		return (data[0] & 1) ? color : data[1]; @@ -954,7 +1060,7 @@ uint16 Wiz::getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, u  		return color;  	}  	if (bitDepth == 2) -		return READ_LE_UINT16(data + y * w + x * 2); +		return READ_LE_UINT16(data + (y * w + x) * 2);  	else  		return data[y * w + x];  } @@ -1043,6 +1149,23 @@ void Wiz::computeRawWizHistogram(uint32 *histogram, const uint8 *data, int srcPi  	}  } +static int wizPackType2(uint8 *dst, const uint8 *src, int srcPitch, const Common::Rect& rCapt) { +	debug(9, "wizPackType2([%d,%d,%d,%d])", rCapt.left, rCapt.top, rCapt.right, rCapt.bottom); +	int w = rCapt.width(); +	int h = rCapt.height(); +	int size = w * h * 2; +	if (dst) { +		src += rCapt.top * srcPitch + rCapt.left * 2; +		while (h--) { +			for (int i = 0; i < w; i++) +				WRITE_LE_UINT16(dst + i * 2, READ_UINT16(src + i * 2)); +			dst += w * 2; +			src += srcPitch; +		} +	} +	return size; +} +  static int wizPackType1(uint8 *dst, const uint8 *src, int srcPitch, const Common::Rect& rCapt, uint8 transColor) {  	debug(9, "wizPackType1(%d, [%d,%d,%d,%d])", transColor, rCapt.left, rCapt.top, rCapt.right, rCapt.bottom);  	src += rCapt.top * srcPitch + rCapt.left; @@ -1179,7 +1302,6 @@ static int wizPackType0(uint8 *dst, const uint8 *src, int srcPitch, const Common  }  void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, int compType) { -	debug(5, "ScummEngine_v72he::captureWizImage(%d, %d, [%d,%d,%d,%d])", resNum, compType, r.left, r.top, r.right, r.bottom);  	uint8 *src = NULL;  	VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];  	if (backBuffer) { @@ -1187,12 +1309,17 @@ void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, in  	} else {  		src = pvs->getPixels(0, 0);  	} -	Common::Rect rCapt(pvs->w, pvs->h); +	captureImage(src, pvs->pitch, pvs->w, pvs->h, resNum, r, compType); +} + +void Wiz::captureImage(uint8 *src, int srcPitch, int srcw, int srch, int resNum, const Common::Rect& r, int compType) { +	debug(0, "captureImage(%d, %d, [%d,%d,%d,%d])", resNum, compType, r.left, r.top, r.right, r.bottom); +	Common::Rect rCapt(srcw, srch);  	if (rCapt.intersects(r)) {  		rCapt.clip(r);  		const uint8 *palPtr;  		if (_vm->_game.heversion >= 99) { -			palPtr = _vm->_hePalettes + 1024; +			palPtr = _vm->_hePalettes + _vm->_hePaletteSlot;  		} else {  			palPtr = _vm->_currentPalette;  		} @@ -1201,15 +1328,21 @@ void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, in  		int h = rCapt.height();  		int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5; +		if (_vm->_game.features & GF_16BIT_COLOR) +			compType = 2; +  		// compute compressed size  		int dataSize = 0;  		int headerSize = palPtr ? 1080 : 36;  		switch (compType) {  		case 0: -			dataSize = wizPackType0(0, src, pvs->pitch, rCapt); +			dataSize = wizPackType0(0, src, srcPitch, rCapt);  			break;  		case 1: -			dataSize = wizPackType1(0, src, pvs->pitch, rCapt, transColor); +			dataSize = wizPackType1(0, src, srcPitch, rCapt, transColor); +			break; +		case 2: +			dataSize = wizPackType2(0, src, srcPitch, rCapt);  			break;  		default:  			error("unhandled compression type %d", compType); @@ -1249,10 +1382,13 @@ void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, in  		// write compressed data  		switch (compType) {  		case 0: -			wizPackType0(wizImg + headerSize, src, pvs->pitch, rCapt); +			wizPackType0(wizImg + headerSize, src, srcPitch, rCapt);  			break;  		case 1: -			wizPackType1(wizImg + headerSize, src, pvs->pitch, rCapt, transColor); +			wizPackType1(wizImg + headerSize, src, srcPitch, rCapt, transColor); +			break; +		case 2: +			wizPackType2(wizImg + headerSize, src, srcPitch, rCapt);  			break;  		default:  			break; @@ -1279,24 +1415,15 @@ void Wiz::displayWizImage(WizImage *pwi) {  		drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, 0, 0, 0);  	} else {  		const Common::Rect *r = NULL; -		drawWizImage(pwi->resNum, pwi->state, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, 0); +		drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0));  	}  } -uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, int palette) { -	debug(3, "drawWizImage(resNum %d, x1 %d y1 %d flags 0x%X zorder %d shadow %d field_390 %d dstResNum %d palette %d)", resNum, x1, y1, flags, zorder, shadow, field_390, dstResNum, palette); +uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr) { +	debug(3, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d field_390 %d dstResNum %d)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, field_390, dstResNum);  	uint8 *dataPtr;  	uint8 *dst = NULL; -	const uint8 *palPtr = NULL; -	if (_vm->_game.heversion >= 99) { -		if (palette) { -			palPtr = _vm->_hePalettes + palette * 1024 + 768; -		} else { -			palPtr = _vm->_hePalettes + 1792; -		} -	} -  	const uint8 *xmapPtr = NULL;  	if (shadow) {  		dataPtr = _vm->getResourceAddress(rtImage, shadow); @@ -1318,6 +1445,21 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int  	uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0);  	assert(wizd); +	uint8 *mask = NULL; +	if (maskNum) { +		uint8 *maskPtr = _vm->getResourceAddress(rtImage, maskNum); +		assert(maskPtr); + +		wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), maskPtr, maskState, 0); +		assert(wizh); +		assert(comp == 2 && READ_LE_UINT32(wizh + 0x0) == 1); +		width  = READ_LE_UINT32(wizh + 0x4); +		height = READ_LE_UINT32(wizh + 0x8); + +		mask = _vm->findWrappedBlock(MKID_BE('WIZD'), maskPtr, maskState, 0); +		assert(mask); +	}		 +  	if (flags & kWIFHasPalette) {  		uint8 *pal = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0);  		assert(pal); @@ -1339,13 +1481,25 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int  		error("WizImage printing is unimplemented");  	} -	int32 cw, ch; +	int32 dstPitch, dstType, cw, ch;  	if (flags & kWIFBlitToMemBuffer) { -		dst = (uint8 *)malloc(width * height); +		dst = (uint8 *)malloc(width * height * _vm->_bitDepth);  		int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? (_vm->VAR(_vm->VAR_WIZ_TCOLOR)) : 5; -		memset(dst, transColor, width * height); + +		if (_vm->_bitDepth == 2) { +			uint8 *tmpPtr = dst; +			for (uint i = 0; i < height; i++) { +				for (uint j = 0; j < width; j++) +					WRITE_LE_UINT16(tmpPtr + j * 2, transColor); +				tmpPtr += width * 2; +			} +		} else { +			memset(dst, transColor, width * height); +		}  		cw = width;  		ch = height; +		dstPitch = cw * _vm->_bitDepth; +		dstType = kDstMemory;  	} else {  		if (dstResNum) {  			uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum); @@ -1353,6 +1507,8 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int  			dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);  			assert(dst);  			getWizImageDim(dstResNum, 0, cw, ch); +			dstPitch = cw * _vm->_bitDepth; +			dstType = kDstResource;  		} else {  			VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];  			if (flags & kWIFMarkBufferDirty) { @@ -1362,6 +1518,8 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int  			}  			cw = pvs->w;  			ch = pvs->h; +			dstPitch = pvs->pitch; +			dstType = kDstScreen;  		}  	} @@ -1381,7 +1539,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int  		}  	} -	if (flags & kWIFRemapPalette) { +	if (flags & kWIFRemapPalette && _vm->_bitDepth == 1) {  		palPtr = rmap + 4;  	} @@ -1393,28 +1551,33 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int  	switch (comp) {  	case 0: -		copyRawWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor); +		copyRawWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor, _vm->_bitDepth);  		break;  	case 1:  		if (flags & 0x80) {  			dst = _vm->getMaskBuffer(0, 0, 1); -			copyWizImageWithMask(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, 0, 2); +			dstPitch /= _vm->_bitDepth; +			copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 2);  		} else if (flags & 0x100) {  			dst = _vm->getMaskBuffer(0, 0, 1); -			copyWizImageWithMask(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, 0, 1); +			dstPitch /= _vm->_bitDepth; +			copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 1);  		} else { -			copyWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr); +			copyWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr, _vm->_bitDepth);  		}  		break;  	case 2: -		copyRaw16BitWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor); +		if (maskNum) { +			copyMaskWizImage(dst, wizd, mask, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr); +		} else { +			copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, transColor); +		}  		break;  	case 4:  		// TODO: Unknown image type  		break;  	case 5: -		// TODO: 16bit color compressed image -		copy16BitWizImage(dst, wizd, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr); +		copy16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, xmapPtr);  		break;  	default:  		error("drawWizImage: Unhandled wiz compression type %d", comp); @@ -1517,6 +1680,74 @@ struct PolygonDrawData {  	}  }; +void Wiz::captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int id2, int compType) { +	debug(0, "captureWizPolygon: resNum %d, maskNum %d maskState %d, id1 %d id2 %d compType %d", resNum, maskNum, maskState, id1, id2, compType); + +	int i, j; +	WizPolygon *wp; + +	wp = NULL; +	for (i = 0; i < ARRAYSIZE(_polygons); ++i) { +		if (_polygons[i].id == id1) { +			wp = &_polygons[i]; +			break; +		} +	} +	if (!wp) { +		error("Polygon1 %d is not defined", id1); +	} +	if (wp->numVerts != 5) { +		error("Invalid point count %d for Polygon1 %d", wp->numVerts, id1); +	} + +	wp = NULL; +	for (i = 0; i < ARRAYSIZE(_polygons); ++i) { +		if (_polygons[i].id == id2) { +			wp = &_polygons[i]; +			break; +		} +	} +	if (!wp) { +		error("Polygon2 %d is not defined", id2); +	} +	if (wp->numVerts != 5) { +		error("Invalid point count %d for Polygon2 %d", wp->numVerts, id2); +	} + +	int32 dstw, dsth, dstpitch; +	int32 srcw, srch; +	uint8 *imageBuffer; + +	assert(maskNum); +	const Common::Rect *r = NULL; +	const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0); +	getWizImageDim(maskNum, maskState, srcw, srch); + +	dstw = wp->bound.width(); +	dsth = wp->bound.height(); +	dstpitch = dstw * _vm->_bitDepth; +	imageBuffer = (uint8 *)malloc(dstw * dsth * _vm->_bitDepth); +	assert(imageBuffer); + +	const uint16 transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5; +	if (_vm->_bitDepth == 2) { +		uint8 *tmpPtr = imageBuffer; +		for (i = 0; i < dsth; i++) { +			for (j = 0; j < dstw; j++) +				WRITE_LE_UINT16(tmpPtr + j * 2, transColor); +			tmpPtr += dstpitch; +		} +	} else { +		memset(imageBuffer, transColor, dstw * dsth); +	} + +	Common::Rect bound; +	drawWizPolygonImage(imageBuffer, src, NULL, dstpitch, kDstMemory, dstw, dsth, srcw, srch, bound, wp->vert, _vm->_bitDepth); + +	captureImage(imageBuffer, dstpitch, dstw, dsth, resNum, wp->bound, compType); +	free(imageBuffer); +} +  void Wiz::drawWizComplexPolygon(int resNum, int state, int po_x, int po_y, int shadow, int angle, int scale, const Common::Rect *r, int flags, int dstResNum, int palette) {  	Common::Point pts[4]; @@ -1544,11 +1775,10 @@ void Wiz::drawWizPolygon(int resNum, int state, int id, int flags, int shadow, i  }  void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette) { -	debug(3, "drawWizPolygonTransform(resNum %d, flags 0x%X, shadow %d dstResNum %d palette %d)", resNum, flags, shadow, dstResNum, palette); +	debug(0, "drawWizPolygonTransform(resNum %d, flags 0x%X, shadow %d dstResNum %d palette %d)", resNum, flags, shadow, dstResNum, palette);  	const Common::Rect *r = NULL;  	uint8 *srcWizBuf = NULL;  	bool freeBuffer = true; -	int i;  	if (_vm->_game.heversion >= 99) {  		if (getWizImageData(resNum, state, 0) != 0 || (flags & (kWIFRemapPalette | kWIFFlipX | kWIFFlipY)) || palette != 0) { @@ -1557,8 +1787,10 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int  			if (flags & 0x800000) {  				debug(0, "drawWizPolygonTransform() unhandled flag 0x800000");  			} -			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, shadow, 0, r, flags, 0, palette); + +			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette));  		} else { +			assert(_vm->_bitDepth == 1);  			uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);  			assert(dataPtr);  			srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); @@ -1567,7 +1799,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int  		}  	} else {  		if (getWizImageData(resNum, state, 0) != 0) { -			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, palette); +			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette));  		} else {  			uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);  			assert(dataPtr); @@ -1577,146 +1809,163 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int  		}  	} -	if (srcWizBuf) { -		uint8 *dst; -		int32 dstw, dsth, dstpitch, wizW, wizH; -		VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen]; -		int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5; +	assert(srcWizBuf); -		if (dstResNum) { -			uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum); -			assert(dstPtr); -			dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0); -			assert(dst); -			getWizImageDim(dstResNum, 0, dstw, dsth); -			dstpitch = dstw; +	uint8 *dst; +	int32 dstw, dsth, dstpitch, dstType, wizW, wizH; +	VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen]; + +	if (dstResNum) { +		uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum); +		assert(dstPtr); +		dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0); +		assert(dst); +		getWizImageDim(dstResNum, 0, dstw, dsth); +		dstpitch = dstw * _vm->_bitDepth; +		dstType = kDstResource; +	} else { +		if (flags & kWIFMarkBufferDirty) { +			dst = pvs->getPixels(0, 0);  		} else { -			if (flags & kWIFMarkBufferDirty) { -				dst = pvs->getPixels(0, 0); -			} else { -				dst = pvs->getBackPixels(0, 0); +			dst = pvs->getBackPixels(0, 0); +		} +		dstw = pvs->w; +		dsth = pvs->h; +		dstpitch = pvs->pitch; +		dstType = kDstScreen; +	} + +	Common::Rect bound; +	getWizImageDim(resNum, state, wizW, wizH); +	drawWizPolygonImage(dst, srcWizBuf, 0, dstpitch, dstType, dstw, dsth, wizW, wizH, bound, wp, _vm->_bitDepth); + +	if (flags & kWIFMarkBufferDirty) { +		_vm->markRectAsDirty(kMainVirtScreen, bound); +	} else { +		_vm->restoreBackgroundHE(bound); +	} + +	if (freeBuffer) +		free(srcWizBuf); +} + +void Wiz::drawWizPolygonImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstpitch, int dstType, int dstw, int dsth, int wizW, int wizH, Common::Rect &bound, Common::Point *wp, uint8 bitDepth) { +	int i, transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5; + +	Common::Point bbox[4]; +	bbox[0].x = 0; +	bbox[0].y = 0; +	bbox[1].x = wizW - 1; +	bbox[1].y = 0; +	bbox[2].x = wizW - 1; +	bbox[2].y = wizH - 1; +	bbox[3].x = 0; +	bbox[3].y = wizH - 1; + +	int16 xmin_p, xmax_p, ymin_p, ymax_p; +	xmin_p = ymin_p = (int16)0x7FFF; +	xmax_p = ymax_p = (int16)0x8000; + +	for (i = 0; i < 4; ++i) { +		xmin_p = MIN(wp[i].x, xmin_p); +		xmax_p = MAX(wp[i].x, xmax_p); +		ymin_p = MIN(wp[i].y, ymin_p); +		ymax_p = MAX(wp[i].y, ymax_p); +	} + +	int16 xmin_b, xmax_b, ymin_b, ymax_b; +	xmin_b = ymin_b = (int16)0x7FFF; +	xmax_b = ymax_b = (int16)0x8000; + +	for (i = 0; i < 4; ++i) { +		xmin_b = MIN(bbox[i].x, xmin_b); +		xmax_b = MAX(bbox[i].x, xmax_b); +		ymin_b = MIN(bbox[i].y, ymin_b); +		ymax_b = MAX(bbox[i].y, ymax_b); +	} + +	PolygonDrawData pdd(ymax_p - ymin_p + 1); +	pdd.mat[0].x = xmin_p; +	pdd.mat[0].y = ymin_p; +	pdd.mat[1].x = xmax_p; +	pdd.mat[1].y = ymax_p; +	pdd.mat[2].x = xmin_b; +	pdd.mat[2].y = ymin_b; +	pdd.mat[3].x = xmax_b; +	pdd.mat[3].y = ymax_b; + +	// precompute the transformation which remaps 'bbox' pixels to 'wp' +	for (i = 0; i < 3; ++i) { +		pdd.transform(&wp[i], &wp[i + 1], &bbox[i], &bbox[i + 1]); +	} +	pdd.transform(&wp[3], &wp[0], &bbox[3], &bbox[0]); + +	pdd.rAreasNum = 0; +	PolygonDrawData::ResultArea *pra = &pdd.ra[0]; +	int32 yoff = pdd.mat[0].y * dstpitch; +	int16 y_start = pdd.mat[0].y; +	for (i = 0; i < pdd.pAreasNum; ++i) { +		PolygonDrawData::PolygonArea *ppa = &pdd.pa[i]; +		if (y_start >= 0 && y_start < dsth) { +			int16 x1 = ppa->xmin; +			if (x1 < 0) { +				x1 = 0;  			} -			dstw = pvs->w; -			dsth = pvs->h; -			dstpitch = pvs->pitch; -		} - -		getWizImageDim(resNum, state, wizW, wizH); - -		Common::Point bbox[4]; -		bbox[0].x = 0; -		bbox[0].y = 0; -		bbox[1].x = wizW - 1; -		bbox[1].y = 0; -		bbox[2].x = wizW - 1; -		bbox[2].y = wizH - 1; -		bbox[3].x = 0; -		bbox[3].y = wizH - 1; - -		int16 xmin_p, xmax_p, ymin_p, ymax_p; -		xmin_p = ymin_p = (int16)0x7FFF; -		xmax_p = ymax_p = (int16)0x8000; - -		for (i = 0; i < 4; ++i) { -			xmin_p = MIN(wp[i].x, xmin_p); -			xmax_p = MAX(wp[i].x, xmax_p); -			ymin_p = MIN(wp[i].y, ymin_p); -			ymax_p = MAX(wp[i].y, ymax_p); -		} - -		int16 xmin_b, xmax_b, ymin_b, ymax_b; -		xmin_b = ymin_b = (int16)0x7FFF; -		xmax_b = ymax_b = (int16)0x8000; - -		for (i = 0; i < 4; ++i) { -			xmin_b = MIN(bbox[i].x, xmin_b); -			xmax_b = MAX(bbox[i].x, xmax_b); -			ymin_b = MIN(bbox[i].y, ymin_b); -			ymax_b = MAX(bbox[i].y, ymax_b); -		} - -		PolygonDrawData pdd(ymax_p - ymin_p + 1); -		pdd.mat[0].x = xmin_p; -		pdd.mat[0].y = ymin_p; -		pdd.mat[1].x = xmax_p; -		pdd.mat[1].y = ymax_p; -		pdd.mat[2].x = xmin_b; -		pdd.mat[2].y = ymin_b; -		pdd.mat[3].x = xmax_b; -		pdd.mat[3].y = ymax_b; - -		// precompute the transformation which remaps 'bbox' pixels to 'wp' -		for (i = 0; i < 3; ++i) { -			pdd.transform(&wp[i], &wp[i + 1], &bbox[i], &bbox[i + 1]); -		} -		pdd.transform(&wp[3], &wp[0], &bbox[3], &bbox[0]); - -		pdd.rAreasNum = 0; -		PolygonDrawData::ResultArea *pra = &pdd.ra[0]; -		int32 yoff = pdd.mat[0].y * dstpitch; -		int16 y_start = pdd.mat[0].y; -		for (i = 0; i < pdd.pAreasNum; ++i) { -			PolygonDrawData::PolygonArea *ppa = &pdd.pa[i]; -			if (y_start >= 0 && y_start < dsth) { -				int16 x1 = ppa->xmin; -				if (x1 < 0) { -					x1 = 0; -				} -				int16 x2 = ppa->xmax; -				if (x2 >= dstw) { -					x2 = dstw - 1; -				} -				int16 w = x2 - x1 + 1; -				if (w > 0) { -					int16 width = ppa->xmax - ppa->xmin + 1; -					pra->x_step = ((ppa->x2 - ppa->x1) << 16) / width; -					pra->y_step = ((ppa->y2 - ppa->y1) << 16) / width; -					pra->dst_offs = yoff + x1; -					pra->w = w; -					pra->x_s = ppa->x1 << 16; -					pra->y_s = ppa->y1 << 16; -					int16 tmp = x1 - ppa->xmin; -					if (tmp != 0) { -						pra->x_s += pra->x_step * tmp; -						pra->y_s += pra->y_step * tmp; -					} -					++pra; -					++pdd.rAreasNum; -				} +			int16 x2 = ppa->xmax; +			if (x2 >= dstw) { +				x2 = dstw - 1;  			} -			++ppa; -			yoff += dstpitch; -			++y_start; -		} - -		pra = &pdd.ra[0]; -		for (i = 0; i < pdd.rAreasNum; ++i, ++pra) { -			uint8 *dstPtr = dst + pra->dst_offs; -			int32 w = pra->w; -			int32 x_acc = pra->x_s; -			int32 y_acc = pra->y_s; -			while (--w) { -				int32 src_offs = (y_acc >> 16) * wizW + (x_acc >> 16); -				assert(src_offs < wizW * wizH); -				x_acc += pra->x_step; -				y_acc += pra->y_step; -				if (transColor == -1 || transColor != srcWizBuf[src_offs]) { -					*dstPtr = srcWizBuf[src_offs]; +			int16 w = x2 - x1 + 1; +			if (w > 0) { +				int16 width = ppa->xmax - ppa->xmin + 1; +				pra->x_step = ((ppa->x2 - ppa->x1) << 16) / width; +				pra->y_step = ((ppa->y2 - ppa->y1) << 16) / width; +				pra->dst_offs = yoff + x1 * _vm->_bitDepth; +				pra->w = w; +				pra->x_s = ppa->x1 << 16; +				pra->y_s = ppa->y1 << 16; +				int16 tmp = x1 - ppa->xmin; +				if (tmp != 0) { +					pra->x_s += pra->x_step * tmp; +					pra->y_s += pra->y_step * tmp;  				} -				dstPtr++; +				++pra; +				++pdd.rAreasNum;  			}  		} - -		Common::Rect bound(xmin_p, ymin_p, xmax_p + 1, ymax_p + 1); -		if (flags & kWIFMarkBufferDirty) { -			_vm->markRectAsDirty(kMainVirtScreen, bound); -		} else { -			_vm->restoreBackgroundHE(bound); +		++ppa; +		yoff += dstpitch; +		++y_start; +	} + +	pra = &pdd.ra[0]; +	for (i = 0; i < pdd.rAreasNum; ++i, ++pra) { +		uint8 *dstPtr = dst + pra->dst_offs; +		int32 w = pra->w; +		int32 x_acc = pra->x_s; +		int32 y_acc = pra->y_s; +		while (--w) { +			int32 src_offs = (y_acc >> 16) * wizW + (x_acc >> 16); +			assert(src_offs < wizW * wizH); +			x_acc += pra->x_step; +			y_acc += pra->y_step; +			if (bitDepth == 2) { +				if (transColor == -1 || transColor != READ_LE_UINT16(src + src_offs * 2)) { +					//if (transColor == -1 || READ_LE_UINT16(dstPtr) != transColor) +						writeColor(dstPtr, dstType, READ_LE_UINT16(src + src_offs * 2)); +				} +			} else { +				if (transColor == -1 || transColor != src[src_offs]) +					*dstPtr = src[src_offs]; +			} +			dstPtr += bitDepth;  		} - -		if (freeBuffer) -			free(srcWizBuf);  	} + +	bound.left = xmin_p; +	bound.top = ymin_p; +	bound.right = xmax_p + 1; +	bound.bottom = ymax_p + 1;  }  void Wiz::flushWizBuffer() { @@ -1726,13 +1975,13 @@ void Wiz::flushWizBuffer() {  			drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, pwi->shadow, 0, pwi->palette);  		} else {  			const Common::Rect *r = NULL; -			drawWizImage(pwi->resNum, pwi->state, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->field_390, r, pwi->flags, 0, pwi->palette); +			drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->field_390, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette));  		}  	}  	_imagesNum = 0;  } -void Wiz::loadWizCursor(int resId) { +void Wiz::loadWizCursor(int resId, int palette) {  	int32 x, y;  	getWizImageSpot(resId, 0, x, y);  	if (x < 0) { @@ -1747,11 +1996,12 @@ void Wiz::loadWizCursor(int resId) {  	}  	const Common::Rect *r = NULL; -	uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0); +	uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette)); +  	int32 cw, ch;  	getWizImageDim(resId, 0, cw, ch);  	_vm->setCursorHotspot(x, y); -	_vm->setCursorFromBuffer(cursor, cw, ch, cw); +	_vm->setCursorFromBuffer(cursor, cw, ch, cw * _vm->_bitDepth);  	// Since we set up cursor palette for default cursor, disable it now  	CursorMan.disableCursorPalette(true); @@ -1763,7 +2013,7 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {  	int sourceImage = 0;  	if (params->processFlags & kWPFMaskImg) {  		sourceImage = params->sourceImage; -		debug(0, "displayWizComplexImage() unhandled flag kWPFMaskImg"); +		debug(0, "displayWizComplexImage() flag kWPFMaskImg");  	}  	int palette = 0;  	if (params->processFlags & kWPFPaletteNum) { @@ -1831,15 +2081,14 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {  		++_imagesNum;  	} else {  		if (sourceImage != 0) { -			// TODO: Add support for kWPFMaskImg -			drawWizImage(params->sourceImage, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, palette); +			drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette));  		} else if (params->processFlags & (kWPFScaled | kWPFRotate)) {  			drawWizComplexPolygon(params->img.resNum, state, po_x, po_y, shadow, rotationAngle, scale, r, flags, dstResNum, palette);  		} else {  			if (flags & kWIFIsPolygon) {  				drawWizPolygon(params->img.resNum, state, po_x, flags, shadow, dstResNum, palette);  			} else { -				drawWizImage(params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, palette); +				drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette));  			}  		}  	} @@ -1847,6 +2096,8 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {  void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int img_h) {  	const uint16 flags = 0xB; +	const uint8 compType = (_vm->_game.features & GF_16BIT_COLOR) ? 2 : 0; +	const uint8 bitDepth = (_vm->_game.features & GF_16BIT_COLOR) ? 2 : 1;  	int res_size = 0x1C;  	if (flags & 1) {  		res_size += 0x308; @@ -1857,11 +2108,11 @@ void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int i  	if (flags & 8) {  		res_size += 0x10C;  	} -	res_size += 8 + img_w * img_h; +	res_size += 8 + img_w * img_h * bitDepth;  	const uint8 *palPtr;  	if (_vm->_game.heversion >= 99) { -		palPtr = _vm->_hePalettes + 1024; +		palPtr = _vm->_hePalettes + _vm->_hePaletteSlot;  	} else {  		palPtr = _vm->_currentPalette;  	} @@ -1874,7 +2125,7 @@ void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int i  		WRITE_BE_UINT32(res_data, res_size); res_data += 4;  		WRITE_BE_UINT32(res_data, 'WIZH'); res_data += 4;  		WRITE_BE_UINT32(res_data, 0x14); res_data += 4; -		WRITE_LE_UINT32(res_data, 0); res_data += 4; +		WRITE_LE_UINT32(res_data, compType); res_data += 4;  		WRITE_LE_UINT32(res_data, img_w); res_data += 4;  		WRITE_LE_UINT32(res_data, img_h); res_data += 4;  		if (flags & 1) { @@ -1897,7 +2148,7 @@ void Wiz::createWizEmptyImage(int resNum, int img_x, int img_y, int img_w, int i  			}  		}  		WRITE_BE_UINT32(res_data, 'WIZD'); res_data += 4; -		WRITE_BE_UINT32(res_data, 8 + img_w * img_h); res_data += 4; +		WRITE_BE_UINT32(res_data, 8 + img_w * img_h * bitDepth); res_data += 4;  	}  	_vm->_res->setModified(rtImage, resNum);  } @@ -1914,7 +2165,8 @@ void Wiz::fillWizRect(const WizParameters *params) {  		int c = READ_LE_UINT32(wizh + 0x0);  		int w = READ_LE_UINT32(wizh + 0x4);  		int h = READ_LE_UINT32(wizh + 0x8); -		assert(c == 0); +		assert(c == 0 || c == 2); +		uint8 bitDepth = (c == 2) ? 2 : 1;  		Common::Rect areaRect, imageRect(w, h);  		if (params->processFlags & kWPFClipBox) {  			if (!imageRect.intersects(params->box)) { @@ -1937,10 +2189,15 @@ void Wiz::fillWizRect(const WizParameters *params) {  			assert(wizd);  			int dx = areaRect.width();  			int dy = areaRect.height(); -			wizd += areaRect.top * w + areaRect.left; +			wizd += (areaRect.top * w + areaRect.left) * bitDepth;  			while (dy--) { -				memset(wizd, color, dx); -				wizd += w; +				if (bitDepth == 2) { +					for (int i = 0; i < dx; i++) +						WRITE_LE_UINT16(wizd + i * 2, color); +				} else { +					memset(wizd, color, dx); +				} +				wizd += w * bitDepth;  			}  		}  	} @@ -1950,14 +2207,19 @@ void Wiz::fillWizRect(const WizParameters *params) {  struct drawProcP {  	Common::Rect *imageRect;  	uint8 *wizd; -	int width; +	int pitch; +	int depth;  };  static void drawProc(int x, int y, int c, void *data) {  	drawProcP *param = (drawProcP *)data;  	if (param->imageRect->contains(x, y)) { -		*(param->wizd + y * param->width + x) = c; +		uint32 offs = y * param->pitch + x * param->depth; +		if (param->depth == 2) +			WRITE_LE_UINT16(param->wizd + offs, c); +		else +			*(param->wizd + offs) = c;  	}  } @@ -1974,7 +2236,8 @@ void Wiz::fillWizLine(const WizParameters *params) {  			int c = READ_LE_UINT32(wizh + 0x0);  			int w = READ_LE_UINT32(wizh + 0x4);  			int h = READ_LE_UINT32(wizh + 0x8); -			assert(c == 0); +			assert(c == 0 || c == 2); +			uint8 bitDepth = (c == 2) ? 2 : 1;  			Common::Rect imageRect(w, h);  			if (params->processFlags & kWPFClipBox) {  				if (!imageRect.intersects(params->box)) { @@ -1997,13 +2260,13 @@ void Wiz::fillWizLine(const WizParameters *params) {  			lineP.imageRect = &imageRect;  			lineP.wizd = wizd; -			lineP.width = w; +			lineP.pitch = w * bitDepth; +			lineP.depth = bitDepth;  			if (params->processFlags & kWPFParams) {  				assert (params->params2 == 1); // Catch untested usage  				Graphics::drawThickLine(x1, y1, x2, y2, params->params1, color, drawProc, &lineP);  			} else { -  				Graphics::drawLine(x1, y1, x2, y2, color, drawProc, &lineP);  			}  		} @@ -2065,7 +2328,7 @@ void Wiz::remapWizImagePal(const WizParameters *params) {  }  void Wiz::processWizImage(const WizParameters *params) { -	byte filename[260]; +	byte buffer[260];  	debug(3, "processWizImage: processMode %d", params->processMode);  	switch (params->processMode) { @@ -2080,18 +2343,28 @@ void Wiz::processWizImage(const WizParameters *params) {  		break;  	case 3:  		if (params->processFlags & kWPFUseFile) { -			Common::File f; +			Common::SeekableReadStream *f = NULL; +			memcpy(buffer, params->filename, 260); +			const char *filename = (char *)buffer + _vm->convertFilePath(buffer, sizeof(buffer)); -			memcpy(filename, params->filename, 260); -			_vm->convertFilePath(filename, sizeof(filename)); +			if (!_vm->_saveFileMan->listSavefiles(filename).empty()) { +				f = _vm->_saveFileMan->openForLoading(filename); +			} else { +				Common::File *nf = new Common::File(); +				nf->open(filename); +				if (!nf->isOpen()) +					delete nf; +				else +					f = nf; +			} -			if (f.open((const char *)filename)) { -				uint32 id = f.readUint32BE(); +			if (f) { +				uint32 id = f->readUint32BE();  				if (id == MKID_BE('AWIZ') || id == MKID_BE('MULT')) { -					uint32 size = f.readUint32BE(); -					f.seek(0, SEEK_SET); +					uint32 size = f->readUint32BE(); +					f->seek(0, SEEK_SET);  					byte *p = _vm->_res->createResource(rtImage, params->img.resNum, size); -					if (f.read(p, size) != size) { +					if (f->read(p, size) != size) {  						_vm->_res->nukeResource(rtImage, params->img.resNum);  						error("i/o error when reading '%s'", filename);  						_vm->VAR(_vm->VAR_GAME_LOADED) = -2; @@ -2105,7 +2378,7 @@ void Wiz::processWizImage(const WizParameters *params) {  					_vm->VAR(_vm->VAR_GAME_LOADED) = -1;  					_vm->VAR(119) = -1;  				} -				f.close(); +				delete f;  			} else {  				_vm->VAR(_vm->VAR_GAME_LOADED) = -3;  				_vm->VAR(119) = -3; @@ -2115,7 +2388,9 @@ void Wiz::processWizImage(const WizParameters *params) {  		break;  	case 4:  		if (params->processFlags & kWPFUseFile) { -			Common::DumpFile f; +			Common::OutSaveFile *f; +			memcpy(buffer, params->filename, 260); +			const char *filename = (char *)buffer + _vm->convertFilePath(buffer, sizeof(buffer));  			switch (params->fileWriteMode) {  			case 2: @@ -2125,22 +2400,20 @@ void Wiz::processWizImage(const WizParameters *params) {  				// TODO Write image to file  				break;  			case 0: -				memcpy(filename, params->filename, 260); -				_vm->convertFilePath(filename, sizeof(filename)); - -				if (!f.open((const char *)filename)) { +				if (!(f = _vm->_saveFileMan->openForSaving(filename))) {  					debug(0, "Unable to open for write '%s'", filename);  					_vm->VAR(119) = -3;  				} else {  					byte *p = _vm->getResourceAddress(rtImage, params->img.resNum);  					uint32 size = READ_BE_UINT32(p + 4); -					if (f.write(p, size) != size) { -						error("i/o error when writing '%s'", params->filename); +					if (f->write(p, size) != size) { +						error("i/o error when writing '%s'", filename);  						_vm->VAR(119) = -2;  					} else {  						_vm->VAR(119) = 0;  					} -					f.close(); +					f->finalize(); +					delete f;  				}  				break;  			default: @@ -2153,9 +2426,7 @@ void Wiz::processWizImage(const WizParameters *params) {  		break;  	// HE 99+  	case 7: -		// Used in PuttsFunShop/SamsFunShop/soccer2004 -		// TODO: Capture polygon -		_vm->_res->setModified(rtImage, params->img.resNum); +		captureWizPolygon(params->img.resNum, params->sourceImage, (params->processFlags & kWPFNewState) ? params->img.state : 0, params->polygonId1, params->polygonId2, params->compType);  		break;  	case 8: {  			int img_w = 640; @@ -2172,6 +2443,9 @@ void Wiz::processWizImage(const WizParameters *params) {  				img_x = params->img.x1;  				img_y = params->img.y1;  			} +			if (params->processFlags & kWPFParams) { +				debug(0, "Compression %d Color Depth %d", params->params1, params->params2); +			}  			createWizEmptyImage(params->img.resNum, img_x, img_y, img_w, img_h);  		}  		break; @@ -2309,7 +2583,7 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags  			ret = isWizPixelNonTransparent(wizd, x, y, w, h, 1);  			break;  		case 2: -				ret = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)) != _vm->VAR(_vm->VAR_WIZ_TCOLOR) ? 1 : 0; +			ret = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)) != _vm->VAR(_vm->VAR_WIZ_TCOLOR) ? 1 : 0;  			break;  		case 4:  			// TODO: Unknown image type diff --git a/engines/scumm/he/wiz_he.h b/engines/scumm/he/wiz_he.h index fe63457ead..d8f984f710 100644 --- a/engines/scumm/he/wiz_he.h +++ b/engines/scumm/he/wiz_he.h @@ -142,6 +142,12 @@ enum {  	kWizCopy  }; +enum DstSurface { +	kDstScreen   = 0, +	kDstMemory   = 1, +	kDstResource = 2 +}; +  class ScummEngine_v71he;  class Wiz { @@ -188,27 +194,37 @@ public:  	void flushWizBuffer();  	void getWizImageSpot(int resId, int state, int32 &x, int32 &y); -	void loadWizCursor(int resId); +	void loadWizCursor(int resId, int palette);  	void captureWizImage(int resNum, const Common::Rect& r, bool frontBuffer, int compType); +	void captureImage(uint8 *src, int srcPitch, int srcw, int srch, int resNum, const Common::Rect& r, int compType); +	void captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int id2, int compType);  	void displayWizComplexImage(const WizParameters *params);  	void displayWizImage(WizImage *pwi);  	void processWizImage(const WizParameters *params); -	uint8 *drawWizImage(int resNum, int state, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, int palette); +	uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr);  	void drawWizPolygon(int resNum, int state, int id, int flags, int shadow, int dstResNum, int palette);  	void drawWizComplexPolygon(int resNum, int state, int po_x, int po_y, int shadow, int angle, int zoom, const Common::Rect *r, int flags, int dstResNum, int palette);  	void drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette); +	void drawWizPolygonImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstpitch, int dstType, int dstw, int dsth, int wizW, int wizH, Common::Rect &bound, Common::Point *wp, uint8 bitDepth); + +	static void copyMaskWizImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr); + +	static void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, uint8 bitdepth); +	static void copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstPitch, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP); +	static void copyWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitdepth); +	static void copyRawWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor, uint8 bitdepth); +	static void copy16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *xmapPtr); +	static void copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, int transColor); +	template<int type> static void decompress16BitWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *xmapPtr = NULL); +	template<int type> static void decompressWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitdepth); +	template<int type> static void decompressRawWizImage(uint8 *dst, int dstPitch, int dstType, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr, uint8 bitdepth); + +	template<int type> static void write16BitColor(uint8 *dst, const uint8 *src, int dstType, const uint8 *xmapPtr); +	template<int type> static void write8BitColor(uint8 *dst, const uint8 *src, int dstType, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth); +	static void writeColor(uint8 *dstPtr, int dstType, uint16 color); -	static void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch); -	static void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags = 0, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL); -	static void copyWizImageWithMask(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int maskT, int maskP); -	void copy16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags = 0, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL); -	static void copyRawWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor); -	void copyRaw16BitWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor); -	template<int type> static void decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL); -	template<int type> void decompress16BitWizImage(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr = NULL, const uint8 *xmapPtr = NULL); -	template<int type> static void decompressRawWizImage(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr = NULL);  	int isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth);  	uint16 getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color);  	uint16 getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color); diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp index c356e7a06c..a596cc5b1a 100644 --- a/engines/scumm/palette.cpp +++ b/engines/scumm/palette.cpp @@ -33,6 +33,27 @@  namespace Scumm { +uint8 *ScummEngine::getHEPaletteSlot(uint16 palSlot) { +	assertRange(0, palSlot, _numPalettes, "palette"); + +	if (_game.heversion >= 99) { +		if (palSlot) +			return _hePalettes + palSlot * _hePaletteSlot + 768; +		else +			return _hePalettes + _hePaletteSlot + 768; +	} + +	return NULL; +} + +uint16 ScummEngine::get16BitColor(uint8 r, uint8 g, uint8 b) { +	uint16 ar = (r >> 3) << 10; +	uint16 ag = (g >> 3) <<  5; +	uint16 ab = (b >> 3) <<  0; +	uint16 col = ar | ag | ab; +	return col; +} +  void ScummEngine::resetPalette() {  	if (_game.version <= 1) {  		if (_game.platform == Common::kPlatformApple2GS) { @@ -310,9 +331,6 @@ void ScummEngine::setDirtyColors(int min, int max) {  		_palDirtyMin = min;  	if (_palDirtyMax < max)  		_palDirtyMax = max; - -	if (_hePaletteCache) -		memset(_hePaletteCache, -1, 65536);  }  void ScummEngine::initCycl(const byte *ptr) { @@ -799,16 +817,6 @@ void ScummEngine_v8::desaturatePalette(int hueScale, int satScale, int lightScal  #endif -int ScummEngine::convert16BitColor(uint16 color, uint8 r, uint8 g, uint8 b) { -	// HACK: Find the closest matching color, and store in -	// cache for faster access. -	if (_hePaletteCache[color] == -1) { -		_hePaletteCache[color] = remapPaletteColor(r, g, b, -1); -	} - -	return _hePaletteCache[color]; -} -  int ScummEngine::remapPaletteColor(int r, int g, int b, int threshold) {  	byte *pal;  	int ar, ag, ab, i; diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp index 67baff97b3..d3faa15c10 100644 --- a/engines/scumm/resource.cpp +++ b/engines/scumm/resource.cpp @@ -919,7 +919,11 @@ bool ScummEngine::isResourceInUse(int type, int i) const {  	case rtCostume:  		return isCostumeInUse(i);  	case rtSound: -		return _sound->isSoundInUse(i); +		// Sound resource 1 is used for queued speech +		if (_game.heversion >= 60 && i == 1) +			return true; +		else +			return _sound->isSoundInUse(i);  	case rtCharset:  		return _charset->getCurID() == i;  	case rtImage: diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index aa4dce470e..7bf61a8762 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -1553,7 +1553,7 @@ void ScummEngine_v90he::saveOrLoad(Serializer *s) {  void ScummEngine_v99he::saveOrLoad(Serializer *s) {  	ScummEngine_v90he::saveOrLoad(s); -	s->saveLoadArrayOf(_hePalettes, (_numPalettes + 1) * 1024, sizeof(_hePalettes[0]), sleUint8); +	s->saveLoadArrayOf(_hePalettes, (_numPalettes + 1) * _hePaletteSlot, sizeof(_hePalettes[0]), sleUint8);  }  void ScummEngine_v100he::saveOrLoad(Serializer *s) { diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index 4f6adc5570..fafb6b383f 100644 --- a/engines/scumm/saveload.h +++ b/engines/scumm/saveload.h @@ -50,7 +50,7 @@ namespace Scumm {   * only saves/loads those which are valid for the version of the savegame   * which is being loaded/saved currently.   */ -#define CURRENT_VER 79 +#define CURRENT_VER 80  /**   * An auxillary macro, used to specify savegame versions. We use this instead diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 8c5731d539..1beda85456 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -110,7 +110,9 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)  	  _currentScript(0xFF), // Let debug() work on init stage  	  _messageDialog(0), _pauseDialog(0), _scummMenuDialog(0), _versionDialog(0) { -	if (_game.platform == Common::kPlatformNES) { +	if (_game.features & GF_16BIT_COLOR) { +		_gdi = new Gdi16Bit(this); +	} else if (_game.platform == Common::kPlatformNES) {  		_gdi = new GdiNES(this);  	} else if (_game.version <= 1) {  		_gdi = new GdiV1(this); @@ -251,6 +253,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)  	_switchRoomEffect2 = 0;  	_switchRoomEffect = 0; +	_bitDepth = 0;  	_doEffect = false;  	_snapScroll = false;  	_currentLights = 0; @@ -267,8 +270,8 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)  	_palManipPalette = NULL;  	_palManipIntermediatePal = NULL;  	memset(gfxUsageBits, 0, sizeof(gfxUsageBits)); -	_hePaletteCache = NULL;  	_hePalettes = NULL; +	_hePaletteSlot = 0;  	_shadowPalette = NULL;  	_shadowPaletteSize = 0;  	memset(_currentPalette, 0, sizeof(_currentPalette)); @@ -523,9 +526,11 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)  		_screenHeight = 200;  	} +	_bitDepth = (_game.features & GF_16BIT_COLOR) ? 2 : 1; +  	// Allocate gfx compositing buffer (not needed for V7/V8 games).  	if (_game.version < 7) -		_compositeBuf = (byte *)malloc(_screenWidth * _screenHeight); +		_compositeBuf = (byte *)malloc(_screenWidth * _screenHeight * _bitDepth);  	else  		_compositeBuf = 0; @@ -830,7 +835,6 @@ ScummEngine_v90he::~ScummEngine_v90he() {  		delete _logicHE;  	}  	if (_game.heversion >= 99) { -		free(_hePaletteCache);  		free(_hePalettes);  	}  } @@ -1095,6 +1099,15 @@ Common::Error ScummEngine::init() {  					// CJK FT and DIG use usual NUT fonts, not FM-TOWNS ROM, so  					// there is no text surface for them. This takes that into account  					(_screenWidth * _textSurfaceMultiplier > 320)); +	} else if (_game.features & GF_16BIT_COLOR) { +#ifdef ENABLE_RGB_COLOR +		Graphics::PixelFormat format = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); +		initGraphics(_screenWidth, _screenHeight, _screenWidth > 320, &format); +		if (format != _system->getScreenFormat()) +			return Common::kUnsupportedColorMode; +#else +		error("16bit color support is required for this game"); +#endif  	} else {  		initGraphics(_screenWidth, _screenHeight, _screenWidth > 320);  	} @@ -1198,7 +1211,7 @@ void ScummEngine::setupScumm() {  	int maxHeapThreshold = -1;  	if (_game.features & GF_16BIT_COLOR) { -		// 16Bit color games require double the memory, due to increased resource sizes. +		// 16bit color games require double the memory, due to increased resource sizes.  		maxHeapThreshold = 12 * 1024 * 1024;  	} else if (_game.features & GF_NEW_COSTUMES) {  		// Since the new costumes are very big, we increase the heap limit, to avoid having @@ -1220,7 +1233,7 @@ void ScummEngine::setupScumm() {  	}  	free(_compositeBuf); -	_compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier); +	_compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier * _bitDepth);  }  #ifdef ENABLE_SCUMM_7_8 @@ -1562,11 +1575,9 @@ void ScummEngine_v99he::resetScumm() {  	ScummEngine_v90he::resetScumm(); -	_hePaletteCache = (int16 *)malloc(65536); -	memset(_hePaletteCache, -1, 65536); - -	_hePalettes = (uint8 *)malloc((_numPalettes + 1) * 1024); -	memset(_hePalettes, 0, (_numPalettes + 1) * 1024); +	_hePaletteSlot = (_game.features & GF_16BIT_COLOR) ? 1280 : 1024; +	_hePalettes = (uint8 *)malloc((_numPalettes + 1) * _hePaletteSlot); +	memset(_hePalettes, 0, (_numPalettes + 1) * _hePaletteSlot);  	// Array 129 is set to base name  	len = strlen(_filenamePattern.pattern); diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index bfb188f1c7..0e2031eea5 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -966,6 +966,7 @@ public:  	int _screenTop;  	Common::RenderMode _renderMode; +	uint8 _bitDepth;  protected:  	ColorCycle _colorCycle[16];	// Palette cycles @@ -985,7 +986,10 @@ protected:  		byte animate, animateIndex;  		int8 state;  	} _cursor; -	byte _grabbedCursor[8192]; + +	// HACK Double the array size to handle 16-bit images. +	// this should be dynamically allocated based on game depth instead. +	byte _grabbedCursor[16384];   	byte _currentCursor;  	byte _newEffect, _switchRoomEffect2, _switchRoomEffect; @@ -1051,7 +1055,8 @@ protected:  	virtual void palManipulateInit(int resID, int start, int end, int time);  	void palManipulate();  public: -	int convert16BitColor(uint16 color, uint8 r, uint8 g, uint8 b); +	uint8 *getHEPaletteSlot(uint16 palSlot); +	uint16 get16BitColor(uint8 r, uint8 g, uint8 b);  	int remapPaletteColor(int r, int g, int b, int threshold);		// Used by Actor::remapActorPalette  protected:  	void moveMemInPalRes(int start, int end, byte direction); @@ -1127,7 +1132,7 @@ public:  	// HE specific  	byte _HEV7ActorPalette[256];  	uint8 *_hePalettes; -	int16 *_hePaletteCache; +	uint16 _hePaletteSlot;  protected:  	int _shadowPaletteSize;  | 
