diff options
Diffstat (limited to 'engines/scumm')
| -rw-r--r-- | engines/scumm/charset.cpp | 109 | ||||
| -rw-r--r-- | engines/scumm/detection.cpp | 7 | ||||
| -rw-r--r-- | engines/scumm/detection_tables.h | 4 | ||||
| -rw-r--r-- | engines/scumm/gfx.cpp | 317 | ||||
| -rwxr-xr-x | engines/scumm/gfxARM.s | 120 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse.cpp | 47 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse.h | 2 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse_script.cpp | 10 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse_sndmgr.cpp | 284 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse_sndmgr.h | 70 | ||||
| -rw-r--r-- | engines/scumm/imuse_digi/dimuse_track.cpp | 31 | ||||
| -rw-r--r-- | engines/scumm/input.cpp | 5 | ||||
| -rw-r--r-- | engines/scumm/module.mk | 5 | ||||
| -rw-r--r-- | engines/scumm/scumm-md5.h | 6 | ||||
| -rw-r--r-- | engines/scumm/scumm.cpp | 28 | ||||
| -rw-r--r-- | engines/scumm/scumm.h | 4 | ||||
| -rw-r--r-- | engines/scumm/smush/smush_player.cpp | 7 | ||||
| -rw-r--r-- | engines/scumm/sound.cpp | 15 | ||||
| -rw-r--r-- | engines/scumm/string.cpp | 16 | 
19 files changed, 742 insertions, 345 deletions
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 28012e5759..2271bf53a1 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -48,6 +48,11 @@ better separation of the various modules.  void ScummEngine::loadCJKFont() {  	Common::File fp;  	_useCJKMode = false; +	_textSurfaceMultiplier = 1; + +	if (_game.platform == Common::kPlatformSegaCD) +		return; +  	if (_language == Common::JA_JPN && _game.version <= 5) { // FM-TOWNS v3 / v5 Kanji  		int numChar = 256 * 32;  		_2byteWidth = 16; @@ -60,6 +65,7 @@ void ScummEngine::loadCJKFont() {  			fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar);  			fp.close();  		} +		_textSurfaceMultiplier = 2;  	} else if (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN) {  		int numChar = 0;  		const char *fontFile = NULL; @@ -76,7 +82,7 @@ void ScummEngine::loadCJKFont() {  		case Common::ZH_TWN:  			if (_game.id == GID_CMI) {  				fontFile = "chinese.fnt"; -				numChar = 1; //FIXME +				numChar = 13630;  			}  			break;  		default: @@ -85,9 +91,26 @@ void ScummEngine::loadCJKFont() {  		if (fontFile && fp.open(fontFile)) {  			debug(2, "Loading CJK Font");  			_useCJKMode = true; -			fp.seek(2, SEEK_CUR); -			_2byteWidth = fp.readByte(); -			_2byteHeight = fp.readByte(); +			_textSurfaceMultiplier = 1; // No multiplication here +			 +			switch (_language) { +			case Common::KO_KOR: +				fp.seek(2, SEEK_CUR); +				_2byteWidth = fp.readByte(); +				_2byteHeight = fp.readByte(); +				break; +			case Common::JA_JPN: +				_2byteWidth = 16; +				_2byteHeight = 16; +				break; +			case Common::ZH_TWN: +				_2byteWidth = 16; +				_2byteHeight = 15; +				// 0xFE -> 0x21. also compared with 0x0d. perhaps a newline +				break; +			default: +				break; +			}  			_2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar];  			fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar); @@ -183,7 +206,7 @@ static int SJIStoFMTChunk(int f, int s) { //converts sjis code to fmt font offse  }  byte *ScummEngine::get2byteCharPtr(int idx) { -	switch (_language) { +	switch (_language) {	  	case Common::KO_KOR:  		idx = ((idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1;  		break; @@ -191,6 +214,43 @@ byte *ScummEngine::get2byteCharPtr(int idx) {  		idx = SJIStoFMTChunk((idx % 256), (idx / 256));  		break;  	case Common::ZH_TWN: +		{ +			int base = 0; +			byte low = idx % 256; +			int high = 0; + +			if (low >= 0x20 && low <= 0x7e) { +				base = (low + low * 2 + 81012) * 5; +			} else { +				if (low >= 0xa1 && low <= 0xa3) { +					base = 392820; +					low += 0x5f; +				} else if (low >= 0xa4 && low <= 0xc6) { +					base = 0; +					low += 0x5c; +				} else if (low >= 0xc9 && low <= 0xf9) { +					base = 162030; +					low += 0x37; +				} else { +					base = 392820; +					low = 0xff; +				} + +				if (low != 0xff) { +					high = idx / 256; +					if (high >= 0x40 && high <= 0x7e) { +						high -= 0x40; +					} else { +						high -= 0x62; +					} + +					base += (low * 0x9d + high) * 30; +				} +			} + +			return _2byteFontPtr + base; +			break; +		}  	default:  		idx = 0;  	} @@ -311,7 +371,7 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {  					break;  			}  		} else { -			if (chr == '@') +			if (chr == '@' && _vm->_language != Common::ZH_TWN)  				continue;  			if (chr == 255 || (_vm->_game.version <= 6 && chr == 254)) {  				chr = text[pos++]; @@ -337,6 +397,15 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {  					continue;  				}  			} +			 +			// Some localizations may override colors +			// See credits in Chinese COMI +			if (chr == '^' && pos == 1) { +				if (text[pos] == 'c') { +					pos += 4; +					chr = text[pos++]; +				} +			}  		}  		if ((chr & 0x80) && _vm->_useCJKMode) {  			pos++; @@ -1257,18 +1326,18 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {  		_hasMask = true;  		_textScreenID = vs->number;  	} -	if (ignoreCharsetMask || !vs->hasTwoBuffers) { +	if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {  		dst = vs->getPixels(_left, drawTop);  		drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight);  	} else { -		dst = (byte *)_vm->_textSurface.pixels + _top * _vm->_textSurface.pitch + _left; +		dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier);  		drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight);  	}  	if (_str.left > _left)  		_str.left = _left; -	_left += origWidth; +	_left += origWidth / _vm->_textSurfaceMultiplier;  	if (_str.right < _left) {  		_str.right = _left; @@ -1276,8 +1345,8 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {  			_str.right++;  	} -	if (_str.bottom < _top + height) -		_str.bottom = _top + height; +	if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier) +		_str.bottom = _top + height / _vm->_textSurfaceMultiplier;  }  void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) { @@ -1391,8 +1460,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {  	_top += offsY;  	_left += offsX; -	if (_left + origWidth > _right + 1 || _left < 0) { -		_left += origWidth; +	if (_left + origWidth / _vm->_textSurfaceMultiplier > _right + 1 || _left < 0) { +		_left += origWidth / _vm->_textSurfaceMultiplier;  		_top -= offsY;  		return;  	} @@ -1424,7 +1493,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {  	printCharIntern(is2byte, charPtr, origWidth, origHeight, width, height, vs, ignoreCharsetMask); -	_left += origWidth; +	_left += origWidth / _vm->_textSurfaceMultiplier;  	if (_str.right < _left) {  		_str.right = _left; @@ -1432,8 +1501,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {  			_str.right++;  	} -	if (_str.bottom < _top + height) -		_str.bottom = _top + height; +	if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier) +		_str.bottom = _top + height / _vm->_textSurfaceMultiplier;  	_top -= offsY;  } @@ -1473,12 +1542,12 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,  	} else {  		Graphics::Surface dstSurface;  		Graphics::Surface backSurface; -		if (ignoreCharsetMask || !vs->hasTwoBuffers) { +		if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {  			dstSurface = *vs;  			dstPtr = vs->getPixels(_left, drawTop);  		} else {  			dstSurface = _vm->_textSurface; -			dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch + _left; +			dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier;  		}  		if (_blitAlso && vs->hasTwoBuffers) { @@ -1717,6 +1786,10 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {  	if (_str.left > _left)  		_str.left = _left; +	// Original keeps glyph width and character dimensions separately +	if (_vm->_language == Common::ZH_TWN && width == 16) +		width = 17; +  	_left += width;  	if (_str.right < shadow.right) diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index e9430337ff..be830cab64 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -231,14 +231,21 @@ static Common::Language detectLanguage(const FSList &fslist, byte id) {  			switch (size) {  			case 439080:	// 2daf3db71d23d99d19fc9a544fcf6431  				return Common::EN_ANY; +			case 322602:	// caba99f4f5a0b69963e5a4d69e6f90af +				return Common::ZH_TWN;  			case 493252:	// 5d59594b24f3f1332e7d7e17455ed533  				return Common::DE_DEU;  			case 461746:	// 35bbe0e4d573b318b7b2092c331fd1fa  				return Common::FR_FRA;  			case 443439:	// 4689d013f67aabd7c35f4fd7c4b4ad69  				return Common::IT_ITA; +			case 398613:	// d1f5750d142d34c4c8f1f330a1278709 +				return Common::KO_KOR;  			case 440586:	// 5a1d0f4fa00917bdbfe035a72a6bba9d  				return Common::PT_BRA; +			case 454457:	// 0e5f450ec474a30254c0e36291fb4ebd +			case 394083:	// ad684ca14c2b4bf4c21a81c1dbed49bc +				return Common::RU_RUS;  			case 449787:	// 64f3fe479d45b52902cf88145c41d172  				return Common::ES_ESP;  			} diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 246126611e..acde4e5ad0 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -79,6 +79,7 @@ static const PlainGameDescriptor gameDescriptions[] = {  	{ "comi", "The Curse of Monkey Island" },  #endif +	{ "brstorm", "Bear Stormin'" },  	{ "fbear", "Fatty Bear's Birthday Surprise" },  	{ "fbpack", "Fatty Bear's Fun Pack" },  	{ "funpack", "Putt-Putt's Fun Pack" }, @@ -248,6 +249,7 @@ static const GameSettings gameVariantsTable[] = {  	{"funpack",  0, 0, GID_FUNPACK, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK},  	{"fbpack",   0, 0, GID_HEGAME,  6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK}, +	{"brstorm", 0, 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK},  	{"fbear", "HE 61", 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK},  	{"fbear", "HE 70", 0, GID_FBEAR, 6, 70, MDT_NONE,             GF_USE_KEY, Common::kPlatformWindows}, @@ -461,6 +463,8 @@ static const GameFilenamePattern gameFilenamesTable[] = {  	{ "fbpack", "fbpack", kGenHEPC, UNK_LANG, UNK, 0 },  	{ "funpack", "funpack", kGenHEPC, UNK_LANG, UNK, 0 }, +	{ "brstorm", "brstorm", kGenHEPC, UNK_LANG, UNK, 0 }, +  	{ "fbear", "fbear", kGenHEPC, UNK_LANG, UNK, 0 },  	{ "fbear", "fbdemo", kGenHEPC, UNK_LANG, UNK, 0 },  	{ "fbear", "Fatty Bear Demo", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 }, diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 3547986ce3..c1e06609b9 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -35,9 +35,12 @@  #include "scumm/usage_bits.h"  #include "scumm/he/wiz_he.h"  #include "scumm/util.h" -#ifdef __DS__ -#include "blitters.h" -#endif + +#ifdef USE_ARM_GFX_ASM +extern "C" void DrawStripToScreenARM(int height, int width, byte const* text, byte const* src, byte* dst,  +	int vsPitch, int vmScreenWidth, int textSurfacePitch); +extern "C" void Copy8ColARM(byte* dst, int dstPitch, const byte* src, int height); +#endif /* USE_ARM_GFX_ASM */  namespace Scumm { @@ -47,6 +50,7 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h);  static void copy8Col(byte *dst, int dstPitch, const byte *src, int height);  static void clear8Col(byte *dst, int dstPitch, int height); +static void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height);  struct StripTable {  	int offsets[160]; @@ -535,21 +539,18 @@ void ScummEngine::updateDirtyScreen(VirtScreenNumber slot) {   */  void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom) { -	if (bottom <= top) +	// Short-circuit if nothing has to be drawn +	if (bottom <= top || top >= vs->h)  		return; -	if (top >= vs->h) -		return; - -	assert(top >= 0 && bottom <= vs->h);	// Paranoia checks +	// Some paranoia checks +	assert(top >= 0 && bottom <= vs->h);  	assert(x >= 0 && width <= vs->pitch);  	assert(_textSurface.pixels); -	assert(_compositeBuf); +	// Perform some clipping  	if (width > vs->w - x)  		width = vs->w - x; - -	// Clip to the visible part of the scene  	if (top < _screenTop)  		top = _screenTop;  	if (bottom > _screenTop + _screenHeight) @@ -559,64 +560,112 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i  	int y = vs->topline + top - _screenTop;  	int height = bottom - top; -	if (height <= 0 || width <= 0) +	if (width <= 0 || height <= 0)  		return; -	// Compute screen etc. buffer pointers  	const byte *src = vs->getPixels(x, top); -	byte *dst = _compositeBuf + x + y * _screenWidth; +	int m = _textSurfaceMultiplier; +	byte *dst; +	int vsPitch; +	int pitch = vs->pitch; + +	if (_useCJKMode && _textSurfaceMultiplier == 2) { +		dst = _fmtownsBuf; + +		scale2x(dst, _screenWidth * m, src, vs->pitch,  width, height); +		src = dst; +		vsPitch = _screenWidth * m - width * m; + +	} else { +		vsPitch = vs->pitch - width; +	} + +	dst = _compositeBuf; +		  	if (_game.version < 7) { -		// Handle the text mask in older games; newer (V7/V8) games do not use it anymore. -		const byte *text = (byte *)_textSurface.getBasePtr(x, y); -	 -#ifdef __DS__ -		DS::asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, _screenWidth, _textSurface.pitch); -#else	 +		// For The Dig, FT and COMI, we just blit everything to the screen at once. +		// For older games, things are more complicated. First off, we need to +		// deal with the _textSurface, which needs to be composited over the +		// screen contents. Secondly, a rendering mode might be active, which +		// means a filter has to be applied. + +		// Compute pointer to the text surface +		assert(_compositeBuf); +		const byte *text = (byte *)_textSurface.getBasePtr(x * m, y * m); + +		// The values x, width, etc. are all multiples of 8 at this point, +		// so loop unrolloing might be a good idea... +		assert(0 == ((long)text & 3)); +		assert(0 == (width & 3)); +  		// Compose the text over the game graphics -		for (int h = 0; h < height; ++h) { -			for (int w = 0; w < width; ++w) { -				if (text[w] == CHARSET_MASK_TRANSPARENCY) -					dst[w] = src[w]; -				else -					dst[w] = text[w]; +		 +		// TODO: Optimize this code. There are several things that come immediately to mind: +		// (1) Loop unrolling: We could read 4 or even 8 pixels at once, since everything is +		//     a multiple of 8 here. +		// (2) More ASM versions (in particular, the ARM code for the NDS could be used on +		//     all ARM systems, couldn't it?) +		// (3) Better encoding of the text surface data. This is the one with the biggest +		//     potential. +		//     (a) Keep an "isEmpty" marker for each pixel row in the _textSurface. The idea +		//         is that most rows won't contain any text data, so we can just use memcpy. +		//     (b) RLE encode the _textSurface row-wise. This is an improved variant of (a), +		//         but also more complicated to implement, and incurs a bigger overhead when +		//         writing to the text surface. +#ifdef ARM_USE_GFX_ASM +		DrawStripToScreenARM(height, width, text, src, dst, vs->pitch, width, _textSurface.pitch); +#else +		for (int h = 0; h < height * m; ++h) { +			for (int w = 0; w < width * m; ++w) { +				byte tmp = *text++; +				if (tmp == CHARSET_MASK_TRANSPARENCY) +					tmp = *src; +				*dst++ = tmp; +				src++;  			} -			src += vs->pitch; -			dst += _screenWidth; -			text += _textSurface.pitch; +			src += vsPitch; +			text += _textSurface.pitch - width * m;  		}  #endif -	} else { -		// Just do a simple blit in V7/V8 games. -		blit(dst, _screenWidth, src, vs->pitch, width, height); -	} - -	if (_renderMode == Common::kRenderCGA) -		ditherCGA(_compositeBuf + x + y * _screenWidth, _screenWidth, x, y, width, height); +		src = _compositeBuf; +		pitch = width; + +		if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { +			ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height); + +			src = _herculesBuf + x + y * Common::kHercW; +			pitch = Common::kHercW; + +			// center image on the screen +			x += (Common::kHercW - _screenWidth * 2) / 2;	// (720 - 320*2)/2 = 40 +		} else if (_useCJKMode && m == 2) { +			pitch *= m; +			x *= m; +			y *= m; +			width *= m; +			height *= m; +		} else { +			if (_renderMode == Common::kRenderCGA) +				ditherCGA(_compositeBuf, width, x, y, width, height); + +			// HACK: This is dirty hack which renders narrow NES rooms centered +			// NES can address negative number strips and that poses problem for +			// our code. So instead of adding zillions of fixes and potentially +			// breaking other games, we shift it right at the rendering stage. +			if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) { +				x += 16; +				while (x + width >= _screenWidth) +					width -= 16; +				if (width < 0) +					return; +			} -	if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { -		ditherHerc(_compositeBuf + x + y * _screenWidth, _herculesBuf, _screenWidth, &x, &y, &width, &height); -		// center image on the screen -		_system->copyRectToScreen(_herculesBuf + x + y * Common::kHercW,  -			Common::kHercW, x + (Common::kHercW - _screenWidth * 2) / 2, y, width, height); -	} else { -		// Finally blit the whole thing to the screen -		int x1 = x; - -		// HACK: This is dirty hack which renders narrow NES rooms centered -		// NES can address negative number strips and that poses problem for -		// our code. So instead of adding zillions of fixes and potentially -		// breaking other games, we shift it right at the rendering stage. -		if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) { -			x += 16; -			while (x + width >= _screenWidth) -				width -= 16; -			if (width < 0) -				return;  		} - -		_system->copyRectToScreen(_compositeBuf + x1 + y * _screenWidth, _screenWidth, x, y, width, height);  	} + +	// Finally blit the whole thing to the screen +	_system->copyRectToScreen(src, pitch, x, y, width, height);  }  // CGA @@ -644,10 +693,10 @@ void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, in  	for (int y1 = 0; y1 < height; y1++) {  		ptr = dst + y1 * dstPitch; -		idx1 = (y + y1) % 2; -  		if (_game.version == 2)  			idx1 = 0; +		else +			idx1 = (y + y1) % 2;  		for (int x1 = 0; x1 < width; x1++) {  			idx2 = (x + x1) % 2; @@ -666,39 +715,52 @@ void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, in  // dd      cccc0  //         cccc1  //         dddd0 -void ScummEngine::ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) const { +void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) {  	byte *srcptr, *dstptr; -	int xo = *x, yo = *y, widtho = *width, heighto = *height; -	int idx1, idx2, dsty = 0, y1; +	const int xo = *x, yo = *y, widtho = *width, heighto = *height; +	int dsty = yo*2 - yo/4; -	// calculate dsty -	for (y1 = 0; y1 < yo; y1++) { -		dsty += 2; -		if (y1 % 4 == 3) -			dsty--; -	} -	*y = dsty; -	*x *= 2; -	*width *= 2; -	*height = 0; +	for (int y1 = 0; y1 < heighto;) { +		assert(dsty < Common::kHercH); -	for (y1 = 0; y1 < heighto;) {  		srcptr = src + y1 * srcPitch;  		dstptr = hercbuf + dsty * Common::kHercW + xo * 2; -		assert(dstptr < hercbuf + Common::kHercW * Common::kHercH + widtho * 2); - -		idx1 = (dsty % 7) % 2; +		const int idx1 = (dsty % 7) % 2;  		for (int x1 = 0; x1 < widtho; x1++) { -			idx2 = (xo + x1) % 2; -			*dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] >> 1; -			*dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] & 0x1; +			const int idx2 = (xo + x1) % 2; +			const byte tmp = cgaDither[idx1][idx2][*srcptr & 0xF]; +			*dstptr++ = tmp >> 1; +			*dstptr++ = tmp & 0x1;  			srcptr++;  		}  		if (idx1 || dsty % 7 == 6)  			y1++;  		dsty++; -		(*height)++; +	} + +	*x *= 2; +	*y = yo*2 - yo/4; +	*width *= 2; +	*height = dsty - *y; +} + +void ScummEngine::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) { +	byte *dstL1 = dst; +	byte *dstL2 = dst + dstPitch; + +	int dstAdd = dstPitch * 2 - w * 2; +	int srcAdd = srcPitch - w; + +	while (h--) { +		for (int x = 0; x < w; ++x, dstL1 += 2, dstL2 += 2) { +			uint16 col = *src++; +			col |= col << 8; +			*(uint16*)(dstL1) = col; +			*(uint16*)(dstL2) = col; +		} +		dstL1 += dstAdd; dstL2 += dstAdd; +		src += srcAdd;  	}  } @@ -1004,11 +1066,14 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h) {  	}  } +#ifdef ARM_USE_GFX_ASM + +#define copy8Col(A,B,C,D) copy8ColARM(A,B,C,D) + +#else +  static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) { -#ifndef __DS__ -	 -	  	do {  #if defined(SCUMM_NEED_ALIGNMENT)  		memcpy(dst, src, 8); @@ -1019,12 +1084,10 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) {  		dst += dstPitch;  		src += dstPitch;  	} while (--height); -#else	 -	DS::asmCopy8Col(dst, dstPitch, src, height); -#endif -	  } +#endif /* ARM_USE_GFX_ASM */ +  static void clear8Col(byte *dst, int dstPitch, int height) {  	do {  #if defined(SCUMM_NEED_ALIGNMENT) @@ -1098,8 +1161,8 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {  			error("can only copy bg to main window");  		blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height);  		if (_charset->_hasMask) { -			byte *mask = (byte *)_textSurface.getBasePtr(x, y - _screenTop); -			fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height); +			byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier); +			fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);  		}  	} else if (_game.heversion >= 71) {  		// Flags are used for different methods in HE games @@ -3343,7 +3406,17 @@ void ScummEngine::dissolveEffect(int width, int height) {  	for (i = 0; i < w * h; i++) {  		x = offsets[i] % vs->pitch;  		y = offsets[i] / vs->pitch; -		_system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height); + +		if (_useCJKMode && _textSurfaceMultiplier == 2) { +			int m = _textSurfaceMultiplier; +			byte *dst = _fmtownsBuf + x * m + y * m * _screenWidth * m; +			scale2x(dst, _screenWidth * m, vs->getPixels(x, y), vs->pitch,  width, height); + +			_system->copyRectToScreen(dst, _screenWidth * m, x * m, (y + vs->topline) * m, width * m, height * m); +		} else { +			_system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height); +		} +  		if (++blits >= blits_before_refresh) {  			blits = 0; @@ -3372,16 +3445,30 @@ void ScummEngine::scrollEffect(int dir) {  	step = (step * delay) / kScrolltime; +	byte *src; +	int m = _textSurfaceMultiplier; +	int vsPitch = vs->pitch; +  	switch (dir) {  	case 0:  		//up  		y = 1 + step;  		while (y < vs->h) {  			moveScreen(0, -step, vs->h); -			_system->copyRectToScreen(vs->getPixels(0, y - step), -				vs->pitch, -				0, vs->h - step, -				vs->w, step); + +			src = vs->getPixels(0, y - step); +			if (_useCJKMode && m == 2) { +				int x1 = 0, y1 = vs->h - step; +				byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; +				scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step); +				src = dst; +				vsPitch = _screenWidth * 2; +			} + +			_system->copyRectToScreen(src, +				vsPitch, +				0 * m, (vs->h - step) * m, +				vs->w * m, step * m);  			_system->updateScreen();  			waitForTimer(delay); @@ -3393,10 +3480,18 @@ void ScummEngine::scrollEffect(int dir) {  		y = 1 + step;  		while (y < vs->h) {  			moveScreen(0, step, vs->h); -			_system->copyRectToScreen(vs->getPixels(0, vs->h - y), -				vs->pitch, +			src = vs->getPixels(0, vs->h - y); +			if (_useCJKMode && m == 2) { +				int x1 = 0, y1 = 0; +				byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; +				scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step); +				src = dst; +				vsPitch = _screenWidth * 2; +			} +			_system->copyRectToScreen(src, +				vsPitch,  				0, 0, -				vs->w, step); +				vs->w * m, step * m);  			_system->updateScreen();  			waitForTimer(delay); @@ -3408,10 +3503,18 @@ void ScummEngine::scrollEffect(int dir) {  		x = 1 + step;  		while (x < vs->w) {  			moveScreen(-step, 0, vs->h); -			_system->copyRectToScreen(vs->getPixels(x - step, 0), -				vs->pitch, -				vs->w - step, 0, -				step, vs->h); +			src = vs->getPixels(x - step, 0); +			if (_useCJKMode && m == 2) { +				int x1 = vs->w - step, y1 = 0; +				byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; +				scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h); +				src = dst; +				vsPitch = _screenWidth * 2; +			} +			_system->copyRectToScreen(src, +				vsPitch, +				(vs->w - step) * m, 0, +				step * m, vs->h * m);  			_system->updateScreen();  			waitForTimer(delay); @@ -3423,8 +3526,16 @@ void ScummEngine::scrollEffect(int dir) {  		x = 1 + step;  		while (x < vs->w) {  			moveScreen(step, 0, vs->h); -			_system->copyRectToScreen(vs->getPixels(vs->w - x, 0), -				vs->pitch, +			src = vs->getPixels(vs->w - x, 0); +			if (_useCJKMode && m == 2) { +				int x1 = 0, y1 = 0; +				byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m; +				scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h); +				src = dst; +				vsPitch = _screenWidth * 2; +			} +			_system->copyRectToScreen(src, +				vsPitch,  				0, 0,  				step, vs->h);  			_system->updateScreen(); diff --git a/engines/scumm/gfxARM.s b/engines/scumm/gfxARM.s new file mode 100755 index 0000000000..fa2457fb29 --- /dev/null +++ b/engines/scumm/gfxARM.s @@ -0,0 +1,120 @@ +@ ScummVM Scumm Interpreter +@ Copyright (C) 2007 The ScummVM project +@ +@ This program is free software@ you can redistribute it and/or +@ modify it under the terms of the GNU General Public License +@ as published by the Free Software Foundation@ either version 2 +@ of the License, or (at your option) any later version. +@ +@ This program is distributed in the hope that it will be useful, +@ but WITHOUT ANY WARRANTY; without even the implied warranty of +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +@ GNU General Public License for more details. +@ +@ You should have received a copy of the GNU General Public License +@ along with this program@ if not, write to the Free Software +@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +@ +@ $URL:  $ +@ $Id:  $ +@ +@ @author Robin Watts (robin@wss.co.uk) + +	.text + +	.global	asmDrawStripToScreen + +	@ ARM implementation of asmDrawStripToScreen. +	@ +	@ C prototype would be: +	@ +	@ extern "C" void asmDrawStripToScreen(int         height, +	@                                      int         width, +	@                                      byte const *text, +	@                                      byte const *src, +	@                                      byte       *dst, +	@                                      int         vsPitch, +	@                                      int         vsScreenWidth, +	@                                      int         textSurfacePitch); +	@ +	@ In addition, we assume that text, src and dst are all word (4 byte) +	@ aligned. This is the same assumption that the old 'inline' version +	@ made. +asmDrawStripToScreen: +	@ r0 = height +	@ r1 = width +	@ r2 = text +	@ r3 = src +	MOV	r12,r13 +	STMFD	r13!,{r4-r7,r9-r11,R14} +	LDMIA	r12,{r4,r5,r6,r7} +	@ r4 = dst +	@ r5 = vsPitch +	@ r6 = vmScreenWidth +	@ r7 = textSurfacePitch + +	CMP	r0,#0			@ If height<=0 +	MOVLE	r0,#1			@    height=1 +	CMP	r1,#4			@ If width<4 +	BLT	end			@    return + +	@ Width &= ~4 ? What's that about then? Width &= ~3 I could have +	@ understood... +	BIC	r1,r1,#4 + +	SUB	r5,r5,r1		@ vsPitch          -= width +	SUB	r6,r6,r1		@ vmScreenWidth    -= width +	SUB	r7,r7,r1		@ textSurfacePitch -= width +	MOV	r10,#253 +	ORR	r10,r10,r10,LSL #8 +	ORR	r10,r10,r10,LSL #16	@ r10 = mask +yLoop: +	MOV	r14,r1			@ r14 = width +xLoop: +	LDR	r12,[r2],#4		@ r12 = [text] +	LDR	r11,[r3],#4		@ r11 = [src] +	CMP	r12,r10 +	BNE	singleByteCompare +	SUBS	r14,r14,#4 +	STR	r11,[r4], #4		@ r4 = [dst] +	BGT	xLoop + +	ADD	r2,r2,r7		@ text += textSurfacePitch +	ADD	r3,r3,r5		@ src  += vsPitch +	ADD	r4,r4,r6		@ dst  += vmScreenWidth +	SUBS	r0,r0,#1 +	BGT	yLoop +	LDMFD	r13!,{r4-r7,r9-r11,PC} + +singleByteCompare: +	MOV	r9,r12,LSR #24		@ r9 = 1st byte of [text] +	CMP	r9,r10,LSR #24		@ if (r9 == mask) +	MOVEQ	r9,r11,LSR #24		@     r9 = 1st byte of [src] +	ORR	r12,r9,r12,LSL #8	@ r12 = combine r9 and r12 + +	MOV	r9,r12,LSR #24		@ r9 = 1st byte of [text] +	CMP	r9,r10,LSR #24		@ if (r9 == mask) +	MOVEQ	r9,r11,LSR #24		@     r9 = 1st byte of [src] +	ORR	r12,r9,r12,LSL #8	@ r12 = combine r9 and r12 + +	MOV	r9,r12,LSR #24		@ r9 = 1st byte of [text] +	CMP	r9,r10,LSR #24		@ if (r9 == mask) +	MOVEQ	r9,r11,LSR #24		@     r9 = 1st byte of [src] +	ORR	r12,r9,r12,LSL #8	@ r12 = combine r9 and r12 + +	MOV	r9,r12,LSR #24		@ r9 = 1st byte of [text] +	CMP	r9,r10,LSR #24		@ if (r9 == mask) +	MOVEQ	r9,r11,LSR #24		@     r9 = 1st byte of [src] +	ORR	r12,r9,r12,LSL #8	@ r12 = combine r9 and r12 + +	STR	r12,[r4],#4 +	SUBS	r14,r14,#4 +	BGT	xLoop + +	ADD	r2,r2,r7		@ text += textSurfacePitch +	ADD	r3,r3,r5		@ src  += vsPitch +	ADD	r4,r4,r6		@ dst  += vmScreenWidth +	SUBS	r0,r0,#1 +	BGT	yLoop +end: +	LDMFD	r13!,{r4-r7,r9-r11,PC} diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp index 0221657966..6d2e7dd217 100644 --- a/engines/scumm/imuse_digi/dimuse.cpp +++ b/engines/scumm/imuse_digi/dimuse.cpp @@ -166,10 +166,10 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {  				continue;  			} -			track->soundHandle = _sound->openSound(track->soundId, +			track->soundDesc = _sound->openSound(track->soundId,  									track->soundName, track->soundType,  									track->volGroupId, -1); -			if (!track->soundHandle) { +			if (!track->soundDesc) {  				warning("IMuseDigital::saveOrLoad: Can't open sound so will not be resumed, propably on diffrent CD");  				track->streamSou = NULL;  				track->stream = NULL; @@ -180,14 +180,14 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {  			if (track->sndDataExtComp) {  				track->regionOffset = 0;  			} -			track->sndDataExtComp = _sound->isSndDataExtComp(track->soundHandle); +			track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc);  			if (track->sndDataExtComp) {  				track->regionOffset = 0;  			} -			track->dataOffset = _sound->getRegionOffset(track->soundHandle, track->curRegion); -			int bits = _sound->getBits(track->soundHandle); -			int channels = _sound->getChannels(track->soundHandle); -			int freq = _sound->getFreq(track->soundHandle); +			track->dataOffset = _sound->getRegionOffset(track->soundDesc, track->curRegion); +			int bits = _sound->getBits(track->soundDesc); +			int channels = _sound->getChannels(track->soundDesc); +			int freq = _sound->getFreq(track->soundDesc);  			track->feedSize = freq * channels;  			track->mixerFlags = 0;  			if (channels == 2) @@ -221,6 +221,7 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {  				type = Audio::Mixer::kMusicSoundType;  			_mixer->playInputStream(type, &track->mixChanHandle, track->stream, -1, vol, pan, false); +			_mixer->pauseHandle(track->mixChanHandle, true);  		}  	}  } @@ -284,8 +285,8 @@ void IMuseDigital::callback() {  						continue;  				} -				int bits = _sound->getBits(track->soundHandle); -				int channels = _sound->getChannels(track->soundHandle); +				int bits = _sound->getBits(track->soundDesc); +				int channels = _sound->getChannels(track->soundDesc);  				int32 feedSize = track->feedSize / _callbackFps; @@ -316,12 +317,12 @@ void IMuseDigital::callback() {  						track->dataMod12Bit = feedSize - tmpLength12Bits;  						int32 tmpOffset = (track->regionOffset * 3) / 4; -						int tmpFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits); +						int tmpFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits);  						curFeedSize = BundleCodecs::decode12BitsSample(tmpPtr, &tmpSndBufferPtr, tmpFeedSize);  						free(tmpPtr);  					} else if (bits == 16) { -						curFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); +						curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);  						if (channels == 1) {  							curFeedSize &= ~1;  						} @@ -329,7 +330,7 @@ void IMuseDigital::callback() {  							curFeedSize &= ~3;  						}  					} else if (bits == 8) { -						curFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); +						curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);  						if (channels == 2) {  							curFeedSize &= ~1;  						} @@ -346,7 +347,7 @@ void IMuseDigital::callback() {  					} else  						delete[] tmpSndBufferPtr; -					if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) { +					if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {  						switchToNextRegion(track);  						if (track->toBeRemoved)  							break; @@ -379,7 +380,7 @@ void IMuseDigital::switchToNextRegion(Track *track) {  		return;  	} -	int num_regions = _sound->getNumRegions(track->soundHandle); +	int num_regions = _sound->getNumRegions(track->soundDesc);  	if (++track->curRegion == num_regions) {  		track->toBeRemoved = true; @@ -387,22 +388,22 @@ void IMuseDigital::switchToNextRegion(Track *track) {  		return;  	} -	ImuseDigiSndMgr::soundStruct *soundHandle = track->soundHandle; -	int jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, track->curHookId); +	ImuseDigiSndMgr::SoundDesc *soundDesc = track->soundDesc; +	int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);  	if (jumpId == -1) -		jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, 0); +		jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);  	if (jumpId != -1) { -		int region = _sound->getRegionIdByJumpId(soundHandle, jumpId); +		int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);  		assert(region != -1); -		int sampleHookId = _sound->getJumpHookId(soundHandle, jumpId); +		int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);  		assert(sampleHookId != -1); -		int fadeDelay = (60 * _sound->getJumpFade(soundHandle, jumpId)) / 1000; +		int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;  		if (sampleHookId != 0) {  			if (track->curHookId == sampleHookId) {  				if (fadeDelay != 0) {  					Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);  					if (fadeTrack) { -						fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion); +						fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);  						fadeTrack->regionOffset = 0;  						debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId);  						fadeTrack->curHookId = 0; @@ -416,7 +417,7 @@ void IMuseDigital::switchToNextRegion(Track *track) {  			if (fadeDelay != 0) {  				Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);  				if (fadeTrack) { -					fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion); +					fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);  					fadeTrack->regionOffset = 0;  					debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId);  				} @@ -427,7 +428,7 @@ void IMuseDigital::switchToNextRegion(Track *track) {  	}  	debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", track->soundId, track->curRegion, track->curHookId); -	track->dataOffset = _sound->getRegionOffset(soundHandle, track->curRegion); +	track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);  	track->regionOffset = 0;  } diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h index 1b088298df..dca9baac60 100644 --- a/engines/scumm/imuse_digi/dimuse.h +++ b/engines/scumm/imuse_digi/dimuse.h @@ -98,7 +98,7 @@ private:  		int32 dataMod12Bit;	// value used between all callback to align 12 bit source of data  		int32 mixerFlags;	// flags for sound mixer's channel (kFlagStereo, kFlag16Bits, kFlagReverseStereo, kFlagUnsigned, kFlagLittleEndian) -		ImuseDigiSndMgr::soundStruct *soundHandle;	// sound handle used by iMuse sound manager +		ImuseDigiSndMgr::SoundDesc *soundDesc;	// sound handle used by iMuse sound manager  		Audio::SoundHandle mixChanHandle;					// sound mixer's channel handle  		Audio::AppendableAudioStream *stream;		// sound mixer's audio stream handle for *.la1 and *.bun  		Audio::AudioStream *streamSou;				// sound mixer's audio stream handle for *.sou diff --git a/engines/scumm/imuse_digi/dimuse_script.cpp b/engines/scumm/imuse_digi/dimuse_script.cpp index 186d04483e..ddc0cd5107 100644 --- a/engines/scumm/imuse_digi/dimuse_script.cpp +++ b/engines/scumm/imuse_digi/dimuse_script.cpp @@ -179,8 +179,8 @@ void IMuseDigital::flushTracks() {  					_mixer->stopHandle(track->mixChanHandle);  					delete track->stream;  					track->stream = NULL; -					_sound->closeSound(track->soundHandle); -					track->soundHandle = NULL; +					_sound->closeSound(track->soundDesc); +					track->soundDesc = NULL;  					track->used = false;  				}  			} else if (track->streamSou) { @@ -245,7 +245,7 @@ void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width  		for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {  			Track *track = _track[l];  			if ((track->soundId == soundId) && track->used && !track->toBeRemoved) { -				_sound->getSyncSizeAndPtrById(track->soundHandle, syncId, sync_size, &sync_ptr); +				_sound->getSyncSizeAndPtrById(track->soundDesc, syncId, sync_size, &sync_ptr);  				if ((sync_size != 0) && (sync_ptr != NULL)) {  					sync_size /= 4;  					while (sync_size--) { @@ -396,8 +396,8 @@ void IMuseDigital::stopAllSounds() {  				_mixer->stopHandle(track->mixChanHandle);  				delete track->stream;  				track->stream = NULL; -				_sound->closeSound(track->soundHandle); -				track->soundHandle = NULL; +				_sound->closeSound(track->soundDesc); +				track->soundDesc = NULL;  			} else if (track->streamSou) {  				_mixer->stopHandle(track->mixChanHandle);  				delete track->streamSou; diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp index ce963eaeea..be80cb73e8 100644 --- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp +++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp @@ -26,6 +26,7 @@  #include "common/scummsys.h"  #include "common/util.h" +#include "sound/flac.h"  #include "sound/voc.h"  #include "sound/vorbis.h"  #include "sound/mp3.h" @@ -40,7 +41,7 @@ namespace Scumm {  ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) {  	for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { -		memset(&_sounds[l], 0, sizeof(soundStruct)); +		memset(&_sounds[l], 0, sizeof(SoundDesc));  	}  	_vm = scumm;  	_disk = 0; @@ -88,7 +89,7 @@ void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, i  	} while (tag != MKID_BE('DATA'));  } -void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *sound, int32 offset, int32 size) { +void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, SoundDesc *sound, int32 offset, int32 size) {  	int l;  	file->seek(offset, SEEK_SET); @@ -104,11 +105,11 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *soun  	sound->numRegions = file->readUint32BE();  	sound->numJumps = file->readUint32BE();  	sound->numSyncs = file->readUint32BE(); -	sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions); +	sound->region = new Region[sound->numRegions];  	assert(sound->region); -	sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps); +	sound->jump = new Jump[sound->numJumps];  	assert(sound->jump); -	sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs); +	sound->sync = new Sync[sound->numSyncs];  	assert(sound->sync);  	for (l = 0; l < sound->numRegions; l++) {  		sound->region[l].offset = file->readUint32BE(); @@ -127,7 +128,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *soun  	}  } -void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) { +void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {  	if (READ_BE_UINT32(ptr) == MKID_BE('Crea')) {  		bool quit = false;  		int len; @@ -135,10 +136,16 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {  		int32 offset = READ_LE_UINT16(ptr + 20);  		int16 code = READ_LE_UINT16(ptr + 24); -		sound->region = (_region *)malloc(sizeof(_region) * 70); +		sound->numRegions = 0; +		sound->region = new Region[70];  		assert(sound->region); -		sound->jump = (_jump *)malloc(sizeof(_jump)); + +		sound->numJumps = 0; +		sound->jump = new Jump[1];  		assert(sound->jump); + +		sound->numSyncs = 0; +  		sound->resPtr = ptr;  		sound->bits = 8;  		sound->channels = 1; @@ -205,11 +212,11 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {  		sound->numJumps = 0;  		sound->numSyncs = 0;  		countElements(ptr, sound->numRegions, sound->numJumps, sound->numSyncs); -		sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions); +		sound->region = new Region[sound->numRegions];  		assert(sound->region); -		sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps); +		sound->jump = new Jump[sound->numJumps];  		assert(sound->jump); -		sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs); +		sound->sync = new Sync[sound->numSyncs];  		assert(sound->sync);  		do { @@ -260,7 +267,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {  	}  } -ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::allocSlot() { +ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::allocSlot() {  	for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {  		if (!_sounds[l].inUse) {  			_sounds[l].inUse = true; @@ -271,7 +278,7 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::allocSlot() {  	return NULL;  } -bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) { +bool ImuseDigiSndMgr::openMusicBundle(SoundDesc *sound, int disk) {  	bool result = false;  	sound->bundle = new BundleMgr(_cacheBundleDir); @@ -306,7 +313,7 @@ bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) {  	return result;  } -bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) { +bool ImuseDigiSndMgr::openVoiceBundle(SoundDesc *sound, int disk) {  	bool result = false;  	sound->bundle = new BundleMgr(_cacheBundleDir); @@ -341,11 +348,11 @@ bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) {  	return result;  } -ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) { +ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) {  	assert(soundId >= 0);  	assert(soundType); -	soundStruct *sound = allocSlot(); +	SoundDesc *sound = allocSlot();  	if (!sound) {  		error("ImuseDigiSndMgr::openSound() can't alloc free sound slot");  	} @@ -423,99 +430,97 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch  	return sound;  } -void ImuseDigiSndMgr::closeSound(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); +void ImuseDigiSndMgr::closeSound(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); -	if (soundHandle->resPtr) { +	if (soundDesc->resPtr) {  		bool found = false;  		for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { -			if ((_sounds[l].soundId == soundHandle->soundId) && (&_sounds[l] != soundHandle)) +			if ((_sounds[l].soundId == soundDesc->soundId) && (&_sounds[l] != soundDesc))  				found = true;  		}  		if (!found) -			_vm->_res->unlock(rtSound, soundHandle->soundId); +			_vm->_res->unlock(rtSound, soundDesc->soundId);  	} -	if (soundHandle->compressedStream) -		delete soundHandle->compressedStream; - -	delete soundHandle->bundle; +	delete soundDesc->compressedStream; +	delete soundDesc->bundle; -	for (int r = 0; r < soundHandle->numSyncs; r++) -		free(soundHandle->sync[r].ptr); -	free(soundHandle->region); -	free(soundHandle->jump); -	free(soundHandle->sync); -	memset(soundHandle, 0, sizeof(soundStruct)); +	for (int r = 0; r < soundDesc->numSyncs; r++) +		free(soundDesc->sync[r].ptr); +	delete[] soundDesc->region; +	delete[] soundDesc->jump; +	delete[] soundDesc->sync; +	memset(soundDesc, 0, sizeof(SoundDesc));  } -ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::cloneSound(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); +ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::cloneSound(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); -	return openSound(soundHandle->soundId, soundHandle->name, soundHandle->type, soundHandle->volGroupId, soundHandle->disk); +	return openSound(soundDesc->soundId, soundDesc->name, soundDesc->type, soundDesc->volGroupId, soundDesc->disk);  } -bool ImuseDigiSndMgr::checkForProperHandle(soundStruct *soundHandle) { -	if (!soundHandle) +bool ImuseDigiSndMgr::checkForProperHandle(SoundDesc *soundDesc) { +	if (!soundDesc)  		return false;  	for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) { -		if (soundHandle == &_sounds[l]) +		if (soundDesc == &_sounds[l])  			return true;  	}  	return false;  } -bool ImuseDigiSndMgr::isSndDataExtComp(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); -	return soundHandle->compressed; +bool ImuseDigiSndMgr::isSndDataExtComp(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); +	return soundDesc->compressed;  } -int ImuseDigiSndMgr::getFreq(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); -	return soundHandle->freq; +int ImuseDigiSndMgr::getFreq(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); +	return soundDesc->freq;  } -int ImuseDigiSndMgr::getBits(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); -	return soundHandle->bits; +int ImuseDigiSndMgr::getBits(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); +	return soundDesc->bits;  } -int ImuseDigiSndMgr::getChannels(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); -	return soundHandle->channels; +int ImuseDigiSndMgr::getChannels(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); +	return soundDesc->channels;  } -bool ImuseDigiSndMgr::isEndOfRegion(soundStruct *soundHandle, int region) { -	assert(checkForProperHandle(soundHandle)); -	assert(region >= 0 && region < soundHandle->numRegions); -	return soundHandle->endFlag; +bool ImuseDigiSndMgr::isEndOfRegion(SoundDesc *soundDesc, int region) { +	assert(checkForProperHandle(soundDesc)); +	assert(region >= 0 && region < soundDesc->numRegions); +	return soundDesc->endFlag;  } -int ImuseDigiSndMgr::getNumRegions(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); -	return soundHandle->numRegions; +int ImuseDigiSndMgr::getNumRegions(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); +	return soundDesc->numRegions;  } -int ImuseDigiSndMgr::getNumJumps(soundStruct *soundHandle) { -	assert(checkForProperHandle(soundHandle)); -	return soundHandle->numJumps; +int ImuseDigiSndMgr::getNumJumps(SoundDesc *soundDesc) { +	assert(checkForProperHandle(soundDesc)); +	return soundDesc->numJumps;  } -int ImuseDigiSndMgr::getRegionOffset(soundStruct *soundHandle, int region) { +int ImuseDigiSndMgr::getRegionOffset(SoundDesc *soundDesc, int region) {  	debug(5, "getRegionOffset() region:%d", region); -	assert(checkForProperHandle(soundHandle)); -	assert(region >= 0 && region < soundHandle->numRegions); -	return soundHandle->region[region].offset; +	assert(checkForProperHandle(soundDesc)); +	assert(region >= 0 && region < soundDesc->numRegions); +	return soundDesc->region[region].offset;  } -int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(soundStruct *soundHandle, int region, int hookId) { +int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(SoundDesc *soundDesc, int region, int hookId) {  	debug(5, "getJumpIdByRegionAndHookId() region:%d, hookId:%d", region, hookId); -	assert(checkForProperHandle(soundHandle)); -	assert(region >= 0 && region < soundHandle->numRegions); -	int32 offset = soundHandle->region[region].offset; -	for (int l = 0; l < soundHandle->numJumps; l++) { -		if (offset == soundHandle->jump[l].offset) { -			if (soundHandle->jump[l].hookId == hookId) +	assert(checkForProperHandle(soundDesc)); +	assert(region >= 0 && region < soundDesc->numRegions); +	int32 offset = soundDesc->region[region].offset; +	for (int l = 0; l < soundDesc->numJumps; l++) { +		if (offset == soundDesc->jump[l].offset) { +			if (soundDesc->jump[l].hookId == hookId)  				return l;  		}  	} @@ -523,25 +528,25 @@ int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(soundStruct *soundHandle, int re  	return -1;  } -void ImuseDigiSndMgr::getSyncSizeAndPtrById(soundStruct *soundHandle, int number, int32 &sync_size, byte **sync_ptr) { -	assert(checkForProperHandle(soundHandle)); +void ImuseDigiSndMgr::getSyncSizeAndPtrById(SoundDesc *soundDesc, int number, int32 &sync_size, byte **sync_ptr) { +	assert(checkForProperHandle(soundDesc));  	assert(number >= 0); -	if (number < soundHandle->numSyncs) { -		sync_size = soundHandle->sync[number].size; -		*sync_ptr = soundHandle->sync[number].ptr; +	if (number < soundDesc->numSyncs) { +		sync_size = soundDesc->sync[number].size; +		*sync_ptr = soundDesc->sync[number].ptr;  	} else {  		sync_size = 0;  		*sync_ptr = NULL;  	}  } -int ImuseDigiSndMgr::getRegionIdByJumpId(soundStruct *soundHandle, int jumpId) { +int ImuseDigiSndMgr::getRegionIdByJumpId(SoundDesc *soundDesc, int jumpId) {  	debug(5, "getRegionIdByJumpId() jumpId:%d", jumpId); -	assert(checkForProperHandle(soundHandle)); -	assert(jumpId >= 0 && jumpId < soundHandle->numJumps); -	int32 dest = soundHandle->jump[jumpId].dest; -	for (int l = 0; l < soundHandle->numRegions; l++) { -		if (dest == soundHandle->region[l].offset) { +	assert(checkForProperHandle(soundDesc)); +	assert(jumpId >= 0 && jumpId < soundDesc->numJumps); +	int32 dest = soundDesc->jump[jumpId].dest; +	for (int l = 0; l < soundDesc->numRegions; l++) { +		if (dest == soundDesc->region[l].offset) {  			return l;  		}  	} @@ -549,89 +554,110 @@ int ImuseDigiSndMgr::getRegionIdByJumpId(soundStruct *soundHandle, int jumpId) {  	return -1;  } -int ImuseDigiSndMgr::getJumpHookId(soundStruct *soundHandle, int number) { +int ImuseDigiSndMgr::getJumpHookId(SoundDesc *soundDesc, int number) {  	debug(5, "getJumpHookId() number:%d", number); -	assert(checkForProperHandle(soundHandle)); -	assert(number >= 0 && number < soundHandle->numJumps); -	return soundHandle->jump[number].hookId; +	assert(checkForProperHandle(soundDesc)); +	assert(number >= 0 && number < soundDesc->numJumps); +	return soundDesc->jump[number].hookId;  } -int ImuseDigiSndMgr::getJumpFade(soundStruct *soundHandle, int number) { +int ImuseDigiSndMgr::getJumpFade(SoundDesc *soundDesc, int number) {  	debug(5, "getJumpFade() number:%d", number); -	assert(checkForProperHandle(soundHandle)); -	assert(number >= 0 && number < soundHandle->numJumps); -	return soundHandle->jump[number].fadeDelay; +	assert(checkForProperHandle(soundDesc)); +	assert(number >= 0 && number < soundDesc->numJumps); +	return soundDesc->jump[number].fadeDelay;  } -int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) { -	debug(5, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundHandle->numRegions); -	assert(checkForProperHandle(soundHandle)); +int32 ImuseDigiSndMgr::getDataFromRegion(SoundDesc *soundDesc, int region, byte **buf, int32 offset, int32 size) { +	debug(5, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundDesc->numRegions); +	assert(checkForProperHandle(soundDesc));  	assert(buf && offset >= 0 && size >= 0); -	assert(region >= 0 && region < soundHandle->numRegions); +	assert(region >= 0 && region < soundDesc->numRegions); -	int32 region_offset = soundHandle->region[region].offset; -	int32 region_length = soundHandle->region[region].length; -	int32 offset_data = soundHandle->offsetData; +	int32 region_offset = soundDesc->region[region].offset; +	int32 region_length = soundDesc->region[region].length; +	int32 offset_data = soundDesc->offsetData;  	int32 start = region_offset - offset_data;  	if (offset + size + offset_data > region_length) {  		size = region_length - offset; -		soundHandle->endFlag = true; +		soundDesc->endFlag = true;  	} else { -		soundHandle->endFlag = false; +		soundDesc->endFlag = false;  	} -	int header_size = soundHandle->offsetData; +	int header_size = soundDesc->offsetData;  	bool header_outside = ((_vm->_game.id == GID_CMI) && !(_vm->_game.features & GF_DEMO)); -	if ((soundHandle->bundle) && (!soundHandle->compressed)) { -		size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside); -	} else if (soundHandle->resPtr) { +	if ((soundDesc->bundle) && (!soundDesc->compressed)) { +		size = soundDesc->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside); +	} else if (soundDesc->resPtr) {  		*buf = new byte[size];  		assert(*buf); -		memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size); -	} else if ((soundHandle->bundle) && (soundHandle->compressed)) { +		memcpy(*buf, soundDesc->resPtr + start + offset + header_size, size); +	} else if ((soundDesc->bundle) && (soundDesc->compressed)) {  		*buf = new byte[size];  		assert(*buf);  		char fileName[24]; -		sprintf(fileName, "%s_reg%03d", soundHandle->name, region); -		if (scumm_stricmp(fileName, soundHandle->lastFileName) != 0) { +		sprintf(fileName, "%s_reg%03d", soundDesc->name, region); +		if (scumm_stricmp(fileName, soundDesc->lastFileName) != 0) {  			int32 offs = 0, len = 0;  			Common::File *cmpFile; -			bool oggMode = false; -			sprintf(fileName, "%s_reg%03d.mp3", soundHandle->name, region); -			cmpFile = soundHandle->bundle->getFile(fileName, offs, len); -#ifndef USE_MAD -			if (len) -				error("Mad library compiled support needed!"); +			uint8 soundMode = 0; + +			sprintf(fileName, "%s_reg%03d.fla", soundDesc->name, region); +			cmpFile = soundDesc->bundle->getFile(fileName, offs, len); +			if (len) { +#ifndef USE_FLAC +				error("FLAC library compiled support needed!");  #endif +				soundMode = 3; +			}  			if (!len) { -				sprintf(fileName, "%s_reg%03d.ogg", soundHandle->name, region); -				cmpFile = soundHandle->bundle->getFile(fileName, offs, len); +				sprintf(fileName, "%s_reg%03d.ogg", soundDesc->name, region); +				cmpFile = soundDesc->bundle->getFile(fileName, offs, len); +				if (len) {  #ifndef USE_VORBIS -				if (len)  					error("Vorbis library compiled support needed!");  #endif -				assert(len); -				oggMode = true; +					soundMode = 2; +				} +			} +			if (!len) { +				sprintf(fileName, "%s_reg%03d.mp3", soundDesc->name, region); +				cmpFile = soundDesc->bundle->getFile(fileName, offs, len); +				if (len) { +#ifndef USE_MAD +					error("Mad library compiled support needed!"); +#endif +					soundMode = 1; +				}  			} -			if (!soundHandle->compressedStream) { +			assert(len); + +			if (!soundDesc->compressedStream) { +				Common::MemoryReadStream *tmp = cmpFile->readStream(len); +				assert(tmp); +#ifdef USE_FLAC +				if (soundMode == 3) +					soundDesc->compressedStream = Audio::makeFlacStream(tmp, true); +#endif  #ifdef USE_VORBIS -				if (oggMode) -					soundHandle->compressedStream = Audio::makeVorbisStream(cmpFile, len); +				if (soundMode == 2) +					soundDesc->compressedStream = Audio::makeVorbisStream(tmp, true);  #endif  #ifdef USE_MAD -				if (!oggMode) -					soundHandle->compressedStream = Audio::makeMP3Stream(cmpFile, len); +				if (soundMode == 1) +					soundDesc->compressedStream = Audio::makeMP3Stream(tmp, true);  #endif -				assert(soundHandle->compressedStream); +				assert(soundDesc->compressedStream);  			} -			strcpy(soundHandle->lastFileName, fileName); +			strcpy(soundDesc->lastFileName, fileName);  		} -		size = soundHandle->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2; -		if (soundHandle->compressedStream->endOfData()) { -			delete soundHandle->compressedStream; -			soundHandle->compressedStream = NULL; -			soundHandle->lastFileName[0] = 0; +		size = soundDesc->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2; +		if (soundDesc->compressedStream->endOfData()) { +			delete soundDesc->compressedStream; +			soundDesc->compressedStream = NULL; +			soundDesc->lastFileName[0] = 0;  		}  	} diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.h b/engines/scumm/imuse_digi/dimuse_sndmgr.h index 5d2f8c88ba..e4e2e795a2 100644 --- a/engines/scumm/imuse_digi/dimuse_sndmgr.h +++ b/engines/scumm/imuse_digi/dimuse_sndmgr.h @@ -48,35 +48,39 @@ public:  #define IMUSE_VOLGRP_MUSIC 3  private: -	struct _region { +	struct Region {  		int32 offset;		// offset of region  		int32 length;		// lenght of region  	}; -	struct _jump { +	struct Jump {  		int32 offset;		// jump offset position  		int32 dest;			// jump to dest position  		byte hookId;		// id of hook  		int16 fadeDelay;	// fade delay in ms  	}; -	struct _sync { +	struct Sync {  		int32 size;			// size of sync  		byte *ptr;			// pointer to sync  	};  public: -	struct soundStruct { +	struct SoundDesc {  		uint16 freq;		// frequency  		byte channels;		// stereo or mono  		byte bits;			// 8, 12, 16 +  		int numJumps;		// number of Jumps +		Region *region; +  		int numRegions;		// number of Regions +		Jump *jump; +  		int numSyncs;		// number of Syncs -		_region *region; -		_jump *jump; -		_sync *sync; +		Sync *sync; +  		bool endFlag;  		bool inUse;  		byte *allData; @@ -95,19 +99,19 @@ public:  private: -	soundStruct _sounds[MAX_IMUSE_SOUNDS]; +	SoundDesc _sounds[MAX_IMUSE_SOUNDS]; -	bool checkForProperHandle(soundStruct *soundHandle); -	soundStruct *allocSlot(); -	void prepareSound(byte *ptr, soundStruct *sound); -	void prepareSoundFromRMAP(Common::File *file, soundStruct *sound, int32 offset, int32 size); +	bool checkForProperHandle(SoundDesc *soundDesc); +	SoundDesc *allocSlot(); +	void prepareSound(byte *ptr, SoundDesc *sound); +	void prepareSoundFromRMAP(Common::File *file, SoundDesc *sound, int32 offset, int32 size);  	ScummEngine *_vm;  	byte _disk;  	BundleDirCache *_cacheBundleDir; -	bool openMusicBundle(soundStruct *sound, int disk); -	bool openVoiceBundle(soundStruct *sound, int disk); +	bool openMusicBundle(SoundDesc *sound, int disk); +	bool openVoiceBundle(SoundDesc *sound, int disk);  	void countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs); @@ -116,25 +120,25 @@ public:  	ImuseDigiSndMgr(ScummEngine *scumm);  	~ImuseDigiSndMgr(); -	soundStruct *openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk); -	void closeSound(soundStruct *soundHandle); -	soundStruct *cloneSound(soundStruct *soundHandle); - -	bool isSndDataExtComp(soundStruct *soundHandle); -	int getFreq(soundStruct *soundHandle); -	int getBits(soundStruct *soundHandle); -	int getChannels(soundStruct *soundHandle); -	bool isEndOfRegion(soundStruct *soundHandle, int region); -	int getNumRegions(soundStruct *soundHandle); -	int getNumJumps(soundStruct *soundHandle); -	int getRegionOffset(soundStruct *soundHandle, int region); -	int getJumpIdByRegionAndHookId(soundStruct *soundHandle, int region, int hookId); -	int getRegionIdByJumpId(soundStruct *soundHandle, int jumpId); -	int getJumpHookId(soundStruct *soundHandle, int number); -	int getJumpFade(soundStruct *soundHandle, int number); -	void getSyncSizeAndPtrById(soundStruct *soundHandle, int number, int32 &sync_size, byte **sync_ptr); - -	int32 getDataFromRegion(soundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size); +	SoundDesc *openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk); +	void closeSound(SoundDesc *soundDesc); +	SoundDesc *cloneSound(SoundDesc *soundDesc); + +	bool isSndDataExtComp(SoundDesc *soundDesc); +	int getFreq(SoundDesc *soundDesc); +	int getBits(SoundDesc *soundDesc); +	int getChannels(SoundDesc *soundDesc); +	bool isEndOfRegion(SoundDesc *soundDesc, int region); +	int getNumRegions(SoundDesc *soundDesc); +	int getNumJumps(SoundDesc *soundDesc); +	int getRegionOffset(SoundDesc *soundDesc, int region); +	int getJumpIdByRegionAndHookId(SoundDesc *soundDesc, int region, int hookId); +	int getRegionIdByJumpId(SoundDesc *soundDesc, int jumpId); +	int getJumpHookId(SoundDesc *soundDesc, int number); +	int getJumpFade(SoundDesc *soundDesc, int number); +	void getSyncSizeAndPtrById(SoundDesc *soundDesc, int number, int32 &sync_size, byte **sync_ptr); + +	int32 getDataFromRegion(SoundDesc *soundDesc, int region, byte **buf, int32 offset, int32 size);  };  } // End of namespace Scumm diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp index 75dde5e60f..987e1bc3c9 100644 --- a/engines/scumm/imuse_digi/dimuse_track.cpp +++ b/engines/scumm/imuse_digi/dimuse_track.cpp @@ -117,20 +117,20 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,  		track->feedSize = 0;  		track->souStreamUsed = true;  		track->soundName[0] = 0; -		track->soundHandle = NULL; +		track->soundDesc = NULL;  	} else {  		track->souStreamUsed = false;  		strcpy(track->soundName, soundName); -		track->soundHandle = _sound->openSound(soundId, soundName, soundType, volGroupId, -1); +		track->soundDesc = _sound->openSound(soundId, soundName, soundType, volGroupId, -1); -		if (track->soundHandle == NULL) +		if (track->soundDesc == NULL)  			return; -		track->sndDataExtComp = _sound->isSndDataExtComp(track->soundHandle); +		track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc); -		bits = _sound->getBits(track->soundHandle); -		channels = _sound->getChannels(track->soundHandle); -		freq = _sound->getFreq(track->soundHandle); +		bits = _sound->getBits(track->soundDesc); +		channels = _sound->getChannels(track->soundDesc); +		freq = _sound->getFreq(track->soundDesc);  		if ((soundId == kTalkSoundID) && (soundType == IMUSE_BUNDLE)) {  			if (_vm->_actorToPrintStrFor != 0xFF && _vm->_actorToPrintStrFor != 0) { @@ -325,15 +325,12 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(const Track *track, int f  	// Clone the settings of the given track  	memcpy(fadeTrack, track, sizeof(Track)); -	// Clone the soundhandle -	// FIXME: Shouldn't we check here whether track->soundHandle is NULL, resp. whether stream2 -	// is being used (as in, we are using compressed data)... -	// -	// -- aquadran -- nope :) this is called only for bundle files and sound data in *.la1 -	// from switchToNextRegion and fadeOutMusic func. -	// stream2 is used only for sou VOICE type sound data (FT) -- -	fadeTrack->soundHandle = _sound->cloneSound(track->soundHandle); -	assert(fadeTrack->soundHandle); +	// Clone the sound. +	// According to aquadran, this is only called for bundle files and sound +	// data in *.la1 from switchToNextRegion and fadeOutMusic func. Henc we +	// know that track->soundDesc != NULL. +	fadeTrack->soundDesc = _sound->cloneSound(track->soundDesc); +	assert(fadeTrack->soundDesc);  	// Set the volume fading parameters to indicate a fade out  	fadeTrack->volFadeDelay = fadeDelay; @@ -357,7 +354,7 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(const Track *track, int f  		type = Audio::Mixer::kPlainSoundType;  		break;  	} -	fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), makeMixerFlags(fadeTrack->mixerFlags)); +	fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags));  	_mixer->playInputStream(type, &fadeTrack->mixChanHandle, fadeTrack->stream, -1, fadeTrack->vol / 1000, fadeTrack->pan, false);  	fadeTrack->mixerStreamRunning = true; diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp index ffcb7d03f2..6647e9fe8d 100644 --- a/engines/scumm/input.cpp +++ b/engines/scumm/input.cpp @@ -162,8 +162,11 @@ void ScummEngine::parseEvents() {  			if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {  				_mouse.x -= (Common::kHercW - _screenWidth * 2) / 2; -				_mouse.x /= 2; +				_mouse.x >>= 1;  				_mouse.y = _mouse.y * 4 / 7; +			} else if (_useCJKMode && _textSurfaceMultiplier == 2) { +				_mouse.x >>= 1; +				_mouse.y >>= 1;  			}  			break;  		case Common::EVENT_LBUTTONUP: diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index d8ef669410..a340f564b3 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -90,6 +90,11 @@ endif  endif +ifdef USE_ARM_GFX_ASM +MODULE_OBJS += \ +	gfxARM.o +endif +  ifndef DISABLE_HE  MODULE_OBJS += \  	he/animation_he.o \ diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index cd48ef4d02..4f6b2477c6 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@  /* -  This file was generated by the md5table tool on Mon Jul  2 22:44:41 2007 +  This file was generated by the md5table tool on Fri Jul 20 21:25:14 2007    DO NOT EDIT MANUALLY!   */ @@ -25,10 +25,12 @@ static const MD5Table md5table[] = {  	{ "04687cdf7f975a89d2474929f7b80946", "indy3", "FM-TOWNS", "", 7552, Common::EN_ANY, Common::kPlatformFMTowns },  	{ "0557df19f046a84c2fdc63507c6616cb", "farm", "HE 72", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },  	{ "055ffe4f47753e47594ac67823220c54", "puttrace", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, +	{ "057c9b456dedcc4d71b991a3072a20b3", "monkey", "SEGA", "", 9465, Common::JA_JPN, Common::kPlatformSegaCD },  	{ "0650e8ab1432564607cd651c0fa3f344", "loom", "PC-Engine", "", -1, Common::EN_ANY, Common::kPlatformPCEngine },  	{ "06b187468113f9ae5a400b148a847fac", "atlantis", "", "Floppy", 12075, Common::EN_ANY, Common::kPlatformMacintosh },  	{ "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },  	{ "07433205acdca3bc553d0e731588b35f", "airport", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, +	{ "07a1eefd8ca95d77310311446c0f53d0", "brstorm", "", "Demo", 5433, Common::EN_ANY, Common::kPlatformUnknown },  	{ "07b810e37be7489263f7bc7627d4765d", "freddi4", "unenc", "Unencrypted", -1, Common::RU_RUS, Common::kPlatformWindows },  	{ "084ed0fa98a6d1e9368d67fe9cfbd417", "freddi", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },  	{ "0855496dde35356b1a9691e22ba84cdc", "freddi", "HE 73", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, @@ -320,6 +322,7 @@ static const MD5Table md5table[] = {  	{ "86be8ada36371d4fdc35659d0e912a26", "indy3", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformPC },  	{ "86c9902b7bec1a17926d4dae85beaa45", "airport", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },  	{ "870d1e3c86bc50846d808d14a36b4e08", "monkey", "VGA", "VGA", -1, Common::ES_ESP, Common::kPlatformAmiga }, +	{ "8776caed014c321272af407c1502a2df", "monkey", "CD", "", 8955, Common::EN_ANY, Common::kPlatformMacintosh },  	{ "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC },  	{ "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },  	{ "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, @@ -444,6 +447,7 @@ static const MD5Table md5table[] = {  	{ "c8575e0b973ff1723aba6cd92c642db2", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },  	{ "c8aac5e3e701874e2fa4117896f9e1b1", "freddi", "HE 73", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },  	{ "c8c5baadcbfc8d0372ed4335abace8a7", "pajama3", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, +	{ "c9717ee6059f1e43b768b464493d2fba", "fbpack", "", "", -1, Common::JA_JPN, Common::kPlatform3DO },  	{ "cb1559e8405d17a5a278a6b5ad9338d1", "freddi3", "", "Demo", 22718, Common::EN_ANY, Common::kPlatformUnknown },  	{ "cc04a076779379524ed4d9c5ee3c6fb1", "tentacle", "", "CD", 282467632, Common::EN_ANY, Common::kPlatformMacintosh },  	{ "cc8ba2b0df2f9c450bcf055fe2711979", "samnmax", "", "Demo", 7485, Common::DE_DEU, Common::kPlatformPC }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 2140b15544..e54060c9e1 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -480,7 +480,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)  		_renderMode = Common::kRenderDefault;  	} -	// Do some render mode restirctions +	// Check some render mode restrictions  	if (_game.version <= 1)  		_renderMode = Common::kRenderDefault; @@ -521,7 +521,11 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)  		_screenHeight = 200;  	} -	_compositeBuf = (byte *)malloc(_screenWidth * _screenHeight); +	// Allocate gfx compositing buffer (not needed for V7/V8 games). +	if (_game.version < 7) +		_compositeBuf = (byte *)malloc(_screenWidth * _screenHeight); +	else +		_compositeBuf = 0;  	_herculesBuf = 0;  	if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { @@ -583,6 +587,7 @@ ScummEngine::~ScummEngine() {  	free(_compositeBuf);  	free(_herculesBuf); +	free(_fmtownsBuf);  	delete _debugger; @@ -1074,12 +1079,19 @@ int ScummEngine::init() {  		_fileHandle = new ScummFile();  	} +	// Load CJK font, if present +	// Load it earlier so _useCJKMode variable could be set +	loadCJKFont(); +  	// Initialize backend  	_system->beginGFXTransaction();  		bool defaultTo1XScaler = false;  		if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {  			_system->initSize(Common::kHercW, Common::kHercH);  			defaultTo1XScaler = true; +		} else if (_useCJKMode) { +			_system->initSize(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier); +			defaultTo1XScaler = true;  		} else {  			_system->initSize(_screenWidth, _screenHeight);  			defaultTo1XScaler = (_screenWidth > 320); @@ -1131,14 +1143,11 @@ void ScummEngine::setupScumm() {  	// Load localization data, if present  	loadLanguageBundle(); -	// Load CJK font, if present -	loadCJKFont(); -  	// Create the charset renderer  	setupCharsetRenderer();  	// Create and clear the text surface -	_textSurface.create(_screenWidth, _screenHeight, 1); +	_textSurface.create(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, 1);  	clearTextSurface();  	// Create the costume renderer @@ -1206,6 +1215,13 @@ void ScummEngine::setupScumm() {  #if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))  	Graphics::initfonts();  #endif + +	_fmtownsBuf = 0; +	if (_game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) { +		_fmtownsBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier); +	} + +	_compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier);  }  #ifndef DISABLE_SCUMM_7_8 diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 4146846856..18c2275029 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -1026,11 +1026,12 @@ protected:  	// Screen rendering  	byte *_compositeBuf;  	byte *_herculesBuf; +	byte *_fmtownsBuf;  	virtual void drawDirtyScreenParts();  	void updateDirtyScreen(VirtScreenNumber slot);  	void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b);  	void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const; -	void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) const; +	void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);  public:  	VirtScreen *findVirtScreen(int y); @@ -1152,6 +1153,7 @@ public:  	 * drawStripToScreen() composits it over the game graphics.  	 */  	Graphics::Surface _textSurface; +	int _textSurfaceMultiplier;  protected:  	byte _charsetColor; diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 2c744a16e2..ce39302e25 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -1178,12 +1178,15 @@ void SmushPlayer::tryCmpFile(const char *filename) {  	char fname[260];  #endif  	Common::File *file = new Common::File(); + +	// FIXME: How about using AudioStream::openStreamFile instead of the code below? +  #ifdef USE_VORBIS  	memcpy(fname, filename, i - filename);  	strcpy(fname + (i - filename), ".ogg");  	if (file->open(fname)) {  		_compressedFileMode = true; -		_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeVorbisStream(file, true, 0, 0)); +		_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeVorbisStream(file, true));  		return;  	}  #endif @@ -1192,7 +1195,7 @@ void SmushPlayer::tryCmpFile(const char *filename) {  	strcpy(fname + (i - filename), ".mp3");  	if (file->open(fname)) {  		_compressedFileMode = true; -		_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeMP3Stream(file, true, 0, 0)); +		_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeMP3Stream(file, true));  		return;  	}  #endif diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index e5720a013f..62f65c22c1 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -607,24 +607,31 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle  	if (!_soundsPaused && _mixer->isReady()) {  		Audio::AudioStream *input = NULL; +		Common::MemoryReadStream *tmp = NULL;  		switch (_soundMode) {  		case kMP3Mode:  	#ifdef USE_MAD  			assert(size > 0); -			input = Audio::makeMP3Stream(_sfxFile, size); +			tmp = _sfxFile->readStream(size); +			assert(tmp); +			input = Audio::makeMP3Stream(tmp, true);  	#endif  			break;  		case kVorbisMode:  	#ifdef USE_VORBIS  			assert(size > 0); -			input = Audio::makeVorbisStream(_sfxFile, size); +			tmp = _sfxFile->readStream(size); +			assert(tmp); +			input = Audio::makeVorbisStream(tmp, true);  	#endif  			break;  		case kFlacMode:  	#ifdef USE_FLAC  			assert(size > 0); -			input = Audio::makeFlacStream(_sfxFile, size); +			tmp = _sfxFile->readStream(size); +			assert(tmp); +			input = Audio::makeFlacStream(tmp, true);  	#endif  			break;  		default: @@ -831,7 +838,7 @@ void Sound::soundKludge(int *list, int num) {  }  void Sound::talkSound(uint32 a, uint32 b, int mode, int channel) { -	if (_vm->_game.version >= 6 && ConfMan.getBool("speech_mute")) +	if (_vm->_game.version >= 5 && ConfMan.getBool("speech_mute"))  		return;  	if (mode == 1) { diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index 44e727b5d3..32fdf0e04e 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -172,6 +172,20 @@ void ScummEngine_v6::drawBlastTexts() {  				if (c == 0x0B)  					continue; +				// Some localizations may override colors +				// See credits in Chinese COMI +				if (c == '^' && (buf == _blastTextQueue[i].text + 1)) { +					int color; +					switch (*buf) { +					case 'c': +						color = buf[3] - '0' + 10 *(buf[2] - '0'); +						_charset->setColor(color); + +						buf += 4; +						c = *buf++; +					} +				} +  				if (c != 0 && c != 0xFF && c != '\n') {  					if (c & 0x80 && _useCJKMode) {  						if (_language == Common::JA_JPN && !checkSJISCode(c)) { @@ -1060,7 +1074,7 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize)  				num += (_game.version == 8) ? 4 : 2;  			}  		} else { -			if (!(chr == '@' && _game.heversion <= 71)) { +			if (!(chr == '@' && _game.heversion <= 71) || _language == Common::ZH_TWN) {  				*dst++ = chr;  			}  		}  | 
