aboutsummaryrefslogtreecommitdiff
path: root/scumm/imuse.cpp
diff options
context:
space:
mode:
authorJamieson Christian2002-11-09 16:55:16 +0000
committerJamieson Christian2002-11-09 16:55:16 +0000
commit4fd2497a21e740856b741a8036dc07fae865008a (patch)
treef90ebb2701cfced76dced0ab4346327546a9a78e /scumm/imuse.cpp
parentcc14b87f25f13535bfd37d2f01a8dbebd1f34ea5 (diff)
downloadscummvm-rg350-4fd2497a21e740856b741a8036dc07fae865008a.tar.gz
scummvm-rg350-4fd2497a21e740856b741a8036dc07fae865008a.tar.bz2
scummvm-rg350-4fd2497a21e740856b741a8036dc07fae865008a.zip
New IMuseMonitor front-end provides thread-safe access into IMuse from scripts and the MIDI parser. This seems to effectively remove pointer corruption observed under IMuseGM, and also provides thread-safe access into IMuseAdlib.
This is an improved version of the mutex-based solution presented in Patch 615737. svn-id: r5474
Diffstat (limited to 'scumm/imuse.cpp')
-rw-r--r--scumm/imuse.cpp54
1 files changed, 52 insertions, 2 deletions
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp
index 3e52af7876..a7ec6e72b8 100644
--- a/scumm/imuse.cpp
+++ b/scumm/imuse.cpp
@@ -33,6 +33,7 @@
*/
#define TICKS_PER_BEAT 480
+// #define FORCE_MT32_SOUNDS // Use only if you are driving an actual MT-32 or compatible
#define IMUSE_SYSEX_ID 0x7D
#define ROLAND_SYSEX_ID 0x41
#define PERCUSSION_CHANNEL 9
@@ -43,6 +44,19 @@
#define MDPG_TAG "MDpg"
#define MDHD_TAG "MDhd"
+#ifdef FORCE_MT32_SOUNDS
+static const byte mt32_to_gmidi[128] = {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0x
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1x
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2x
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3x
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4x
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5x
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 6x
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127 // 7x
+};
+#else
/* Roland to General Midi patch table. Still needs some work. */
static const byte mt32_to_gmidi[128] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
@@ -55,12 +69,46 @@ static const byte mt32_to_gmidi[128] = {
61, 11, 11, 98, 14, 9, 14, 13, 12, 107, 107, 77, 78, 78, 76, 76, // 6x
47, 117, 127, 118, 118, 116, 115, 119, 115, 112, 55, 124, 123, 0, 14, 117 // 7x
};
+#endif
/* Put IMUSE specific classes here, instead of in a .h file
* they will only be used from this file, so it will reduce
* compile time */
+// IMuseMonitor serves as a front-end to IMuseInternal and
+// ensures that only one thread accesses the object at a time.
+// This is necessary to prevent scripts and the MIDI parser
+// from yanking objects out from underneath each other.
+class IMuseMonitor : public IMuse {
+private:
+ OSystem *_system;
+ IMuse *_target;
+ void *_mutex;
+
+ void in() { _system->lock_mutex (_mutex); }
+ void out() { _system->unlock_mutex (_mutex); }
+public:
+ IMuseMonitor (OSystem *system, IMuse *target) : _system (system), _target (target) { _mutex = system->create_mutex(); }
+ virtual ~IMuseMonitor() { _system->delete_mutex (_mutex); };
+
+ void on_timer() { in(); _target->on_timer(); out(); }
+ void pause(bool paused) { in(); _target->pause (paused); out(); }
+ int save_or_load(Serializer *ser, Scumm *scumm) { in(); int ret = _target->save_or_load (ser, scumm); out(); return ret; }
+ int set_music_volume(uint vol) { in(); int ret = _target->set_music_volume (vol); out(); return ret; }
+ int get_music_volume() { in(); int ret = _target->get_music_volume(); out(); return ret; }
+ int set_master_volume(uint vol) { in(); int ret = _target->set_master_volume (vol); out(); return ret; }
+ int get_master_volume() { in(); int ret = _target->get_master_volume(); out(); return ret; }
+ bool start_sound(int sound) { in(); bool ret = _target->start_sound (sound); out(); return ret; }
+ int stop_sound(int sound) { in(); int ret = _target->stop_sound (sound); out(); return ret; }
+ int stop_all_sounds() { in(); int ret = _target->stop_all_sounds(); out(); return ret; }
+ int get_sound_status(int sound) { in(); int ret = _target->get_sound_status (sound); out(); return ret; }
+ int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h) { in(); int32 ret = _target->do_command (a,b,c,d,e,f,g,h); out(); return ret; }
+ int clear_queue() { in(); int ret = _target->clear_queue(); out(); return ret; }
+ void setBase(byte **base) { in(); _target->setBase (base); out(); }
+ uint32 property(int prop, uint32 value) { in(); uint32 ret = _target->property (prop, value); out(); return ret; }
+};
+
class IMuseDriver;
struct Part;
@@ -4734,7 +4782,8 @@ int IMuseGM::midi_driver_thread(void *param)
cur_time = mid->_system->get_msecs();
while (old_time < cur_time) {
old_time += 10;
- mid->_se->on_timer();
+ //mid->_se->on_timer();
+ g_scumm->_imuse->on_timer();
}
}
@@ -4962,7 +5011,8 @@ void IMuseGM::part_off(Part *part)
// to the client.
IMuse *IMuse::create(OSystem *syst, MidiDriver *midi, SoundMixer *mixer)
{
- return (IMuse *) IMuseInternal::create (syst, midi, mixer);
+ IMuse *engine = (IMuse *) IMuseInternal::create (syst, midi, mixer);
+ return (IMuse *) new IMuseMonitor (syst, engine);
}