diff options
author | Paul Gilbert | 2016-09-12 21:02:28 -0400 |
---|---|---|
committer | Paul Gilbert | 2016-09-12 21:02:28 -0400 |
commit | dd06b6fd7a98748d6a4c0f9f63519847dc6dd3f7 (patch) | |
tree | e41da3392fb2e9bcf67f09fa5fb1a273ea96fda5 /engines/xeen | |
parent | 48235c9055849e29e8aebf95a473bc607b398807 (diff) | |
download | scummvm-rg350-dd06b6fd7a98748d6a4c0f9f63519847dc6dd3f7.tar.gz scummvm-rg350-dd06b6fd7a98748d6a4c0f9f63519847dc6dd3f7.tar.bz2 scummvm-rg350-dd06b6fd7a98748d6a4c0f9f63519847dc6dd3f7.zip |
XEEN: Implement Music playEffect method
Diffstat (limited to 'engines/xeen')
-rw-r--r-- | engines/xeen/music.cpp | 58 | ||||
-rw-r--r-- | engines/xeen/music.h | 47 |
2 files changed, 103 insertions, 2 deletions
diff --git a/engines/xeen/music.cpp b/engines/xeen/music.cpp index f95683ac3d..741fe81c31 100644 --- a/engines/xeen/music.cpp +++ b/engines/xeen/music.cpp @@ -27,10 +27,15 @@ namespace Xeen { -#define ADLIB_CHANNEL_COUNT 9 #define CALLBACKS_PER_SECOND 60 -Music::Music(Audio::Mixer *mixer) : _mixer(mixer), _effectsData(nullptr) { +Music::Music(Audio::Mixer *mixer) : _mixer(mixer), _effectsData(nullptr), + _musicPtr1(nullptr), _musicPtr2(nullptr), _lowMusicIgnored(false), + _fieldF(false), _field109(0), _field10B(0), _field114(0), + _field115(0), _field117(0) { + _channels.resize(ADLIB_CHANNEL_COUNT); + Common::fill(&_field10D[0], &_field10D[7], 0); + _mixer = mixer; _opl = OPL::Config::create(); _opl->init(); @@ -72,6 +77,10 @@ void Music::onTimer() { flush(); } +void Music::write(int reg, int val) { + _queue.push(RegisterValue(reg, val)); +} + void Music::flush() { Common::StackLock slock(_driverMutex); @@ -85,4 +94,49 @@ void Music::update() { // TODO } +void Music::playEffect(uint effectId) { + if (!_lowMusicIgnored || effectId < 7 || effectId >= 11) { + if (effectId < _effectsOffsets.size()) { + _musicPtr1 = _musicPtr2 = &_effectsData[_effectsOffsets[effectId]]; + _field117 = 0; + _field115 = 0; + _field114 = 0; + reset(); + _lowMusicIgnored = true; + } + } +} + +void Music::reset() { + if (!_fieldF) { + _field109 = 0; + setFrequency(7, 0); + _channels[7]._outputLevel = 63; + setOutputLevel(7, 63); + } + + _field10B = 0; + setFrequency(8, 0); + _channels[8]._outputLevel = 63; + setOutputLevel(8, 63); +} + +void Music::setFrequency(byte operatorNum, uint frequency) { + write(0xA0 + operatorNum, frequency & 0xff); + write(0xB0 + operatorNum, (frequency >> 8)); +} + +void Music::setOutputLevel(byte channelNum, uint level) { + write(0x40 + OPERATOR2_INDEXES[channelNum], level | + (_channels[channelNum]._scalingValue & 0xC0)); +} + +const byte Music::OPERATOR1_INDEXES[ADLIB_CHANNEL_COUNT] = { + 0, 1, 2, 8, 9, 0xA, 0x10, 0x11, 0x12 +}; + +const byte Music::OPERATOR2_INDEXES[ADLIB_CHANNEL_COUNT] = { + 3, 4, 5, 0xB, 0xC, 0xD, 0x13, 0x14, 0x15 +}; + } // End of namespace Xeen diff --git a/engines/xeen/music.h b/engines/xeen/music.h index 202f8ba982..40059be327 100644 --- a/engines/xeen/music.h +++ b/engines/xeen/music.h @@ -29,6 +29,8 @@ #include "common/mutex.h" #include "common/queue.h" +#define ADLIB_CHANNEL_COUNT 9 + namespace OPL { class OPL; } @@ -45,12 +47,31 @@ struct RegisterValue { }; class Music { + struct Channel { + byte _outputLevel; + byte _scalingValue; + + Channel() : _outputLevel(0), _scalingValue(0) {} + }; +private: + static const byte OPERATOR1_INDEXES[ADLIB_CHANNEL_COUNT]; + static const byte OPERATOR2_INDEXES[ADLIB_CHANNEL_COUNT]; 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; + bool _fieldF; + int _field109; + int _field10B; + byte _field10D[7]; + int _field114; + int _field115; + int _field117; + bool _lowMusicIgnored; private: /** * Loads effects data that was embedded in the music driver @@ -58,6 +79,12 @@ private: void loadEffectsData(); /** + * Adds a register write to the pending queue that will be flushed + * out to the OPL on the next timer call + */ + void write(int reg, int val); + + /** * Timer function for OPL */ void onTimer(); @@ -71,11 +98,31 @@ private: * Updates any playing music */ void update(); + + /** + * Does a reset + */ + void reset(); + + /** + * Sets the frequency for an operator + */ + void setFrequency(byte operatorNum, uint frequency); + + /** + * Sets the output level for a channel + */ + void setOutputLevel(byte channelNum, uint level); protected: Audio::Mixer *_mixer; public: Music(Audio::Mixer *mixer); ~Music(); + + /** + * Starts an effect playing + */ + void playEffect(uint effectId); }; } // End of namespace Xeen |