SCUMM: Implement support for special sfx in MI2 Mac.

This also increases the savegame version, since it introduces a new
Instrument subclass.
This commit is contained in:
Johannes Schickel 2012-09-20 01:57:53 +02:00
parent 58f542d434
commit 6ea51e8c45
6 changed files with 83 additions and 4 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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); }

View File

@ -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) {

View File

@ -74,7 +74,8 @@ private:
enum {
kDefaultInstrument = 0x3E7,
kProgramChangeBase = 0x3E8
kProgramChangeBase = 0x3E8,
kSysExBase = 0x7D0
};
Instrument getInstrument(int idx) const;

View File

@ -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