aboutsummaryrefslogtreecommitdiff
path: root/engines/xeen
diff options
context:
space:
mode:
authorPaul Gilbert2016-09-12 21:02:28 -0400
committerPaul Gilbert2016-09-12 21:02:28 -0400
commitdd06b6fd7a98748d6a4c0f9f63519847dc6dd3f7 (patch)
treee41da3392fb2e9bcf67f09fa5fb1a273ea96fda5 /engines/xeen
parent48235c9055849e29e8aebf95a473bc607b398807 (diff)
downloadscummvm-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.cpp58
-rw-r--r--engines/xeen/music.h47
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