[Scummvm-cvs-logs] CVS: scummvm/scumm sound_he.cpp,NONE,2.1 actor.cpp,1.392,1.393 intern.h,2.542,2.543 module.mk,1.57,1.58 resource.cpp,1.350,1.351 resource_v7he.cpp,1.48,1.49 script_v100he.cpp,2.181,2.182 script_v72he.cpp,2.319,2.320 script_v7he.cpp,2.173,2.174 script_v80he.cpp,2.129,2.130 script_v90he.cpp,2.290,2.291 scumm.cpp,1.670,1.671 scumm.h,1.660,1.661 sound.cpp,1.492,1.493 sound.h,1.94,1.95 vars.cpp,1.156,1.157

kirben kirben at users.sourceforge.net
Wed Jan 4 23:08:00 CET 2006


Update of /cvsroot/scummvm/scummvm/scumm
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30960/scumm

Modified Files:
	actor.cpp intern.h module.mk resource.cpp resource_v7he.cpp 
	script_v100he.cpp script_v72he.cpp script_v7he.cpp 
	script_v80he.cpp script_v90he.cpp scumm.cpp scumm.h sound.cpp 
	sound.h vars.cpp 
Added Files:
	sound_he.cpp 
Log Message:

Initial support for sound code in HE games.
Split HE sound functions into separate file.


--- NEW FILE: sound_he.cpp ---
/* 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: /cvsroot/scummvm/scummvm/scumm/sound_he.cpp,v 2.1 2006/01/05 07:06:47 kirben Exp $
 *
 */

#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

Index: actor.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/actor.cpp,v
retrieving revision 1.392
retrieving revision 1.393
diff -u -d -r1.392 -r1.393
--- actor.cpp	27 Nov 2005 23:48:14 -0000	1.392
+++ actor.cpp	5 Jan 2006 07:06:47 -0000	1.393
@@ -1146,9 +1146,14 @@
 
 	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 @@
 
 	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);
 		}
 	}
 }

Index: intern.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/intern.h,v
retrieving revision 2.542
retrieving revision 2.543
diff -u -d -r2.542 -r2.543
--- intern.h	3 Dec 2005 21:29:11 -0000	2.542
+++ intern.h	5 Jan 2006 07:06:47 -0000	2.543
@@ -1086,7 +1086,8 @@
 
 	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 @@
 
 	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 @@
 	void o100_resourceRoutines();
 	void o100_wizImageOps();
 	void o100_jumpToScript();
-	void o100_loadSBNG();
+	void o100_createSound();
 	void o100_dim2dim2Array();
 	void o100_paletteOps();
 	void o100_jumpToScriptUnk();

Index: module.mk
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/module.mk,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- module.mk	18 Oct 2005 19:17:21 -0000	1.57
+++ module.mk	5 Jan 2006 07:06:47 -0000	1.58
@@ -42,6 +42,7 @@
 	scumm/script_v6he.o \
 	scumm/scumm.o \
 	scumm/sound.o \
+	scumm/sound_he.o \
 	scumm/string.o \
 	scumm/usage_bits.o \
 	scumm/util.o \

Index: resource.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/resource.cpp,v
retrieving revision 1.350
retrieving revision 1.351
diff -u -d -r1.350 -r1.351
--- resource.cpp	19 Nov 2005 03:37:34 -0000	1.350
+++ resource.cpp	5 Jan 2006 07:06:47 -0000	1.351
@@ -1005,6 +1005,8 @@
 		return _sound->isSoundInUse(i);
 	case rtCharset:
 		return _charset->getCurID() == i;
+	case rtSpoolBuffer:
+		return _sound->isSoundRunning(10000 + i);
 	default:
 		return false;
 	}
@@ -1348,6 +1350,9 @@
 	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 @@
 		return "Image";
 	case rtTalkie:
 		return "Talkie";
+	case rtSpoolBuffer:
+		return "SpoolBuffer";
 	case rtNumTypes:
 		return "NumTypes";
 	default:

Index: resource_v7he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/resource_v7he.cpp,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -d -r1.48 -r1.49
--- resource_v7he.cpp	5 Nov 2005 10:46:28 -0000	1.48
+++ resource_v7he.cpp	5 Jan 2006 07:06:47 -0000	1.49
@@ -1797,4 +1797,119 @@
 	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

Index: script_v100he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/script_v100he.cpp,v
retrieving revision 2.181
retrieving revision 2.182
diff -u -d -r2.181 -r2.182
--- script_v100he.cpp	6 Nov 2005 06:18:19 -0000	2.181
+++ script_v100he.cpp	5 Jan 2006 07:06:47 -0000	2.182
@@ -68,7 +68,7 @@
 		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 @@
 	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 @@
 		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);

