diff options
author | Alejandro Marzini | 2010-07-30 05:28:09 +0000 |
---|---|---|
committer | Alejandro Marzini | 2010-07-30 05:28:09 +0000 |
commit | fb4086cadb8ce3e473dae40558d713e7a31b3858 (patch) | |
tree | 95c19d544da914c43a43f0538a1977f43e17cb39 /engines/sci/sound | |
parent | 7b070bbef8275ff25dfc2cbc3106acfdc8de74a5 (diff) | |
parent | a17e3c444917ca90dfd537c2102a6150e7ffe977 (diff) | |
download | scummvm-rg350-fb4086cadb8ce3e473dae40558d713e7a31b3858.tar.gz scummvm-rg350-fb4086cadb8ce3e473dae40558d713e7a31b3858.tar.bz2 scummvm-rg350-fb4086cadb8ce3e473dae40558d713e7a31b3858.zip |
Merged from trunk, from Rev 50841 to HEAD
svn-id: r51495
Diffstat (limited to 'engines/sci/sound')
-rw-r--r-- | engines/sci/sound/audio.cpp | 15 | ||||
-rw-r--r-- | engines/sci/sound/drivers/amigamac.cpp (renamed from engines/sci/sound/drivers/amiga.cpp) | 562 | ||||
-rw-r--r-- | engines/sci/sound/drivers/mididriver.h | 4 | ||||
-rw-r--r-- | engines/sci/sound/midiparser_sci.cpp | 6 | ||||
-rw-r--r-- | engines/sci/sound/music.cpp | 20 | ||||
-rw-r--r-- | engines/sci/sound/music.h | 2 | ||||
-rw-r--r-- | engines/sci/sound/soundcmd.cpp | 76 | ||||
-rw-r--r-- | engines/sci/sound/soundcmd.h | 2 |
8 files changed, 504 insertions, 183 deletions
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index d9e9d2e8db..640273c20e 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -35,6 +35,7 @@ #include "sound/audiostream.h" #include "sound/decoders/aiff.h" #include "sound/decoders/flac.h" +#include "sound/decoders/mac_snd.h" #include "sound/decoders/mp3.h" #include "sound/decoders/raw.h" #include "sound/decoders/vorbis.h" @@ -337,19 +338,9 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 } else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1 && READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) { // Mac snd detected - // See http://developer.apple.com/legacy/mac/library/documentation/mac/Sound/Sound-60.html#HEADING60-15 for more details + Common::MemoryReadStream *sndStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); - uint32 soundHeaderOffset = READ_BE_UINT32(audioRes->data + 16); - assert(READ_BE_UINT32(audioRes->data + soundHeaderOffset) == 0); - size = READ_BE_UINT32(audioRes->data + soundHeaderOffset + 4); - _audioRate = READ_BE_UINT16(audioRes->data + soundHeaderOffset + 8); // Really floating point, but we're just truncating - - if (*(audioRes->data + soundHeaderOffset + 20) != 0) - error("Unhandled Mac snd extended/compressed header"); - - data = (byte *)malloc(size); - memcpy(data, audioRes->data + soundHeaderOffset + 22, size); - flags = Audio::FLAG_UNSIGNED; + audioSeekStream = Audio::makeMacSndStream(sndStream, DisposeAfterUse::YES); } else { // SCI1 raw audio size = audioRes->size; diff --git a/engines/sci/sound/drivers/amiga.cpp b/engines/sci/sound/drivers/amigamac.cpp index 0413dbb79e..4fb9146b53 100644 --- a/engines/sci/sound/drivers/amiga.cpp +++ b/engines/sci/sound/drivers/amigamac.cpp @@ -25,6 +25,7 @@ #include "sound/softsynth/emumidi.h" #include "sci/sound/drivers/mididriver.h" +#include "sci/resource.h" #include "common/file.h" #include "common/frac.h" @@ -34,35 +35,14 @@ namespace Sci { /* #define DEBUG */ -// Frequencies for every note -// FIXME Store only one octave -static const int freq_table[] = { - 58, 62, 65, 69, 73, 78, 82, 87, - 92, 98, 104, 110, 117, 124, 131, 139, - 147, 156, 165, 175, 185, 196, 208, 220, - 234, 248, 262, 278, 294, 312, 331, 350, - 371, 393, 417, 441, 468, 496, 525, 556, - 589, 625, 662, 701, 743, 787, 834, 883, - 936, 992, 1051, 1113, 1179, 1250, 1324, 1403, - 1486, 1574, 1668, 1767, 1872, 1984, 2102, 2227, - 2359, 2500, 2648, 2806, 2973, 3149, 3337, 3535, - 3745, 3968, 4204, 4454, 4719, 5000, 5297, 5612, - 5946, 6299, 6674, 7071, 7491, 7937, 8408, 8908, - 9438, 10000, 10594, 11224, 11892, 12599, 13348, 14142, - 14983, 15874, 16817, 17817, 18877, 20000, 21189, 22449, - 23784, 25198, 26696, 28284, 29966, 31748, 33635, 35635, - 37754, 40000, 42378, 44898, 47568, 50396, 53393, 56568, - 59932, 63496, 67271, 71271, 75509, 80000, 84757, 89796 -}; - -class MidiDriver_Amiga : public MidiDriver_Emulated { +class MidiDriver_AmigaMac : public MidiDriver_Emulated { public: enum { kVoices = 4 }; - MidiDriver_Amiga(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { } - virtual ~MidiDriver_Amiga() { } + MidiDriver_AmigaMac(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { } + virtual ~MidiDriver_AmigaMac() { } // MidiDriver int open(); @@ -99,6 +79,7 @@ private: int instrument; int volume; int pan; + uint16 pitch; }; struct Envelope { @@ -121,7 +102,7 @@ private: frac_t rate; }; - struct Instrument { + struct InstrumentSample { char name[30]; int mode; int size; // Size of non-looping part in bytes @@ -130,35 +111,55 @@ private: Envelope envelope[4]; // Envelope int8 *samples; int8 *loop; + int16 startNote; + int16 endNote; + bool isUnsigned; + uint16 baseFreq; + uint16 baseNote; + int16 fixedNote; + }; + + class Instrument : public Common::Array<InstrumentSample *> { + public: + char name[30]; }; struct Bank { char name[30]; uint size; - Instrument *instruments[256]; + Common::Array<Instrument> instruments; }; + bool _isSci1; bool _playSwitch; int _masterVolume; int _frequency; Envelope _envDecay; Bank _bank; // Instrument bank + double _freqTable[48]; Channel _channels[MIDI_CHANNELS]; /* Internal channels */ Voice _voices[kChannels]; void setEnvelope(Voice *channel, Envelope *envelope, int phase); - int interpolate(int8 *samples, frac_t offset); + void setOutputFrac(int voice); + int interpolate(int8 *samples, frac_t offset, bool isUnsigned); void playInstrument(int16 *dest, Voice *channel, int count); void changeInstrument(int channel, int instrument); void stopChannel(int ch); void stopNote(int ch, int note); void startNote(int ch, int note, int velocity); - Instrument *readInstrument(Common::File &file, int *id); + InstrumentSample *findInstrument(int instrument, int note); + void pitchWheel(int ch, uint16 pitch); + + bool loadInstrumentsSCI0(Common::File &file); + bool loadInstrumentsSCI0Mac(Common::SeekableReadStream &file); + InstrumentSample *readInstrumentSCI0(Common::SeekableReadStream &file, int *id); + bool loadInstrumentsSCI1(Common::SeekableReadStream &file); }; -void MidiDriver_Amiga::setEnvelope(Voice *channel, Envelope *envelope, int phase) { +void MidiDriver_AmigaMac::setEnvelope(Voice *channel, Envelope *envelope, int phase) { channel->envelope = phase; channel->envelope_samples = envelope[phase].length; @@ -168,25 +169,32 @@ void MidiDriver_Amiga::setEnvelope(Voice *channel, Envelope *envelope, int phase channel->velocity = envelope[phase - 1].target; } -int MidiDriver_Amiga::interpolate(int8 *samples, frac_t offset) { +int MidiDriver_AmigaMac::interpolate(int8 *samples, frac_t offset, bool isUnsigned) { int x = fracToInt(offset); - int diff = (samples[x + 1] - samples[x]) << 8; + if (isUnsigned) { + int s1 = (byte)samples[x] - 0x80; + int s2 = (byte)samples[x + 1] - 0x80; + int diff = (s2 - s1) << 8; + return (s1 << 8) + fracToInt(diff * (offset & FRAC_LO_MASK)); + } + + int diff = (samples[x + 1] - samples[x]) << 8; return (samples[x] << 8) + fracToInt(diff * (offset & FRAC_LO_MASK)); } -void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) { +void MidiDriver_AmigaMac::playInstrument(int16 *dest, Voice *channel, int count) { int index = 0; int vol = _channels[channel->hw_channel].volume; - Instrument *instrument = _bank.instruments[channel->instrument]; + InstrumentSample *instrument = findInstrument(channel->instrument, channel->note); while (1) { /* Available source samples until end of segment */ frac_t lin_avail; - int seg_end, rem, i, amount; + uint32 seg_end, rem, i, amount; int8 *samples; - if (channel->looping) { + if (channel->looping && instrument->loop) { samples = instrument->loop; seg_end = instrument->loop_size; } else { @@ -208,11 +216,11 @@ void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) { amount = rem; /* Stop at next envelope event */ - if ((channel->envelope_samples != -1) && (amount > channel->envelope_samples)) + if ((channel->envelope_samples != -1) && (amount > (uint32)channel->envelope_samples)) amount = channel->envelope_samples; for (i = 0; i < amount; i++) { - dest[index++] = interpolate(samples, channel->offset) * channel->velocity / 64 * channel->note_velocity * vol / (127 * 127); + dest[index++] = interpolate(samples, channel->offset, instrument->isUnsigned) * channel->velocity / 64 * channel->note_velocity * vol / (127 * 127); channel->offset += channel->rate; } @@ -263,7 +271,7 @@ void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) { if (index == count) break; - if (fracToInt(channel->offset) >= seg_end) { + if ((uint32)fracToInt(channel->offset) >= seg_end) { if (instrument->mode & kModeLoop) { /* Loop the samples */ channel->offset -= intToFrac(seg_end); @@ -277,9 +285,9 @@ void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) { } } -void MidiDriver_Amiga::changeInstrument(int channel, int instrument) { +void MidiDriver_AmigaMac::changeInstrument(int channel, int instrument) { #ifdef DEBUG - if (_bank.instruments[instrument]) + if (_bank.instruments[instrument][0]) printf("[sfx:seq:amiga] Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument]->name, instrument); else warning("[sfx:seq:amiga] instrument %i does not exist (channel %i)", instrument, channel); @@ -287,7 +295,7 @@ void MidiDriver_Amiga::changeInstrument(int channel, int instrument) { _channels[channel].instrument = instrument; } -void MidiDriver_Amiga::stopChannel(int ch) { +void MidiDriver_AmigaMac::stopChannel(int ch) { int i; /* Start decay phase for note on this hw channel, if any */ @@ -300,9 +308,16 @@ void MidiDriver_Amiga::stopChannel(int ch) { } } -void MidiDriver_Amiga::stopNote(int ch, int note) { +void MidiDriver_AmigaMac::pitchWheel(int ch, uint16 pitch) { + _channels[ch].pitch = pitch; + + for (int i = 0; i < kChannels; i++) + if (_voices[i].note != -1 && _voices[i].hw_channel == ch) + setOutputFrac(i); +} + +void MidiDriver_AmigaMac::stopNote(int ch, int note) { int channel; - Instrument *instrument; for (channel = 0; channel < kChannels; channel++) if (_voices[channel].note == note && _voices[channel].hw_channel == ch && !_voices[channel].decay) @@ -315,15 +330,75 @@ void MidiDriver_Amiga::stopNote(int ch, int note) { return; } - instrument = _bank.instruments[_voices[channel].instrument]; + InstrumentSample *instrument = findInstrument(_voices[channel].instrument, note); + + // FIXME: SCI1 envelope support is not perfect yet /* Start the envelope phases for note-off if looping is on and envelope is enabled */ if ((instrument->mode & kModeLoop) && (instrument->envelope[0].length != 0)) setEnvelope(&_voices[channel], instrument->envelope, 2); } -void MidiDriver_Amiga::startNote(int ch, int note, int velocity) { - Instrument *instrument; +MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::findInstrument(int instrument, int note) { + if ((uint)instrument >= _bank.instruments.size()) + return 0; + + for (uint32 i = 0; i < _bank.instruments[instrument].size(); i++) { + InstrumentSample *sample = _bank.instruments[instrument][i]; + if (note >= sample->startNote && note <= sample->endNote) + return sample; + } + + return 0; +} + +void MidiDriver_AmigaMac::setOutputFrac(int voice) { + InstrumentSample *instrument = findInstrument(_voices[voice].instrument, _voices[voice].note); + + int fnote = 0; + + if (instrument->fixedNote == -1) { + fnote = _voices[voice].note; + + // Handle SCI0-style transposing here + if (!_isSci1) + fnote += instrument->transpose; + + if (fnote < 0 || fnote > 127) { + warning("[sfx:seq:amiga] illegal note %i", fnote); + return; + } + } else + fnote = instrument->fixedNote; + + // Compute rate for note + int mulFact = 1, divFact = 1; + + fnote -= instrument->baseNote; + fnote *= 4; + // FIXME: check how SSCI maps this + fnote += (_channels[_voices[voice].hw_channel].pitch - 0x2000) / 169; + + while (fnote < 0) { + divFact *= 2; + fnote += 12 * 4; + } + + while (fnote >= 12 * 4) { + mulFact *= 2; + fnote -= 12 * 4; + } + + double freq = _freqTable[fnote] * instrument->baseFreq * mulFact / divFact; + + // Handle SCI1-style transposing here + if (instrument->transpose && _isSci1) + freq = freq + ((_freqTable[4] - 1.0) * freq * (double)instrument->transpose / (double)16); + + _voices[voice].rate = doubleToFrac(freq / _frequency); +} + +void MidiDriver_AmigaMac::startNote(int ch, int note, int velocity) { int channel; if (_channels[ch].instrument < 0 || _channels[ch].instrument > 255) { @@ -331,7 +406,7 @@ void MidiDriver_Amiga::startNote(int ch, int note, int velocity) { return; } - instrument = _bank.instruments[_channels[ch].instrument]; + InstrumentSample *instrument = findInstrument(_channels[ch].instrument, note); if (!instrument) { warning("[sfx:seq:amiga] instrument %i does not exist", _channels[ch].instrument); @@ -349,19 +424,6 @@ void MidiDriver_Amiga::startNote(int ch, int note, int velocity) { stopChannel(ch); - if (instrument->mode & kModePitch) { - int fnote = note + instrument->transpose; - - if (fnote < 0 || fnote > 127) { - warning("[sfx:seq:amiga] illegal note %i\n", fnote); - return; - } - - /* Compute rate for note */ - _voices[channel].rate = doubleToFrac(freq_table[fnote] / (double) _frequency); - } else - _voices[channel].rate = doubleToFrac(kBaseFreq / (double) _frequency); - _voices[channel].instrument = _channels[ch].instrument; _voices[channel].note = note; _voices[channel].note_velocity = velocity; @@ -377,30 +439,34 @@ void MidiDriver_Amiga::startNote(int ch, int note, int velocity) { _voices[channel].hw_channel = ch; _voices[channel].decay = 0; _voices[channel].looping = 0; + setOutputFrac(channel); } -MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &file, int *id) { - Instrument *instrument; +MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(Common::SeekableReadStream &file, int *id) { byte header[61]; - int size; - int seg_size[3]; - int loop_offset; - int i; if (file.read(header, 61) < 61) { warning("[sfx:seq:amiga] failed to read instrument header"); return NULL; } - instrument = new Instrument; - + int seg_size[3]; seg_size[0] = READ_BE_UINT16(header + 35) * 2; seg_size[1] = READ_BE_UINT16(header + 41) * 2; seg_size[2] = READ_BE_UINT16(header + 47) * 2; + InstrumentSample *instrument = new InstrumentSample; + + instrument->startNote = 0; + instrument->endNote = 127; + instrument->isUnsigned = false; + instrument->baseFreq = kBaseFreq; + instrument->baseNote = 101; + instrument->fixedNote = 101; + instrument->mode = header[33]; instrument->transpose = (int8) header[34]; - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { int length = (int8) header[49 + i]; if (length == 0 && i > 0) @@ -413,13 +479,14 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil /* Final target must be 0 */ instrument->envelope[3].target = 0; - loop_offset = READ_BE_UINT32(header + 37) & ~1; - size = seg_size[0] + seg_size[1] + seg_size[2]; + int loop_offset = READ_BE_UINT32(header + 37) & ~1; + int size = seg_size[0] + seg_size[1] + seg_size[2]; *id = READ_BE_UINT16(header); strncpy(instrument->name, (char *) header + 2, 29); instrument->name[29] = 0; + #ifdef DEBUG printf("[sfx:seq:amiga] Reading instrument %i: \"%s\" (%i bytes)\n", *id, instrument->name, size); @@ -429,6 +496,7 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil printf(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]); printf(" Segment offsets: 0 %i %i\n", loop_offset, read_int32(header + 43)); #endif + instrument->samples = (int8 *) malloc(size + 1); if (file.read(instrument->samples, size) < (unsigned int)size) { warning("[sfx:seq:amiga] failed to read instrument samples"); @@ -437,6 +505,9 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil return NULL; } + if (instrument->mode & kModePitch) + instrument->fixedNote = -1; + if (instrument->mode & kModeLoop) { if (loop_offset + seg_size[1] > size) { #ifdef DEBUG @@ -463,6 +534,7 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil instrument->loop[instrument->loop_size] = instrument->loop[0]; } else { instrument->loop = NULL; + instrument->loop_size = 0; instrument->size = size; instrument->samples[instrument->size] = 0; } @@ -470,7 +542,7 @@ MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &fil return instrument; } -uint32 MidiDriver_Amiga::property(int prop, uint32 param) { +uint32 MidiDriver_AmigaMac::property(int prop, uint32 param) { switch(prop) { case MIDI_PROP_MASTER_VOLUME: if (param != 0xffff) @@ -482,28 +554,17 @@ uint32 MidiDriver_Amiga::property(int prop, uint32 param) { return 0; } -int MidiDriver_Amiga::open() { +int MidiDriver_AmigaMac::open() { + _isSci1 = false; + + for (int i = 0; i < 48; i++) + _freqTable[i] = pow(2, i / (double)48); + _frequency = _mixer->getOutputRate(); _envDecay.length = _frequency / (32 * 64); _envDecay.delta = 1; _envDecay.target = 0; - Common::File file; - byte header[40]; - - if (!file.open("bank.001")) { - warning("[sfx:seq:amiga] file bank.001 not found"); - return Common::kUnknownError; - } - - if (file.read(header, 40) < 40) { - warning("[sfx:seq:amiga] failed to read header of file bank.001"); - return Common::kUnknownError; - } - - for (uint i = 0; i < 256; i++) - _bank.instruments[i] = NULL; - for (uint i = 0; i < kChannels; i++) { _voices[i].note = -1; _voices[i].hw_channel = 0; @@ -513,32 +574,46 @@ int MidiDriver_Amiga::open() { _channels[i].instrument = -1; _channels[i].volume = 127; _channels[i].pan = (i % 4 == 0 || i % 4 == 3 ? kPanLeft : kPanRight); + _channels[i].pitch = 0x2000; } - _bank.size = READ_BE_UINT16(header + 38); - strncpy(_bank.name, (char *) header + 8, 29); - _bank.name[29] = 0; -#ifdef DEBUG - printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name); -#endif - - for (uint i = 0; i < _bank.size; i++) { - int id; - Instrument *instrument = readInstrument(file, &id); + Common::File file; - if (!instrument) { - warning("[sfx:seq:amiga] failed to read bank.001"); + if (file.open("bank.001")) { + if (!loadInstrumentsSCI0(file)) { + file.close(); return Common::kUnknownError; } + file.close(); + } else { + ResourceManager *resMan = g_sci->getResMan(); - if (id < 0 || id > 255) { - warning("[sfx:seq:amiga] Error: instrument ID out of bounds"); + Resource *resource = resMan->findResource(ResourceId(kResourceTypePatch, 7), false); + if (!resource) + resource = resMan->findResource(ResourceId(kResourceTypePatch, 9), false); + + // If we have a patch by this point, it's SCI1 + if (resource) + _isSci1 = true; + + // Check for the SCI0 Mac patch + if (!resource) + resource = resMan->findResource(ResourceId(kResourceTypePatch, 200), false); + + if (!resource) { + warning("Could not open patch for Amiga sound driver"); return Common::kUnknownError; } - _bank.instruments[id] = instrument; - } + Common::MemoryReadStream stream(resource->data, resource->size); + if (_isSci1) { + if (!loadInstrumentsSCI1(stream)) + return Common::kUnknownError; + } else if (!loadInstrumentsSCI0Mac(stream)) + return Common::kUnknownError; + } + MidiDriver_Emulated::open(); _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO); @@ -546,28 +621,30 @@ int MidiDriver_Amiga::open() { return Common::kNoError; } -void MidiDriver_Amiga::close() { +void MidiDriver_AmigaMac::close() { _mixer->stopHandle(_mixerSoundHandle); for (uint i = 0; i < _bank.size; i++) { - if (_bank.instruments[i]) { - if (_bank.instruments[i]->loop) - free(_bank.instruments[i]->loop); - free(_bank.instruments[i]->samples); - delete _bank.instruments[i]; + for (uint32 j = 0; j < _bank.instruments[i].size(); j++) { + if (_bank.instruments[i][j]) { + if (_bank.instruments[i][j]->loop) + free(_bank.instruments[i][j]->loop); + free(_bank.instruments[i][j]->samples); + delete _bank.instruments[i][j]; + } } } } -void MidiDriver_Amiga::playSwitch(bool play) { +void MidiDriver_AmigaMac::playSwitch(bool play) { _playSwitch = play; } -void MidiDriver_Amiga::setVolume(byte volume_) { +void MidiDriver_AmigaMac::setVolume(byte volume_) { _masterVolume = volume_; } -void MidiDriver_Amiga::send(uint32 b) { +void MidiDriver_AmigaMac::send(uint32 b) { byte command = b & 0xf0; byte channel = b & 0xf; byte op1 = (b >> 8) & 0xff; @@ -603,12 +680,15 @@ void MidiDriver_Amiga::send(uint32 b) { case 0xc0: changeInstrument(channel, op1); break; + case 0xe0: + pitchWheel(channel, (op2 << 7) | op1); + break; default: warning("[sfx:seq:amiga] unknown event %02x", command); } } -void MidiDriver_Amiga::generateSamples(int16 *data, int len) { +void MidiDriver_AmigaMac::generateSamples(int16 *data, int len) { if (len == 0) return; @@ -651,24 +731,256 @@ void MidiDriver_Amiga::generateSamples(int16 *data, int len) { free(buffers); } -class MidiPlayer_Amiga : public MidiPlayer { +bool MidiDriver_AmigaMac::loadInstrumentsSCI0(Common::File &file) { + _isSci1 = false; + + byte header[40]; + + if (file.read(header, 40) < 40) { + warning("[sfx:seq:amiga] failed to read header of file bank.001"); + return false; + } + + _bank.size = READ_BE_UINT16(header + 38); + strncpy(_bank.name, (char *) header + 8, 29); + _bank.name[29] = 0; +#ifdef DEBUG + printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name); +#endif + + for (uint i = 0; i < _bank.size; i++) { + int id; + InstrumentSample *instrument = readInstrumentSCI0(file, &id); + + if (!instrument) { + warning("[sfx:seq:amiga] failed to read bank.001"); + return false; + } + + if (id < 0 || id > 255) { + warning("[sfx:seq:amiga] Error: instrument ID out of bounds"); + return false; + } + + if ((uint)id >= _bank.instruments.size()) + _bank.instruments.resize(id + 1); + + _bank.instruments[id].push_back(instrument); + memcpy(_bank.instruments[id].name, instrument->name, sizeof(instrument->name)); + } + + return true; +} + +bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &file) { + byte header[40]; + + if (file.read(header, 40) < 40) { + warning("[sfx:seq:amiga] failed to read header of file patch.200"); + return false; + } + + _bank.size = 128; + strncpy(_bank.name, (char *) header + 8, 29); + _bank.name[29] = 0; +#ifdef DEBUG + printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name); +#endif + + Common::Array<uint32> instrumentOffsets; + instrumentOffsets.resize(_bank.size); + _bank.instruments.resize(_bank.size); + + for (uint32 i = 0; i < _bank.size; i++) + instrumentOffsets[i] = file.readUint32BE(); + + for (uint i = 0; i < _bank.size; i++) { + // 0 signifies it doesn't exist + if (instrumentOffsets[i] == 0) + continue; + + file.seek(instrumentOffsets[i]); + + uint16 id = file.readUint16BE(); + if (id != i) + error("Instrument number mismatch"); + + InstrumentSample *instrument = new InstrumentSample; + + instrument->startNote = 0; + instrument->endNote = 127; + instrument->isUnsigned = true; + instrument->baseFreq = kBaseFreq; + instrument->baseNote = 101; + instrument->fixedNote = 101; + instrument->mode = file.readUint16BE(); + + // Read in the offsets + int32 seg_size[3]; + seg_size[0] = file.readUint32BE(); + seg_size[1] = file.readUint32BE(); + seg_size[2] = file.readUint32BE(); + + instrument->transpose = file.readUint16BE(); + + for (byte j = 0; j < 4; j++) { + int length = (int8)file.readByte(); + + if (length == 0 && j > 0) + length = 256; + + instrument->envelope[j].length = length * _frequency / 60; + instrument->envelope[j].delta = (int8)file.readByte(); + instrument->envelope[j].target = file.readByte(); + } + + // Final target must be 0 + instrument->envelope[3].target = 0; + + file.read(instrument->name, 30); + + if (instrument->mode & kModePitch) + instrument->fixedNote = -1; + + uint32 size = seg_size[2]; + uint32 loop_offset = seg_size[0]; + + instrument->samples = (int8 *)malloc(size + 1); + if (file.read(instrument->samples, size) < size) { + warning("[sfx:seq:amiga] failed to read instrument sample"); + free(instrument->samples); + delete instrument; + continue; + } + + if (instrument->mode & kModeLoop) { + instrument->size = seg_size[0]; + instrument->loop_size = seg_size[1] - seg_size[0]; + + instrument->loop = (int8*)malloc(instrument->loop_size + 1); + memcpy(instrument->loop, instrument->samples + loop_offset, instrument->loop_size); + + instrument->samples[instrument->size] = instrument->loop[0]; + instrument->loop[instrument->loop_size] = instrument->loop[0]; + } else { + instrument->loop = NULL; + instrument->loop_size = 0; + instrument->size = size; + instrument->samples[instrument->size] = (int8)0x80; + } + + _bank.instruments[id].push_back(instrument); + memcpy(_bank.instruments[id].name, instrument->name, sizeof(instrument->name)); + } + + return true; +} + +bool MidiDriver_AmigaMac::loadInstrumentsSCI1(Common::SeekableReadStream &file) { + _bank.size = 128; + + Common::Array<uint32> instrumentOffsets; + instrumentOffsets.resize(_bank.size); + _bank.instruments.resize(_bank.size); + + for (uint32 i = 0; i < _bank.size; i++) + instrumentOffsets[i] = file.readUint32BE(); + + for (uint32 i = 0; i < _bank.size; i++) { + // 0 signifies it doesn't exist + if (instrumentOffsets[i] == 0) + continue; + + file.seek(instrumentOffsets[i]); + + // Read in the instrument name + file.read(_bank.instruments[i].name, 10); // last two bytes are always 0 + + for (uint32 j = 0; ; j++) { + InstrumentSample *sample = new InstrumentSample; + memset(sample, 0, sizeof(InstrumentSample)); + + sample->startNote = file.readSint16BE(); + + // startNote being -1 signifies we're done with this instrument + if (sample->startNote == -1) { + delete sample; + break; + } + + sample->endNote = file.readSint16BE(); + uint32 samplePtr = file.readUint32BE(); + sample->transpose = file.readSint16BE(); + for (int env = 0; env < 3; env++) { + sample->envelope[env].length = file.readByte() * _frequency / 60; + sample->envelope[env].delta = (env == 0 ? 10 : -10); + sample->envelope[env].target = file.readByte(); + } + + sample->envelope[3].length = 0; + sample->fixedNote = file.readSint16BE(); + int16 loop = file.readSint16BE(); + uint32 nextSamplePos = file.pos(); + + file.seek(samplePtr); + file.read(sample->name, 8); + + sample->isUnsigned = file.readUint16BE() == 0; + uint16 phase1Offset = file.readUint16BE(); + uint16 phase1End = file.readUint16BE(); + uint16 phase2Offset = file.readUint16BE(); + uint16 phase2End = file.readUint16BE(); + sample->baseNote = file.readUint16BE(); + uint32 periodTableOffset = file.readUint32BE(); + uint32 sampleDataPos = file.pos(); + + sample->size = phase1End - phase1Offset + 1; + sample->loop_size = phase2End - phase2Offset + 1; + + sample->samples = (int8 *)malloc(sample->size + 1); + file.seek(phase1Offset + sampleDataPos); + file.read(sample->samples, sample->size); + sample->samples[sample->size] = (sample->isUnsigned ? (int8)0x80 : 0); + + if (loop == 0 && sample->loop_size > 1) { + sample->loop = (int8 *)malloc(sample->loop_size + 1); + file.seek(phase2Offset + sampleDataPos); + file.read(sample->loop, sample->loop_size); + sample->mode |= kModeLoop; + sample->samples[sample->size] = sample->loop[0]; + sample->loop[sample->loop_size] = sample->loop[0]; + } + + _bank.instruments[i].push_back(sample); + + file.seek(periodTableOffset + 0xe0); + sample->baseFreq = file.readUint16BE(); + + file.seek(nextSamplePos); + } + } + + return true; +} + +class MidiPlayer_AmigaMac : public MidiPlayer { public: - MidiPlayer_Amiga(SciVersion version) : MidiPlayer(version) { _driver = new MidiDriver_Amiga(g_system->getMixer()); } + MidiPlayer_AmigaMac(SciVersion version) : MidiPlayer(version) { _driver = new MidiDriver_AmigaMac(g_system->getMixer()); } byte getPlayId(); - int getPolyphony() const { return MidiDriver_Amiga::kVoices; } + int getPolyphony() const { return MidiDriver_AmigaMac::kVoices; } bool hasRhythmChannel() const { return false; } - void setVolume(byte volume) { static_cast<MidiDriver_Amiga *>(_driver)->setVolume(volume); } - void playSwitch(bool play) { static_cast<MidiDriver_Amiga *>(_driver)->playSwitch(play); } + void setVolume(byte volume) { static_cast<MidiDriver_AmigaMac *>(_driver)->setVolume(volume); } + void playSwitch(bool play) { static_cast<MidiDriver_AmigaMac *>(_driver)->playSwitch(play); } void loadInstrument(int idx, byte *data); }; -MidiPlayer *MidiPlayer_Amiga_create(SciVersion version) { - return new MidiPlayer_Amiga(version); +MidiPlayer *MidiPlayer_AmigaMac_create(SciVersion version) { + return new MidiPlayer_AmigaMac(version); } -byte MidiPlayer_Amiga::getPlayId() { - if (_version != SCI_VERSION_0_LATE) - error("Amiga sound support not available for this SCI version"); +byte MidiPlayer_AmigaMac::getPlayId() { + if (_version > SCI_VERSION_0_LATE) + return 0x06; return 0x40; } diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h index 58803db260..2db6f25c70 100644 --- a/engines/sci/sound/drivers/mididriver.h +++ b/engines/sci/sound/drivers/mididriver.h @@ -86,7 +86,7 @@ public: virtual byte getPlayId() = 0; virtual int getPolyphony() const = 0; - virtual int getFirstChannel() { return 0; }; + virtual int getFirstChannel() { return 0; } virtual void setVolume(byte volume) { if(_driver) @@ -113,7 +113,7 @@ protected: }; extern MidiPlayer *MidiPlayer_AdLib_create(SciVersion version); -extern MidiPlayer *MidiPlayer_Amiga_create(SciVersion version); +extern MidiPlayer *MidiPlayer_AmigaMac_create(SciVersion version); extern MidiPlayer *MidiPlayer_PCJr_create(SciVersion version); extern MidiPlayer *MidiPlayer_PCSpeaker_create(SciVersion version); extern MidiPlayer *MidiPlayer_Midi_create(SciVersion version); diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index cc09ba79f0..e58fa5120b 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -475,7 +475,7 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to // get immediately removed, so we currently filter it. // Sierra SCI ignores them as well at that time - if (_position._play_tick) { + if ((_position._play_tick) || (info.delta)) { _signalSet = true; _signalToSet = info.basic.param1; } @@ -516,10 +516,11 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { break; case SCI_VERSION_1_EARLY: case SCI_VERSION_1_LATE: + case SCI_VERSION_2_1: _dataincToAdd = 1; break; default: - break; + error("unsupported _soundVersion"); } break; case kResetOnPause: @@ -672,6 +673,7 @@ void MidiParser_SCI::setVolume(byte volume) { case SCI_VERSION_1_EARLY: case SCI_VERSION_1_LATE: + case SCI_VERSION_2_1: // Send previous channel volumes again to actually update the volume for (int i = 0; i < 15; i++) if (_channelRemap[i] != -1) diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 55a7e1fdc4..c3315bd2b5 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -63,23 +63,15 @@ void SciMusic::init() { // SCI sound init _dwTempo = 0; - // Default to MIDI in SCI32 games, as many don't have AdLib support. - // WORKAROUND: Default to MIDI in Amiga SCI1_EGA+ games as we don't support - // those patches yet. We also don't yet support the 7.pat file of SCI1+ Mac - // games or SCI0 Mac patches, so we default to MIDI in those games to let - // them run. + // Default to MIDI in SCI2.1+ games, as many don't have AdLib support. Common::Platform platform = g_sci->getPlatform(); - uint32 dev = MidiDriver::detectDevice( - (getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || - (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) - ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM) - : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); + uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2_1) ? (MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM) : (MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI)); switch (MidiDriver::getMusicType(dev)) { case MT_ADLIB: // FIXME: There's no Amiga sound option, so we hook it up to AdLib - if (g_sci->getPlatform() == Common::kPlatformAmiga) - _pMidiDrv = MidiPlayer_Amiga_create(_soundVersion); + if (g_sci->getPlatform() == Common::kPlatformAmiga || platform == Common::kPlatformMacintosh) + _pMidiDrv = MidiPlayer_AmigaMac_create(_soundVersion); else _pMidiDrv = MidiPlayer_AdLib_create(_soundVersion); break; @@ -410,6 +402,8 @@ void SciMusic::soundStop(MusicEntry *pSnd) { pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } + + pSnd->fadeStep = 0; // end fading, if fading was in progress } void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) { @@ -604,7 +598,7 @@ MusicEntry::MusicEntry() { priority = 0; loop = 0; volume = MUSIC_VOLUME_DEFAULT; - hold = 0; + hold = -1; pauseCounter = 0; sampleLoopCounter = 0; diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 943a5bd2a8..37e3c30030 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -71,7 +71,7 @@ public: byte priority; uint16 loop; int16 volume; - byte hold; + int16 hold; int16 pauseCounter; uint sampleLoopCounter; diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 51832af09f..bd88a5fca8 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -33,9 +33,6 @@ namespace Sci { -#define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */ -#define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */ - SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) : _resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) { @@ -48,6 +45,7 @@ SoundCommandParser::~SoundCommandParser() { } reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) { + debugC(2, kDebugLevelSound, "kDoSound(init): %04x:%04x", PRINT_REG(argv[0])); processInitSound(argv[0]); return acc; } @@ -73,8 +71,8 @@ void SoundCommandParser::processInitSound(reg_t obj) { if (_soundVersion >= SCI_VERSION_1_EARLY) newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX); - debugC(2, kDebugLevelSound, "kDoSound(init): number %d, loop %d, prio %d, vol %d", resourceId, - newSound->loop, newSound->priority, newSound->volume); + debugC(2, kDebugLevelSound, "kDoSound(init): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), + resourceId, newSound->loop, newSound->priority, newSound->volume); // In SCI1.1 games, sound effects are started from here. If we can find // a relevant audio resource, play it, otherwise switch to synthesized @@ -105,6 +103,7 @@ void SoundCommandParser::processInitSound(reg_t obj) { } reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { + debugC(2, kDebugLevelSound, "kDoSound(play): %04x:%04x", PRINT_REG(argv[0])); processPlaySound(argv[0]); return acc; } @@ -142,8 +141,8 @@ void SoundCommandParser::processPlaySound(reg_t obj) { if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); - debugC(2, kDebugLevelSound, "kDoSound(play): number %d, loop %d, prio %d, vol %d", resourceId, - musicSlot->loop, musicSlot->priority, musicSlot->volume); + debugC(2, kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj), + resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume); _music->soundPlay(musicSlot); } @@ -154,6 +153,7 @@ reg_t SoundCommandParser::kDoSoundDummy(int argc, reg_t *argv, reg_t acc) { } reg_t SoundCommandParser::kDoSoundDispose(int argc, reg_t *argv, reg_t acc) { + debugC(2, kDebugLevelSound, "kDoSound(dispose): %04x:%04x", PRINT_REG(argv[0])); processDisposeSound(argv[0]); return acc; } @@ -176,6 +176,7 @@ void SoundCommandParser::processDisposeSound(reg_t obj) { } reg_t SoundCommandParser::kDoSoundStop(int argc, reg_t *argv, reg_t acc) { + debugC(2, kDebugLevelSound, "kDoSound(stop): %04x:%04x", PRINT_REG(argv[0])); processStopSound(argv[0], false); return acc; } @@ -209,6 +210,11 @@ void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) } reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { + if (argc == 1) + debugC(2, kDebugLevelSound, "kDoSound(pause): %04x:%04x", PRINT_REG(argv[0])); + else + debugC(2, kDebugLevelSound, "kDoSound(pause): %04x:%04x, %04x:%04x", PRINT_REG(argv[0]), PRINT_REG(argv[1])); + if (_soundVersion <= SCI_VERSION_0_LATE) { // SCI0 games give us 0/1 for either resuming or pausing the current music // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume @@ -250,26 +256,18 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { } // SCI0 only command -reg_t SoundCommandParser::kDoSoundResume(int argc, reg_t *argv, reg_t acc) { - // this doesn't seem to do what we think it's doing - // it's called with no arguments at all (just restore a game in qfg1) - return acc; - reg_t obj = argv[0]; - - MusicEntry *musicSlot = _music->getSlot(obj); - if (!musicSlot) { - warning("kDoSound(resume):: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return acc; - } - - writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); - _music->soundResume(musicSlot); +// It's called right after restoring a game - it's responsible to kick off playing music again +// we don't need this at all, so we don't do anything here +reg_t SoundCommandParser::kDoSoundResumeAfterRestore(int argc, reg_t *argv, reg_t acc) { return acc; } reg_t SoundCommandParser::kDoSoundMute(int argc, reg_t *argv, reg_t acc) { - if (argc > 0) + if (argc > 0) { + debugC(2, kDebugLevelSound, "kDoSound(mute): %d", argv[0].toUint16()); _music->soundSetSoundOn(argv[0].toUint16()); + } + return make_reg(0, _music->soundGetSoundOn()); } @@ -300,7 +298,7 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { // If sound is not playing currently, set signal directly if (musicSlot->status != kSoundPlaying) { - debugC(2, kDebugLevelSound, "kDoSound(fade): fading requested, but sound is currently not playing"); + debugC(2, kDebugLevelSound, "kDoSound(fade): %04x:%04x fading requested, but sound is currently not playing", PRINT_REG(obj)); writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); return acc; } @@ -328,7 +326,7 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { error("kDoSound(fade): unsupported argc %d", argc); } - debugC(2, kDebugLevelSound, "kDoSound(fade): to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); + debugC(2, kDebugLevelSound, "kDoSound(fade): %04x:%04x to %d, step %d, ticker %d", PRINT_REG(obj), musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); return acc; } @@ -339,6 +337,8 @@ reg_t SoundCommandParser::kDoSoundGetPolyphony(int argc, reg_t *argv, reg_t acc) reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; + debugC(2, kDebugLevelSound, "kDoSound(update): %04x:%04x", PRINT_REG(argv[0])); + MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(update): Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -379,9 +379,13 @@ void SoundCommandParser::processUpdateCues(reg_t obj) { musicSlot->loop -= currentLoopCounter - musicSlot->sampleLoopCounter; musicSlot->sampleLoopCounter = currentLoopCounter; } - if ((!_music->soundIsActive(musicSlot)) && (musicSlot->status != kSoundPaused)) { - processStopSound(obj, true); - } else { + if (musicSlot->status == kSoundPlaying) { + if (!_music->soundIsActive(musicSlot)) { + processStopSound(obj, true); + } else { + _music->updateAudioStreamTicker(musicSlot); + } + } else if (musicSlot->status == kSoundPaused) { _music->updateAudioStreamTicker(musicSlot); } // We get a flag from MusicEntry::doFade() here to set volume for the stream @@ -443,9 +447,15 @@ reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { byte channel = argv[1].toUint16() & 0xf; byte midiCmd = argv[2].toUint16() & 0xff; + // TODO: first there is a 4-parameter variant of this call which needs to get reversed + // second the current code isn't 100% accurate, sierra sci does checks on the 4th parameter + if (argc == 4) + return acc; + uint16 controller = argv[3].toUint16(); uint16 param = argv[4].toUint16(); + debugC(2, kDebugLevelSound, "kDoSound(sendMidi): %04x:%04x, %d, %d, %d, %d", PRINT_REG(obj), channel, midiCmd, controller, param); if (channel) channel--; // channel is given 1-based, we are using 0-based @@ -464,6 +474,7 @@ reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { } reg_t SoundCommandParser::kDoSoundReverb(int argc, reg_t *argv, reg_t acc) { + debugC(2, kDebugLevelSound, "doSoundReverb: %d", argv[0].toUint16() & 0xF); _music->setReverb(argv[0].toUint16() & 0xF); return acc; } @@ -471,6 +482,8 @@ reg_t SoundCommandParser::kDoSoundReverb(int argc, reg_t *argv, reg_t acc) { reg_t SoundCommandParser::kDoSoundSetHold(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; + debugC(2, kDebugLevelSound, "doSoundSetHold: %04x:%04x, %d", PRINT_REG(argv[0]), argv[1].toUint16()); + MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(setHold): Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -488,6 +501,11 @@ reg_t SoundCommandParser::kDoSoundGetAudioCapability(int argc, reg_t *argv, reg_ } reg_t SoundCommandParser::kDoSoundStopAll(int argc, reg_t *argv, reg_t acc) { + // TODO: this can't be right, this gets called in kq1 - e.g. being in witch house, getting the note + // now the point jingle plays and after a messagebox they call this - and would stop the background effects with it + // this doesn't make sense, so i disable it for now + return acc; + Common::StackLock(_music->_mutex); const MusicList::iterator end = _music->getPlayListEnd(); @@ -535,6 +553,8 @@ reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) reg_t obj = argv[0]; int16 value = argv[1].toSint16(); + debugC(2, kDebugLevelSound, "kDoSound(setPriority): %04x:%04x, %d", PRINT_REG(obj), value); + MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -565,6 +585,8 @@ reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; int16 value = argv[1].toSint16(); + debugC(2, kDebugLevelSound, "kDoSound(setLoop): %04x:%04x, %d", PRINT_REG(obj), value); + MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Apparently, it's perfectly normal for a game to call cmdSetSoundLoop diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index a8bc1eb280..10915e8ea9 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -85,7 +85,7 @@ public: reg_t kDoSoundDummy(int argc, reg_t *argv, reg_t acc); reg_t kDoSoundMute(int argc, reg_t *argv, reg_t acc); reg_t kDoSoundPause(int argc, reg_t *argv, reg_t acc); - reg_t kDoSoundResume(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundResumeAfterRestore(int argc, reg_t *argv, reg_t acc); reg_t kDoSoundStop(int argc, reg_t *argv, reg_t acc); reg_t kDoSoundStopAll(int argc, reg_t *argv, reg_t acc); reg_t kDoSoundDispose(int argc, reg_t *argv, reg_t acc); |