[Scummvm-cvs-logs] SF.net SVN: scummvm:[42980] scummvm/branches/gsoc2009-mods

nolange at users.sourceforge.net nolange at users.sourceforge.net
Sun Aug 2 01:02:45 CEST 2009


Revision: 42980
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42980&view=rev
Author:   nolange
Date:     2009-08-01 23:02:45 +0000 (Sat, 01 Aug 2009)

Log Message:
-----------
engines/scumm/scumm.cpp: terminate method is pretty redundant - removed
tfmx, player_v4a: refactored Tfmx to allow sharing of resources between 2 instances. Needed changes in player_v4a aswell

Modified Paths:
--------------
    scummvm/branches/gsoc2009-mods/engines/scumm/music.h
    scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.cpp
    scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.h
    scummvm/branches/gsoc2009-mods/engines/scumm/scumm.cpp
    scummvm/branches/gsoc2009-mods/sound/mods/tfmx.cpp
    scummvm/branches/gsoc2009-mods/sound/mods/tfmx.h

Modified: scummvm/branches/gsoc2009-mods/engines/scumm/music.h
===================================================================
--- scummvm/branches/gsoc2009-mods/engines/scumm/music.h	2009-08-01 21:17:38 UTC (rev 42979)
+++ scummvm/branches/gsoc2009-mods/engines/scumm/music.h	2009-08-01 23:02:45 UTC (rev 42980)
@@ -81,12 +81,6 @@
 	 * @return the music timer
 	 */
 	virtual int  getMusicTimer() const { return 0; }
-
-	/**
-	 * Terminate the music engine. Called just before the music engine
-	 * is deleted.
-	 */
-	virtual void terminate() {}
 };
 
 } // End of namespace Scumm

Modified: scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.cpp
===================================================================
--- scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.cpp	2009-08-01 21:17:38 UTC (rev 42979)
+++ scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.cpp	2009-08-01 23:02:45 UTC (rev 42980)
@@ -32,10 +32,22 @@
 
 namespace Scumm {
 
-Player_V4A::Player_V4A(ScummEngine *scumm, Audio::Mixer *mixer)
-	: _vm(scumm), _mixer(mixer), _musicId(), _sfxSlots(), _initState(0), _tfmxMusic(0), _tfmxSfx(0), _musicHandle(), _sfxHandle(), _signal(0) {
+Player_V4A::Player_V4A(ScummEngine *scumm, Audio::Mixer *mixer) :
+	_vm(scumm),
+	_mixer(mixer),
+	_tfmxMusic(_mixer->getOutputRate(), true),
+	_tfmxSfx(_mixer->getOutputRate(), true),
+	_musicHandle(),
+	_sfxHandle(),
+	_musicId(),
+	_sfxSlots(),
+	_initState(0),
+	_signal(0) {
+
 	assert(scumm);
 	assert(mixer);
+	assert(_vm->_game.id == GID_MONKEY_VGA);
+	_tfmxMusic.setSignalPtr(&_signal, 1);
 }
 
 bool Player_V4A::init() {
@@ -44,33 +56,19 @@
 	
 	Common::File fileMdat;
 	Common::File fileSample;
-	bool mdatExists = fileMdat.open("music.dat");
-	bool sampleExists = fileSample.open("sample.dat");
 
-	if (mdatExists && sampleExists) {
-		Audio::Tfmx *play =  new Audio::Tfmx(_mixer->getOutputRate(), true);
-		if (play->load(fileMdat, fileSample)) {
-			play->setSignalPtr(&_signal, 1);
-			_tfmxMusic = play;
-		} else
-			delete play;
-
-		play = new Audio::Tfmx(_mixer->getOutputRate(), true);
-		fileMdat.seek(0);
-		fileSample.seek(0);
-		if (play->load(fileMdat, fileSample)) {
-			_tfmxSfx = play;
-		} else
-			delete play;
+	if (fileMdat.open("music.dat") && fileSample.open("sample.dat")) {
+		if (_tfmxMusic.load(fileMdat, fileSample)) {
+			_tfmxSfx.setModuleData(_tfmxMusic);
+			return true;
+		}
 	}
-	return _tfmxMusic != 0;
+	return false;
 }
 
 Player_V4A::~Player_V4A() {
 	_mixer->stopHandle(_musicHandle);
 	_mixer->stopHandle(_sfxHandle);
-	delete _tfmxMusic;
-	delete _tfmxSfx;
 }
 
 void Player_V4A::setMusicVolume(int vol) {
@@ -79,13 +77,11 @@
 
 void Player_V4A::stopAllSounds() {
 	debug(5, "player_v4a: stopAllSounds");
-	if (_tfmxMusic) {
-		_tfmxMusic->stopSong();
-		_signal = 0;		
-	}
+	_tfmxMusic.stopSong();
+	_signal = 0;		
 	_musicId = 0;
-	if (_tfmxSfx)
-		_tfmxSfx->stopSong();
+
+	_tfmxSfx.stopSong();
 	clearSfxSlots();
 }
 
@@ -95,13 +91,13 @@
 		return;
 	if (nr == _musicId) {
 		_musicId = 0;
-		_tfmxMusic->stopSong();
+		_tfmxMusic.stopSong();
 		_signal = 0;
 	} else {
 		const int chan = getSfxChan(nr);
 		if (chan != -1) {
 			setSfxSlot(chan, 0);
-			_tfmxSfx->stopMacroEffect(chan);
+			_tfmxSfx.stopMacroEffect(chan);
 		}
 	}
 }
@@ -139,10 +135,10 @@
 		debug(3, "player_v4a: play %d: custom %i - %02X", nr, index, type);
 
 		// start an empty Song so timing is setup
-		if (_tfmxSfx->getSongIndex() < 0)
-			_tfmxSfx->doSong(0x18);
+		if (_tfmxSfx.getSongIndex() < 0)
+			_tfmxSfx.doSong(0x18);
 
-		const int chan = _tfmxSfx->doSfx((uint16)index);
+		const int chan = _tfmxSfx.doSfx((uint16)index);
 		if (chan >= 0 && chan < ARRAYSIZE(_sfxSlots))
 			setSfxSlot(chan, nr, type);
 		else
@@ -150,20 +146,20 @@
 
 		// the Tfmx-player newer "ends" the output by itself, so this should be threadsafe
 		if (!_mixer->isSoundHandleActive(_sfxHandle))
-			_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _tfmxSfx, -1, Audio::Mixer::kMaxChannelVolume, 0, false);
+			_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, &_tfmxSfx, -1, Audio::Mixer::kMaxChannelVolume, 0, false);
 
 	} else {	// Song
 		debug(3, "player_v4a: play %d: song %i - %02X", nr, index, type);
 		if (ptr[6] != 0x7F)
 			warning("player_v4a: Song has wrong type");
 
-		_tfmxMusic->doSong(index);
+		_tfmxMusic.doSong(index);
 		_signal = 2;
 		_musicId = nr;
 
 		// the Tfmx-player newer "ends" the output by itself, so this should be threadsafe 
 		if (!_mixer->isSoundHandleActive(_musicHandle))
-			_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, _tfmxMusic, -1, Audio::Mixer::kMaxChannelVolume, 0, false);
+			_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, &_tfmxMusic, -1, Audio::Mixer::kMaxChannelVolume, 0, false);
 	}
 }
 

Modified: scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.h
===================================================================
--- scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.h	2009-08-01 21:17:38 UTC (rev 42979)
+++ scummvm/branches/gsoc2009-mods/engines/scumm/player_v4a.h	2009-08-01 23:02:45 UTC (rev 42980)
@@ -56,8 +56,8 @@
 	ScummEngine *const _vm;
 	Audio::Mixer *const _mixer;
 
-	Audio::Tfmx *_tfmxMusic;
-	Audio::Tfmx *_tfmxSfx;
+	Audio::Tfmx _tfmxMusic;
+	Audio::Tfmx _tfmxSfx;
 	Audio::SoundHandle _musicHandle;
 	Audio::SoundHandle _sfxHandle;
 

Modified: scummvm/branches/gsoc2009-mods/engines/scumm/scumm.cpp
===================================================================
--- scummvm/branches/gsoc2009-mods/engines/scumm/scumm.cpp	2009-08-01 21:17:38 UTC (rev 42979)
+++ scummvm/branches/gsoc2009-mods/engines/scumm/scumm.cpp	2009-08-01 23:02:45 UTC (rev 42980)
@@ -546,10 +546,7 @@
 ScummEngine::~ScummEngine() {
 	Common::clearAllDebugChannels();
 
-	if (_musicEngine) {
-		_musicEngine->terminate();
-		delete _musicEngine;
-	}
+	delete _musicEngine;
 
 	_mixer->stopAll();
 

Modified: scummvm/branches/gsoc2009-mods/sound/mods/tfmx.cpp
===================================================================
--- scummvm/branches/gsoc2009-mods/sound/mods/tfmx.cpp	2009-08-01 21:17:38 UTC (rev 42979)
+++ scummvm/branches/gsoc2009-mods/sound/mods/tfmx.cpp	2009-08-01 23:02:45 UTC (rev 42980)
@@ -48,7 +48,7 @@
 	 214,  202,  191,  180 };
 
 Tfmx::Tfmx(int rate, bool stereo)
