From 3fae9f17dacaa4f8253c2f6b47adb9845cdb52b0 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 5 Mar 2015 12:16:24 -0500 Subject: MADS: Show a warning if sound code reads beyond end of sound data blocks --- engines/mads/nebular/sound_nebular.cpp | 24 ++++++++++++++++++++++++ engines/mads/nebular/sound_nebular.h | 20 ++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp index 0a054440b2..d41d0075eb 100644 --- a/engines/mads/nebular/sound_nebular.cpp +++ b/engines/mads/nebular/sound_nebular.cpp @@ -36,6 +36,7 @@ namespace Nebular { bool AdlibChannel::_channelsEnabled; AdlibChannel::AdlibChannel() { + _owner = nullptr; _activeCount = 0; _field1 = 0; _field2 = 0; @@ -55,6 +56,7 @@ AdlibChannel::AdlibChannel() { _pSrc = nullptr; _ptr3 = nullptr; _ptr4 = nullptr; + _ptrEnd = nullptr; _field17 = 0; _field19 = 0; _soundData = nullptr; @@ -108,6 +110,9 @@ void AdlibChannel::load(byte *pData) { _fieldB = 0; _field17 = 0; _field19 = 0; + + CachedDataEntry &cacheEntry = _owner->getCachedData(pData); + _ptrEnd = cacheEntry._dataEnd; } void AdlibChannel::check(byte *nullPtr) { @@ -192,6 +197,9 @@ ASound::ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, _channelData[i]._freqBase = 0; _channelData[i]._field6 = 0; } + + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i]._owner = this; AdlibChannel::_channelsEnabled = false; @@ -283,6 +291,17 @@ void ASound::noise() { } } +CachedDataEntry &ASound::getCachedData(byte *pData) { + Common::List::iterator i; + for (i = _dataCache.begin(); i != _dataCache.end(); ++i) { + CachedDataEntry &e = *i; + if (e._data == pData) + return e; + } + + error("Could not find previously loaded data"); +} + void ASound::write(int reg, int val) { _queue.push(RegisterValue(reg, val)); } @@ -331,6 +350,7 @@ byte *ASound::loadData(int offset, int size) { CachedDataEntry rec; rec._offset = offset; rec._data = new byte[size]; + rec._dataEnd = rec._data + size - 1; _soundFile.seek(_dataOffset + offset); _soundFile.read(rec._data, size); _dataCache.push_back(rec); @@ -449,6 +469,10 @@ void ASound::pollActiveChannel() { warning("pollActiveChannel(): No data found for sound channel"); break; } + if (pSrc > chan->_ptrEnd) { + warning("Read beyond end of loaded sound data"); + } + if (!(*pSrc & 0x80) || (*pSrc <= 0xF0)) { if (updateFlag) updateActiveChannel(); diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h index ccfd40ad52..cfacb211a4 100644 --- a/engines/mads/nebular/sound_nebular.h +++ b/engines/mads/nebular/sound_nebular.h @@ -37,11 +37,15 @@ class SoundManager; namespace Nebular { +class ASound; + /** * Represents the data for a channel on the Adlib */ class AdlibChannel { public: + ASound *_owner; + int _activeCount; int _field1; int _field2; @@ -61,6 +65,7 @@ public: byte *_pSrc; byte *_ptr3; byte *_ptr4; + byte *_ptrEnd; int _field17; int _field19; byte *_soundData; @@ -128,15 +133,17 @@ struct RegisterValue { #define ADLIB_CHANNEL_MIDWAY 5 #define CALLBACKS_PER_SECOND 60 +struct CachedDataEntry { + int _offset; + byte *_data; + byte *_dataEnd; +}; + /** * Base class for the sound player resource files */ class ASound : public Audio::AudioStream { private: - struct CachedDataEntry { - int _offset; - byte *_data; - }; Common::List _dataCache; uint16 _randomSeed; @@ -350,6 +357,11 @@ public: */ int getFrameCounter() { return _frameCounter; } + /** + * Return the cached data block record for previously loaded sound data + */ + CachedDataEntry &getCachedData(byte *pData); + // AudioStream interface /** * Main buffer read -- cgit v1.2.3