aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2014-02-16 23:04:02 -0500
committerPaul Gilbert2014-02-16 23:04:02 -0500
commitece3e9a2200052cc65f60e0295b674095d7a6a66 (patch)
tree024f23a5d25edba49e4be59ec76e611e6d063b12
parent409f51cb99bcd9e1024e57b250d70327f61e6d15 (diff)
downloadscummvm-rg350-ece3e9a2200052cc65f60e0295b674095d7a6a66.tar.gz
scummvm-rg350-ece3e9a2200052cc65f60e0295b674095d7a6a66.tar.bz2
scummvm-rg350-ece3e9a2200052cc65f60e0295b674095d7a6a66.zip
MADS: Booyah! Copy protection failure air escaping sound playing
-rw-r--r--engines/mads/mads.cpp8
-rw-r--r--engines/mads/sound_nebular.cpp61
-rw-r--r--engines/mads/sound_nebular.h51
3 files changed, 102 insertions, 18 deletions
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index 39ef195cd6..25730fa9e4 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -45,8 +45,6 @@ void MADSEngine::initialise() {
_soundManager.setVm(this, _mixer);
}
-static uint32 lastSoundFrame = 0;
-
Common::Error MADSEngine::run() {
initGraphics(320, 200, false);
initialise();
@@ -56,12 +54,6 @@ Common::Error MADSEngine::run() {
while (!shouldQuit()) {
g_system->getEventManager()->pollEvent(e);
g_system->delayMillis(10);
-
- uint32 milli = g_system->getMillis();
- if (milli > (lastSoundFrame + 50)) {
- lastSoundFrame = milli;
- _soundManager.poll();
- }
}
return Common::kNoError;
diff --git a/engines/mads/sound_nebular.cpp b/engines/mads/sound_nebular.cpp
index a1116932d1..146a620261 100644
--- a/engines/mads/sound_nebular.cpp
+++ b/engines/mads/sound_nebular.cpp
@@ -148,12 +148,6 @@ ASound::ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffs
if (!_soundFile.open(filename))
error("Could not open file - %s", filename.c_str());
- _dataOffset = dataOffset;
- _mixer = mixer;
- _opl = OPL::Config::create();
- assert(_opl);
- _opl->init(11025);
-
// Initialise fields
_activeChannelPtr = nullptr;
_samplePtr = nullptr;
@@ -179,6 +173,21 @@ ASound::ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffs
_randomSeed = 1234;
_amDep = _vibDep = _splitPoint = true;
+ _samplesTillCallback = 0;
+ _samplesTillCallbackRemainder = 0;
+ _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
+ _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
+
+ // Store passed parameters, and setup OPL
+ _dataOffset = dataOffset;
+ _mixer = mixer;
+ _opl = OPL::Config::create();
+ assert(_opl);
+
+ _opl->init(getRate());
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1,
+ Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
// Initialise the Adlib
adlibInit();
@@ -191,6 +200,7 @@ ASound::~ASound() {
for (i = _dataCache.begin(); i != _dataCache.end(); ++i)
delete[] (*i)._data;
+ _mixer->stopHandle(_soundHandle);
delete _opl;
}
@@ -233,7 +243,7 @@ void ASound::noise() {
}
void ASound::write(int reg, int val) {
- _opl->write(reg, val);
+ _queue.push(RegisterValue(reg, val));
}
int ASound::write2(int state, int reg, int val) {
@@ -243,6 +253,15 @@ int ASound::write2(int state, int reg, int val) {
return state;
}
+void ASound::flush() {
+ Common::StackLock slock(_driverMutex);
+
+ while (!_queue.empty()) {
+ RegisterValue v = _queue.pop();
+ _opl->writeReg(v._regNum, v._value);
+ }
+}
+
void ASound::channelOn(int reg, int volume) {
write2(8, reg, (_ports[reg] & 0xC0) | (volume & 0x3F));
}
@@ -754,6 +773,34 @@ void ASound::updateFNumber() {
write2(8, hiReg, val2);
}
+int ASound::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock slock(_driverMutex);
+
+ int32 samplesLeft = numSamples;
+ memset(buffer, 0, sizeof(int16) * numSamples);
+ while (samplesLeft) {
+ if (!_samplesTillCallback) {
+ poll();
+ flush();
+
+ _samplesTillCallback = _samplesPerCallback;
+ _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
+ if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) {
+ _samplesTillCallback++;
+ _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND;
+ }
+ }
+
+ int32 render = MIN<int>(samplesLeft, _samplesTillCallback);
+ samplesLeft -= render;
+ _samplesTillCallback -= render;
+
+ _opl->readBuffer(buffer, render);
+ buffer += render;
+ }
+ return numSamples;
+}
+
int ASound::command0() {
bool isDisabled = _isDisabled;
_isDisabled = true;
diff --git a/engines/mads/sound_nebular.h b/engines/mads/sound_nebular.h
index e2367a5bd8..f9251c9329 100644
--- a/engines/mads/sound_nebular.h
+++ b/engines/mads/sound_nebular.h
@@ -25,6 +25,8 @@
#include "common/scummsys.h"
#include "common/file.h"
+#include "common/mutex.h"
+#include "common/queue.h"
#include "audio/audiostream.h"
#include "audio/fmopl.h"
#include "audio/mixer.h"
@@ -108,13 +110,23 @@ public:
AdlibSample(Common::SeekableReadStream &s);
};
+struct RegisterValue {
+ uint8 _regNum;
+ uint8 _value;
+
+ RegisterValue(int regNum, int value) {
+ _regNum = regNum; _value = value;
+ }
+};
+
#define ADLIB_CHANNEL_COUNT 9
#define ADLIB_CHANNEL_MIDWAY 5
+#define CALLBACKS_PER_SECOND 60
/**
* Base class for the sound player resource files
*/
-class ASound {
+class ASound: public Audio::AudioStream {
private:
struct CachedDataEntry {
int _offset;
@@ -169,16 +181,21 @@ private:
void updateFNumber();
protected:
/**
- * Write a byte to an Adlib register
+ * Queue a byte for an Adlib register
*/
void write(int reg, int val);
/**
- * Write a byte to an Adlib register, and store it in the _ports array
+ * Queue a byte for an Adlib register, and store it in the _ports array
*/
int write2(int state, int reg, int val);
/**
+ * Flush any pending Adlib register values to the OPL driver
+ */
+ void flush();
+
+ /**
* Turn a channel on
*/
void channelOn(int reg, int volume);
@@ -239,12 +256,15 @@ protected:
public:
Audio::Mixer *_mixer;
FM_OPL *_opl;
+ Audio::SoundHandle _soundHandle;
AdlibChannel _channels[ADLIB_CHANNEL_COUNT];
AdlibChannel *_activeChannelPtr;
AdlibChannelData _channelData[11];
Common::Array<AdlibSample> _samples;
AdlibSample *_samplePtr;
Common::File _soundFile;
+ Common::Queue<RegisterValue> _queue;
+ Common::Mutex _driverMutex;
int _dataOffset;
int _frameCounter;
bool _isDisabled;
@@ -268,6 +288,10 @@ public:
int _activeChannelReg;
int _v11;
bool _amDep, _vibDep, _splitPoint;
+ int _samplesPerCallback;
+ int _samplesPerCallbackRemainder;
+ int _samplesTillCallback;
+ int _samplesTillCallbackRemainder;
public:
/**
* Constructor
@@ -306,6 +330,27 @@ public:
* Return the current frame counter
*/
int getFrameCounter() { return _frameCounter; }
+
+ // AudioStream interface
+ /**
+ * Main buffer read
+ */
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+
+ /**
+ * Mono sound only
+ */
+ virtual bool isStereo() const { return false; }
+
+ /**
+ * Data is continuously pushed, so definitive end
+ */
+ virtual bool endOfData() const { return false; }
+
+ /**
+ * Return sample rate
+ */
+ virtual int getRate() const { return 11025; }
};
class ASound1: public ASound {