-: Paula(stereo, rate), _resource(), _playerCtx() {
+: Paula(stereo, rate), _resource(), _resourceSample(), _playerCtx() {
 	_playerCtx.stopWithLastPattern = false;
 
 	for (int i = 0; i < kNumVoices; ++i) 
@@ -65,6 +65,7 @@
 }
 
 Tfmx::~Tfmx() {
+	freeResourceData();
 }
 
 void Tfmx::interrupt() {
@@ -131,7 +132,7 @@
 	// addBegin
 	if (channel.addBeginLength) {
 		channel.sampleStart += channel.addBeginDelta;
-		Paula::setChannelSampleStart(channel.paulaChannel, _resource.getSamplePtr(channel.sampleStart));
+		Paula::setChannelSampleStart(channel.paulaChannel, getSamplePtr(channel.sampleStart));
 		if (!(--channel.addBeginCount)) {
 			channel.addBeginCount = channel.addBeginLength;
 			channel.addBeginDelta = -channel.addBeginDelta;
@@ -215,7 +216,7 @@
 void Tfmx::macroRun(ChannelContext &channel) {
 	bool deferWait = channel.deferWait;
 	for (;;) {
-		const byte *const macroPtr = (byte *)(_resource.getMacroPtr(channel.macroOffset) + channel.macroStep);
+		const byte *const macroPtr = (byte *)(getMacroPtr(channel.macroOffset) + channel.macroStep);
 		++channel.macroStep;
 
 		switch (macroPtr[0]) {
@@ -265,7 +266,7 @@
 		case 0x02:	// SetBeginn. Parameters: SampleOffset(L)
 			channel.addBeginLength = 0;
 			channel.sampleStart = READ_BE_UINT32(macroPtr) & 0xFFFFFF;
-			Paula::setChannelSampleStart(channel.paulaChannel, _resource.getSamplePtr(channel.sampleStart));
+			Paula::setChannelSampleStart(channel.paulaChannel, getSamplePtr(channel.sampleStart));
 			continue;
 
 		case 0x03:	// SetLength. Parameters: SampleLength(W)
@@ -293,7 +294,7 @@
 
 		case 0x06:	// Jump. Parameters: MacroIndex, MacroStep(W)
 			channel.macroIndex = macroPtr[1] & (kMaxMacroOffsets - 1);
-			channel.macroOffset = _macroOffset[macroPtr[1] & (kMaxMacroOffsets - 1)];
+			channel.macroOffset = _resource->macroOffset[macroPtr[1] & (kMaxMacroOffsets - 1)];
 			channel.macroStep = READ_BE_UINT16(&macroPtr[2]);
 			channel.macroLoopCount = 0xFF;
 			continue;
@@ -357,7 +358,7 @@
 			channel.addBeginLength = channel.addBeginCount = macroPtr[1];
 			channel.addBeginDelta = (int16)READ_BE_UINT16(&macroPtr[2]);
 			channel.sampleStart += channel.addBeginDelta;
-			Paula::setChannelSampleStart(channel.paulaChannel, _resource.getSamplePtr(channel.sampleStart));
+			Paula::setChannelSampleStart(channel.paulaChannel, getSamplePtr(channel.sampleStart));
 			continue;
 
 		case 0x12:	// AddLen. Parameters: added Length(W)
@@ -379,7 +380,7 @@
 			channel.macroReturnOffset = channel.macroOffset;
 			channel.macroReturnStep = channel.macroStep;
 
-			channel.macroOffset = _macroOffset[macroPtr[1] & (kMaxMacroOffsets - 1)];
+			channel.macroOffset = _resource->macroOffset[macroPtr[1] & (kMaxMacroOffsets - 1)];
 			channel.macroStep = READ_BE_UINT16(&macroPtr[2]);
 			// TODO: MI does some weird stuff there. Figure out which varioables need to be set
 			continue;
@@ -404,7 +405,7 @@
 				warning("Tfmx: Problematic value for sampleloop: %06X", (macroPtr[1] << 16) | temp);
 			channel.sampleStart += temp & 0xFFFE;
 			channel.sampleLen -= (temp / 2) /* & 0x7FFF */;
-			Paula::setChannelSampleStart(channel.paulaChannel, _resource.getSamplePtr(channel.sampleStart));
+			Paula::setChannelSampleStart(channel.paulaChannel, getSamplePtr(channel.sampleStart));
 			Paula::setChannelSampleLen(channel.paulaChannel, channel.sampleLen);
 			continue;
 		}
@@ -412,7 +413,7 @@
 			channel.addBeginLength = 0;
 			channel.sampleStart = 0;
 			channel.sampleLen = 1;
-			Paula::setChannelSampleStart(channel.paulaChannel, _resource.getSamplePtr(0));
+			Paula::setChannelSampleStart(channel.paulaChannel, getSamplePtr(0));
 			Paula::setChannelSampleLen(channel.paulaChannel, 1);
 			continue;
 
@@ -501,7 +502,7 @@
 
 bool Tfmx::patternRun(PatternContext &pattern) {
 	for (;;) {
-		const byte *const patternPtr = (byte *)(_resource.getPatternPtr(pattern.offset) + pattern.step);
+		const byte *const patternPtr = (byte *)(getPatternPtr(pattern.offset) + pattern.step);
 		++pattern.step;
 		const byte pattCmd = patternPtr[0];
 
@@ -538,7 +539,7 @@
 				continue;
 
 			case 2: 	// Jump. Parameters: PatternIndex, PatternStep(W)
-				pattern.offset = _patternOffset[patternPtr[1]];
+				pattern.offset = _resource->patternOffset[patternPtr[1] & (kMaxPatternOffsets - 1)];
 				pattern.step = READ_BE_UINT16(&patternPtr[2]);
 				continue;
 
@@ -570,7 +571,7 @@
 				pattern.savedOffset = pattern.offset;
 				pattern.savedStep = pattern.step;
 
-				pattern.offset = _patternOffset[patternPtr[1] & (kMaxPatternOffsets - 1)];
+				pattern.offset = _resource->patternOffset[patternPtr[1] & (kMaxPatternOffsets - 1)];
 				pattern.step = READ_BE_UINT16(&patternPtr[2]);
 				continue;
 
@@ -588,7 +589,7 @@
 				PatternContext &target = _patternCtx[patternPtr[2] & (kNumChannels - 1)];
 
 				target.command = patternPtr[1];
-				target.offset = _patternOffset[patternPtr[1] & (kMaxPatternOffsets - 1)];
+				target.offset = _resource->patternOffset[patternPtr[1] & (kMaxPatternOffsets - 1)];
 				target.expose = patternPtr[3];
 				target.step = 0;
 				target.wait = 0;
@@ -623,7 +624,7 @@
 			++_trackCtx.posInd;
 	}
 	for (;;) {
-		const uint16 *const trackData = _resource.getTrackPtr(_trackCtx.posInd);
+		const uint16 *const trackData = getTrackPtr(_trackCtx.posInd);
 
 		if (trackData[0] != FROM_BE_16(0xEFFE)) {
 			// 8 commands for Patterns
@@ -636,7 +637,7 @@
 					_patternCtx[i].step = 0;
 					_patternCtx[i].wait = 0;
 					_patternCtx[i].loopCount = 0xFF;
-					_patternCtx[i].offset = _patternOffset[patNum];
+					_patternCtx[i].offset = _resource->patternOffset[patNum];
 				}
 				_patternCtx[i].command = (uint8)patNum;
 				_patternCtx[i].expose = patCmd & 0xFF;
@@ -703,7 +704,7 @@
 		channel.prevNote = channel.note;
 		channel.note = note;
 		channel.macroIndex = param1 & (kMaxMacroOffsets - 1);
-		channel.macroOffset = _macroOffset[param1 & (kMaxMacroOffsets - 1)];
+		channel.macroOffset = _resource->macroOffset[param1 & (kMaxMacroOffsets - 1)];
 		channel.relVol = (param2 >> 4) & 0xF;
 		channel.fineTune = (int8)param3;
 
@@ -736,128 +737,182 @@
 	}
 }
 
-bool Tfmx::load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData) {
-	bool res;
+void Tfmx::setModuleData(Tfmx &otherPlayer) {
+	setModuleData(otherPlayer._resource, otherPlayer._resourceSample.sampleData, otherPlayer._resourceSample.sampleLen, false);
+}
 
-	assert(0 == _resource.mdatData);
-	assert(0 == _resource.sampleData);
+bool Tfmx::load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData, bool autoDelete) {
+	MdatResource *mdat = new MdatResource();
+	if (loadMdatFile(*mdat, musicData)) {
+		int8 *sampleDat = 0;
+		uint32 sampleLen = 0;
+		if (loadSampleFile(sampleDat, sampleLen, sampleData)) {
+			setModuleData(mdat, sampleDat, sampleLen, autoDelete);
+			return true;
+		}
+	}
+	delete[] mdat->mdatAlloc;
+	delete mdat;
+	return false;
+}
 
-	// TODO: Sanity checks if we have a valid TFMX-Module
-	// TODO: check for Stream-Errors (other than using asserts)
+void Tfmx::freeResourceData() {
+	if (_deleteResource) {
+		if (_resource) {
+			delete[] _resource->mdatAlloc;
+			delete _resource;
+		}
+		delete[] _resourceSample.sampleData;
+	}
+	_resource = 0;
+	_resourceSample.sampleData = 0;
+	_resourceSample.sampleLen = 0;
+}
 
-	// 0x0000: 10 Bytes Header "TFMX-SONG "
-	// 0x000A: int16 ?
-	// 0x000C: int32 ?
-	musicData.read(_resource.header, 10);
-	_resource.headerFlags = musicData.readUint16BE();
-	_resource.headerUnknown = musicData.readUint32BE();
+void Tfmx::setModuleData(const MdatResource *resource, const int8 *sampleData, uint32 sampleLen, bool autoDelete) {
+	Common::StackLock lock(_mutex);
+	// TODO: stop sound and deallocate previous resources
+	_resource = resource;
+	_resourceSample.sampleData = sampleData;
+	_resourceSample.sampleLen = sampleData ? sampleLen : 0;
+	_deleteResource = autoDelete;
+}
 
-	// This might affect timing
-	// bool isPalModule = (_resource.headerFlags & 2) != 0;
+bool Tfmx::loadSampleFile(int8 *&sampleData, uint32 &sampleLen, Common::SeekableReadStream &sampleStream) {
+	assert(!sampleData);
+	sampleData = 0;
+	sampleLen = 0;
 
+	const int32 sampleSize = sampleStream.size();
+	if (sampleSize < 4) {
+		warning("Tfmx: Cant load Samplefile");
+		return false;
+	}
+
+	int8 *sampleAlloc = new int8[sampleSize];
+	if (!sampleAlloc) {
+		warning("Tfmx: Could not allocate Memory: %dKB", sampleSize / 1024);
+		return false;
+	}
+
+	if (sampleStream.read(sampleAlloc, sampleSize) == (uint32)sampleSize) {
+		sampleAlloc[0] = sampleAlloc[1] = sampleAlloc[2] = sampleAlloc[3] = 0;
+		sampleData = sampleAlloc;
+		sampleLen = sampleSize;
+	} else {
+		delete sampleAlloc;
+		warning("Tfmx: Encountered IO-Error");
+		return false;
+	}
+	return true;
+}
+
+bool Tfmx::loadMdatFile(MdatResource &resource, Common::SeekableReadStream &musicData) {
+	assert(!resource.mdatAlloc);
+
+	resource.mdatAlloc = 0;
+	resource.mdatData = 0;
+	resource.mdatLen = 0;
+
+	bool hasHeader = false;
+	const int32 mdatSize = musicData.size();
+	if (mdatSize >= 0x200) {
+		byte buf[16] = { 0 };
+		// 0x0000: 10 Bytes Header "TFMX-SONG "
+		musicData.read(buf, 10);
+		hasHeader = memcmp(buf, "TFMX-SONG ", 10) == 0;
+	}
+	
+	if (!hasHeader) {
+		warning("Tfmx: File is not a Tfmx Module");
+		return false;
+	}
+
+	// 0x000A: int16 flags
+	resource.headerFlags = musicData.readUint16BE();
+	// 0x000C: int32 ?
 	// 0x0010: 6*40 Textfield
-	musicData.read(_resource.textField, 6 * 40);
+	musicData.skip(4 + 6 * 40);
 
 	/* 0x0100: Songstart x 32*/
 	for (int i = 0; i < kNumSubsongs; ++i)
-		_subsong[i].songstart = musicData.readUint16BE();
-
+		resource.subsong[i].songstart = musicData.readUint16BE();
 	/* 0x0140: Songend x 32*/
 	for (int i = 0; i < kNumSubsongs; ++i)
-		_subsong[i].songend = musicData.readUint16BE();
-
+		resource.subsong[i].songend = musicData.readUint16BE();
 	/* 0x0180: Tempo x 32*/
 	for (int i = 0; i < kNumSubsongs; ++i)
-		_subsong[i].tempo  = musicData.readUint16BE();
+		resource.subsong[i].tempo  = musicData.readUint16BE();
 
 	/* 0x01c0: unused ? */
 	musicData.skip(16);
 
 	/* 0x01d0: trackstep, pattern data p, macro data p */
-	uint32 offTrackstep = musicData.readUint32BE();
-	uint32 offPatternP = musicData.readUint32BE();
-	uint32 offMacroP = musicData.readUint32BE();
-	_resource.sfxTableOffset = 0x200;
-	bool getSfxIndex = false;
+	const uint32 offTrackstep = musicData.readUint32BE();
+	uint32 offPatternP, offMacroP;
 
 	// This is how MI`s TFMX-Player tests for unpacked Modules.
-	if (offTrackstep == 0) {
-		offTrackstep	= 0x600 + 0x200;
+	if (!offTrackstep) { // unpacked File
+		resource.trackstepOffset = 0x600 + 0x200;
 		offPatternP		= 0x200 + 0x200;
 		offMacroP		= 0x400 + 0x200;
-		getSfxIndex = true;
-		_resource.sfxTableOffset = 0x5FC;
+	} else { // packed File
+		resource.trackstepOffset = offTrackstep;
+		offPatternP = musicData.readUint32BE();
+		offMacroP = musicData.readUint32BE();
 	}
 
-	_resource.trackstepOffset = offTrackstep;
+	// End of basic header, check if everything worked ok
+	if (musicData.err()) {
+		warning("Tfmx: Encountered IO-Error");
+		return false;
+	}
 
+	// TODO: if a File is packed it could have for Ex only 2 Patterns/Macros
+	// the following loops could then read beyond EOF. 
+	// To correctly handle this it would be necessary to sort the pointers and
+	// figure out the number of Macros/Patterns
+	// We could also analyze pointers if they are correct offsets,
+	// so that accesses can be unchecked later
+
 	// Read in pattern starting offsets
 	musicData.seek(offPatternP);
 	for (int i = 0; i < kMaxPatternOffsets; ++i)
-		_patternOffset[i] = musicData.readUint32BE();
+		resource.patternOffset[i] = musicData.readUint32BE();
 
-	res = musicData.err();
-	assert(!res);
+	// use last PatternOffset (stored at 0x5FC in mdat) if unpacked File
+	// or fixed offset 0x200 if packed
+	resource.sfxTableOffset = !offTrackstep ? resource.patternOffset[127] : 0x200;
 
-	if (getSfxIndex)
-		_resource.sfxTableOffset = _patternOffset[127];
-
 	// Read in macro starting offsets
 	musicData.seek(offMacroP);
 	for (int i = 0; i < kMaxMacroOffsets; ++i)
-		_macroOffset[i] = musicData.readUint32BE();
+		resource.macroOffset[i] = musicData.readUint32BE();
 
-	res = musicData.err();
-	assert(!res);
-
-	// Read in whole mdat-file
-	int32 size = musicData.size();
-	assert(size != -1);
-	// TODO: special routine if size = -1?
-
-	_resource.mdatData = new byte[size];
-	assert(_resource.mdatData);
-	_resource.mdatLen = size;
-	musicData.seek(0);
-	musicData.read(_resource.mdatData, size);
+	// Read in mdat-file
+	// TODO: we can skip everything thats already stored in the resource-structure.
+	const int32 mdatOffset = 0x200;	// 0x200 is very conservative
+	const uint32 allocSize = (uint32)mdatSize - mdatOffset;
 	
-	res = musicData.err();
-	assert(!res);
-	musicData.readByte();
-	res = musicData.eos();
-	assert(res);
+	byte *mdatAlloc = new byte[allocSize];
+	if (!mdatAlloc) {
+		warning("Tfmx: Could not allocate Memory: %dKB", allocSize / 1024);
+		return false;
+	}
+	musicData.seek(mdatOffset);
+	if (musicData.read(mdatAlloc, allocSize) == allocSize) {
+		resource.mdatAlloc = mdatAlloc;
+		resource.mdatData = mdatAlloc - mdatOffset;
+		resource.mdatLen = mdatSize;
+	} else {
+		delete mdatAlloc;
+		warning("Tfmx: Encountered IO-Error");
+		return false;
+	}
 
-
-	// TODO: It would be possible to analyze the pointers and be able to
-	// seperate the file in trackstep, patterns and macro blocks
-	// Modules could do weird stuff like having those blocks mixed though.
-	// TODO: Analyze pointers if they are correct offsets,
-	// so that accesses can be unchecked later
-
-	// Read in whole sample-file
-	size = sampleData.size();
-	assert(size >= 4);
-	assert(size != -1);
-	// TODO: special routine if size = -1?
-
-	_resource.sampleData = new byte[size];
-	assert(_resource.sampleData);
-	_resource.sampleLen = size;
-	sampleData.seek(0);
-	sampleData.read(_resource.sampleData, size);
-	for (int i = 0; i < 4; ++i)
-		_resource.sampleData[i] = 0;
-	
-	res = sampleData.err();
-	assert(!res);
-	sampleData.readByte();
-	res = sampleData.eos();
-	assert(res);
-
 	return true;
 }
 
-
 void Tfmx::doMacro(int note, int macro, int relVol, int finetune, int channelNo) {
 	assert(0 <= macro && macro < kMaxMacroOffsets);
 	assert(0 <= note && note < 0xC0);
@@ -901,11 +956,11 @@
 	_playerCtx.song = (int8)songPos;
 
 	_trackCtx.loopCount = -1;
-	_trackCtx.startInd = _trackCtx.posInd = _subsong[songPos].songstart;
-	_trackCtx.stopInd = _subsong[songPos].songend;
+	_trackCtx.startInd = _trackCtx.posInd = _resource->subsong[songPos].songstart;
+	_trackCtx.stopInd = _resource->subsong[songPos].songend;
 
-	const bool palFlag = (_resource.headerFlags & 2) != 0;
-	const uint16 tempo = _subsong[songPos].tempo;
+	const bool palFlag = (_resource->headerFlags & 2) != 0;
+	const uint16 tempo = _resource->subsong[songPos].tempo;
 	uint16 ciaIntervall;
 	if (tempo >= 0x10) {
 		ciaIntervall = (uint16)(kCiaBaseInterval / tempo);
@@ -925,7 +980,7 @@
 	assert(0 <= sfxIndex && sfxIndex < 128);
 	Common::StackLock lock(_mutex);
 
-	const byte *sfxEntry = _resource.getSfxPtr(sfxIndex);
+	const byte *sfxEntry = getSfxPtr(sfxIndex);
 	if (sfxEntry[0] == 0xFB) {
 		// custompattern
 		const uint8 patCmd = sfxEntry[2];

Modified: scummvm/branches/gsoc2009-mods/sound/mods/tfmx.h
===================================================================
--- scummvm/branches/gsoc2009-mods/sound/mods/tfmx.h	2009-08-01 21:17:38 UTC (rev 42979)
+++ scummvm/branches/gsoc2009-mods/sound/mods/tfmx.h	2009-08-01 23:02:45 UTC (rev 42980)
@@ -28,16 +28,6 @@
 
 #include "sound/mods/paula.h"
 
-namespace {
-#ifndef NDEBUG
-inline void boundaryCheck(const void *bufStart, size_t bufLen, const void *address, size_t accessLen = 1) {
-	assert(bufStart <= address && (const byte *)address + accessLen <= (const byte *)bufStart + bufLen);
-}
-#else
-inline void boundaryCheck(const void *, size_t, void *, size_t = 1) {}
-#endif
-}
-
 namespace Audio {
 
 class Tfmx : public Paula {
@@ -49,12 +39,18 @@
 	void doSong(int songPos, bool stopAudio = false);
 	int doSfx(uint16 sfxIndex, bool unlockChannel = false);
 	void doMacro(int note, int macro, int relVol = 0, int finetune = 0, int channelNo = 0);
-	bool load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData);
 	int getTicks() const { return _playerCtx.tickCount; } 
 	int getSongIndex() const { return _playerCtx.song; }
 	void setSignalPtr(uint16 *ptr, uint16 numSignals) { _playerCtx.signal = ptr; _playerCtx.numSignals = numSignals; }
 	void stopMacroEffect(int channel);
 
+	struct MdatResource;
+	bool load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData, bool autoDelete = true);
+	void setModuleData(Tfmx &otherPlayer);
+	void setModuleData(const MdatResource *resource, const int8 *sampleData, uint32 sampleLen, bool autoDelete = true);
+	static bool loadMdatFile(MdatResource &resource, Common::SeekableReadStream &musicData);
+	static bool loadSampleFile(int8 *&sampleData, uint32 &sampleLen, Common::SeekableReadStream &sampleStream);
+
 protected:
 	void interrupt();
 
@@ -64,72 +60,47 @@
 
 	static const uint16 noteIntervalls[64];
 
-	struct Resource {
-		uint32 trackstepOffset;	//!< Offset in mdat
-		uint32 sfxTableOffset;
+public: // TODO change this to private somehow=
+	struct MdatResource {
+		const byte *mdatAlloc;	//!< allocated Block of Memory
+		const byte *mdatData;  	//!< Start of mdat-File, might point before mdatAlloc to correct Offset
+		uint32 mdatLen;
 
-		byte *mdatData;  	//!< Currently the whole mdat-File
-		byte *sampleData;	//!< Currently the whole sample-File
-		
-		uint32 mdatLen;  
-		uint32 sampleLen;
-
-		byte header[10];
 		uint16 headerFlags;
-		uint32 headerUnknown;
-		char textField[6 * 40];
+//		uint32 headerUnknown;
+//		char textField[6 * 40];
 
-		const byte *getSfxPtr(uint16 index = 0) {
-			byte *sfxPtr = (byte *)(mdatData + sfxTableOffset + index * 8);
+		struct Subsong {
+			uint16 songstart;	//!< Index in Trackstep-Table
+			uint16 songend;		//!< Last index in Trackstep-Table
+			uint16 tempo;
+		} subsong[kNumSubsongs];
 
-			boundaryCheck(mdatData, mdatLen, sfxPtr, 8);
-			return sfxPtr;
-		}
+		uint32 trackstepOffset;	//!< Offset in mdat
+		uint32 sfxTableOffset;
 
-		const uint16 *getTrackPtr(uint16 trackstep = 0) {
-			uint16 *trackData = (uint16 *)(mdatData + trackstepOffset + 16 * trackstep);
+		uint32 patternOffset[kMaxPatternOffsets];	//!< Offset in mdat
+		uint32 macroOffset[kMaxMacroOffsets];	//!< Offset in mdat
 
-			boundaryCheck(mdatData, mdatLen, trackData, 16);
-			return trackData;
+		void boundaryCheck(const void *address, size_t accessLen = 1) const {
+			assert(mdatAlloc <= address && (const byte *)address + accessLen <= (const byte *)mdatData + mdatLen);
 		}
+	};
 
-		const uint32 *getPatternPtr(uint32 offset) {
-			uint32 *pattData = (uint32 *)(mdatData + offset);
+private:
+	const MdatResource *_resource;
 
-			boundaryCheck(mdatData, mdatLen, pattData, 4);
-			return pattData;
-		}
+	struct SampleResource {
+		const int8 *sampleData;	//!< The whole sample-File
+		uint32 sampleLen;
 
-		const uint32 *getMacroPtr(uint32 offset) {
-			uint32 *macroData = (uint32 *)(mdatData + offset);
-
-			boundaryCheck(mdatData, mdatLen, macroData, 4);
-			return macroData;
+		void boundaryCheck(const void *address, size_t accessLen = 2) const {
+			assert(sampleData <= address && (const byte *)address + accessLen <= (const byte *)sampleData + sampleLen);
 		}
+	} _resourceSample;
 
-		const int8 *getSamplePtr(const uint32 offset) {
-			int8 *sample = (int8 *)(sampleData + offset);
+	bool _deleteResource;
 
-			boundaryCheck(sampleData, sampleLen, sample, 2);
-			return sample;
-		}
-		Resource() : mdatData(), mdatLen(), sampleData(), sampleLen() {}
-
-		~Resource() {
-			delete[] mdatData;
-			delete[] sampleData;
-		}
-	} _resource;
-
-	uint32 _patternOffset[kMaxPatternOffsets];	//!< Offset in mdat
-	uint32 _macroOffset[kMaxMacroOffsets];	//!< Offset in mdat
-
-	struct Subsong {
-		uint16 songstart;	//!< Index in Trackstep-Table
-		uint16 songend;		//!< Last index in Trackstep-Table
-		uint16 tempo;
-	} _subsong[kNumSubsongs];
-
 	struct ChannelContext {
 		byte	paulaChannel;
 
@@ -225,6 +196,41 @@
 		bool	stopWithLastPattern; //!< hack to automatically stop the whole player if no Pattern is running
 	} _playerCtx;
 
+	const byte *getSfxPtr(uint16 index = 0) const {
+		const byte *sfxPtr = (byte *)(_resource->mdatData + _resource->sfxTableOffset + index * 8);
+
+		_resource->boundaryCheck(sfxPtr, 8);
+		return sfxPtr;
+	}
+
+	const uint16 *getTrackPtr(uint16 trackstep = 0) const {
+		const uint16 *trackData = (uint16 *)(_resource->mdatData + _resource->trackstepOffset + 16 * trackstep);
+
+		_resource->boundaryCheck(trackData, 16);
+		return trackData;
+	}
+
+	const uint32 *getPatternPtr(uint32 offset) const {
+		const uint32 *pattData = (uint32 *)(_resource->mdatData + offset);
+
+		_resource->boundaryCheck(pattData, 4);
+		return pattData;
+	}
+
+	const uint32 *getMacroPtr(uint32 offset) const {
+		const uint32 *macroData = (uint32 *)(_resource->mdatData + offset);
+
+		_resource->boundaryCheck(macroData, 4);
+		return macroData;
+	}
+
+	const int8 *getSamplePtr(const uint32 offset) const {
+		const int8 *sample = _resourceSample.sampleData + offset;
+
+		_resourceSample.boundaryCheck(sample, 2);
+		return sample;
+	}
+
 	static void initMacroProgramm(ChannelContext &channel) {
 		channel.macroStep = 0;
 		channel.macroWait = 0;
@@ -293,6 +299,8 @@
 		}
 	}
 
+	
+	void freeResourceData();
 	void effects(ChannelContext &channel);
 	void macroRun(ChannelContext &channel);
 	void advancePatterns();


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list