From 6ea51e8c4564004ce995f4a8e1c80fdd76562c8f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 20 Sep 2012 01:57:53 +0200 Subject: SCUMM: Implement support for special sfx in MI2 Mac. This also increases the savegame version, since it introduces a new Instrument subclass. --- engines/scumm/imuse/imuse_part.cpp | 13 ++++++++- engines/scumm/imuse/instrument.cpp | 60 ++++++++++++++++++++++++++++++++++++++ engines/scumm/imuse/instrument.h | 4 ++- engines/scumm/imuse/mac_m68k.cpp | 5 ++++ engines/scumm/imuse/mac_m68k.h | 3 +- engines/scumm/saveload.h | 2 +- 6 files changed, 83 insertions(+), 4 deletions(-) diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 73e7704469..d4e4740451 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -27,6 +27,7 @@ #include "common/util.h" #include "scumm/imuse/imuse_internal.h" #include "scumm/saveload.h" +#include "scumm/scumm.h" namespace Scumm { @@ -365,7 +366,17 @@ void Part::set_instrument(uint b) { _bank = (byte)(b >> 8); if (_bank) error("Non-zero instrument bank selection. Please report this"); - _instrument.program((byte)b, _player->isMT32()); + // HACK: Horrible hack to allow tracing of program change source. + // The Mac version of Monkey Island 2 uses a different program "bank" + // when it gets program change events through the iMuse SysEx handler. + // We emulate this by introducing a special instrument, which sets + // the instrument via sysEx_customInstrument. This seems to be + // exclusively used for special sound effects like the "spit" sound. + if (g_scumm->_game.id == GID_MONKEY2 && g_scumm->_game.platform == Common::kPlatformMacintosh) { + _instrument.macSfx(b); + } else { + _instrument.program((byte)b, _player->isMT32()); + } if (clearToTransmit()) _instrument.send(_mc); } diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp index 11bb4e7605..61c73b1e2d 100644 --- a/engines/scumm/imuse/instrument.cpp +++ b/engines/scumm/imuse/instrument.cpp @@ -278,6 +278,21 @@ private: byte _instrument[23]; }; +class Instrument_MacSfx : public InstrumentInternal { +private: + byte _program; + +public: + Instrument_MacSfx(byte program); + Instrument_MacSfx(Serializer *s); + void saveOrLoad(Serializer *s); + void send(MidiChannel *mc); + void copy_to(Instrument *dest) { dest->macSfx(_program); } + bool is_valid() { + return (_program < 128); + } +}; + //////////////////////////////////////// // // Instrument class members @@ -326,6 +341,14 @@ void Instrument::pcspk(const byte *instrument) { _instrument = new Instrument_PcSpk(instrument); } +void Instrument::macSfx(byte prog) { + clear(); + if (prog > 127) + return; + _type = itMacSfx; + _instrument = new Instrument_MacSfx(prog); +} + void Instrument::saveOrLoad(Serializer *s) { if (s->isSaving()) { s->saveByte(_type); @@ -349,6 +372,9 @@ void Instrument::saveOrLoad(Serializer *s) { case itPcSpk: _instrument = new Instrument_PcSpk(s); break; + case itMacSfx: + _instrument = new Instrument_MacSfx(s); + break; default: warning("No known instrument classification #%d", (int)_type); _type = itNone; @@ -528,4 +554,38 @@ void Instrument_PcSpk::send(MidiChannel *mc) { mc->sysEx_customInstrument('SPK ', (byte *)&_instrument); } +//////////////////////////////////////// +// +// Instrument_MacSfx class members +// +//////////////////////////////////////// + +Instrument_MacSfx::Instrument_MacSfx(byte program) : + _program(program) { + if (program > 127) { + _program = 255; + } +} + +Instrument_MacSfx::Instrument_MacSfx(Serializer *s) { + _program = 255; + if (!s->isSaving()) { + saveOrLoad(s); + } +} + +void Instrument_MacSfx::saveOrLoad(Serializer *s) { + if (s->isSaving()) { + s->saveByte(_program); + } else { + _program = s->loadByte(); + } +} + +void Instrument_MacSfx::send(MidiChannel *mc) { + if (_program > 127) { + return; + } + mc->sysEx_customInstrument('MAC ', &_program); +} } // End of namespace Scumm diff --git a/engines/scumm/imuse/instrument.h b/engines/scumm/imuse/instrument.h index a855c64155..7e09e86fa5 100644 --- a/engines/scumm/imuse/instrument.h +++ b/engines/scumm/imuse/instrument.h @@ -52,7 +52,8 @@ public: itProgram = 1, itAdLib = 2, itRoland = 3, - itPcSpk = 4 + itPcSpk = 4, + itMacSfx = 5 }; Instrument() : _type(0), _instrument(0) { } @@ -72,6 +73,7 @@ public: void adlib(const byte *instrument); void roland(const byte *instrument); void pcspk(const byte *instrument); + void macSfx(byte program); byte getType() { return _type; } bool isValid() { return (_instrument ? _instrument->is_valid() : false); } diff --git a/engines/scumm/imuse/mac_m68k.cpp b/engines/scumm/imuse/mac_m68k.cpp index 9d6bdd0544..4d7a6a64c0 100644 --- a/engines/scumm/imuse/mac_m68k.cpp +++ b/engines/scumm/imuse/mac_m68k.cpp @@ -111,6 +111,7 @@ void MacM68kDriver::send(uint32 d) { } void MacM68kDriver::sysEx_customInstrument(byte channel, uint32 type, const byte *instr) { + assert(false); } MidiChannel *MacM68kDriver::allocateChannel() { @@ -416,6 +417,10 @@ void MacM68kDriver::MidiChannel_MacM68k::priority(byte value) { } void MacM68kDriver::MidiChannel_MacM68k::sysEx_customInstrument(uint32 type, const byte *instr) { + assert(instr); + if (type == 'MAC ') { + _instrument = _owner->getInstrument(*instr + kSysExBase); + } } void MacM68kDriver::MidiChannel_MacM68k::init(MacM68kDriver *owner, byte channel) { diff --git a/engines/scumm/imuse/mac_m68k.h b/engines/scumm/imuse/mac_m68k.h index a8686e776f..59e2f68b9b 100644 --- a/engines/scumm/imuse/mac_m68k.h +++ b/engines/scumm/imuse/mac_m68k.h @@ -74,7 +74,8 @@ private: enum { kDefaultInstrument = 0x3E7, - kProgramChangeBase = 0x3E8 + kProgramChangeBase = 0x3E8, + kSysExBase = 0x7D0 }; Instrument getInstrument(int idx) const; diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index d5f7ea526e..a640bc1e17 100644 --- a/engines/scumm/saveload.h +++ b/engines/scumm/saveload.h @@ -47,7 +47,7 @@ namespace Scumm { * only saves/loads those which are valid for the version of the savegame * which is being loaded/saved currently. */ -#define CURRENT_VER 92 +#define CURRENT_VER 93 /** * An auxillary macro, used to specify savegame versions. We use this instead -- cgit v1.2.3