[Scummvm-git-logs] scummvm master -> 78433d5085d14a307848cccdc3a5ca917fe09fd7
athrxx
noreply at scummvm.org
Thu Mar 7 21:31:05 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
78433d5085 SCUMM: (MI1/Mac) - extend new sound player to support MI1
Commit: 78433d5085d14a307848cccdc3a5ca917fe09fd7
https://github.com/scummvm/scummvm/commit/78433d5085d14a307848cccdc3a5ca917fe09fd7
Author: athrxx (athrxx at scummvm.org)
Date: 2024-03-07T22:30:18+01:00
Commit Message:
SCUMM: (MI1/Mac) - extend new sound player to support MI1
Changed paths:
A engines/scumm/players/player_mac_loom_monkey.cpp
R engines/scumm/players/player_mac_loom.cpp
engines/scumm/module.mk
engines/scumm/players/player_mac_intern.h
engines/scumm/players/player_mac_new.cpp
engines/scumm/players/player_mac_new.h
engines/scumm/players/player_v5m.cpp
engines/scumm/saveload.cpp
engines/scumm/scumm.cpp
engines/scumm/sound.cpp
engines/scumm/vars.cpp
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 4ce393f1ac1..ba7673d6177 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -54,7 +54,7 @@ MODULE_OBJS := \
players/player_he.o \
players/player_mac.o \
players/player_mac_indy3.o \
- players/player_mac_loom.o \
+ players/player_mac_loom_monkey.o \
players/player_mac_new.o \
players/player_mod.o \
players/player_nes.o \
diff --git a/engines/scumm/players/player_mac_intern.h b/engines/scumm/players/player_mac_intern.h
index 3b48d57d23c..28c1d2eaa17 100644
--- a/engines/scumm/players/player_mac_intern.h
+++ b/engines/scumm/players/player_mac_intern.h
@@ -367,12 +367,13 @@ public:
MusicChannel *getMusicChannel(uint8 id) const;
};
-class LoomMacSnd final : public VblTaskClientDriver, public MacLowLevelPCMDriver::CallbackClient {
+class MacSndLoader;
+class LoomMonkeyMacSnd final : public VblTaskClientDriver, public MacLowLevelPCMDriver::CallbackClient {
private:
- LoomMacSnd(ScummEngine *vm, Audio::Mixer *mixer);
+ LoomMonkeyMacSnd(ScummEngine *vm, Audio::Mixer *mixer);
public:
- ~LoomMacSnd();
- static Common::SharedPtr<LoomMacSnd> open(ScummEngine *scumm, Audio::Mixer *mixer);
+ ~LoomMonkeyMacSnd();
+ static Common::SharedPtr<LoomMonkeyMacSnd> open(ScummEngine *scumm, Audio::Mixer *mixer);
bool startDevice(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation, bool stereo, bool internal16Bit);
void setMusicVolume(int vol);
@@ -393,7 +394,7 @@ public:
void sndChannelCallback(uint16 arg1, const void *arg2) override;
private:
- void sendSoundCommands(const byte *data, int timeStamp);
+ void sendSoundCommands(int timeStamp);
void stopActiveSound();
void setupChannels();
void disposeAllChannels();
@@ -401,33 +402,17 @@ private:
void detectQuality();
bool isSoundCardType10() const;
- struct Instrument {
- public:
- Instrument(uint16 id, Common::SeekableReadStream *&in, Common::String &&name);
- ~Instrument() { _res.reset(); }
- const MacLowLevelPCMDriver::PCMSound *data() const { return &_snd; }
- uint16 id() const { return _id; }
- private:
- uint16 _id;
- Common::SharedPtr<const byte> _res;
- Common::String _name;
- MacLowLevelPCMDriver::PCMSound _snd;
- };
-
- bool loadInstruments();
- const Common::SharedPtr<Instrument> *findInstrument(uint16 id) const;
- Common::Array<Common::SharedPtr<Instrument> > _instruments;
-
int _curSound;
+ int _restartSound;
+ int _curSoundSaveVar;
int _songTimer;
byte _songTimerInternal;
- byte *_soundUsage;
byte *_chanConfigTable;
const int _idRangeMax;
+ const byte _saveVersionChange;
+ const byte _legacySaveUnits;
bool _mixerThread;
- MacLowLevelPCMDriver *_sdrv;
-
int _machineRating;
int _selectedQuality;
int _effectiveChanConfig;
@@ -438,13 +423,15 @@ private:
MacLowLevelPCMDriver::ChanHandle _musChannels[4];
MacPlayerAudioStream *_macstr;
+ MacSndLoader *_loader;
+ MacLowLevelPCMDriver *_sdrv;
Audio::SoundHandle _soundHandle;
- MacPlayerAudioStream::CallbackProc _songTimerUpdt;
+ MacPlayerAudioStream::CallbackProc _vblTskProc;
MacLowLevelPCMDriver::ChanCallback _chanCbProc;
ScummEngine *_vm;
Audio::Mixer *_mixer;
- static Common::WeakPtr<LoomMacSnd> *_inst;
+ static Common::WeakPtr<LoomMonkeyMacSnd> *_inst;
byte _curChanConfig;
byte _chanUse;
@@ -452,21 +439,6 @@ private:
Audio::Mixer::SoundType _curSndType;
Audio::Mixer::SoundType _lastSndType;
byte _chanPlaying;
-
- struct SoundConfig {
- SoundConfig(LoomMacSnd *pl) : player(pl), sndRes6(0), switchable(0), sndRes10(0), chanSetup(0), timbre(0) {
- assert(player);
- memset(instruments, 0, sizeof(instruments));
- }
- void load(const byte *data);
- byte sndRes6;
- byte switchable;
- byte sndRes10;
- uint16 chanSetup;
- uint16 timbre;
- const Common::SharedPtr<Instrument> *instruments[5];
- LoomMacSnd *player;
- } _soundConfig;
};
extern const uint8 _fourToneSynthWaveForm[256];
diff --git a/engines/scumm/players/player_mac_loom.cpp b/engines/scumm/players/player_mac_loom.cpp
deleted file mode 100644
index 318e1f04447..00000000000
--- a/engines/scumm/players/player_mac_loom.cpp
+++ /dev/null
@@ -1,590 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#include "scumm/players/player_mac_new.h"
-#include "scumm/players/player_mac_intern.h"
-#include "scumm/resource.h"
-
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "common/punycode.h"
-#include "common/macresman.h"
-
-namespace Scumm {
-
-#define ASC_DEVICE_RATE 0x56EE8BA3
-#define PCM_BUFFER_SIZE 1024
-
-Common::WeakPtr<LoomMacSnd> *LoomMacSnd::_inst = nullptr;
-
-LoomMacSnd::LoomMacSnd(ScummEngine *vm, Audio::Mixer *mixer) : VblTaskClientDriver(),
- _vm(vm), _mixer(mixer), _curSound(0), _macstr(nullptr), _soundUsage(0), _sdrv(nullptr), _songTimerUpdt(this, &VblTaskClientDriver::vblCallback), _soundConfig(this),
- _songTimer(0), _songTimerInternal(0), _machineRating(0), _selectedQuality(2), _effectiveChanConfig(0), _16bit(false), _idRangeMax(200), _sndChannel(0), _chanUse(0),
- _defaultChanConfig(0), _chanConfigTable(nullptr), _chanPlaying(0), _curChanConfig(0), _curSynthType(0), _curSndType(Audio::Mixer::kPlainSoundType),
- _mixerThread(false), _lastSndType(Audio::Mixer::kPlainSoundType), _chanCbProc(this, &MacLowLevelPCMDriver::CallbackClient::sndChannelCallback) {
- assert(_vm);
- assert(_mixer);
-
- static const byte cfgtable[] = { 0, 0, 0, 1, 4, 5, 1, 5, 6, 6, 8, 9 };
- _chanConfigTable = new byte[sizeof(cfgtable)]();
- memcpy(_chanConfigTable, cfgtable, sizeof(cfgtable));
- _soundUsage = new byte[_idRangeMax]();
- memset(_musChannels, 0, sizeof(_musChannels));
-}
-
-LoomMacSnd::~LoomMacSnd() {
- _mixer->stopHandle(_soundHandle);
- delete _macstr;
- delete[] _soundUsage;
- delete[] _chanConfigTable;
-
- disposeAllChannels();
- delete _sdrv;
-
- delete _inst;
- _inst = nullptr;
-}
-
-Common::SharedPtr<LoomMacSnd> LoomMacSnd::open(ScummEngine *vm, Audio::Mixer *mixer) {
- Common::SharedPtr<LoomMacSnd> scp = nullptr;
-
- if (_inst == nullptr) {
- scp = Common::SharedPtr<LoomMacSnd>(new LoomMacSnd(vm, mixer));
- _inst = new Common::WeakPtr<LoomMacSnd>(scp);
- // We can start this with the ScummVM mixer output rate instead of the ASC rate. The Mac sample rate converter can handle it (at
- // least for up to 48 KHz, I haven't tried higher settings) and we don't have to do another rate conversion in the ScummVM mixer.
- if ((_inst == nullptr) || (mixer == nullptr) || !(scp->startDevice(mixer->getOutputRate(), mixer->getOutputRate() << 16/*ASC_DEVICE_RATE*/, PCM_BUFFER_SIZE, true, false, true)))
- error("LoomMacSnd::open(): Failed to start player");
- }
-
- return _inst->lock();
-}
-
-bool LoomMacSnd::startDevice(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation, bool stereo, bool internal16Bit) {
- _macstr = new MacPlayerAudioStream(this, outputRate, stereo, enableInterpolation, internal16Bit);
- if (!_macstr || !_mixer)
- return false;
-
- if (!loadInstruments())
- return false;
-
- _sdrv = new MacLowLevelPCMDriver(_mixer->mutex(), pcmDeviceRate, internal16Bit);
- if (!_sdrv)
- return false;
-
- _effectiveChanConfig = 9;
- _16bit = internal16Bit;
-
- _macstr->initDrivers();
- _macstr->initBuffers(feedBufferSize);
- _macstr->setVblCallback(&_songTimerUpdt);
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, _macstr, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- return true;
-}
-
-void LoomMacSnd::setMusicVolume(int vol) {
- Common::StackLock lock(_mixer->mutex());
- if (_macstr)
- _macstr->setMasterVolume(Audio::Mixer::kMusicSoundType, vol);
-}
-
-void LoomMacSnd::setSfxVolume(int vol) {
- Common::StackLock lock(_mixer->mutex());
- if (_macstr)
- _macstr->setMasterVolume(Audio::Mixer::kSFXSoundType, vol);
-}
-
-void LoomMacSnd::startSound(int id, int jumpToTick) {
- if (_sdrv == nullptr || id < 0 || id >= _idRangeMax) {
- warning("LoomMacSnd::startSound(): sound id '%d' out of range (0 - %d)", id, _idRangeMax - 1);
- return;
- }
-
- Common::StackLock lock(_mixer->mutex());
-
- const byte *ptr = _vm->getResourceAddress(rtSound, id);
- assert(ptr);
-
- if (READ_BE_UINT16(ptr + 4) != 'so' || READ_BE_UINT32(ptr + 10)) {
- warning("LoomMacSnd::startSound(): Sound resource '%d' cannot be played", id);
- return;
- }
-
- stopActiveSound();
- if (_chanUse <= 1)
- disposeAllChannels();
-
- if (!_defaultChanConfig)
- detectQuality();
-
- _soundConfig.load(ptr);
- //if (_sndDisableFlags && _soundConfig.switchable)
- // return;
-
- if (_soundConfig.chanSetup) {
- _effectiveChanConfig = _soundConfig.chanSetup;
- _curSndType = Audio::Mixer::kSFXSoundType;
- } else {
- _effectiveChanConfig = _defaultChanConfig;
- _curSndType = Audio::Mixer::kMusicSoundType;
- }
-
- if (_lastSndType != _curSndType)
- _curChanConfig = 0;
-
- _curSound = id;
- _soundUsage[id] = 1;
-
- setupChannels();
- sendSoundCommands(ptr, jumpToTick);
-
- if (!jumpToTick) {
- _songTimer = 0;
- _songTimerInternal = 0;
- }
-}
-
-void LoomMacSnd::stopSound(int id) {
- if (id < 0 || id >= _idRangeMax) {
- warning("LoomMacSnd::stopSound(): sound id '%d' out of range (0 - %d)", id, _idRangeMax - 1);
- return;
- }
-
- Common::StackLock lock(_mixer->mutex());
- _soundUsage[id] = 0;
-
- if (id == _curSound)
- stopActiveSound();
-}
-
-void LoomMacSnd::stopAllSounds() {
- Common::StackLock lock(_mixer->mutex());
- memset(_soundUsage, 0, _idRangeMax);
- stopActiveSound();
-}
-
-int LoomMacSnd::getMusicTimer() {
- Common::StackLock lock(_mixer->mutex());
- return _songTimer;
-}
-
-int LoomMacSnd::getSoundStatus(int id) const {
- if (id < 0 || id >= _idRangeMax) {
- warning("LoomMacSnd::getSoundStatus(): sound id '%d' out of range (0 - %d)", id, _idRangeMax - 1);
- return 0;
- }
- Common::StackLock lock(_mixer->mutex());
- return _soundUsage[id];
-}
-
-void LoomMacSnd::setQuality(int qual) {
- assert(qual >= MacSound::kQualityAuto && qual <= MacSound::kQualityHighest);
- Common::StackLock lock(_mixer->mutex());
-
- if (qual > MacSound::kQualityAuto) {
- qual--;
- _machineRating = (qual / 3) + 1;
- _selectedQuality = qual % 3;
- qual = _chanConfigTable[_machineRating * 3 + _selectedQuality];
- if (qual && qual == _defaultChanConfig)
- return;
- }
-
- int csnd = _curSound;
- int32 timeStamp = csnd ? _songTimer * 1000 + ((_songTimerInternal * 1000) / 30) : 0;
- stopActiveSound();
-
- detectQuality();
- if (csnd)
- startSound(csnd, timeStamp);
-}
-
-void LoomMacSnd::saveLoadWithSerializer(Common::Serializer &ser) {
- if (ser.isLoading() && ser.getVersion() < VER(94)) {
- memset(_soundUsage, 0, _idRangeMax);
- _curSound = 0;
- return;
- }
-
- if (ser.isLoading() && ser.getVersion() < VER(114)) {
- memset(_soundUsage, 0, _idRangeMax);
- // Skip over old driver savedata, since it is not needed here.
- ser.skip(4);
- // We need only this
- ser.syncAsSint16LE(_curSound);
- _curSound = CLIP<int>(_curSound, 0, _idRangeMax - 1);
- if (_curSound > 0)
- _soundUsage[_curSound] = 1;
- // Skip the rest
- ser.skip(ser.getVersion() >= VER(94) && ser.getVersion() <= VER(103) ? 120 : 100);
- } else {
- ser.syncBytes(_soundUsage, _idRangeMax, VER(114));
- }
-}
-
-void LoomMacSnd::restoreAfterLoad() {
- for (int i = 1; i < _idRangeMax; ++i) {
- if (_soundUsage[i]) {
- _soundUsage[i] = 0;
- startSound(i);
- }
- }
-}
-
-void LoomMacSnd::vblCallback() {
- if (_songTimerInternal++ == 29) {
- _songTimerInternal = 0;
- ++_songTimer;
- }
-}
-
-void LoomMacSnd::generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) const {
- assert(dst);
- memset(dst, 0, len);
- _sdrv->feed(dst, len, type, expectStereo);
-}
-
-const MacSoundDriver::Status &LoomMacSnd::getDriverStatus(uint8, Audio::Mixer::SoundType sndType) const {
- return _sdrv->getStatus(sndType);
-}
-
-void LoomMacSnd::sndChannelCallback(uint16 arg1, const void*) {
- // We do this a little smarter than the original player which would stop the track immediately when
- // the first channel invoked its end-of-track callback. This would cut of the playback early, in an
- // unpleasant way. Instead, we stop the playback not before all channels have finished.
- _chanPlaying &= ~arg1;
- if (_chanPlaying)
- return;
- stopActiveSound();
-}
-
-void LoomMacSnd::sendSoundCommands(const byte *data, int timeStamp) {
- if (!_defaultChanConfig || !_curSound)
- return;
-
- if (_chanUse == 1 && _sndChannel) {
- const byte *s = data + READ_BE_UINT16(data + 30) + 6;
- uint16 len = READ_BE_UINT16(s - 2);
- while (len--) {
- uint16 p1 = READ_BE_UINT16(s);
- s += 2;
- uint8 note = *s++;
-
- if (timeStamp > 0) {
- int ts = timeStamp;
- timeStamp = MAX<int>(0, timeStamp - p1);
- p1 -= ts;
- }
- if (timeStamp)
- continue;
-
- _sdrv->playNote(_sndChannel, MacLowLevelPCMDriver::kEnqueue, note & 0x7f, p1);
- if (note == 0) // Workaround for tempo glitch in original driver
- _sdrv->wait(_sndChannel, MacLowLevelPCMDriver::kEnqueue, p1);
- }
- _sdrv->quiet(_sndChannel, MacLowLevelPCMDriver::kEnqueue);
- _sdrv->callback(_sndChannel, MacLowLevelPCMDriver::kEnqueue, 1, nullptr);
- _chanPlaying |= 1;
-
- } else if (_chanUse == 4) {
- const byte *src[4];
- uint16 len[4];
- int tmstmp[4];
-
- for (int i = 0; i < 4; ++i) {
- src[i] = nullptr;
- len[i] = 0;
- tmstmp[i] = timeStamp;
- if (!_musChannels[i])
- continue;
- src[i] = data + READ_BE_UINT16(data + 32 + 2 * i) + 6;
- len[i] = READ_BE_UINT16(src[i] - 2);
- }
-
- for (bool loop = true; loop; ) {
- loop = false;
- for (int i = 0; i < 4; ++i) {
- if (!src[i] || !len[i])
- continue;
- uint16 p1 = READ_BE_UINT16(src[i]);
- src[i] += 2;
- byte note = *src[i]++;
- if (tmstmp[i] > 0) {
- int ts = tmstmp[i];
- tmstmp[i] = MAX<int>(0, tmstmp[i] - p1);
- p1 -= ts;
- }
- loop |= static_cast<bool>(--len[i]);
-
- if (tmstmp[i])
- continue;
-
- _sdrv->playNote(_musChannels[i], MacLowLevelPCMDriver::kEnqueue, (_curSynthType == 4 && note == 0) ? 1 : note & 0x7f, p1);
- // Workaround for tempo glitch in original driver. For the sampled synth in 4 channel mode, there is
- // some sort of fix in the original (see above), but that really does not work well for the other cases.
- if (note == 0 && _curSynthType != 4)
- _sdrv->wait(_musChannels[i], MacLowLevelPCMDriver::kEnqueue, p1);
- }
- }
-
- _chanPlaying = 0;
- for (int i = 0; i < 4; ++i) {
- if (src[i]) {
- _sdrv->quiet(_musChannels[i], MacLowLevelPCMDriver::kEnqueue);
- _sdrv->callback(_musChannels[i], MacLowLevelPCMDriver::kEnqueue, 1 << i, nullptr);
- _chanPlaying |= (1 << i);
- }
- }
- }
-}
-
-void LoomMacSnd::stopActiveSound() {
- if (_sndChannel) {
- _sdrv->quiet(_sndChannel, MacLowLevelPCMDriver::kImmediate);
- _sdrv->flush(_sndChannel, MacLowLevelPCMDriver::kImmediate);
- }
-
- for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
- if (_musChannels[i]) {
- _sdrv->quiet(_musChannels[i], MacLowLevelPCMDriver::kImmediate);
- _sdrv->flush(_musChannels[i], MacLowLevelPCMDriver::kImmediate);
- }
- }
-
- if (_curSound) {
- _soundUsage[_curSound] = 0;
- _curSound = 0;
- }
- _chanPlaying = 0;
-}
-
-void LoomMacSnd::setupChannels() {
- static const byte synthType[] = { 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x02, 0x04, 0x04, 0x04 };
- static const byte numChan[] = { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04 };
- static const byte attrib[] = { 0x00, 0x00, 0x04, 0xAC, 0xA4, 0xA0, 0x04, 0xAC, 0xA4, 0xA0 };
-
- if (!_defaultChanConfig)
- return;
-
- if (_curChanConfig != _effectiveChanConfig) {
- disposeAllChannels();
- _curChanConfig = _effectiveChanConfig;
- _curSynthType = synthType[_curChanConfig];
- _chanUse = numChan[_curChanConfig];
- _lastSndType = _curSndType;
-
- switch (_curSynthType) {
- case 1:
- if (_chanUse == 1 && !_sndChannel) {
- _sndChannel = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kSquareWaveSynth, attrib[_curChanConfig], &_chanCbProc);
- }
- break;
- case 2:
- if (_chanUse == 1 && !_sndChannel) {
- _sndChannel = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kWaveTableSynth, attrib[_curChanConfig], &_chanCbProc);
- } else if (_chanUse == 4) {
- for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
- if ((_soundConfig.instruments[i + 1] && _soundConfig.instruments[i + 1]->get()->id() == 0x2D1C) || _musChannels[i])
- continue;
- _musChannels[i] = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kWaveTableSynth, attrib[_curChanConfig] + i, &_chanCbProc);
- }
- }
- break;
- case 4:
- if (_chanUse == 1 && !_sndChannel) {
- _sndChannel = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kSampledSynth, attrib[_curChanConfig], &_chanCbProc);
- } else if (_chanUse == 4) {
- for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
- if ((_soundConfig.instruments[i + 1] && _soundConfig.instruments[i + 1]->get()->id() == 0x2D1C) || _musChannels[i])
- continue;
- _musChannels[i] = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kSampledSynth, attrib[_curChanConfig], &_chanCbProc);
- }
- }
- break;
- default:
- break;
- }
- }
-
- switch (_curSynthType) {
- case 1:
- if (_sndChannel)
- _sdrv->setTimbre(_sndChannel, MacLowLevelPCMDriver::kImmediate, _soundConfig.timbre);
- break;
- case 2:
- if (_chanUse == 1) {
- if (_sndChannel)
- _sdrv->loadWaveTable(_sndChannel, MacLowLevelPCMDriver::kImmediate, _fourToneSynthWaveForm, _fourToneSynthWaveFormSize);
- } else {
- for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
- if (_musChannels[i])
- _sdrv->loadWaveTable(_musChannels[i], MacLowLevelPCMDriver::kImmediate, _fourToneSynthWaveForm, _fourToneSynthWaveFormSize);
- }
- }
- break;
- case 4:
- if (_chanUse == 1) {
- if (_sndChannel && _soundConfig.instruments[0])
- _sdrv->loadInstrument(_sndChannel, MacLowLevelPCMDriver::kImmediate, _soundConfig.instruments[0]->get()->data());
- } else {
- for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
- if (_musChannels[i] && _soundConfig.instruments[i + 1])
- _sdrv->loadInstrument(_musChannels[i], MacLowLevelPCMDriver::kImmediate, _soundConfig.instruments[i + 1]->get()->data());
- }
- }
- break;
- default:
- break;
- }
-}
-
-void LoomMacSnd::disposeAllChannels() {
- if (_sndChannel)
- _sdrv->disposeChannel(_sndChannel);
- _sndChannel = 0;
-
- for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
- if (_musChannels[i])
- _sdrv->disposeChannel(_musChannels[i]);
- _musChannels[i] = 0;
- }
-
- _curChanConfig = 0;
-}
-
-void LoomMacSnd::detectQuality() {
- if (_machineRating == 0) {
- if (isSoundCardType10())
- _machineRating = 1;
- /*else if (0)
- _machineRating = 2;*/
- else
- _machineRating = 3;
- }
-
- _defaultChanConfig = _effectiveChanConfig = _chanConfigTable[_machineRating * 3 + _selectedQuality];
- _curChanConfig = 0;
- disposeAllChannels();
- setupChannels();
- _chanConfigTable[_machineRating * 3 + _selectedQuality] = _defaultChanConfig;
-}
-
-bool LoomMacSnd::isSoundCardType10() const {
- return _mixerThread ? (_machineRating == 1) : (_vm->VAR_SOUNDCARD != 0xff && _vm->VAR(_vm->VAR_SOUNDCARD) == 10);
-}
-
-LoomMacSnd::Instrument::Instrument(uint16 id, Common::SeekableReadStream *&in, Common::String &&name) : _id(id), _name(name) {
- in->seek(2);
- uint16 numTypes = in->readUint16BE();
- in->seek(numTypes * 6 + 4);
- in->seek(in->readUint16BE() * 8 + numTypes * 6 + 10);
-
- _snd.len = in->readUint32BE();
- _snd.rate = in->readUint32BE();
- _snd.loopst = in->readUint32BE();
- _snd.loopend = in->readUint32BE();
- _snd.enc = in->readByte();
- _snd.baseFreq = in->readByte();
-
- byte *buff = new byte[_snd.len];
- in->read(buff, _snd.len);
- _snd.data = Common::SharedPtr<const byte> (buff, Common::ArrayDeleter<const byte>());
-}
-
-bool LoomMacSnd::loadInstruments() {
- static const char *tryNames[] = {
- "Loom",
- "Loom\xaa",
- "Loom PPC",
- "Loom\xaa PPC"
- };
-
- const Common::CodePage tryCodePages[] = {
- Common::kMacRoman,
- Common::kISO8859_1
- };
-
- Common::MacResManager resMan;
- Common::Path resFile;
- for (int i = 0; resFile.empty() && i < ARRAYSIZE(tryNames); ++i) {
- for (int ii = 0; resFile.empty() && ii < ARRAYSIZE(tryCodePages); ++ii) {
- Common::U32String fn(tryNames[i], tryCodePages[ii]);
- resFile = Common::Path(fn.encode(Common::kUtf8));
- if (!resMan.exists(resFile) || !resMan.open(resFile) || !resMan.hasResFork()) {
- resMan.close();
- resFile = Common::Path(Common::punycode_encodefilename(fn));
- if (!resMan.exists(resFile) || !resMan.open(resFile) || !resMan.hasResFork()) {
- resMan.close();
- resFile.clear();
- }
- }
- }
- }
-
- if (resFile.empty()) {
- warning("LoomMacSnd::loadInstruments(): Loom resource fork not found");
- return false;
- }
-
- Common::MacResIDArray ids = resMan.getResIDArray(MKTAG('s', 'n', 'd', ' '));
- for (uint i = 0; i < ids.size(); ++i) {
- Common::SeekableReadStream *str = resMan.getResource(MKTAG('s', 'n', 'd', ' '), ids[i]);
- if (!str || str->readUint16BE() != 1) {
- static const char *const errStr[2] = { "Failed to load", "Invalid sound resource format for" };
- warning("LoomMacSnd::loadInstruments(): %s instrument with id 0x%04x", errStr[str ? 1 : 0], ids[i]);
- delete str;
- return false;
- }
- _instruments.push_back(Common::SharedPtr<Instrument>(new Instrument(ids[i], str, resMan.getResName(MKTAG('s', 'n', 'd', ' '), ids[i]))));
- delete str;
- }
-
- return true;
-}
-
-const Common::SharedPtr<LoomMacSnd::Instrument> *LoomMacSnd::findInstrument(uint16 id) const {
- Common::Array<Common::SharedPtr<Instrument> >::const_iterator replacement = _instruments.end();
- for (Common::Array<Common::SharedPtr<Instrument> >::const_iterator i = _instruments.begin(); i != _instruments.end(); ++i) {
- if ((*i)->id() == id)
- return i;
- else if ((*i)->id() == 0x2D1C)
- replacement = i;
- }
- return (replacement != _instruments.end()) ? replacement : nullptr;
-}
-
-void LoomMacSnd::SoundConfig::load(const byte *data) {
- sndRes6 = READ_BE_UINT16(data + 6) & 0xff;
- switchable = READ_BE_UINT16(data + 8) >> 8;
- sndRes10 = READ_BE_UINT16(data + 10) >> 8;
- chanSetup = READ_BE_UINT16(data + 16);
- timbre = READ_BE_UINT16(data + 18);
- for (int i = 0; i < 5; ++i)
- instruments[i] = player->findInstrument(READ_BE_UINT16(data + 20 + 2 * i));
-}
-
-#undef ASC_DEVICE_RATE
-#undef PCM_BUFFER_SIZE
-
-} // End of namespace Scumm
diff --git a/engines/scumm/players/player_mac_loom_monkey.cpp b/engines/scumm/players/player_mac_loom_monkey.cpp
new file mode 100644
index 00000000000..6bbd6fe4c4d
--- /dev/null
+++ b/engines/scumm/players/player_mac_loom_monkey.cpp
@@ -0,0 +1,901 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "scumm/players/player_mac_new.h"
+#include "scumm/players/player_mac_intern.h"
+#include "scumm/resource.h"
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "common/punycode.h"
+#include "common/macresman.h"
+#include "common/memstream.h"
+
+namespace Scumm {
+
+#define ASC_DEVICE_RATE 0x56EE8BA3
+#define PCM_BUFFER_SIZE 1024
+
+class MacSndLoader{
+protected:
+ MacSndLoader(bool useInstrTag);
+public:
+ virtual ~MacSndLoader() {}
+
+ virtual bool init() = 0;
+ virtual bool checkResource(const byte *data, uint32 dataSize) const = 0;
+ virtual bool blocked(const byte *data, uint32 dataSize) const = 0;
+ virtual bool loadSound(byte synthType, const byte *data, uint32 dataSize) = 0;
+ virtual void unblock() = 0;
+
+ const MacLowLevelPCMDriver::PCMSound *getInstrData(uint16 chan);
+ virtual bool isInstrUsable(uint16 chan) const = 0;
+ virtual bool parseNextEvent(uint16 chan, uint16 &duration, uint8 ¬e, bool &skip, bool &updateInstr) = 0;
+ virtual uint16 getChanSetup() const = 0;
+ uint16 getTimbre() const { return _timbre; }
+ virtual bool isMusic() const = 0;
+ bool isLooping() const { return _loop; }
+ virtual bool restartSoundAfterLoad() const = 0;
+
+ virtual bool ignoreMachineRating() const = 0;
+
+protected:
+ bool loadInstruments(const char *const *tryFileNames, uint16 numTryFileNames, uint16 numInstruments);
+
+ struct Instrument {
+ public:
+ Instrument(uint32 id, Common::SeekableReadStream *&in, Common::String &&name);
+ ~Instrument() { _res.reset(); }
+ const MacLowLevelPCMDriver::PCMSound *data() const { return &_snd; }
+ uint32 id() const { return _id; }
+
+ private:
+ uint32 _id;
+ Common::SharedPtr<const byte> _res;
+ Common::String _name;
+ MacLowLevelPCMDriver::PCMSound _snd;
+ };
+
+ Common::Array<Common::SharedPtr<Instrument> > _instruments;
+
+ byte _sndRes6;
+ byte _isMusic;
+ byte _sndRes9;
+ byte _sndRes10;
+ byte _sndRes11;
+ byte _sndRes12;
+ uint16 _chanSetup;
+ uint16 _timbre;
+ bool _loop;
+ byte _synth;
+ const byte *_chanSndData[5];
+ uint32 _chanNumEvents[5];
+ uint32 _chanCurEvent[5];
+ const Common::SharedPtr<Instrument> *_chanInstr[5];
+ const Common::SharedPtr<Instrument> *_chanInstr2[5];
+
+ const bool _useInstrTag;
+};
+
+class LoomMacSndLoader final : public MacSndLoader {
+public:
+ LoomMacSndLoader() : MacSndLoader(false) {}
+ ~LoomMacSndLoader() override {}
+
+ bool init() override;
+ bool checkResource(const byte *data, uint32 dataSize) const override;
+ bool blocked(const byte *data, uint32 dataSize) const override { return false; }
+ bool loadSound(byte synthType, const byte *data, uint32 dataSize) override;
+ void unblock() override {}
+
+ bool isInstrUsable(uint16 chan) const override;
+ bool parseNextEvent(uint16 chan, uint16 &duration, uint8 ¬e, bool &skip, bool &updateInstr) override;
+ uint16 getChanSetup() const override { return _chanSetup; }
+ bool isMusic() const override { return (_chanSetup == 0); }
+ bool restartSoundAfterLoad() const override { return true; }
+ bool ignoreMachineRating() const override { return false; }
+private:
+ const Common::SharedPtr<Instrument> *fetchInstrument(uint16 id) const;
+};
+
+class MonkeyMacSndLoader final : public MacSndLoader {
+public:
+ MonkeyMacSndLoader() : MacSndLoader(true), _numInstrumentsMax(17), _blockSfx(false), _transpose(0) {}
+ ~MonkeyMacSndLoader() override {}
+
+ bool init() override;
+ bool checkResource(const byte *data, uint32 dataSize) const override;
+ bool blocked(const byte *data, uint32 dataSize) const override;
+ bool loadSound(byte synthType, const byte *data, uint32 dataSize) override;
+ void unblock() override { _blockSfx = false; }
+
+ bool isInstrUsable(uint16 chan) const override;
+ bool parseNextEvent(uint16 chan, uint16 &duration, uint8 ¬e, bool &skip, bool &updateInstr) override;
+ uint16 getChanSetup() const override { return _isMusic ? _chanSetup : 7; }
+ bool isMusic() const override { return _isMusic; }
+ bool restartSoundAfterLoad() const override { return _isMusic && _loop; }
+ bool ignoreMachineRating() const override { return true; }
+private:
+ const Common::SharedPtr<Instrument> *fetchInstrument(const byte *data, uint32 dataSize, uint32 tagOrOffset);
+ bool _blockSfx;
+ byte _transpose;
+ const byte _numInstrumentsMax;
+};
+
+MacSndLoader::Instrument::Instrument(uint32 id, Common::SeekableReadStream *&in, Common::String &&name) : _id(id), _name(name) {
+ in->seek(2);
+ uint16 numTypes = in->readUint16BE();
+ in->seek(numTypes * 6 + 4);
+ in->seek(in->readUint16BE() * 8 + numTypes * 6 + 10);
+
+ _snd.len = in->readUint32BE();
+ _snd.rate = in->readUint32BE();
+ _snd.loopst = in->readUint32BE();
+ _snd.loopend = in->readUint32BE();
+ _snd.enc = in->readByte();
+ _snd.baseFreq = in->readByte();
+
+ byte *buff = new byte[_snd.len];
+ if (in->read(buff, _snd.len) != _snd.len)
+ error("MacSndLoader::Instrument::Instrument(): Data error");
+ _snd.data = Common::SharedPtr<const byte>(buff, Common::ArrayDeleter<const byte>());
+}
+
+MacSndLoader::MacSndLoader(bool useInstrTag) : _sndRes6(0), _isMusic(0), _sndRes9(0), _sndRes10(0), _sndRes11(0), _sndRes12(0), _chanSetup(0),
+ _timbre(0), _useInstrTag(useInstrTag), _synth(0), _loop(false) {
+ memset(_chanInstr, 0, sizeof(_chanInstr));
+ memset(_chanInstr2, 0, sizeof(_chanInstr2));
+ memset(_chanSndData, 0, sizeof(_chanSndData));
+ memset(_chanNumEvents, 0, sizeof(_chanNumEvents));
+ memset(_chanCurEvent, 0, sizeof(_chanCurEvent));
+}
+
+const MacLowLevelPCMDriver::PCMSound *MacSndLoader::getInstrData(uint16 chan) {
+ return (chan < ARRAYSIZE(_chanInstr) && _chanInstr[chan]) ? _chanInstr[chan]->get()->data() : nullptr;
+}
+
+bool MacSndLoader::loadInstruments(const char *const *tryFileNames, uint16 numTryFileNames, uint16 numInstruments) {
+ assert(tryFileNames && numTryFileNames && numInstruments);
+ uint32 tag = 0;
+ const Common::CodePage tryCodePages[] = {
+ Common::kMacRoman,
+ Common::kISO8859_1
+ };
+
+ Common::MacResManager resMan;
+ Common::Path resFile;
+ for (int i = 0; resFile.empty() && i < numTryFileNames; ++i) {
+ for (int ii = 0; resFile.empty() && ii < ARRAYSIZE(tryCodePages); ++ii) {
+ Common::U32String fn(tryFileNames[i], tryCodePages[ii]);
+ resFile = Common::Path(fn.encode(Common::kUtf8));
+ if (!resMan.exists(resFile) || !resMan.open(resFile) || !resMan.hasResFork()) {
+ resMan.close();
+ resFile = Common::Path(Common::punycode_encodefilename(fn));
+ if (!resMan.exists(resFile) || !resMan.open(resFile) || !resMan.hasResFork()) {
+ resMan.close();
+ resFile.clear();
+ }
+ }
+ }
+ }
+
+ if (resFile.empty()) {
+ warning("MacSndLoader::loadInstruments(): Resource fork not found");
+ return false;
+ }
+
+ Common::MacResIDArray ids = resMan.getResIDArray(MKTAG('s', 'n', 'd', ' '));
+ for (uint i = 0; i < ids.size(); ++i) {
+ Common::SeekableReadStream *str = resMan.getResource(MKTAG('s', 'n', 'd', ' '), ids[i]);
+ if (!str || str->readUint16BE() != 1) {
+ static const char *const errStr[2] = {"Failed to load", "Invalid sound resource format for"};
+ warning("MacSndLoader::loadInstruments(): %s instrument with id 0x%04x", errStr[str ? 1 : 0], ids[i]);
+ delete str;
+ return false;
+ }
+ Common::String nm(resMan.getResName(MKTAG('s', 'n', 'd', ' '), ids[i]));
+ memcpy(&tag, nm.c_str(), MIN<uint>(nm.size(), sizeof(tag)));
+ uint32 id = _useInstrTag ? FROM_BE_32(tag) : ids[i];
+ _instruments.push_back(Common::SharedPtr<Instrument>(new Instrument(id, str, Common::move(nm))));
+ delete str;
+ }
+
+ if (_instruments.size() != numInstruments)
+ warning("MacSndLoader::loadInstruments(): Unexpected number of instruments found (expected: %d, found: %d)", numInstruments, _instruments.size());
+
+ return true;
+}
+
+bool LoomMacSndLoader::init() {
+ static const char *execNames[] = {
+ "Loom",
+ "Loom\xaa",
+ "Loom PPC",
+ "Loom\xaa PPC"
+ };
+
+ return loadInstruments(execNames, ARRAYSIZE(execNames), 10);
+}
+
+bool LoomMacSndLoader::checkResource(const byte *data, uint32 dataSize) const {
+ return (dataSize >= 14 && READ_BE_UINT16(data + 4) == 'so' && !READ_BE_UINT32(data + 10));
+}
+
+bool LoomMacSndLoader::loadSound(byte synthType, const byte *data, uint32 dataSize) {
+ if (dataSize < 40)
+ return false;
+
+ _sndRes6 = READ_BE_UINT16(data + 6) & 0xff;
+ _isMusic = READ_BE_UINT16(data + 8) >> 8;
+ _sndRes10 = READ_BE_UINT16(data + 10) >> 8;
+ _chanSetup = READ_BE_UINT16(data + 16);
+ _timbre = READ_BE_UINT16(data + 18);
+ for (int i = 0; i < 5; ++i) {
+ _chanInstr[i] = fetchInstrument(READ_BE_UINT16(data + 20 + 2 * i));
+ _chanSndData[i] = data + READ_BE_UINT16(data + 30 + 2 * i) + 6;
+ _chanNumEvents[i] = READ_BE_UINT16(_chanSndData[i] - 2);
+ _chanCurEvent[i] = 0;
+ }
+
+ _synth = synthType;
+
+ return true;
+}
+
+bool LoomMacSndLoader::isInstrUsable(uint16 chan) const {
+ return (chan < ARRAYSIZE(_chanInstr) && _chanInstr[chan] && _chanInstr[chan]->get()->id() != 0x2D1C);
+}
+
+bool LoomMacSndLoader::parseNextEvent(uint16 chan, uint16 &duration, uint8 ¬e, bool &skip, bool &updateInstr) {
+ if (chan >= ARRAYSIZE(_chanSndData) || !_chanSndData[chan] || _chanCurEvent[chan] >= _chanNumEvents[chan])
+ return false;
+
+ const byte *s = _chanSndData[chan] + (_chanCurEvent[chan]++) * 3;
+ duration = READ_BE_UINT16(s);
+ note = s[2] & 0x7f;
+ skip = false;
+ updateInstr = false;
+
+ if (_synth == 4 && chan != 0 && note == 0)
+ note = 1;
+
+ return true;
+}
+
+const Common::SharedPtr<MacSndLoader::Instrument> *LoomMacSndLoader::fetchInstrument(uint16 id) const {
+ Common::Array<Common::SharedPtr<Instrument> >::const_iterator instr = _instruments.end();
+ for (Common::Array<Common::SharedPtr<Instrument> >::const_iterator i = _instruments.begin(); i != _instruments.end(); ++i) {
+ if ((*i)->id() == id)
+ return i;
+ else if ((*i)->id() == 0x2D1C)
+ instr = i;
+ }
+ return (instr != _instruments.end()) ? instr : nullptr;
+}
+
+bool MonkeyMacSndLoader::init() {
+ static const char *execNames[] = {
+ "Monkey Island"
+ };
+
+ return loadInstruments(execNames, ARRAYSIZE(execNames), _numInstrumentsMax - 1);
+}
+
+bool MonkeyMacSndLoader::checkResource(const byte *data, uint32 dataSize) const {
+ return (dataSize >= 14 && (READ_BE_UINT32(data) == 'Mac0' || READ_BE_UINT32(data) == 'Mac1'));
+}
+
+bool MonkeyMacSndLoader::blocked(const byte *data, uint32 dataSize) const {
+ return (dataSize < 14 || (_blockSfx && !data[13]));
+}
+
+bool MonkeyMacSndLoader::loadSound(byte synthType, const byte *data, uint32 dataSize) {
+ if (dataSize < 32)
+ return false;
+
+ _sndRes9 = data[9];
+ _isMusic = data[13];
+ _sndRes10 = data[10];
+ _chanSetup = data[11];
+ _sndRes12 = data[12];
+
+ for (int i = 0; i < 4; ++i) {
+ uint32 offs = READ_BE_UINT32(data + 16 + 4 * i);
+ _chanCurEvent[i] = 0;
+ if (offs) {
+ if (dataSize < offs + 12)
+ return false;
+ _chanInstr[i] = fetchInstrument(data, dataSize, READ_BE_UINT32(data + offs + 8));
+ _chanInstr2[i] = nullptr;
+ _chanSndData[i] = &data[offs + 12];
+ _chanNumEvents[i] = 0;
+
+ for (const byte *s = _chanSndData[i]; s < &data[dataSize - 4]; s += 4) {
+ uint32 in = READ_BE_UINT32(s);
+ if (in == MKTAG('L', 'o', 'o', 'p') || in == MKTAG('D', 'o', 'n', 'e')) {
+ if (i == 1)
+ _loop = (in == MKTAG('L', 'o', 'o', 'p'));
+ break;
+ }
+ _chanNumEvents[i]++;
+ }
+ } else {
+ _chanInstr[i] = nullptr;
+ _chanSndData[i] = nullptr;
+ }
+ }
+
+ _blockSfx = (_isMusic && _loop);
+ _synth = synthType;
+
+ return true;
+}
+
+bool MonkeyMacSndLoader::isInstrUsable(uint16 chan) const {
+ return (chan < ARRAYSIZE(_chanInstr) && _chanInstr[chan] && _chanInstr[chan]->get()->id() != MKTAG('s', 'i', 'l', 'e'));
+}
+
+bool MonkeyMacSndLoader::parseNextEvent(uint16 chan, uint16 &duration, uint8 ¬e, bool &skip, bool &updateInstr) {
+ if (chan >= ARRAYSIZE(_chanSndData) || !_chanSndData[chan] || _chanCurEvent[chan] >= _chanNumEvents[chan])
+ return false;
+
+ const byte *s = _chanSndData[chan] + (_chanCurEvent[chan]++) * 4;
+ duration = READ_BE_UINT16(s);
+ note = s[2];
+ skip = false;
+ updateInstr = true;
+
+ if (duration == 0 && _chanCurEvent[chan] == _chanNumEvents[chan])
+ skip = true;
+
+ if (_synth == 4) {
+ if (!skip && note == 0) {
+ note = 60;
+ _chanInstr2[chan] = _chanInstr[chan];
+ _chanInstr[chan] = fetchInstrument(nullptr, 0, MKTAG('s', 'i', 'l', 'e'));
+ } else if (_chanInstr2[chan]) {
+ _chanInstr[chan] = _chanInstr2[chan];
+ _chanInstr2[chan] = nullptr;
+ } else {
+ updateInstr = false;
+ }
+ if (note == 1)
+ skip = true;
+ else if (s[6] == 1)
+ duration += READ_BE_UINT16(s + 4);
+ } else {
+ updateInstr = false;
+ if (note == 1)
+ note = 0;
+ else if (note != 0)
+ note += _transpose;
+ }
+
+ return true;
+}
+
+const Common::SharedPtr<MacSndLoader::Instrument> *MonkeyMacSndLoader::fetchInstrument(const byte *data, uint32 dataSize, uint32 tagOrOffset) {
+ Common::Array<Common::SharedPtr<Instrument> >::const_iterator instr = _instruments.end();
+ if (tagOrOffset & ~0x7fffff) {
+ for (Common::Array<Common::SharedPtr<Instrument> >::const_iterator i = _instruments.begin(); i != _instruments.end(); ++i) {
+ if ((*i)->id() == tagOrOffset)
+ return i;
+ else if ((*i)->id() == MKTAG('s', 'i', 'l', 'e'))
+ instr = i;
+ }
+ } else if (dataSize >= tagOrOffset + 8) {
+ Common::SeekableReadStream *str = new Common::MemoryReadStream(&data[tagOrOffset + 8], READ_BE_UINT32(data + tagOrOffset + 4), DisposeAfterUse::NO);
+ if (_instruments.size() == _numInstrumentsMax)
+ _instruments.pop_back();
+ _instruments.push_back(Common::SharedPtr<Instrument>(new Instrument(READ_BE_UINT32(&data[tagOrOffset]), str, Common::String())));
+ delete str;
+ instr = _instruments.end() - 1;
+ }
+ return (instr != _instruments.end()) ? instr : nullptr;
+}
+
+Common::WeakPtr<LoomMonkeyMacSnd> *LoomMonkeyMacSnd::_inst = nullptr;
+
+LoomMonkeyMacSnd::LoomMonkeyMacSnd(ScummEngine *vm, Audio::Mixer *mixer) : VblTaskClientDriver(), _vm(vm), _mixer(mixer), _curSound(0), _loader(nullptr),
+ _macstr(nullptr), _sdrv(nullptr), _vblTskProc(this, &VblTaskClientDriver::vblCallback), _songTimer(0), _songTimerInternal(0),
+ _machineRating(0), _selectedQuality(2), _effectiveChanConfig(0), _16bit(false), _idRangeMax(200), _sndChannel(0), _chanUse(0), _defaultChanConfig(0),
+ _chanConfigTable(nullptr), _chanPlaying(0), _curChanConfig(0), _curSynthType(0), _curSndType(Audio::Mixer::kPlainSoundType), _mixerThread(false),
+ _restartSound(0), _lastSndType(Audio::Mixer::kPlainSoundType), _chanCbProc(this, &MacLowLevelPCMDriver::CallbackClient::sndChannelCallback),
+ _curSoundSaveVar(0), _saveVersionChange(vm->_game.id == GID_MONKEY ? 115 : 114), _legacySaveUnits(vm->_game.id == GID_MONKEY ? 3 : 5) {
+ assert(_vm);
+ assert(_mixer);
+
+ static const byte cfgtable[] = { 0, 0, 0, 1, 4, 5, 1, 5, 6, 6, 8, 9 };
+ _chanConfigTable = new byte[sizeof(cfgtable)]();
+ memcpy(_chanConfigTable, cfgtable, sizeof(cfgtable));
+
+ if (vm->_game.id == GID_MONKEY)
+ _chanConfigTable[10] = 7;
+
+ memset(_musChannels, 0, sizeof(_musChannels));
+}
+
+LoomMonkeyMacSnd::~LoomMonkeyMacSnd() {
+ _mixer->stopHandle(_soundHandle);
+ delete _macstr;
+ delete[] _chanConfigTable;
+
+ disposeAllChannels();
+ delete _sdrv;
+ delete _loader;
+
+ delete _inst;
+ _inst = nullptr;
+}
+
+Common::SharedPtr<LoomMonkeyMacSnd> LoomMonkeyMacSnd::open(ScummEngine *vm, Audio::Mixer *mixer) {
+ Common::SharedPtr<LoomMonkeyMacSnd> scp = nullptr;
+
+ if (_inst == nullptr) {
+ scp = Common::SharedPtr<LoomMonkeyMacSnd>(new LoomMonkeyMacSnd(vm, mixer));
+ _inst = new Common::WeakPtr<LoomMonkeyMacSnd>(scp);
+ // We can start this with the ScummVM mixer output rate instead of the ASC rate. The Mac sample rate converter can handle it (at
+ // least for up to 48 KHz, I haven't tried higher settings) and we don't have to do another rate conversion in the ScummVM mixer.
+ if ((_inst == nullptr) || (mixer == nullptr) || !(scp->startDevice(mixer->getOutputRate(), mixer->getOutputRate() << 16/*ASC_DEVICE_RATE*/, PCM_BUFFER_SIZE, true, false, true)))
+ error("LoomMonkeyMacSnd::open(): Failed to start player");
+ }
+
+ return _inst->lock();
+}
+
+bool LoomMonkeyMacSnd::startDevice(uint32 outputRate, uint32 pcmDeviceRate, uint32 feedBufferSize, bool enableInterpolation, bool stereo, bool internal16Bit) {
+ _macstr = new MacPlayerAudioStream(this, outputRate, stereo, enableInterpolation, internal16Bit);
+ if (!_macstr || !_mixer)
+ return false;
+
+ if (_vm->_game.id == GID_LOOM)
+ _loader = new LoomMacSndLoader();
+ else if(_vm->_game.id == GID_MONKEY)
+ _loader = new MonkeyMacSndLoader();
+
+ if (!_loader || !_loader->init())
+ return false;
+
+ _sdrv = new MacLowLevelPCMDriver(_mixer->mutex(), pcmDeviceRate, internal16Bit);
+ if (!_sdrv)
+ return false;
+
+ _effectiveChanConfig = 9;
+ _16bit = internal16Bit;
+
+ _macstr->initDrivers();
+ _macstr->initBuffers(feedBufferSize);
+ _macstr->setVblCallback(&_vblTskProc);
+
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, _macstr, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
+ return true;
+}
+
+void LoomMonkeyMacSnd::setMusicVolume(int vol) {
+ Common::StackLock lock(_mixer->mutex());
+ if (_macstr)
+ _macstr->setMasterVolume(Audio::Mixer::kMusicSoundType, vol);
+}
+
+void LoomMonkeyMacSnd::setSfxVolume(int vol) {
+ Common::StackLock lock(_mixer->mutex());
+ if (_macstr)
+ _macstr->setMasterVolume(Audio::Mixer::kSFXSoundType, vol);
+}
+
+void LoomMonkeyMacSnd::startSound(int id, int jumpToTick) {
+ if (_sdrv == nullptr || id < 0 || id >= _idRangeMax) {
+ warning("LoomMonkeyMacSnd::startSound(): sound id '%d' out of range (0 - %d)", id, _idRangeMax - 1);
+ return;
+ }
+
+ Common::StackLock lock(_mixer->mutex());
+
+ uint32 size = _vm->getResourceSize(rtSound, id);
+ const byte *ptr = _vm->getResourceAddress(rtSound, id);
+ assert(ptr);
+
+ if (!_loader->checkResource(ptr, size)) {
+ warning("LoomMonkeyMacSnd::startSound(): Sound resource '%d' cannot be played", id);
+ return;
+ }
+
+ if (_loader->blocked(ptr, size))
+ return;
+
+ stopActiveSound();
+ if (_chanUse <= 1)
+ disposeAllChannels();
+
+ if (!_defaultChanConfig)
+ detectQuality();
+
+ if (!_loader->loadSound(_curSynthType, ptr, size)) {
+ warning("LoomMonkeyMacSnd::startSound(): Sound resource '%d' cannot be played", id);
+ return;
+ }
+
+ //if (_sndDisableFlags && _loader->isMusic())
+ // return;
+
+ _effectiveChanConfig = _loader->getChanSetup() ? _loader->getChanSetup() : _defaultChanConfig;
+ _curSndType = _loader->isMusic() ? Audio::Mixer::kMusicSoundType : Audio::Mixer::kSFXSoundType;
+
+ if (_lastSndType != _curSndType)
+ _curChanConfig = 0;
+
+ _curSound = id;
+ _curSoundSaveVar = _loader->isMusic() && _loader->isLooping() ? _curSound : 0;
+
+ setupChannels();
+ sendSoundCommands(jumpToTick);
+
+ if (!jumpToTick) {
+ _songTimer = 0;
+ _songTimerInternal = 0;
+ }
+}
+
+void LoomMonkeyMacSnd::stopSound(int id) {
+ if (id < 0 || id >= _idRangeMax) {
+ warning("LoomMonkeyMacSnd::stopSound(): sound id '%d' out of range (0 - %d)", id, _idRangeMax - 1);
+ return;
+ }
+
+ Common::StackLock lock(_mixer->mutex());
+
+ if (id == _curSound)
+ stopActiveSound();
+}
+
+void LoomMonkeyMacSnd::stopAllSounds() {
+ Common::StackLock lock(_mixer->mutex());
+ stopActiveSound();
+}
+
+int LoomMonkeyMacSnd::getMusicTimer() {
+ Common::StackLock lock(_mixer->mutex());
+ return _songTimer;
+}
+
+int LoomMonkeyMacSnd::getSoundStatus(int id) const {
+ if (id < 0 || id >= _idRangeMax) {
+ warning("LoomMonkeyMacSnd::getSoundStatus(): sound id '%d' out of range (0 - %d)", id, _idRangeMax - 1);
+ return 0;
+ }
+ Common::StackLock lock(_mixer->mutex());
+ return (_curSound == id) ? 1 : 0;
+}
+
+void LoomMonkeyMacSnd::setQuality(int qual) {
+ assert(qual >= MacSound::kQualityAuto && qual <= MacSound::kQualityHighest);
+ Common::StackLock lock(_mixer->mutex());
+
+ if (qual > MacSound::kQualityAuto) {
+ qual--;
+ if (!_loader->ignoreMachineRating())
+ _machineRating = (qual / 3) + 1;
+ _selectedQuality = qual % 3;
+ qual = _chanConfigTable[_machineRating * 3 + _selectedQuality];
+ if (qual && qual == _defaultChanConfig)
+ return;
+ }
+
+ int csnd = _curSound;
+ int32 timeStamp = csnd ? _songTimer * 1000 + ((_songTimerInternal * 1000) / 30) : 0;
+ stopActiveSound();
+
+ detectQuality();
+ if (csnd)
+ startSound(csnd, timeStamp);
+}
+
+void LoomMonkeyMacSnd::saveLoadWithSerializer(Common::Serializer &ser) {
+ if (ser.isLoading() && ser.getVersion() < VER(94)) {
+ _curSound = _curSoundSaveVar = 0;
+ return;
+ }
+
+ if (ser.isLoading()) {
+ if (ser.getVersion() < VER(_saveVersionChange)) {
+ // Skip over old driver savedata, since it is not needed here.
+ ser.skip(4);
+ // We need only this
+ ser.syncAsSint16LE(_curSound);
+ _curSoundSaveVar = CLIP<int>(_curSound, 0, _idRangeMax - 1);
+ // Skip the rest
+ ser.skip(_legacySaveUnits * (ser.getVersion() >= VER(94) && ser.getVersion() <= VER(103) ? 24 : 20));
+ } else if (ser.getVersion() <= VER(114)) {
+ _curSoundSaveVar = 0;
+ byte tmp = 0;
+ for (int i = 0; !_curSoundSaveVar && i < 200; ++i) {
+ ser.syncAsByte(tmp);
+ if (tmp)
+ _curSoundSaveVar = i;
+ }
+ }
+ }
+ ser.syncAsSint16LE(_curSoundSaveVar, VER(115));
+}
+
+void LoomMonkeyMacSnd::restoreAfterLoad() {
+ int sound = _curSoundSaveVar;
+ stopActiveSound();
+ startSound(sound);
+}
+
+void LoomMonkeyMacSnd::vblCallback() {
+ if (_songTimerInternal++ == 29) {
+ _songTimerInternal = 0;
+ ++_songTimer;
+ }
+
+ if (_restartSound) {
+ startSound(_restartSound);
+ _restartSound = 0;
+ }
+}
+
+void LoomMonkeyMacSnd::generateData(int8 *dst, uint32 len, Audio::Mixer::SoundType type, bool expectStereo) const {
+ assert(dst);
+ memset(dst, 0, len);
+ _sdrv->feed(dst, len, type, expectStereo);
+}
+
+const MacSoundDriver::Status &LoomMonkeyMacSnd::getDriverStatus(uint8, Audio::Mixer::SoundType sndType) const {
+ return _sdrv->getStatus(sndType);
+}
+
+void LoomMonkeyMacSnd::sndChannelCallback(uint16 arg1, const void*) {
+ // We do this a little smarter than the original player which would stop the track immediately when
+ // the first channel invoked its end-of-track callback. This would cut of the playback early, in an
+ // unpleasant way. Instead, we stop the playback not before all channels have finished.
+ _chanPlaying &= ~arg1;
+ if (_chanPlaying)
+ return;
+
+ if (_loader->isLooping())
+ _restartSound = _curSound;
+
+ stopActiveSound();
+}
+
+void LoomMonkeyMacSnd::sendSoundCommands(int timeStamp) {
+ if (!_defaultChanConfig || !_curSound)
+ return;
+
+ uint16 duration = 0;
+ byte note = 0;
+ bool skip = false;
+ bool updateInstr = false;
+ _chanPlaying = 0;
+
+ if (_chanUse == 1 && _sndChannel) {
+ while (_loader->parseNextEvent(0, duration, note, skip, updateInstr)) {
+ if (timeStamp > 0) {
+ int ts = timeStamp;
+ timeStamp = MAX<int>(0, timeStamp - duration);
+ duration -= ts;
+ }
+ if (timeStamp)
+ continue;
+
+ if (updateInstr)
+ _sdrv->loadInstrument(_sndChannel, MacLowLevelPCMDriver::kEnqueue, _loader->getInstrData(0));
+
+ if (!skip) {
+ _sdrv->playNote(_sndChannel, MacLowLevelPCMDriver::kEnqueue, note, duration);
+ if (note == 0) // Workaround for tempo glitch in original driver
+ _sdrv->wait(_sndChannel, MacLowLevelPCMDriver::kEnqueue, duration);
+ }
+ }
+ _sdrv->quiet(_sndChannel, MacLowLevelPCMDriver::kEnqueue);
+ _sdrv->callback(_sndChannel, MacLowLevelPCMDriver::kEnqueue, 1, nullptr);
+ _chanPlaying |= 1;
+
+ } else if (_chanUse == 4) {
+ int tmstmp[4];
+ uint8 busy = 0;
+
+ for (int i = 0; i < 4; ++i) {
+ tmstmp[i] = timeStamp;
+ if (_musChannels[i])
+ busy |= (1 << i);
+ }
+
+ while (busy) {
+ for (int i = 0; i < 4; ++i) {
+ if (!(busy & (1 << i)) || !_loader->parseNextEvent(i + 1, duration, note, skip, updateInstr)) {
+ busy &= ~(1 << i);
+ continue;
+ }
+ if (tmstmp[i] > 0) {
+ int ts = tmstmp[i];
+ tmstmp[i] = MAX<int>(0, tmstmp[i] - duration);
+ duration -= ts;
+ }
+
+ if (tmstmp[i])
+ continue;
+
+ if (updateInstr)
+ _sdrv->loadInstrument(_musChannels[i], MacLowLevelPCMDriver::kEnqueue, _loader->getInstrData(i + 1));
+
+ if (!skip) {
+ _sdrv->playNote(_musChannels[i], MacLowLevelPCMDriver::kEnqueue, note, duration);
+ // Workaround for tempo glitch in original driver. For the sampled synth in 4 channel mode, there is
+ // some sort of fix in the original (see parseNextEvent()), but that really does not work well for the other cases.
+ if (note == 0 && _curSynthType != 4)
+ _sdrv->wait(_musChannels[i], MacLowLevelPCMDriver::kEnqueue, duration);
+ }
+ _chanPlaying |= (1 << i);
+ }
+ }
+
+
+ for (int i = 0; i < 4; ++i) {
+ if (_chanPlaying & (1 << i)) {
+ _sdrv->quiet(_musChannels[i], MacLowLevelPCMDriver::kEnqueue);
+ _sdrv->callback(_musChannels[i], MacLowLevelPCMDriver::kEnqueue, 1 << i, nullptr);
+ }
+ }
+ }
+}
+
+void LoomMonkeyMacSnd::stopActiveSound() {
+ if (_sndChannel) {
+ _sdrv->quiet(_sndChannel, MacLowLevelPCMDriver::kImmediate);
+ _sdrv->flush(_sndChannel, MacLowLevelPCMDriver::kImmediate);
+ }
+
+ for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
+ if (_musChannels[i]) {
+ _sdrv->quiet(_musChannels[i], MacLowLevelPCMDriver::kImmediate);
+ _sdrv->flush(_musChannels[i], MacLowLevelPCMDriver::kImmediate);
+ }
+ }
+
+ _chanPlaying = 0;
+ _curSound = 0;
+ _curSoundSaveVar = 0;
+ _loader->unblock();
+}
+
+void LoomMonkeyMacSnd::setupChannels() {
+ static const byte synthType[] = { 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x02, 0x04, 0x04, 0x04 };
+ static const byte numChan[] = { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04 };
+ static const byte attrib[] = { 0x00, 0x00, 0x04, 0xAC, 0xA4, 0xA0, 0x04, 0xAC, 0xA4, 0xA0 };
+
+ if (!_defaultChanConfig)
+ return;
+
+ if (_curChanConfig != _effectiveChanConfig) {
+ disposeAllChannels();
+ _curChanConfig = _effectiveChanConfig;
+ _curSynthType = synthType[_curChanConfig];
+ _chanUse = numChan[_curChanConfig];
+ _lastSndType = _curSndType;
+
+ switch (_curSynthType) {
+ case 1:
+ if (_chanUse == 1 && !_sndChannel) {
+ _sndChannel = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kSquareWaveSynth, attrib[_curChanConfig], &_chanCbProc);
+ }
+ break;
+ case 2:
+ if (_chanUse == 1 && !_sndChannel) {
+ _sndChannel = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kWaveTableSynth, attrib[_curChanConfig], &_chanCbProc);
+ } else if (_chanUse == 4) {
+ for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
+ if (!_musChannels[i] && _loader->isInstrUsable(i + 1))
+ _musChannels[i] = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kWaveTableSynth, attrib[_curChanConfig] + i, &_chanCbProc);
+ }
+ }
+ break;
+ case 4:
+ if (_chanUse == 1 && !_sndChannel) {
+ _sndChannel = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kSampledSynth, attrib[_curChanConfig], &_chanCbProc);
+ } else if (_chanUse == 4) {
+ for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
+ if (!_musChannels[i] && _loader->isInstrUsable(i + 1))
+ _musChannels[i] = _sdrv->createChannel(_curSndType, MacLowLevelPCMDriver::kSampledSynth, attrib[_curChanConfig], &_chanCbProc);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (_curSynthType) {
+ case 1:
+ if (_sndChannel)
+ _sdrv->setTimbre(_sndChannel, MacLowLevelPCMDriver::kImmediate, _loader->getTimbre());
+ break;
+ case 2:
+ if (_chanUse == 1) {
+ if (_sndChannel)
+ _sdrv->loadWaveTable(_sndChannel, MacLowLevelPCMDriver::kImmediate, _fourToneSynthWaveForm, _fourToneSynthWaveFormSize);
+ } else {
+ for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
+ if (_musChannels[i])
+ _sdrv->loadWaveTable(_musChannels[i], MacLowLevelPCMDriver::kImmediate, _fourToneSynthWaveForm, _fourToneSynthWaveFormSize);
+ }
+ }
+ break;
+ case 4:
+ if (_chanUse == 1) {
+ if (_sndChannel && _loader->getInstrData(0))
+ _sdrv->loadInstrument(_sndChannel, MacLowLevelPCMDriver::kImmediate, _loader->getInstrData(0));
+ } else {
+ for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
+ if (_musChannels[i] && _loader->getInstrData(i + 1))
+ _sdrv->loadInstrument(_musChannels[i], MacLowLevelPCMDriver::kImmediate, _loader->getInstrData(i + 1));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void LoomMonkeyMacSnd::disposeAllChannels() {
+ if (_sndChannel)
+ _sdrv->disposeChannel(_sndChannel);
+ _sndChannel = 0;
+
+ for (int i = 0; i < ARRAYSIZE(_musChannels); ++i) {
+ if (_musChannels[i])
+ _sdrv->disposeChannel(_musChannels[i]);
+ _musChannels[i] = 0;
+ }
+
+ _curChanConfig = 0;
+}
+
+void LoomMonkeyMacSnd::detectQuality() {
+ if (_machineRating == 0) {
+ if (!_loader->ignoreMachineRating()) {
+ if (isSoundCardType10())
+ _machineRating = 2;
+ /*else if (0)
+ _machineRating = 1;*/
+ }
+ _machineRating ^= 3;
+ }
+
+ _defaultChanConfig = _effectiveChanConfig = _chanConfigTable[_machineRating * 3 + _selectedQuality];
+ _curChanConfig = 0;
+ disposeAllChannels();
+ setupChannels();
+ _chanConfigTable[_machineRating * 3 + _selectedQuality] = _defaultChanConfig;
+}
+
+bool LoomMonkeyMacSnd::isSoundCardType10() const {
+ return _mixerThread ? (_machineRating == 1) : (_vm->VAR_SOUNDCARD != 0xff && _vm->VAR(_vm->VAR_SOUNDCARD) == 10);
+}
+
+#undef ASC_DEVICE_RATE
+#undef PCM_BUFFER_SIZE
+
+} // End of namespace Scumm
diff --git a/engines/scumm/players/player_mac_new.cpp b/engines/scumm/players/player_mac_new.cpp
index 7c0e5b5866d..a37c235641c 100644
--- a/engines/scumm/players/player_mac_new.cpp
+++ b/engines/scumm/players/player_mac_new.cpp
@@ -1050,7 +1050,7 @@ const uint8 _fourToneSynthWaveForm[256] = {
const uint32 _fourToneSynthWaveFormSize = sizeof(_fourToneSynthWaveForm);
class Indy3MacSnd;
-class LoomMacSnd;
+class LoomMonkeyMacSnd;
template<typename T> class MusicEngineImpl : public MusicEngine {
public:
@@ -1138,7 +1138,8 @@ MusicEngine *createPlayer(ScummEngine *vm) {
res = new MusicEngineImpl<Indy3MacSnd>(vm, vm->_mixer);
break;
case GID_LOOM:
- res = new MusicEngineImpl<LoomMacSnd>(vm, vm->_mixer);
+ case GID_MONKEY:
+ res = new MusicEngineImpl<LoomMonkeyMacSnd>(vm, vm->_mixer);
break;
default:
break;
diff --git a/engines/scumm/players/player_mac_new.h b/engines/scumm/players/player_mac_new.h
index 3015880dbc8..d63be962fa5 100644
--- a/engines/scumm/players/player_mac_new.h
+++ b/engines/scumm/players/player_mac_new.h
@@ -32,6 +32,12 @@ namespace MacSound {
enum {
kQualityAuto = 0,
kQualityLowest = 1,
+ kHardwareRatingLow = 0,
+ kHardwareRatingMedium = 3,
+ kHardwareRatingHigh = 6,
+ kQualitySelectionGood = 1,
+ kQualitySelectionBetter = 2,
+ kQualitySelectionBest = 3,
kQualityHighest = 9
};
diff --git a/engines/scumm/players/player_v5m.cpp b/engines/scumm/players/player_v5m.cpp
index c113aad04c7..cba59227780 100644
--- a/engines/scumm/players/player_v5m.cpp
+++ b/engines/scumm/players/player_v5m.cpp
@@ -83,6 +83,7 @@ namespace Scumm {
Player_V5M::Player_V5M(ScummEngine *scumm, Audio::Mixer *mixer)
: Player_Mac(scumm, mixer, 3, 0x07, false) {
assert(_vm->_game.id == GID_MONKEY);
+ //_lastVersionBeforeSaveFormatChange = VER(114);
}
bool Player_V5M::loadMusic(const byte *ptr) {
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index cd0913afbe0..1f26b094d48 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -69,7 +69,7 @@ struct SaveInfoSection {
#define SaveInfoSectionSize (4+4+4 + 4+4 + 4+2)
-#define CURRENT_VER 114
+#define CURRENT_VER 115
#define INFOSECTION_VERSION 2
#pragma mark -
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index c4787408e87..b529b699ebe 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2166,11 +2166,14 @@ void ScummEngine::setupMusic(int midi, const Common::Path &macInstrumentFile) {
#endif
} else if (_game.platform == Common::kPlatformAmiga && _game.version <= 4) {
_musicEngine = new Player_V4A(this, _mixer);
- } else if (_game.platform == Common::kPlatformMacintosh && (_game.id == GID_INDY3 || _game.id == GID_LOOM)) {
-#if 0
+ } else if (_game.platform == Common::kPlatformMacintosh && (_game.id == GID_INDY3 || _game.id == GID_LOOM || _game.id == GID_MONKEY)) {
+#if 1
if (_game.id == GID_LOOM) {
_musicEngine = new Player_V3M(this, _mixer, ConfMan.getBool("mac_v3_low_quality_music"));
((Player_V3M *)_musicEngine)->init(macInstrumentFile);
+ } else if (_game.id == GID_MONKEY) {
+ _musicEngine = new Player_V5M(this, _mixer);
+ ((Player_V5M *)_musicEngine)->init(macInstrumentFile);
} else
#endif
{
@@ -2181,9 +2184,6 @@ void ScummEngine::setupMusic(int midi, const Common::Path &macInstrumentFile) {
_musicEngine->setQuality(ConfMan.getInt("mac_snd_quality"));
_sound->_musicType = MDT_MACINTOSH;
}
- } else if (_game.platform == Common::kPlatformMacintosh && _game.id == GID_MONKEY) {
- _musicEngine = new Player_V5M(this, _mixer);
- ((Player_V5M *)_musicEngine)->init(macInstrumentFile);
} else if (_game.id == GID_MANIAC && _game.version == 1) {
_musicEngine = new Player_V1(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK);
} else if (_game.version <= 2) {
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 6526a742a0f..1007fd952b0 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -382,24 +382,6 @@ void Sound::triggerSound(int soundID) {
return;
}
- // Support for SFX in Monkey Island 1, Mac version
- // This is rather hackish right now, but works OK. SFX are not sounding
- // 100% correct, though, not sure right now what is causing this.
- else if (READ_BE_UINT32(ptr) == MKTAG('M','a','c','1')) {
- // Read info from the header
- size = READ_BE_UINT32(ptr+0x60);
- rate = READ_BE_UINT16(ptr+0x64);
-
- // Skip over the header (fixed size)
- ptr += 0x72;
-
- // Allocate a sound buffer, copy the data into it, and play
- sound = (byte *)malloc(size);
- memcpy(sound, ptr, size);
-
- stream = Audio::makeRawStream(sound, size, rate, Audio::FLAG_UNSIGNED);
- _mixer->playStream(Audio::Mixer::kSFXSoundType, nullptr, stream, soundID);
- }
// WORKAROUND bug #2221
else if (READ_BE_UINT32(ptr) == 0x460e200d) {
// This sound resource occurs in the Macintosh version of Monkey Island.
diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp
index ae7c807bf7e..ac6269c70fe 100644
--- a/engines/scumm/vars.cpp
+++ b/engines/scumm/vars.cpp
@@ -862,6 +862,8 @@ void ScummEngine::setSoundCardVarToCurrentConfig() {
VAR(VAR_SOUNDCARD) = (ConfMan.hasKey("mac_v3_low_quality_music") && ConfMan.getBool("mac_v3_low_quality_music")) ? 10 : 11;
else if (_game.id == GID_LOOM)
VAR(VAR_SOUNDCARD) = (ConfMan.hasKey("mac_snd_quality") && ConfMan.getInt("mac_snd_quality") > 0 && ConfMan.getInt("mac_snd_quality") < 4) ? 10 : 11;
+ else if (_game.id == GID_MONKEY)
+ VAR(VAR_SOUNDCARD) = 0xffff;
else
VAR(VAR_SOUNDCARD) = 3;
break;
More information about the Scummvm-git-logs
mailing list