aboutsummaryrefslogtreecommitdiff
path: root/engines/xeen/music.h
diff options
context:
space:
mode:
authorPaul Gilbert2016-09-14 20:53:35 -0400
committerPaul Gilbert2016-09-14 20:53:35 -0400
commitb93b8f8245400c937f0d571f9a076d552b6fd0ce (patch)
treecdedf865ebbdaa02755615ac7bbc1a128b55ac07 /engines/xeen/music.h
parent87168baf323c9db3acd90d154848fd4f3a554df6 (diff)
downloadscummvm-rg350-b93b8f8245400c937f0d571f9a076d552b6fd0ce.tar.gz
scummvm-rg350-b93b8f8245400c937f0d571f9a076d552b6fd0ce.tar.bz2
scummvm-rg350-b93b8f8245400c937f0d571f9a076d552b6fd0ce.zip
XEEN: Fleshing out music player
Diffstat (limited to 'engines/xeen/music.h')
-rw-r--r--engines/xeen/music.h261
1 files changed, 179 insertions, 82 deletions
diff --git a/engines/xeen/music.h b/engines/xeen/music.h
index b1fa43daa2..0d5188e697 100644
--- a/engines/xeen/music.h
+++ b/engines/xeen/music.h
@@ -28,8 +28,9 @@
#include "common/array.h"
#include "common/mutex.h"
#include "common/queue.h"
+#include "common/stack.h"
-#define ADLIB_CHANNEL_COUNT 9
+#define CHANNEL_COUNT 9
namespace OPL {
class OPL;
@@ -37,52 +38,132 @@ namespace OPL {
namespace Xeen {
-class Music;
+class MusicDriver;
-typedef bool (Music::*CommandFn)(const byte *&srcP, byte nextByte);
+typedef bool (MusicDriver::*CommandFn)(const byte *&srcP, byte param);
-struct RegisterValue {
- uint8 _regNum;
- uint8 _value;
+/**
+ * Base class for music drivers
+ */
+class MusicDriver {
+ struct Subroutine {
+ const byte *_returnP;
+ const byte *_jumpP;
+ Subroutine() : _returnP(nullptr), _jumpP(nullptr) {}
+ Subroutine(const byte *returnP, const byte *endP) :
+ _returnP(returnP), _jumpP(endP) {}
+ };
+private:
+ static const CommandFn FX_COMMANDS[16];
+ static const CommandFn MUSIC_COMMANDS[16];
+private:
+ Common::Stack<Subroutine> _musSubroutines, _fxSubroutines;
+ bool _field1E;
+ int _musCountdownTimer;
+ int _fxCountdownTimer;
+ bool _lowMusicIgnored;
+ const byte *_fxDataPtr, *_musDataPtr;
+ const byte *_fxStartPtr;
+ const byte *_musStartPtr;
+ bool _flags[CHANNEL_COUNT];
+ byte _field15C[CHANNEL_COUNT];
+ byte _field165[CHANNEL_COUNT];
+ byte _field177[CHANNEL_COUNT];
+private:
+ /**
+ * Executes the next command
+ * @param srcP Command data pointer
+ * @returns If true, execution of commands for the current timer call stops
+ */
+ bool command(const byte *&srcP);
+protected:
+ bool _fieldF;
+protected:
+ /**
+ * Executes a series of commands until instructed to stop
+ */
+ void execute();
+
+ // Music commands (with some also used by FX)
+ virtual bool musCallSubroutine(const byte *&srcP, byte param);
+ virtual bool musSetCountdown(const byte *&srcP, byte param);
+ virtual bool musSetInstrument(const byte *&srcP, byte param) = 0;
+ virtual bool cmdNoOperation(const byte *&srcP, byte param);
+ virtual bool musSetPitchWheel(const byte *&srcP, byte param) = 0;
+ virtual bool musSkipWord(const byte *&srcP, byte param);
+ virtual bool musSetPanning(const byte *&srcP, byte param) = 0;
+ virtual bool musFade(const byte *&srcP, byte param) = 0;
+ virtual bool musStartNote(const byte *&srcP, byte param) = 0;
+ virtual bool musSetVolume(const byte *&srcP, byte param) = 0;
+ virtual bool musInjectMidi(const byte *&srcP, byte param) = 0;
+ virtual bool musPlayInstrument(const byte *&srcP, byte param) = 0;
+ virtual bool cmdClearFlag(const byte *&srcP, byte param);
+ virtual bool cmdWibbly(const byte *&srcP, byte param);
+ virtual bool musEndSubroutine(const byte *&srcP, byte param);
+
+ // FX commands
+ virtual bool fxCallSubroutine(const byte *&srcP, byte param);
+ virtual bool fxSetCountdown(const byte *&srcP, byte param);
+ virtual bool fxSetInstrument(const byte *&srcP, byte param) = 0;
+ virtual bool fxSetVolume(const byte *&srcP, byte param) = 0;
+ virtual bool fxMidiReset(const byte *&srcP, byte param) = 0;
+ virtual bool fxMidiDword(const byte *&srcP, byte param) = 0;
+ virtual bool fxSetPanning(const byte *&srcP, byte param) = 0;
+ virtual bool fxChannelOff(const byte *&srcP, byte param) = 0;
+ virtual bool fxFade(const byte *&srcP, byte param) = 0;
+ virtual bool fxStartNote(const byte *&srcP, byte param) = 0;
+ virtual bool fxInjectMidi(const byte *&srcP, byte param) = 0;
+ virtual bool fxPlayInstrument(const byte *&srcP, byte param) = 0;
+ virtual bool fxEndSubroutine(const byte *&srcP, byte param);
- RegisterValue(int regNum, int value) {
- _regNum = regNum; _value = value;
- }
+ virtual void postProcess() = 0;
+
+ /**
+ * Does a reset of any sound effect
+ */
+ virtual void resetFX() = 0;
+public:
+ /**
+ * Constructor
+ */
+ MusicDriver();
+
+ /**
+ * Destructor
+ */
+ virtual ~MusicDriver() {}
+
+ /**
+ * Starts an special effect playing
+ */
+ void playFX(uint effectId, const byte *data);
};
-class Music {
- struct Channel {
- byte _outputLevel;
- byte _scalingValue;
+class AdlibMusicDriver : public MusicDriver {
+ struct RegisterValue {
+ uint8 _regNum;
+ uint8 _value;
- Channel() : _outputLevel(0), _scalingValue(0) {}
+ RegisterValue(int regNum, int value) {
+ _regNum = regNum; _value = value;
+ }
};
private:
- static const byte OPERATOR1_INDEXES[ADLIB_CHANNEL_COUNT];
- static const byte OPERATOR2_INDEXES[ADLIB_CHANNEL_COUNT];
- static const CommandFn COMMAND_TABLE1[16];
- static const CommandFn COMMAND_TABLE2[16];
+ static const byte OPERATOR1_INDEXES[CHANNEL_COUNT];
+ static const byte OPERATOR2_INDEXES[CHANNEL_COUNT];
+ static const uint WAVEFORMS[24];
private:
OPL::OPL *_opl;
- Common::Mutex _driverMutex;
- Common::Array<Channel> _channels;
Common::Queue<RegisterValue> _queue;
- const byte *_effectsData;
- Common::Array<uint16> _effectsOffsets;
- const byte *_musicPtr1, *_musicPtr2;
- const byte *_dataPtr;
- bool _fieldF;
- bool _field1C;
- bool _field1E;
- uint _fieldFB[7];
- int _field109;
- int _field10B;
- byte _field10D[7];
- int _field114;
- int _field115;
- int _field116;
- int _field117;
- bool _lowMusicIgnored;
+ Common::Mutex _driverMutex;
+ byte _volumes[CHANNEL_COUNT];
+ byte _scalingValues[CHANNEL_COUNT];
+ const byte *_musInstrumentPtrs[16];
+ const byte *_fxInstrumentPtrs[16];
+ uint _frequencies[7];
+ int _field180;
+ int _field182;
+ int _volume;
private:
/**
* Initializes the state of the Adlib OPL driver
@@ -90,11 +171,6 @@ private:
void initialize();
/**
- * Loads effects data that was embedded in the music driver
- */
- void loadEffectsData();
-
- /**
* Adds a register write to the pending queue that will be flushed
* out to the OPL on the next timer call
*/
@@ -111,16 +187,6 @@ private:
void flush();
/**
- * Updates any playing music
- */
- void update();
-
- /**
- * Does a reset
- */
- void reset();
-
- /**
* Resets all the output frequencies
*/
void resetFrequencies();
@@ -131,42 +197,73 @@ private:
void setFrequency(byte operatorNum, uint frequency);
/**
+ * Calculates the frequency for a note
+ */
+ uint calcFrequency(byte note);
+
+ /**
* Sets the output level for a channel
*/
void setOutputLevel(byte channelNum, uint level);
/**
- * Post-process
- */
- void postProcess();
-
- /**
- * Update command methods
- */
- bool cmd1(const byte *&srcP, byte nextByte);
- bool cmd2(const byte *&srcP, byte nextByte);
- bool cmd3(const byte *&srcP, byte nextByte);
- bool cmd4(const byte *&srcP, byte nextByte);
- bool cmd5(const byte *&srcP, byte nextByte);
- bool cmd6(const byte *&srcP, byte nextByte);
- bool cmd7(const byte *&srcP, byte nextByte);
- bool cmd8(const byte *&srcP, byte nextByte);
- bool cmd9(const byte *&srcP, byte nextByte);
- bool cmd10(const byte *&srcP, byte nextByte);
- bool cmd11(const byte *&srcP, byte nextByte);
- bool cmd12(const byte *&srcP, byte nextByte);
- bool cmd13(const byte *&srcP, byte nextByte);
- bool cmd14(const byte *&srcP, byte nextByte);
- bool cmd15(const byte *&srcP, byte nextByte);
- bool cmd16(const byte *&srcP, byte nextByte);
- bool cmd17(const byte *&srcP, byte nextByte);
- bool cmd18(const byte *&srcP, byte nextByte);
- bool cmd19(const byte *&srcP, byte nextByte);
- bool cmd20(const byte *&srcP, byte nextByte);
- bool cmd21(const byte *&srcP, byte nextByte);
- bool cmd22(const byte *&srcP, byte nextByte);
- bool cmd23(const byte *&srcP, byte nextByte);
- bool cmd24(const byte *&srcP, byte nextByte);
+ * Starts playing an instrument
+ */
+ void playInstrument(byte channelNum, const byte *data);
+protected:
+ virtual bool musSetInstrument(const byte *&srcP, byte param);
+ virtual bool musSetPitchWheel(const byte *&srcP, byte param);
+ virtual bool musSetPanning(const byte *&srcP, byte param);
+ virtual bool musFade(const byte *&srcP, byte param);
+ virtual bool musStartNote(const byte *&srcP, byte param);
+ virtual bool musSetVolume(const byte *&srcP, byte param);
+ virtual bool musInjectMidi(const byte *&srcP, byte param);
+ virtual bool musPlayInstrument(const byte *&srcP, byte param);
+
+ virtual bool fxSetInstrument(const byte *&srcP, byte param);
+ virtual bool fxSetVolume(const byte *&srcP, byte param);
+ virtual bool fxMidiReset(const byte *&srcP, byte param);
+ virtual bool fxMidiDword(const byte *&srcP, byte param);
+ virtual bool fxSetPanning(const byte *&srcP, byte param);
+ virtual bool fxChannelOff(const byte *&srcP, byte param);
+ virtual bool fxFade(const byte *&srcP, byte param);
+ virtual bool fxStartNote(const byte *&srcP, byte param);
+ virtual bool fxInjectMidi(const byte *&srcP, byte param);
+ virtual bool fxPlayInstrument(const byte *&srcP, byte param);
+
+ /**
+ * Does a reset of any sound effect
+ */
+ virtual void resetFX();
+public:
+ /**
+ * Constructor
+ */
+ AdlibMusicDriver();
+
+ /**
+ * Destructor
+ */
+ virtual ~AdlibMusicDriver();
+};
+
+
+class Music {
+private:
+ MusicDriver *_musicDriver;
+ const byte *_effectsData;
+ Common::Array<uint16> _effectsOffsets;
+private:
+ /**
+ * Loads effects data that was embedded in the music driver
+ */
+ void loadEffectsData();
+
+ /**
+ * Updates any playing music
+ */
+ void update();
+
protected:
Audio::Mixer *_mixer;
public: