diff options
Diffstat (limited to 'sound/mods/tfmx.h')
-rw-r--r-- | sound/mods/tfmx.h | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/sound/mods/tfmx.h b/sound/mods/tfmx.h new file mode 100644 index 0000000000..fa132d5618 --- /dev/null +++ b/sound/mods/tfmx.h @@ -0,0 +1,233 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SOUND_MODS_TFMX_H +#define SOUND_MODS_TFMX_H + +#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 { +public: + Tfmx(int rate, bool stereo); + virtual ~Tfmx(); + + void interrupt(); + void doSong(int songPos); + void doMacro(int macro, int note); + bool load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData); + +// Note: everythings public so the debug-Routines work. +// private: + enum {kPalDefaultCiaVal = 11822, kNtscDefaultCiaVal = 14320, kCiaBaseInterval = 0x1B51F8}; + enum {kNumVoices = 4, kNumChannels = 8, kNumSubsongs = 32, kMaxPatternOffsets = 128, kMaxMacroOffsets = 128}; + + static const uint16 noteIntervalls[64]; + + struct Resource { + uint32 _trackstepOffset; //!< Offset in mdat + + 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]; + + const uint16 *getTrackPtr(uint16 trackstep = 0) { + uint16 *trackData = (uint16 *)(_mdatData + _trackstepOffset + 16 * trackstep); + + boundaryCheck(_mdatData, _mdatLen, trackData, 16); + return trackData; + } + + const uint32 *getPatternPtr(uint32 offset) { + uint32 *pattData = (uint32 *)(_mdatData + offset); + + boundaryCheck(_mdatData, _mdatLen, pattData, 4); + return pattData; + } + + const uint32 *getMacroPtr(uint32 offset) { + uint32 *macroData = (uint32 *)(_mdatData + offset); + + boundaryCheck(_mdatData, _mdatLen, macroData, 4); + return macroData; + } + + const int8 *getSamplePtr(const uint32 offset) { + int8 *sampleData = (int8 *)(_sampleData + offset); + + boundaryCheck(_sampleData, _sampleLen, sampleData, 2); + return sampleData; + } + 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; + + uint16 macroWait; + uint32 macroOffset; + uint32 macroReturnOffset; + uint16 macroStep; + uint32 macroReturnStep; + uint8 macroLoopCount; + bool macroRun; + + bool sfxLocked; + int16 sfxLockTime; + bool keyUp; + + bool deferWait; + bool countDmaInterrupts; + uint16 dmaCount; + + uint32 sampleStart; + uint16 sampleLen; + uint16 period; + + int8 volume; + uint8 relVol; + uint8 note; + uint8 prevNote; + uint16 fineTune; + + uint16 portaDestPeriod; + uint16 portaPeriod; + uint8 portaReset; + uint8 portaTime; + int16 portaRate; + + uint8 envReset; + uint8 envTime; + uint8 envRate; + uint8 envEndVolume; + + int16 vibOffset; + int8 vibWidth; + uint8 vibFlag; + uint8 vibReset; + uint8 vibTime; + + uint8 addBeginTime; + uint8 addBeginReset; + int32 addBegin; + } _channelCtx[kNumVoices]; + + struct PatternContext { + uint32 offset; // patternStart, Offset from mdat + uint32 savedOffset; // for subroutine calls + uint16 step; // distance from patternStart + uint16 savedStep; + + uint8 command; + int8 expose; + uint8 loopCount; + uint8 wait; //!< how many ticks to wait before next Command + } _patternCtx[kNumChannels]; + + struct TrackStepContext { + uint16 startInd; + uint16 stopInd; + uint16 posInd; + int16 loopCount; + } _trackCtx; + + struct PlayerContext { + bool enabled; +// bool end; + int8 song; //!< >= 0 if Song is running (means process Patterns) + + bool pendingTrackstep; + + uint16 patternCount; + uint16 patternSkip; //!< skip that amount of CIA-Interrupts + + int8 volume; //!< Master Volume + +/* int8 fadeDest; + int8 fadeTime; + int8 fadeReset; + int8 fadeSlope; */ + } _playerCtx; + + void initMacroProgramm(ChannelContext &channel) { + channel.macroStep = 0; + channel.macroWait = 0; + channel.macroRun = true; + channel.macroLoopCount = 0xFF; + channel.countDmaInterrupts = false; + } + + void stopChannel(ChannelContext &channel) { + if (!channel.sfxLocked) { + channel.macroRun = false; + channel.countDmaInterrupts = false; + Paula::disableChannel(channel.paulaChannel); + } + } + + void effects(ChannelContext &channel); + FORCEINLINE bool macroStep(ChannelContext &channel); + void advancePatterns(); + FORCEINLINE bool patternStep(PatternContext &pattern); + bool trackStep(); + void noteCommand(uint8 note, uint8 param1, uint8 param2, uint8 param3); + +}; + +} + +#endif |