From c7697fb200a10f2c6406239b32d66cc7163c3d59 Mon Sep 17 00:00:00 2001 From: Norbert Lange Date: Fri, 19 Jun 2009 14:30:09 +0000 Subject: added support for SFX by using a seperate Player for them. svn-id: r41676 --- sound/mods/tfmx.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++------ sound/mods/tfmx.h | 13 ++++++++++ 2 files changed, 77 insertions(+), 8 deletions(-) (limited to 'sound/mods') diff --git a/sound/mods/tfmx.cpp b/sound/mods/tfmx.cpp index 7272848ae1..be9f9ebf73 100644 --- a/sound/mods/tfmx.cpp +++ b/sound/mods/tfmx.cpp @@ -49,7 +49,7 @@ Tfmx::Tfmx(int rate, bool stereo) : Paula(stereo, rate), _resource() { _playerCtx.enabled = false; _playerCtx.song = -1; - _playerCtx.stopWithLastPattern = true; + _playerCtx.stopWithLastPattern = false; for (int i = 0; i < kNumVoices; ++i) _channelCtx[i].paulaChannel = (byte)i; @@ -73,6 +73,25 @@ void Tfmx::interrupt() { } } + if (channel.sfxLockTime >= 0) + --channel.sfxLockTime; + else { + channel.sfxLocked = false; + channel.customMacroPrio = 0; + } + + if (channel.customMacro) { + const byte *const noteCmd = (const byte *)&channel.customMacro; + const int channelNo = (&channel - _channelCtx); + + channel.sfxLocked = false; + noteCommand(noteCmd[0], noteCmd[1], (noteCmd[2] & 0xF0) | channelNo, noteCmd[3]); + channel.customMacro = 0; + channel.sfxLocked = (channel.customMacroPrio != 0); + } + + + // TODO: Sometimes a macro will be executed here // apply timebased effects on Parameters @@ -103,11 +122,6 @@ void Tfmx::interrupt() { } void Tfmx::effects(ChannelContext &channel) { - if (channel.sfxLockTime >= 0) - --channel.sfxLockTime; - else - channel.sfxLocked = false; - // addBegin // TODO: macroNote pending? @@ -782,12 +796,16 @@ bool Tfmx::load(Common::SeekableReadStream &musicData, Common::SeekableReadStrea uint32 offTrackstep = musicData.readUint32BE(); uint32 offPatternP = musicData.readUint32BE(); uint32 offMacroP = musicData.readUint32BE(); + _resource._sfxTableOffset = 0x200; + bool getSfxIndex = false; // This is how MI`s TFMX-Player tests for unpacked Modules. if (offTrackstep == 0) { offTrackstep = 0x600 + 0x200; offPatternP = 0x200 + 0x200; offMacroP = 0x400 + 0x200; + getSfxIndex = true; + _resource._sfxTableOffset = 0x5FC; } _resource._trackstepOffset = offTrackstep; @@ -800,6 +818,9 @@ bool Tfmx::load(Common::SeekableReadStream &musicData, Common::SeekableReadStrea res = musicData.err(); assert(!res); + if (getSfxIndex) + _resource._sfxTableOffset = _patternOffset[127]; + // Read in macro starting offsets musicData.seek(offMacroP); for (int i = 0; i < kMaxMacroOffsets; ++i) @@ -859,6 +880,7 @@ bool Tfmx::load(Common::SeekableReadStream &musicData, Common::SeekableReadStrea void Tfmx::doMacro(int macro, int note) { assert(0 <= macro && macro < kMaxMacroOffsets); assert(0 <= note && note < 0xC0); + Common::StackLock lock(_mutex); _playerCtx.song = -1; _playerCtx.volume = 0x40; @@ -885,6 +907,7 @@ void Tfmx::doMacro(int macro, int note) { void Tfmx::doSong(int songPos) { assert(0 <= songPos && songPos < kNumSubsongs); + Common::StackLock lock(_mutex); _playerCtx.song = (int8)songPos; _playerCtx.volume = 0x40; @@ -906,8 +929,6 @@ void Tfmx::doSong(int songPos) { _playerCtx.patternCount = 0; - _playerCtx.pendingTrackstep = true; - for (int i = 0; i < kNumChannels; ++i) { _patternCtx[i].command = 0xFF; _patternCtx[i].expose = 0; @@ -920,11 +941,46 @@ void Tfmx::doSong(int songPos) { _channelCtx[i].vibValue = 0; stopChannel(_channelCtx[i]); _channelCtx[i].volume = 0; + _channelCtx[i].customMacro = 0; } setTimerBaseValue(kPalCiaClock); setInterruptFreqUnscaled(ciaIntervall); + + while (trackStep()) + ; + _playerCtx.pendingTrackstep = false; startPaula(); } +void Tfmx::doSfx(int sfxIndex) { + assert(0 <= sfxIndex && sfxIndex < 128); + Common::StackLock lock(_mutex); + + const byte *sfxEntry = _resource.getSfxPtr(sfxIndex); + + if (sfxEntry[0] == 0xFB) { + // custompattern + const uint8 patCmd = sfxEntry[2]; + const int8 patExp = (int8)sfxEntry[3]; + } else { + // custommacro + // byte index = (_playerCtx.song >= 0) ? sfxEntry[2] : sfxEntry[4]; + const byte channelNo = sfxEntry[2] % kNumVoices; + const byte priority = sfxEntry[5] & 0x7F; + + ChannelContext &channel = _channelCtx[channelNo]; + + const int16 sfxLocktime = channel.sfxLockTime; + + if (priority >= channel.customMacroPrio || sfxLocktime < 0) { + if (sfxIndex != channel.customMacroIndex || sfxLocktime < 0 || (sfxEntry[5] < 0x80) ) { + channel.customMacro = READ_UINT32(sfxEntry); // intentionally not "endian-correct" + channel.customMacroPrio = priority; + channel.customMacroIndex = (uint8)sfxIndex; + } + } + } +} + } diff --git a/sound/mods/tfmx.h b/sound/mods/tfmx.h index bcb25fbf8b..9761cef494 100644 --- a/sound/mods/tfmx.h +++ b/sound/mods/tfmx.h @@ -47,6 +47,7 @@ public: void interrupt(); void doSong(int songPos); + void doSfx(int sfxIndex); void doMacro(int macro, int note); bool load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData); int getTicks() {return _playerCtx.tickCount;} @@ -60,6 +61,7 @@ public: struct Resource { uint32 _trackstepOffset; //!< Offset in mdat + uint32 _sfxTableOffset; byte *_mdatData; //!< Currently the whole mdat-File byte *_sampleData; //!< Currently the whole sample-File @@ -72,6 +74,13 @@ public: uint32 headerUnknown; char textField[6 * 40]; + const byte *getSfxPtr(uint8 index = 0) { + byte *sfxPtr = (byte *)(_mdatData + _sfxTableOffset + index * 8); + + boundaryCheck(_mdatData, _mdatLen, sfxPtr, 8); + return sfxPtr; + } + const uint16 *getTrackPtr(uint16 trackstep = 0) { uint16 *trackData = (uint16 *)(_mdatData + _trackstepOffset + 16 * trackstep); @@ -128,6 +137,10 @@ public: uint8 macroLoopCount; bool macroRun; + uint32 customMacro; + uint8 customMacroIndex; + uint8 customMacroPrio; + bool sfxLocked; int16 sfxLockTime; bool keyUp; -- cgit v1.2.3