diff options
| -rw-r--r-- | scumm/actor.cpp | 14 | ||||
| -rw-r--r-- | scumm/intern.h | 9 | ||||
| -rw-r--r-- | scumm/module.mk | 1 | ||||
| -rw-r--r-- | scumm/resource.cpp | 7 | ||||
| -rw-r--r-- | scumm/resource_v7he.cpp | 115 | ||||
| -rw-r--r-- | scumm/script_v100he.cpp | 18 | ||||
| -rw-r--r-- | scumm/script_v72he.cpp | 10 | ||||
| -rw-r--r-- | scumm/script_v7he.cpp | 4 | ||||
| -rw-r--r-- | scumm/script_v80he.cpp | 22 | ||||
| -rw-r--r-- | scumm/script_v90he.cpp | 2 | ||||
| -rw-r--r-- | scumm/scumm.cpp | 23 | ||||
| -rw-r--r-- | scumm/scumm.h | 20 | ||||
| -rw-r--r-- | scumm/sound.cpp | 259 | ||||
| -rw-r--r-- | scumm/sound.h | 28 | ||||
| -rw-r--r-- | scumm/sound_he.cpp | 506 | ||||
| -rw-r--r-- | scumm/vars.cpp | 2 | 
16 files changed, 766 insertions, 274 deletions
diff --git a/scumm/actor.cpp b/scumm/actor.cpp index 2ae09deb5d..a28cc6f7c0 100644 --- a/scumm/actor.cpp +++ b/scumm/actor.cpp @@ -1146,9 +1146,14 @@ void Actor::drawActorCostume(bool hitTestMode) {  	if (_vm->_heversion >= 80 && _heNoTalkAnimation == 0 && _animProgress == 0) {  		if (_vm->getTalkingActor() == _number && !_vm->_string[0].no_talk_anim) { -			// Get sound var 19 of sound 1, if sound code is active. -			// Otherwise choose random animation -			setTalkCondition(_vm->_rnd.getRandomNumberRng(1, 10)); +			int talkState = 0; + +			if (_vm->_sound->isSoundCodeUsed(1)) +				talkState = _vm->_sound->getSoundVar(1, 19); +			if (talkState == 0) +				talkState = _vm->_rnd.getRandomNumberRng(1, 10); + +			setTalkCondition(talkState);  		} else {  			setTalkCondition(1);  		} @@ -1557,8 +1562,7 @@ void Actor::setActorCostume(int c) {  	if (_vm->_heversion >= 71 && _vm->getTalkingActor() == _number) {  		if (_vm->_heversion <= 95 || (_vm->_heversion >= 98 && _vm->VAR(_vm->VAR_SKIP_RESET_TALK_ACTOR) == 0)) { -			// TODO -			// _vm->setTalkingActor(0); +			_vm->setTalkingActor(0);  		}  	}  } diff --git a/scumm/intern.h b/scumm/intern.h index ff8614f8b7..3d7a7c61ac 100644 --- a/scumm/intern.h +++ b/scumm/intern.h @@ -1086,7 +1086,8 @@ protected:  	const OpcodeEntryV80he *_opcodesV80he; -	int32 _heSBNGId; +	int32 _heSndResId; +	int _curSndId, _sndOffs1, _sndOffs2;  public:  	ScummEngine_v80he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs, uint8 md5sum[16], int substResFileNameIndex); @@ -1102,11 +1103,13 @@ protected:  	virtual void clearDrawQueues(); +	void createSound(int snd1id, int snd2id); +  	void drawLine(int x1, int y1, int x, int unk1, int unk2, int type, int id);  	void drawPixel(int x, int y, int flags);  	/* HE version 80 script opcodes */ -	void o80_loadSBNG(); +	void o80_createSound();  	void o80_getFileSize();  	void o80_stringToInt();  	void o80_getSoundVar(); @@ -1300,7 +1303,7 @@ protected:  	void o100_resourceRoutines();  	void o100_wizImageOps();  	void o100_jumpToScript(); -	void o100_loadSBNG(); +	void o100_createSound();  	void o100_dim2dim2Array();  	void o100_paletteOps();  	void o100_jumpToScriptUnk(); diff --git a/scumm/module.mk b/scumm/module.mk index 60498cb631..547a64e174 100644 --- a/scumm/module.mk +++ b/scumm/module.mk @@ -42,6 +42,7 @@ MODULE_OBJS := \  	scumm/script_v6he.o \  	scumm/scumm.o \  	scumm/sound.o \ +	scumm/sound_he.o \  	scumm/string.o \  	scumm/usage_bits.o \  	scumm/util.o \ diff --git a/scumm/resource.cpp b/scumm/resource.cpp index a2ad0988e5..63deb1b520 100644 --- a/scumm/resource.cpp +++ b/scumm/resource.cpp @@ -1005,6 +1005,8 @@ bool ScummEngine::isResourceInUse(int type, int i) const {  		return _sound->isSoundInUse(i);  	case rtCharset:  		return _charset->getCurID() == i; +	case rtSpoolBuffer: +		return _sound->isSoundRunning(10000 + i);  	default:  		return false;  	} @@ -1348,6 +1350,9 @@ void ScummEngine::allocateArrays() {  	allocResTypeData(rtImage, MKID('AWIZ'), _numImages, "images", 1);  	allocResTypeData(rtTalkie, MKID('TLKE'), _numTalkies, "talkie", 1); +	if (_heversion >= 70) { +		allocResTypeData(rtSpoolBuffer, MKID('NONE'), 9, "spool buffer", 0); +	}  }  void ScummEngine::dumpResource(const char *tag, int idx, const byte *ptr, int length) { @@ -1577,6 +1582,8 @@ const char *resTypeFromId(int id) {  		return "Image";  	case rtTalkie:  		return "Talkie"; +	case rtSpoolBuffer: +		return "SpoolBuffer";  	case rtNumTypes:  		return "NumTypes";  	default: diff --git a/scumm/resource_v7he.cpp b/scumm/resource_v7he.cpp index 9c95bbdb48..931ca67266 100644 --- a/scumm/resource_v7he.cpp +++ b/scumm/resource_v7he.cpp @@ -1797,4 +1797,119 @@ int ScummEngine_v72he::getSoundResourceSize(int id) {  	return size;  } +void ScummEngine_v80he::createSound(int snd1id, int snd2id) { +	debug(0, "createSound: snd1id %d snd2id %d", snd1id, snd2id); + +	byte *snd1Ptr, *snd2Ptr; +	byte *sbng1Ptr, *sbng2Ptr; +	byte *sdat1Ptr, *sdat2Ptr; +	byte *src, *dst, *tmp; +	int curOffs, len, offs, size; + +	if (snd2id == -1) { +		_sndOffs1 = 0; +		_sndOffs2 = 0; +		return; +	} + +	if (snd1id != _curSndId) { +		_curSndId = snd1id; +		_sndOffs1 = 0; +		_sndOffs2 = 0; +	} + +	res.lock(rtSound, snd1id); +	res.lock(rtSound, snd2id); + +	snd1Ptr = getResourceAddress(rtSound, snd1id); +	snd2Ptr = getResourceAddress(rtSound, snd2id); + +	int i; +	int chan = -1; +	for (i = 0; i < ARRAYSIZE(_sound->_heChannel); i++) { +		if (_sound->_heChannel[i].sound == snd1id) +			chan =  i; +	} + +	sbng1Ptr = heFindResource(MKID('SBNG'), snd1Ptr); +	sbng2Ptr = heFindResource(MKID('SBNG'), snd2Ptr); + +	if (sbng1Ptr != NULL && sbng2Ptr != NULL) { +		if (chan != -1 && _sound->_heChannel[chan].codeOffs > 0) { +			curOffs = _sound->_heChannel[chan].codeOffs; + +			src = snd1Ptr + curOffs; +			dst = sbng1Ptr + 8; +			size = READ_BE_UINT32(sbng1Ptr + 4); +			len = sbng1Ptr - snd1Ptr + size - curOffs; +			memcpy(dst, src, len); + + +			dst = sbng1Ptr + 8; +			while ((offs = READ_LE_UINT16(dst)) != 0) +				dst += offs; +		} else { +			dst = sbng1Ptr + 8; +		} + +		_sound->_heChannel[chan].codeOffs = sbng1Ptr - snd1Ptr + 8; + +		tmp = sbng2Ptr + 8; +		while ((offs = READ_LE_UINT16(tmp)) != 0) { +			tmp += offs; +		} + +		src = sbng2Ptr + 8; +		len = tmp - sbng2Ptr - 6; +		memcpy(dst, src, len); + +		int time; +		while (READ_LE_UINT16(dst) != 0) { +			time = READ_LE_UINT32(dst + 2); +			time += _sndOffs2; +			size = READ_LE_UINT16(dst); +			WRITE_LE_UINT32(dst + 2, time); +			dst += size; +		} +	} + +	int size1, size2; + +	sdat1Ptr = heFindResource(MKID('SDAT'), snd1Ptr); +	assert(sdat1Ptr); +	sdat2Ptr = heFindResource(MKID('SDAT'), snd2Ptr); +	assert(sdat2Ptr); + +	size1 = READ_BE_UINT32(sdat1Ptr + 4) - 8 - _sndOffs1; +	size2 = READ_BE_UINT32(sdat2Ptr + 4) - 8; + +	if (size2 < size1) { +		src = sdat2Ptr + 8; +		dst = sdat1Ptr + 8 + _sndOffs1; +		len = size2; +		 +		memcpy(dst, src, len); + +		_sndOffs1 += size2; +		_sndOffs2 += size2; +	} else { +		src = sdat2Ptr + 8; +		dst = sdat1Ptr + 8 + _sndOffs1; +		len = size1; +		 +		memcpy(dst, src, len); + +		int tmp3 = size2 - size1; +		if (tmp3 != 0) { +			// TODO: Additional copy +		} + +		_sndOffs1 += tmp3; +		_sndOffs2 += size2; +	} +	 +	res.unlock(rtSound, snd1id); +	res.unlock(rtSound, snd2id); +} +  } // End of namespace Scumm diff --git a/scumm/script_v100he.cpp b/scumm/script_v100he.cpp index 49763c31c9..7dcaec45e2 100644 --- a/scumm/script_v100he.cpp +++ b/scumm/script_v100he.cpp @@ -68,7 +68,7 @@ void ScummEngine_v100he::setupOpcodes() {  		OPCODE(o6_loadRoomWithEgo),  		OPCODE(o6_invalid),  		OPCODE(o72_setFilePath), -		OPCODE(o100_loadSBNG), +		OPCODE(o100_createSound),  		/* 18 */  		OPCODE(o6_cutscene),  		OPCODE(o6_pop), @@ -708,28 +708,25 @@ void ScummEngine_v100he::o100_jumpToScript() {  	runScript(script, (flags == 128 || flags == 129), (flags == 130 || flags == 129), args);  } -void ScummEngine_v100he::o100_loadSBNG() { -	// Loads SBNG sound resource +void ScummEngine_v100he::o100_createSound() {  	byte subOp = fetchScriptByte();  	switch (subOp) {  	case 0: -		_heSBNGId = pop(); +		_heSndResId = pop();  		break;  	case 53: -		//loadSBNG(_heSBNGId, -1); +		createSound(_heSndResId, -1);  		break;  	case 92:  		// dummy case  		break;  	case 128: -		//loadSBNG(_heSBNGId, pop(); -		pop(); +		createSound(_heSndResId, pop());  		break;  	default: -		error("o100_loadSBNG: default case %d", subOp); +		error("o100_createSound: default case %d", subOp);  	} -	debug(1,"o100_loadSBNG stub (%d)",subOp);  }  void ScummEngine_v100he::o100_dim2dimArray() { @@ -1679,7 +1676,8 @@ void ScummEngine_v100he::o100_startSound() {  		value = pop();  		var = pop();  		_heSndSoundId = pop(); -		debug(0,"o100_startSound: case 29 (snd %d, var %d, value %d)", _heSndSoundId, var, value); +		_sound->setSoundVar(_heSndSoundId, var, value); +		debug(0,"o100_startSound: case 83 (snd %d, var %d, value %d)", _heSndSoundId, var, value);  		break;  	case 92:  		debug(0, "o100_startSound (ID %d, Offset %d, Channel %d, Flags %d)", _heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags); diff --git a/scumm/script_v72he.cpp b/scumm/script_v72he.cpp index bc8fbbcfab..516827daca 100644 --- a/scumm/script_v72he.cpp +++ b/scumm/script_v72he.cpp @@ -868,9 +868,7 @@ void ScummEngine_v72he::o72_getTimer() {  	int cmd = fetchScriptByte();  	if (cmd == 10 || cmd == 50) { -		checkRange(3, 1, timer, "o72_getTimer: Timer %d out of range(%d)"); -		int diff = _system->getMillis() - _timers[timer]; -		push(diff); +		push(getHETimer(timer));  	} else {  		push(0);  	} @@ -881,8 +879,7 @@ void ScummEngine_v72he::o72_setTimer() {  	int cmd = fetchScriptByte();  	if (cmd == 158 || cmd == 61) { -		checkRange(3, 1, timer, "o72_setTimer: Timer %d out of range(%d)"); -		_timers[timer] = _system->getMillis(); +		setHETimer(timer);  	} else {  		error("TIMER command %d?", cmd);  	} @@ -890,8 +887,7 @@ void ScummEngine_v72he::o72_setTimer() {  void ScummEngine_v72he::o72_getSoundPosition() {  	int snd = pop(); -	push(_sound->getSoundElapsedTime(snd) * 10); -	debug(1,"o72_getSoundPosition (%d)", snd); +	push(_sound->getSoundPos(snd));  }  void ScummEngine_v72he::o72_startScript() { diff --git a/scumm/script_v7he.cpp b/scumm/script_v7he.cpp index b5e7ee5e66..6153ecbf1b 100644 --- a/scumm/script_v7he.cpp +++ b/scumm/script_v7he.cpp @@ -436,11 +436,13 @@ void ScummEngine_v70he::o70_startSound() {  		value = pop();  		var = pop();  		_heSndSoundId = pop(); +		_sound->setSoundVar(_heSndSoundId, var, value);  		debug(0,"o70_startSound: case 23 (snd %d, var %d, value %d)", _heSndSoundId, var, value);  		break;  	case 25:  		value = pop();  		_heSndSoundId = pop(); +		debug(0, "o70_startSound: case 25 (ID %d, Offset 0, Channel 0, Flags 8)", _heSndSoundId);  		_sound->addSoundToQueue(_heSndSoundId, 0, 0, 8);  	case 56:  		_heSndFlags |= 16; @@ -467,7 +469,7 @@ void ScummEngine_v70he::o70_startSound() {  		_heSndFlags |= 1;  		break;  	case 255: -		debug(1, "o70_startSound (ID %d, Offset %d, Channel %d, Flags %d)", _heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags); +		debug(0, "o70_startSound (ID %d, Offset %d, Channel %d, Flags %d)", _heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags);  		_sound->addSoundToQueue(_heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags);  		_heSndFlags = 0;  		break; diff --git a/scumm/script_v80he.cpp b/scumm/script_v80he.cpp index 600b22bf1e..a771f87c7f 100644 --- a/scumm/script_v80he.cpp +++ b/scumm/script_v80he.cpp @@ -129,7 +129,7 @@ void ScummEngine_v80he::setupOpcodes() {  		OPCODE(o6_writeWordVar),  		/* 44 */  		OPCODE(o6_invalid), -		OPCODE(o80_loadSBNG), +		OPCODE(o80_createSound),  		OPCODE(o80_getFileSize),  		OPCODE(o6_wordArrayWrite),  		/* 48 */ @@ -376,28 +376,25 @@ const char *ScummEngine_v80he::getOpcodeDesc(byte i) {  	return _opcodesV80he[i].desc;  } -void ScummEngine_v80he::o80_loadSBNG() { -	// Loads SBNG sound resource +void ScummEngine_v80he::o80_createSound() {  	byte subOp = fetchScriptByte();  	switch (subOp) {  	case 27: -		//loadSBNG(_heSBNGId, pop(); -		pop(); +		createSound(_heSndResId, pop());  		break;  	case 217: -		//loadSBNG(_heSBNGId, -1); +		createSound(_heSndResId, -1);  		break;  	case 232: -		_heSBNGId = pop(); +		_heSndResId = pop();  		break;  	case 255:  		// dummy case  		break;  	default: -		error("o80_loadSBNG: default case %d", subOp); +		error("o80_createSound: default case %d", subOp);  	} -	debug(1,"o80_loadSBNG stub (%d)",subOp);  }  void ScummEngine_v80he::o80_getFileSize() { @@ -432,14 +429,9 @@ void ScummEngine_v80he::o80_stringToInt() {  }  void ScummEngine_v80he::o80_getSoundVar() { -	// Checks sound variable  	int var = pop();  	int snd = pop(); -	int rnd = _rnd.getRandomNumberRng(1, 3); - -	checkRange(27, 0, var, "Illegal sound variable %d"); -	push (rnd); -	debug(1,"o80_getSoundVar stub (snd %d, var %d)", snd, var); +	push(_sound->getSoundVar(snd, var));  }  void ScummEngine_v80he::o80_localizeArrayToRoom() { diff --git a/scumm/script_v90he.cpp b/scumm/script_v90he.cpp index 5b6eddecbb..2f2a01abe0 100644 --- a/scumm/script_v90he.cpp +++ b/scumm/script_v90he.cpp @@ -127,7 +127,7 @@ void ScummEngine_v90he::setupOpcodes() {  		OPCODE(o6_writeWordVar),  		/* 44 */  		OPCODE(o90_getObjectData), -		OPCODE(o80_loadSBNG), +		OPCODE(o80_createSound),  		OPCODE(o80_getFileSize),  		OPCODE(o6_wordArrayWrite),  		/* 48 */ diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index 7aa7104364..3be3704c53 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -1210,7 +1210,7 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS  	_actorClipOverride.right = 640;  	_skipDrawObject = 0; -	memset(_timers, 0, sizeof(_timers)); +	memset(_heTimers, 0, sizeof(_heTimers));  	memset(_akosQueue, 0, sizeof(_akosQueue));  	_akosQueuePos = 0; @@ -1340,6 +1340,8 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS  	VAR_SKIP_RESET_TALK_ACTOR = 0xFF;  	VAR_MUSIC_CHANNEL = 0xFF;  	VAR_SOUND_CHANNEL = 0xFF; +	VAR_SOUNDCODE_TMR = 0xFF; +	VAR_DEFAULT_SOUND_CHANNEL = 0xFF;  	VAR_NUM_SCRIPT_CYCLES = 0xFF;  	VAR_SCRIPT_CYCLE = 0xFF; @@ -1605,7 +1607,10 @@ ScummEngine_v72he::ScummEngine_v72he(GameDetector *detector, OSystem *syst, cons  ScummEngine_v80he::ScummEngine_v80he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs, uint8 md5sum[16], int substResFileNameIndex)  	: ScummEngine_v72he(detector, syst, gs, md5sum, substResFileNameIndex) { -	_heSBNGId = 0; +	_heSndResId = 0; +	_curSndId = 0; +	_sndOffs1 = 0; +	_sndOffs2 = 0;  }  ScummEngine_v90he::ScummEngine_v90he(GameDetector *detector, OSystem *syst, const ScummGameSettings &gs, uint8 md5sum[16], int substResFileNameIndex) @@ -2489,6 +2494,9 @@ load_game:  		_fullRedraw = true;  	} +	if (_heversion >= 80) { +		_sound->processSoundCode(); +	}  	runAllScripts();  	checkExecVerbs();  	checkAndRunSentenceScript(); @@ -2609,6 +2617,17 @@ load_game:  #pragma mark --- SCUMM ---  #pragma mark - +int ScummEngine::getHETimer(int timer) { +	checkRange(15, 1, timer, "getHETimer: Timer %d out of range(%d)"); +	int time = _system->getMillis() - _heTimers[timer]; +	return time; +} + +void ScummEngine::setHETimer(int timer) { +	checkRange(15, 1, timer, "setHETimer: Timer %d out of range(%d)"); +	_heTimers[timer] = _system->getMillis(); +} +  void ScummEngine::pauseGame() {  	pauseDialog();  } diff --git a/scumm/scumm.h b/scumm/scumm.h index c73dd16ae6..091f90d828 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -311,8 +311,9 @@ enum ResTypes {  	rtRoomImage = 18,  	rtImage = 19,  	rtTalkie = 20, -	rtLast = 20, -	rtNumTypes = 21 +	rtSpoolBuffer = 21, +	rtLast = 21, +	rtNumTypes = 22  };  class ResourceManager { @@ -1074,14 +1075,19 @@ protected:  	bool testGfxOtherUsageBits(int strip, int bit);  public: -	uint8 *_hePalettes; -	byte _HEV7ActorPalette[256];  	byte _roomPalette[256];  	byte *_shadowPalette;  	bool _skipDrawObject; -	int _timers[4];  	int _voiceMode; +	// HE specific +	byte _HEV7ActorPalette[256]; +	uint8 *_hePalettes; + +	int _heTimers[16]; +	int getHETimer(int timer); +	void setHETimer(int timer); +  protected:  	int _shadowPaletteSize;  	byte _currentPalette[3 * 256]; @@ -1310,7 +1316,7 @@ public:  	byte VAR_SAVELOAD_SCRIPT;	// V6/V7 (not HE)  	byte VAR_SAVELOAD_SCRIPT2;	// V6/V7 (not HE) -	// V6/V7 specific variables (actually, they are only used in FT and Sam, it seems?) +	// V6/V7 specific variables (FT & Sam & Max specific)  	byte VAR_CHARSET_MASK;  	// V6 specific variables @@ -1328,6 +1334,8 @@ public:  	byte VAR_SKIP_RESET_TALK_ACTOR;  	byte VAR_MUSIC_CHANNEL;  	byte VAR_SOUND_CHANNEL; +	byte VAR_SOUNDCODE_TMR; +	byte VAR_DEFAULT_SOUND_CHANNEL;  	byte VAR_SCRIPT_CYCLE;  	byte VAR_NUM_SCRIPT_CYCLES; diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 9102ab7bd0..01e292bea3 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -29,6 +29,7 @@  #include "scumm/util.h"  #include "common/config-manager.h" +#include "common/system.h"  #include "common/timer.h"  #include "common/util.h" @@ -79,6 +80,7 @@ Sound::Sound(ScummEngine *parent)  	_sfxMode(0),  	_heMusicTracks(0) { +	memset(_heChannel, 0, sizeof(_heChannel));  	memset(_soundQue, 0, sizeof(_soundQue));  	memset(_soundQue2, 0, sizeof(_soundQue2));  	memset(_mouthSyncTimes, 0, sizeof(_mouthSyncTimes)); @@ -92,9 +94,16 @@ Sound::~Sound() {  void Sound::addSoundToQueue(int sound, int heOffset, int heChannel, int heFlags) {  	if (_vm->VAR_LAST_SOUND != 0xFF)  		_vm->VAR(_vm->VAR_LAST_SOUND) = sound; + +	if (heFlags & 16) { +		playHESound(sound, heOffset, heChannel, heFlags); +		return; +	} +  	// HE music resources are in separate file  	if (sound <= _vm->_numSounds)  		_vm->ensureResourceLoaded(rtSound, sound); +  	addSoundToQueue2(sound, heOffset, heChannel, heFlags);  } @@ -140,8 +149,12 @@ void Sound::processSoundQueues() {  		heOffset = _soundQue2[_soundQue2Pos].offset;  		heChannel = _soundQue2[_soundQue2Pos].channel;  		heFlags = _soundQue2[_soundQue2Pos].flags; -		if (snd) -			playSound(snd, heOffset, heChannel, heFlags); +		if (snd) { +			if (_vm->_heversion>= 60) +				playHESound(snd, heOffset, heChannel, heFlags); +			else +				playSound(snd); +		}  	}  	while (i < _soundQuePos) { @@ -168,64 +181,7 @@ void Sound::processSoundQueues() {  	_soundQuePos = 0;  } -void Sound::setOverrideFreq(int freq) { -	_overrideFreq = freq; -} - -void Sound::setupHEMusicFile() { -	int i, total_size; -	char buf[32], buf1[128]; -	Common::File musicFile; - -	sprintf(buf, "%s.he4", _vm->getGameName()); - -	if (_vm->_substResFileNameIndex > 0) { -		_vm->generateSubstResFileName(buf, buf1, sizeof(buf1)); -		strcpy(buf, buf1); -	} -	if (musicFile.open(buf) == true) { -		musicFile.seek(4, SEEK_SET); -		total_size = musicFile.readUint32BE(); -		musicFile.seek(16, SEEK_SET); -		_heMusicTracks = musicFile.readUint32LE(); -		debug(0, "Total music tracks %d", _heMusicTracks); - -		int musicStart = (_vm->_heversion >= 80) ? 56 : 20; -		musicFile.seek(musicStart, SEEK_SET); - -		_heMusic = (HEMusic *)malloc((_heMusicTracks + 1) * sizeof(HEMusic)); -		for (i = 0; i < _heMusicTracks; i++) { -			_heMusic[i].id = musicFile.readUint32LE(); -			_heMusic[i].offset = musicFile.readUint32LE(); -			_heMusic[i].size = musicFile.readUint32LE(); - -			if (_vm->_heversion >= 80) { -				musicFile.seek(+9, SEEK_CUR); -			} else { -				musicFile.seek(+13, SEEK_CUR); -			} -		} - -		musicFile.close(); -	} -} - -bool Sound::getHEMusicDetails(int id, int &musicOffs, int &musicSize) { -	int i; - -	for (i = 0; i < _heMusicTracks; i++) { -		if (_heMusic[i].id == id) { -			musicOffs = _heMusic[i].offset; -			musicSize = _heMusic[i].size; -			return 1; -		} -	} - -	return 0; -} - -void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) { -	debug(5,"playSound: soundID %d heOffset %d heChannel %d heFlags %d", soundID, heOffset, heChannel, heFlags); +void Sound::playSound(int soundID) {  	byte *mallocedPtr = NULL;  	byte *ptr;  	char *sound; @@ -233,56 +189,10 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) {  	int rate;  	byte flags = Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE; -	if (heChannel == -1) { -		heChannel = 1; -	} -	if (_vm->_heversion >= 70 && soundID > _vm->_numSounds) { -		debug(1, "playSound #%d", soundID); - -		if (soundID >= 10000) { -			// Special codes, used in pjgames -			return; -		} - -		int music_offs; -		char buf[32], buf1[128]; -		Common::File musicFile; - -		sprintf(buf, "%s.he4", _vm->getGameName()); - -		if (_vm->_substResFileNameIndex > 0) { -			_vm->generateSubstResFileName(buf, buf1, sizeof(buf1)); -			strcpy(buf, buf1); -		} -		if (musicFile.open(buf) == false) { -			warning("playSound: Can't open music file %s", buf); -			return; -		} -		if (!getHEMusicDetails(soundID, music_offs, size)) { -			debug(0, "playSound: musicID %d not found", soundID); -			return; -		} - -		musicFile.seek(music_offs, SEEK_SET); -		ptr = (byte *)malloc(size); -		musicFile.read(ptr, size); -		musicFile.close(); +	debugC(DEBUG_SOUND, "playSound #%d (room %d)", soundID, +		_vm->getResourceRoomNr(rtSound, soundID)); -		_vm->_mixer->stopID(_currentMusic); -		_currentMusic = soundID; -		if (_vm->_heversion == 70) { -			_vm->_mixer->playRaw(&_heSoundChannels[heChannel], ptr, size, 11025, flags, soundID); -			return; -		} - -		// This pointer will be freed at the end of the function -		mallocedPtr = ptr; -	} else { -		debugC(DEBUG_SOUND, "playSound #%d (room %d)", soundID, -			_vm->getResourceRoomNr(rtSound, soundID)); - -		ptr = _vm->getResourceAddress(rtSound, soundID); -	} +	ptr = _vm->getResourceAddress(rtSound, soundID);  	if (!ptr) {  		return; @@ -304,7 +214,6 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) {  		memcpy(sound, ptr, size);  		_vm->_mixer->playRaw(NULL, sound, size, rate, flags, soundID);  	} -  	// WORKAROUND bug # 1311447  	else if (READ_UINT32(ptr) == MKID(0x460e200d)) {  		// This sound resource occurs in the Macintosh version of Monkey Island. @@ -327,91 +236,6 @@ void Sound::playSound(int soundID, int heOffset, int heChannel, int heFlags) {  		memcpy(sound, ptr, size);  		_vm->_mixer->playRaw(NULL, sound, size, rate, flags, soundID);  	} - -	// Support for sound in later Backyard sports games -	else if (READ_UINT32(ptr) == MKID('RIFF')) { -		uint16 type; -		int blockAlign; -		size = READ_LE_UINT32(ptr + 4); -		Common::MemoryReadStream stream(ptr, size); - -		if (!loadWAVFromStream(stream, size, rate, flags, &type, &blockAlign)) { -			error("playSound: Not a valid WAV file"); -		} - -		if (type == 17) { -			AudioStream *voxStream = new ADPCMInputStream(&stream, size, kADPCMIma, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign); - -			sound = (char *)malloc(size * 4); -			size = voxStream->readBuffer((int16*)sound, size * 2); -			size *= 2; // 16bits. -		} else { -			// Allocate a sound buffer, copy the data into it, and play -			sound = (char *)malloc(size); -			memcpy(sound, ptr + stream.pos(), size); -		} -		_vm->_mixer->playRaw(&_heSoundChannels[heChannel], sound, size, rate, flags, soundID); -	} -	// Support for sound in Humongous Entertainment games -	else if (READ_UINT32(ptr) == MKID('DIGI') || READ_UINT32(ptr) == MKID('TALK') || READ_UINT32(ptr) == MKID('HSHD')) { -		int priority; - -		if (READ_UINT32(ptr) == MKID('HSHD')) { -			priority = READ_LE_UINT16(ptr + 10); -			rate = READ_LE_UINT16(ptr + 14); -			ptr += READ_BE_UINT32(ptr + 4); -		} else { -			priority = READ_LE_UINT16(ptr + 18); -			rate = READ_LE_UINT16(ptr + 22); -			ptr += 8 + READ_BE_UINT32(ptr + 12); -		} - -		if (READ_UINT32(ptr) == MKID('SBNG')) { -			ptr += READ_BE_UINT32(ptr + 4); -		} - -		assert(READ_UINT32(ptr) == MKID('SDAT')); -		size = READ_BE_UINT32(ptr+4) - 8; -		if (heOffset < 0 || heOffset > size) { -			// Occurs when making fireworks in puttmoon -			debug(0, "playSound: Invalid sound offset (%d) in sound %d", heOffset, soundID); -			heOffset = 0; -		} -		size -= heOffset; - -		if (_overrideFreq) { -			// Used by the piano in Fatty Bear's Birthday Surprise -			rate = _overrideFreq; -			_overrideFreq = 0; -		} - -		if (heFlags & 1) { -			// TODO -			// flags |= Audio::Mixer::FLAG_LOOP; -		} - -		// Allocate a sound buffer, copy the data into it, and play -		sound = (char *)malloc(size); -		memcpy(sound, ptr + heOffset + 8, size); -		_vm->_mixer->playRaw(&_heSoundChannels[heChannel], sound, size, rate, flags, soundID); -	} -	// Support for PCM music in 3DO versions of Humongous Entertainment games -	else if (READ_UINT32(ptr) == MKID('MRAW')) { -		ptr += 8 + READ_BE_UINT32(ptr+12); -		if (READ_UINT32(ptr) != MKID('SDAT')) -			return; - -		size = READ_BE_UINT32(ptr+4) - 8; -		rate = 22050; -		flags = Audio::Mixer::FLAG_AUTOFREE; - -		// Allocate a sound buffer, copy the data into it, and play -		sound = (char *)malloc(size); -		memcpy(sound, ptr + 8, size); -		_vm->_mixer->stopID(_currentMusic); -		_currentMusic = soundID; -		_vm->_mixer->playRaw(NULL, sound, size, rate, flags, soundID); -	}  	// Support for sampled sound effects in Monkey Island 1 and 2  	else if (READ_UINT32(ptr) == MKID('SBL ')) {  		debugC(DEBUG_SOUND, "Using SBL sound effect"); @@ -696,30 +520,6 @@ static int compareMP3OffsetTable(const void *a, const void *b) {  	return ((const MP3OffsetTable *)a)->org_offset - ((const MP3OffsetTable *)b)->org_offset;  } -void Sound::startHETalkSound(uint32 offset) { -	byte *ptr; -	int32 size; - -	if (ConfMan.getBool("speech_mute")) -		return; - -	if (!_sfxFile->isOpen()) { -		error("startHETalkSound: Speech file is not open"); -		return; -	} - -	_sfxMode |= 2; -	_vm->res.nukeResource(rtSound, 1); -	_sfxFile->seek(offset + 4, SEEK_SET); -	 size = _sfxFile->readUint32BE() - 8; -	_vm->res.createResource(rtSound, 1, size); -	ptr = _vm->getResourceAddress(rtSound, 1); -	_sfxFile->read(ptr, size); - -	int channel = (_vm->VAR_SOUND_CHANNEL != 0xFF) ? _vm->VAR(_vm->VAR_SOUND_CHANNEL) : 0; -	addSoundToQueue2(1, 0, channel, 0); -} -  void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle *handle) {  	int num = 0, i;  	int size = 0; @@ -1008,7 +808,13 @@ void Sound::stopSound(int sound) {  	if (_vm->_heversion >= 70) {  		if ( sound >= 10000) { -			_vm->_mixer->stopHandle(_heSoundChannels[sound - 10000]); +			int chan = sound - 10000; +			_vm->_mixer->stopHandle(_heSoundChannels[chan]); +			_heChannel[chan].sound = 0; +			_heChannel[chan].priority = 0; +			_heChannel[chan].sbngBlock = 0; +			_heChannel[chan].codeOffs = 0; +			memset(_heChannel[chan].soundVars, 0, sizeof(_heChannel[chan].soundVars));  		}  	} else if (_vm->_heversion >= 60) {  		if (sound == -2) { @@ -1033,6 +839,16 @@ void Sound::stopSound(int sound) {  	if (_vm->_musicEngine)  		_vm->_musicEngine->stopSound(sound); +	for (i = 0; i < ARRAYSIZE(_heChannel); i++) { +		if (_heChannel[i].sound == sound) { +			_heChannel[i].sound = 0; +			_heChannel[i].priority = 0; +			_heChannel[i].sbngBlock = 0; +			_heChannel[i].codeOffs = 0; +			memset(_heChannel[i].soundVars, 0, sizeof(_heChannel[i].soundVars)); +		} +	} +  	for (i = 0; i < ARRAYSIZE(_soundQue2); i++) {  		if (_soundQue2[i].sound == sound) {  			_soundQue2[i].sound = 0; @@ -1050,6 +866,9 @@ void Sound::stopAllSounds() {  		stopCDTimer();  	} +	// Clear sound channels for HE games +	memset(_heChannel, 0, sizeof(_heChannel)); +  	// Clear the (secondary) sound queue  	_soundQue2Pos = 0;  	memset(_soundQue2, 0, sizeof(_soundQue2)); diff --git a/scumm/sound.h b/scumm/sound.h index 7bc34cfab1..a8e3cd9715 100644 --- a/scumm/sound.h +++ b/scumm/sound.h @@ -95,6 +95,16 @@ protected:  	HEMusic *_heMusic;  	int16 _heMusicTracks; +public: // Used by createSound() +	struct { +		int sound; +		int codeOffs; +		int priority; +		int sbngBlock; +		int soundVars[27]; +		int timer; +	} _heChannel[9]; +  public:  	Audio::SoundHandle _talkChannelHandle;	// Handle of mixer channel actor is talking on  	Audio::SoundHandle _heSoundChannels[8]; @@ -109,9 +119,8 @@ public:  	void addSoundToQueue2(int sound, int heOffset = 0, int heChannel = 0, int heFlags = 0);  	void processSound();  	void processSoundQueues(); -	void setOverrideFreq(int freq); -	void playSound(int soundID, int heOffset, int heChannel, int heFlags); -	void startHETalkSound(uint32 offset); + +	void playSound(int soundID);  	void startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle *handle = NULL);  	void stopTalkSound();  	bool isMouthSyncOff(uint pos); @@ -134,8 +143,19 @@ public:  	void updateCD();  	int getCurrentCDSound() const { return _currentCDSound; } -	void setupHEMusicFile(); +	// HE specific  	bool getHEMusicDetails(int id, int &musicOffs, int &musicSize); +	int isSoundCodeUsed(int sound); +	int getSoundPos(int sound); +	int getSoundPriority(int sound); +	int getSoundVar(int sound, int var); +	void setSoundVar(int sound, int var, int val); +	void playHESound(int soundID, int heOffset, int heChannel, int heFlags); +	void processSoundCode(); +	void processSoundOpcodes(int sound, byte *codePtr, int *soundVars); +	void setOverrideFreq(int freq); +	void setupHEMusicFile(); +	void startHETalkSound(uint32 offset);  	// Used by the save/load system:  	void saveLoadWithSerializer(Serializer *ser); diff --git a/scumm/sound_he.cpp b/scumm/sound_he.cpp new file mode 100644 index 0000000000..662417ef26 --- /dev/null +++ b/scumm/sound_he.cpp @@ -0,0 +1,506 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001  Ludvig Strigeus + * Copyright (C) 2001-2005 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. + * + * $Header$ + * + */ + +#include "common/stdafx.h" +#include "scumm/actor.h" +#include "scumm/scumm.h" +#include "scumm/sound.h" +#include "scumm/util.h" + +#include "common/config-manager.h" +#include "common/system.h" +#include "common/timer.h" +#include "common/util.h" + +#include "sound/adpcm.h" +#include "sound/audiocd.h" +#include "sound/flac.h" +#include "sound/mididrv.h" +#include "sound/mixer.h" +#include "sound/mp3.h" +#include "sound/voc.h" +#include "sound/vorbis.h" +#include "sound/wave.h" + +namespace Scumm { + +int Sound::isSoundCodeUsed(int sound) { +	int chan = -1; +	for (int i = 0; i < ARRAYSIZE(_heChannel); i ++) { +		if (_heChannel[i].sound == sound) +			chan = i; +	} + +	if (chan != -1) { +		return _heChannel[chan].sbngBlock; +	} else { +		return 0; +	} +} + +int Sound::getSoundPos(int sound) { +	int chan = -1; +	for (int i = 0; i < ARRAYSIZE(_heChannel); i ++) { +		if (_heChannel[i].sound == sound) +			chan = i; +	} + +	if (chan != -1) { +		int time =  _vm->getHETimer(chan + 4) * 11025 / 1000; +		return time; +	} else { +		return 0; +	} +} + +int Sound::getSoundPriority(int sound) { +	int chan = -1; +	for (int i = 0; i < ARRAYSIZE(_heChannel); i ++) { +		if (_heChannel[i].sound == sound) +			chan = i; +	} + +	if (chan != -1) { +		return _heChannel[chan].priority; +	} else { +		return 0; +	} +} + +int Sound::getSoundVar(int sound, int var) { +	checkRange(25, 0, var, "Illegal sound variable %d"); + +	int chan = -1; +	for (int i = 0; i < ARRAYSIZE(_heChannel); i ++) { +		if (_heChannel[i].sound == sound) +			chan = i; +	} + +	if (chan != -1) { +		//debug(1, "getSoundVar: sound %d var %d result %d\n", sound, var, _heChannel[chan].soundVars[var]); +		return _heChannel[chan].soundVars[var]; +	} else { +		return 0; +	} +} + +void Sound::setSoundVar(int sound, int var, int val) { +	checkRange(25, 0, var, "Illegal sound variable %d"); + +	int chan = -1; +	for (int i = 0; i < ARRAYSIZE(_heChannel); i ++) { +		if (_heChannel[i].sound == sound) +			chan = i; +	} + +	if (chan != -1) { +		_heChannel[chan].soundVars[var] = val; +	} +} + +void Sound::setOverrideFreq(int freq) { +	_overrideFreq = freq; +} + +void Sound::setupHEMusicFile() { +	int i, total_size; +	char buf[32], buf1[128]; +	Common::File musicFile; + +	sprintf(buf, "%s.he4", _vm->getGameName()); + +	if (_vm->_substResFileNameIndex > 0) { +		_vm->generateSubstResFileName(buf, buf1, sizeof(buf1)); +		strcpy(buf, buf1); +	} +	if (musicFile.open(buf) == true) { +		musicFile.seek(4, SEEK_SET); +		total_size = musicFile.readUint32BE(); +		musicFile.seek(16, SEEK_SET); +		_heMusicTracks = musicFile.readUint32LE(); +		debug(0, "Total music tracks %d", _heMusicTracks); + +		int musicStart = (_vm->_heversion >= 80) ? 56 : 20; +		musicFile.seek(musicStart, SEEK_SET); + +		_heMusic = (HEMusic *)malloc((_heMusicTracks + 1) * sizeof(HEMusic)); +		for (i = 0; i < _heMusicTracks; i++) { +			_heMusic[i].id = musicFile.readUint32LE(); +			_heMusic[i].offset = musicFile.readUint32LE(); +			_heMusic[i].size = musicFile.readUint32LE(); + +			if (_vm->_heversion >= 80) { +				musicFile.seek(+9, SEEK_CUR); +			} else { +				musicFile.seek(+13, SEEK_CUR); +			} +		} + +		musicFile.close(); +	} +} + +bool Sound::getHEMusicDetails(int id, int &musicOffs, int &musicSize) { +	int i; + +	for (i = 0; i < _heMusicTracks; i++) { +		if (_heMusic[i].id == id) { +			musicOffs = _heMusic[i].offset; +			musicSize = _heMusic[i].size; +			return 1; +		} +	} + +	return 0; +} + +void Sound::processSoundCode() { +	byte *codePtr; +	int chan, tmr, size, time; + +	for (chan = 0; chan < ARRAYSIZE(_heChannel); chan++) { +		if (_heChannel[chan].sound == 0) { +			continue; +		} + +		if (_heChannel[chan].codeOffs == -1) { +			continue; +		} + +		tmr = _vm->getHETimer(chan + 4) * 11025 / 1000; +		tmr += _vm->VAR(_vm->VAR_SOUNDCODE_TMR); +		if (tmr < 0) +			tmr = 0; + +		if (_heChannel[chan].sound > _vm->_numSounds) { +			codePtr = _vm->getResourceAddress(rtSpoolBuffer, chan); +		} else { +			codePtr = _vm->getResourceAddress(rtSound, _heChannel[chan].sound); +		} +		assert(codePtr); +		codePtr += _heChannel[chan].codeOffs; + +		while(1) { +			size = READ_LE_UINT16(codePtr); +			time = READ_LE_UINT32(codePtr + 2); + +			if (size == 0) { +				_heChannel[chan].codeOffs = -1; +				break; +			} + +			debug(1, "Channel %d Timer %d Time %d", chan,tmr, time); +			if (time >= tmr) +				break; + +			processSoundOpcodes(_heChannel[chan].sound, codePtr + 6, _heChannel[chan].soundVars); + +			codePtr += size; +			_heChannel[chan].codeOffs += size; +		} +	} +} + +void Sound::processSoundOpcodes(int sound, byte *codePtr, int *soundVars) { +	int edi, opcode, var, val; + +	while(READ_LE_UINT16(codePtr) != 0) { +		codePtr += 2; +		opcode = READ_LE_UINT16(codePtr); codePtr += 2; +		opcode &= ~0xF000; +		opcode /= 16; +		edi = opcode; +		opcode &= ~3; +		edi &= 3; + +		debug(1, "processSoundOpcodes: sound %d opcode %d", sound, opcode); +		switch (opcode) { +		case 0: // Continue +			break; +		case 16: // Set talk state +			val = READ_LE_UINT16(codePtr); codePtr += 2; +			setSoundVar(sound, 19, val); +			break; +		case 32: // Set var +			var = READ_LE_UINT16(codePtr); codePtr += 2; +			val = READ_LE_UINT16(codePtr); codePtr += 2; +			if (edi == 2) { +				val = getSoundVar(sound, val); +			} +			setSoundVar(sound, var, val); +			break; +		case 48: // Add +			var = READ_LE_UINT16(codePtr); codePtr += 2;; +			val = READ_LE_UINT16(codePtr); codePtr += 2;; + +			val = getSoundVar(sound, var) + val; +			setSoundVar(sound, var, val); +			break; +		case 56: // Subtract +			var = READ_LE_UINT16(codePtr); codePtr += 2;; +			val = READ_LE_UINT16(codePtr); codePtr += 2;; + +			val = getSoundVar(sound, var) - val; +			setSoundVar(sound, var, val); +			break; +		case 64: // Multiple +			var = READ_LE_UINT16(codePtr); codePtr += 2;; +			val = READ_LE_UINT16(codePtr); codePtr += 2; +			if (edi == 2) { +				val = getSoundVar(sound, val); +			} + +			val = getSoundVar(sound, var) * val; +			setSoundVar(sound, var, val); +			break; +		case 80: // Divide +			var = READ_LE_UINT16(codePtr); codePtr += 2;; +			val = READ_LE_UINT16(codePtr); codePtr += 2; +			if (edi == 2) { +				val = getSoundVar(sound, val); +			} + +			val = getSoundVar(sound, var) / val; +			setSoundVar(sound, var, val); +			break; +		case 96: // Increment +			var = READ_LE_UINT16(codePtr); codePtr += 2; +			val = getSoundVar(sound, var) + 1; +			setSoundVar(sound, var, val); +			break; +		case 104: // Decrement +			var = READ_LE_UINT16(codePtr); codePtr += 2; +			val = getSoundVar(sound, var) - 1; +			setSoundVar(sound, var, val); +			break; +		default: +			error("Illegal sound %d opcode %d", sound, opcode); +		} +	} +} + +void Sound::playHESound(int soundID, int heOffset, int heChannel, int heFlags) { +	debug(0,"playHESound: soundID %d heOffset %d heChannel %d heFlags %d", soundID, heOffset, heChannel, heFlags); +	byte *mallocedPtr = NULL; +	byte *ptr, *spoolPtr; +	char *sound; +	int size = -1; +	int rate; +	byte flags = Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE; + +	if (heChannel == -1) { +		if (_vm->_heversion >= 95 && _vm->VAR(_vm->VAR_DEFAULT_SOUND_CHANNEL) != 0) +			heChannel = _vm->VAR(_vm->VAR_DEFAULT_SOUND_CHANNEL); +		else +			heChannel = 1; +	} + +	if (soundID > _vm->_numSounds) { +		if (soundID >= 10000) { +			// Special codes, used in pjgames +			return; +		} + +		int music_offs; +		char buf[32], buf1[128]; +		Common::File musicFile; + +		sprintf(buf, "%s.he4", _vm->getGameName()); + +		if (_vm->_substResFileNameIndex > 0) { +			_vm->generateSubstResFileName(buf, buf1, sizeof(buf1)); +			strcpy(buf, buf1); +		} +		if (musicFile.open(buf) == false) { +			warning("playSound: Can't open music file %s", buf); +			return; +		} +		if (!getHEMusicDetails(soundID, music_offs, size)) { +			debug(0, "playSound: musicID %d not found", soundID); +			return; +		} + +		musicFile.seek(music_offs, SEEK_SET); + +		if (_vm->_heversion == 70) { +			spoolPtr = (byte *)malloc(size); +			musicFile.read(spoolPtr, size); +		} else { +			spoolPtr = _vm->res.createResource(rtSpoolBuffer, heChannel, size); +			assert(spoolPtr); +			musicFile.read(spoolPtr, size); +		} +		musicFile.close(); + +		_vm->_mixer->stopID(_currentMusic); +		_currentMusic = soundID; +		if (_vm->_heversion == 70) { +			_vm->_mixer->playRaw(&_heSoundChannels[heChannel], spoolPtr, size, 11025, flags, soundID); +			return; +		} + +		// This pointer will be freed at the end of the function +		mallocedPtr = spoolPtr; +	} + +	if (soundID > _vm->_numSounds) { +		ptr = _vm->getResourceAddress(rtSpoolBuffer, heChannel); +	} else { +		ptr = _vm->getResourceAddress(rtSound, soundID); +	} + +	if (!ptr) { +		return; +	} + +	// Support for sound in later Backyard sports games +	if (READ_UINT32(ptr) == MKID('RIFF')) { +		uint16 type; +		int blockAlign; +		size = READ_LE_UINT32(ptr + 4); +		Common::MemoryReadStream stream(ptr, size); + +		if (!loadWAVFromStream(stream, size, rate, flags, &type, &blockAlign)) { +			error("playSound: Not a valid WAV file"); +		} + +		if (type == 17) { +			AudioStream *voxStream = new ADPCMInputStream(&stream, size, kADPCMIma, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign); + +			sound = (char *)malloc(size * 4); +			size = voxStream->readBuffer((int16*)sound, size * 2); +			size *= 2; // 16bits. +		} else { +			// Allocate a sound buffer, copy the data into it, and play +			sound = (char *)malloc(size); +			memcpy(sound, ptr + stream.pos(), size); +		} +		_vm->_mixer->playRaw(&_heSoundChannels[heChannel], sound, size, rate, flags, soundID); +	} +	// Support for sound in Humongous Entertainment games +	else if (READ_UINT32(ptr) == MKID('DIGI') || READ_UINT32(ptr) == MKID('TALK') || READ_UINT32(ptr) == MKID('HSHD')) { +		byte *sndPtr = ptr; +		int priority; + +		if (READ_UINT32(ptr) == MKID('HSHD')) { +			priority = READ_LE_UINT16(ptr + 10); +			rate = READ_LE_UINT16(ptr + 14); +			ptr += READ_BE_UINT32(ptr + 4); +		} else { +			priority = READ_LE_UINT16(ptr + 18); +			rate = READ_LE_UINT16(ptr + 22); +			ptr += 8 + READ_BE_UINT32(ptr + 12); +		} + +		//if (_vm->_mixer->isSoundHandleActive(_heSoundChannels[heChannel]) && _heChannel[heChannel].priority > priority) +		//	return; + +		int codeOffs = -1; +		if (READ_UINT32(ptr) == MKID('SBNG')) { +			codeOffs = ptr - sndPtr + 8; +			ptr += READ_BE_UINT32(ptr + 4); +		} + +		assert(READ_UINT32(ptr) == MKID('SDAT')); +		size = READ_BE_UINT32(ptr+4) - 8; +		if (heOffset < 0 || heOffset > size) { +			// Occurs when making fireworks in puttmoon +			debug(0, "playSound: Invalid sound offset (offset %d, size %d) in sound %d", heOffset, size, soundID); +			heOffset = 0; +		} +		size -= heOffset; + +		if (_overrideFreq) { +			// Used by the piano in Fatty Bear's Birthday Surprise +			rate = _overrideFreq; +			_overrideFreq = 0; +		} + +		if (heFlags & 1) { +			flags |= Audio::Mixer::FLAG_LOOP; +		} + +		// Allocate a sound buffer, copy the data into it, and play +		sound = (char *)malloc(size); +		memcpy(sound, ptr + heOffset + 8, size); +		//_vm->_mixer->stopHandle(_heSoundChannels[heChannel]); +		_vm->_mixer->playRaw(&_heSoundChannels[heChannel], sound, size, rate, flags, soundID); + +		_vm->setHETimer(heChannel + 4); +		_heChannel[heChannel].sound = soundID; +		_heChannel[heChannel].priority = priority; +		_heChannel[heChannel].timer = 0; +		_heChannel[heChannel].sbngBlock = (codeOffs != 0) ? 1 : 0; +		_heChannel[heChannel].codeOffs = codeOffs; +		memset(_heChannel[heChannel].soundVars, 0, sizeof(_heChannel[heChannel].soundVars)); +	} +	// Support for PCM music in 3DO versions of Humongous Entertainment games +	else if (READ_UINT32(ptr) == MKID('MRAW')) { +		ptr += 8 + READ_BE_UINT32(ptr+12); +		if (READ_UINT32(ptr) != MKID('SDAT')) +			return; + +		size = READ_BE_UINT32(ptr+4) - 8; +		rate = 22050; +		flags = Audio::Mixer::FLAG_AUTOFREE; + +		// Allocate a sound buffer, copy the data into it, and play +		sound = (char *)malloc(size); +		memcpy(sound, ptr + 8, size); +		_vm->_mixer->stopID(_currentMusic); +		_currentMusic = soundID; +		_vm->_mixer->playRaw(NULL, sound, size, rate, flags, soundID); +	} +	else { +		//if (_vm->_musicEngine) { +		//	_vm->_musicEngine->startSound(soundID); +		//} +	} + +	free(mallocedPtr); +} + +void Sound::startHETalkSound(uint32 offset) { +	byte *ptr; +	int32 size; + +	if (ConfMan.getBool("speech_mute")) +		return; + +	if (!_sfxFile->isOpen()) { +		error("startHETalkSound: Speech file is not open"); +		return; +	} + +	_sfxMode |= 2; +	_vm->res.nukeResource(rtSound, 1); +	_sfxFile->seek(offset + 4, SEEK_SET); +	 size = _sfxFile->readUint32BE() - 8; +	_vm->res.createResource(rtSound, 1, size); +	ptr = _vm->getResourceAddress(rtSound, 1); +	_sfxFile->read(ptr, size); + +	int channel = (_vm->VAR_SOUND_CHANNEL != 0xFF) ? _vm->VAR(_vm->VAR_SOUND_CHANNEL) : 0; +	addSoundToQueue2(1, 0, channel, 0); +} + +} // End of namespace Scumm diff --git a/scumm/vars.cpp b/scumm/vars.cpp index d4e9c574e8..82a97a673b 100644 --- a/scumm/vars.cpp +++ b/scumm/vars.cpp @@ -298,6 +298,7 @@ void ScummEngine_v72he::setupScummVars() {  		VAR_PLATFORM = 78;  		// 1 is PC, 2 is Macintosh   		VAR_WINDOWS_VERSION = 79; 	// 31 is Windows 3.1, 40 is Windows 95+  		VAR_CURRENT_CHARSET = 80; +		VAR_SOUNDCODE_TMR = 84;  		VAR_KEY_STATE = 86;  		VAR_NUM_SOUND_CHANNELS = 88;  	if (_heversion >= 90) { @@ -310,6 +311,7 @@ void ScummEngine_v72he::setupScummVars() {  		VAR_U32_VERSION = 107;  		VAR_U32_ARRAY_UNK = 116;  		VAR_WIZ_TCOLOR = 117; +		VAR_DEFAULT_SOUND_CHANNEL = 120;  	}  	if (_heversion >= 98) {  		VAR_SKIP_RESET_TALK_ACTOR = 125;  | 