Index: script_v72he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/script_v72he.cpp,v
retrieving revision 2.319
retrieving revision 2.320
diff -u -d -r2.319 -r2.320
--- script_v72he.cpp	3 Dec 2005 00:58:30 -0000	2.319
+++ script_v72he.cpp	5 Jan 2006 07:06:47 -0000	2.320
@@ -868,9 +868,7 @@
 	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 @@
 	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_getSoundPosition() {
 	int snd = pop();
-	push(_sound->getSoundElapsedTime(snd) * 10);
-	debug(1,"o72_getSoundPosition (%d)", snd);
+	push(_sound->getSoundPos(snd));
 }
 
 void ScummEngine_v72he::o72_startScript() {

Index: script_v7he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/script_v7he.cpp,v
retrieving revision 2.173
retrieving revision 2.174
diff -u -d -r2.173 -r2.174
--- script_v7he.cpp	4 Jan 2006 05:03:46 -0000	2.173
+++ script_v7he.cpp	5 Jan 2006 07:06:47 -0000	2.174
@@ -436,11 +436,13 @@
 		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 @@
 		_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;

Index: script_v80he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/script_v80he.cpp,v
retrieving revision 2.129
retrieving revision 2.130
diff -u -d -r2.129 -r2.130
--- script_v80he.cpp	16 Nov 2005 05:08:11 -0000	2.129
+++ script_v80he.cpp	5 Jan 2006 07:06:47 -0000	2.130
@@ -129,7 +129,7 @@
 		OPCODE(o6_writeWordVar),
 		/* 44 */
 		OPCODE(o6_invalid),
-		OPCODE(o80_loadSBNG),
+		OPCODE(o80_createSound),
 		OPCODE(o80_getFileSize),
 		OPCODE(o6_wordArrayWrite),
 		/* 48 */
@@ -376,28 +376,25 @@
 	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_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() {

Index: script_v90he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/script_v90he.cpp,v
retrieving revision 2.290
retrieving revision 2.291
diff -u -d -r2.290 -r2.291
--- script_v90he.cpp	16 Nov 2005 05:08:11 -0000	2.290
+++ script_v90he.cpp	5 Jan 2006 07:06:47 -0000	2.291
@@ -127,7 +127,7 @@
 		OPCODE(o6_writeWordVar),
 		/* 44 */
 		OPCODE(o90_getObjectData),
-		OPCODE(o80_loadSBNG),
+		OPCODE(o80_createSound),
 		OPCODE(o80_getFileSize),
 		OPCODE(o6_wordArrayWrite),
 		/* 48 */

Index: scumm.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.cpp,v
retrieving revision 1.670
retrieving revision 1.671
diff -u -d -r1.670 -r1.671
--- scumm.cpp	2 Jan 2006 23:49:40 -0000	1.670
+++ scumm.cpp	5 Jan 2006 07:06:47 -0000	1.671
@@ -1210,7 +1210,7 @@
 	_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 @@
 	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_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 @@
 		_fullRedraw = true;
 	}
 
+	if (_heversion >= 80) {
+		_sound->processSoundCode();
+	}
 	runAllScripts();
 	checkExecVerbs();
 	checkAndRunSentenceScript();
@@ -2609,6 +2617,17 @@
 #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();
 }

Index: scumm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.h,v
retrieving revision 1.660
retrieving revision 1.661
diff -u -d -r1.660 -r1.661
--- scumm.h	30 Dec 2005 14:18:20 -0000	1.660
+++ scumm.h	5 Jan 2006 07:06:47 -0000	1.661
@@ -311,8 +311,9 @@
 	rtRoomImage = 18,
 	rtImage = 19,
 	rtTalkie = 20,
-	rtLast = 20,
-	rtNumTypes = 21
+	rtSpoolBuffer = 21,
+	rtLast = 21,
+	rtNumTypes = 22
 };
 
 class ResourceManager {
@@ -1074,14 +1075,19 @@
 	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 @@
 	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 @@
 	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;

Index: sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/sound.cpp,v
retrieving revision 1.492
retrieving revision 1.493
diff -u -d -r1.492 -r1.493
--- sound.cpp	4 Jan 2006 05:03:46 -0000	1.492
+++ sound.cpp	5 Jan 2006 07:06:47 -0000	1.493
@@ -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 @@
 	_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 @@
 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 @@
 		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 @@
 	_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 @@
 	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();
-
-		_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));
+	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 @@
 		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 @@
 		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 @@
 	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 @@
 
 	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 @@
 	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 @@
 		stopCDTimer();
 	}
 
+	// Clear sound channels for HE games
+	memset(_heChannel, 0, sizeof(_heChannel));
+
 	// Clear the (secondary) sound queue
 	_soundQue2Pos = 0;
 	memset(_soundQue2, 0, sizeof(_soundQue2));

Index: sound.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/sound.h,v
retrieving revision 1.94
retrieving revision 1.95
diff -u -d -r1.94 -r1.95
--- sound.h	21 Oct 2005 23:04:58 -0000	1.94
+++ sound.h	5 Jan 2006 07:06:47 -0000	1.95
@@ -95,6 +95,16 @@
 	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 @@
 	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 @@
 	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);

Index: vars.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/vars.cpp,v
retrieving revision 1.156
retrieving revision 1.157
diff -u -d -r1.156 -r1.157
--- vars.cpp	30 Dec 2005 14:18:20 -0000	1.156
+++ vars.cpp	5 Jan 2006 07:06:47 -0000	1.157
@@ -298,6 +298,7 @@
 		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 @@
 		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;





More information about the Scummvm-git-logs mailing list