Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

tfmx.h

/* 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$
 *
 */

// see if all engines using this class are DISABLED
#if !defined(ENABLE_SCUMM)

// normal Header Guard
#elif !defined(SOUND_MODS_TFMX_H)
#define SOUND_MODS_TFMX_H

#include "audio/mods/paula.h"

namespace Audio {

class Tfmx : public Paula {
public:
      Tfmx(int rate, bool stereo);
      virtual ~Tfmx();

      /**
       * Stops a playing Song (but leaves macros running) and optionally also stops the player
       *
       * @param stopAudio     stops player and audio output
       * @param dataSize      number of bytes to be written
       * @return the number of bytes which were actually written.
       */
      void stopSong(bool stopAudio = true) { Common::StackLock lock(_mutex); stopSongImpl(stopAudio); }
      /**
       * Stops currently playing Song (if any) and cues up a new one.
       * if stopAudio is specified, the player gets reset before starting the new song
       *
       * @param songPos index of Song to play
       * @param stopAudio     stops player and audio output
       * @param dataSize      number of bytes to be written
       * @return the number of bytes which were actually written.
       */
      void doSong(int songPos, bool stopAudio = false);
      /**
       * plays an effect from the sfx-table, does not start audio-playback.
       *
       * @param sfxIndex      index of effect to play
       * @param unlockChannel overwrite higher priority effects
       * @return  index of the channel which now queued up the effect.
       *                -1 in case the effect couldnt be queued up
       */
      int doSfx(uint16 sfxIndex, bool unlockChannel = false);
      /**
       * stop a running macro channel
       *
       * @param channel index of effect to stop
       */
      void stopMacroEffect(int channel);

      void doMacro(int note, int macro, int relVol = 0, int finetune = 0, int channelNo = 0);
      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 freeResources() { _deleteResource = true; freeResourceDataImpl(); }
      bool load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData, bool autoDelete = true);
      void setModuleData(Tfmx &otherPlayer);

protected:
      void interrupt();

private:
      enum { kPalDefaultCiaVal = 11822, kNtscDefaultCiaVal = 14320, kCiaBaseInterval = 0x1B51F8 };
      enum { kNumVoices = 4, kNumChannels = 8, kNumSubsongs = 32, kMaxPatternOffsets = 128, kMaxMacroOffsets = 128 };

      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;

            uint16 headerFlags;
//          uint32 headerUnknown;
//          char textField[6 * 40];

            struct Subsong {
                  uint16 songstart; ///< Index in Trackstep-Table
                  uint16 songend;         ///< Last index in Trackstep-Table
                  uint16 tempo;
            } subsong[kNumSubsongs];

            uint32 trackstepOffset; ///< Offset in mdat
            uint32 sfxTableOffset;

            uint32 patternOffset[kMaxPatternOffsets]; ///< Offset in mdat
            uint32 macroOffset[kMaxMacroOffsets];     ///< Offset in mdat

            void boundaryCheck(const void *address, size_t accessLen = 1) const {
                  assert(mdatAlloc <= address && (const byte *)address + accessLen <= (const byte *)mdatData + mdatLen);
            }
      } const *_resource;

      struct SampleResource {
            const int8 *sampleData; ///< The whole sample-File
            uint32 sampleLen;

            void boundaryCheck(const void *address, size_t accessLen = 2) const {
                  assert(sampleData <= address && (const byte *)address + accessLen <= (const byte *)sampleData + sampleLen);
            }
      } _resourceSample;

      bool _deleteResource;

      bool hasResources() {
            return _resource && _resource->mdatLen && _resourceSample.sampleLen;
      }

      struct ChannelContext {
            byte  paulaChannel;

//          byte  macroIndex;
            uint16      macroWait;
            uint32      macroOffset;
            uint32      macroReturnOffset;
            uint16      macroStep;
            uint16      macroReturnStep;
            uint8 macroLoopCount;
            bool  macroRun;
            int8  macroSfxRun;      ///< values are the folowing: -1 macro disabled, 0 macro init, 1 macro running

            uint32      customMacro;
            uint8 customMacroIndex;
            uint8 customMacroPrio;

            bool  sfxLocked;
            int16 sfxLockTime;
            bool  keyUp;

            bool  deferWait;
            uint16      dmaIntCount;

            uint32      sampleStart;
            uint16      sampleLen;
            uint16      refPeriod;
            uint16      period;

            int8  volume;
            uint8 relVol;
            uint8 note;
            uint8 prevNote;
            int16 fineTune; // always a signextended byte

            uint8 portaSkip;
            uint8 portaCount;
            uint16      portaDelta;
            uint16      portaValue;

            uint8 envSkip;
            uint8 envCount;
            uint8 envDelta;
            int8  envEndVolume;

            uint8 vibLength;
            uint8 vibCount;
            int16 vibValue;
            int8  vibDelta;

            uint8 addBeginLength;
            uint8 addBeginCount;
            int32 addBeginDelta;
      } _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 {
            int8  song; ///< >= 0 if Song is running (means process Patterns)

            uint16      patternCount;
            uint16      patternSkip;      ///< skip that amount of CIA-Interrupts

            int8  volume;     ///< Master Volume

            uint8 fadeSkip;
            uint8 fadeCount;
            int8  fadeEndVolume;
            int8  fadeDelta;

            int         tickCount;

            uint16      *signal;
            uint16      numSignals;

            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 = (const byte *)(_resource->mdatData + _resource->sfxTableOffset + index * 8);

            _resource->boundaryCheck(sfxPtr, 8);
            return sfxPtr;
      }

      const uint16 *getTrackPtr(uint16 trackstep = 0) const {
            const uint16 *trackData = (const uint16 *)(_resource->mdatData + _resource->trackstepOffset + 16 * trackstep);

            _resource->boundaryCheck(trackData, 16);
            return trackData;
      }

      const uint32 *getPatternPtr(uint32 offset) const {
            const uint32 *pattData = (const uint32 *)(_resource->mdatData + offset);

            _resource->boundaryCheck(pattData, 4);
            return pattData;
      }

      const uint32 *getMacroPtr(uint32 offset) const {
            const uint32 *macroData = (const 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 inline void initMacroProgramm(ChannelContext &channel);
      static inline void clearEffects(ChannelContext &channel);
      static inline void haltMacroProgramm(ChannelContext &channel);
      static inline void unlockMacroChannel(ChannelContext &channel);
      static inline void initPattern(PatternContext &pattern, uint8 cmd, int8 expose, uint32 offset);
      void stopSongImpl(bool stopAudio = true);
      static inline void setNoteMacro(ChannelContext &channel, uint note, int fineTune);
      void initFadeCommand(const uint8 fadeTempo, const int8 endVol);
      void setModuleData(const MdatResource *resource, const int8 *sampleData, uint32 sampleLen, bool autoDelete = true);
      static const MdatResource *loadMdatFile(Common::SeekableReadStream &musicData);
      static const int8 *loadSampleFile(uint32 &sampleLen, Common::SeekableReadStream &sampleStream);
      void freeResourceDataImpl();
      void effects(ChannelContext &channel);
      void macroRun(ChannelContext &channel);
      void advancePatterns();
      bool patternRun(PatternContext &pattern);
      bool trackRun(bool incStep = false);
      void noteCommand(uint8 note, uint8 param1, uint8 param2, uint8 param3);
};

}     // End of namespace Audio

#endif // !defined(SOUND_MODS_TFMX_H)

Generated by  Doxygen 1.6.0   Back to index