aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/player
diff options
context:
space:
mode:
Diffstat (limited to 'engines/scumm/player')
-rw-r--r--engines/scumm/player/ad.cpp959
-rw-r--r--engines/scumm/player/ad.h190
-rw-r--r--engines/scumm/player/apple2.cpp500
-rw-r--r--engines/scumm/player/apple2.h297
-rw-r--r--engines/scumm/player/mac.cpp419
-rw-r--r--engines/scumm/player/mac.h133
-rw-r--r--engines/scumm/player/mod.cpp223
-rw-r--r--engines/scumm/player/mod.h100
-rw-r--r--engines/scumm/player/nes.cpp1067
-rw-r--r--engines/scumm/player/nes.h114
-rw-r--r--engines/scumm/player/pce.cpp756
-rw-r--r--engines/scumm/player/pce.h133
-rw-r--r--engines/scumm/player/sid.cpp1384
-rw-r--r--engines/scumm/player/sid.h276
-rw-r--r--engines/scumm/player/towns.cpp753
-rw-r--r--engines/scumm/player/towns.h180
-rw-r--r--engines/scumm/player/v1.cpp607
-rw-r--r--engines/scumm/player/v1.h98
-rw-r--r--engines/scumm/player/v2.cpp327
-rw-r--r--engines/scumm/player/v2.h72
-rw-r--r--engines/scumm/player/v2a.cpp1954
-rw-r--r--engines/scumm/player/v2a.h73
-rw-r--r--engines/scumm/player/v2base.cpp654
-rw-r--r--engines/scumm/player/v2base.h145
-rw-r--r--engines/scumm/player/v2cms.cpp787
-rw-r--r--engines/scumm/player/v2cms.h177
-rw-r--r--engines/scumm/player/v3a.cpp357
-rw-r--r--engines/scumm/player/v3a.h101
-rw-r--r--engines/scumm/player/v3m.cpp214
-rw-r--r--engines/scumm/player/v3m.h54
-rw-r--r--engines/scumm/player/v4a.cpp190
-rw-r--r--engines/scumm/player/v4a.h96
-rw-r--r--engines/scumm/player/v5m.cpp246
-rw-r--r--engines/scumm/player/v5m.h57
34 files changed, 0 insertions, 13693 deletions
diff --git a/engines/scumm/player/ad.cpp b/engines/scumm/player/ad.cpp
deleted file mode 100644
index d3cd0483b6..0000000000
--- a/engines/scumm/player/ad.cpp
+++ /dev/null
@@ -1,959 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "scumm/player/ad.h"
-#include "scumm/imuse/imuse.h"
-#include "scumm/scumm.h"
-#include "scumm/resource.h"
-
-#include "audio/fmopl.h"
-
-#include "common/textconsole.h"
-#include "common/config-manager.h"
-
-namespace Scumm {
-
-#define AD_CALLBACK_FREQUENCY 472
-
-Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
- : _vm(scumm), _mixer(mixer), _rate(mixer->getOutputRate()) {
- _opl2 = OPL::Config::create();
- if (!_opl2->init(_rate)) {
- error("Could not initialize OPL2 emulator");
- }
-
- _samplesPerCallback = _rate / AD_CALLBACK_FREQUENCY;
- _samplesPerCallbackRemainder = _rate % AD_CALLBACK_FREQUENCY;
- _samplesTillCallback = 0;
- _samplesTillCallbackRemainder = 0;
-
- memset(_registerBackUpTable, 0, sizeof(_registerBackUpTable));
- writeReg(0x01, 0x00);
- writeReg(0xBD, 0x00);
- writeReg(0x08, 0x00);
- writeReg(0x01, 0x20);
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- _engineMusicTimer = 0;
- _soundPlaying = -1;
-
- _curOffset = 0;
-
- _sfxTimer = 4;
- _rndSeed = 1;
-
- memset(_channels, 0, sizeof(_channels));
- memset(_sfxResource, 0, sizeof(_sfxResource));
- memset(_sfxPriority, 0, sizeof(_sfxPriority));
-}
-
-Player_AD::~Player_AD() {
- _mixer->stopHandle(_soundHandle);
-
- stopAllSounds();
- Common::StackLock lock(_mutex);
- delete _opl2;
- _opl2 = 0;
-}
-
-void Player_AD::setMusicVolume(int vol) {
- // HACK: We ignore the parameter and set up the volume specified in the
- // config manager. This allows us to differentiate between music and sfx
- // volume changes.
- setupVolume();
-}
-
-void Player_AD::startSound(int sound) {
- Common::StackLock lock(_mutex);
-
- // Query the sound resource
- const byte *res = _vm->getResourceAddress(rtSound, sound);
-
- if (res[2] == 0x80) {
- // Stop the current sounds
- stopAllSounds();
-
- // Lock the new music resource
- _soundPlaying = sound;
- _vm->_res->lock(rtSound, _soundPlaying);
-
- // Start the new music resource
- _resource = res;
- startMusic();
- } else {
- // Only try to start a sfx when no music is playing.
- if (_soundPlaying == -1) {
- const byte priority = res[0];
- const byte channel = res[1];
-
- // Check for out of bounds access
- if (channel >= 3) {
- warning("AdLib sfx resource %d uses channel %d", sound, channel);
- return;
- }
-
- // Check whether the channel is free or the priority of the new
- // sfx resource is above the old one.
- if (_channels[channel * 3 + 0].state
- || _channels[channel * 3 + 1].state
- || _channels[channel * 3 + 2].state) {
- if (_sfxPriority[channel] > priority) {
- return;
- }
- }
-
- // Lock the new resource
- _sfxResource[channel] = sound;
- _sfxPriority[channel] = priority;
- _vm->_res->lock(rtSound, sound);
-
- // Start the actual sfx resource
- _resource = res;
- startSfx();
- }
- }
-
- // Setup the sound volume
- setupVolume();
-}
-
-void Player_AD::stopSound(int sound) {
- Common::StackLock lock(_mutex);
-
- if (sound == _soundPlaying) {
- stopAllSounds();
- } else {
- for (int i = 0; i < 3; ++i) {
- if (_sfxResource[i] == sound) {
- if (_channels[i * 3 + 0].state
- || _channels[i * 3 + 1].state
- || _channels[i * 3 + 2].state) {
- // Unlock the sound resource
- _vm->_res->unlock(rtSound, sound);
-
- // Stop the actual sfx playback
- _channels[i * 3 + 0].state = 0;
- _channels[i * 3 + 1].state = 0;
- _channels[i * 3 + 2].state = 0;
- clearChannel(i * 3 + 0);
- clearChannel(i * 3 + 1);
- clearChannel(i * 3 + 2);
- }
- }
- }
- }
-}
-
-void Player_AD::stopAllSounds() {
- Common::StackLock lock(_mutex);
-
- // Unlock the music resource if present
- if (_soundPlaying != -1) {
- _vm->_res->unlock(rtSound, _soundPlaying);
- _soundPlaying = -1;
- }
-
- // Stop the music playback
- _curOffset = 0;
-
- // Unloack all used sfx resources
- for (int i = 0; i < 3; ++i) {
- if (_channels[i * 3 + 0].state || _channels[i * 3 + 1].state || _channels[i * 3 + 2].state) {
- _vm->_res->unlock(rtSound, _sfxResource[i]);
- }
- }
-
- // Reset all the sfx channels
- for (int i = 0; i < 9; ++i) {
- _channels[i].state = 0;
- clearChannel(i);
- }
-
- writeReg(0xBD, 0x00);
-}
-
-int Player_AD::getMusicTimer() {
- return _engineMusicTimer;
-}
-
-int Player_AD::getSoundStatus(int sound) const {
- return (sound == _soundPlaying);
-}
-
-void Player_AD::saveLoadWithSerializer(Serializer *ser) {
- Common::StackLock lock(_mutex);
-
- if (ser->getVersion() < VER(95)) {
- IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL);
- dummyImuse->save_or_load(ser, _vm, false);
- delete dummyImuse;
- return;
- }
-
- // TODO: Be nicer than the original and save the data to continue the
- // currently played sound resources on load?
-}
-
-int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- int len = numSamples;
-
- while (len > 0) {
- if (!_samplesTillCallback) {
- // Run the update callback for music or sfx depending on which is
- // active.
- if (_curOffset) {
- updateMusic();
- } else {
- updateSfx();
- }
-
- _samplesTillCallback = _samplesPerCallback;
- _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
- if (_samplesTillCallbackRemainder >= AD_CALLBACK_FREQUENCY) {
- ++_samplesTillCallback;
- _samplesTillCallbackRemainder -= AD_CALLBACK_FREQUENCY;
- }
- }
-
- const int samplesToRead = MIN(len, _samplesTillCallback);
- _opl2->readBuffer(buffer, samplesToRead);
-
- buffer += samplesToRead;
- len -= samplesToRead;
- _samplesTillCallback -= samplesToRead;
- }
-
- return numSamples;
-}
-
-void Player_AD::setupVolume() {
- // Setup the correct volume
- int soundVolumeMusic = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume);
- int soundVolumeSfx = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume);
- if (ConfMan.hasKey("mute")) {
- if (ConfMan.getBool("mute")) {
- soundVolumeMusic = 0;
- soundVolumeSfx = 0;
- }
- }
-
- // In case a music is being played set the music volume. Set the sfx
- // volume otherwise. This is safe because in the latter case either
- // sfx are playing or there is no sound being played at all.
- if (_soundPlaying != -1) {
- _mixer->setChannelVolume(_soundHandle, soundVolumeMusic);
- } else {
- _mixer->setChannelVolume(_soundHandle, soundVolumeSfx);
- }
-}
-
-void Player_AD::writeReg(int r, int v) {
- if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
- _registerBackUpTable[r] = v;
- }
- _opl2->writeReg(r, v);
-}
-
-uint8 Player_AD::readReg(int r) const {
- if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) {
- return _registerBackUpTable[r];
- } else {
- return 0;
- }
-}
-
-void Player_AD::setupChannel(const uint channel, const byte *instrOffset) {
- instrOffset += 2;
- writeReg(0xC0 + channel, *instrOffset++);
- setupOperator(_operatorOffsetTable[channel * 2 + 0], instrOffset);
- setupOperator(_operatorOffsetTable[channel * 2 + 1], instrOffset);
-}
-
-void Player_AD::setupOperator(const uint opr, const byte *&instrOffset) {
- writeReg(0x20 + opr, *instrOffset++);
- writeReg(0x40 + opr, *instrOffset++);
- writeReg(0x60 + opr, *instrOffset++);
- writeReg(0x80 + opr, *instrOffset++);
- writeReg(0xE0 + opr, *instrOffset++);
-}
-
-const int Player_AD::_operatorOffsetTable[18] = {
- 0, 3, 1, 4,
- 2, 5, 8, 11,
- 9, 12, 10, 13,
- 16, 19, 17, 20,
- 18, 21
-};
-
-// Music
-
-void Player_AD::startMusic() {
- memset(_instrumentOffset, 0, sizeof(_instrumentOffset));
- memset(_channelLastEvent, 0, sizeof(_channelLastEvent));
- memset(_channelFrequency, 0, sizeof(_channelFrequency));
- memset(_channelB0Reg, 0, sizeof(_channelB0Reg));
-
- _voiceChannels = 0;
- uint instruments = _resource[10];
- for (uint i = 0; i < instruments; ++i) {
- const int instrIndex = _resource[11 + i] - 1;
- if (0 <= instrIndex && instrIndex < 16) {
- _instrumentOffset[instrIndex] = i * 16 + 16 + 3;
- _voiceChannels |= _resource[_instrumentOffset[instrIndex] + 13];
- }
- }
-
- if (_voiceChannels) {
- _mdvdrState = 0x20;
- _voiceChannels = 6;
- } else {
- _mdvdrState = 0;
- _voiceChannels = 9;
- }
-
- _curOffset = 0x93;
- // TODO: is this the same for Loom?
- _nextEventTimer = 40;
- _engineMusicTimer = 0;
- _internalMusicTimer = 0;
- _musicTimer = 0;
-
- writeReg(0xBD, _mdvdrState);
-
- const bool isLoom = (_vm->_game.id == GID_LOOM);
- _timerLimit = isLoom ? 473 : 256;
- _musicTicks = _resource[3] * (isLoom ? 2 : 1);
- _loopFlag = (_resource[4] == 0);
- _musicLoopStart = READ_LE_UINT16(_resource + 5);
-}
-
-void Player_AD::updateMusic() {
- _musicTimer += _musicTicks;
- if (_musicTimer < _timerLimit) {
- return;
- }
- _musicTimer -= _timerLimit;
-
- ++_internalMusicTimer;
- if (_internalMusicTimer > 120) {
- _internalMusicTimer = 0;
- ++_engineMusicTimer;
- }
-
- --_nextEventTimer;
- if (_nextEventTimer) {
- return;
- }
-
- while (true) {
- uint command = _resource[_curOffset++];
- if (command == 0xFF) {
- // META EVENT
- // Get the command number.
- command = _resource[_curOffset++];
- if (command == 47) {
- // End of track
- if (_loopFlag) {
- // In case the track is looping jump to the start.
- _curOffset = _musicLoopStart;
- _nextEventTimer = 0;
- } else {
- // Otherwise completely stop playback.
- stopAllSounds();
- }
- return;
- } else if (command == 88) {
- // This is proposedly a debug information insertion. The CMS
- // player code handles this differently, but is still using
- // the same resources...
- _curOffset += 5;
- } else if (command == 81) {
- // Change tempo. This is used exclusively in Loom.
- const uint timing = _resource[_curOffset + 2] | (_resource[_curOffset + 1] << 8);
- _musicTicks = 0x73000 / timing;
- command = _resource[_curOffset++];
- _curOffset += command;
- } else {
- // In case an unknown meta event occurs just skip over the
- // data by using the length supplied.
- command = _resource[_curOffset++];
- _curOffset += command;
- }
- } else {
- if (command >= 0x90) {
- // NOTE ON
- // Extract the channel number and save it in command.
- command -= 0x90;
-
- const uint instrOffset = _instrumentOffset[command];
- if (instrOffset) {
- if (_resource[instrOffset + 13] != 0) {
- setupRhythm(_resource[instrOffset + 13], instrOffset);
- } else {
- int channel = findFreeChannel();
- if (channel != -1) {
- noteOff(channel);
- setupChannel(channel, instrOffset);
- _channelLastEvent[channel] = command + 0x90;
- _channelFrequency[channel] = _resource[_curOffset];
- setupFrequency(channel, _resource[_curOffset]);
- }
- }
- }
- } else {
- // NOTE OFF
- const uint note = _resource[_curOffset];
- command += 0x10;
-
- // Find the output channel which plays the note.
- uint channel = 0xFF;
- for (uint i = 0; i < _voiceChannels; ++i) {
- if (_channelFrequency[i] == note && _channelLastEvent[i] == command) {
- channel = i;
- break;
- }
- }
-
- if (channel != 0xFF) {
- // In case a output channel playing the note was found,
- // stop it.
- noteOff(channel);
- } else {
- // In case there is no such note this will disable the
- // rhythm instrument played on the channel.
- command -= 0x90;
- const uint instrOffset = _instrumentOffset[command];
- if (instrOffset && _resource[instrOffset + 13] != 0) {
- const uint rhythmInstr = _resource[instrOffset + 13];
- if (rhythmInstr < 6) {
- _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF;
- writeReg(0xBD, _mdvdrState);
- }
- }
- }
- }
-
- _curOffset += 2;
- }
-
- // In case there is a delay till the next event stop handling.
- if (_resource[_curOffset] != 0) {
- break;
- }
- ++_curOffset;
- }
-
- _nextEventTimer = _resource[_curOffset++];
- if (_nextEventTimer & 0x80) {
- _nextEventTimer -= 0x80;
- _nextEventTimer <<= 7;
- _nextEventTimer |= _resource[_curOffset++];
- }
-
- _nextEventTimer >>= (_vm->_game.id == GID_LOOM) ? 2 : 1;
- if (!_nextEventTimer) {
- _nextEventTimer = 1;
- }
-}
-
-void Player_AD::noteOff(uint channel) {
- _channelLastEvent[channel] = 0;
- writeReg(0xB0 + channel, _channelB0Reg[channel] & 0xDF);
-}
-
-int Player_AD::findFreeChannel() {
- for (uint i = 0; i < _voiceChannels; ++i) {
- if (!_channelLastEvent[i]) {
- return i;
- }
- }
-
- return -1;
-}
-
-void Player_AD::setupFrequency(uint channel, int8 frequency) {
- frequency -= 31;
- if (frequency < 0) {
- frequency = 0;
- }
-
- uint octave = 0;
- while (frequency >= 12) {
- frequency -= 12;
- ++octave;
- }
-
- const uint noteFrequency = _noteFrequencies[frequency];
- octave <<= 2;
- octave |= noteFrequency >> 8;
- octave |= 0x20;
- writeReg(0xA0 + channel, noteFrequency & 0xFF);
- _channelB0Reg[channel] = octave;
- writeReg(0xB0 + channel, octave);
-}
-
-void Player_AD::setupRhythm(uint rhythmInstr, uint instrOffset) {
- if (rhythmInstr == 1) {
- setupChannel(6, instrOffset);
- writeReg(0xA6, _resource[instrOffset++]);
- writeReg(0xB6, _resource[instrOffset] & 0xDF);
- _mdvdrState |= 0x10;
- writeReg(0xBD, _mdvdrState);
- } else if (rhythmInstr < 6) {
- const byte *secondOperatorOffset = _resource + instrOffset + 8;
- setupOperator(_rhythmOperatorTable[rhythmInstr], secondOperatorOffset);
- writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++]);
- writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++] & 0xDF);
- writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset]);
- _mdvdrState |= _mdvdrTable[rhythmInstr];
- writeReg(0xBD, _mdvdrState);
- }
-}
-
-const uint Player_AD::_noteFrequencies[12] = {
- 0x200, 0x21E, 0x23F, 0x261,
- 0x285, 0x2AB, 0x2D4, 0x300,
- 0x32E, 0x35E, 0x390, 0x3C7
-};
-
-const uint Player_AD::_mdvdrTable[6] = {
- 0x00, 0x10, 0x08, 0x04, 0x02, 0x01
-};
-
-const uint Player_AD::_rhythmOperatorTable[6] = {
- 0x00, 0x00, 0x14, 0x12, 0x15, 0x11
-};
-
-const uint Player_AD::_rhythmChannelTable[6] = {
- 0x00, 0x00, 0x07, 0x08, 0x08, 0x07
-};
-
-// SFX
-
-void Player_AD::startSfx() {
- writeReg(0xBD, 0x00);
-
- // The second byte of the resource defines the logical channel where
- // the sound effect should be played.
- const int startChannel = _resource[1] * 3;
-
- // Clear the channel.
- _channels[startChannel + 0].state = 0;
- _channels[startChannel + 1].state = 0;
- _channels[startChannel + 2].state = 0;
-
- clearChannel(startChannel + 0);
- clearChannel(startChannel + 1);
- clearChannel(startChannel + 2);
-
- // Set up the first channel to pick up playback.
- _channels[startChannel].currentOffset = _channels[startChannel].startOffset = _resource + 2;
- _channels[startChannel].state = 1;
-
- // Scan for the start of the other channels and set them up if required.
- int curChannel = startChannel + 1;
- const byte *bufferPosition = _resource + 2;
- uint8 command = 0;
- while ((command = *bufferPosition) != 0xFF) {
- switch (command) {
- case 1:
- // INSTRUMENT DEFINITION
- bufferPosition += 15;
- break;
-
- case 2:
- // NOTE DEFINITION
- bufferPosition += 11;
- break;
-
- case 0x80:
- // LOOP
- bufferPosition += 1;
- break;
-
- default:
- // START OF CHANNEL
- bufferPosition += 1;
- _channels[curChannel].currentOffset = bufferPosition;
- _channels[curChannel].startOffset = bufferPosition;
- _channels[curChannel].state = 1;
- ++curChannel;
- break;
- }
- }
-}
-
-void Player_AD::updateSfx() {
- if (--_sfxTimer) {
- return;
- }
- _sfxTimer = 4;
-
- for (int i = 0; i <= 9; ++i) {
- if (!_channels[i].state) {
- continue;
- }
-
- updateChannel(i);
- }
-}
-
-void Player_AD::clearChannel(int channel) {
- writeReg(0xA0 + channel, 0x00);
- writeReg(0xB0 + channel, 0x00);
-}
-
-void Player_AD::updateChannel(int channel) {
- if (_channels[channel].state == 1) {
- parseSlot(channel);
- } else {
- updateSlot(channel);
- }
-}
-
-void Player_AD::parseSlot(int channel) {
- while (true) {
- const byte *curOffset = _channels[channel].currentOffset;
-
- switch (*curOffset) {
- case 1:
- // INSTRUMENT DEFINITION
- ++curOffset;
- _channels[channel].instrumentData[0] = *(curOffset + 0);
- _channels[channel].instrumentData[1] = *(curOffset + 2);
- _channels[channel].instrumentData[2] = *(curOffset + 9);
- _channels[channel].instrumentData[3] = *(curOffset + 8);
- _channels[channel].instrumentData[4] = *(curOffset + 4);
- _channels[channel].instrumentData[5] = *(curOffset + 3);
- _channels[channel].instrumentData[6] = 0;
-
- setupChannel(channel, curOffset);
-
- writeReg(0xA0 + channel, *(curOffset + 0));
- writeReg(0xB0 + channel, *(curOffset + 1) & 0xDF);
-
- _channels[channel].currentOffset += 15;
- break;
-
- case 2:
- // NOTE DEFINITION
- ++curOffset;
- _channels[channel].state = 2;
- noteOffOn(channel);
- parseNote(channel, 0, curOffset);
- parseNote(channel, 1, curOffset);
- return;
-
- case 0x80:
- // LOOP
- _channels[channel].currentOffset = _channels[channel].startOffset;
- break;
-
- default:
- // START OF CHANNEL
- // When we encounter a start of another channel while playback
- // it means that the current channel is finished. Thus, we will
- // stop it.
- clearChannel(channel);
- _channels[channel].state = 0;
-
- // If no channel of the sound effect is playing anymore, unlock
- // the resource.
- channel /= 3;
- if (!_channels[channel + 0].state
- && !_channels[channel + 1].state
- && !_channels[channel + 2].state) {
- _vm->_res->unlock(rtSound, _sfxResource[channel]);
- }
- return;
- }
- }
-}
-
-void Player_AD::updateSlot(int channel) {
- const byte *curOffset = _channels[channel].currentOffset + 1;
-
- for (int num = 0; num <= 1; ++num, curOffset += 5) {
- if (!(*curOffset & 0x80)) {
- continue;
- }
-
- const int note = channel * 2 + num;
- bool updateNote = false;
-
- if (_notes[note].state == 2) {
- if (!--_notes[note].sustainTimer) {
- updateNote = true;
- }
- } else {
- updateNote = processNoteEnvelope(note, _notes[note].instrumentValue);
-
- if (_notes[note].bias) {
- writeRegisterSpecial(note, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07);
- } else {
- writeRegisterSpecial(note, _notes[note].instrumentValue, *curOffset & 0x07);
- }
- }
-
- if (updateNote) {
- if (processNote(note, curOffset)) {
- if (!(*curOffset & 0x08)) {
- _channels[channel].currentOffset += 11;
- _channels[channel].state = 1;
- continue;
- } else if (*curOffset & 0x10) {
- noteOffOn(channel);
- }
-
- _notes[note].state = -1;
- processNote(note, curOffset);
- }
- }
-
- if ((*curOffset & 0x20) && !--_notes[note].playTime) {
- _channels[channel].currentOffset += 11;
- _channels[channel].state = 1;
- }
- }
-}
-
-void Player_AD::parseNote(int channel, int num, const byte *offset) {
- if (num) {
- offset += 5;
- }
-
- if (*offset & 0x80) {
- const int note = channel * 2 + num;
- _notes[note].state = -1;
- processNote(note, offset);
- _notes[note].playTime = 0;
-
- if (*offset & 0x20) {
- _notes[note].playTime = (*(offset + 4) >> 4) * 118;
- _notes[note].playTime += (*(offset + 4) & 0x0F) * 8;
- }
- }
-}
-
-bool Player_AD::processNote(int note, const byte *offset) {
- if (++_notes[note].state == 4) {
- return true;
- }
-
- const int instrumentDataOffset = *offset & 0x07;
- _notes[note].bias = _noteBiasTable[instrumentDataOffset];
-
- uint8 instrumentDataValue = 0;
- if (_notes[note].state == 0) {
- instrumentDataValue = _channels[note / 2].instrumentData[instrumentDataOffset];
- }
-
- uint8 noteInstrumentValue = readRegisterSpecial(note, instrumentDataValue, instrumentDataOffset);
- if (_notes[note].bias) {
- noteInstrumentValue = _notes[note].bias - noteInstrumentValue;
- }
- _notes[note].instrumentValue = noteInstrumentValue;
-
- if (_notes[note].state == 2) {
- _notes[note].sustainTimer = _numStepsTable[*(offset + 3) >> 4];
-
- if (*offset & 0x40) {
- _notes[note].sustainTimer = (((getRnd() << 8) * _notes[note].sustainTimer) >> 16) + 1;
- }
- } else {
- int timer1, timer2;
- if (_notes[note].state == 3) {
- timer1 = *(offset + 3) & 0x0F;
- timer2 = 0;
- } else {
- timer1 = *(offset + _notes[note].state + 1) >> 4;
- timer2 = *(offset + _notes[note].state + 1) & 0x0F;
- }
-
- int adjustValue = ((_noteAdjustTable[timer2] * _noteAdjustScaleTable[instrumentDataOffset]) >> 16) - noteInstrumentValue;
- setupNoteEnvelopeState(note, _numStepsTable[timer1], adjustValue);
- }
-
- return false;
-}
-
-void Player_AD::noteOffOn(int channel) {
- const uint8 regValue = readReg(0xB0 | channel);
- writeReg(0xB0 | channel, regValue & 0xDF);
- writeReg(0xB0 | channel, regValue | 0x20);
-}
-
-void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) {
- if (offset == 6) {
- return;
- }
-
- // Division by 2 extracts the channel number out of the note.
- note /= 2;
-
- uint8 regNum;
- if (_useOperatorTable[offset]) {
- regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
- } else {
- regNum = _channelOffsetTable[note];
- }
-
- regNum += _baseRegisterTable[offset];
-
- uint8 regValue = readReg(regNum) & (~_registerMaskTable[offset]);
- regValue |= value << _registerShiftTable[offset];
-
- writeReg(regNum, regValue);
-}
-
-uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) {
- if (offset == 6) {
- return 0;
- }
-
- // Division by 2 extracts the channel number out of the note.
- note /= 2;
-
- uint8 regNum;
- if (_useOperatorTable[offset]) {
- regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2];
- } else {
- regNum = _channelOffsetTable[note];
- }
-
- regNum += _baseRegisterTable[offset];
-
- uint8 regValue;
- if (defaultValue) {
- regValue = defaultValue;
- } else {
- regValue = readReg(regNum);
- }
-
- regValue &= _registerMaskTable[offset];
- regValue >>= _registerShiftTable[offset];
-
- return regValue;
-}
-
-void Player_AD::setupNoteEnvelopeState(int note, int steps, int adjust) {
- _notes[note].preIncrease = 0;
- if (ABS(adjust) > steps) {
- _notes[note].preIncrease = 1;
- _notes[note].adjust = adjust / steps;
- _notes[note].envelope.stepIncrease = ABS(adjust % steps);
- } else {
- _notes[note].adjust = adjust;
- _notes[note].envelope.stepIncrease = ABS(adjust);
- }
-
- _notes[note].envelope.step = steps;
- _notes[note].envelope.stepCounter = 0;
- _notes[note].envelope.timer = steps;
-}
-
-bool Player_AD::processNoteEnvelope(int note, int &instrumentValue) {
- if (_notes[note].preIncrease) {
- instrumentValue += _notes[note].adjust;
- }
-
- _notes[note].envelope.stepCounter += _notes[note].envelope.stepIncrease;
- if (_notes[note].envelope.stepCounter >= _notes[note].envelope.step) {
- _notes[note].envelope.stepCounter -= _notes[note].envelope.step;
-
- if (_notes[note].adjust < 0) {
- --instrumentValue;
- } else {
- ++instrumentValue;
- }
- }
-
- if (--_notes[note].envelope.timer) {
- return false;
- } else {
- return true;
- }
-}
-
-uint8 Player_AD::getRnd() {
- if (_rndSeed & 1) {
- _rndSeed >>= 1;
- _rndSeed ^= 0xB8;
- } else {
- _rndSeed >>= 1;
- }
-
- return _rndSeed;
-}
-
-const uint Player_AD::_noteBiasTable[7] = {
- 0x00, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x00
-};
-
-const uint Player_AD::_numStepsTable[16] = {
- 1, 4, 6, 8,
- 10, 14, 18, 24,
- 36, 64, 100, 160,
- 240, 340, 600, 1200
-};
-
-const uint Player_AD::_noteAdjustScaleTable[7] = {
- 255, 7, 63, 15, 63, 15, 63
-};
-
-const uint Player_AD::_noteAdjustTable[16] = {
- 0, 4369, 8738, 13107,
- 17476, 21845, 26214, 30583,
- 34952, 39321, 43690, 48059,
- 52428, 46797, 61166, 65535
-};
-
-const bool Player_AD::_useOperatorTable[7] = {
- false, false, true, true, true, true, false
-};
-
-const uint Player_AD::_channelOffsetTable[11] = {
- 0, 1, 2, 3,
- 4, 5, 6, 7,
- 8, 8, 7
-};
-
-const uint Player_AD::_channelOperatorOffsetTable[7] = {
- 0, 0, 1, 1, 0, 0, 0
-};
-
-const uint Player_AD::_baseRegisterTable[7] = {
- 0xA0, 0xC0, 0x40, 0x20, 0x40, 0x20, 0x00
-};
-
-const uint Player_AD::_registerMaskTable[7] = {
- 0xFF, 0x0E, 0x3F, 0x0F, 0x3F, 0x0F, 0x00
-};
-
-const uint Player_AD::_registerShiftTable[7] = {
- 0, 1, 0, 0, 0, 0, 0
-};
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/ad.h b/engines/scumm/player/ad.h
deleted file mode 100644
index da6c7177ef..0000000000
--- a/engines/scumm/player/ad.h
+++ /dev/null
@@ -1,190 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_AD_H
-#define SCUMM_PLAYER_AD_H
-
-#include "scumm/music.h"
-
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-#include "common/mutex.h"
-
-namespace OPL {
-class OPL;
-}
-
-namespace Scumm {
-
-class ScummEngine;
-
-/**
- * Sound output for v3/v4 AdLib data.
- */
-class Player_AD : public MusicEngine, public Audio::AudioStream {
-public:
- Player_AD(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_AD();
-
- // MusicEngine API
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getMusicTimer();
- virtual int getSoundStatus(int sound) const;
-
- virtual void saveLoadWithSerializer(Serializer *ser);
-
- // AudioStream API
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo() const { return false; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _rate; }
-
-private:
- ScummEngine *const _vm;
- Common::Mutex _mutex;
- Audio::Mixer *const _mixer;
- const int _rate;
- Audio::SoundHandle _soundHandle;
- void setupVolume();
-
- OPL::OPL *_opl2;
-
- int _samplesPerCallback;
- int _samplesPerCallbackRemainder;
- int _samplesTillCallback;
- int _samplesTillCallbackRemainder;
-
- int _soundPlaying;
- int _engineMusicTimer;
-
- // AdLib register utilities
- uint8 _registerBackUpTable[256];
- void writeReg(int r, int v);
- uint8 readReg(int r) const;
-
- // Instrument setup
- void setupChannel(const uint channel, uint instrOffset) {
- setupChannel(channel, _resource + instrOffset);
- }
- void setupChannel(const uint channel, const byte *instrOffset);
- void setupOperator(const uint opr, const byte *&instrOffset);
- static const int _operatorOffsetTable[18];
-
- // Sound data
- const byte *_resource;
-
- // Music handling
- void startMusic();
- void updateMusic();
- void noteOff(uint channel);
- int findFreeChannel();
- void setupFrequency(uint channel, int8 frequency);
- void setupRhythm(uint rhythmInstr, uint instrOffset);
-
- uint _timerLimit;
- uint _musicTicks;
- uint _musicTimer;
- uint _internalMusicTimer;
- bool _loopFlag;
- uint _musicLoopStart;
- uint _instrumentOffset[16];
- uint _channelLastEvent[9];
- uint _channelFrequency[9];
- uint _channelB0Reg[9];
-
- uint _mdvdrState;
- uint _voiceChannels;
-
- uint _curOffset;
- uint _nextEventTimer;
-
- static const uint _noteFrequencies[12];
- static const uint _mdvdrTable[6];
- static const uint _rhythmOperatorTable[6];
- static const uint _rhythmChannelTable[6];
-
- // SFX handling
- void startSfx();
- void updateSfx();
- void clearChannel(int channel);
- void updateChannel(int channel);
- void parseSlot(int channel);
- void updateSlot(int channel);
- void parseNote(int channel, int num, const byte *offset);
- bool processNote(int note, const byte *offset);
- void noteOffOn(int channel);
- void writeRegisterSpecial(int note, uint8 value, int offset);
- uint8 readRegisterSpecial(int note, uint8 defaultValue, int offset);
- void setupNoteEnvelopeState(int note, int steps, int adjust);
- bool processNoteEnvelope(int note, int &instrumentValue);
-
- int _sfxTimer;
-
- int _sfxResource[3];
- int _sfxPriority[3];
-
- struct Channel {
- int state;
- const byte *currentOffset;
- const byte *startOffset;
- uint8 instrumentData[7];
- } _channels[11];
-
- uint8 _rndSeed;
- uint8 getRnd();
-
- struct Note {
- int state;
- int playTime;
- int sustainTimer;
- int instrumentValue;
- int bias;
- int preIncrease;
- int adjust;
-
- struct Envelope {
- int stepIncrease;
- int step;
- int stepCounter;
- int timer;
- } envelope;
- } _notes[22];
-
- static const uint _noteBiasTable[7];
- static const uint _numStepsTable[16];
- static const uint _noteAdjustScaleTable[7];
- static const uint _noteAdjustTable[16];
- static const bool _useOperatorTable[7];
- static const uint _channelOffsetTable[11];
- static const uint _channelOperatorOffsetTable[7];
- static const uint _baseRegisterTable[7];
- static const uint _registerMaskTable[7];
- static const uint _registerShiftTable[7];
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/apple2.cpp b/engines/scumm/player/apple2.cpp
deleted file mode 100644
index 671cbf9580..0000000000
--- a/engines/scumm/player/apple2.cpp
+++ /dev/null
@@ -1,500 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "engines/engine.h"
-#include "scumm/player/apple2.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-/************************************
- * Apple-II sound-resource parsers
- ************************************/
-
-/*
- * SoundFunction1: frequency up/down
- */
-class AppleII_SoundFunction1_FreqUpDown : public AppleII_SoundFunction {
-public:
- virtual void init(Player_AppleII *player, const byte *params) {
- _player = player;
- _delta = params[0];
- _count = params[1];
- _interval = params[2];
- _limit = params[3];
- _decInterval = (params[4] >= 0x40);
- }
-
- virtual bool update() { // D085
- if (_decInterval) {
- do {
- _update(_interval, _count);
- _interval -= _delta;
- } while (_interval >= _limit);
- } else {
- do {
- _update(_interval, _count);
- _interval += _delta;
- } while (_interval < _limit);
- }
- return true;
- }
-
-private:
- void _update(int interval /*a*/, int count /*y*/) { // D076
- assert(interval > 0); // 0 == 256?
- assert(count > 0); // 0 == 256?
-
- for (; count >= 0; --count) {
- _player->speakerToggle();
- _player->generateSamples(17 + 5 * interval);
- }
- }
-
-protected:
- int _delta;
- int _count;
- byte _interval; // must be unsigned byte ("interval < delta" possible)
- int _limit;
- bool _decInterval;
-};
-
-/*
- * SoundFunction2: symmetric wave (~)
- */
-class AppleII_SoundFunction2_SymmetricWave : public AppleII_SoundFunction {
-public:
- virtual void init(Player_AppleII *player, const byte *params) {
- _player = player;
- _params = params;
- _pos = 1;
- }
-
- virtual bool update() { // D0D6
- // while (pos = 1; pos < 256; ++pos)
- if (_pos < 256) {
- byte interval = _params[_pos];
- if (interval == 0xFF)
- return true;
- _update(interval, _params[0] /*, LD12F=interval*/);
-
- ++_pos;
- return false;
- }
- return true;
- }
-
-private:
- void _update(int interval /*a*/, int count) { // D0EF
- if (interval == 0xFE) {
- _player->wait(interval, 10);
- } else {
- assert(count > 0); // 0 == 256?
- assert(interval > 0); // 0 == 256?
-
- int a = (interval >> 3) + count;
- for (int y = a; y > 0; --y) {
- _player->generateSamples(1292 - 5*interval);
- _player->speakerToggle();
-
- _player->generateSamples(1287 - 5*interval);
- _player->speakerToggle();
- }
- }
- }
-
-protected:
- const byte *_params;
- int _pos;
-};
-
-/*
- * SoundFunction3: asymmetric wave (__-)
- */
-class AppleII_SoundFunction3_AsymmetricWave : public AppleII_SoundFunction {
-public:
- virtual void init(Player_AppleII *player, const byte *params) {
- _player = player;
- _params = params;
- _pos = 1;
- }
-
- virtual bool update() { // D132
- // while (pos = 1; pos < 256; ++pos)
- if (_pos < 256) {
- byte interval = _params[_pos];
- if (interval == 0xFF)
- return true;
- _update(interval, _params[0]);
-
- ++_pos;
- return false;
- }
- return true;
- }
-
-private:
- void _update(int interval /*a*/, int count /*LD12D*/) { // D14B
- if (interval == 0xFE) {
- _player->wait(interval, 70);
- } else {
- assert(interval > 0); // 0 == 256?
- assert(count > 0); // 0 == 256?
-
- for (int y = count; y > 0; --y) {
- _player->generateSamples(1289 - 5*interval);
- _player->speakerToggle();
- }
- }
- }
-
-protected:
- const byte *_params;
- int _pos;
-};
-
-/*
- * SoundFunction4: polyphone (2 voices)
- */
-class AppleII_SoundFunction4_Polyphone : public AppleII_SoundFunction {
-public:
- virtual void init(Player_AppleII *player, const byte *params) {
- _player = player;
- _params = params;
- _updateRemain1 = 80;
- _updateRemain2 = 10;
- _count = 0;
- }
-
- virtual bool update() { // D170
- // while (_params[0] != 0x01)
- if (_params[0] != 0x01) {
- if (_count == 0) // prepare next loop
- nextLoop(_params[0], _params[1], _params[2]);
- if (loopIteration()) // loop finished -> fetch next parameter set
- _params += 3;
- return false;
- }
- return true;
- }
-
-private:
- /*
- * prepare for next parameter set loop
- */
- void nextLoop(byte param0, byte param1, byte param2) { // LD182
- _count = (-param2 << 8) | 0x3;
-
- _bitmask1 = 0x3;
- _bitmask2 = 0x3;
-
- _updateInterval2 = param0;
- if (_updateInterval2 == 0)
- _bitmask2 = 0x0;
-
- _updateInterval1 = param1;
- if (_updateInterval1 == 0) {
- _bitmask1 = 0x0;
- if (_bitmask2 != 0) {
- _bitmask1 = _bitmask2;
- _bitmask2 = 0;
- _updateInterval1 = _updateInterval2;
- }
- }
-
- _speakerShiftReg = 0;
- }
-
- /*
- * perform one loop iteration
- * Returns true if loop finished
- */
- bool loopIteration() { // D1A2
- --_updateRemain1;
- --_updateRemain2;
-
- if (_updateRemain2 == 0) {
- _updateRemain2 = _updateInterval2;
- // use only first voice's data (bitmask1) if both voices are triggered
- if (_updateRemain1 != 0) {
- _speakerShiftReg ^= _bitmask2;
- }
- }
-
- if (_updateRemain1 == 0) {
- _updateRemain1 = _updateInterval1;
- _speakerShiftReg ^= _bitmask1;
- }
-
- if (_speakerShiftReg & 0x1)
- _player->speakerToggle();
- _speakerShiftReg >>= 1;
- _player->generateSamples(42); /* actually 42.5 */
-
- ++_count;
- return (_count == 0);
- }
-
-protected:
- const byte *_params;
-
- byte _updateRemain1;
- byte _updateRemain2;
-
- uint16 _count;
- byte _bitmask1;
- byte _bitmask2;
- byte _updateInterval1;
- byte _updateInterval2;
- byte _speakerShiftReg;
-};
-
-/*
- * SoundFunction5: periodic noise
- */
-class AppleII_SoundFunction5_Noise : public AppleII_SoundFunction {
-public:
- virtual void init(Player_AppleII *player, const byte *params) {
- _player = player;
- _index = 0;
- _param0 = params[0];
- assert(_param0 > 0);
- }
-
- virtual bool update() { // D222
- const byte noiseMask[] = {
- 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F
- };
-
- // while (i = 0; i < 10; ++i)
- if (_index < 10) {
- int count = _param0;
- do {
- _update(noise() & noiseMask[_index], 1);
- --count;
- } while (count > 0);
-
- ++_index;
- return false;
- }
-
- return true;
- }
-
-private:
- void _update(int interval /*a*/, int count) { // D270
- assert(count > 0); // 0 == 256?
- if (interval == 0)
- interval = 256;
-
- for (int i = count; i > 0; --i) {
- _player->generateSamples(10 + 5*interval);
- _player->speakerToggle();
-
- _player->generateSamples(5 + 5*interval);
- _player->speakerToggle();
- }
- }
-
- byte /*a*/ noise() { // D261
- static int pos = 0; // initial value?
- byte result = _noiseTable[pos];
- pos = (pos + 1) % 256;
- return result;
- }
-
-protected:
- int _index;
- int _param0;
-
-private:
- static const byte _noiseTable[256];
-};
-
-// LD000[loc] ^ LD00A[loc]
-const byte AppleII_SoundFunction5_Noise::_noiseTable[256] = {
- 0x65, 0x1b, 0xda, 0x11, 0x61, 0xe5, 0x77, 0x57, 0x92, 0xc8, 0x51, 0x1c, 0xd4, 0x91, 0x62, 0x63,
- 0x00, 0x38, 0x57, 0xd5, 0x18, 0xd8, 0xdc, 0x40, 0x03, 0x86, 0xd3, 0x2f, 0x10, 0x11, 0xd8, 0x3c,
- 0xbe, 0x00, 0x19, 0xc5, 0xd2, 0xc3, 0xca, 0x34, 0x00, 0x28, 0xbf, 0xb9, 0x18, 0x20, 0x01, 0xcc,
- 0xda, 0x08, 0xbc, 0x75, 0x7c, 0xb0, 0x8d, 0xe0, 0x09, 0x18, 0xbf, 0x5d, 0xe9, 0x8c, 0x75, 0x64,
- 0xe5, 0xb5, 0x5d, 0xe0, 0xb7, 0x7d, 0xe9, 0x8c, 0x55, 0x65, 0xc5, 0xb5, 0x5d, 0xd8, 0x09, 0x0d,
- 0x64, 0xf0, 0xf0, 0x08, 0x63, 0x03, 0x00, 0x55, 0x35, 0xc0, 0x00, 0x20, 0x74, 0xa5, 0x1e, 0xe3,
- 0x00, 0x06, 0x3c, 0x52, 0xd1, 0x70, 0xd0, 0x57, 0x02, 0xf0, 0x00, 0xb6, 0xfc, 0x02, 0x11, 0x9a,
- 0x3b, 0xc8, 0x38, 0xdf, 0x1a, 0xb0, 0xd1, 0xb8, 0xd0, 0x18, 0x8a, 0x4a, 0xea, 0x1b, 0x12, 0x5d,
- 0x29, 0x58, 0xd8, 0x43, 0xb8, 0x2d, 0xd2, 0x61, 0x10, 0x3c, 0x0c, 0x5d, 0x1b, 0x61, 0x10, 0x3c,
- 0x0a, 0x5d, 0x1d, 0x61, 0x10, 0x3c, 0x0b, 0x19, 0x88, 0x21, 0xc0, 0x21, 0x07, 0x00, 0x65, 0x62,
- 0x08, 0xe9, 0x36, 0x40, 0x20, 0x41, 0x06, 0x00, 0x20, 0x00, 0x00, 0xed, 0xa3, 0x00, 0x88, 0x06,
- 0x98, 0x01, 0x5d, 0x7f, 0x02, 0x1d, 0x78, 0x03, 0x60, 0xcb, 0x3a, 0x01, 0xbd, 0x78, 0x02, 0x5d,
- 0x7e, 0x03, 0x1d, 0xf5, 0xa6, 0x40, 0x81, 0xb4, 0xd0, 0x8d, 0xd3, 0xd0, 0x6d, 0xd5, 0x61, 0x48,
- 0x61, 0x4d, 0xd1, 0xc8, 0xb1, 0xd8, 0x69, 0xff, 0x61, 0xd9, 0xed, 0xa0, 0xfe, 0x19, 0x91, 0x37,
- 0x19, 0x37, 0x00, 0xf1, 0x00, 0x01, 0x1f, 0x00, 0xad, 0xc1, 0x01, 0x01, 0x2e, 0x00, 0x40, 0xc6,
- 0x7a, 0x9b, 0x95, 0x43, 0xfc, 0x18, 0xd2, 0x9e, 0x2a, 0x5a, 0x4b, 0x2a, 0xb6, 0x87, 0x30, 0x6c
-};
-
-/************************************
- * Apple-II player
- ************************************/
-
-Player_AppleII::Player_AppleII(ScummEngine *scumm, Audio::Mixer *mixer)
- : _mixer(mixer), _vm(scumm), _soundFunc(0) {
- resetState();
- setSampleRate(_mixer->getOutputRate());
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_AppleII::~Player_AppleII() {
- _mixer->stopHandle(_soundHandle);
- delete _soundFunc;
-}
-
-void Player_AppleII::resetState() {
- _soundNr = 0;
- _type = 0;
- _loop = 0;
- _params = NULL;
- _speakerState = 0;
- delete _soundFunc;
- _soundFunc = 0;
- _sampleConverter.reset();
-}
-
-void Player_AppleII::startSound(int nr) {
- Common::StackLock lock(_mutex);
-
- byte *data = _vm->getResourceAddress(rtSound, nr);
- assert(data);
- byte *ptr1 = data + 4;
-
- resetState();
- _soundNr = nr;
- _type = ptr1[0];
- _loop = ptr1[1];
- _params = &ptr1[2];
-
- switch (_type) {
- case 0: // empty (nothing to play)
- resetState();
- return;
- case 1:
- _soundFunc = new AppleII_SoundFunction1_FreqUpDown();
- break;
- case 2:
- _soundFunc = new AppleII_SoundFunction2_SymmetricWave();
- break;
- case 3:
- _soundFunc = new AppleII_SoundFunction3_AsymmetricWave();
- break;
- case 4:
- _soundFunc = new AppleII_SoundFunction4_Polyphone();
- break;
- case 5:
- _soundFunc = new AppleII_SoundFunction5_Noise();
- break;
- }
- _soundFunc->init(this, _params);
-
- assert(_loop > 0);
-
- debug(4, "startSound %d: type %d, loop %d",
- nr, _type, _loop);
-}
-
-bool Player_AppleII::updateSound() {
- if (!_soundFunc)
- return false;
-
- if (_soundFunc->update()) {
- --_loop;
- if (_loop <= 0) {
- delete _soundFunc;
- _soundFunc = 0;
- } else {
- // reset function state on each loop
- _soundFunc->init(this, _params);
- }
- }
-
- return true;
-}
-
-void Player_AppleII::stopAllSounds() {
- Common::StackLock lock(_mutex);
- resetState();
-}
-
-void Player_AppleII::stopSound(int nr) {
- Common::StackLock lock(_mutex);
- if (_soundNr == nr) {
- resetState();
- }
-}
-
-int Player_AppleII::getSoundStatus(int nr) const {
- Common::StackLock lock(_mutex);
- return (_soundNr == nr);
-}
-
-int Player_AppleII::getMusicTimer() {
- /* Apple-II sounds are synchronous -> no music timer */
- return 0;
-}
-
-int Player_AppleII::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- if (!_soundNr)
- return 0;
-
- int samplesLeft = numSamples;
- do {
- int nSamplesRead = _sampleConverter.readSamples(buffer, samplesLeft);
- samplesLeft -= nSamplesRead;
- buffer += nSamplesRead;
- } while ((samplesLeft > 0) && updateSound());
-
- // reset state if sound is played completely
- if (!_soundFunc && (_sampleConverter.availableSize() == 0))
- resetState();
-
- return numSamples - samplesLeft;
-}
-
-/************************************
- * Apple-II sound-resource helpers
- ************************************/
-
-// toggle speaker on/off
-void Player_AppleII::speakerToggle() {
- _speakerState ^= 0x1;
-}
-
-void Player_AppleII::generateSamples(int cycles) {
- _sampleConverter.addCycles(_speakerState, cycles);
-}
-
-void Player_AppleII::wait(int interval, int count /*y*/) {
- assert(count > 0); // 0 == 256?
- assert(interval > 0); // 0 == 256?
- generateSamples(11 + count*(8 + 5 * interval));
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/apple2.h b/engines/scumm/player/apple2.h
deleted file mode 100644
index e1ec9d8946..0000000000
--- a/engines/scumm/player/apple2.h
+++ /dev/null
@@ -1,297 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_APPLEII_H
-#define SCUMM_PLAYER_APPLEII_H
-
-#include "common/mutex.h"
-#include "common/scummsys.h"
-#include "common/memstream.h"
-#include "scumm/music.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/softsynth/sid.h"
-
-namespace Scumm {
-
-class ScummEngine;
-
-/*
- * Optimized for use with periodical read/write phases when the buffer
- * is filled in a write phase and completely read in a read phase.
- * The growing strategy is optimized for repeated small (e.g. 2 bytes)
- * single writes resulting in large buffers
- * (avg.: 4KB, max: 18KB @ 16bit/22.050kHz (MM sound21)).
- */
-class SampleBuffer {
-public:
- SampleBuffer() : _data(0) {
- clear();
- }
-
- ~SampleBuffer() {
- free(_data);
- }
-
- void clear() {
- free(_data);
- _data = 0;
- _capacity = 0;
- _writePos = 0;
- _readPos = 0;
- }
-
- void ensureFree(uint32 needed) {
- // if data was read completely, reset read/write pos to front
- if ((_writePos != 0) && (_writePos == _readPos)) {
- _writePos = 0;
- _readPos = 0;
- }
-
- // check for enough space at end of buffer
- uint32 freeEndCnt = _capacity - _writePos;
- if (needed <= freeEndCnt)
- return;
-
- uint32 avail = availableSize();
-
- // check for enough space at beginning and end of buffer
- if (needed <= _readPos + freeEndCnt) {
- // move unread data to front of buffer
- memmove(_data, _data + _readPos, avail);
- _writePos = avail;
- _readPos = 0;
- } else { // needs a grow
- byte *old_data = _data;
- uint32 new_len = avail + needed;
-
- _capacity = new_len + 2048;
- _data = (byte *)malloc(_capacity);
-
- if (old_data) {
- // copy old unread data to front of new buffer
- memcpy(_data, old_data + _readPos, avail);
- free(old_data);
- _writePos = avail;
- _readPos = 0;
- }
- }
- }
-
- uint32 availableSize() const {
- if (_readPos >= _writePos)
- return 0;
- return _writePos - _readPos;
- }
-
- uint32 write(const void *dataPtr, uint32 dataSize) {
- ensureFree(dataSize);
- memcpy(_data + _writePos, dataPtr, dataSize);
- _writePos += dataSize;
- return dataSize;
- }
-
- uint32 read(byte *dataPtr, uint32 dataSize) {
- uint32 avail = availableSize();
- if (avail == 0)
- return 0;
- if (dataSize > avail)
- dataSize = avail;
- memcpy(dataPtr, _data + _readPos, dataSize);
- _readPos += dataSize;
- return dataSize;
- }
-
-private:
- uint32 _writePos;
- uint32 _readPos;
- uint32 _capacity;
- byte *_data;
-};
-
-// CPU_CLOCK according to AppleWin
-static const double APPLEII_CPU_CLOCK = 1020484.5; // ~ 1.02 MHz
-
-/*
- * Converts the 1-bit speaker state values into audio samples.
- * This is done by aggregation of the speaker states at each
- * CPU cycle in a sampling period into an audio sample.
- */
-class SampleConverter {
-private:
- void addSampleToBuffer(int sample) {
- int16 value = sample * _volume / _maxVolume;
- _buffer.write(&value, sizeof(value));
- }
-
-public:
- SampleConverter() :
- _cyclesPerSampleFP(0),
- _missingCyclesFP(0),
- _sampleCyclesSumFP(0),
- _volume(_maxVolume)
- {}
-
- ~SampleConverter() {}
-
- void reset() {
- _missingCyclesFP = 0;
- _sampleCyclesSumFP = 0;
- _buffer.clear();
- }
-
- uint32 availableSize() const {
- return _buffer.availableSize();
- }
-
- void setMusicVolume(int vol) {
- assert(vol >= 0 && vol <= _maxVolume);
- _volume = vol;
- }
-
- void setSampleRate(int rate) {
- /* ~46 CPU cycles per sample @ 22.05kHz */
- _cyclesPerSampleFP = int(APPLEII_CPU_CLOCK * (1 << PREC_SHIFT) / rate);
- reset();
- }
-
- void addCycles(byte level, const int cycles) {
- /* convert to fixed precision floats */
- int cyclesFP = cycles << PREC_SHIFT;
-
- // step 1: if cycles are left from the last call, process them first
- if (_missingCyclesFP > 0) {
- int n = (_missingCyclesFP < cyclesFP) ? _missingCyclesFP : cyclesFP;
- if (level)
- _sampleCyclesSumFP += n;
- cyclesFP -= n;
- _missingCyclesFP -= n;
- if (_missingCyclesFP == 0) {
- addSampleToBuffer(2*32767 * _sampleCyclesSumFP / _cyclesPerSampleFP - 32767);
- } else {
- return;
- }
- }
-
- _sampleCyclesSumFP = 0;
-
- // step 2: process blocks of cycles fitting into a whole sample
- while (cyclesFP >= _cyclesPerSampleFP) {
- addSampleToBuffer(level ? 32767 : -32767);
- cyclesFP -= _cyclesPerSampleFP;
- }
-
- // step 3: remember cycles left for next call
- if (cyclesFP > 0) {
- _missingCyclesFP = _cyclesPerSampleFP - cyclesFP;
- if (level)
- _sampleCyclesSumFP = cyclesFP;
- }
- }
-
- uint32 readSamples(void *buffer, int numSamples) {
- return _buffer.read((byte *)buffer, numSamples * 2) / 2;
- }
-
-private:
- static const int PREC_SHIFT = 7;
-
-private:
- int _cyclesPerSampleFP; /* (fixed precision) */
- int _missingCyclesFP; /* (fixed precision) */
- int _sampleCyclesSumFP; /* (fixed precision) */
- int _volume; /* 0 - 256 */
- static const int _maxVolume = 256;
- SampleBuffer _buffer;
-};
-
-class Player_AppleII;
-
-class AppleII_SoundFunction {
-public:
- AppleII_SoundFunction() {}
- virtual ~AppleII_SoundFunction() {}
- virtual void init(Player_AppleII *player, const byte *params) = 0;
- /* returns true if finished */
- virtual bool update() = 0;
-protected:
- Player_AppleII *_player;
-};
-
-class Player_AppleII : public Audio::AudioStream, public MusicEngine {
-public:
- Player_AppleII(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_AppleII();
-
- virtual void setMusicVolume(int vol) { _sampleConverter.setMusicVolume(vol); }
- void setSampleRate(int rate) {
- _sampleRate = rate;
- _sampleConverter.setSampleRate(rate);
- }
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getSoundStatus(int sound) const;
- virtual int getMusicTimer();
-
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return false; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
-
-public:
- void speakerToggle();
- void generateSamples(int cycles);
- void wait(int interval, int count);
-
-private:
- // sound number
- int _soundNr;
- // type of sound
- int _type;
- // number of loops left
- int _loop;
- // global sound param list
- const byte *_params;
- // speaker toggle state (0 / 1)
- byte _speakerState;
- // sound function
- AppleII_SoundFunction *_soundFunc;
- // cycle to sample converter
- SampleConverter _sampleConverter;
-
-private:
- ScummEngine *_vm;
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
- int _sampleRate;
- Common::Mutex _mutex;
-
-private:
- void resetState();
- bool updateSound();
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/mac.cpp b/engines/scumm/player/mac.cpp
deleted file mode 100644
index 1fba266311..0000000000
--- a/engines/scumm/player/mac.cpp
+++ /dev/null
@@ -1,419 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/macresman.h"
-#include "common/translation.h"
-#include "engines/engine.h"
-#include "gui/message.h"
-#include "scumm/player/mac.h"
-#include "scumm/resource.h"
-#include "scumm/scumm.h"
-#include "scumm/imuse/imuse.h"
-
-namespace Scumm {
-
-Player_Mac::Player_Mac(ScummEngine *scumm, Audio::Mixer *mixer, int numberOfChannels, int channelMask, bool fadeNoteEnds)
- : _vm(scumm),
- _mixer(mixer),
- _sampleRate(_mixer->getOutputRate()),
- _soundPlaying(-1),
- _numberOfChannels(numberOfChannels),
- _channelMask(channelMask),
- _fadeNoteEnds(fadeNoteEnds) {
- assert(scumm);
- assert(mixer);
-}
-
-void Player_Mac::init() {
- _channel = new Player_Mac::Channel[_numberOfChannels];
-
- int i;
-
- for (i = 0; i < _numberOfChannels; i++) {
- _channel[i]._looped = false;
- _channel[i]._length = 0;
- _channel[i]._data = NULL;
- _channel[i]._pos = 0;
- _channel[i]._pitchModifier = 0;
- _channel[i]._velocity = 0;
- _channel[i]._remaining = 0;
- _channel[i]._notesLeft = false;
- _channel[i]._instrument._data = NULL;
- _channel[i]._instrument._size = 0;
- _channel[i]._instrument._rate = 0;
- _channel[i]._instrument._loopStart = 0;
- _channel[i]._instrument._loopEnd = 0;
- _channel[i]._instrument._baseFreq = 0;
- _channel[i]._instrument._pos = 0;
- _channel[i]._instrument._subPos = 0;
- }
-
- _pitchTable[116] = 1664510;
- _pitchTable[117] = 1763487;
- _pitchTable[118] = 1868350;
- _pitchTable[119] = 1979447;
- _pitchTable[120] = 2097152;
- _pitchTable[121] = 2221855;
- _pitchTable[122] = 2353973;
- _pitchTable[123] = 2493948;
- _pitchTable[124] = 2642246;
- _pitchTable[125] = 2799362;
- _pitchTable[126] = 2965820;
- _pitchTable[127] = 3142177;
- for (i = 115; i >= 0; --i) {
- _pitchTable[i] = _pitchTable[i + 12] / 2;
- }
-
- setMusicVolume(255);
-
- if (!checkMusicAvailable()) {
- return;
- }
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_Mac::~Player_Mac() {
- Common::StackLock lock(_mutex);
- _mixer->stopHandle(_soundHandle);
- stopAllSounds_Internal();
- delete[] _channel;
-}
-
-void Player_Mac::saveLoadWithSerializer(Serializer *ser) {
- Common::StackLock lock(_mutex);
- if (ser->getVersion() < VER(94)) {
- if (_vm->_game.id == GID_MONKEY && ser->isLoading()) {
- IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL);
- dummyImuse->save_or_load(ser, _vm, false);
- delete dummyImuse;
- }
- } else {
- static const SaveLoadEntry musicEntries[] = {
- MKLINE(Player_Mac, _sampleRate, sleUint32, VER(94)),
- MKLINE(Player_Mac, _soundPlaying, sleInt16, VER(94)),
- MKEND()
- };
-
- static const SaveLoadEntry channelEntries[] = {
- MKLINE(Channel, _pos, sleUint16, VER(94)),
- MKLINE(Channel, _pitchModifier, sleInt32, VER(94)),
- MKLINE(Channel, _velocity, sleUint8, VER(94)),
- MKLINE(Channel, _remaining, sleUint32, VER(94)),
- MKLINE(Channel, _notesLeft, sleUint8, VER(94)),
- MKEND()
- };
-
- static const SaveLoadEntry instrumentEntries[] = {
- MKLINE(Instrument, _pos, sleUint32, VER(94)),
- MKLINE(Instrument, _subPos, sleUint32, VER(94)),
- MKEND()
- };
-
- uint32 mixerSampleRate = _sampleRate;
- int i;
-
- ser->saveLoadEntries(this, musicEntries);
-
- if (ser->isLoading() && _soundPlaying != -1) {
- const byte *ptr = _vm->getResourceAddress(rtSound, _soundPlaying);
- assert(ptr);
- loadMusic(ptr);
- }
-
- ser->saveLoadArrayOf(_channel, _numberOfChannels, sizeof(Channel), channelEntries);
- for (i = 0; i < _numberOfChannels; i++) {
- ser->saveLoadEntries(&_channel[i], instrumentEntries);
- }
-
- if (ser->isLoading()) {
- // If necessary, adjust the channel data to fit the
- // current sample rate.
- if (_soundPlaying != -1 && _sampleRate != mixerSampleRate) {
- double mult = (double)_sampleRate / (double)mixerSampleRate;
- for (i = 0; i < _numberOfChannels; i++) {
- _channel[i]._pitchModifier = (int)((double)_channel[i]._pitchModifier * mult);
- _channel[i]._remaining = (int)((double)_channel[i]._remaining / mult);
- }
- }
- _sampleRate = mixerSampleRate;
- }
- }
-}
-
-void Player_Mac::setMusicVolume(int vol) {
- debug(5, "Player_Mac::setMusicVolume(%d)", vol);
-}
-
-void Player_Mac::stopAllSounds_Internal() {
- if (_soundPlaying != -1) {
- _vm->_res->unlock(rtSound, _soundPlaying);
- }
- _soundPlaying = -1;
- for (int i = 0; i < _numberOfChannels; i++) {
- // The channel data is managed by the resource manager, so
- // don't delete that.
- delete[] _channel[i]._instrument._data;
- _channel[i]._instrument._data = NULL;
-
- _channel[i]._remaining = 0;
- _channel[i]._notesLeft = false;
- }
-}
-
-void Player_Mac::stopAllSounds() {
- Common::StackLock lock(_mutex);
- debug(5, "Player_Mac::stopAllSounds()");
- stopAllSounds_Internal();
-}
-
-void Player_Mac::stopSound(int nr) {
- Common::StackLock lock(_mutex);
- debug(5, "Player_Mac::stopSound(%d)", nr);
-
- if (nr == _soundPlaying) {
- stopAllSounds();
- }
-}
-
-void Player_Mac::startSound(int nr) {
- Common::StackLock lock(_mutex);
- debug(5, "Player_Mac::startSound(%d)", nr);
-
- stopAllSounds_Internal();
-
- const byte *ptr = _vm->getResourceAddress(rtSound, nr);
- assert(ptr);
-
- if (!loadMusic(ptr)) {
- return;
- }
-
- _vm->_res->lock(rtSound, nr);
- _soundPlaying = nr;
-}
-
-bool Player_Mac::Channel::loadInstrument(Common::SeekableReadStream *stream) {
- uint16 soundType = stream->readUint16BE();
- if (soundType != 1) {
- warning("Player_Mac::loadInstrument: Unsupported sound type %d", soundType);
- return false;
- }
- uint16 typeCount = stream->readUint16BE();
- if (typeCount != 1) {
- warning("Player_Mac::loadInstrument: Unsupported data type count %d", typeCount);
- return false;
- }
- uint16 dataType = stream->readUint16BE();
- if (dataType != 5) {
- warning("Player_Mac::loadInstrument: Unsupported data type %d", dataType);
- return false;
- }
-
- stream->readUint32BE(); // initialization option
-
- uint16 cmdCount = stream->readUint16BE();
- if (cmdCount != 1) {
- warning("Player_Mac::loadInstrument: Unsupported command count %d", cmdCount);
- return false;
- }
- uint16 command = stream->readUint16BE();
- if (command != 0x8050 && command != 0x8051) {
- warning("Player_Mac::loadInstrument: Unsupported command 0x%04X", command);
- return false;
- }
-
- stream->readUint16BE(); // 0
- uint32 soundHeaderOffset = stream->readUint32BE();
-
- stream->seek(soundHeaderOffset);
-
- uint32 soundDataOffset = stream->readUint32BE();
- uint32 size = stream->readUint32BE();
- uint32 rate = stream->readUint32BE() >> 16;
- uint32 loopStart = stream->readUint32BE();
- uint32 loopEnd = stream->readUint32BE();
- byte encoding = stream->readByte();
- byte baseFreq = stream->readByte();
-
- if (encoding != 0) {
- warning("Player_Mac::loadInstrument: Unsupported encoding %d", encoding);
- return false;
- }
-
- stream->skip(soundDataOffset);
-
- byte *data = new byte[size];
- stream->read(data, size);
-
- _instrument._data = data;
- _instrument._size = size;
- _instrument._rate = rate;
- _instrument._loopStart = loopStart;
- _instrument._loopEnd = loopEnd;
- _instrument._baseFreq = baseFreq;
-
- return true;
-}
-
-int Player_Mac::getMusicTimer() {
- return 0;
-}
-
-int Player_Mac::getSoundStatus(int nr) const {
- return _soundPlaying == nr;
-}
-
-uint32 Player_Mac::durationToSamples(uint16 duration) {
- // The correct formula should be:
- //
- // (duration * 473 * _sampleRate) / (4 * 480 * 480)
- //
- // But that's likely to cause integer overflow, so we do it in two
- // steps using bitwise operations to perform
- // ((duration * 473 * _sampleRate) / 4096) without overflowing,
- // then divide this by 225
- // (note that 4 * 480 * 480 == 225 * 4096 == 225 << 12)
- //
- // The original code is a bit unclear on if it should be 473 or 437,
- // but since the comments indicated 473 I'm assuming 437 was a typo.
- uint32 samples = (duration * _sampleRate);
- samples = (samples >> 12) * 473 + (((samples & 4095) * 473) >> 12);
- samples = samples / 225;
- return samples;
-}
-
-int Player_Mac::noteToPitchModifier(byte note, Instrument *instrument) {
- if (note > 0) {
- const int pitchIdx = note + 60 - instrument->_baseFreq;
- // I don't want to use floating-point arithmetics here, but I
- // ran into overflow problems with the church music in Monkey
- // Island. It's only once per note, so it should be ok.
- double mult = (double)instrument->_rate / (double)_sampleRate;
- return (int)(mult * _pitchTable[pitchIdx]);
- } else {
- return 0;
- }
-}
-
-int Player_Mac::readBuffer(int16 *data, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- memset(data, 0, numSamples * 2);
- if (_soundPlaying == -1) {
- return numSamples;
- }
-
- bool notesLeft = false;
-
- for (int i = 0; i < _numberOfChannels; i++) {
- if (!(_channelMask & (1 << i))) {
- continue;
- }
-
- uint samplesLeft = numSamples;
- int16 *ptr = data;
-
- while (samplesLeft > 0) {
- int generated;
- if (_channel[i]._remaining == 0) {
- uint32 samples;
- int pitchModifier;
- byte velocity;
- if (getNextNote(i, samples, pitchModifier, velocity)) {
- _channel[i]._remaining = samples;
- _channel[i]._pitchModifier = pitchModifier;
- _channel[i]._velocity = velocity;
-
- } else {
- _channel[i]._pitchModifier = 0;
- _channel[i]._velocity = 0;
- _channel[i]._remaining = samplesLeft;
- }
- }
- generated = MIN<uint32>(_channel[i]._remaining, samplesLeft);
- if (_channel[i]._velocity != 0) {
- _channel[i]._instrument.generateSamples(ptr, _channel[i]._pitchModifier, _channel[i]._velocity, generated, _channel[i]._remaining, _fadeNoteEnds);
- }
- ptr += generated;
- samplesLeft -= generated;
- _channel[i]._remaining -= generated;
- }
-
- if (_channel[i]._notesLeft) {
- notesLeft = true;
- }
- }
-
- if (!notesLeft) {
- stopAllSounds_Internal();
- }
-
- return numSamples;
-}
-
-void Player_Mac::Instrument::generateSamples(int16 *data, int pitchModifier, int volume, int numSamples, int remainingSamplesOnNote, bool fadeNoteEnds) {
- int samplesLeft = numSamples;
- while (samplesLeft) {
- _subPos += pitchModifier;
- while (_subPos >= 0x10000) {
- _subPos -= 0x10000;
- _pos++;
- if (_pos >= _loopEnd) {
- _pos = _loopStart;
- }
- }
-
- int newSample = (((int16)((_data[_pos] << 8) ^ 0x8000)) * volume) / 255;
-
- if (fadeNoteEnds) {
- // Fade out the last 100 samples on each note. Even at
- // low output sample rates this is just a fraction of a
- // second, but it gets rid of distracting "pops" at the
- // end when the sample would otherwise go abruptly from
- // something to nothing. This was particularly
- // noticeable on the distaff notes in Loom.
- //
- // The reason it's conditional is that Monkey Island
- // appears to have a "hold current note" command, and
- // if we fade out the current note in that case we
- // will actually introduce new "pops".
-
- remainingSamplesOnNote--;
- if (remainingSamplesOnNote < 100) {
- newSample = (newSample * remainingSamplesOnNote) / 100;
- }
- }
-
- int sample = *data + newSample;
- if (sample > 32767) {
- sample = 32767;
- } else if (sample < -32768) {
- sample = -32768;
- }
-
- *data++ = sample;
- samplesLeft--;
- }
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/mac.h b/engines/scumm/player/mac.h
deleted file mode 100644
index 09307b4e57..0000000000
--- a/engines/scumm/player/mac.h
+++ /dev/null
@@ -1,133 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_MAC_H
-#define SCUMM_PLAYER_MAC_H
-
-#include "common/scummsys.h"
-#include "common/util.h"
-#include "common/mutex.h"
-#include "scumm/music.h"
-#include "scumm/saveload.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-#define RES_SND MKTAG('s', 'n', 'd', ' ')
-
-class Mixer;
-
-namespace Scumm {
-
-class ScummEngine;
-
-/**
- * Scumm Macintosh music driver, base class.
- */
-class Player_Mac : public Audio::AudioStream, public MusicEngine {
-public:
- Player_Mac(ScummEngine *scumm, Audio::Mixer *mixer, int numberOfChannels, int channelMask, bool fadeNoteEnds);
- virtual ~Player_Mac();
-
- void init();
-
- // MusicEngine API
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getMusicTimer();
- virtual int getSoundStatus(int sound) const;
-
- // AudioStream API
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo() const { return false; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _sampleRate; }
-
- virtual void saveLoadWithSerializer(Serializer *ser);
-
-private:
- Common::Mutex _mutex;
- Audio::Mixer *const _mixer;
- Audio::SoundHandle _soundHandle;
- uint32 _sampleRate;
- int _soundPlaying;
-
- void stopAllSounds_Internal();
-
- struct Instrument {
- byte *_data;
- uint32 _size;
- uint32 _rate;
- uint32 _loopStart;
- uint32 _loopEnd;
- byte _baseFreq;
-
- uint _pos;
- uint _subPos;
-
- void newNote() {
- _pos = 0;
- _subPos = 0;
- }
-
- void generateSamples(int16 *data, int pitchModifier, int volume, int numSamples, int remainingSamplesOnNote, bool fadeNoteEnds);
- };
-
- int _pitchTable[128];
- int _numberOfChannels;
- int _channelMask;
- bool _fadeNoteEnds;
-
- virtual bool checkMusicAvailable() { return false; }
- virtual bool loadMusic(const byte *ptr) { return false; }
- virtual bool getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity) { return false; }
-
-protected:
- struct Channel {
- virtual ~Channel() {}
-
- Instrument _instrument;
- bool _looped;
- uint32 _length;
- const byte *_data;
-
- uint _pos;
- int _pitchModifier;
- byte _velocity;
- uint32 _remaining;
-
- bool _notesLeft;
-
- bool loadInstrument(Common::SeekableReadStream *stream);
- };
-
- ScummEngine *const _vm;
- Channel *_channel;
-
- uint32 durationToSamples(uint16 duration);
- int noteToPitchModifier(byte note, Instrument *instrument);
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/mod.cpp b/engines/scumm/player/mod.cpp
deleted file mode 100644
index afa8967343..0000000000
--- a/engines/scumm/player/mod.cpp
+++ /dev/null
@@ -1,223 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-
-#include "scumm/player/mod.h"
-#include "audio/mixer.h"
-#include "audio/rate.h"
-#include "audio/decoders/raw.h"
-
-namespace Scumm {
-
-Player_MOD::Player_MOD(Audio::Mixer *mixer)
- : _mixer(mixer), _sampleRate(mixer->getOutputRate()) {
- int i;
- _mixamt = 0;
- _mixpos = 0;
-
- for (i = 0; i < MOD_MAXCHANS; i++) {
- _channels[i].id = 0;
- _channels[i].vol = 0;
- _channels[i].freq = 0;
- _channels[i].input = NULL;
- _channels[i].ctr = 0;
- _channels[i].pos = 0;
- }
-
- _playproc = NULL;
- _playparam = NULL;
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_MOD::~Player_MOD() {
- _mixer->stopHandle(_soundHandle);
- for (int i = 0; i < MOD_MAXCHANS; i++) {
- if (!_channels[i].id)
- continue;
- delete _channels[i].input;
- }
-}
-
-void Player_MOD::setMusicVolume(int vol) {
- _maxvol = vol;
-}
-
-void Player_MOD::setUpdateProc(ModUpdateProc *proc, void *param, int freq) {
- _playproc = proc;
- _playparam = param;
- _mixamt = _sampleRate / freq;
-}
-void Player_MOD::clearUpdateProc() {
- _playproc = NULL;
- _playparam = NULL;
- _mixamt = 0;
-}
-
-void Player_MOD::startChannel(int id, void *data, int size, int rate, uint8 vol, int loopStart, int loopEnd, int8 pan) {
- int i;
- if (id == 0)
- error("player_mod - attempted to start channel id 0");
-
- for (i = 0; i < MOD_MAXCHANS; i++) {
- if (!_channels[i].id)
- break;
- }
- if (i == MOD_MAXCHANS) {
- warning("player_mod - too many music channels playing (%i max)",MOD_MAXCHANS);
- return;
- }
- _channels[i].id = id;
- _channels[i].vol = vol;
- _channels[i].pan = pan;
- _channels[i].freq = rate;
- _channels[i].ctr = 0;
-
- Audio::SeekableAudioStream *stream = Audio::makeRawStream((const byte *)data, size, rate, 0);
- if (loopStart != loopEnd) {
- _channels[i].input = new Audio::SubLoopingAudioStream(stream, 0, Audio::Timestamp(0, loopStart, rate), Audio::Timestamp(0, loopEnd, rate));
- } else {
- _channels[i].input = stream;
- }
-
- // read the first sample
- _channels[i].input->readBuffer(&_channels[i].pos, 1);
-}
-
-void Player_MOD::stopChannel(int id) {
- if (id == 0)
- error("player_mod - attempted to stop channel id 0");
- for (int i = 0; i < MOD_MAXCHANS; i++) {
- if (_channels[i].id == id) {
- delete _channels[i].input;
- _channels[i].input = NULL;
- _channels[i].id = 0;
- _channels[i].vol = 0;
- _channels[i].freq = 0;
- _channels[i].ctr = 0;
- _channels[i].pos = 0;
- }
- }
-}
-void Player_MOD::setChannelVol(int id, uint8 vol) {
- if (id == 0)
- error("player_mod - attempted to set volume for channel id 0");
- for (int i = 0; i < MOD_MAXCHANS; i++) {
- if (_channels[i].id == id) {
- _channels[i].vol = vol;
- break;
- }
- }
-}
-
-void Player_MOD::setChannelPan(int id, int8 pan) {
- if (id == 0)
- error("player_mod - attempted to set pan for channel id 0");
- for (int i = 0; i < MOD_MAXCHANS; i++) {
- if (_channels[i].id == id) {
- _channels[i].pan = pan;
- break;
- }
- }
-}
-
-void Player_MOD::setChannelFreq(int id, int freq) {
- if (id == 0)
- error("player_mod - attempted to set frequency for channel id 0");
- for (int i = 0; i < MOD_MAXCHANS; i++) {
- if (_channels[i].id == id) {
- if (freq > 31400) // this is about as high as WinUAE goes
- freq = 31400; // can't easily verify on my own Amiga
- _channels[i].freq = freq;
- break;
- }
- }
-}
-
-void Player_MOD::do_mix(int16 *data, uint len) {
- int i;
- int dpos = 0;
- uint dlen = 0;
- memset(data, 0, 2 * len * sizeof(int16));
- while (len) {
- if (_playproc) {
- dlen = _mixamt - _mixpos;
- if (!_mixpos)
- _playproc(_playparam);
- if (dlen <= len) {
- _mixpos = 0;
- len -= dlen;
- } else {
- _mixpos = len;
- dlen = len;
- len = 0;
- }
- } else {
- dlen = len;
- len = 0;
- }
- for (i = 0; i < MOD_MAXCHANS; i++) {
- if (_channels[i].id) {
- Audio::st_volume_t vol_l = (127 - _channels[i].pan) * _channels[i].vol / 127;
- Audio::st_volume_t vol_r = (127 + _channels[i].pan) * _channels[i].vol / 127;
- for (uint j = 0; j < dlen; j++) {
- // simple linear resample, unbuffered
- int delta = (uint32)(_channels[i].freq * 0x10000) / _sampleRate;
- uint16 cfrac = ~_channels[i].ctr & 0xFFFF;
- if (_channels[i].ctr + delta < 0x10000)
- cfrac = delta;
- _channels[i].ctr += delta;
- int32 cpos = _channels[i].pos * cfrac / 0x10000;
- while (_channels[i].ctr >= 0x10000) {
- if (_channels[i].input->readBuffer(&_channels[i].pos, 1) != 1) { // out of data
- stopChannel(_channels[i].id);
- goto skipchan; // exit 2 loops at once
- }
- _channels[i].ctr -= 0x10000;
- if (_channels[i].ctr > 0x10000)
- cpos += _channels[i].pos;
- else
- cpos += (int32)(_channels[i].pos * (_channels[i].ctr & 0xFFFF)) / 0x10000;
- }
- int16 pos = 0;
- // if too many samples play in a row, the calculation below will overflow and clip
- // so try and split it up into pieces it can manage comfortably
- while (cpos < -0x8000) {
- pos -= 0x80000000 / delta;
- cpos += 0x8000;
- }
- while (cpos > 0x7FFF) {
- pos += 0x7FFF0000 / delta;
- cpos -= 0x7FFF;
- }
- pos += cpos * 0x10000 / delta;
- Audio::clampedAdd(data[(dpos + j) * 2 + 0], pos * vol_l / Audio::Mixer::kMaxMixerVolume);
- Audio::clampedAdd(data[(dpos + j) * 2 + 1], pos * vol_r / Audio::Mixer::kMaxMixerVolume);
- }
- }
-skipchan: ; // channel ran out of data
- }
- dpos += dlen;
- }
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/mod.h b/engines/scumm/player/mod.h
deleted file mode 100644
index 619d83541d..0000000000
--- a/engines/scumm/player/mod.h
+++ /dev/null
@@ -1,100 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_MOD_H
-#define SCUMM_PLAYER_MOD_H
-
-#include "scumm/scumm.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-namespace Audio {
-class RateConverter;
-}
-
-namespace Scumm {
-
-/**
- * Generic Amiga MOD mixer - provides a 60Hz 'update' routine.
- */
-class Player_MOD : public Audio::AudioStream {
-public:
- Player_MOD(Audio::Mixer *mixer);
- virtual ~Player_MOD();
- virtual void setMusicVolume(int vol);
-
- virtual void startChannel(int id, void *data, int size, int rate, uint8 vol, int loopStart = 0, int loopEnd = 0, int8 pan = 0);
- virtual void stopChannel(int id);
- virtual void setChannelVol(int id, uint8 vol);
- virtual void setChannelPan(int id, int8 pan);
- virtual void setChannelFreq(int id, int freq);
-
- typedef void ModUpdateProc(void *param);
-
- virtual void setUpdateProc(ModUpdateProc *proc, void *param, int freq);
- virtual void clearUpdateProc();
-
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples) {
- do_mix(buffer, numSamples / 2);
- return numSamples;
- }
- bool isStereo() const { return true; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
-
-private:
- enum {
- MOD_MAXCHANS = 24
- };
-
- struct soundChan {
- int id;
- uint8 vol;
- int8 pan;
- uint16 freq;
-
- uint32 ctr;
- int16 pos;
- Audio::AudioStream *input;
- };
-
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
-
- uint32 _mixamt;
- uint32 _mixpos;
- const int _sampleRate;
-
- soundChan _channels[MOD_MAXCHANS];
-
- uint8 _maxvol;
-
- virtual void do_mix(int16 *buf, uint len);
-
- ModUpdateProc *_playproc;
- void *_playparam;
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/nes.cpp b/engines/scumm/player/nes.cpp
deleted file mode 100644
index 072f46dd5a..0000000000
--- a/engines/scumm/player/nes.cpp
+++ /dev/null
@@ -1,1067 +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 2
- * 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
- * aint32 with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef DISABLE_NES_APU
-
-#include "engines/engine.h"
-#include "scumm/player/nes.h"
-#include "scumm/scumm.h"
-#include "audio/mixer.h"
-
-namespace Scumm {
-
-static const byte channelMask[4] = {1, 2, 4, 8};
-
-static const uint16 freqTable[64] = {
- 0x07F0, 0x077E, 0x0712, 0x06AE, 0x064E, 0x05F3, 0x059E, 0x054D,
- 0x0501, 0x04B9, 0x0475, 0x0435, 0x03F8, 0x03BF, 0x0389, 0x0357,
- 0x0327, 0x02F9, 0x02CF, 0x02A6, 0x0280, 0x025C, 0x023A, 0x021A,
- 0x01FC, 0x01DF, 0x01C4, 0x01AB, 0x0193, 0x017C, 0x0167, 0x0152,
- 0x013F, 0x012D, 0x011C, 0x010C, 0x00FD, 0x00EE, 0x00E1, 0x00D4,
- 0x00C8, 0x00BD, 0x00B2, 0x00A8, 0x009F, 0x0096, 0x008D, 0x0085,
- 0x007E, 0x0076, 0x0070, 0x0069, 0x0063, 0x005E, 0x0058, 0x0053,
- 0x004F, 0x004A, 0x0046, 0x0042, 0x003E, 0x003A, 0x0037, 0x0034
-};
-
-static const byte instChannel[16] = {
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 1, 3, 3, 3
-};
-static const byte startCmd[16] = {
- 0x05, 0x03, 0x06, 0x08, 0x0B, 0x01, 0x01, 0x1A,
- 0x16, 0x06, 0x04, 0x17, 0x02, 0x10, 0x0E, 0x0D
-};
-static const byte releaseCmd[16] = {
- 0x0F, 0x00, 0x00, 0x09, 0x00, 0x14, 0x15, 0x00,
- 0x00, 0x00, 0x1B, 0x1B, 0x0F, 0x0F, 0x0F, 0x0F
-};
-static const byte nextCmd[28] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0x17, 0xFF, 0x07, 0xFF,
- 0xFF, 0x0A, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00,
- 0x11, 0x12, 0x11, 0x03, 0xFF, 0xFF, 0x18, 0x00,
- 0x19, 0x00, 0x00, 0x00
-};
-static const byte nextDelay[28] = {
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
- 0x00, 0x05, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00,
- 0x03, 0x00, 0x00, 0x00
-};
-
-namespace APUe {
-
-static const byte LengthCounts[32] = {
- 0x0A,0xFE,
- 0x14,0x02,
- 0x28,0x04,
- 0x50,0x06,
- 0xA0,0x08,
- 0x3C,0x0A,
- 0x0E,0x0C,
- 0x1A,0x0E,
-
- 0x0C,0x10,
- 0x18,0x12,
- 0x30,0x14,
- 0x60,0x16,
- 0xC0,0x18,
- 0x48,0x1A,
- 0x10,0x1C,
- 0x20,0x1E
-};
-
-class SoundGen {
-protected:
- byte wavehold;
- uint32 freq; // short
- uint32 CurD;
-
-public:
- byte Timer;
- int32 Pos;
- uint32 Cycles; // short
-
- inline byte GetTimer() const { return Timer; }
-};
-
-class Square : public SoundGen {
-protected:
- byte volume, envelope, duty, swpspeed, swpdir, swpstep, swpenab;
- byte Vol;
- byte EnvCtr, Envelope, BendCtr;
- bool Enabled, ValidFreq, Active;
- bool EnvClk, SwpClk;
-
- void CheckActive();
-
-public:
- void Reset();
- void Write(int Reg, byte Val);
- void Run();
- void QuarterFrame();
- void HalfFrame();
-};
-
-static const int8 Duties[4][8] = {
- {-4,+4,-4,-4,-4,-4,-4,-4},
- {-4,+4,+4,-4,-4,-4,-4,-4},
- {-4,+4,+4,+4,+4,-4,-4,-4},
- {+4,-4,-4,+4,+4,+4,+4,+4}
-};
-
-void Square::Reset() {
- memset(this, 0, sizeof(*this));
- Cycles = 1;
- EnvCtr = 1;
- BendCtr = 1;
-}
-
-void Square::CheckActive() {
- ValidFreq = (freq >= 0x8) && ((swpdir) || !((freq + (freq >> swpstep)) & 0x800));
- Active = Timer && ValidFreq;
- Pos = Active ? (Duties[duty][CurD] * Vol) : 0;
-}
-
-void Square::Write(int Reg, byte Val) {
- switch (Reg) {
- case 0:
- volume = Val & 0xF;
- envelope = Val & 0x10;
- wavehold = Val & 0x20;
- duty = (Val >> 6) & 0x3;
- Vol = envelope ? volume : Envelope;
- break;
-
- case 1:
- swpstep = Val & 0x07;
- swpdir = Val & 0x08;
- swpspeed = (Val >> 4) & 0x7;
- swpenab = Val & 0x80;
- SwpClk = true;
- break;
-
- case 2:
- freq &= 0x700;
- freq |= Val;
- break;
-
- case 3:
- freq &= 0xFF;
- freq |= (Val & 0x7) << 8;
-
- if (Enabled)
- Timer = LengthCounts[(Val >> 3) & 0x1F];
-
- CurD = 0;
- EnvClk = true;
- break;
-
- case 4:
- Enabled = (Val != 0);
- if (!Enabled)
- Timer = 0;
- break;
- }
- CheckActive();
-}
-
-void Square::Run() {
- Cycles = (freq + 1) << 1;
- CurD = (CurD + 1) & 0x7;
-
- if (Active)
- Pos = Duties[duty][CurD] * Vol;
-}
-
-void Square::QuarterFrame() {
- if (EnvClk) {
- EnvClk = false;
- Envelope = 0xF;
- EnvCtr = volume + 1;
- } else if (!--EnvCtr) {
- EnvCtr = volume + 1;
-
- if (Envelope)
- Envelope--;
- else
- Envelope = wavehold ? 0xF : 0x0;
- }
-
- Vol = envelope ? volume : Envelope;
- CheckActive();
-}
-
-void Square::HalfFrame() {
- if (!--BendCtr) {
- BendCtr = swpspeed + 1;
-
- if (swpenab && swpstep && ValidFreq) {
- int sweep = freq >> swpstep;
- // FIXME: Is -sweep or ~sweep correct???
- freq += swpdir ? -sweep : sweep;
- }
- }
-
- if (SwpClk) {
- SwpClk = false;
- BendCtr = swpspeed + 1;
- }
-
- if (Timer && !wavehold)
- Timer--;
-
- CheckActive();
-}
-
-
-class Triangle : public SoundGen {
-protected:
- byte linear;
- byte LinCtr;
- bool Enabled, Active;
- bool LinClk;
-
- void CheckActive();
-
-public:
- void Reset();
- void Write(int Reg, byte Val);
- void Run();
- void QuarterFrame();
- void HalfFrame();
-};
-
-static const int8 TriDuty[32] = {
- -8,-7,-6,-5,-4,-3,-2,-1,
- +0,+1,+2,+3,+4,+5,+6,+7,
- +7,+6,+5,+4,+3,+2,+1,+0,
- -1,-2,-3,-4,-5,-6,-7,-8
-};
-
-void Triangle::Reset() {
- memset(this, 0, sizeof(*this));
- Cycles = 1;
-}
-
-void Triangle::CheckActive() {
- Active = Timer && LinCtr;
-
- if (freq < 4)
- Pos = 0; // beyond hearing range
- else
- Pos = TriDuty[CurD] * 8;
-}
-
-void Triangle::Write(int Reg, byte Val) {
- switch (Reg) {
- case 0:
- linear = Val & 0x7F;
- wavehold = (Val >> 7) & 0x1;
- break;
-
- case 2:
- freq &= 0x700;
- freq |= Val;
- break;
-
- case 3:
- freq &= 0xFF;
- freq |= (Val & 0x7) << 8;
-
- if (Enabled)
- Timer = LengthCounts[(Val >> 3) & 0x1F];
-
- LinClk = true;
- break;
-
- case 4:
- Enabled = (Val != 0);
- if (!Enabled)
- Timer = 0;
- break;
- }
- CheckActive();
-}
-
-void Triangle::Run() {
- Cycles = freq + 1;
-
- if (Active) {
- CurD++;
- CurD &= 0x1F;
-
- if (freq < 4)
- Pos = 0; // beyond hearing range
- else
- Pos = TriDuty[CurD] * 8;
- }
-}
-
-void Triangle::QuarterFrame() {
- if (LinClk)
- LinCtr = linear;
- else if (LinCtr)
- LinCtr--;
-
- if (!wavehold)
- LinClk = false;
-
- CheckActive();
-}
-
-void Triangle::HalfFrame() {
- if (Timer && !wavehold)
- Timer--;
-
- CheckActive();
-}
-
-class Noise : public SoundGen {
-protected:
- byte volume, envelope, datatype;
- byte Vol;
- byte EnvCtr, Envelope;
- bool Enabled;
- bool EnvClk;
-
- void CheckActive();
-
-public:
- void Reset();
- void Write(int Reg, byte Val);
- void Run();
- void QuarterFrame();
- void HalfFrame();
-};
-
-static const uint32 NoiseFreq[16] = {
- 0x004,0x008,0x010,0x020,0x040,0x060,0x080,0x0A0,
- 0x0CA,0x0FE,0x17C,0x1FC,0x2FA,0x3F8,0x7F2,0xFE4
-};
-
-void Noise::Reset() {
- memset(this, 0, sizeof(*this));
- CurD = 1;
- Cycles = 1;
- EnvCtr = 1;
-
-}
-
-void Noise::Write(int Reg, byte Val) {
- switch (Reg) {
- case 0:
- volume = Val & 0x0F;
- envelope = Val & 0x10;
- wavehold = Val & 0x20;
- Vol = envelope ? volume : Envelope;
-
- if (Timer)
- Pos = ((CurD & 0x4000) ? -2 : 2) * Vol;
- break;
-
- case 2:
- freq = Val & 0xF;
- datatype = Val & 0x80;
- break;
-
- case 3:
- if (Enabled)
- Timer = LengthCounts[(Val >> 3) & 0x1F];
-
- EnvClk = true;
- break;
-
- case 4:
- Enabled = (Val != 0);
- if (!Enabled)
- Timer = 0;
- break;
- }
-}
-
-void Noise::Run() {
- Cycles = NoiseFreq[freq]; /* no + 1 here */
-
- if (datatype)
- CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 8)) & 0x1);
- else
- CurD = (CurD << 1) | (((CurD >> 14) ^ (CurD >> 13)) & 0x1);
-
- if (Timer)
- Pos = ((CurD & 0x4000) ? -2 : 2) * Vol;
-}
-
-void Noise::QuarterFrame() {
- if (EnvClk) {
- EnvClk = false;
- Envelope = 0xF;
- EnvCtr = volume + 1;
- } else if (!--EnvCtr) {
- EnvCtr = volume + 1;
-
- if (Envelope)
- Envelope--;
- else
- Envelope = wavehold ? 0xF : 0x0;
- }
-
- Vol = envelope ? volume : Envelope;
-
- if (Timer)
- Pos = ((CurD & 0x4000) ? -2 : 2) * Vol;
-}
-
-void Noise::HalfFrame() {
- if (Timer && !wavehold)
- Timer--;
-}
-
-class APU {
-protected:
- int BufPos;
- int SampleRate;
-
- Square _square0;
- Square _square1;
- Triangle _triangle;
- Noise _noise;
-
- struct {
- uint32 Cycles;
- int Num;
- } Frame;
-
-public:
- APU(int rate) : SampleRate(rate) {
- Reset();
- }
-
- void WriteReg(int Addr, byte Val);
- byte Read4015();
- void Reset ();
- int16 GetSample();
-};
-
-void APU::WriteReg(int Addr, byte Val) {
- switch (Addr) {
- case 0x000: _square0.Write(0,Val); break;
- case 0x001: _square0.Write(1,Val); break;
- case 0x002: _square0.Write(2,Val); break;
- case 0x003: _square0.Write(3,Val); break;
- case 0x004: _square1.Write(0,Val); break;
- case 0x005: _square1.Write(1,Val); break;
- case 0x006: _square1.Write(2,Val); break;
- case 0x007: _square1.Write(3,Val); break;
- case 0x008: _triangle.Write(0,Val); break;
- case 0x009: _triangle.Write(1,Val); break;
- case 0x00A: _triangle.Write(2,Val); break;
- case 0x00B: _triangle.Write(3,Val); break;
- case 0x00C: _noise.Write(0,Val); break;
- case 0x00D: _noise.Write(1,Val); break;
- case 0x00E: _noise.Write(2,Val); break;
- case 0x00F: _noise.Write(3,Val); break;
- case 0x015: _square0.Write(4,Val & 0x1);
- _square1.Write(4,Val & 0x2);
- _triangle.Write(4,Val & 0x4);
- _noise.Write(4,Val & 0x8);
- break;
- }
-}
-
-byte APU::Read4015() {
- byte result =
- (( _square0.GetTimer()) ? 0x01 : 0) |
- (( _square1.GetTimer()) ? 0x02 : 0) |
- ((_triangle.GetTimer()) ? 0x04 : 0) |
- (( _noise.GetTimer()) ? 0x08 : 0);
- return result;
-}
-
-void APU::Reset () {
- BufPos = 0;
-
- _square0.Reset();
- _square1.Reset();
- _triangle.Reset();
- _noise.Reset();
-
- Frame.Num = 0;
- Frame.Cycles = 1;
-}
-
-template<class T>
-int step(T &obj, int sampcycles, uint frame_Cycles, int frame_Num) {
- int samppos = 0;
- while (sampcycles) {
- // Compute the maximal amount we can step ahead before triggering
- // an action (i.e. compute the minimum of sampcycles, frame_Cycles
- // and obj.Cycles).
- uint max_step = sampcycles;
- if (max_step > frame_Cycles)
- max_step = frame_Cycles;
- if (max_step > obj.Cycles)
- max_step = obj.Cycles;
-
- // During all but the last of these steps, we just add the value of obj.Pos
- // to samppos -- so we can to that all at once with a simple multiplication:
- samppos += obj.Pos * (max_step - 1);
-
- // Now step ahead...
- sampcycles -= max_step;
- frame_Cycles -= max_step;
- obj.Cycles -= max_step;
-
- if (!frame_Cycles) {
- frame_Cycles = 7457;
-
- if (frame_Num < 4) {
- obj.QuarterFrame();
-
- if (frame_Num & 1)
- frame_Cycles++;
- else
- obj.HalfFrame();
-
- frame_Num++;
- } else
- frame_Num = 0;
- }
-
- if (!obj.Cycles)
- obj.Run();
-
- samppos += obj.Pos;
- }
-
- return samppos;
-}
-
-int16 APU::GetSample() {
- int samppos = 0;
-
- const int sampcycles = 1+(1789773-BufPos-1)/SampleRate;
- BufPos = BufPos + sampcycles * SampleRate - 1789773;
-
- samppos += step( _square0, sampcycles, Frame.Cycles, Frame.Num);
- samppos += step( _square1, sampcycles, Frame.Cycles, Frame.Num);
- samppos += step(_triangle, sampcycles, Frame.Cycles, Frame.Num);
- samppos += step( _noise, sampcycles, Frame.Cycles, Frame.Num);
-
- uint tmp = sampcycles;
- while (tmp >= Frame.Cycles) {
- tmp -= Frame.Cycles;
- Frame.Cycles = 7457;
-
- if (Frame.Num < 4) {
- if (Frame.Num & 1)
- Frame.Cycles++;
- Frame.Num++;
- } else
- Frame.Num = 0;
- }
-
- Frame.Cycles -= tmp;
-
- return (samppos << 6) / sampcycles;
-}
-
-} // End of namespace APUe
-
-Player_NES::Player_NES(ScummEngine *scumm, Audio::Mixer *mixer) {
- int i;
- _vm = scumm;
- _mixer = mixer;
- _sampleRate = _mixer->getOutputRate();
- _apu = new APUe::APU(_sampleRate);
-
- _samples_per_frame = _sampleRate / 60;
- _current_sample = 0;
-
- for (i = 0; i < NUMSLOTS; i++) {
- _slot[i].id = -1;
- _slot[i].framesleft = 0;
- _slot[i].type = 0;
- _slot[i].offset = 0;
- _slot[i].data = NULL;
- }
-
- for (i = 0; i < NUMCHANS; i++) {
- _mchan[i].command = 0;
- _mchan[i].framedelay = 0;
- _mchan[i].pitch = 0;
- _mchan[i].volume = 0;
- _mchan[i].voldelta = 0;
- _mchan[i].envflags = 0;
- _mchan[i].cmdlock = 0;
- }
- isSFXplaying = wasSFXplaying = false;
-
- auxData1 = auxData2 = NULL;
- numNotes = 0;
-
- APU_writeControl(0);
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_NES::~Player_NES() {
- _mixer->stopHandle(_soundHandle);
- delete _apu;
-}
-
-void Player_NES::setMusicVolume (int vol) {
- _maxvol = vol;
-}
-
-int Player_NES::readBuffer(int16 *buffer, const int numSamples) {
- for (int n = 0; n < numSamples; n++) {
- buffer[n] = _apu->GetSample() * _maxvol / 255;
- _current_sample++;
-
- if (_current_sample == _samples_per_frame) {
- _current_sample = 0;
- sound_play();
- }
- }
- return numSamples;
-}
-void Player_NES::stopAllSounds() {
- for (int i = 0; i < NUMSLOTS; i++) {
- _slot[i].framesleft = 0;
- _slot[i].type = 0;
- _slot[i].id = -1;
- }
-
- isSFXplaying = 0;
- checkSilenceChannels(0);
-}
-
-void Player_NES::stopSound(int nr) {
- if (nr == -1)
- return;
-
- for (int i = 0; i < NUMSLOTS; i++) {
- if (_slot[i].id != nr)
- continue;
-
- isSFXplaying = 0;
- _slot[i].framesleft = 0;
- _slot[i].type = 0;
- _slot[i].id = -1;
- checkSilenceChannels(i);
- }
-}
-
-void Player_NES::startSound(int nr) {
- byte *data = _vm->getResourceAddress(rtSound, nr) + 2;
- assert(data);
-
- int soundType = data[1];
- int chan = data[0];
-
- if (chan == 4) {
- if (_slot[2].framesleft)
- return;
- chan = 0;
- }
-
- if (soundType < _slot[chan].type)
- return;
-
- _slot[chan].type = soundType;
- _slot[chan].id = nr;
- _slot[chan].data = data;
- _slot[chan].offset = 2;
- _slot[chan].framesleft = 1;
- checkSilenceChannels(chan);
- if (chan == 2) {
- numNotes = _slot[chan].data[2];
- auxData1 = _slot[chan].data + 3;
- auxData2 = auxData1 + numNotes;
- _slot[chan].data = auxData2 + numNotes;
- _slot[chan].offset = 0;
-
- for (int i = 0; i < NUMCHANS; i++)
- _mchan[i].cmdlock = 0;
- }
-}
-
-void Player_NES::checkSilenceChannels(int chan) {
- for (chan--; chan >= 0; chan--) {
- if (_slot[chan].framesleft)
- return;
- }
- APU_writeControl(0);
-}
-
-void Player_NES::sound_play() {
- if (_slot[0].framesleft)
- playSFX(0);
- else if (_slot[1].framesleft)
- playSFX(1);
-
- playMusic();
-}
-
-void Player_NES::playSFX (int nr) {
- if (--_slot[nr].framesleft)
- return;
-
- while (1) {
- int a = _slot[nr].data[_slot[nr].offset++];
- if (a < 16) {
- a >>= 2;
- APU_writeControl(APU_readStatus() | channelMask[a]);
- isSFXplaying = true;
- APU_writeChannel(a, 0, _slot[nr].data[_slot[nr].offset++]);
- APU_writeChannel(a, 1, _slot[nr].data[_slot[nr].offset++]);
- APU_writeChannel(a, 2, _slot[nr].data[_slot[nr].offset++]);
- APU_writeChannel(a, 3, _slot[nr].data[_slot[nr].offset++]);
- } else if (a == 0xFE) {
- _slot[nr].offset = 2;
- } else if (a == 0xFF) {
- _slot[nr].id = -1;
- _slot[nr].type = 0;
- isSFXplaying = false;
- APU_writeControl(0);
-
- if (!nr && _slot[1].framesleft) {
- _slot[1].framesleft = 1;
- isSFXplaying = true;
- }
- return;
- } else {
- _slot[nr].framesleft = _slot[nr].data[_slot[nr].offset++];
- return;
- }
- }
-}
-
-void Player_NES::playMusic() {
- if (!_slot[2].framesleft)
- return;
-
- if (wasSFXplaying && !isSFXplaying)
- for (int x = 1; x >= 0; x--)
- if (_mchan[x].cmdlock) {
- _mchan[x].command = _mchan[x].cmdlock;
- _mchan[x].framedelay = 1;
- }
-
- wasSFXplaying = isSFXplaying;
- if (!--_slot[2].framesleft) {
-top:
- int b = _slot[2].data[_slot[2].offset++];
- if (b == 0xFF) {
- _slot[2].id = -1;
- _slot[2].type = 0;
- b = 0;
- } else if (b == 0xFE) {
- _slot[2].offset = 0;
- goto top;
- } else {
- if (b < numNotes) {
- int inst = auxData1[b];
- int ch = instChannel[inst];
- _mchan[ch].pitch = auxData2[b];
- _mchan[ch].cmdlock = startCmd[inst];
- _mchan[ch].command = startCmd[inst];
- _mchan[ch].framedelay = 1;
- goto top;
- }
- b -= numNotes;
- if (b < 16) {
- int inst = b;
- int ch = instChannel[inst];
- _mchan[ch].cmdlock = 0;
- _mchan[ch].command = releaseCmd[inst];
- _mchan[ch].framedelay = 1;
- goto top;
- }
- b -= 16;
- }
- _slot[2].framesleft = b;
- }
-
- for (int x = NUMCHANS - 1; x >= 0; x--) {
- if (_slot[0].framesleft || _slot[1].framesleft) {
- _mchan[x].volume = 0;
- _mchan[x].framedelay = 0;
- continue;
- }
-
- if (_mchan[x].framedelay && !--_mchan[x].framedelay) {
- switch (_mchan[x].command) {
- case 0x00:
- case 0x13:
- _mchan[x].voldelta = -10;
- break;
-
- case 0x01:
- case 0x03:
- case 0x08:
- case 0x16:
- _mchan[x].envflags = 0x30;
- _mchan[x].volume = 0x6F;
- _mchan[x].voldelta = 0;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeChannel(x, 1, 0x7F);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x02:
- _mchan[x].envflags = 0xB0;
- _mchan[x].volume = 0x6F;
- _mchan[x].voldelta = 0;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeChannel(x, 1, 0x84);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x04:
- _mchan[x].envflags = 0x80;
- _mchan[x].volume = 0x6F;
- _mchan[x].voldelta = 0;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeChannel(x, 1, 0x7F);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x05:
- _mchan[x].envflags = 0xF0;
- _mchan[x].volume = 0x6F;
- _mchan[x].voldelta = -15;
-
- APU_writeChannel(x, 1, 0x7F);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x06:
- _mchan[x].pitch += 0x18;
- _mchan[x].envflags = 0x80;
- _mchan[x].volume = 0x6F;
- _mchan[x].voldelta = 0;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeChannel(x, 1, 0x7F);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x07:
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch - 0x0C] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch - 0x0C] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x09:
- _mchan[x].voldelta = -2;
-
- APU_writeChannel(x, 1, 0x7F);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x0A:
- APU_writeChannel(x, 1, 0x86);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x0B: case 0x1A:
- _mchan[x].envflags = 0x70;
- _mchan[x].volume = 0x6F;
- _mchan[x].voldelta = 0;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeChannel(x, 1, 0x7F);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x0C:
- _mchan[x].envflags = 0xB0;
-
- chainCommand(x);
- break;
-
- case 0x0D:
- _mchan[x].envflags = 0x30;
- _mchan[x].volume = 0x5F;
- _mchan[x].voldelta = -22;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, _mchan[x].pitch & 0xF);
- APU_writeChannel(x, 3, 0xFF);
-
- chainCommand(x);
- break;
-
- case 0x0E:
- case 0x10:
- _mchan[x].envflags = 0x30;
- _mchan[x].volume = 0x5F;
- _mchan[x].voldelta = -6;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, _mchan[x].pitch & 0xF);
- APU_writeChannel(x, 3, 0xFF);
-
- chainCommand(x);
- break;
-
- case 0x0F:
- chainCommand(x);
- break;
-
- case 0x11:
- APU_writeChannel(x, 2, _mchan[x].pitch & 0xF);
- APU_writeChannel(x, 3, 0xFF);
-
- chainCommand(x);
- break;
-
- case 0x12:
- APU_writeChannel(x, 2, (_mchan[x].pitch + 3) & 0xF);
- APU_writeChannel(x, 3, 0xFF);
-
- chainCommand(x);
- break;
-
- case 0x14:
- _mchan[x].voldelta = -12;
-
- APU_writeChannel(x, 1, 0x8C);
-
- chainCommand(x);
- break;
-
- case 0x15:
- _mchan[x].voldelta = -12;
-
- APU_writeChannel(x, 1, 0x84);
-
- chainCommand(x);
- break;
-
- case 0x17:
- _mchan[x].pitch += 0x0C;
- _mchan[x].envflags = 0x80;
- _mchan[x].volume = 0x6F;
- _mchan[x].voldelta = 0;
-
- APU_writeChannel(x, 0, 0x00);
- APU_writeChannel(x, 1, 0x7F);
- APU_writeControl(APU_readStatus() | channelMask[x]);
- APU_writeChannel(x, 2, freqTable[_mchan[x].pitch] & 0xFF);
- APU_writeChannel(x, 3, freqTable[_mchan[x].pitch] >> 8);
-
- chainCommand(x);
- break;
-
- case 0x18:
- _mchan[x].envflags = 0x70;
-
- chainCommand(x);
- break;
-
- case 0x19:
- _mchan[x].envflags = 0xB0;
-
- chainCommand(x);
- break;
-
- case 0x1B:
- _mchan[x].envflags = 0x00;
- _mchan[x].voldelta = -10;
- break;
- }
- }
-
- _mchan[x].volume += _mchan[x].voldelta;
-
- if (_mchan[x].volume < 0)
- _mchan[x].volume = 0;
- if (_mchan[x].volume > MAXVOLUME)
- _mchan[x].volume = MAXVOLUME;
-
- APU_writeChannel(x, 0, (_mchan[x].volume >> 3) | _mchan[x].envflags);
- }
-}
-
-void Player_NES::chainCommand(int c) {
- int i = _mchan[c].command;
- _mchan[c].command = nextCmd[i];
- _mchan[c].framedelay = nextDelay[i];
-}
-
-int Player_NES::getSoundStatus(int nr) const {
- for (int i = 0; i < NUMSLOTS; i++)
- if (_slot[i].id == nr)
- return 1;
- return 0;
-}
-
-void Player_NES::APU_writeChannel(int chan, int offset, byte value) {
- _apu->WriteReg(0x000 + 4 * chan + offset, value);
-}
-void Player_NES::APU_writeControl(byte value) {
- _apu->WriteReg(0x015, value);
-}
-byte Player_NES::APU_readStatus() {
- return _apu->Read4015();
-}
-
-} // End of namespace Scumm
-
-#endif // DISABLE_NES_APU
diff --git a/engines/scumm/player/nes.h b/engines/scumm/player/nes.h
deleted file mode 100644
index be1617e0f6..0000000000
--- a/engines/scumm/player/nes.h
+++ /dev/null
@@ -1,114 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_NES_H
-#define SCUMM_PLAYER_NES_H
-
-#include "common/scummsys.h"
-#include "scumm/music.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-namespace Scumm {
-
-class ScummEngine;
-namespace APUe {
-class APU;
-}
-
-static const int MAXVOLUME = 0x7F;
-static const int NUMSLOTS = 3;
-static const int NUMCHANS = 4;
-
-/**
- * Scumm NES sound/music driver.
- */
-class Player_NES : public Audio::AudioStream, public MusicEngine {
-public:
- Player_NES(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_NES();
-
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getSoundStatus(int sound) const;
-
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return false; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
-
-private:
-
- void sound_play();
- void playSFX(int nr);
- void playMusic();
- byte fetchSoundByte(int nr);
- void chainCommand(int chan);
- void checkSilenceChannels(int chan);
-
- void APU_writeChannel(int chan, int offset, byte value);
- void APU_writeControl(byte value);
- byte APU_readStatus();
-
- ScummEngine *_vm;
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
- APUe::APU *_apu;
- int _sampleRate;
- int _samples_per_frame;
- int _current_sample;
- int _maxvol;
-
- struct slot {
- int framesleft;
- int id;
- int type;
- byte *data;
- int offset;
- } _slot[NUMSLOTS];
-
- struct mchan {
- int command;
- int framedelay;
- int pitch;
- int volume;
- int voldelta;
- int envflags;
- int cmdlock;
- } _mchan[NUMCHANS];
-
- bool isSFXplaying, wasSFXplaying;
-
- byte *dataStart;
- int numNotes;
- byte *auxData1;
- byte *auxData2;
-
- byte *soundptr;
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/pce.cpp b/engines/scumm/player/pce.cpp
deleted file mode 100644
index 0a9cbaa315..0000000000
--- a/engines/scumm/player/pce.cpp
+++ /dev/null
@@ -1,756 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-/*
- * The PSG_HuC6280 class is based on the HuC6280 sound chip emulator
- * by Charles MacDonald (E-mail: cgfm2@hotmail.com, WWW: http://cgfm2.emuviews.com)
- * The implementation used here was taken from MESS (http://www.mess.org/)
- * the Multiple Emulator Super System (sound/c6280.c).
- * LFO and noise channel support have been removed (not used by Loom PCE).
- */
-
-#include <math.h>
-#include "scumm/player/pce.h"
-#include "common/endian.h"
-
-// PCE sound engine is only used by Loom, which requires 16bit color support
-#ifdef USE_RGB_COLOR
-
-namespace Scumm {
-
-// CPU and PSG use the same base clock but with a different divider
-const double MASTER_CLOCK = 21477270.0; // ~21.48 MHz
-const double CPU_CLOCK = MASTER_CLOCK / 3; // ~7.16 MHz
-const double PSG_CLOCK = MASTER_CLOCK / 6; // ~3.58 MHz
-const double TIMER_CLOCK = CPU_CLOCK / 1024; // ~6.9 kHz
-
-// The PSG update routine is originally triggered by the timer IRQ (not by VSYNC)
-// approx. 120 times per second (TIML=0x39). But as just every second call is used
-// to update the PSG we will call the update routine approx. 60 times per second.
-const double UPDATE_FREQ = TIMER_CLOCK / (57 + 1) / 2; // ~60 Hz
-
-// $AFA5
-static const byte wave_table[7][32] = {
- { // sine
- 0x10, 0x19, 0x1C, 0x1D, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1D, 0x1C, 0x19,
- 0x10, 0x05, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x05,
- }, { // mw-shaped
- 0x10, 0x1C, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, 0x1E, 0x1C, 0x1E, 0x1F, 0x1F, 0x1E, 0x1E, 0x1D, 0x1C,
- 0x10, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03,
- }, { // square
- 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- }, { // triangle
- 0x10, 0x0C, 0x08, 0x04, 0x01, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, 0x1F, 0x1C, 0x18, 0x14,
- 0x10, 0x0C, 0x08, 0x04, 0x01, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, 0x1F, 0x1C, 0x18, 0x14,
- }, { // saw-tooth
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
- }, { // sigmoid
- 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1F, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19,
- 0x08, 0x06, 0x05, 0x03, 0x02, 0x01, 0x00, 0x00, 0x0F, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x16,
- }, { // MW-shaped
- 0x1F, 0x1E, 0x1D, 0x1D, 0x1C, 0x1A, 0x17, 0x0F, 0x0F, 0x17, 0x1A, 0x1C, 0x1D, 0x1D, 0x1E, 0x1F,
- 0x00, 0x01, 0x02, 0x02, 0x03, 0x05, 0x08, 0x0F, 0x0F, 0x08, 0x05, 0x03, 0x02, 0x02, 0x01, 0x00
- }
-};
-
-// AEBC
-static const int control_offsets[14] = {
- 0, 7, 20, 33, 46, 56, 75, 88, 116, 126, 136, 152, 165, 181
-};
-
-// AED8
-static const byte control_data[205] = {
- /* 0*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0xFF,
- /* 7*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x01, 0x00, 0xF0, 0x3A, 0x00, 0xFD, 0xFF,
- /* 20*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x01, 0x00, 0xF0, 0x1D, 0x00, 0xF8, 0xFF,
- /* 33*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x02, 0x00, 0xF0, 0x1E, 0x00, 0xFC, 0xFF,
- /* 46*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x07, 0x00, 0xE0, 0xFF,
- /* 56*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x01, 0x00, 0xD8, 0xF0, 0x00, 0xD8, 0x01, 0x00, 0x00, 0x04, 0x00, 0xF0, 0xFF,
- /* 75*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x03, 0x00, 0xF8, 0x6E, 0x00, 0xFF, 0xFF,
- /* 88*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x08, 0x00, 0xF0, 0xF0, 0x00, 0xD0, 0x01, 0x00, 0x00, 0x05, 0x00, 0xF0, 0xF0, 0x00, 0xB8, 0xE6, 0x80, 0xFF, 0xE6, 0x80, 0xFF, 0xFF,
- /*116*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x05, 0x00, 0xD0, 0xFF,
- /*126*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x04, 0x00, 0xF8, 0xFF,
- /*136*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x03, 0x00, 0xF4, 0xE6, 0xC0, 0xFF, 0xE6, 0xC0, 0xFF, 0xFF,
- /*152*/ 0xF0, 0x00, 0xD0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x10, 0x0E, 0x00, 0xFE, 0xFF,
- /*165*/ 0xF0, 0x00, 0xA8, 0x01, 0x00, 0x00, 0x18, 0x00, 0x02, 0xE6, 0x80, 0xFE, 0xE6, 0xC0, 0xFF, 0xFF,
- /*181*/ 0xF0, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x02, 0x00, 0xF8, 0x02, 0x00, 0x00, 0x02, 0x00, 0xF0, 0x01, 0x00, 0xF8, 0x02, 0x00, 0x08, 0xF1, 0x99, 0xAF
-};
-
-static const uint16 lookup_table[87] = {
- 0x0D40, 0x0C80, 0x0BC0, 0x0B20, 0x0A80, 0x09E0, 0x0940, 0x08C0,
- 0x0840, 0x07E0, 0x0760, 0x0700, 0x06A0, 0x0640, 0x05E0, 0x0590,
- 0x0540, 0x04F0, 0x04A0, 0x0460, 0x0420, 0x03F0, 0x03B0, 0x0380,
- 0x0350, 0x0320, 0x02F0, 0x02C8, 0x02A0, 0x0278, 0x0250, 0x0230,
- 0x0210, 0x01F8, 0x01D8, 0x01C0, 0x01A8, 0x0190, 0x0178, 0x0164,
- 0x0150, 0x013C, 0x0128, 0x0118, 0x0108, 0x00FC, 0x00EC, 0x00E0,
- 0x00D4, 0x00C8, 0x00BC, 0x00B2, 0x00A8, 0x009E, 0x0094, 0x008C,
- 0x0084, 0x007E, 0x0076, 0x0070, 0x006A, 0x0064, 0x005E, 0x0059,
- 0x0054, 0x004F, 0x004A, 0x0046, 0x0042, 0x003F, 0x003B, 0x0038,
- 0x0035, 0x0032, 0x0030, 0x002D, 0x002A, 0x0028, 0x0026, 0x0024,
- 0x0022, 0x0020, 0x001E, 0x001C, 0x001B, 0x8E82, 0xB500
-};
-
-// B27B
-static const uint16 freq_offset[3] = {
- 0, 2, 9
-};
-
-static const uint16 freq_table[] = {
- 0x0000, 0x0800,
- 0xFFB0, 0xFFD1, 0xFFE8, 0xFFF1, 0x0005, 0x0000, 0x0800,
- 0xFF9C, 0xFFD8, 0x0000, 0x000F, 0x0005, 0x0000, 0x0800
-};
-
-static const int sound_table[13] = {
- 0, 2, 3, 4, 5, 6, 7, 8, 9, 11, 1, 10, 11
-};
-
-// 0xAE12
-// Note:
-// - offsets relative to data_table
-// - byte one of each sound was always 0x3F (= use all channels) -> removed from table
-static const uint16 sounds[13][6] = {
- { 481, 481, 481, 481, 481, 481 },
- { 395, 408, 467, 480, 480, 480 },
- { 85, 96, 109, 109, 109, 109 },
- { 110, 121, 134, 134, 134, 134 },
- { 135, 146, 159, 159, 159, 159 },
- { 160, 171, 184, 184, 184, 184 },
- { 185, 196, 209, 209, 209, 209 },
- { 210, 221, 234, 234, 234, 234 },
- { 235, 246, 259, 259, 259, 259 },
- { 260, 271, 284, 284, 284, 284 },
- { 285, 298, 311, 324, 335, 348 },
- { 349, 360, 361, 362, 373, 384 },
- { 0, 84, 84, 84, 84, 84 } // unused
-};
-
-// 0xB2A1
-static const byte data_table[482] = {
- /* 0*/ 0xE2, 0x0A, 0xE1, 0x0D, 0xE6, 0xED, 0xE0, 0x0F, 0xE2, 0x00, 0xE1, 0x00,
- 0xF2, 0xF2, 0xB2, 0xE1, 0x01, 0xF2, 0xF2, 0xB2, 0xE1, 0x02, 0xF2, 0xF2,
- 0xB2, 0xE1, 0x03, 0xF2, 0xF2, 0xB2, 0xE1, 0x04, 0xF2, 0xF2, 0xB2, 0xE1,
- 0x05, 0xF2, 0xF2, 0xB2, 0xE1, 0x06, 0xF2, 0xF2, 0xB2, 0xE1, 0x07, 0xF2,
- 0xF2, 0xB2, 0xE1, 0x08, 0xF2, 0xF2, 0xB2, 0xE1, 0x09, 0xF2, 0xF2, 0xB2,
- 0xE1, 0x0A, 0xF2, 0xF2, 0xB2, 0xE1, 0x0B, 0xF2, 0xF2, 0xB2, 0xE1, 0x0C,
- 0xF2, 0xF2, 0xB2, 0xE1, 0x0D, 0xF2, 0xF2, 0xB2, 0xFF, 0xD1, 0x03, 0xF3,
- /* 84*/ 0xFF,
-
- /* 85*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD3, 0x07, 0xFF,
- /* 96*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0x07, 0xFF,
- /*109*/ 0xFF,
-
- /*110*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD3, 0x27, 0xFF,
- /*121*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0x27, 0xFF,
- /*134*/ 0xFF,
-
- /*135*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD3, 0x47, 0xFF,
- /*146*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0x47, 0xFF,
- /*159*/ 0xFF,
-
- /*160*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD3, 0x57, 0xFF,
- /*171*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0x57, 0xFF,
- /*184*/ 0xFF,
-
- /*185*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD3, 0x77, 0xFF,
- /*196*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0x77, 0xFF,
- /*209*/ 0xFF,
-
- /*210*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD3, 0x97, 0xFF,
- /*221*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0x97, 0xFF,
- /*234*/ 0xFF,
-
- /*235*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD3, 0xB7, 0xFF,
- /*246*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0xB7, 0xFF,
- /*259*/ 0xFF,
-
- /*260*/ 0xE2, 0x0C, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD4, 0x07, 0xFF,
- /*271*/ 0xE2, 0x06, 0xE1, 0x02, 0xE0, 0x0F, 0xE6, 0xED, 0xD5, 0xF0, 0x0C, 0x07, 0xFF,
- /*284*/ 0xFF,
-
- /*285*/ 0xE2, 0x0B, 0xE1, 0x04, 0xE6, 0xED, 0xE0, 0x0A, 0xD0, 0xDB, 0x14, 0x0E, 0xFF,
- /*298*/ 0xE2, 0x0B, 0xE1, 0x04, 0xE6, 0xED, 0xE0, 0x0A, 0xD0, 0xDB, 0x32, 0x1E, 0xFF,
- /*311*/ 0xE2, 0x0B, 0xE1, 0x0B, 0xE6, 0xED, 0xE0, 0x0A, 0xD0, 0xDB, 0x50, 0x1E, 0xFF,
- /*324*/ 0xE2, 0x0B, 0xE1, 0x0B, 0xE6, 0xED, 0xE0, 0x0A, 0xD0, 0x0E, 0xFF,
- /*335*/ 0xE2, 0x0B, 0xE1, 0x02, 0xE6, 0xED, 0xE0, 0x0A, 0xD0, 0xDB, 0x0A, 0x0E, 0xFF,
- /*348*/ 0xFF,
-
- /*349*/ 0xE2, 0x03, 0xE1, 0x01, 0xE6, 0xED, 0xE0, 0x06, 0xD6, 0x17, 0xFF,
- /*360*/ 0xFF,
- /*361*/ 0xFF,
- /*362*/ 0xE2, 0x04, 0xE1, 0x04, 0xE6, 0xED, 0xE0, 0x06, 0xD5, 0xA7, 0xFF,
- /*373*/ 0xE2, 0x03, 0xE1, 0x06, 0xE6, 0xED, 0xE0, 0x06, 0xD6, 0x37, 0xFF,
- /*384*/ 0xE2, 0x04, 0xE1, 0x06, 0xE6, 0xED, 0xE0, 0x06, 0xD3, 0x87, 0xFF,
-
- /*395*/ 0xE2, 0x0C, 0xE1, 0x00, 0xE0, 0x04, 0xE6, 0xED, 0xD4, 0x0B, 0xE8, 0x0B, 0xFF,
- /*408*/ 0xE2, 0x0C, 0xE1, 0x03, 0xE0, 0x04, 0xE6, 0xED, 0xD4, 0xF0, 0x0C, 0x00,
- 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xE8, 0x00,
- 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xE8, 0x00,
- 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xE8, 0x00,
- 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xE8, 0x00, 0xE8, 0x10, 0xFF,
- /*467*/ 0xE2, 0x0C, 0xE1, 0x00, 0xE0, 0x04, 0xE6, 0xED, 0xD4, 0x1B, 0xE8, 0x1B, 0xFF,
- /*480*/ 0xFF,
-
- /*481*/ 0xFF
-};
-
-
-/*
- * PSG_HuC6280
- */
-
-class PSG_HuC6280 {
-private:
- typedef struct {
- uint16 frequency;
- uint8 control;
- uint8 balance;
- uint8 waveform[32];
- uint8 index;
- int16 dda;
- uint32 counter;
- } channel_t;
-
- double _clock;
- double _rate;
- uint8 _select;
- uint8 _balance;
- channel_t _channel[8];
- int16 _volumeTable[32];
- uint32 _noiseFreqTable[32];
- uint32 _waveFreqTable[4096];
-
-public:
- void init();
- void reset();
- void write(int offset, byte data);
- void update(int16* samples, int sampleCnt);
-
- PSG_HuC6280(double clock, double samplerate);
-};
-
-PSG_HuC6280::PSG_HuC6280(double clock, double samplerate) {
- _clock = clock;
- _rate = samplerate;
-
- // Initialize PSG_HuC6280 emulator
- init();
-}
-
-void PSG_HuC6280::init() {
- int i;
- double step;
-
- // Loudest volume level for table
- double level = 65535.0 / 6.0 / 32.0;
-
- // Clear context
- reset();
-
- // Make waveform frequency table
- for (i = 0; i < 4096; i++) {
- step = ((_clock / _rate) * 4096) / (i+1);
- _waveFreqTable[(1 + i) & 0xFFF] = (uint32)step;
- }
-
- // Make noise frequency table
- for (i = 0; i < 32; i++) {
- step = ((_clock / _rate) * 32) / (i+1);
- _noiseFreqTable[i] = (uint32)step;
- }
-
- // Make volume table
- // PSG_HuC6280 has 48dB volume range spread over 32 steps
- step = 48.0 / 32.0;
- for (i = 0; i < 31; i++) {
- _volumeTable[i] = (uint16)level;
- level /= pow(10.0, step / 20.0);
- }
- _volumeTable[31] = 0;
-}
-
-void PSG_HuC6280::reset() {
- _select = 0;
- _balance = 0xFF;
- memset(_channel, 0, sizeof(_channel));
- memset(_volumeTable, 0, sizeof(_volumeTable));
- memset(_noiseFreqTable, 0, sizeof(_noiseFreqTable));
- memset(_waveFreqTable, 0, sizeof(_waveFreqTable));
-}
-
-void PSG_HuC6280::write(int offset, byte data) {
- channel_t *chan = &_channel[_select];
-
- switch(offset & 0x0F) {
- case 0x00: // Channel select
- _select = data & 0x07;
- break;
-
- case 0x01: // Global balance
- _balance = data;
- break;
-
- case 0x02: // Channel frequency (LSB)
- chan->frequency = (chan->frequency & 0x0F00) | data;
- chan->frequency &= 0x0FFF;
- break;
-
- case 0x03: // Channel frequency (MSB)
- chan->frequency = (chan->frequency & 0x00FF) | (data << 8);
- chan->frequency &= 0x0FFF;
- break;
-
- case 0x04: // Channel control (key-on, DDA mode, volume)
- // 1-to-0 transition of DDA bit resets waveform index
- if ((chan->control & 0x40) && ((data & 0x40) == 0)) {
- chan->index = 0;
- }
- chan->control = data;
- break;
-
- case 0x05: // Channel balance
- chan->balance = data;
- break;
-
- case 0x06: // Channel waveform data
- switch(chan->control & 0xC0) {
- case 0x00:
- chan->waveform[chan->index & 0x1F] = data & 0x1F;
- chan->index = (chan->index + 1) & 0x1F;
- break;
-
- case 0x40:
- break;
-
- case 0x80:
- chan->waveform[chan->index & 0x1F] = data & 0x1F;
- chan->index = (chan->index + 1) & 0x1F;
- break;
-
- case 0xC0:
- chan->dda = data & 0x1F;
- break;
- }
-
- break;
-
- case 0x07: // Noise control (enable, frequency)
- case 0x08: // LFO frequency
- case 0x09: // LFO control (enable, mode)
- break;
-
- default:
- break;
- }
-}
-
-void PSG_HuC6280::update(int16* samples, int sampleCnt) {
- static const int scale_tab[] = {
- 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
- 0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F
- };
- int ch;
- int i;
-
- int lmal = (_balance >> 4) & 0x0F;
- int rmal = (_balance >> 0) & 0x0F;
- int vll, vlr;
-
- lmal = scale_tab[lmal];
- rmal = scale_tab[rmal];
-
- // Clear buffer
- memset(samples, 0, 2 * sampleCnt * sizeof(int16));
-
- for (ch = 0; ch < 6; ch++) {
- // Only look at enabled channels
- if (_channel[ch].control & 0x80) {
- int lal = (_channel[ch].balance >> 4) & 0x0F;
- int ral = (_channel[ch].balance >> 0) & 0x0F;
- int al = _channel[ch].control & 0x1F;
-
- lal = scale_tab[lal];
- ral = scale_tab[ral];
-
- // Calculate volume just as the patent says
- vll = (0x1F - lal) + (0x1F - al) + (0x1F - lmal);
- if (vll > 0x1F) vll = 0x1F;
-
- vlr = (0x1F - ral) + (0x1F - al) + (0x1F - rmal);
- if (vlr > 0x1F) vlr = 0x1F;
-
- vll = _volumeTable[vll];
- vlr = _volumeTable[vlr];
-
- // Check channel mode
- if (_channel[ch].control & 0x40) {
- /* DDA mode */
- for (i = 0; i < sampleCnt; i++) {
- samples[2*i] += (int16)(vll * (_channel[ch].dda - 16));
- samples[2*i + 1] += (int16)(vlr * (_channel[ch].dda - 16));
- }
- } else {
- /* Waveform mode */
- uint32 step = _waveFreqTable[_channel[ch].frequency];
- for (i = 0; i < sampleCnt; i += 1) {
- int offset;
- int16 data;
- offset = (_channel[ch].counter >> 12) & 0x1F;
- _channel[ch].counter += step;
- _channel[ch].counter &= 0x1FFFF;
- data = _channel[ch].waveform[offset];
- samples[2*i] += (int16)(vll * (data - 16));
- samples[2*i + 1] += (int16)(vlr * (data - 16));
- }
- }
- }
- }
-}
-
-
-/*
- * Player_PCE
- */
-
-void Player_PCE::PSG_Write(int reg, byte data) {
- _psg->write(reg, data);
-}
-
-void Player_PCE::setupWaveform(byte bank) {
- const byte *ptr = wave_table[bank];
- PSG_Write(4, 0x40);
- PSG_Write(4, 0x00);
- for (int i = 0; i < 32; ++i) {
- PSG_Write(6, ptr[i]);
- }
-}
-
-// A541
-void Player_PCE::procA541(channel_t *channel) {
- channel->soundDataPtr = NULL;
- channel->controlVecShort10 = 0;
-
- channel->controlVecShort03 = 0;
- channel->controlVecShort06 = 0;
- channel->controlVec8 = 0;
- channel->controlVec9 = 0;
- channel->controlVec10 = 0;
- channel->soundUpdateCounter = 0;
- channel->controlVec18 = 0;
- channel->controlVec19 = 0;
- channel->controlVec23 = false;
- channel->controlVec24 = false;
- channel->controlVec21 = 0;
-
- channel->waveformCtrl = 0x80;
-}
-
-// A592
-void Player_PCE::startSound(int sound) {
- channel_t *channel;
- const uint16 *ptr = sounds[sound_table[sound]];
-
- for (int i = 0; i < 6; ++i) {
- channel = &channels[i];
- procA541(channel);
-
- channel->controlVec24 = true;
- channel->waveformCtrl = 0;
- channel->controlVec0 = 0;
- channel->controlVec19 = 0;
- channel->controlVec18 = 0;
- channel->soundDataPtr = &data_table[*ptr++];
- }
-}
-
-// A64B
-void Player_PCE::updateSound() {
- for (int i = 0; i < 12; i++) {
- channel_t *channel = &channels[i];
- bool cond = true;
- if (i < 6) {
- channel->controlVec21 ^= 0xFF;
- if (!channel->controlVec21)
- cond = false;
- }
- if (cond) {
- processSoundData(channel);
- procAB7F(channel);
- procAC24(channel);
- channel->controlVec11 = (channel->controlVecShort10 >> 11) | 0x80;
- channel->balance = channel->balance2;
- }
- }
-
- for (int i = 0; i < 6; ++i) {
- procA731(&channels[i]);
- }
-}
-
-int Player_PCE::readBuffer(int16 *buffer, const int numSamples) {
- int sampleCopyCnt;
- int samplesLeft = numSamples;
-
- Common::StackLock lock(_mutex);
-
- while (true) {
- // copy samples to output buffer
- sampleCopyCnt = (samplesLeft < _sampleBufferCnt) ? samplesLeft : _sampleBufferCnt;
- if (sampleCopyCnt > 0) {
- memcpy(buffer, _sampleBuffer, sampleCopyCnt * sizeof(int16));
- buffer += sampleCopyCnt;
- samplesLeft -= sampleCopyCnt;
- _sampleBufferCnt -= sampleCopyCnt;
- }
-
- if (samplesLeft == 0)
- break;
-
- // retrieve samples for one timer period
- updateSound();
- _psg->update(_sampleBuffer, _samplesPerPeriod / 2);
- _sampleBufferCnt = _samplesPerPeriod;
- }
-
- // copy remaining samples to the front of the buffer
- if (_sampleBufferCnt > 0) {
- memmove(&_sampleBuffer[0],
- &_sampleBuffer[_samplesPerPeriod - _sampleBufferCnt],
- _sampleBufferCnt * sizeof(int16));
- }
-
- return numSamples;
-}
-
-void Player_PCE::procA731(channel_t *channel) {
- PSG_Write(0, channel->id);
- PSG_Write(2, channel->freq & 0xFF);
- PSG_Write(3, (channel->freq >> 8) & 0xFF);
-
- int tmp = channel->controlVec11;
- if ((channel->controlVec11 & 0xC0) == 0x80) {
- tmp = channel->controlVec11 & 0x1F;
- if (tmp != 0) {
- tmp -= channel->controlVec0;
- if (tmp >= 0) {
- tmp |= 0x80;
- } else {
- tmp = 0;
- }
- }
- }
-
- PSG_Write(5, channel->balance);
- if ((channel->waveformCtrl & 0x80) == 0) {
- channel->waveformCtrl |= 0x80;
- PSG_Write(0, channel->id);
- setupWaveform(channel->waveformCtrl & 0x7F);
- }
-
- PSG_Write(4, tmp);
-}
-
-// A793
-void Player_PCE::processSoundData(channel_t *channel) {
- channel->soundUpdateCounter--;
- if (channel->soundUpdateCounter > 0) {
- return;
- }
-
- while (true) {
- const byte *ptr = channel->soundDataPtr;
- byte value = (ptr ? *ptr++ : 0xFF);
- if (value < 0xD0) {
- int mult = (value & 0x0F) + 1;
- channel->soundUpdateCounter = mult * channel->controlVec1;
- value >>= 4;
- procAA62(channel, value);
- channel->soundDataPtr = ptr;
- return;
- }
-
- // jump_table (A7F7)
- switch (value - 0xD0) {
- case 0: /*A85A*/
- case 1: /*A85D*/
- case 2: /*A861*/
- case 3: /*A865*/
- case 4: /*A869*/
- case 5: /*A86D*/
- case 6: /*A871*/
- channel->controlVec2 = (value - 0xD0) * 12;
- break;
- case 11: /*A8A8*/
- channel->controlVecShort06 = (int8)*ptr++;
- break;
- case 16: /*A8C2*/
- channel->controlVec1 = *ptr++;
- break;
- case 17: /*A8CA*/
- channel->waveformCtrl = *ptr++;
- break;
- case 18: /*A8D2*/
- channel->controlVec10 = *ptr++;
- break;
- case 22: /*A8F2*/
- value = *ptr;
- channel->balance = value;
- channel->balance2 = value;
- ptr++;
- break;
- case 24: /*A905*/
- channel->controlVec23 = true;
- break;
- case 32: /*A921*/
- ptr++;
- break;
- case 47:
- channel->controlVec24 = false;
- channel->controlVec10 &= 0x7F;
- channel->controlVecShort10 &= 0x00FF;
- return;
- default:
- // unused -> ignore
- break;
- }
-
- channel->soundDataPtr = ptr;
- }
-}
-
-void Player_PCE::procAA62(channel_t *channel, int a) {
- procACEA(channel, a);
- if (channel->controlVec23) {
- channel->controlVec23 = false;
- return;
- }
-
- channel->controlVec18 = 0;
-
- channel->controlVec10 |= 0x80;
- int y = channel->controlVec10 & 0x7F;
- channel->controlBufferPos = &control_data[control_offsets[y]];
- channel->controlVec5 = 0;
-}
-
-void Player_PCE::procAB7F(channel_t *channel) {
- uint16 freqValue = channel->controlVecShort02;
- channel->controlVecShort02 += channel->controlVecShort03;
-
- int pos = freq_offset[channel->controlVec19] + channel->controlVec18;
- freqValue += freq_table[pos];
- if (freq_table[pos + 1] != 0x0800) {
- channel->controlVec18++;
- }
- freqValue += channel->controlVecShort06;
-
- channel->freq = freqValue;
-}
-
-void Player_PCE::procAC24(channel_t *channel) {
- if ((channel->controlVec10 & 0x80) == 0)
- return;
-
- if (channel->controlVec5 == 0) {
- const byte *ctrlPtr = channel->controlBufferPos;
- byte value = *ctrlPtr++;
- while (value >= 0xF0) {
- if (value == 0xF0) {
- channel->controlVecShort10 = READ_LE_UINT16(ctrlPtr);
- ctrlPtr += 2;
- } else if (value == 0xFF) {
- channel->controlVec10 &= 0x7F;
- return;
- } else {
- // unused
- }
- value = *ctrlPtr++;
- }
- channel->controlVec5 = value;
- channel->controlVecShort09 = READ_LE_UINT16(ctrlPtr);
- ctrlPtr += 2;
- channel->controlBufferPos = ctrlPtr;
- }
-
- channel->controlVecShort10 += channel->controlVecShort09;
- channel->controlVec5--;
-}
-
-void Player_PCE::procACEA(channel_t *channel, int a) {
- int x = a +
- channel->controlVec2 +
- channel->controlVec8 +
- channel->controlVec9;
- channel->controlVecShort02 = lookup_table[x];
-}
-
-Player_PCE::Player_PCE(ScummEngine *scumm, Audio::Mixer *mixer) {
- for (int i = 0; i < 12; ++i) {
- memset(&channels[i], 0, sizeof(channel_t));
- channels[i].id = i;
- }
-
- _mixer = mixer;
- _sampleRate = _mixer->getOutputRate();
- _vm = scumm;
-
- _samplesPerPeriod = 2 * (int)(_sampleRate / UPDATE_FREQ);
- _sampleBuffer = new int16[_samplesPerPeriod];
- _sampleBufferCnt = 0;
-
- _psg = new PSG_HuC6280(PSG_CLOCK, _sampleRate);
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_PCE::~Player_PCE() {
- _mixer->stopHandle(_soundHandle);
- delete[] _sampleBuffer;
- delete _psg;
-}
-
-void Player_PCE::stopSound(int nr) {
- // TODO: implement
-}
-
-void Player_PCE::stopAllSounds() {
- // TODO: implement
-}
-
-int Player_PCE::getSoundStatus(int nr) const {
- // TODO: status for each sound
- for (int i = 0; i < 6; ++i) {
- if (channels[i].controlVec24)
- return 1;
- }
- return 0;
-}
-
-int Player_PCE::getMusicTimer() {
- return 0;
-}
-
-} // End of namespace Scumm
-
-#endif // USE_RGB_COLOR
diff --git a/engines/scumm/player/pce.h b/engines/scumm/player/pce.h
deleted file mode 100644
index 427fb1ace6..0000000000
--- a/engines/scumm/player/pce.h
+++ /dev/null
@@ -1,133 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_PCE_H
-#define SCUMM_PLAYER_PCE_H
-
-#include "common/scummsys.h"
-#include "common/mutex.h"
-#include "scumm/music.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-// PCE sound engine is only used by Loom, which requires 16bit color support
-#ifdef USE_RGB_COLOR
-
-namespace Scumm {
-
-class ScummEngine;
-class PSG_HuC6280;
-
-class Player_PCE : public Audio::AudioStream, public MusicEngine {
-private:
- struct channel_t {
- int id;
-
- byte controlVec0;
- byte controlVec1;
- byte controlVec2;
- byte controlVec5;
- byte balance;
- byte balance2;
- byte controlVec8;
- byte controlVec9;
- byte controlVec10;
- byte controlVec11;
- int16 soundUpdateCounter;
- byte controlVec18;
- byte controlVec19;
- byte waveformCtrl;
- byte controlVec21;
- bool controlVec23;
- bool controlVec24;
-
- uint16 controlVecShort02;
- uint16 controlVecShort03;
- int16 controlVecShort06;
- uint16 freq;
- uint16 controlVecShort09;
- uint16 controlVecShort10;
-
- const byte* soundDataPtr;
- const byte* controlBufferPos;
- };
-
-public:
- Player_PCE(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_PCE();
-
- virtual void setMusicVolume(int vol) { _maxvol = vol; }
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getSoundStatus(int sound) const;
- virtual int getMusicTimer();
-
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return true; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
-
-private:
- ScummEngine *_vm;
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
- int _sampleRate;
- int _maxvol;
-
-private:
- PSG_HuC6280 *_psg;
- channel_t channels[12];
- Common::Mutex _mutex;
-
- // number of samples per timer period
- int _samplesPerPeriod;
- int16* _sampleBuffer;
- int _sampleBufferCnt;
-
- void init();
- bool isPlaying();
-
- void PSG_Write(int reg, byte data);
-
- void setupWaveform(byte bank);
- void procA541(channel_t *channel);
- void updateSound();
- void procA731(channel_t *channel);
- void processSoundData(channel_t *channel);
- void procA9F3(int x);
- void procAA62(channel_t *channel, int a);
- uint16 procAAF6(int x);
- void procAB7F(channel_t *channel);
- void procAC24(channel_t *channel);
- void procACEA(channel_t *channel, int a);
- void procAD21(int a, int x);
- void procAD29(int value);
- void procAD3D(int a, int x);
-};
-
-} // End of namespace Scumm
-
-#endif // USE_RGB_COLOR
-
-#endif
diff --git a/engines/scumm/player/sid.cpp b/engines/scumm/player/sid.cpp
deleted file mode 100644
index ae5346f18f..0000000000
--- a/engines/scumm/player/sid.cpp
+++ /dev/null
@@ -1,1384 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef DISABLE_SID
-
-#include "engines/engine.h"
-#include "scumm/player/sid.h"
-#include "scumm/scumm.h"
-#include "audio/mixer.h"
-
-namespace Scumm {
-
-/*
- * The player's update() routine is called once per (NTSC/PAL) frame as it is
- * called by the VIC Rasterline interrupt handler which is in turn called
- * approx. 50 (PAL) or 60 (NTSC) times per second.
- * The SCUMM V0/V1 music playback routines or sound data have not been adjusted
- * to PAL systems. As a consequence, music is played audibly (-16%) slower
- * on PAL systems.
- * In addition, the SID oscillator frequency depends on the video clock too.
- * As SCUMM games use an NTSC frequency table for both NTSC and PAL versions
- * all tone frequencies on PAL systems are slightly (-4%) lower than on NTSC ones.
- *
- * For more info on the SID chip see:
- * - http://www.dopeconnection.net/C64_SID.htm (German)
- * For more info on the VIC chip see:
- * - http://www.htu.tugraz.at/~herwig/c64/man-vic.php (German)
- * - http://www.c64-wiki.de/index.php/VIC (German)
- */
-
-struct TimingProps {
- double clockFreq;
- int cyclesPerFrame;
-};
-
-static const TimingProps timingProps[2] = {
- { 17734472.0 / 18, 312 * 63 }, // PAL: 312*63 cycles/frame @ 985248 Hz (~50Hz)
- { 14318180.0 / 14, 263 * 65 } // NTSC: 263*65 cycles/frame @ 1022727 Hz (~60Hz)
-};
-
-static const uint8 BITMASK[7] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40
-};
-static const uint8 BITMASK_INV[7] = {
- 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF
-};
-
-static const int SID_REG_OFFSET[7] = {
- 0, 7, 14, 21, 2, 9, 16
-};
-
-// NTSC frequency table (also used for PAL versions).
-// FREQ_TBL[i] = tone_freq[i] * 2^24 / clockFreq
-static const uint16 FREQ_TBL[97] = {
- 0x0000, 0x010C, 0x011C, 0x012D, 0x013E, 0x0151, 0x0166, 0x017B,
- 0x0191, 0x01A9, 0x01C3, 0x01DD, 0x01FA, 0x0218, 0x0238, 0x025A,
- 0x027D, 0x02A3, 0x02CC, 0x02F6, 0x0323, 0x0353, 0x0386, 0x03BB,
- 0x03F4, 0x0430, 0x0470, 0x04B4, 0x04FB, 0x0547, 0x0598, 0x05ED,
- 0x0647, 0x06A7, 0x070C, 0x0777, 0x07E9, 0x0861, 0x08E1, 0x0968,
- 0x09F7, 0x0A8F, 0x0B30, 0x0BDA, 0x0C8F, 0x0D4E, 0x0E18, 0x0EEF,
- 0x0FD2, 0x10C3, 0x11C3, 0x12D1, 0x13EF, 0x151F, 0x1660, 0x17B5,
- 0x191E, 0x1A9C, 0x1C31, 0x1DDF, 0x1FA5, 0x2187, 0x2386, 0x25A2,
- 0x27DF, 0x2A3E, 0x2CC1, 0x2F6B, 0x323C, 0x3539, 0x3863, 0x3BBE,
- 0x3F4B, 0x430F, 0x470C, 0x4B45, 0x4FBF, 0x547D, 0x5983, 0x5ED6,
- 0x6479, 0x6A73, 0x70C7, 0x777C, 0x7E97, 0x861E, 0x8E18, 0x968B,
- 0x9F7E, 0xA8FA, 0xB306, 0xBDAC, 0xC8F3, 0xD4E6, 0xE18F, 0xEEF8,
- 0xFD2E
-};
-
-static const int SONG_CHANNEL_OFFSET[3] = { 6, 8, 10 };
-static const int RES_ID_CHANNEL[3] = { 3, 4, 5 };
-
-#define LOBYTE_(a) ((a) & 0xFF)
-#define HIBYTE_(a) (((a) >> 8) & 0xFF)
-
-#define GETBIT(var, pos) ((var) & (1<<(pos)))
-
-void Player_SID::handleMusicBuffer() { // $33cd
- int channel = 2;
- while (channel >= 0) {
- if ((statusBits1A & BITMASK[channel]) == 0 ||
- (busyChannelBits & BITMASK[channel]) != 0) {
- --channel;
- continue;
- }
-
- if (setupSongFileData() == 1)
- return;
-
- uint8* l_chanFileDataPtr = chanFileData[channel];
-
- uint16 l_freq = 0;
- bool l_keepFreq = false;
-
- int y = 0;
- uint8 curByte = l_chanFileDataPtr[y++];
-
- // freq or 0/0xFF
- if (curByte == 0) {
- func_3674(channel);
- if (!isMusicPlaying)
- return;
- continue;
- } else if (curByte == 0xFF) {
- l_keepFreq = true;
- } else {
- l_freq = FREQ_TBL[curByte];
- }
-
- uint8 local1 = 0;
- curByte = l_chanFileDataPtr[y++];
- bool isLastCmdByte = (curByte & 0x80) != 0;
- uint16 curStepSum = stepTbl[curByte & 0x7f];
-
- for (int i = 0; !isLastCmdByte && (i < 2); ++i) {
- curByte = l_chanFileDataPtr[y++];
- isLastCmdByte = (curByte & 0x80) != 0;
- if (curByte & 0x40) {
- // note: bit used in zak theme (95) only (not used/handled in MM)
- _music_timer = curByte & 0x3f;
- } else {
- local1 = curByte & 0x3f;
- }
- }
-
- chanFileData[channel] += y;
- chanDataOffset[channel] += y;
-
- uint8 *l_chanBuf = getResource(RES_ID_CHANNEL[channel]);
-
- if (local1 != 0) {
- // TODO: signed or unsigned?
- uint16 offset = READ_LE_UINT16(&actSongFileData[local1*2 + 12]);
- l_chanFileDataPtr = actSongFileData + offset;
-
- // next five bytes: freqDelta, attack, sustain and phase bit
- for (int i = 0; i < 5; ++i) {
- l_chanBuf[15 + i] = l_chanFileDataPtr[i];
- }
- phaseBit[channel] = l_chanFileDataPtr[4];
-
- for (int i = 0; i < 17; ++i) {
- l_chanBuf[25 + i] = l_chanFileDataPtr[5 + i];
- }
- }
-
- if (l_keepFreq) {
- if (!releasePhase[channel]) {
- l_chanBuf[10] &= 0xfe; // release phase
- }
- releasePhase[channel] = true;
- } else {
- if (releasePhase[channel]) {
- l_chanBuf[19] = phaseBit[channel];
- l_chanBuf[10] |= 0x01; // attack phase
- }
- l_chanBuf[11] = LOBYTE_(l_freq);
- l_chanBuf[12] = HIBYTE_(l_freq);
- releasePhase[channel] = false;
- }
-
- // set counter value for frequency update (freqDeltaCounter)
- l_chanBuf[13] = LOBYTE_(curStepSum);
- l_chanBuf[14] = HIBYTE_(curStepSum);
-
- _soundQueue[channel] = RES_ID_CHANNEL[channel];
- processSongData(channel);
- _soundQueue[channel+4] = RES_ID_CHANNEL[channel];
- processSongData(channel+4);
- --channel;
- }
-}
-
-int Player_SID::setupSongFileData() { // $36cb
- // no song playing
- // TODO: remove (never NULL)
- if (_music == NULL) {
- for (int i = 2; i >= 0; --i) {
- if (songChannelBits & BITMASK[i]) {
- func_3674(i);
- }
- }
- return 1;
- }
-
- // no new song
- songFileOrChanBufData = _music;
- if (_music == actSongFileData) {
- return 0;
- }
-
- // new song selected
- actSongFileData = _music;
- for (int i = 0; i < 3; ++i) {
- chanFileData[i] = _music + chanDataOffset[i];
- }
-
- return -1;
-}
-
-//x:0..2
-void Player_SID::func_3674(int channel) { // $3674
- statusBits1B &= BITMASK_INV[channel];
- if (statusBits1B == 0) {
- isMusicPlaying = false;
- unlockCodeLocation();
- safeUnlockResource(resID_song);
- for (int i = 0; i < 3; ++i) {
- safeUnlockResource(RES_ID_CHANNEL[i]);
- }
- }
-
- chanPrio[channel] = 2;
-
- statusBits1A &= BITMASK_INV[channel];
- phaseBit[channel] = 0;
-
- func_4F45(channel);
-}
-
-void Player_SID::resetPlayerState() { // $48f7
- for (int i = 6; i >= 0; --i)
- releaseChannel(i);
-
- isMusicPlaying = false;
- unlockCodeLocation(); // does nothing
- statusBits1B = 0;
- statusBits1A = 0;
- freeChannelCount = 3;
- swapPrepared = false;
- filterSwapped = false;
- pulseWidthSwapped = false;
- //var5163 = 0;
-}
-
-void Player_SID::resetSID() { // $48D8
- SIDReg24 = 0x0f;
-
- SID_Write( 4, 0);
- SID_Write(11, 0);
- SID_Write(18, 0);
- SID_Write(23, 0);
- SID_Write(21, 0);
- SID_Write(22, 0);
- SID_Write(24, SIDReg24);
-
- resetPlayerState();
-}
-
-void Player_SID::update() { // $481B
- if (initializing)
- return;
-
- if (_soundInQueue) {
- for (int i = 6; i >= 0; --i) {
- if (_soundQueue[i] != -1)
- processSongData(i);
- }
- _soundInQueue = false;
- }
-
- // no sound
- if (busyChannelBits == 0)
- return;
-
- for (int i = 6; i >= 0; --i) {
- if (busyChannelBits & BITMASK[i]) {
- updateFreq(i);
- }
- }
-
- // seems to be used for background (prio=1?) sounds.
- // If a bg sound cannot be played because all SID
- // voices are used by higher priority sounds, the
- // bg sound's state is updated here so it will be at
- // the correct state when a voice is available again.
- if (swapPrepared) {
- swapVars(0, 0);
- swapVarLoaded = true;
- updateFreq(0);
- swapVars(0, 0);
- if (pulseWidthSwapped) {
- swapVars(4, 1);
- updateFreq(4);
- swapVars(4, 1);
- }
- swapVarLoaded = false;
- }
-
- for (int i = 6; i >= 0; --i) {
- if (busyChannelBits & BITMASK[i])
- setSIDWaveCtrlReg(i);
- };
-
- if (isMusicPlaying) {
- handleMusicBuffer();
- }
-
- return;
-}
-
-// channel: 0..6
-void Player_SID::processSongData(int channel) { // $4939
- // always: _soundQueue[channel] != -1
- // -> channelMap[channel] != -1
- channelMap[channel] = _soundQueue[channel];
- _soundQueue[channel] = -1;
- songPosUpdateCounter[channel] = 0;
-
- isVoiceChannel = (channel < 3);
-
- songFileOrChanBufOffset[channel] = vec6[channel];
-
- setupSongPtr(channel);
-
- //vec5[channel] = songFileOrChanBufData; // not used
-
- if (songFileOrChanBufData == NULL) { // chanBuf (4C1C)
- /*
- // TODO: do we need this?
- LOBYTE_(vec20[channel]) = 0;
- LOBYTE_(songPosPtr[channel]) = LOBYTE_(songFileOrChanBufOffset[channel]);
- */
- releaseResourceUnk(channel);
- return;
- }
-
- vec20[channel] = songFileOrChanBufData; // chanBuf (4C1C)
- songPosPtr[channel] = songFileOrChanBufData + songFileOrChanBufOffset[channel]; // chanBuf (4C1C)
- uint8* ptr1 = songPosPtr[channel];
-
- int y = -1;
- if (channel < 4) {
- ++y;
- if (channel == 3) {
- readSetSIDFilterAndProps(&y, ptr1);
- } else if (statusBits1A & BITMASK[channel]) {
- ++y;
- } else { // channel = 0/1/2
- waveCtrlReg[channel] = ptr1[y];
-
- ++y;
- if (ptr1[y] & 0x0f) {
- // filter on for voice channel
- SIDReg23 |= BITMASK[channel];
- } else {
- // filter off for voice channel
- SIDReg23 &= BITMASK_INV[channel];
- }
- SID_Write(23, SIDReg23);
- }
- }
-
- saveSongPos(y, channel);
- busyChannelBits |= BITMASK[channel];
- readSongChunk(channel);
-}
-
-void Player_SID::readSetSIDFilterAndProps(int *offset, uint8* dataPtr) { // $49e7
- SIDReg23 |= dataPtr[*offset];
- SID_Write(23, SIDReg23);
- ++*offset;
- SIDReg24 = dataPtr[*offset];
- SID_Write(24, SIDReg24);
-}
-
-void Player_SID::saveSongPos(int y, int channel) {
- ++y;
- songPosPtr[channel] += y;
- songFileOrChanBufOffset[channel] += y;
-}
-
-// channel: 0..6
-void Player_SID::updateFreq(int channel) {
- isVoiceChannel = (channel < 3);
-
- --freqDeltaCounter[channel];
- if (freqDeltaCounter[channel] < 0) {
- readSongChunk(channel);
- } else {
- freqReg[channel] += freqDelta[channel];
- }
- setSIDFreqAS(channel);
-}
-
-void Player_SID::resetFreqDelta(int channel) {
- freqDeltaCounter[channel] = 0;
- freqDelta[channel] = 0;
-}
-
-void Player_SID::readSongChunk(int channel) { // $4a6b
- while (true) {
- if (setupSongPtr(channel) == 1) {
- // do something with code resource
- releaseResourceUnk(1);
- return;
- }
-
- uint8* ptr1 = songPosPtr[channel];
-
- //curChannelActive = true;
-
- uint8 l_cmdByte = ptr1[0];
- if (l_cmdByte == 0) {
- //curChannelActive = false;
- songPosUpdateCounter[channel] = 0;
-
- var481A = -1;
- releaseChannel(channel);
- return;
- }
-
- //vec19[channel] = l_cmdByte;
-
- // attack (1) / release (0) phase
- if (isVoiceChannel) {
- if (GETBIT(l_cmdByte, 0))
- waveCtrlReg[channel] |= 0x01; // start attack phase
- else
- waveCtrlReg[channel] &= 0xfe; // start release phase
- }
-
- // channel finished bit
- if (GETBIT(l_cmdByte, 1)) {
- var481A = -1;
- releaseChannel(channel);
- return;
- }
-
- int y = 0;
-
- // frequency
- if (GETBIT(l_cmdByte, 2)) {
- y += 2;
- freqReg[channel] = READ_LE_UINT16(&ptr1[y-1]);
- if (!GETBIT(l_cmdByte, 6)) {
- y += 2;
- freqDeltaCounter[channel] = READ_LE_UINT16(&ptr1[y-1]);
- y += 2;
- freqDelta[channel] = READ_LE_UINT16(&ptr1[y-1]);
- } else {
- resetFreqDelta(channel);
- }
- } else {
- resetFreqDelta(channel);
- }
-
- // attack / release
- if (isVoiceChannel && GETBIT(l_cmdByte, 3)) {
- // start release phase
- waveCtrlReg[channel] &= 0xfe;
- setSIDWaveCtrlReg(channel);
-
- ++y;
- attackReg[channel] = ptr1[y];
- ++y;
- sustainReg[channel] = ptr1[y];
-
- // set attack (1) or release (0) phase
- waveCtrlReg[channel] |= (l_cmdByte & 0x01);
- }
-
- if (GETBIT(l_cmdByte, 4)) {
- ++y;
- uint8 curByte = ptr1[y];
-
- // pulse width
- if (isVoiceChannel && GETBIT(curByte, 0)) {
- int reg = SID_REG_OFFSET[channel+4];
-
- y += 2;
- SID_Write(reg, ptr1[y-1]);
- SID_Write(reg+1, ptr1[y]);
- }
-
- if (GETBIT(curByte, 1)) {
- ++y;
- readSetSIDFilterAndProps(&y, ptr1);
-
- y += 2;
- SID_Write(21, ptr1[y-1]);
- SID_Write(22, ptr1[y]);
- }
-
- if (GETBIT(curByte, 2)) {
- resetFreqDelta(channel);
-
- y += 2;
- freqDeltaCounter[channel] = READ_LE_UINT16(&ptr1[y-1]);
- }
- }
-
- // set waveform (?)
- if (GETBIT(l_cmdByte, 5)) {
- ++y;
- waveCtrlReg[channel] = (waveCtrlReg[channel] & 0x0f) | ptr1[y];
- }
-
- // song position
- if (GETBIT(l_cmdByte, 7)) {
- if (songPosUpdateCounter[channel] == 1) {
- y += 2;
- --songPosUpdateCounter[channel];
- saveSongPos(y, channel);
- } else {
- // looping / skipping / ...
- ++y;
- songPosPtr[channel] -= ptr1[y];
- songFileOrChanBufOffset[channel] -= ptr1[y];
-
- ++y;
- if (songPosUpdateCounter[channel] == 0) {
- songPosUpdateCounter[channel] = ptr1[y];
- } else {
- --songPosUpdateCounter[channel];
- }
- }
- } else {
- saveSongPos(y, channel);
- return;
- }
- }
-}
-
-/**
- * Sets frequency, attack and sustain register
- */
-void Player_SID::setSIDFreqAS(int channel) { // $4be6
- if (swapVarLoaded)
- return;
- int reg = SID_REG_OFFSET[channel];
- SID_Write(reg, LOBYTE_(freqReg[channel])); // freq/pulseWidth voice 1/2/3
- SID_Write(reg+1, HIBYTE_(freqReg[channel]));
- if (channel < 3) {
- SID_Write(reg+5, attackReg[channel]); // attack
- SID_Write(reg+6, sustainReg[channel]); // sustain
- }
-}
-
-void Player_SID::setSIDWaveCtrlReg(int channel) { // $4C0D
- if (channel < 3) {
- int reg = SID_REG_OFFSET[channel];
- SID_Write(reg+4, waveCtrlReg[channel]);
- }
-}
-
-// channel: 0..6
-int Player_SID::setupSongPtr(int channel) { // $4C1C
- //resID:5,4,3,songid
- int resID = channelMap[channel];
-
- // TODO: when does this happen, only if resID == 0?
- if (getResource(resID) == NULL) {
- releaseResourceUnk(resID);
- if (resID == bgSoundResID) {
- bgSoundResID = 0;
- bgSoundActive = false;
- swapPrepared = false;
- pulseWidthSwapped = false;
- }
- return 1;
- }
-
- songFileOrChanBufData = getResource(resID); // chanBuf (4C1C)
- if (songFileOrChanBufData == vec20[channel]) {
- return 0;
- } else {
- vec20[channel] = songFileOrChanBufData;
- songPosPtr[channel] = songFileOrChanBufData + songFileOrChanBufOffset[channel];
- return -1;
- }
-}
-
-// ignore: no effect
-// chanResIndex: 3,4,5 or 58
-void Player_SID::unlockResource(int chanResIndex) { // $4CDA
- if ((resStatus[chanResIndex] & 0x7F) != 0)
- --resStatus[chanResIndex];
-}
-
-void Player_SID::countFreeChannels() { // $4f26
- freeChannelCount = 0;
- for (int i = 0; i < 3; ++i) {
- if (GETBIT(usedChannelBits, i) == 0)
- ++freeChannelCount;
- }
-}
-
-void Player_SID::func_4F45(int channel) { // $4F45
- if (swapVarLoaded) {
- if (channel == 0) {
- swapPrepared = false;
- resetSwapVars();
- }
- pulseWidthSwapped = false;
- } else {
- if (channel == 3) {
- filterUsed = false;
- }
-
- if (chanPrio[channel] == 1) {
- if (var481A == 1)
- prepareSwapVars(channel);
- else if (channel < 3)
- clearSIDWaveform(channel);
- } else if (channel < 3 && bgSoundActive && swapPrepared &&
- !(filterSwapped && filterUsed))
- {
- busyChannelBits |= BITMASK[channel];
- useSwapVars(channel);
- waveCtrlReg[channel] |= 0x01;
- setSIDWaveCtrlReg(channel);
-
- safeUnlockResource(channelMap[channel]);
- return;
- }
-
- chanPrio[channel] = 0;
- usedChannelBits &= BITMASK_INV[channel];
- countFreeChannels();
- }
-
- int resIndex = channelMap[channel];
- channelMap[channel] = 0;
- safeUnlockResource(resIndex);
-}
-
-// chanResIndex: 3,4,5 or 58
-void Player_SID::safeUnlockResource(int resIndex) { // $4FEA
- if (!isMusicPlaying) {
- unlockResource(resIndex);
- }
-}
-
-void Player_SID::releaseResource(int resIndex) { // $5031
- releaseResChannels(resIndex);
- if (resIndex == bgSoundResID && var481A == -1) {
- safeUnlockResource(resIndex);
-
- bgSoundResID = 0;
- bgSoundActive = false;
- swapPrepared = false;
- pulseWidthSwapped = false;
-
- resetSwapVars();
- }
-}
-
-void Player_SID::releaseResChannels(int resIndex) { // $5070
- for (int i = 3; i >= 0; --i) {
- if (resIndex == channelMap[i]) {
- releaseChannel(i);
- }
- }
-}
-
-void Player_SID::stopSound_intern(int soundResID) { // $5093
- for (int i = 0; i < 7; ++i) {
- if (soundResID == _soundQueue[i]) {
- _soundQueue[i] = -1;
- }
- }
- var481A = -1;
- releaseResource(soundResID);
-}
-
-void Player_SID::stopMusic_intern() { // $4CAA
- statusBits1B = 0;
- isMusicPlaying = false;
-
- if (resID_song != 0) {
- unlockResource(resID_song);
- }
-
- chanPrio[0] = 2;
- chanPrio[1] = 2;
- chanPrio[2] = 2;
-
- statusBits1A = 0;
- phaseBit[0] = 0;
- phaseBit[1] = 0;
- phaseBit[2] = 0;
-}
-
-void Player_SID::releaseResourceUnk(int resIndex) { // $50A4
- var481A = -1;
- releaseResource(resIndex);
-}
-
-// a: 0..6
-void Player_SID::releaseChannel(int channel) {
- stopChannel(channel);
- if (channel >= 4) {
- return;
- }
- if (channel < 3) {
- SIDReg23Stuff = SIDReg23;
- clearSIDWaveform(channel);
- }
- func_4F45(channel);
- if (channel >= 3) {
- return;
- }
- if ((SIDReg23 != SIDReg23Stuff) &&
- (SIDReg23 & 0x07) == 0)
- {
- if (filterUsed) {
- func_4F45(3);
- stopChannel(3);
- }
- }
-
- stopChannel(channel + 4);
-}
-
-void Player_SID::clearSIDWaveform(int channel) {
- if (!isMusicPlaying && var481A == -1) {
- waveCtrlReg[channel] &= 0x0e;
- setSIDWaveCtrlReg(channel);
- }
-}
-
-void Player_SID::stopChannel(int channel) {
- songPosUpdateCounter[channel] = 0;
- // clear "channel" bit
- busyChannelBits &= BITMASK_INV[channel];
- if (channel >= 4) {
- // pulsewidth = 0
- channelMap[channel] = 0;
- }
-}
-
-// channel: 0..6, swapIndex: 0..2
-void Player_SID::swapVars(int channel, int swapIndex) { // $51a5
- if (channel < 3) {
- SWAP(attackReg[channel], swapAttack[swapIndex]);
- SWAP(sustainReg[channel], swapSustain[swapIndex]);
- }
- //SWAP(vec5[channel], swapVec5[swapIndex]); // not used
- //SWAP(vec19[channel], swapVec19[swapIndex]); // not used
-
- SWAP(chanPrio[channel], swapSongPrio[swapIndex]);
- SWAP(channelMap[channel], swapVec479C[swapIndex]);
- SWAP(songPosUpdateCounter[channel], swapSongPosUpdateCounter[swapIndex]);
- SWAP(waveCtrlReg[channel], swapWaveCtrlReg[swapIndex]);
- SWAP(songPosPtr[channel], swapSongPosPtr[swapIndex]);
- SWAP(freqReg[channel], swapFreqReg[swapIndex]);
- SWAP(freqDeltaCounter[channel], swapVec11[swapIndex]);
- SWAP(freqDelta[channel], swapVec10[swapIndex]);
- SWAP(vec20[channel], swapVec20[swapIndex]);
- SWAP(songFileOrChanBufOffset[channel], swapVec8[swapIndex]);
-}
-
-void Player_SID::resetSwapVars() { // $52d0
- for (int i = 0; i < 2; ++i) {
- swapAttack[i] = 0;
- swapSustain[i] = 0;
- }
- for (int i = 0; i < 3; ++i) {
- swapVec5[i] = 0;
- swapSongPrio[i] = 0;
- swapVec479C[i] = 0;
- swapVec19[i] = 0;
- swapSongPosUpdateCounter[i] = 0;
- swapWaveCtrlReg[i] = 0;
- swapSongPosPtr[i] = 0;
- swapFreqReg[i] = 0;
- swapVec11[i] = 0;
- swapVec10[i] = 0;
- swapVec20[i] = 0;
- swapVec8[i] = 0;
- }
-}
-
-void Player_SID::prepareSwapVars(int channel) { // $52E5
- if (channel >= 4)
- return;
-
- if (channel < 3) {
- if (!keepSwapVars) {
- resetSwapVars();
- }
- swapVars(channel, 0);
- if (busyChannelBits & BITMASK[channel+4]) {
- swapVars(channel+4, 1);
- pulseWidthSwapped = true;
- }
- } else if (channel == 3) {
- SIDReg24_HiNibble = SIDReg24 & 0x70;
- resetSwapVars();
- keepSwapVars = true;
- swapVars(3, 2);
- filterSwapped = true;
- }
- swapPrepared = true;
-}
-
-void Player_SID::useSwapVars(int channel) { // $5342
- if (channel >= 3)
- return;
-
- swapVars(channel, 0);
- setSIDFreqAS(channel);
- if (pulseWidthSwapped) {
- swapVars(channel+4, 1);
- setSIDFreqAS(channel+4);
- }
- if (filterSwapped) {
- swapVars(3, 2);
-
- // resonating filter freq. or voice-to-filter mapping?
- SIDReg23 = (SIDReg23Stuff & 0xf0) | BITMASK[channel];
- SID_Write(23, SIDReg23);
-
- // filter props
- SIDReg24 = (SIDReg24 & 0x0f) | SIDReg24_HiNibble;
- SID_Write(24, SIDReg24);
-
- // filter freq.
- SID_Write(21, LOBYTE_(freqReg[3]));
- SID_Write(22, HIBYTE_(freqReg[3]));
- } else {
- SIDReg23 = SIDReg23Stuff & BITMASK_INV[channel];
- SID_Write(23, SIDReg23);
- }
-
- swapPrepared = false;
- pulseWidthSwapped = false;
- keepSwapVars = false;
- SIDReg24_HiNibble = 0;
- filterSwapped = false;
-}
-
-// ignore: no effect
-// resIndex: 3,4,5 or 58
-void Player_SID::lockResource(int resIndex) { // $4ff4
- if (!isMusicPlaying)
- ++resStatus[resIndex];
-}
-
-void Player_SID::reserveChannel(int channel, uint8 prioValue, int chanResIndex) { // $4ffe
- if (channel == 3) {
- filterUsed = true;
- } else if (channel < 3) {
- usedChannelBits |= BITMASK[channel];
- countFreeChannels();
- }
-
- chanPrio[channel] = prioValue;
- lockResource(chanResIndex);
-}
-
-// ignore: no effect
-void Player_SID::unlockCodeLocation() { // $513e
- resStatus[1] &= 0x80;
- resStatus[2] &= 0x80;
-}
-
-// ignore: no effect
-void Player_SID::lockCodeLocation() { // $514f
- resStatus[1] |= 0x01;
- resStatus[2] |= 0x01;
-}
-
-void Player_SID::initMusic(int songResIndex) { // $7de6
- unlockResource(resID_song);
-
- resID_song = songResIndex;
- _music = getResource(resID_song);
- if (_music == NULL) {
- return;
- }
-
- // song base address
- uint8* songFileDataPtr = _music;
- actSongFileData = _music;
-
- initializing = true;
- _soundInQueue = false;
- isMusicPlaying = false;
-
- unlockCodeLocation();
- resetPlayerState();
-
- lockResource(resID_song);
- buildStepTbl(songFileDataPtr[5]);
-
- // fetch sound
- songChannelBits = songFileDataPtr[4];
- for (int i = 2; i >= 0; --i) {
- if ((songChannelBits & BITMASK[i]) != 0) {
- func_7eae(i, songFileDataPtr);
- }
- }
-
- isMusicPlaying = true;
- lockCodeLocation();
-
- SIDReg23 &= 0xf0;
- SID_Write(23, SIDReg23);
-
- handleMusicBuffer();
-
- initializing = false;
- _soundInQueue = true;
-}
-
-// params:
-// channel: channel 0..2
-void Player_SID::func_7eae(int channel, uint8* songFileDataPtr) {
- int pos = SONG_CHANNEL_OFFSET[channel];
- chanDataOffset[channel] = READ_LE_UINT16(&songFileDataPtr[pos]);
- chanFileData[channel] = songFileDataPtr + chanDataOffset[channel];
-
- //vec5[channel+4] = vec5[channel] = CHANNEL_BUFFER_ADDR[RES_ID_CHANNEL[channel]]; // not used
- vec6[channel+4] = 0x0019;
- vec6[channel] = 0x0008;
-
- func_819b(channel);
-
- waveCtrlReg[channel] = 0;
-}
-
-void Player_SID::func_819b(int channel) {
- reserveChannel(channel, 127, RES_ID_CHANNEL[channel]);
-
- statusBits1B |= BITMASK[channel];
- statusBits1A |= BITMASK[channel];
-}
-
-void Player_SID::buildStepTbl(int step) { // $82B4
- stepTbl[0] = 0;
- stepTbl[1] = step - 2;
- for (int i = 2; i < 33; ++i) {
- stepTbl[i] = stepTbl[i-1] + step;
- }
-}
-
-int Player_SID::reserveSoundFilter(uint8 value, uint8 chanResIndex) { // $4ED0
- int channel = 3;
- reserveChannel(channel, value, chanResIndex);
- return channel;
-}
-
-int Player_SID::reserveSoundVoice(uint8 value, uint8 chanResIndex) { // $4EB8
- for (int i = 2; i >= 0; --i) {
- if ((usedChannelBits & BITMASK[i]) == 0) {
- reserveChannel(i, value, chanResIndex);
- return i;
- }
- }
- return 0;
-}
-
-void Player_SID::findLessPrioChannels(uint8 soundPrio) { // $4ED8
- minChanPrio = 127;
-
- chansWithLowerPrioCount = 0;
- for (int i = 2; i >= 0; --i) {
- if (usedChannelBits & BITMASK[i]) {
- if (chanPrio[i] < soundPrio)
- ++chansWithLowerPrioCount;
- if (chanPrio[i] < minChanPrio) {
- minChanPrio = chanPrio[i];
- minChanPrioIndex = i;
- }
- }
- }
-
- if (chansWithLowerPrioCount == 0)
- return;
-
- if (soundPrio >= chanPrio[3]) {
- actFilterHasLowerPrio = true;
- } else {
- /* TODO: is this really a no-op?
- if (minChanPrioIndex < chanPrio[3])
- minChanPrioIndex = minChanPrioIndex;
- */
-
- actFilterHasLowerPrio = false;
- }
-}
-
-void Player_SID::releaseResourceBySound(int resID) { // $5088
- var481A = 1;
- releaseResource(resID);
-}
-
-void Player_SID::readVec6Data(int x, int *offset, uint8 *songFilePtr, int chanResID) { // $4E99
- //vec5[x] = songFilePtr;
- vec6[x] = songFilePtr[*offset];
- *offset += 2;
- _soundQueue[x] = chanResID;
-}
-
-int Player_SID::initSound(int soundResID) { // $4D0A
- initializing = true;
-
- if (isMusicPlaying && (statusBits1A & 0x07) == 0x07) {
- initializing = false;
- return -2;
- }
-
- uint8 *songFilePtr = getResource(soundResID);
- if (songFilePtr == NULL) {
- initializing = false;
- return 1;
- }
-
- uint8 soundPrio = songFilePtr[4];
- // for (mostly but not always looped) background sounds
- if (soundPrio == 1) {
- bgSoundResID = soundResID;
- bgSoundActive = true;
- }
-
- uint8 requestedChannels = 0;
- if ((songFilePtr[5] & 0x40) == 0) {
- ++requestedChannels;
- if (songFilePtr[5] & 0x02)
- ++requestedChannels;
- if (songFilePtr[5] & 0x08)
- ++requestedChannels;
- }
-
- bool filterNeeded = (songFilePtr[5] & 0x20) != 0;
- bool filterBlocked = (filterUsed && filterNeeded);
- if (filterBlocked || (freeChannelCount < requestedChannels)) {
- findLessPrioChannels(soundPrio);
-
- if ((freeChannelCount + chansWithLowerPrioCount < requestedChannels) ||
- (filterBlocked && !actFilterHasLowerPrio)) {
- initializing = false;
- return -1;
- }
-
- if (filterBlocked) {
- if (soundPrio < chanPrio[3]) {
- initializing = false;
- return -1;
- }
-
- uint8 l_resID = channelMap[3];
- releaseResourceBySound(l_resID);
- }
-
- while ((freeChannelCount < requestedChannels) || (filterNeeded && filterUsed)) {
- findLessPrioChannels(soundPrio);
- if (minChanPrio >= soundPrio) {
- initializing = false;
- return -1;
- }
-
- uint8 l_resID = channelMap[minChanPrioIndex];
- releaseResourceBySound(l_resID);
- }
- }
-
- int x;
- uint8 soundByte5 = songFilePtr[5];
- if (soundByte5 & 0x40)
- x = reserveSoundFilter(soundPrio, soundResID);
- else
- x = reserveSoundVoice(soundPrio, soundResID);
-
- uint8 var4CF3 = x;
- int y = 6;
- if (soundByte5 & 0x01) {
- x += 4;
- readVec6Data(x, &y, songFilePtr, soundResID);
- }
- if (soundByte5 & 0x02) {
- x = reserveSoundVoice(soundPrio, soundResID);
- readVec6Data(x, &y, songFilePtr, soundResID);
- }
- if (soundByte5 & 0x04) {
- x += 4;
- readVec6Data(x, &y, songFilePtr, soundResID);
- }
- if (soundByte5 & 0x08) {
- x = reserveSoundVoice(soundPrio, soundResID);
- readVec6Data(x, &y, songFilePtr, soundResID);
- }
- if (soundByte5 & 0x10) {
- x += 4;
- readVec6Data(x, &y, songFilePtr, soundResID);
- }
- if (soundByte5 & 0x20) {
- x = reserveSoundFilter(soundPrio, soundResID);
- readVec6Data(x, &y, songFilePtr, soundResID);
- }
-
- //vec5[var4CF3] = songFilePtr;
- vec6[var4CF3] = y;
- _soundQueue[var4CF3] = soundResID;
-
- initializing = false;
- _soundInQueue = true;
-
- return soundResID;
-}
-
-void Player_SID::unused1() { // $50AF
- var481A = -1;
- if (bgSoundResID != 0) {
- releaseResourceUnk(bgSoundResID);
- }
-}
-
-///////////////////////////
-///////////////////////////
-
-#define ZEROMEM(a) memset(a, 0, sizeof(a))
-
-Player_SID::Player_SID(ScummEngine *scumm, Audio::Mixer *mixer) {
- /*
- * clear memory
- */
-
- resID_song = 0;
- statusBits1A = 0;
- statusBits1B = 0;
- busyChannelBits = 0;
- SIDReg23 = 0;
- SIDReg23Stuff = 0;
- SIDReg24 = 0;
- bgSoundResID = 0;
- freeChannelCount = 0;
- usedChannelBits = 0;
- var481A = 0;
- songChannelBits = 0;
- //var5163 = 0;
- SIDReg24_HiNibble = 0;
- chansWithLowerPrioCount = 0;
- minChanPrio = 0;
- minChanPrioIndex = 0;
-
- _music = NULL;
- songFileOrChanBufData = NULL;
- actSongFileData = NULL;
-
- initializing = false;
- _soundInQueue = false;
- isVoiceChannel = false;
- isMusicPlaying = false;
- swapVarLoaded = false;
- bgSoundActive = false;
- filterUsed = false;
- pulseWidthSwapped = false;
- swapPrepared = false;
- filterSwapped = false;
- keepSwapVars = false;
- actFilterHasLowerPrio = false;
-
- ZEROMEM(chanFileData);
- ZEROMEM(chanDataOffset);
- ZEROMEM(songPosPtr);
- ZEROMEM(freqReg);
- ZEROMEM(vec6);
- ZEROMEM(songFileOrChanBufOffset);
- ZEROMEM(freqDelta);
- ZEROMEM(freqDeltaCounter);
- ZEROMEM(swapSongPosPtr);
- ZEROMEM(swapVec5);
- ZEROMEM(swapVec8);
- ZEROMEM(swapVec10);
- ZEROMEM(swapFreqReg);
- ZEROMEM(swapVec11);
- ZEROMEM(vec20);
- ZEROMEM(swapVec20);
- ZEROMEM(resStatus);
- ZEROMEM(attackReg);
- ZEROMEM(sustainReg);
- ZEROMEM(phaseBit);
- ZEROMEM(releasePhase);
- ZEROMEM(_soundQueue);
- ZEROMEM(channelMap);
- ZEROMEM(songPosUpdateCounter);
- ZEROMEM(chanPrio);
- ZEROMEM(waveCtrlReg);
- ZEROMEM(swapAttack);
- ZEROMEM(swapSustain);
- ZEROMEM(swapSongPrio);
- ZEROMEM(swapVec479C);
- ZEROMEM(swapVec19);
- ZEROMEM(swapSongPosUpdateCounter);
- ZEROMEM(swapWaveCtrlReg);
- ZEROMEM(stepTbl);
-
- /*
- * initialize data
- */
-
- const uint8 chanBuffer_const[3][45] = {
- {
- 0x00,0x00,0x00,0x00,0x7f,0x01,0x19,0x00,
- 0x00,0x00,0x2d,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0xf0,0x40,0x10,0x04,0x00,0x00,
- 0x00,0x04,0x27,0x03,0xff,0xff,0x01,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00
- },
- {
- 0x00,0x00,0x00,0x00,0x7f,0x01,0x19,0x00,
- 0x00,0x00,0x2d,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0xf0,0x20,0x10,0x04,0x00,0x00,
- 0x00,0x04,0x27,0x03,0xff,0xff,0x02,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00
- },
- {
- 0x00,0x00,0x00,0x00,0x7f,0x01,0x19,0x00,
- 0x00,0x00,0x2d,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0xf0,0x20,0x10,0x04,0x00,0x00,
- 0x00,0x04,0x27,0x03,0xff,0xff,0x02,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00
- }
- };
- memcpy(chanBuffer, chanBuffer_const, sizeof(chanBuffer_const));
-
- for (int i = 0; i < 7; ++i) {
- _soundQueue[i] = -1;
- };
-
- _music_timer = 0;
-
- _mixer = mixer;
- _sampleRate = _mixer->getOutputRate();
- _vm = scumm;
-
- // sound speed is slightly different on NTSC and PAL machines
- // as the SID clock depends on the frame rate.
- // ScummVM does not distinguish between NTSC and PAL targets
- // so we use the NTSC timing here as the music was composed for
- // NTSC systems (music on PAL systems is slower).
- _videoSystem = NTSC;
- _cpuCyclesLeft = 0;
-
- initSID();
- resetSID();
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_SID::~Player_SID() {
- _mixer->stopHandle(_soundHandle);
- delete _sid;
-}
-
-uint8 *Player_SID::getResource(int resID) {
- switch (resID) {
- case 0:
- return NULL;
- case 3:
- case 4:
- case 5:
- return chanBuffer[resID-3];
- default:
- return _vm->getResourceAddress(rtSound, resID);
- }
-}
-
-int Player_SID::readBuffer(int16 *buffer, const int numSamples) {
- int samplesLeft = numSamples;
-
- Common::StackLock lock(_mutex);
-
- while (samplesLeft > 0) {
- // update SID status after each frame
- if (_cpuCyclesLeft <= 0) {
- update();
- _cpuCyclesLeft = timingProps[_videoSystem].cyclesPerFrame;
- }
- // fetch samples
- int sampleCount = _sid->updateClock(_cpuCyclesLeft, (short *)buffer, samplesLeft);
- samplesLeft -= sampleCount;
- buffer += sampleCount;
- }
-
- return numSamples;
-}
-
-void Player_SID::SID_Write(int reg, uint8 data) {
- _sid->write(reg, data);
-}
-
-void Player_SID::initSID() {
- _sid = new Resid::SID();
- _sid->set_sampling_parameters(
- timingProps[_videoSystem].clockFreq,
- _sampleRate);
- _sid->enable_filter(true);
-
- _sid->reset();
- // Synchronize the waveform generators (must occur after reset)
- _sid->write( 4, 0x08);
- _sid->write(11, 0x08);
- _sid->write(18, 0x08);
- _sid->write( 4, 0x00);
- _sid->write(11, 0x00);
- _sid->write(18, 0x00);
-}
-
-void Player_SID::startSound(int nr) {
- byte *data = _vm->getResourceAddress(rtSound, nr);
- assert(data);
-
- // WORKAROUND:
- // sound[4] contains either a song prio or a music channel usage byte.
- // As music channel usage is always 0x07 for all music files and
- // prio 7 is never used in any sound file use this byte for auto-detection.
- bool isMusic = (data[4] == 0x07);
-
- Common::StackLock lock(_mutex);
-
- if (isMusic) {
- initMusic(nr);
- } else {
- stopSound_intern(nr);
- initSound(nr);
- }
-}
-
-void Player_SID::stopSound(int nr) {
- if (nr == -1)
- return;
-
- Common::StackLock lock(_mutex);
- stopSound_intern(nr);
-}
-
-void Player_SID::stopAllSounds() {
- Common::StackLock lock(_mutex);
- resetPlayerState();
-}
-
-int Player_SID::getSoundStatus(int nr) const {
- int result = 0;
-
- //Common::StackLock lock(_mutex);
-
- if (resID_song == nr && isMusicPlaying) {
- result = 1;
- }
-
- for (int i = 0; (i < 4) && (result == 0); ++i) {
- if (nr == _soundQueue[i] || nr == channelMap[i]) {
- result = 1;
- }
- }
-
- return result;
-}
-
-int Player_SID::getMusicTimer() {
- int result = _music_timer;
- _music_timer = 0;
- return result;
-}
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/sid.h b/engines/scumm/player/sid.h
deleted file mode 100644
index 12e3573575..0000000000
--- a/engines/scumm/player/sid.h
+++ /dev/null
@@ -1,276 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_SID_H
-#define SCUMM_PLAYER_SID_H
-
-#include "common/mutex.h"
-#include "common/scummsys.h"
-#include "scumm/music.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/softsynth/sid.h"
-
-namespace Scumm {
-
-// the "channel" parameters seem to be in fact SID register
-// offsets. Should be replaced.
-enum sid_reg_t {
- FREQ_VOICE1,
- FREQ_VOICE2,
- FREQ_VOICE3,
- FREQ_FILTER,
- PULSE_VOICE1,
- PULSE_VOICE2,
- PULSE_VOICE3
-};
-
-enum VideoStandard {
- PAL,
- NTSC
-};
-
-class ScummEngine;
-
-class Player_SID : public Audio::AudioStream, public MusicEngine {
-public:
- Player_SID(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_SID();
-
- virtual void setMusicVolume(int vol) { _maxvol = vol; }
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getSoundStatus(int sound) const;
- virtual int getMusicTimer();
-
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return false; }
- bool endOfData() const { return false; }
- int getRate() const { return _sampleRate; }
-
-private:
- Resid::SID *_sid;
- void SID_Write(int reg, uint8 data);
- void initSID();
- uint8 *getResource(int resID);
-
- // number of cpu cycles until next frame update
- Resid::cycle_count _cpuCyclesLeft;
-
- ScummEngine *_vm;
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
- int _sampleRate;
- int _maxvol;
- Common::Mutex _mutex;
-
- VideoStandard _videoSystem;
-
- int _music_timer;
- uint8* _music;
-
-private:
- void initMusic(int songResIndex); // $7de6
- int initSound(int soundResID); // $4D0A
- void stopSound_intern(int soundResID); // $5093
- void stopMusic_intern(); // $4CAA
-
- void resetSID(); // $48D8
- void update(); // $481B
- void handleMusicBuffer();
- int setupSongFileData(); // $36cb
- void func_3674(int channel); // $3674
- void resetPlayerState(); // $48f7
- void processSongData(int channel); // $4939
- void readSetSIDFilterAndProps(int *offset, uint8* dataPtr); // $49e7
- void saveSongPos(int y, int channel);
- void updateFreq(int channel);
- void resetFreqDelta(int channel);
- void readSongChunk(int channel); // $4a6b
- void setSIDFreqAS(int channel); // $4be6
- void setSIDWaveCtrlReg(int channel); // $4C0D
- int setupSongPtr(int channel); // $4C1C
- void unlockResource(int chanResIndex); // $4CDA
- void countFreeChannels(); // $4f26
- void func_4F45(int channel); // $4F45
- void safeUnlockResource(int resIndex); // $4FEA
- void releaseResource(int resIndex); // $5031
- void releaseResChannels(int resIndex); // $5070
- void releaseResourceUnk(int resIndex); // $50A4
- void releaseChannel(int channel);
- void clearSIDWaveform(int channel);
- void stopChannel(int channel);
- void swapVars(int channel, int swapIndex); // $51a5
- void resetSwapVars(); // $52d0
- void prepareSwapVars(int channel); // $52E5
- void useSwapVars(int channel); // $5342
- void lockResource(int resIndex); // $4ff4
- void reserveChannel(int channel, uint8 prioValue, int chanResIndex); // $4ffe
- void unlockCodeLocation(); // $513e
- void lockCodeLocation(); // $514f
- void func_7eae(int channel, uint8* songFileDataPtr); // $7eae
- void func_819b(int channel); // $819b
- void buildStepTbl(int step); // $82B4
- int reserveSoundFilter(uint8 value, uint8 chanResIndex); // $4ED0
- int reserveSoundVoice(uint8 value, uint8 chanResIndex); // $4EB8
- void findLessPrioChannels(uint8 soundPrio); // $4ED8
- void releaseResourceBySound(int resID); // $5088
- void readVec6Data(int x, int *offset, uint8 *songFilePtr, int chanResID); // $4E99
-
- void unused1(); // $50AF
-
- uint8 chanBuffer[3][45];
-
- int resID_song;
-
- // statusBits1A/1B are always equal
- uint8 statusBits1A;
- uint8 statusBits1B;
-
- uint8 busyChannelBits;
-
- uint8 SIDReg23;
- uint8 SIDReg23Stuff;
- uint8 SIDReg24;
-
- uint8* chanFileData[3];
- uint16 chanDataOffset[3];
- uint8* songPosPtr[7];
-
- // 0..2: freq value voice1/2/3
- // 3: filter freq
- // 4..6: pulse width
- uint16 freqReg[7];
-
- // start offset[i] for songFileOrChanBufData to obtain songPosPtr[i]
- // vec6[0..2] = 0x0008;
- // vec6[4..6] = 0x0019;
- uint16 vec6[7];
-
- // current offset[i] for songFileOrChanBufData to obtain songPosPtr[i] (starts with vec6[i], increased later)
- uint16 songFileOrChanBufOffset[7];
-
- uint16 freqDelta[7];
- int freqDeltaCounter[7];
- uint8* swapSongPosPtr[3];
- uint8* swapVec5[3];
- uint16 swapVec8[3];
- uint16 swapVec10[3];
- uint16 swapFreqReg[3];
- int swapVec11[3];
-
- // never read
- //uint8* vec5[7];
- // never read
- //uint8 vec19[7];
- // never read (needed by scumm engine?)
- //bool curChannelActive;
-
- uint8* vec20[7];
-
- uint8* swapVec20[3];
-
- // resource status (never read)
- // bit7: some flag
- // bit6..0: counter (use-count?), maybe just bit0 as flag (used/unused?)
- uint8 resStatus[70];
-
- uint8* songFileOrChanBufData;
- uint8* actSongFileData;
-
- uint16 stepTbl[33];
-
- bool initializing;
- bool _soundInQueue;
- bool isVoiceChannel;
-
- bool isMusicPlaying;
- bool swapVarLoaded;
- bool bgSoundActive;
- bool filterUsed;
-
- uint8 bgSoundResID;
- uint8 freeChannelCount;
-
- // seems to be used for managing the three voices
- // bit[0..2]: 0 -> unused, 1 -> already in use
- uint8 usedChannelBits;
- uint8 attackReg[3];
- uint8 sustainReg[3];
-
- // -1/0/1
- int var481A;
-
- // bit-array: 00000cba
- // a/b/c: channel1/2/3
- uint8 songChannelBits;
-
- bool pulseWidthSwapped;
- bool swapPrepared;
-
- // never read
- //uint8 var5163;
-
- bool filterSwapped;
- uint8 SIDReg24_HiNibble;
- bool keepSwapVars;
-
- uint8 phaseBit[3];
- bool releasePhase[3];
-
- // values: a resID or -1
- // resIDs: 3, 4, 5 or song-number
- int _soundQueue[7];
-
- // values: a resID or 0
- // resIDs: 3, 4, 5 or song-number
- int channelMap[7];
-
- uint8 songPosUpdateCounter[7];
-
- // priortity of channel contents
- // MM: 1: lowest .. 120: highest (1,2,A,64,6E,73,78)
- // Zak: -???: lowest .. 120: highest (5,32,64,65,66,6E,78, A5,A6,AF,D7)
- uint8 chanPrio[7];
-
- // only [0..2] used?
- uint8 waveCtrlReg[7];
-
- uint8 swapAttack[2];
- uint8 swapSustain[2];
- uint8 swapSongPrio[3];
- int swapVec479C[3];
- uint8 swapVec19[3];
- uint8 swapSongPosUpdateCounter[3];
- uint8 swapWaveCtrlReg[3];
-
- bool actFilterHasLowerPrio;
- uint8 chansWithLowerPrioCount;
- uint8 minChanPrio;
- uint8 minChanPrioIndex;
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/towns.cpp b/engines/scumm/player/towns.cpp
deleted file mode 100644
index 4adb11b5a3..0000000000
--- a/engines/scumm/player/towns.cpp
+++ /dev/null
@@ -1,753 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-
-#include "scumm/sound.h"
-#include "scumm/player/towns.h"
-
-namespace Scumm {
-
-Player_Towns::Player_Towns(ScummEngine *vm, bool isVersion2) : _vm(vm), _v2(isVersion2), _intf(0), _numSoundMax(isVersion2 ? 256 : 200), _unkFlags(0x33) {
- memset(_pcmCurrentSound, 0, sizeof(_pcmCurrentSound));
-}
-
-void Player_Towns::setSfxVolume(int vol) {
- if (!_intf)
- return;
- _intf->setSoundEffectVolume(vol);
-}
-
-int Player_Towns::getSoundStatus(int sound) const {
- if (!_intf)
- return 0;
- for (int i = 1; i < 9; i++) {
- if (_pcmCurrentSound[i].index == sound)
- return _intf->callback(40, 0x3f + i) ? 1 : 0;
- }
- return 0;
-}
-
-void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
- static const SaveLoadEntry pcmEntries[] = {
- MKLINE(PcmCurrentSound, index, sleInt16, VER(81)),
- MKLINE(PcmCurrentSound, chan, sleInt16, VER(81)),
- MKLINE(PcmCurrentSound, note, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, velo, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, pan, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, paused, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, looping, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, priority, sleUint32, VER(81)),
- MKEND()
- };
-
- for (int i = 1; i < 9; i++) {
- if (!_pcmCurrentSound[i].index)
- continue;
-
- if (_intf->callback(40, i + 0x3f))
- continue;
-
- _intf->callback(39, i + 0x3f);
-
- _pcmCurrentSound[i].index = 0;
- }
-
- ser->saveLoadArrayOf(_pcmCurrentSound, 9, sizeof(PcmCurrentSound), pcmEntries);
-}
-
-void Player_Towns::restoreAfterLoad() {
- Common::Array<uint16> restoredSounds;
-
- for (int i = 1; i < 9; i++) {
- if (!_pcmCurrentSound[i].index || _pcmCurrentSound[i].index == 0xffff)
- continue;
-
- // Don't restart multichannel sounds more than once
- if (Common::find(restoredSounds.begin(), restoredSounds.end(), _pcmCurrentSound[i].index) != restoredSounds.end())
- continue;
-
- if (!_v2)
- restoredSounds.push_back(_pcmCurrentSound[i].index);
-
- uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index);
- if (!ptr)
- continue;
-
- if (_vm->_game.version != 3)
- ptr += 2;
-
- if (ptr[13])
- continue;
-
- playPcmTrack(_pcmCurrentSound[i].index, ptr + 6, _pcmCurrentSound[i].velo, _pcmCurrentSound[i].pan, _pcmCurrentSound[i].note, _pcmCurrentSound[i].priority);
- }
-}
-
-void Player_Towns::playPcmTrack(int sound, const uint8 *data, int velo, int pan, int note, int priority) {
- if (!_intf)
- return;
-
- const uint8 *sfxData = data + 16;
-
- int numChan = _v2 ? 1 : data[14];
- for (int i = 0; i < numChan; i++) {
- int chan = allocatePcmChannel(sound, i, priority);
- if (!chan)
- return;
-
- _intf->callback(70, _unkFlags);
- _intf->callback(3, chan + 0x3f, pan);
- _intf->callback(37, chan + 0x3f, note, velo, sfxData);
-
- _pcmCurrentSound[chan].note = note;
- _pcmCurrentSound[chan].velo = velo;
- _pcmCurrentSound[chan].pan = pan;
- _pcmCurrentSound[chan].paused = 0;
- _pcmCurrentSound[chan].looping = READ_LE_UINT32(&sfxData[20]) ? 1 : 0;
-
- sfxData += (READ_LE_UINT32(&sfxData[12]) + 32);
- }
-}
-
-void Player_Towns::stopPcmTrack(int sound) {
- if (!_intf)
- return;
-
- for (int i = 1; i < 9; i++) {
- if (sound == _pcmCurrentSound[i].index || !sound) {
- _intf->callback(39, i + 0x3f);
- _pcmCurrentSound[i].index = 0;
- }
- }
-}
-
-int Player_Towns::allocatePcmChannel(int sound, int sfxChanRelIndex, uint32 priority) {
- if (!_intf)
- return 0;
-
- int chan = 0;
-
- if (_v2 && priority > 255) {
- chan = 8;
- if (_intf->callback(40, 0x47))
- _intf->callback(39, 0x47);
- } else {
- for (int i = 8; i; i--) {
- if (!_pcmCurrentSound[i].index) {
- chan = i;
- continue;
- }
-
- if (_intf->callback(40, i + 0x3f))
- continue;
-
- chan = i;
- if (_pcmCurrentSound[chan].index == 0xffff)
- _intf->callback(39, chan + 0x3f);
- else
- _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
- }
-
- if (!chan) {
- for (int i = 1; i < 9; i++) {
- if (priority >= _pcmCurrentSound[i].priority)
- chan = i;
- }
- if (_pcmCurrentSound[chan].index == 0xffff)
- _intf->callback(39, chan + 0x3f);
- else
- _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
- }
- }
-
- if (chan) {
- _pcmCurrentSound[chan].index = sound;
- _pcmCurrentSound[chan].chan = sfxChanRelIndex;
- _pcmCurrentSound[chan].priority = priority;
- }
-
- return chan;
-}
-
-Player_Towns_v1::Player_Towns_v1(ScummEngine *vm, Audio::Mixer *mixer) : Player_Towns(vm, false) {
- _soundOverride = 0;
- _cdaCurrentSound = _eupCurrentSound = _cdaNumLoops = 0;
- _cdaForceRestart = 0;
- _cdaVolLeft = _cdaVolRight = 0;
-
- _eupVolLeft = _eupVolRight = 0;
- _eupLooping = false;
-
- if (_vm->_game.version == 3) {
- _soundOverride = new SoundOvrParameters[_numSoundMax];
- memset(_soundOverride, 0, _numSoundMax * sizeof(SoundOvrParameters));
- }
-
- _driver = new TownsEuphonyDriver(mixer);
-}
-
-Player_Towns_v1::~Player_Towns_v1() {
- delete _driver;
- delete[] _soundOverride;
-}
-
-bool Player_Towns_v1::init() {
- if (!_driver)
- return false;
-
- if (!_driver->init())
- return false;
-
- _driver->reserveSoundEffectChannels(8);
- _intf = _driver->intf();
-
- // Treat all 6 fm channels and all 8 pcm channels as sound effect channels
- // since music seems to exist as CD audio only in the games which use this
- // MusicEngine implementation.
- _intf->setSoundEffectChanMask(-1);
-
- setVolumeCD(255, 255);
-
- return true;
-}
-
-void Player_Towns_v1::setMusicVolume(int vol) {
- _driver->setMusicVolume(vol);
-}
-
-void Player_Towns_v1::startSound(int sound) {
- uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
- if (_vm->_game.version != 3)
- ptr += 2;
-
- int type = ptr[13];
-
- if (type == 0) {
- uint8 velocity = 0;
- uint8 note = 0;
-
- if (_vm->_game.version == 3) {
- velocity = (_soundOverride[sound].vLeft + _soundOverride[sound].vRight);
- note = _soundOverride[sound].note;
- }
-
- velocity = velocity ? velocity >> 2 : ptr[14] >> 1;
- uint16 len = READ_LE_UINT16(ptr) + 2;
- playPcmTrack(sound, ptr + 6, velocity, 64, note ? note : (len > 50 ? ptr[50] : 60), READ_LE_UINT16(ptr + 10));
-
- } else if (type == 1) {
- playEuphonyTrack(sound, ptr + 6);
-
- } else if (type == 2) {
- playCdaTrack(sound, ptr + 6);
- }
-
- if (_vm->_game.version == 3)
- _soundOverride[sound].vLeft = _soundOverride[sound].vRight = _soundOverride[sound].note = 0;
-}
-
-void Player_Towns_v1::stopSound(int sound) {
- if (sound == 0 || sound == _cdaCurrentSound) {
- _cdaCurrentSound = 0;
- _vm->_sound->stopCD();
- _vm->_sound->stopCDTimer();
- }
-
- if (sound != 0 && sound == _eupCurrentSound) {
- _eupCurrentSound = 0;
- _eupLooping = false;
- _driver->stopParser();
- }
-
- stopPcmTrack(sound);
-}
-
-void Player_Towns_v1::stopAllSounds() {
- _cdaCurrentSound = 0;
- _vm->_sound->stopCD();
- _vm->_sound->stopCDTimer();
-
- _eupCurrentSound = 0;
- _eupLooping = false;
- _driver->stopParser();
-
- stopPcmTrack(0);
-}
-
-int Player_Towns_v1::getSoundStatus(int sound) const {
- if (sound == _cdaCurrentSound)
- return _vm->_sound->pollCD();
- if (sound == _eupCurrentSound)
- return _driver->parserIsPlaying() ? 1 : 0;
- return Player_Towns::getSoundStatus(sound);
-}
-
-int32 Player_Towns_v1::doCommand(int numargs, int args[]) {
- int32 res = 0;
-
- switch (args[0]) {
- case 2:
- _driver->intf()->callback(73, 0);
- break;
-
- case 3:
- restartLoopingSounds();
- break;
-
- case 8:
- startSound(args[1]);
- break;
-
- case 9:
- _vm->_sound->stopSound(args[1]);
- break;
-
- case 11:
- stopPcmTrack(0);
- break;
-
- case 14:
- startSoundEx(args[1], args[2], args[3], args[4]);
- break;
-
- case 15:
- stopSoundSuspendLooping(args[1]);
- break;
-
- default:
- warning("Player_Towns_v1::doCommand: Unknown command %d", args[0]);
- break;
- }
-
- return res;
-}
-
-void Player_Towns_v1::setVolumeCD(int left, int right) {
- _cdaVolLeft = left & 0xff;
- _cdaVolRight = right & 0xff;
- _driver->setOutputVolume(1, left >> 1, right >> 1);
-}
-
-void Player_Towns_v1::setSoundVolume(int sound, int left, int right) {
- if (_soundOverride && sound > 0 && sound < _numSoundMax) {
- _soundOverride[sound].vLeft = left;
- _soundOverride[sound].vRight = right;
- }
-}
-
-void Player_Towns_v1::setSoundNote(int sound, int note) {
- if (_soundOverride && sound > 0 && sound < _numSoundMax)
- _soundOverride[sound].note = note;
-}
-
-void Player_Towns_v1::saveLoadWithSerializer(Serializer *ser) {
- _cdaCurrentSoundTemp = (_vm->_sound->pollCD() && _cdaNumLoops > 1) ? _cdaCurrentSound & 0xff : 0;
- _cdaNumLoopsTemp = _cdaNumLoops & 0xff;
-
- static const SaveLoadEntry cdEntries[] = {
- MKLINE(Player_Towns_v1, _cdaCurrentSoundTemp, sleUint8, VER(81)),
- MKLINE(Player_Towns_v1, _cdaNumLoopsTemp, sleUint8, VER(81)),
- MKLINE(Player_Towns_v1, _cdaVolLeft, sleUint8, VER(81)),
- MKLINE(Player_Towns_v1, _cdaVolRight, sleUint8, VER(81)),
- MKEND()
- };
-
- ser->saveLoadEntries(this, cdEntries);
-
- if (!_eupLooping && !_driver->parserIsPlaying())
- _eupCurrentSound = 0;
-
- static const SaveLoadEntry eupEntries[] = {
- MKLINE(Player_Towns_v1, _eupCurrentSound, sleUint8, VER(81)),
- MKLINE(Player_Towns_v1, _eupLooping, sleUint8, VER(81)),
- MKLINE(Player_Towns_v1, _eupVolLeft, sleUint8, VER(81)),
- MKLINE(Player_Towns_v1, _eupVolRight, sleUint8, VER(81)),
- MKEND()
- };
-
- ser->saveLoadEntries(this, eupEntries);
-
- Player_Towns::saveLoadWithSerializer(ser);
-}
-
-void Player_Towns_v1::restoreAfterLoad() {
- setVolumeCD(_cdaVolLeft, _cdaVolRight);
-
- if (_cdaCurrentSoundTemp) {
- uint8 *ptr = _vm->getResourceAddress(rtSound, _cdaCurrentSoundTemp) + 6;
- if (_vm->_game.version != 3)
- ptr += 2;
-
- if (ptr[7] == 2) {
- playCdaTrack(_cdaCurrentSoundTemp, ptr, true);
- _cdaCurrentSound = _cdaCurrentSoundTemp;
- _cdaNumLoops = _cdaNumLoopsTemp;
- }
- }
-
- if (_eupCurrentSound) {
- uint8 *ptr = _vm->getResourceAddress(rtSound, _eupCurrentSound) + 6;
- if (_vm->_game.version != 3)
- ptr += 2;
-
- if (ptr[7] == 1) {
- setSoundVolume(_eupCurrentSound, _eupVolLeft, _eupVolRight);
- playEuphonyTrack(_eupCurrentSound, ptr);
- }
- }
-
- Player_Towns::restoreAfterLoad();
-}
-
-void Player_Towns_v1::restartLoopingSounds() {
- if (_cdaNumLoops && !_cdaForceRestart)
- _cdaForceRestart = 1;
-
- for (int i = 1; i < 9; i++) {
- if (!_pcmCurrentSound[i].paused)
- continue;
-
- _pcmCurrentSound[i].paused = 0;
-
- uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index);
- if (!ptr)
- continue;
- ptr += 24;
-
- int c = 1;
- while (_pcmCurrentSound[i].chan != c) {
- ptr = ptr + READ_LE_UINT32(&ptr[12]) + 32;
- c++;
- }
-
- _driver->playSoundEffect(i + 0x3f, _pcmCurrentSound[i].note, _pcmCurrentSound[i].velo, ptr);
- }
-
- _driver->intf()->callback(73, 1);
-}
-
-void Player_Towns_v1::startSoundEx(int sound, int velo, int pan, int note) {
- uint8 *ptr = _vm->getResourceAddress(rtSound, sound) + 2;
-
- if (pan > 99)
- pan = 99;
-
- velo = velo ? (velo * ptr[14] + 50) / 100 : ptr[14];
- velo = CLIP(velo, 1, 255);
- uint16 pri = READ_LE_UINT16(ptr + 10);
-
- if (ptr[13] == 0) {
- velo >>= 1;
-
- if (!velo)
- velo = 1;
-
- pan = pan ? (((pan << 7) - pan) + 50) / 100 : 64;
-
- playPcmTrack(sound, ptr + 6, velo ? velo : ptr[14] >> 1, pan, note ? note : ptr[50], pri);
-
- } else if (ptr[13] == 2) {
- int volLeft = velo;
- int volRight = velo;
-
- if (pan < 50)
- volRight = ((pan * 2 + 1) * velo + 50) / 100;
- else if (pan > 50)
- volLeft = (((99 - pan) * 2 + 1) * velo + 50) / 100;
-
- setVolumeCD(volLeft, volRight);
-
- if (!_cdaForceRestart && sound == _cdaCurrentSound)
- return;
-
- playCdaTrack(sound, ptr + 6, true);
- }
-}
-
-void Player_Towns_v1::stopSoundSuspendLooping(int sound) {
- if (!sound) {
- return;
- } else if (sound == _cdaCurrentSound) {
- if (_cdaNumLoops && _cdaForceRestart)
- _cdaForceRestart = 1;
- } else {
- for (int i = 1; i < 9; i++) {
- if (sound == _pcmCurrentSound[i].index) {
- if (!_driver->soundEffectIsPlaying(i + 0x3f))
- continue;
- _driver->stopSoundEffect(i + 0x3f);
- if (_pcmCurrentSound[i].looping)
- _pcmCurrentSound[i].paused = 1;
- else
- _pcmCurrentSound[i].index = 0;
- }
- }
- }
-}
-
-void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
- const uint8 *pos = data + 16;
- const uint8 *src = pos + data[14] * 48;
- const uint8 *trackData = src + 150;
-
- for (int i = 0; i < 32; i++)
- _driver->configChan_enable(i, *src++);
- for (int i = 0; i < 32; i++)
- _driver->configChan_setMode(i, 0xff);
- for (int i = 0; i < 32; i++)
- _driver->configChan_remap(i, *src++);
- for (int i = 0; i < 32; i++)
- _driver->configChan_adjustVolume(i, *src++);
- for (int i = 0; i < 32; i++)
- _driver->configChan_setTranspose(i, *src++);
-
- src += 8;
- for (int i = 0; i < 6; i++)
- _driver->assignChannel(i, *src++);
-
- for (int i = 0; i < data[14]; i++) {
- _driver->loadInstrument(i, i, pos + i * 48);
- _driver->intf()->callback(4, i, i);
- }
-
- _eupVolLeft = _soundOverride[sound].vLeft;
- _eupVolRight = _soundOverride[sound].vRight;
- int lvl = _soundOverride[sound].vLeft + _soundOverride[sound].vRight;
- if (!lvl)
- lvl = data[8] + data[9];
- lvl >>= 2;
-
- for (int i = 0; i < 6; i++)
- _driver->chanVolume(i, lvl);
-
- uint32 trackSize = READ_LE_UINT32(src);
- src += 4;
- uint8 startTick = *src++;
-
- _driver->setMusicTempo(*src++);
- _driver->startMusicTrack(trackData, trackSize, startTick);
-
- _eupLooping = (*src != 1) ? 1 : 0;
- _driver->setMusicLoop(_eupLooping != 0);
- _driver->continueParsing();
- _eupCurrentSound = sound;
-}
-
-void Player_Towns_v1::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo) {
- const uint8 *ptr = data;
-
- if (!sound)
- return;
-
- if (!skipTrackVelo) {
- if (_vm->_game.version == 3) {
- if (_soundOverride[sound].vLeft + _soundOverride[sound].vRight)
- setVolumeCD(_soundOverride[sound].vLeft, _soundOverride[sound].vRight);
- else
- setVolumeCD(ptr[8], ptr[9]);
- } else {
- setVolumeCD(ptr[8], ptr[9]);
- }
- }
-
- if (sound == _cdaCurrentSound && _vm->_sound->pollCD() == 1)
- return;
-
- ptr += 16;
-
- int track = ptr[0];
- _cdaNumLoops = ptr[1];
- int start = (ptr[2] * 60 + ptr[3]) * 75 + ptr[4];
- int end = (ptr[5] * 60 + ptr[6]) * 75 + ptr[7];
-
- _vm->_sound->playCDTrack(track, _cdaNumLoops == 0xff ? -1 : _cdaNumLoops, start, end <= start ? 0 : end - start);
- _cdaForceRestart = 0;
- _cdaCurrentSound = sound;
-}
-
-Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, Audio::Mixer *mixer, IMuse *imuse, bool disposeIMuse) : Player_Towns(vm, true), _imuse(imuse), _imuseDispose(disposeIMuse), _sblData(0) {
- _soundOverride = new SoundOvrParameters[_numSoundMax];
- memset(_soundOverride, 0, _numSoundMax * sizeof(SoundOvrParameters));
- _intf = new TownsAudioInterface(mixer, 0);
-}
-
-Player_Towns_v2::~Player_Towns_v2() {
- delete _intf;
- _intf = 0;
-
- if (_imuseDispose)
- delete _imuse;
-
- delete[] _sblData;
- delete[] _soundOverride;
-}
-
-bool Player_Towns_v2::init() {
- if (!_intf)
- return false;
-
- if (!_intf->init())
- return false;
-
- _intf->callback(33, 8);
- _intf->setSoundEffectChanMask(~0x3f);
-
- return true;
-}
-
-void Player_Towns_v2::setMusicVolume(int vol) {
- _imuse->setMusicVolume(vol);
-}
-
-int Player_Towns_v2::getSoundStatus(int sound) const {
- if (_soundOverride[sound].type == 7)
- return Player_Towns::getSoundStatus(sound);
- return _imuse->getSoundStatus(sound);
-}
-
-void Player_Towns_v2::startSound(int sound) {
- uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
-
- if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) {
- _soundOverride[sound].type = 7;
- uint8 velo = _soundOverride[sound].velo ? _soundOverride[sound].velo - 1: (ptr[10] + ptr[11] + 1) >> 1;
- uint8 pan = _soundOverride[sound].pan ? _soundOverride[sound].pan - 1 : 64;
- uint8 pri = ptr[9];
- _soundOverride[sound].velo = _soundOverride[sound].pan = 0;
- playPcmTrack(sound, ptr + 8, velo, pan, ptr[52], pri);
-
- } else if (READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
- _soundOverride[sound].type = 5;
- playVocTrack(ptr + 27);
-
- } else {
- _soundOverride[sound].type = 3;
- _imuse->startSound(sound);
- }
-}
-
-void Player_Towns_v2::stopSound(int sound) {
- if (_soundOverride[sound].type == 7) {
- stopPcmTrack(sound);
- } else {
- _imuse->stopSound(sound);
- }
-}
-
-void Player_Towns_v2::stopAllSounds() {
- stopPcmTrack(0);
- _imuse->stopAllSounds();
-}
-
-int32 Player_Towns_v2::doCommand(int numargs, int args[]) {
- int32 res = -1;
- uint8 *ptr = 0;
-
- switch (args[0]) {
- case 8:
- startSound(args[1]);
- res = 0;
- break;
-
- case 9:
- case 15:
- stopSound(args[1]);
- res = 0;
- break;
-
- case 11:
- stopPcmTrack(0);
- break;
-
- case 13:
- res = getSoundStatus(args[1]);
- break;
-
- case 258:
- if (_soundOverride[args[1]].type == 0) {
- ptr = _vm->getResourceAddress(rtSound, args[1]);
- if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S'))
- _soundOverride[args[1]].type = 7;
- }
- if (_soundOverride[args[1]].type == 7) {
- _soundOverride[args[1]].velo = args[2] + 1;
- res = 0;
- }
- break;
-
- case 259:
- if (_soundOverride[args[1]].type == 0) {
- ptr = _vm->getResourceAddress(rtSound, args[1]);
- if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S'))
- _soundOverride[args[1]].type = 7;
- }
- if (_soundOverride[args[1]].type == 7) {
- _soundOverride[args[1]].pan = 64 - CLIP<int>(args[2], -63, 63);
- res = 0;
- }
- break;
-
- default:
- break;
- }
-
- if (res == -1)
- return _imuse->doCommand(numargs, args);
-
- return res;
-}
-
-void Player_Towns_v2::saveLoadWithSerializer(Serializer *ser) {
- if (ser->getVersion() >= 83)
- Player_Towns::saveLoadWithSerializer(ser);
-}
-
-void Player_Towns_v2::playVocTrack(const uint8 *data) {
- static const uint8 header[] = {
- 0x54, 0x61, 0x6C, 0x6B, 0x69, 0x65, 0x20, 0x20,
- 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x36, 0x04, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00
- };
-
- uint32 len = (READ_LE_UINT32(data) >> 8) - 2;
-
- int chan = allocatePcmChannel(0xffff, 0, 0x1000);
- if (!chan)
- return;
-
- delete[] _sblData;
- _sblData = new uint8[len + 32];
-
- memcpy(_sblData, header, 32);
- WRITE_LE_UINT32(_sblData + 12, len);
-
- const uint8 *src = data + 6;
- uint8 *dst = _sblData + 32;
- for (uint32 i = 0; i < len; i++)
- *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
-
- _intf->callback(37, 0x3f + chan, 60, 127, _sblData);
- _pcmCurrentSound[chan].paused = 0;
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/towns.h b/engines/scumm/player/towns.h
deleted file mode 100644
index 5c76d7c6c7..0000000000
--- a/engines/scumm/player/towns.h
+++ /dev/null
@@ -1,180 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_TOWNS_H
-#define SCUMM_PLAYER_TOWNS_H
-
-#include "scumm/scumm.h"
-#include "scumm/imuse/imuse.h"
-#include "audio/softsynth/fmtowns_pc98/towns_euphony.h"
-#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
-
-namespace Scumm {
-
-class Player_Towns : public MusicEngine {
-public:
- Player_Towns(ScummEngine *vm, bool isVersion2);
- virtual ~Player_Towns() {}
-
- virtual bool init() = 0;
-
- void setSfxVolume(int vol);
-
- int getSoundStatus(int sound) const;
-
- virtual int32 doCommand(int numargs, int args[]) = 0;
-
- virtual void saveLoadWithSerializer(Serializer *ser);
- virtual void restoreAfterLoad();
-
- // version 1 specific
- virtual int getCurrentCdaSound() { return 0; }
- virtual int getCurrentCdaVolume() { return 0; }
- virtual void setVolumeCD(int left, int right) {}
- virtual void setSoundVolume(int sound, int left, int right) {}
- virtual void setSoundNote(int sound, int note) {}
-
-protected:
- void playPcmTrack(int sound, const uint8 *data, int velo = 0, int pan = 64, int note = 0, int priority = 0);
- void stopPcmTrack(int sound);
-
- int allocatePcmChannel(int sound, int sfxChanRelIndex, uint32 priority);
-
- struct PcmCurrentSound {
- uint16 index;
- uint16 chan;
- uint8 note;
- uint8 velo;
- uint8 pan;
- uint8 paused;
- uint8 looping;
- uint32 priority;
- } _pcmCurrentSound[9];
-
- uint8 _unkFlags;
-
- TownsAudioInterface *_intf;
- ScummEngine *_vm;
-
- const int _numSoundMax;
- const bool _v2;
-};
-
-class Player_Towns_v1 : public Player_Towns {
-public:
- Player_Towns_v1(ScummEngine *vm, Audio::Mixer *mixer);
- ~Player_Towns_v1();
-
- bool init();
-
- void setMusicVolume(int vol);
- void startSound(int sound);
- void stopSound(int sound);
- void stopAllSounds();
-
- int getSoundStatus(int sound) const;
- int getCurrentCdaSound() { return _cdaCurrentSound; }
- int getCurrentCdaVolume() { return (_cdaVolLeft + _cdaVolRight + 1) >> 1; }
-
- int32 doCommand(int numargs, int args[]);
-
- void setVolumeCD(int left, int right);
- void setSoundVolume(int sound, int left, int right);
- void setSoundNote(int sound, int note);
-
- void saveLoadWithSerializer(Serializer *ser);
- void restoreAfterLoad();
-
- TownsEuphonyDriver *driver() { return _driver; }
-
-private:
- void restartLoopingSounds();
- void startSoundEx(int sound, int velo, int pan, int note);
- void stopSoundSuspendLooping(int sound);
-
- void playEuphonyTrack(int sound, const uint8 *data);
- void playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo = false);
-
- struct SoundOvrParameters {
- uint8 vLeft;
- uint8 vRight;
- uint8 note;
- };
-
- SoundOvrParameters *_soundOverride;
-
- uint8 _cdaVolLeft;
- uint8 _cdaVolRight;
-
- uint8 _eupCurrentSound;
- uint8 _eupLooping;
- uint8 _eupVolLeft;
- uint8 _eupVolRight;
-
- uint8 _cdaCurrentSound;
- uint8 _cdaNumLoops;
- uint8 _cdaForceRestart;
-
- uint8 _cdaCurrentSoundTemp;
- uint8 _cdaNumLoopsTemp;
-
- TownsEuphonyDriver *_driver;
-};
-
-class Player_Towns_v2 : public Player_Towns {
-public:
- Player_Towns_v2(ScummEngine *vm, Audio::Mixer *mixer, IMuse *imuse, bool disposeIMuse);
- ~Player_Towns_v2();
-
- bool init();
-
- void setMusicVolume(int vol);
-
- int getSoundStatus(int sound) const;
- void startSound(int sound);
- void stopSound(int sound);
- void stopAllSounds();
-
- int32 doCommand(int numargs, int args[]);
-
- void saveLoadWithSerializer(Serializer *ser);
-
-private:
- void playVocTrack(const uint8 *data);
-
- struct SoundOvrParameters {
- uint8 velo;
- uint8 pan;
- uint8 type;
- };
-
- SoundOvrParameters *_soundOverride;
-
- uint8 *_sblData;
-
- IMuse *_imuse;
- const bool _imuseDispose;
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v1.cpp b/engines/scumm/player/v1.cpp
deleted file mode 100644
index 25f42f143c..0000000000
--- a/engines/scumm/player/v1.cpp
+++ /dev/null
@@ -1,607 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-
-#include "engines/engine.h"
-#include "scumm/player/v1.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-#define FB_WNOISE 0x12000 /* feedback for white noise */
-#define FB_PNOISE 0x08000 /* feedback for periodic noise */
-
-#define TIMER_BASE_FREQ 1193000
-#define FIXP_SHIFT 16
-
-Player_V1::Player_V1(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr)
- : Player_V2(scumm, mixer, pcjr) {
- // Initialize channel code
- for (int i = 0; i < 4; ++i)
- clear_channel(i);
-
- _mplex_step = (_sampleRate << FIXP_SHIFT) / 1193000;
- _next_chunk = _repeat_chunk = 0;
- _forced_level = 0;
- _random_lsr = 0;
-}
-
-Player_V1::~Player_V1() {
-}
-
-void Player_V1::chainSound(int nr, byte *data) {
- uint i;
- for (i = 0; i < 4; ++i)
- clear_channel(i);
-
- _current_nr = nr;
- _current_data = data;
- _repeat_chunk = _next_chunk = data + (_pcjr ? 2 : 4);
-
- debug(4, "Chaining new sound %d", nr);
- if (_pcjr)
- parsePCjrChunk();
- else
- parseSpeakerChunk();
-}
-
-void Player_V1::startSound(int nr) {
- Common::StackLock lock(_mutex);
-
- byte *data = _vm->getResourceAddress(rtSound, nr);
- assert(data);
-
- int offset = _pcjr ? READ_LE_UINT16(data+4) : 6;
- int cprio = _current_data ? *(_current_data) & 0x7f : 0;
- int prio = *(data + offset) & 0x7f;
- int restartable = *(data + offset) & 0x80;
-
- debug(4, "startSound %d: prio %d%s, cprio %d",
- nr, prio, restartable ? " restartable" : "", cprio);
-
- if (!_current_nr || cprio <= prio) {
- if (_current_data && (*(_current_data) & 0x80)) {
- _next_nr = _current_nr;
- _next_data = _current_data;
- }
-
- chainSound(nr, data + offset);
- }
-}
-
-void Player_V1::stopAllSounds() {
- Common::StackLock lock(_mutex);
-
- for (int i = 0; i < 4; i++)
- clear_channel(i);
- _repeat_chunk = _next_chunk = 0;
- _next_nr = _current_nr = 0;
- _next_data = _current_data = 0;
-}
-
-void Player_V1::stopSound(int nr) {
- Common::StackLock lock(_mutex);
-
- if (_next_nr == nr) {
- _next_nr = 0;
- _next_data = 0;
- }
- if (_current_nr == nr) {
- for (int i = 0; i < 4; i++) {
- clear_channel(i);
- }
- _repeat_chunk = _next_chunk = 0;
- _current_nr = 0;
- _current_data = 0;
- chainNextSound();
- }
-}
-
-void Player_V1::clear_channel(int i) {
- _channels[i].freq = 0;
- _channels[i].volume = 15;
-}
-
-int Player_V1::getMusicTimer() {
- /* Do V1 games have a music timer? */
- return 0;
-}
-
-void Player_V1::parseSpeakerChunk() {
- set_mplex(3000);
- _forced_level = 0;
-
- parse_again:
- _chunk_type = READ_LE_UINT16(_next_chunk);
- debug(6, "parseSpeakerChunk: sound %d, offset %lx, chunk %x",
- _current_nr, (long)(_next_chunk - _current_data), _chunk_type);
-
- _next_chunk += 2;
- switch (_chunk_type) {
- case 0xffff:
- _current_nr = 0;
- _current_data = 0;
- _channels[0].freq = 0;
- _next_chunk = 0;
- chainNextSound();
- break;
- case 0xfffe:
- _repeat_chunk = _next_chunk;
- goto parse_again;
-
- case 0xfffd:
- _next_chunk = _repeat_chunk;
- goto parse_again;
-
- case 0xfffc:
- /* handle reset. We don't need this do we? */
- goto parse_again;
-
- case 0:
- _time_left = 1;
- set_mplex(READ_LE_UINT16(_next_chunk));
- _next_chunk += 2;
- break;
- case 1:
- set_mplex(READ_LE_UINT16(_next_chunk));
- _start = READ_LE_UINT16(_next_chunk + 2);
- _end = READ_LE_UINT16(_next_chunk + 4);
- _delta = (int16) READ_LE_UINT16(_next_chunk + 6);
- _repeat_ctr = READ_LE_UINT16(_next_chunk + 8);
- _channels[0].freq = _start;
- _next_chunk += 10;
- debug(6, "chunk 1: mplex %d, freq %d -> %d step %d x %d",
- _mplex, _start, _end, _delta, _repeat_ctr);
- break;
- case 2:
- _start = READ_LE_UINT16(_next_chunk);
- _end = READ_LE_UINT16(_next_chunk + 2);
- _delta = (int16) READ_LE_UINT16(_next_chunk + 4);
- _channels[0].freq = 0;
- _next_chunk += 6;
- _forced_level = -1;
- debug(6, "chunk 2: %d -> %d step %d",
- _start, _end, _delta);
- break;
- case 3:
- _start = READ_LE_UINT16(_next_chunk);
- _end = READ_LE_UINT16(_next_chunk + 2);
- _delta = (int16) READ_LE_UINT16(_next_chunk + 4);
- _channels[0].freq = 0;
- _next_chunk += 6;
- _forced_level = -1;
- debug(6, "chunk 3: %d -> %d step %d",
- _start, _end, _delta);
- break;
- }
-}
-
-void Player_V1::nextSpeakerCmd() {
- uint16 lsr;
- switch (_chunk_type) {
- case 0:
- if (--_time_left)
- return;
- _time_left = READ_LE_UINT16(_next_chunk);
- _next_chunk += 2;
- if (_time_left == 0xfffb) {
- /* handle 0xfffb?? */
- _time_left = READ_LE_UINT16(_next_chunk);
- _next_chunk += 2;
- }
- debug(7, "nextSpeakerCmd: chunk %d, offset %4lx: notelen %d",
- _chunk_type, (long)(_next_chunk - 2 - _current_data), _time_left);
- if (_time_left == 0) {
- parseSpeakerChunk();
- } else {
- _channels[0].freq = READ_LE_UINT16(_next_chunk);
- _next_chunk += 2;
- debug(7, "freq_current: %d", _channels[0].freq);
- }
- break;
-
- case 1:
- _channels[0].freq = (_channels[0].freq + _delta) & 0xffff;
- if (_channels[0].freq == _end) {
- if (!--_repeat_ctr) {
- parseSpeakerChunk();
- return;
- }
- _channels[0].freq = _start;
- }
- break;
-
- case 2:
- _start = (_start + _delta) & 0xffff;
- if (_start == _end) {
- parseSpeakerChunk();
- return;
- }
- set_mplex(_start);
- _forced_level = -_forced_level;
- break;
- case 3:
- _start = (_start + _delta) & 0xffff;
- if (_start == _end) {
- parseSpeakerChunk();
- return;
- }
- lsr = _random_lsr + 0x9248;
- lsr = (lsr >> 3) | (lsr << 13);
- _random_lsr = lsr;
- set_mplex((_start & lsr) | 0x180);
- _forced_level = -_forced_level;
- break;
- }
-}
-
-void Player_V1::parsePCjrChunk() {
- uint tmp;
- uint i;
-
- set_mplex(3000);
- _forced_level = 0;
-
-parse_again:
-
- _chunk_type = READ_LE_UINT16(_next_chunk);
- debug(6, "parsePCjrChunk: sound %d, offset %4lx, chunk %x",
- _current_nr, (long)(_next_chunk - _current_data), _chunk_type);
-
- _next_chunk += 2;
- switch (_chunk_type) {
- case 0xffff:
- for (i = 0; i < 4; ++i)
- clear_channel(i);
- _current_nr = 0;
- _current_data = 0;
- _repeat_chunk = _next_chunk = 0;
- chainNextSound();
- break;
-
- case 0xfffe:
- _repeat_chunk = _next_chunk;
- goto parse_again;
-
- case 0xfffd:
- _next_chunk = _repeat_chunk;
- goto parse_again;
-
- case 0xfffc:
- /* handle reset. We don't need this do we? */
- goto parse_again;
-
- case 0:
- set_mplex(READ_LE_UINT16(_next_chunk));
- _next_chunk += 2;
- for (i = 0; i < 4; i++) {
- tmp = READ_LE_UINT16(_next_chunk);
- _next_chunk += 2;
- if (tmp == 0xffff) {
- _channels[i].cmd_ptr = 0;
- continue;
- }
- _channels[i].attack = READ_LE_UINT16(_current_data + tmp);
- _channels[i].decay = READ_LE_UINT16(_current_data + tmp + 2);
- _channels[i].level = READ_LE_UINT16(_current_data + tmp + 4);
- _channels[i].sustain_1 = READ_LE_UINT16(_current_data + tmp + 6);
- _channels[i].sustain_2 = READ_LE_UINT16(_current_data + tmp + 8);
- _channels[i].notelen = 1;
- _channels[i].volume = 15;
- _channels[i].cmd_ptr = _current_data + tmp + 10;
- }
- break;
-
- case 1:
- set_mplex(READ_LE_UINT16(_next_chunk));
- tmp = READ_LE_UINT16(_next_chunk + 2);
- _channels[0].cmd_ptr = tmp != 0xffff ? _current_data + tmp : NULL;
- tmp = READ_LE_UINT16(_next_chunk + 4);
- _start = READ_LE_UINT16(_next_chunk + 6);
- _delta = (int16) READ_LE_UINT16(_next_chunk + 8);
- _time_left = READ_LE_UINT16(_next_chunk + 10);
- _next_chunk += 12;
- if (tmp >= 0xe0) {
- _channels[3].freq = tmp & 0xf;
- _value_ptr = &_channels[3].volume;
- } else {
- assert(!(tmp & 0x10));
- tmp = (tmp & 0x60) >> 5;
- _value_ptr = &_channels[tmp].freq;
- _channels[tmp].volume = 0;
- }
- *_value_ptr = _start;
- if (_channels[0].cmd_ptr) {
- tmp = READ_LE_UINT16(_channels[0].cmd_ptr);
- _start_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 2);
- _delta_2 = (int16) READ_LE_UINT16(_channels[0].cmd_ptr + 4);
- _time_left_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 6);
- _channels[0].cmd_ptr += 8;
- if (_value_ptr == &_channels[3].volume) {
- tmp = (tmp & 0x70) >> 4;
- if (tmp & 1)
- _value_ptr_2 = &_channels[tmp >> 1].volume;
- else
- _value_ptr_2 = &_channels[tmp >> 1].freq;
- } else {
- assert(!(tmp & 0x10));
- tmp = (tmp & 0x60) >> 5;
- _value_ptr_2 = &_channels[tmp].freq;
- _channels[tmp].volume = 0;
- }
- *_value_ptr_2 = _start_2;
- }
- debug(6, "chunk 1: %lu: %d step %d for %d, %lu: %d step %d for %d",
- (long)(_value_ptr - (uint *)_channels), _start, _delta, _time_left,
- (long)(_value_ptr_2 - (uint *)_channels), _start_2, _delta_2, _time_left_2);
- break;
-
- case 2:
- _start = READ_LE_UINT16(_next_chunk);
- _end = READ_LE_UINT16(_next_chunk + 2);
- _delta = (int16) READ_LE_UINT16(_next_chunk + 4);
- _channels[0].freq = 0;
- _next_chunk += 6;
- _forced_level = -1;
- debug(6, "chunk 2: %d -> %d step %d",
- _start, _end, _delta);
- break;
- case 3:
- set_mplex(READ_LE_UINT16(_next_chunk));
- tmp = READ_LE_UINT16(_next_chunk + 2);
- assert((tmp & 0xf0) == 0xe0);
- _channels[3].freq = tmp & 0xf;
- if ((tmp & 3) == 3) {
- _next_chunk += 2;
- _channels[2].freq = READ_LE_UINT16(_next_chunk + 2);
- }
- _channels[3].volume = READ_LE_UINT16(_next_chunk + 4);
- _repeat_ctr = READ_LE_UINT16(_next_chunk + 6);
- _delta = (int16) READ_LE_UINT16(_next_chunk + 8);
- _next_chunk += 10;
- break;
- }
-}
-
-void Player_V1::nextPCjrCmd() {
- uint i;
- int dummy;
- switch (_chunk_type) {
- case 0:
- for (i = 0; i < 4; i++) {
- if (!_channels[i].cmd_ptr)
- continue;
- if (!--_channels[i].notelen) {
- dummy = READ_LE_UINT16(_channels[i].cmd_ptr);
- if (dummy >= 0xfffe) {
- if (dummy == 0xfffe)
- _next_chunk = _current_data + 2;
- parsePCjrChunk();
- return;
- }
- _channels[i].notelen = 4 * dummy;
- dummy = READ_LE_UINT16(_channels[i].cmd_ptr + 2);
- if (dummy == 0) {
- _channels[i].hull_counter = 4;
- _channels[i].sustctr = _channels[i].sustain_2;
- } else {
- _channels[i].hull_counter = 1;
- _channels[i].freq = dummy;
- }
- debug(7, "chunk 0: channel %d play %d for %d",
- i, dummy, _channels[i].notelen);
- _channels[i].cmd_ptr += 4;
- }
-
-
- switch (_channels[i].hull_counter) {
- case 1:
- _channels[i].volume -= _channels[i].attack;
- if ((int) _channels[i].volume <= 0) {
- _channels[i].volume = 0;
- _channels[i].hull_counter++;
- }
- break;
- case 2:
- _channels[i].volume += _channels[i].decay;
- if (_channels[i].volume >= _channels[i].level) {
- _channels[i].volume = _channels[i].level;
- _channels[i].hull_counter++;
- }
- break;
- case 4:
- if (--_channels[i].sustctr < 0) {
- _channels[i].sustctr = _channels[i].sustain_2;
- _channels[i].volume += _channels[i].sustain_1;
- if ((int) _channels[i].volume >= 15) {
- _channels[i].volume = 15;
- _channels[i].hull_counter++;
- }
- }
- break;
- }
- }
- break;
-
- case 1:
- _start += _delta;
- *_value_ptr = _start;
- if (!--_time_left) {
- _start = READ_LE_UINT16(_next_chunk);
- _next_chunk += 2;
- if (_start == 0xffff) {
- parsePCjrChunk();
- return;
- }
- _delta = (int16) READ_LE_UINT16(_next_chunk);
- _time_left = READ_LE_UINT16(_next_chunk + 2);
- _next_chunk += 4;
- *_value_ptr = _start;
- }
-
- if (_channels[0].cmd_ptr) {
- _start_2 += _delta_2;
- *_value_ptr_2 = _start_2;
- if (!--_time_left_2) {
- _start_2 = READ_LE_UINT16(_channels[0].cmd_ptr);
- if (_start_2 == 0xffff) {
- _next_chunk = _channels[0].cmd_ptr + 2;
- parsePCjrChunk();
- return;
- }
- _delta_2 = (int16) READ_LE_UINT16(_channels[0].cmd_ptr + 2);
- _time_left_2 = READ_LE_UINT16(_channels[0].cmd_ptr + 4);
- _channels[0].cmd_ptr += 6;
- }
- }
- break;
-
- case 2:
- _start += _delta;
- if (_start == _end) {
- parsePCjrChunk();
- return;
- }
- set_mplex(_start);
- debug(7, "chunk 2: mplex %d curve %d", _start, _forced_level);
- _forced_level = -_forced_level;
- break;
- case 3:
- dummy = _channels[3].volume + _delta;
- if (dummy >= 15) {
- _channels[3].volume = 15;
- } else if (dummy <= 0) {
- _channels[3].volume = 0;
- } else {
- _channels[3].volume = dummy;
- break;
- }
-
- if (!--_repeat_ctr) {
- parsePCjrChunk();
- return;
- }
- _delta = READ_LE_UINT16(_next_chunk);
- _next_chunk += 2;
- break;
- }
-}
-
-void Player_V1::set_mplex(uint mplex) {
- if (mplex == 0)
- mplex = 65536;
- _mplex = mplex;
- _tick_len = _mplex_step * mplex;
-}
-
-void Player_V1::nextTick() {
- if (_next_chunk) {
- if (_pcjr)
- nextPCjrCmd();
- else
- nextSpeakerCmd();
- }
-}
-
-void Player_V1::generateSpkSamples(int16 *data, uint len) {
- uint i;
-
- memset(data, 0, 2 * sizeof(int16) * len);
- if (_channels[0].freq == 0) {
- if (_forced_level) {
- int sample = _forced_level * _volumetable[0];
- for (i = 0; i < len; i++)
- data[2*i] = data[2*i+1] = sample;
- debug(9, "speaker: %8x: forced one", _tick_len);
- } else if (!_level) {
- return;
- }
- } else {
- squareGenerator(0, _channels[0].freq, 0, 0, data, len);
- debug(9, "speaker: %8x: freq %d %.1f", _tick_len,
- _channels[0].freq, 1193000.0 / _channels[0].freq);
- }
- lowPassFilter(data, len);
-}
-
-void Player_V1::generatePCjrSamples(int16 *data, uint len) {
- uint i, j;
- uint freq, vol;
- bool hasdata = false;
-
- memset(data, 0, 2 * sizeof(int16) * len);
-
- if (_forced_level) {
- int sample = _forced_level * _volumetable[0];
- for (i = 0; i < len; i++)
- data[2*i] = data[2*i+1] = sample;
- hasdata = true;
- debug(9, "channel[4]: %8x: forced one", _tick_len);
- }
-
- for (i = 1; i < 3; i++) {
- freq = _channels[i].freq;
- if (freq) {
- for (j = 0; j < i; j++) {
- if (freq == _channels[j].freq) {
- /* HACK: this channel is playing at
- * the same frequency as another.
- * Synchronize it to the same phase to
- * prevent interference.
- */
- _timer_count[i] = _timer_count[j];
- _timer_output ^= (1 << i) &
- (_timer_output ^ _timer_output << (i - j));
- }
- }
- }
- }
-
- for (i = 0; i < 4; i++) {
- freq = _channels[i].freq;
- vol = _channels[i].volume;
- if (!_volumetable[_channels[i].volume]) {
- _timer_count[i] -= len << FIXP_SHIFT;
- if (_timer_count[i] < 0)
- _timer_count[i] = 0;
- } else if (i < 3) {
- hasdata = true;
- squareGenerator(i, freq, vol, 0, data, len);
- debug(9, "channel[%d]: %8x: freq %d %.1f ; volume %d",
- i, _tick_len, freq, 111860.0 / freq, vol);
- } else {
- int noiseFB = (freq & 4) ? FB_WNOISE : FB_PNOISE;
- int n = (freq & 3);
-
- freq = (n == 3) ? 2 * (_channels[2].freq) : 1 << (5 + n);
- hasdata = true;
- squareGenerator(i, freq, vol, noiseFB, data, len);
- debug(9, "channel[%d]: %x: noise freq %d %.1f ; volume %d",
- i, _tick_len, freq, 111860.0 / freq, vol);
- }
- }
-
- if (_level || hasdata)
- lowPassFilter(data, len);
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v1.h b/engines/scumm/player/v1.h
deleted file mode 100644
index d6e08bd7ab..0000000000
--- a/engines/scumm/player/v1.h
+++ /dev/null
@@ -1,98 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V1_H
-#define SCUMM_PLAYER_V1_H
-
-#include "scumm/player/v2.h"
-
-namespace Scumm {
-
-/**
- * Scumm V1 PC-Speaker player.
- */
-class Player_V1 : public Player_V2 {
-public:
- Player_V1(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr);
- ~Player_V1();
-
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getMusicTimer();
-
-protected:
- virtual void nextTick();
- virtual void clear_channel(int i);
- virtual void chainSound(int nr, byte *data);
-
- virtual void generateSpkSamples(int16 *data, uint len);
- virtual void generatePCjrSamples(int16 *data, uint len);
-
- void restartSound();
-
- void set_mplex(uint mplex);
- void parseSpeakerChunk();
- void nextSpeakerCmd();
- void parsePCjrChunk();
- void nextPCjrCmd();
-
-private:
- struct channel_data_v1 {
- uint freq;
- uint volume;
- byte *cmd_ptr;
- uint notelen;
- uint hull_counter;
- uint attack;
- uint decay;
- uint level;
- uint sustain_1;
- uint sustain_2;
- int sustctr;
- };
-
- channel_data_v1 _channels[4];
-
- byte *_next_chunk;
- byte *_repeat_chunk;
- uint _chunk_type;
- uint _mplex_step;
- uint _mplex;
- uint _repeat_ctr;
- uint _freq_current;
- int _forced_level;
- uint16 _random_lsr;
- uint *_value_ptr;
- uint _time_left;
- uint _start;
- uint _end;
- int _delta;
- uint *_value_ptr_2;
- uint _time_left_2;
- uint _start_2;
- int _delta_2;
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v2.cpp b/engines/scumm/player/v2.cpp
deleted file mode 100644
index e3b3c978dd..0000000000
--- a/engines/scumm/player/v2.cpp
+++ /dev/null
@@ -1,327 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "scumm/player/v2.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-#define SPK_DECAY 0xa000 /* Depends on sample rate */
-#define PCJR_DECAY 0xa000 /* Depends on sample rate */
-
-#define NG_PRESET 0x0f35 /* noise generator preset */
-#define FB_WNOISE 0x12000 /* feedback for white noise */
-#define FB_PNOISE 0x08000 /* feedback for periodic noise */
-
-
-Player_V2::Player_V2(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr)
- : Player_V2Base(scumm, mixer, pcjr) {
-
- int i;
-
- // Initialize square generator
- _level = 0;
-
- _RNG = NG_PRESET;
-
- _pcjr = pcjr;
-
- if (_pcjr) {
- _decay = PCJR_DECAY;
- _update_step = (_sampleRate << FIXP_SHIFT) / (111860 * 2);
- } else {
- _decay = SPK_DECAY;
- _update_step = (_sampleRate << FIXP_SHIFT) / (1193000 * 2);
- }
-
- // Adapt _decay to sample rate. It must be squared when
- // sample rate doubles.
- for (i = 0; (_sampleRate << i) < 30000; i++)
- _decay = _decay * _decay / 65536;
-
- _timer_output = 0;
- for (i = 0; i < 4; i++)
- _timer_count[i] = 0;
-
- setMusicVolume(255);
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_V2::~Player_V2() {
- Common::StackLock lock(_mutex);
- _mixer->stopHandle(_soundHandle);
-}
-
-void Player_V2::setMusicVolume (int vol) {
- if (vol > 255)
- vol = 255;
-
- /* scale to int16, FIXME: find best value */
- double out = vol * 128 / 3;
-
- /* build volume table (2dB per step) */
- for (int i = 0; i < 15; i++) {
- /* limit volume to avoid clipping */
- if (out > 0xffff)
- _volumetable[i] = 0xffff;
- else
- _volumetable[i] = (int) out;
-
- out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */
- }
- _volumetable[15] = 0;
-}
-
-void Player_V2::stopAllSounds() {
- Common::StackLock lock(_mutex);
-
- for (int i = 0; i < 4; i++) {
- clear_channel(i);
- }
- _next_nr = _current_nr = 0;
- _next_data = _current_data = 0;
-}
-
-void Player_V2::stopSound(int nr) {
- Common::StackLock lock(_mutex);
-
- if (_next_nr == nr) {
- _next_nr = 0;
- _next_data = 0;
- }
- if (_current_nr == nr) {
- for (int i = 0; i < 4; i++) {
- clear_channel(i);
- }
- _current_nr = 0;
- _current_data = 0;
- chainNextSound();
- }
-}
-
-void Player_V2::startSound(int nr) {
- Common::StackLock lock(_mutex);
-
- byte *data = _vm->getResourceAddress(rtSound, nr);
- assert(data);
-
- int cprio = _current_data ? *(_current_data + _header_len) : 0;
- int prio = *(data + _header_len);
- int nprio = _next_data ? *(_next_data + _header_len) : 0;
-
- int restartable = *(data + _header_len + 1);
-
- if (!_current_nr || cprio <= prio) {
- int tnr = _current_nr;
- int tprio = cprio;
- byte *tdata = _current_data;
-
- chainSound(nr, data);
- nr = tnr;
- prio = tprio;
- data = tdata;
- restartable = data ? *(data + _header_len + 1) : 0;
- }
-
- if (!_current_nr) {
- nr = 0;
- _next_nr = 0;
- _next_data = 0;
- }
-
- if (nr != _current_nr
- && restartable
- && (!_next_nr
- || nprio <= prio)) {
-
- _next_nr = nr;
- _next_data = data;
- }
-}
-
-int Player_V2::getSoundStatus(int nr) const {
- return _current_nr == nr || _next_nr == nr;
-}
-
-int Player_V2::readBuffer(int16 *data, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- uint step;
- uint len = numSamples / 2;
-
- do {
- if (!(_next_tick >> FIXP_SHIFT)) {
- _next_tick += _tick_len;
- nextTick();
- }
-
- step = len;
- if (step > (_next_tick >> FIXP_SHIFT))
- step = (_next_tick >> FIXP_SHIFT);
- if (_pcjr)
- generatePCjrSamples(data, step);
- else
- generateSpkSamples(data, step);
- data += 2 * step;
- _next_tick -= step << FIXP_SHIFT;
- } while (len -= step);
-
- return numSamples;
-}
-
-void Player_V2::lowPassFilter(int16 *sample, uint len) {
- for (uint i = 0; i < len; i++) {
- _level = (int) (_level * _decay
- + sample[0] * (0x10000 - _decay)) >> 16;
- sample[0] = sample[1] = _level;
- sample += 2;
- }
-}
-
-void Player_V2::squareGenerator(int channel, int freq, int vol,
- int noiseFeedback, int16 *sample, uint len) {
- int32 period = _update_step * freq;
- int32 nsample;
- if (period == 0)
- period = _update_step;
-
- for (uint i = 0; i < len; i++) {
- uint32 duration = 0;
-
- if (_timer_output & (1 << channel))
- duration += _timer_count[channel];
-
- _timer_count[channel] -= (1 << FIXP_SHIFT);
- while (_timer_count[channel] <= 0) {
-
- if (noiseFeedback) {
- if (_RNG & 1) {
- _RNG ^= noiseFeedback;
- _timer_output ^= (1 << channel);
- }
- _RNG >>= 1;
- } else {
- _timer_output ^= (1 << channel);
- }
-
- if (_timer_output & (1 << channel))
- duration += period;
-
- _timer_count[channel] += period;
- }
-
- if (_timer_output & (1 << channel))
- duration -= _timer_count[channel];
-
- nsample = *sample +
- (((int32) (duration - (1 << (FIXP_SHIFT - 1)))
- * (int32) _volumetable[vol]) >> FIXP_SHIFT);
- /* overflow: clip value */
- if (nsample > 0x7fff)
- nsample = 0x7fff;
- if (nsample < -0x8000)
- nsample = -0x8000;
- *sample = nsample;
- // The following write isn't necessary, because the lowPassFilter does it for us
- //sample[1] = sample[0];
- sample += 2;
- }
-}
-
-void Player_V2::generateSpkSamples(int16 *data, uint len) {
- int winning_channel = -1;
- for (int i = 0; i < 4; i++) {
- if (winning_channel == -1
- && _channels[i].d.volume
- && _channels[i].d.time_left) {
- winning_channel = i;
- }
- }
-
- memset(data, 0, 2 * sizeof(int16) * len);
- if (winning_channel != -1) {
- squareGenerator(0, _channels[winning_channel].d.freq, 0,
- 0, data, len);
- } else if (_level == 0)
- /* shortcut: no sound is being played. */
- return;
-
- lowPassFilter(data, len);
-}
-
-void Player_V2::generatePCjrSamples(int16 *data, uint len) {
- int i, j;
- int freq, vol;
-
- memset(data, 0, 2 * sizeof(int16) * len);
- bool hasdata = false;
-
- for (i = 1; i < 3; i++) {
- freq = _channels[i].d.freq >> 6;
- if (_channels[i].d.volume && _channels[i].d.time_left) {
- for (j = 0; j < i; j++) {
- if (_channels[j].d.volume
- && _channels[j].d.time_left
- && freq == (_channels[j].d.freq >> 6)) {
- /* HACK: this channel is playing at
- * the same frequency as another.
- * Synchronize it to the same phase to
- * prevent interference.
- */
- _timer_count[i] = _timer_count[j];
- _timer_output ^= (1 << i) &
- (_timer_output ^ _timer_output << (i - j));
- }
- }
- }
- }
-
- for (i = 0; i < 4; i++) {
- freq = _channels[i].d.freq >> 6;
- vol = (65535 - _channels[i].d.volume) >> 12;
- if (!_channels[i].d.volume || !_channels[i].d.time_left) {
- _timer_count[i] -= len << FIXP_SHIFT;
- if (_timer_count[i] < 0)
- _timer_count[i] = 0;
- } else if (i < 3) {
- hasdata = true;
- squareGenerator(i, freq, vol, 0, data, len);
- } else {
- int noiseFB = (freq & 4) ? FB_WNOISE : FB_PNOISE;
- int n = (freq & 3);
-
- freq = (n == 3) ? 2 * (_channels[2].d.freq>>6) : 1 << (5 + n);
- hasdata = true;
- squareGenerator(i, freq, vol, noiseFB, data, len);
- }
-#if 0
- debug(9, "channel[%d]: freq %d %.1f ; volume %d",
- i, freq, 111860.0 / freq, vol);
-#endif
- }
-
- if (_level || hasdata)
- lowPassFilter(data, len);
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v2.h b/engines/scumm/player/v2.h
deleted file mode 100644
index e23f74cb31..0000000000
--- a/engines/scumm/player/v2.h
+++ /dev/null
@@ -1,72 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V2_H
-#define SCUMM_PLAYER_V2_H
-
-#include "scumm/player/v2base.h"
-
-namespace Scumm {
-
-/**
- * Scumm V2 PC-Speaker MIDI driver.
- * This simulates the pc speaker sound, which is driven by the 8253 (square
- * wave generator) and a low-band filter.
- */
-class Player_V2 : public Player_V2Base {
-public:
- Player_V2(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr);
- virtual ~Player_V2();
-
- // MusicEngine API
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
-// virtual int getMusicTimer();
- virtual int getSoundStatus(int sound) const;
-
- // AudioStream API
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
-protected:
- unsigned int _update_step;
- unsigned int _decay;
- int _level;
- unsigned int _RNG;
- unsigned int _volumetable[16];
-
- int _timer_count[4];
- int _timer_output;
-
-protected:
- virtual void generateSpkSamples(int16 *data, uint len);
- virtual void generatePCjrSamples(int16 *data, uint len);
-
- void lowPassFilter(int16 *data, uint len);
- void squareGenerator(int channel, int freq, int vol,
- int noiseFeedback, int16 *sample, uint len);
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v2a.cpp b/engines/scumm/player/v2a.cpp
deleted file mode 100644
index 2350d7e048..0000000000
--- a/engines/scumm/player/v2a.cpp
+++ /dev/null
@@ -1,1954 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "engines/engine.h"
-#include "scumm/player/v2a.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-#define BASE_FREQUENCY 3579545
-
-static uint32 CRCtable[256];
-
-
-static void InitCRC() {
- const uint32 poly = 0xEDB88320;
- int i, j;
- uint32 n;
-
- for (i = 0; i < 256; i++) {
- n = i;
- for (j = 0; j < 8; j++)
- n = (n & 1) ? ((n >> 1) ^ poly) : (n >> 1);
- CRCtable[i] = n;
- }
-}
-
-static uint32 GetCRC(byte *data, int len) {
- uint32 CRC = 0xFFFFFFFF;
- int i;
- for (i = 0; i < len; i++)
- CRC = (CRC >> 8) ^ CRCtable[(CRC ^ data[i]) & 0xFF];
- return CRC ^ 0xFFFFFFFF;
-}
-
-class V2A_Sound {
-public:
- V2A_Sound() : _id(0), _mod(NULL) { }
- virtual ~V2A_Sound() {}
- virtual void start(Player_MOD *mod, int id, const byte *data) = 0;
- virtual bool update() = 0;
- virtual void stop() = 0;
-protected:
- int _id;
- Player_MOD *_mod;
-};
-
-// unsupported sound effect, print warning message to console
-class V2A_Sound_Unsupported : public V2A_Sound {
-public:
- V2A_Sound_Unsupported() { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- warning("player_v2a - sound %i not supported", id);
- }
- virtual bool update() { return false; }
- virtual void stop() { }
-};
-
-// template, automatically stops all channels when a sound is silenced
-template<int numChan>
-class V2A_Sound_Base : public V2A_Sound {
-public:
- V2A_Sound_Base() : _offset(0), _size(0), _data(0) { }
- V2A_Sound_Base(uint16 offset, uint16 size) : _offset(offset), _size(size), _data(0) { }
- virtual void stop() {
- assert(_id);
- for (int i = 0; i < numChan; i++)
- _mod->stopChannel(_id | (i << 8));
- _id = 0;
- free(_data);
- _data = 0;
- }
-protected:
- const uint16 _offset;
- const uint16 _size;
-
- char *_data;
-};
-
-// plays a music track
-class V2A_Sound_Music : public V2A_Sound {
-public:
- V2A_Sound_Music(uint16 instoff, uint16 voloff, uint16 chan1off, uint16 chan2off, uint16 chan3off, uint16 chan4off, uint16 sampoff, bool looped) :
- _instoff(instoff), _voloff(voloff), _chan1off(chan1off), _chan2off(chan2off), _chan3off(chan3off), _chan4off(chan4off), _sampoff(sampoff), _looped(looped) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
-
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _chan[0].dataptr_i = _chan1off;
- _chan[1].dataptr_i = _chan2off;
- _chan[2].dataptr_i = _chan3off;
- _chan[3].dataptr_i = _chan4off;
- for (int i = 0; i < 4; i++) {
- _chan[i].dataptr = _chan[i].dataptr_i;
- _chan[i].volbase = 0;
- _chan[i].volptr = 0;
- _chan[i].chan = 0;
- _chan[i].dur = 0;
- _chan[i].ticks = 0;
- }
- update();
- }
- virtual bool update() {
- assert(_id);
- int i, j = 0;
- for (i = 0; i < 4; i++) {
- if (_chan[i].dur) {
- if (!--_chan[i].dur) {
- _mod->stopChannel(_id | (_chan[i].chan << 8));
- } else {
- _mod->setChannelVol(_id | (_chan[i].chan << 8),
- READ_BE_UINT16(_data + _chan[i].volbase + (_chan[i].volptr++ << 1)));
- if (_chan[i].volptr == 0) {
- _mod->stopChannel(_id | (_chan[i].chan << 8));
- _chan[i].dur = 0;
- }
- }
- }
- if (!_chan[i].dataptr) {
- j++;
- continue;
- }
- if (READ_BE_UINT16(_data + _chan[i].dataptr) <= _chan[i].ticks) {
- if (READ_BE_UINT16(_data + _chan[i].dataptr + 2) == 0xFFFF) {
- if (_looped) {
- _chan[i].dataptr = _chan[i].dataptr_i;
- _chan[i].ticks = 0;
- if (READ_BE_UINT16(_data + _chan[i].dataptr) > 0) {
- _chan[i].ticks++;
- continue;
- }
- } else {
- _chan[i].dataptr = 0;
- j++;
- continue;
- }
- }
- int freq = BASE_FREQUENCY / READ_BE_UINT16(_data + _chan[i].dataptr + 2);
- int inst = READ_BE_UINT16(_data + _chan[i].dataptr + 8);
- _chan[i].volbase = _voloff + (READ_BE_UINT16(_data + _instoff + (inst << 5)) << 9);
- _chan[i].volptr = 0;
- _chan[i].chan = READ_BE_UINT16(_data + _chan[i].dataptr + 6) & 0x3;
-
- if (_chan[i].dur) // if there's something playing, stop it
- _mod->stopChannel(_id | (_chan[i].chan << 8));
-
- _chan[i].dur = READ_BE_UINT16(_data + _chan[i].dataptr + 4);
-
- int vol = READ_BE_UINT16(_data + _chan[i].volbase + (_chan[i].volptr++ << 1));
-
- int pan;
- if ((_chan[i].chan == 0) || (_chan[i].chan == 3))
- pan = -127;
- else
- pan = 127;
- int offset = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x14);
- int len = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x18);
- int loopoffset = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x16);
- int looplen = READ_BE_UINT16(_data + _instoff + (inst << 5) + 0x10);
-
- int size = len + looplen;
- char *data = (char *)malloc(size);
- memcpy(data, _data + _sampoff + offset, len);
- memcpy(data + len, _data + _sampoff + loopoffset, looplen);
-
- _mod->startChannel(_id | (_chan[i].chan << 8), data, size, freq, vol, len, looplen + len, pan);
- _chan[i].dataptr += 16;
- }
- _chan[i].ticks++;
- }
- if (j == 4)
- return false;
- return true;
- }
- virtual void stop() {
- assert(_id);
- for (int i = 0; i < 4; i++) {
- if (_chan[i].dur)
- _mod->stopChannel(_id | (_chan[i].chan << 8));
- }
- free(_data);
- _id = 0;
- }
-private:
- const uint16 _instoff;
- const uint16 _voloff;
- const uint16 _chan1off;
- const uint16 _chan2off;
- const uint16 _chan3off;
- const uint16 _chan4off;
- const uint16 _sampoff;
- const bool _looped;
-
- char *_data;
- struct tchan {
- uint16 dataptr_i;
- uint16 dataptr;
- uint16 volbase;
- uint8 volptr;
- uint16 chan;
- uint16 dur;
- uint16 ticks;
- } _chan[4];
-};
-
-// plays a single waveform
-class V2A_Sound_Single : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Single(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
- V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- int vol = (_vol << 2) | (_vol >> 4);
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, vol, 0, 0);
- _ticks = 1 + (60 * _size * _freq) / BASE_FREQUENCY;
- }
- virtual bool update() {
- assert(_id);
- _ticks--;
- if (!_ticks) {
- return false;
- }
- return true;
- }
-private:
- const uint16 _freq;
- const uint8 _vol;
-
- int _ticks;
-};
-
-// plays a single looped waveform
-class V2A_Sound_SingleLooped : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_SingleLooped(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint16 loopoffset, uint16 loopsize) :
- V2A_Sound_Base<1>(offset, size), _loopoffset(loopoffset), _loopsize(loopsize), _freq(freq), _vol(vol) { }
- V2A_Sound_SingleLooped(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
- V2A_Sound_Base<1>(offset, size), _loopoffset(0), _loopsize(size), _freq(freq), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- int vol = (_vol << 2) | (_vol >> 4);
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, vol, _loopoffset, _loopoffset + _loopsize);
- }
- virtual bool update() {
- assert(_id);
- return true;
- }
-private:
- const uint16 _loopoffset;
- const uint16 _loopsize;
- const uint16 _freq;
- const uint8 _vol;
-};
-
-// plays two looped waveforms
-class V2A_Sound_MultiLooped : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_MultiLooped(uint16 offset, uint16 size, uint16 freq1, uint8 vol1, uint16 freq2, uint8 vol2) :
- V2A_Sound_Base<2>(offset, size), _freq1(freq1), _vol1(vol1), _freq2(freq2), _vol2(vol2) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- memcpy(tmp_data1, data + _offset, _size);
- memcpy(tmp_data2, data + _offset, _size);
- int vol1 = (_vol1 << 1) | (_vol1 >> 5);
- int vol2 = (_vol2 << 1) | (_vol2 >> 5);
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, vol1, 0, _size, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, vol2, 0, _size, 127);
- }
- virtual bool update() {
- assert(_id);
- return true;
- }
-private:
- const uint16 _freq1;
- const uint8 _vol1;
- const uint16 _freq2;
- const uint8 _vol2;
-};
-
-// plays two looped waveforms for a fixed number of frames
-class V2A_Sound_MultiLoopedDuration : public V2A_Sound_MultiLooped {
-public:
- V2A_Sound_MultiLoopedDuration(uint16 offset, uint16 size, uint16 freq1, uint8 vol1, uint16 freq2, uint8 vol2, uint16 numframes) :
- V2A_Sound_MultiLooped(offset, size, freq1, vol1, freq2, vol2), _duration(numframes) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- V2A_Sound_MultiLooped::start(mod, id, data);
- _ticks = 0;
- }
- virtual bool update() {
- assert(_id);
- _ticks++;
- if (_ticks >= _duration)
- return false;
- return true;
- }
-private:
- const uint16 _duration;
-
- int _ticks;
-};
-
-// plays a single looped waveform which starts at one frequency and bends to another frequency, where it remains until stopped
-class V2A_Sound_SingleLoopedPitchbend : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_SingleLoopedPitchbend(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 vol, uint8 step) :
- V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _vol(vol), _step(step) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- int vol = (_vol << 2) | (_vol >> 4);
- _curfreq = _freq1;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, vol, 0, _size);
- }
- virtual bool update() {
- assert(_id);
- if (_freq1 < _freq2) {
- _curfreq += _step;
- if (_curfreq > _freq2)
- _curfreq = _freq2;
- else
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- } else {
- _curfreq -= _step;
- if (_curfreq < _freq2)
- _curfreq = _freq2;
- else
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- }
- return true;
- }
-private:
- const uint16 _freq1;
- const uint16 _freq2;
- const uint8 _vol;
- const uint16 _step;
-
- uint16 _curfreq;
-};
-
-// plays a single looped waveform starting at a specific frequency/volume, dropping in frequency and fading volume to zero
-// used when Maniac Mansion explodes
-class V2A_Sound_Special_Maniac69 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Maniac69(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
- V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- _curvol = (_vol << 3) | (_vol >> 3);
- _curfreq = _freq;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, _curvol >> 1, 0, _size);
- }
- virtual bool update() {
- assert(_id);
- _curfreq += 2;
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- _curvol--;
- if (_curvol == 0)
- return false;
- _mod->setChannelVol(_id, _curvol >> 1);
- return true;
- }
-private:
- const uint16 _freq;
- const uint8 _vol;
-
- uint16 _curfreq;
- uint16 _curvol;
-};
-
-// plays a single looped waveform, fading the volume from zero to maximum at one rate, then back to zero at another rate
-// used when a microwave oven goes 'Ding'
-class V2A_Sound_Special_ManiacDing : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_ManiacDing(uint16 offset, uint16 size, uint16 freq, uint8 fadeinrate, uint8 fadeoutrate) :
- V2A_Sound_Base<1>(offset, size), _freq(freq), _fade1(fadeinrate), _fade2(fadeoutrate) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- _curvol = 1;
- _dir = 0;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, _curvol, 0, _size);
- }
- virtual bool update() {
- assert(_id);
- if (_dir == 0) {
- _curvol += _fade1;
- if (_curvol > 0x3F) {
- _curvol = 0x3F;
- _dir = 1;
- }
- } else {
- _curvol -= _fade2;
- if (_curvol < 1)
- return false;
- }
- _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
- return true;
- }
-private:
- const uint16 _freq;
- const uint16 _fade1;
- const uint16 _fade2;
-
- int _curvol;
- int _dir;
-};
-
-// plays two looped waveforms, fading the volume from zero to maximum at one rate, then back to zero at another rate
-// used in Zak McKracken for several stereo 'Ding' sounds
-class V2A_Sound_Special_ZakStereoDing : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_Special_ZakStereoDing(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 fadeinrate, uint8 fadeoutrate) :
- V2A_Sound_Base<2>(offset, size), _freq1(freq1), _freq2(freq2), _fade1(fadeinrate), _fade2(fadeoutrate) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- memcpy(tmp_data1, data + _offset, _size);
- memcpy(tmp_data2, data + _offset, _size);
- _curvol = 1;
- _dir = 0;
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, 1, 0, _size, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, 1, 0, _size, 127);
- }
- virtual bool update() {
- assert(_id);
- if (_dir == 0) {
- _curvol += _fade1;
- if (_curvol > 0x3F) {
- _curvol = 0x3F;
- _dir = 1;
- }
- } else {
- _curvol -= _fade2;
- if (_curvol < 1)
- return false;
- }
- _mod->setChannelVol(_id | 0x000, (_curvol << 1) | (_curvol >> 5));
- _mod->setChannelVol(_id | 0x100, (_curvol << 1) | (_curvol >> 5));
- return true;
- }
-private:
- const uint16 _freq1;
- const uint16 _freq2;
- const uint16 _fade1;
- const uint16 _fade2;
-
- int _curvol;
- int _dir;
-};
-
-// plays a single looped waveform, starting at one frequency and at full volume, bending down to another frequency, and then fading volume to zero
-// used in Maniac Mansion for the tentacle sounds
-class V2A_Sound_Special_ManiacTentacle : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_ManiacTentacle(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 step) :
- V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _step(step) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- _curfreq = _freq1;
- _curvol = 0x3F;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_curvol << 2) | (_curvol >> 4), 0, _size);
- }
- virtual bool update() {
- assert(_id);
- if (_curfreq > _freq2)
- _curvol = 0x3F + _freq2 - _curfreq;
- if (_curvol < 1)
- return false;
- _curfreq += _step;
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
- return true;
- }
-private:
- const uint16 _freq1;
- const uint16 _freq2;
- const uint16 _step;
-
- uint16 _curfreq;
- int _curvol;
-};
-
-// plays a single looped waveform, starting at one frequency, bending down to another frequency, and then back up to the original frequency
-// used for electronic noises
-class V2A_Sound_Special_Maniac59 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Maniac59(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 step, uint8 vol) :
- V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _step(step), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- int vol = (_vol << 2) | (_vol >> 4);
- _curfreq = _freq1;
- _dir = 2;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, vol, 0, _size);
- }
- virtual bool update() {
- assert(_id);
- if (_dir == 2) {
- _curfreq += _step;
- if (_curfreq > _freq2) {
- _curfreq = _freq2;
- _dir = 1;
- }
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- } else if (_dir == 1) {
- _curfreq -= _step;
- if (_curfreq < _freq1) {
- _curfreq = _freq1;
- _dir = 0;
- }
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- }
- return true;
- }
-private:
- const uint16 _freq1;
- const uint16 _freq2;
- const uint16 _step;
- const uint8 _vol;
-
- uint16 _curfreq;
- int _dir;
-};
-
-// plays a single looped waveform, simultaneously bending the frequency downward and slowly fading volume to zero
-// don't remember where this one is used
-class V2A_Sound_Special_Maniac61 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Maniac61(uint16 offset, uint16 size, uint16 freq1, uint16 freq2) :
- V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- _curfreq = _freq1;
- _curvol = 0x3F;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_curvol << 2) | (_curvol >> 4), 0, _size);
- }
- virtual bool update() {
- assert(_id);
- _curfreq++;
- if (!(_curfreq & 3))
- _curvol--;
- if ((_curfreq == _freq2) || (_curvol == 0))
- return false;
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
- return true;
- }
-private:
- const uint16 _freq1;
- const uint16 _freq2;
-
- uint16 _curfreq;
- uint8 _curvol;
-};
-
-// intermittently plays two looped waveforms for a specific duration
-// used for ringing telephones
-class V2A_Sound_Special_ManiacPhone : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_Special_ManiacPhone(uint16 offset, uint16 size, uint16 freq1, uint8 vol1, uint16 freq2, uint8 vol2, uint16 numframes, uint8 playwidth, uint8 loopwidth) :
- V2A_Sound_Base<2>(offset, size), _freq1(freq1), _vol1(vol1), _freq2(freq2), _vol2(vol2), _duration(numframes), _playwidth(playwidth), _loopwidth(loopwidth) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
- soundon();
- _ticks = 0;
- _loop = 0;
- }
- virtual bool update() {
- assert(_id);
- if (_loop == _playwidth) {
- _mod->stopChannel(_id | 0x000);
- _mod->stopChannel(_id | 0x100);
- }
- if (_loop == _loopwidth) {
- _loop = 0;
- soundon();
- }
- _loop++;
- _ticks++;
- if (_ticks >= _duration)
- return false;
- return true;
- }
-private:
- const uint16 _freq1;
- const uint8 _vol1;
- const uint16 _freq2;
- const uint8 _vol2;
- const uint16 _duration;
- const uint8 _playwidth;
- const uint8 _loopwidth;
-
- int _ticks;
- int _loop;
-
- void soundon() {
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- memcpy(tmp_data1, _data + _offset, _size);
- memcpy(tmp_data2, _data + _offset, _size);
- int vol1 = (_vol1 << 1) | (_vol1 >> 5);
- int vol2 = (_vol2 << 1) | (_vol2 >> 5);
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, vol1, 0, _size, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, vol2, 0, _size, 127);
- }
-};
-
-// intermittently plays a single waveform for a specified duration
-// used when applying a wrench to a pipe
-class V2A_Sound_Special_Maniac46 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Maniac46(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint8 loopwidth, uint8 numloops) :
- V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol), _loopwidth(loopwidth), _numloops(numloops) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
- soundon();
- _loop = 0;
- _loopctr = 0;
- }
- virtual bool update() {
- assert(_id);
- _loop++;
- if (_loop == _loopwidth) {
- _loop = 0;
- _loopctr++;
- if (_loopctr == _numloops)
- return false;
- _mod->stopChannel(_id);
- soundon();
- }
- return true;
- }
-private:
- const uint16 _freq;
- const uint8 _vol;
- const uint8 _loopwidth;
- const uint8 _numloops;
-
- int _loop;
- int _loopctr;
-
- void soundon() {
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, _data + _offset, _size);
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, (_vol << 2) | (_vol >> 4), 0, 0);
- }
-};
-
-// plays a single waveform at irregular intervals for a specified number of frames, possibly looped
-// used for typewriter noises, as well as tapping on the bus in Zak McKracken
-class V2A_Sound_Special_ManiacTypewriter : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_ManiacTypewriter(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint8 numdurs, const uint8 *durations, bool looped) :
- V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol), _numdurs(numdurs), _durations(durations), _looped(looped) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
- soundon();
- _curdur = 0;
- _ticks = _durations[_curdur++];
- }
- virtual bool update() {
- assert(_id);
- _ticks--;
- if (!_ticks) {
- if (_curdur == _numdurs) {
- if (_looped)
- _curdur = 0;
- else
- return false;
- }
- _mod->stopChannel(_id);
- soundon();
- _ticks = _durations[_curdur++];
- }
- return true;
- }
-private:
- const uint16 _freq;
- const uint8 _vol;
- const uint8 _numdurs;
- const uint8 *_durations;
- const bool _looped;
-
- int _ticks;
- int _curdur;
-
- void soundon() {
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, _data + _offset, _size);
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, (_vol << 2) | (_vol >> 4), 0, 0);
- }
-};
-
-// plays two looped waveforms pitch bending up at various predefined rates
-// used for some sort of siren-like noise in Maniac Mansion
-class V2A_Sound_Special_Maniac44 : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_Special_Maniac44(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq1, uint16 freq2, uint8 vol) :
- _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _freq1(freq1), _freq2(freq2), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _loopnum = 1;
- _step = 2;
- _curfreq = _freq1;
-
- soundon(_data + _offset1, _size1);
- }
- virtual bool update() {
- assert(_id);
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _curfreq);
- _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_curfreq + 3));
- _curfreq -= _step;
- if (_loopnum == 7) {
- if ((BASE_FREQUENCY / _curfreq) >= 65536)
- return false;
- else
- return true;
- }
- if (_curfreq >= _freq2)
- return true;
- const char steps[8] = {0, 2, 2, 3, 4, 8, 15, 2};
- _curfreq = _freq1;
- _step = steps[++_loopnum];
- if (_loopnum == 7) {
- _mod->stopChannel(_id | 0x000);
- _mod->stopChannel(_id | 0x100);
- soundon(_data + _offset2, _size2);
- }
- return true;
- }
-private:
- const uint16 _offset1;
- const uint16 _size1;
- const uint16 _offset2;
- const uint16 _size2;
- const uint16 _freq1;
- const uint16 _freq2;
- const uint8 _vol;
-
- int _curfreq;
- uint16 _loopnum;
- uint16 _step;
-
- void soundon(const char *data, int size) {
- char *tmp_data1 = (char *)malloc(size);
- char *tmp_data2 = (char *)malloc(size);
- memcpy(tmp_data1, data, size);
- memcpy(tmp_data2, data, size);
- int vol = (_vol << 1) | (_vol >> 5);
- _mod->startChannel(_id | 0x000, tmp_data1, size, BASE_FREQUENCY / _curfreq, vol, 0, size, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, size, BASE_FREQUENCY / (_curfreq + 3), vol, 0, size, 127);
- }
-};
-
-// plays 4 looped waveforms, each at modulating frequencies
-// used for the siren noise in Maniac Mansion
-class V2A_Sound_Special_Maniac32 : public V2A_Sound_Base<4> {
-public:
- V2A_Sound_Special_Maniac32(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint8 vol) :
- _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
-
- _freq1 = 0x02D0;
- _step1 = -0x000A;
- _freq2 = 0x0122;
- _step2 = 0x000A;
- _freq3 = 0x02BC;
- _step3 = -0x0005;
- _freq4 = 0x010E;
- _step4 = 0x0007;
-
- char *tmp_data1 = (char *)malloc(_size1);
- char *tmp_data2 = (char *)malloc(_size2);
- char *tmp_data3 = (char *)malloc(_size1);
- char *tmp_data4 = (char *)malloc(_size2);
- memcpy(tmp_data1, data + _offset1, _size1);
- memcpy(tmp_data2, data + _offset2, _size2);
- memcpy(tmp_data3, data + _offset1, _size1);
- memcpy(tmp_data4, data + _offset2, _size2);
- _mod->startChannel(_id | 0x000, tmp_data1, _size1, BASE_FREQUENCY / _freq1, _vol, 0, _size1, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size2, BASE_FREQUENCY / _freq2, _vol, 0, _size2, 127);
- _mod->startChannel(_id | 0x200, tmp_data3, _size1, BASE_FREQUENCY / _freq3, _vol, 0, _size1, 127);
- _mod->startChannel(_id | 0x300, tmp_data4, _size2, BASE_FREQUENCY / _freq4, _vol, 0, _size2, -127);
- }
- virtual bool update() {
- assert(_id);
- updatefreq(_freq1, _step1, 0x00AA, 0x00FA);
- updatefreq(_freq2, _step2, 0x019A, 0x03B6);
- updatefreq(_freq3, _step3, 0x00AA, 0x00FA);
- updatefreq(_freq4, _step4, 0x019A, 0x03B6);
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq1);
- _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / _freq2);
- _mod->setChannelFreq(_id | 0x200, BASE_FREQUENCY / _freq3);
- _mod->setChannelFreq(_id | 0x300, BASE_FREQUENCY / _freq4);
- return true;
- }
-private:
- const uint16 _offset1;
- const uint16 _size1;
- const uint16 _offset2;
- const uint16 _size2;
- const uint8 _vol;
-
- uint16 _freq1;
- int16 _step1;
- uint16 _freq2;
- int16 _step2;
- uint16 _freq3;
- int16 _step3;
- uint16 _freq4;
- int16 _step4;
-
- void updatefreq(uint16 &freq, int16 &step, uint16 min, uint16 max) {
- freq += step;
- if (freq <= min) {
- freq = min;
- step = -step;
- }
- if (freq >= max) {
- freq = max;
- step = -step;
- }
- }
-};
-
-// plays 4 looped waveforms
-// used in the white crystal chamber
-class V2A_Sound_Special_Zak70 : public V2A_Sound_Base<4> {
-public:
- V2A_Sound_Special_Zak70(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 freq3, uint16 freq4, uint8 vol) :
- V2A_Sound_Base<4>(offset, size), _freq1(freq1), _freq2(freq2), _freq3(freq3), _freq4(freq4), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
-
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- char *tmp_data3 = (char *)malloc(_size);
- char *tmp_data4 = (char *)malloc(_size);
- memcpy(tmp_data1, data + _offset, _size);
- memcpy(tmp_data2, data + _offset, _size);
- memcpy(tmp_data3, data + _offset, _size);
- memcpy(tmp_data4, data + _offset, _size);
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, _vol, 0, _size, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, _vol, 0, _size, 127);
- _mod->startChannel(_id | 0x200, tmp_data3, _size, BASE_FREQUENCY / _freq3, _vol, 0, _size, 127);
- _mod->startChannel(_id | 0x300, tmp_data4, _size, BASE_FREQUENCY / _freq4, _vol, 0, _size, -127);
- }
- virtual bool update() {
- assert(_id);
- return true;
- }
-protected:
- const uint16 _freq1;
- const uint16 _freq2;
- const uint16 _freq3;
- const uint16 _freq4;
- const uint8 _vol;
-};
-
-// plays 4 looped waveforms and fades volume to zero after a specific delay
-// used when the Mindbender disappears
-class V2A_Sound_Special_Zak101 : public V2A_Sound_Special_Zak70 {
-public:
- V2A_Sound_Special_Zak101(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 freq3, uint16 freq4, uint8 vol, uint16 dur) :
- V2A_Sound_Special_Zak70(offset, size, freq1, freq2, freq3, freq4, vol), _dur(dur) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- V2A_Sound_Special_Zak70::start(mod, id, data);
- _ticks = _dur;
- }
- virtual bool update() {
- assert(_id);
- if (!--_ticks)
- return false;
- if (_ticks < _vol) {
- _mod->setChannelVol(_id | 0x000, _ticks);
- _mod->setChannelVol(_id | 0x100, _ticks);
- _mod->setChannelVol(_id | 0x200, _ticks);
- _mod->setChannelVol(_id | 0x300, _ticks);
- }
- return true;
- }
-private:
- const uint16 _dur;
-
- int _ticks;
-};
-
-// plays a single looped waveform and slowly fades volume to zero
-// used when refilling oxygen
-class V2A_Sound_Special_Zak37 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Zak37(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
- V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- _curvol = _vol << 2;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _freq, _curvol, 0, _size);
- }
- virtual bool update() {
- assert(_id);
- if (!--_curvol)
- return false;
- _mod->setChannelVol(_id, _curvol);
- return true;
- }
-private:
- const uint16 _freq;
- const uint8 _vol;
-
- int _curvol;
-};
-
-// plays a single looped waveform, slowly bending from one frequency to another and then slowly fading volume from max to zero
-// used in Zak for airplane taking off and landing
-class V2A_Sound_Special_ZakAirplane : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_ZakAirplane(uint16 offset, uint16 size, uint16 freq1, uint16 freq2) :
- V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- _curfreq = _freq1;
- _curvol = 0x3F;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_curvol << 2) | (_curvol >> 4), 0, _size);
- _ticks = 0;
- }
- virtual bool update() {
- assert(_id);
- _ticks++;
- if (_ticks < 4)
- return true;
- _ticks = 0;
- if (_curfreq == _freq2) {
- _curvol--;
- if (_curvol == 0)
- return false;
- _mod->setChannelVol(_id, (_curvol << 2) | (_curvol >> 4));
- } else {
- if (_freq1 < _freq2)
- _curfreq++;
- else
- _curfreq--;
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- }
- return true;
- }
-private:
- const uint16 _freq1;
- const uint16 _freq2;
-
- uint16 _curfreq;
- int _curvol;
- int _ticks;
-};
-
-// plays 4 looped waveforms, starting at specific frequencies and bending at different rates while fading volume to zero
-// used when the white crystal machine turns off
-class V2A_Sound_Special_Zak71 : public V2A_Sound_Base<4> {
-public:
- V2A_Sound_Special_Zak71(uint16 offset, uint16 size) :
- _offset(offset), _size(size) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
-
- _freq1 = 0x00C8;
- _freq2 = 0x0190;
- _freq3 = 0x0320;
- _freq4 = 0x0640;
- _vol = 0x78;
-
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- char *tmp_data3 = (char *)malloc(_size);
- char *tmp_data4 = (char *)malloc(_size);
- memcpy(tmp_data1, data + _offset, _size);
- memcpy(tmp_data2, data + _offset, _size);
- memcpy(tmp_data3, data + _offset, _size);
- memcpy(tmp_data4, data + _offset, _size);
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq1, MIN((_vol >> 1) + 3, 0x32), 0, _size, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq2, MIN((_vol >> 1) + 3, 0x32), 0, _size, 127);
- _mod->startChannel(_id | 0x200, tmp_data3, _size, BASE_FREQUENCY / _freq3, MIN((_vol >> 1) + 3, 0x32), 0, _size, 127);
- _mod->startChannel(_id | 0x300, tmp_data4, _size, BASE_FREQUENCY / _freq4, MIN((_vol >> 1) + 3, 0x32), 0, _size, -127);
- }
- virtual bool update() {
- assert(_id);
- _freq1 += 0x14;
- _freq2 += 0x1E;
- _freq3 += 0x32;
- _freq4 += 0x50;
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq1);
- _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / _freq2);
- _mod->setChannelFreq(_id | 0x200, BASE_FREQUENCY / _freq3);
- _mod->setChannelFreq(_id | 0x300, BASE_FREQUENCY / _freq4);
- _vol--;
- if (_vol == 0)
- return false;
- _mod->setChannelVol(_id | 0x000, MIN((_vol >> 1) + 3, 0x32));
- _mod->setChannelVol(_id | 0x100, MIN((_vol >> 1) + 3, 0x32));
- _mod->setChannelVol(_id | 0x200, MIN((_vol >> 1) + 3, 0x32));
- _mod->setChannelVol(_id | 0x300, MIN((_vol >> 1) + 3, 0x32));
- return true;
- }
-private:
- const uint16 _offset;
- const uint16 _size;
-
- uint16 _freq1;
- uint16 _freq2;
- uint16 _freq3;
- uint16 _freq4;
- uint8 _vol;
-};
-
-// plays a single looped waveform, bending the frequency upward at a varying rate
-// used when the Skolarian device activates
-class V2A_Sound_Special_Zak99 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Zak99(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 vol) :
- V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _vol(vol) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, data + _offset, _size);
- _curfreq = _freq1;
- _mod->startChannel(_id, tmp_data, _size, BASE_FREQUENCY / _curfreq, (_vol << 2) | (_vol >> 4), 0, _size);
- _bendrate = 8;
- _bendctr = 100;
- _holdctr = 30;
- }
- virtual bool update() {
- assert(_id);
- if (_curfreq >= _freq2) {
- _mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
- _curfreq -= _bendrate;
- if (--_bendctr)
- return true;
- _bendrate--;
- if (_bendrate < 2)
- _bendrate = 2;
- } else {
- if (!--_holdctr)
- return false;
- }
- return true;
- }
-private:
- const uint16 _freq1;
- const uint16 _freq2;
- const uint16 _vol;
-
- uint16 _curfreq;
- uint16 _bendrate;
- uint16 _bendctr;
- uint16 _holdctr;
-};
-
-// plays one waveform, then switches to a different looped waveform and slowly fades volume to zero
-// used when depressurizing the hostel
-class V2A_Sound_Special_Zak54 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Zak54(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq) :
- _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _freq(freq) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
- char *tmp_data = (char *)malloc(_size1);
- memcpy(tmp_data, data + _offset1, _size1);
- _vol = 0xFC;
- _mod->startChannel(_id, tmp_data, _size1, BASE_FREQUENCY / _freq, _vol, 0, _size1);
- _loop = _size1 * _freq * 60 / BASE_FREQUENCY;
- }
- virtual bool update() {
- assert(_id);
- if (!_loop) {
- _vol--;
- if (_vol)
- _mod->setChannelVol(_id, _vol);
- else
- return false;
- } else if (!--_loop) {
- _mod->stopChannel(_id);
- char *tmp_data = (char *)malloc(_size2);
- memcpy(tmp_data, _data + _offset2, _size2);
- _mod->startChannel(_id, tmp_data, _size2, BASE_FREQUENCY / _freq, _vol, 0, _size2);
- }
- return true;
- }
-
-private:
- const uint16 _offset1;
- const uint16 _offset2;
- const uint16 _size1;
- const uint16 _size2;
- const uint16 _freq;
-
- int _vol;
- int _loop;
-};
-
-// plays 2 looped waveforms at different frequencies, pulsing at different frequencies and ramping the volume up and down once
-// used when abducted at the Bermuda Triangle
-class V2A_Sound_Special_Zak110 : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_Special_Zak110(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq1, uint16 freq2) :
- _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _freq1(freq1), _freq2(freq2) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _loopnum = 0;
- _vol = 0x1500;
- _beepcount = 0;
- }
- virtual bool update() {
- char *tmp_data;
- assert(_id);
-
- int vol = (((_vol >> 7) & 0x7E) | ((_vol >> 15) & 0x01));
- _beepcount++;
-
- switch (_beepcount & 0x3) {
- case 0:
- _mod->stopChannel(_id | 0x000);
- break;
- case 1:
- tmp_data = (char *)malloc(_size1);
- memcpy(tmp_data, _data + _offset1, _size1);
- _mod->startChannel(_id | 0x000, tmp_data, _size1, BASE_FREQUENCY / _freq1, vol, 0, _size1, -127);
- break;
- default:
- _mod->setChannelVol(_id | 0x000, vol);
- break;
- }
-
- switch (_beepcount & 0x7) {
- case 0:
- _mod->stopChannel(_id | 0x100);
- break;
- case 1:
- tmp_data = (char *)malloc(_size2);
- memcpy(tmp_data, _data + _offset2, _size2);
- _mod->startChannel(_id | 0x100, tmp_data, _size2, BASE_FREQUENCY / _freq2, vol, 0, _size2, 127);
- break;
- default:
- _mod->setChannelVol(_id | 0x100, vol);
- break;
- }
-
- if (_loopnum == 0) {
- _vol += 0x80;
- if (_vol == 0x4000) {
- _vol = 0x3F00;
- _loopnum = 1;
- }
- } else if (_loopnum == 1) {
- _vol -= 0x20;
- if (_vol == 0x2000)
- _loopnum = 2;
- }
- return true;
- }
-private:
- const uint16 _offset1;
- const uint16 _size1;
- const uint16 _offset2;
- const uint16 _size2;
- const uint16 _freq1;
- const uint16 _freq2;
-
- uint16 _loopnum;
- uint16 _vol;
- uint16 _beepcount;
-};
-
-// plays a stereo siren, sweeping up and down quickly several times before sweeping up slowly, stopping, and then going silent
-// door orb sound in the Mars Face
-class V2A_Sound_Special_Zak32 : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_Special_Zak32(uint16 offset1, uint16 offset2, uint16 size1, uint16 size2) :
- _offset1(offset1), _offset2(offset2), _size1(size1), _size2(size2) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _loopnum = 1;
- _freqmod = -4;
- _freq = 0x00C8;
-
- char *tmp_data1 = (char *)malloc(_size1);
- char *tmp_data2 = (char *)malloc(_size1);
- memcpy(tmp_data1, _data + _offset1, _size1);
- memcpy(tmp_data2, _data + _offset1, _size1);
- _mod->startChannel(_id | 0x000, tmp_data1, _size1, BASE_FREQUENCY / _freq, 0x7F, 0, _size1, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size1, BASE_FREQUENCY / (_freq + 3), 0x7F, 0, _size1, 127);
- }
- virtual bool update() {
- assert(_id);
-
- if (_loopnum < 7) {
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq);
- _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_freq + 3));
- _freq += _freqmod;
- if (_freq <= 0x80)
- _freqmod = -_freqmod;
- else if (_freq >= 0xC8) {
- _freqmod = -_freqmod;
- _loopnum++;
- if (_loopnum == 7) {
- _freq = 0x00C8;
- _freqmod = 2;
- }
- }
- return true;
- } else {
- if (_loopnum == 7) {
- _mod->stopChannel(_id | 0x000);
- _mod->stopChannel(_id | 0x100);
-
- char *tmp_data1 = (char *)malloc(_size2);
- char *tmp_data2 = (char *)malloc(_size2);
- memcpy(tmp_data1, _data + _offset2, _size2);
- memcpy(tmp_data2, _data + _offset2, _size2);
- _mod->startChannel(_id | 0x000, tmp_data1, _size2, BASE_FREQUENCY / (_freq), 0x7F, 0, _size2, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size2, BASE_FREQUENCY / (_freq + 3), 0x7F, 0, _size2, 127);
- _loopnum++;
- } else {
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq);
- _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_freq + 3));
- }
- _freq -= _freqmod;
- if (_freq > 0)
- return true;
- else
- return false;
- }
- }
-private:
- const uint16 _offset1;
- const uint16 _offset2;
- const uint16 _size1;
- const uint16 _size2;
-
- uint16 _loopnum;
- int16 _freqmod;
- uint16 _freq;
-};
-
-// plays a looped waveform, increasing frequency and reducing volume once the frequency reaches a certain point
-// probably used for some sort of vehicle sound
-class V2A_Sound_Special_Zak52 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Zak52(uint16 offset, uint16 size) :
- _offset(offset), _size(size) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _curfreq = 0x0312;
-
- char *tmp_data = (char *)malloc(_size);
- memcpy(tmp_data, _data + _offset, _size);
- _mod->startChannel(_id | 0x000, tmp_data, _size, BASE_FREQUENCY / _curfreq, 0xFF, 0, _size, -127);
- }
- virtual bool update() {
- assert(_id);
- int vol = (_curfreq - 0xC8) >> 3;
- if (vol > 0x3F)
- vol = 0x3F;
- vol = (vol << 2) | (vol >> 4);
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _curfreq);
- _mod->setChannelVol(_id | 0x000, vol);
- _curfreq--;
- if (_curfreq >= 0x107)
- return true;
- else
- return false;
- }
-private:
- const uint16 _offset;
- const uint16 _size;
-
- uint16 _curfreq;
-};
-
-// plays a looped waveform, sweeping the frequency up while modulating it (alternating which channel updates) and fading volume out
-// used when teleporting out with the yellow crystal
-class V2A_Sound_Special_Zak61 : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_Special_Zak61(uint16 offset, uint16 size) :
- _offset(offset), _size(size) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _loop = 1;
- _curfreq = 0x01F4;
-
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- memcpy(tmp_data1, _data + _offset, _size);
- memcpy(tmp_data2, _data + _offset, _size);
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _curfreq, 0x7F, 0, _size, -127);
- // start 2nd channel silent
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _curfreq, 0, 0, _size, 127);
- }
- virtual bool update() {
- assert(_id);
- int freq = (_loop << 4) + _curfreq;
- int vol = freq - 0x76;
- if (vol > 0x3F)
- vol = 0x3F;
- vol = (vol << 1) | (vol >> 5);
- switch (_loop) {
- case 0:
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / freq);
- _mod->setChannelVol(_id | 0x000, vol);
- break;
- case 1:
- _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / freq);
- _mod->setChannelVol(_id | 0x100, vol);
- break;
- }
- _loop = (_loop + 1) & 3;
- if (!_loop) {
- _curfreq -= 4;
- if (_curfreq <= 0x80)
- return false;
- }
- return true;
- }
-private:
- const uint16 _offset;
- const uint16 _size;
-
- uint16 _loop;
- uint16 _curfreq;
-};
-
-// just like Zak61, but sweeps frequency in the other direction
-// used when teleporting in with the yellow crystal
-class V2A_Sound_Special_Zak62 : public V2A_Sound_Base<2> {
-public:
- V2A_Sound_Special_Zak62(uint16 offset, uint16 size) :
- _offset(offset), _size(size) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _loop = 1;
- _curfreq = 0x0080;
-
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- memcpy(tmp_data1, _data + _offset, _size);
- memcpy(tmp_data2, _data + _offset, _size);
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _curfreq, 0x7F, 0, _size, -127);
- // start 2nd channel silent
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _curfreq, 0, 0, _size, 127);
- }
- virtual bool update() {
- assert(_id);
- int freq = (_loop << 4) + _curfreq;
- int vol = 0x0200 - freq;
- if (vol > 0x3F)
- vol = 0x3F;
- vol = (vol << 1) | (vol >> 5);
- switch (_loop) {
- case 0:
- _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / freq);
- _mod->setChannelVol(_id | 0x000, vol);
- break;
- case 1:
- _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / freq);
- _mod->setChannelVol(_id | 0x100, vol);
- break;
- }
- _loop = (_loop + 1) & 3;
- if (!_loop) {
- _curfreq += 4;
- if (_curfreq >= 0x01F4)
- return false;
- }
- return true;
- }
-private:
- const uint16 _offset;
- const uint16 _size;
-
- uint16 _loop;
- uint16 _curfreq;
-};
-
-// plays a series of double-looped sounds at varying frequencies and delays, very specialized
-// Guardian of the Sphinx, perhaps?
-class V2A_Sound_Special_Zak82 : public V2A_Sound_Base<4> {
-public:
- V2A_Sound_Special_Zak82(uint16 offset, uint16 size) :
- _offset(offset), _size(size) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- // Wait values were to insure playing an integral number of loops on each sample
- // and have been adjusted to reflect the actual duration spent playing
- _loop = 0;
- _playctr = 240;
- _wait1 = 76; // was 39, extended to loop twice
- _wait2 = 10000;
- _wait3 = 10000;
- _wait4 = 10000;
-
- int size = 2000;
- int offset = _offset;
- assert(offset + size <= _offset + _size);
- char *tmp_data = (char *)malloc(size);
- memcpy(tmp_data, _data + offset, size);
- _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0479, 0xFF, 0, size);
- }
- virtual bool update() {
- assert(_id);
- char *tmp_data1, *tmp_data2;
- int size, offset = _offset;
-
- if (!--_wait1) {
- _wait1 = 10000;
- _mod->stopChannel(_id | 0x000);
- } else if (!--_wait2) {
- _wait2 = 10000;
- _mod->stopChannel(_id | 0x000);
- } else if (!--_wait3) {
- _wait3 = 10000;
- _mod->stopChannel(_id | 0x200);
- } else if (!--_wait4) {
- _wait4 = 10000;
- _mod->stopChannel(_id | 0x100);
- _mod->stopChannel(_id | 0x300);
- }
- if (--_playctr)
- return true;
-
- switch (++_loop) {
- case 1:
- size = 6300;
- offset += 0x07D0;
- assert(offset + size <= _offset + _size);
- tmp_data1 = (char *)malloc(size);
- memcpy(tmp_data1, _data + offset, size);
- _mod->startChannel(_id | 0x000, tmp_data1, size, BASE_FREQUENCY / 0x0479, 0x7F, 0, size, -127);
- _wait2 = 241; // was 120, extended to loop twice
- _playctr = 10;
- break;
- case 2:
- size = 6292;
- offset += 0x206C;
- assert(offset + size <= _offset + _size);
- tmp_data1 = (char *)malloc(size);
- memcpy(tmp_data1, _data + offset, size);
- _mod->startChannel(_id | 0x200, tmp_data1, size, BASE_FREQUENCY / 0x0384, 0x7F, 0, size, 127);
- _wait3 = 189; // was 94, extended to loop twice
- _playctr = 20;
- break;
- case 3:
- size = 6300;
- offset += 0x07D0;
- assert(offset + size <= _offset + _size);
- tmp_data1 = (char *)malloc(size);
- tmp_data2 = (char *)malloc(size);
- memcpy(tmp_data1, _data + offset, size);
- memcpy(tmp_data2, _data + offset, size);
- _mod->startChannel(_id | 0x100, tmp_data1, size, BASE_FREQUENCY / 0x01E0, 0x7F, 0, size, 127);
- _mod->startChannel(_id | 0x300, tmp_data2, size, BASE_FREQUENCY / 0x01E0, 0x7F, 0, size, -127);
- _wait4 = 101; // was 50, extended to loop twice
- _playctr = 120;
- break;
- default:
- return false;
- }
- return true;
- }
-private:
- const uint16 _offset;
- const uint16 _size;
-
- uint16 _loop;
- uint16 _playctr;
- uint16 _wait1;
- uint16 _wait2;
- uint16 _wait3;
- uint16 _wait4;
-};
-
-// plays a "ding" (volume 0-max-0) followed by a sound sample, a pause, then loops again
-// Mars Tram about to depart
-class V2A_Sound_Special_Zak86 : public V2A_Sound_Base<1> {
-public:
- V2A_Sound_Special_Zak86(uint16 offset, uint16 size) :
- _offset(offset), _size(size) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _mode = 0;
- _vol = 0;
- _volmod = 16;
-
- int size = 32;
- int offset = _offset + 0x2B8E;
- assert(offset + size <= _offset + _size);
- char *tmp_data = (char *)malloc(size);
- memcpy(tmp_data, _data + offset, size);
- _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0096, 0, 0, size, 0);
- }
- virtual bool update() {
- assert(_id);
- int size, offset;
- char *tmp_data;
-
- switch (_mode) {
- case 0:
- _mod->setChannelVol(_id | 0x000, (_vol << 2) | (_vol >> 4));
- if (_vol + _volmod > 0) {
- _vol += _volmod;
- if (_vol > 0x3F) {
- _vol = 0x3F;
- _volmod = -4;
- }
- return true;
- }
- _mod->stopChannel(_id | 0x000);
- _mode = 1;
-
- size = 0x2B8E;
- offset = _offset;
- assert(offset + size <= _offset + _size);
- tmp_data = (char *)malloc(size);
- memcpy(tmp_data, _data + offset, size);
- _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0152, 0x3F);
- _volmod = 100;
- break;
- case 1:
- if (!--_volmod) {
- size = 32;
- offset = _offset + 0x2B8E;
- assert(offset + size <= _offset + _size);
- tmp_data = (char *)malloc(size);
- memcpy(tmp_data, _data + offset, size);
- _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0096, 0, 0, size, 0);
- _mode = 0;
- _vol = 0;
- _volmod = 16;
- }
- break;
- }
- return true;
- }
-private:
- const uint16 _offset;
- const uint16 _size;
-
- uint16 _mode;
- uint16 _vol;
- int16 _volmod;
-};
-
-// modulates volume on 4 samples, frequency on only 2 of them
-// Skolarian device pedestal activated without any parts
-class V2A_Sound_Special_Zak98 : public V2A_Sound_Base<4> {
-public:
- V2A_Sound_Special_Zak98(uint16 offset, uint16 size) :
- _offset(offset), _size(size) { }
- virtual void start(Player_MOD *mod, int id, const byte *data) {
- _mod = mod;
- _id = id;
- _data = (char *)malloc(READ_LE_UINT16(data));
- memcpy(_data, data, READ_LE_UINT16(data));
-
- _freq[0] = 0x1E0;
- _freq[1] = 0x3E8;
- _freq[2] = 0x200;
- _freq[3] = 0x408;
- _vol[0] = 0x3F;
- _vol[1] = 0x3F;
- _vol[2] = 0x3F;
- _vol[3] = 0x3F;
- _freqmod = 4;
- _volmod[0] = -2;
- _volmod[1] = -1;
-
- char *tmp_data1 = (char *)malloc(_size);
- char *tmp_data2 = (char *)malloc(_size);
- char *tmp_data3 = (char *)malloc(_size);
- char *tmp_data4 = (char *)malloc(_size);
- memcpy(tmp_data1, _data + _offset, _size);
- memcpy(tmp_data2, _data + _offset, _size);
- memcpy(tmp_data3, _data + _offset, _size);
- memcpy(tmp_data4, _data + _offset, _size);
- _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq[0], _vol[0], 0, _size, -127);
- _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq[1], _vol[1], 0, _size, 127);
- _mod->startChannel(_id | 0x200, tmp_data3, _size, BASE_FREQUENCY / _freq[2], _vol[2], 0, _size, 127);
- _mod->startChannel(_id | 0x300, tmp_data4, _size, BASE_FREQUENCY / _freq[3], _vol[3], 0, _size, -127);
- }
- virtual bool update() {
- assert(_id);
- const uint16 _minvol[2] = {0x2E, 0x32};
- int i;
- for (i = 0; i < 4; i++) {
- _mod->setChannelFreq(_id | (i << 8), BASE_FREQUENCY / _freq[i]);
- _mod->setChannelVol(_id | (i << 8), _vol[i]);
- }
- for (i = 0; i < 2; i++) {
- _vol[i] += _volmod[i];
- if (_vol[i] > 0x3F) {
- _vol[i] = 0x3F;
- _volmod[i] = -_volmod[i];
- } else if (_vol[i] < _minvol[i]) {
- _vol[i] = _minvol[i];
- _volmod[i] = -_volmod[i];
- }
- _vol[i + 2] = _vol[i];
- }
- _freq[0] += _freqmod;
- if (_freq[0] > 0x2BC) {
- _freq[0] = 0x2BC;
- _freqmod = -_freqmod;
- } else if (_freq[0] < 0x1E0) {
- _freq[0] = 0x1E0;
- _freqmod = -_freqmod;
- }
- _freq[2] = _freq[0] + 0x20;
- return true;
- }
-private:
- const uint16 _offset;
- const uint16 _size;
-
- uint16 _freq[4];
- uint16 _vol[4];
- int16 _freqmod;
- int16 _volmod[2];
-};
-
-#define CRCToSound(CRC, SOUND) \
- if (crc == CRC) \
- return new SOUND
-
-static V2A_Sound *findSound(unsigned long crc) {
- CRCToSound(0x8FAB08C4, V2A_Sound_SingleLooped(0x006C, 0x2B58, 0x016E, 0x3F)); // Maniac 17
- CRCToSound(0xB673160A, V2A_Sound_SingleLooped(0x006C, 0x1E78, 0x01C2, 0x1E)); // Maniac 38
- CRCToSound(0x4DB1D0B2, V2A_Sound_MultiLooped(0x0072, 0x1BC8, 0x023D, 0x3F, 0x0224, 0x3F)); // Maniac 20
- CRCToSound(0x754D75EF, V2A_Sound_Single(0x0076, 0x0738, 0x01FC, 0x3F)); // Maniac 10
- CRCToSound(0x6E3454AF, V2A_Sound_Single(0x0076, 0x050A, 0x017C, 0x3F)); // Maniac 12
- CRCToSound(0x92F0BBB6, V2A_Sound_Single(0x0076, 0x3288, 0x012E, 0x3F)); // Maniac 41
- CRCToSound(0xE1B13982, V2A_Sound_MultiLoopedDuration(0x0078, 0x0040, 0x007C, 0x3F, 0x007B, 0x3F, 0x001E)); // Maniac 21
- CRCToSound(0x288B16CF, V2A_Sound_MultiLoopedDuration(0x007A, 0x0040, 0x007C, 0x3F, 0x007B, 0x3F, 0x000A)); // Maniac 11
- CRCToSound(0xA7565268, V2A_Sound_MultiLoopedDuration(0x007A, 0x0040, 0x00F8, 0x3F, 0x00F7, 0x3F, 0x000A)); // Maniac 19
- CRCToSound(0x7D419BFC, V2A_Sound_MultiLoopedDuration(0x007E, 0x0040, 0x012C, 0x3F, 0x0149, 0x3F, 0x001E)); // Maniac 22
- CRCToSound(0x1B52280C, V2A_Sound_Single(0x0098, 0x0A58, 0x007F, 0x32)); // Maniac 6
- CRCToSound(0x38D4A810, V2A_Sound_Single(0x0098, 0x2F3C, 0x0258, 0x32)); // Maniac 7
- CRCToSound(0x09F98FC2, V2A_Sound_Single(0x0098, 0x0A56, 0x012C, 0x32)); // Maniac 16
- CRCToSound(0x90440A65, V2A_Sound_Single(0x0098, 0x0208, 0x0078, 0x28)); // Maniac 28
- CRCToSound(0x985C76EF, V2A_Sound_Single(0x0098, 0x0D6E, 0x00C8, 0x32)); // Maniac 30
- CRCToSound(0x76156137, V2A_Sound_Single(0x0098, 0x2610, 0x017C, 0x39)); // Maniac 39
- CRCToSound(0x5D95F88C, V2A_Sound_Single(0x0098, 0x0A58, 0x007F, 0x1E)); // Maniac 65
- CRCToSound(0x92D704EA, V2A_Sound_SingleLooped(0x009C, 0x29BC, 0x012C, 0x3F, 0x1BD4, 0x0DE8)); // Maniac 15
- CRCToSound(0x92F5513C, V2A_Sound_Single(0x009E, 0x0DD4, 0x01F4, 0x3F)); // Maniac 13
- CRCToSound(0xCC2F3B5A, V2A_Sound_Single(0x009E, 0x00DE, 0x01AC, 0x3F)); // Maniac 43
- CRCToSound(0x153207D3, V2A_Sound_Single(0x009E, 0x0E06, 0x02A8, 0x3F)); // Maniac 67
- CRCToSound(0xC4F370CE, V2A_Sound_Single(0x00AE, 0x0330, 0x01AC, 0x3F)); // Maniac 8
- CRCToSound(0x928C4BAC, V2A_Sound_Single(0x00AE, 0x08D6, 0x01AC, 0x3F)); // Maniac 9
- CRCToSound(0x62D5B11F, V2A_Sound_Single(0x00AE, 0x165C, 0x01CB, 0x3F)); // Maniac 27
- CRCToSound(0x3AB22CB5, V2A_Sound_Single(0x00AE, 0x294E, 0x012A, 0x3F)); // Maniac 62
- CRCToSound(0x2D70BBE9, V2A_Sound_SingleLoopedPitchbend(0x00B4, 0x1702, 0x03E8, 0x0190, 0x3F, 5)); // Maniac 64
- CRCToSound(0xFA4C1B1C, V2A_Sound_Special_Maniac69(0x00B2, 0x1702, 0x0190, 0x3F)); // Maniac 69
- CRCToSound(0x19D50D67, V2A_Sound_Special_ManiacDing(0x00B6, 0x0020, 0x00C8, 16, 2)); // Maniac 14
- CRCToSound(0x3E6FBE15, V2A_Sound_Special_ManiacTentacle(0x00B2, 0x0010, 0x007C, 0x016D, 1)); // Maniac 25
- CRCToSound(0x5305753C, V2A_Sound_Special_ManiacTentacle(0x00B2, 0x0010, 0x007C, 0x016D, 7)); // Maniac 36
- CRCToSound(0x28895106, V2A_Sound_Special_Maniac59(0x00C0, 0x00FE, 0x00E9, 0x0111, 4, 0x0A)); // Maniac 59
- CRCToSound(0xB641ACF6, V2A_Sound_Special_Maniac61(0x00C8, 0x0100, 0x00C8, 0x01C2)); // Maniac 61
- CRCToSound(0xE1A91583, V2A_Sound_Special_ManiacPhone(0x00D0, 0x0040, 0x007C, 0x3F, 0x007B, 0x3F, 0x3C, 5, 6)); // Maniac 23
- CRCToSound(0x64816ED5, V2A_Sound_Special_ManiacPhone(0x00D0, 0x0040, 0x00BE, 0x37, 0x00BD, 0x37, 0x3C, 5, 6)); // Maniac 24
- CRCToSound(0x639D72C2, V2A_Sound_Special_Maniac46(0x00D0, 0x10A4, 0x0080, 0x3F, 0x28, 3)); // Maniac 46
- CRCToSound(0xE8826D92, V2A_Sound_Special_ManiacTypewriter(0x00EC, 0x025A, 0x023C, 0x3F, 8, (const uint8 *)"\x20\x41\x04\x21\x08\x10\x13\x07", true)); // Maniac 45
- CRCToSound(0xEDFF3D41, V2A_Sound_Single(0x00F8, 0x2ADE, 0x01F8, 0x3F)); // Maniac 42 (this should echo, but it's barely noticeable and I don't feel like doing it)
- CRCToSound(0x15606D06, V2A_Sound_Special_Maniac32(0x0148, 0x0020, 0x0168, 0x0020, 0x3F)); // Maniac 32
- CRCToSound(0x753EAFE3, V2A_Sound_Special_Maniac44(0x017C, 0x0010, 0x018C, 0x0020, 0x00C8, 0x0080, 0x3F)); // Maniac 44
- CRCToSound(0xB1AB065C, V2A_Sound_Music(0x0032, 0x00B2, 0x08B2, 0x1222, 0x1A52, 0x23C2, 0x3074, false)); // Maniac 50
- CRCToSound(0x091F5D9C, V2A_Sound_Music(0x0032, 0x0132, 0x0932, 0x1802, 0x23D2, 0x3EA2, 0x4F04, false)); // Maniac 58
-
- CRCToSound(0x8E2C8AB3, V2A_Sound_SingleLooped(0x005C, 0x0F26, 0x0168, 0x3C)); // Zak 41
- CRCToSound(0x3792071F, V2A_Sound_SingleLooped(0x0060, 0x1A18, 0x06A4, 0x3F)); // Zak 88
- CRCToSound(0xF192EDE9, V2A_Sound_SingleLooped(0x0062, 0x0054, 0x01FC, 0x1E)); // Zak 68
- CRCToSound(0xC43B0245, V2A_Sound_Special_Zak70(0x006C, 0x166E, 0x00C8, 0x0190, 0x0320, 0x0640, 0x32)); // Zak 70
- CRCToSound(0xCEB51670, V2A_Sound_SingleLooped(0x00AC, 0x26DC, 0x012C, 0x3F)); // Zak 42
- CRCToSound(0x10347B51, V2A_Sound_SingleLooped(0x006C, 0x00E0, 0x0594, 0x3F)); // Zak 18
- CRCToSound(0x9D2FADC0, V2A_Sound_MultiLooped(0x0072, 0x1FC8, 0x016A, 0x3F, 0x01CE, 0x3F)); // Zak 80
- CRCToSound(0xFAD2C676, V2A_Sound_MultiLooped(0x0076, 0x0010, 0x0080, 0x3F, 0x0090, 0x3B)); // Zak 40
- CRCToSound(0x01508B48, V2A_Sound_Single(0x0076, 0x0D8C, 0x017C, 0x3F)); // Zak 90
- CRCToSound(0x9C18DC46, V2A_Sound_Single(0x0076, 0x0D8C, 0x015E, 0x3F)); // Zak 91
- CRCToSound(0xF98F7EAC, V2A_Sound_Single(0x0076, 0x0D8C, 0x0140, 0x3F)); // Zak 92
- CRCToSound(0xC925FBEF, V2A_Sound_MultiLoopedDuration(0x0080, 0x0010, 0x0080, 0x3F, 0x0090, 0x3B, 0x0168)); // Zak 53
- CRCToSound(0xCAB35257, V2A_Sound_Special_Zak101(0x00DA, 0x425C, 0x023C, 0x08F0, 0x0640, 0x0478, 0x3F, 0x012C)); // Zak 101
- CRCToSound(0xA31FE4FD, V2A_Sound_Single(0x0094, 0x036A, 0x00E1, 0x3F)); // Zak 97
- CRCToSound(0x0A1AE0F5, V2A_Sound_Single(0x009E, 0x0876, 0x0168, 0x3F)); // Zak 5
- CRCToSound(0xD01A66CB, V2A_Sound_Single(0x009E, 0x04A8, 0x0168, 0x3F)); // Zak 47
- CRCToSound(0x5497B912, V2A_Sound_Single(0x009E, 0x0198, 0x01F4, 0x3F)); // Zak 39
- CRCToSound(0x2B50362F, V2A_Sound_Single(0x009E, 0x09B6, 0x023D, 0x3F)); // Zak 67
- CRCToSound(0x7BFB6E72, V2A_Sound_Single(0x009E, 0x0D14, 0x0078, 0x3F)); // Zak 69
- CRCToSound(0xB803A792, V2A_Sound_Single(0x009E, 0x2302, 0x02BC, 0x3F)); // Zak 78
- CRCToSound(0x7AB82E39, V2A_Sound_SingleLooped(0x00A0, 0x2A3C, 0x016E, 0x3F, 0x1018, 0x1A24)); // Zak 100
- CRCToSound(0x28057CEC, V2A_Sound_Single(0x0098, 0x0FEC, 0x0140, 0x32)); // Zak 63
- CRCToSound(0x1180A2FC, V2A_Sound_Single(0x0098, 0x0F06, 0x0190, 0x32)); // Zak 64
- CRCToSound(0x12616755, V2A_Sound_Single(0x0098, 0x14C8, 0x023C, 0x14)); // Zak 9
- CRCToSound(0x642723AA, V2A_Sound_Special_Zak37(0x00A2, 0x1702, 0x01F4, 0x3F)); // Zak 37
- CRCToSound(0xDEE56848, V2A_Sound_Single(0x009A, 0x0F86, 0x0100, 0x3F)); // Zak 93
- CRCToSound(0xF9BE27B8, V2A_Sound_Special_Zak37(0x011C, 0x1704, 0x0228, 0x3F)); // Zak 113
- CRCToSound(0xC73487B2, V2A_Sound_Single(0x00B0, 0x18BA, 0x0478, 0x3F)); // Zak 81
- CRCToSound(0x32D8F925, V2A_Sound_Single(0x00B0, 0x2E46, 0x00F0, 0x3F)); // Zak 94
- CRCToSound(0x988C83A5, V2A_Sound_Single(0x00B0, 0x0DE0, 0x025B, 0x3F)); // Zak 106
- CRCToSound(0x8F1E3B3D, V2A_Sound_Single(0x00B0, 0x05FE, 0x04E2, 0x3F)); // Zak 107
- CRCToSound(0x0A2A7646, V2A_Sound_Single(0x00B0, 0x36FE, 0x016E, 0x3F)); // Zak 43
- CRCToSound(0x6F1FC435, V2A_Sound_Single(0x00B0, 0x2808, 0x044C, 0x3F)); // Zak 108
- CRCToSound(0x870EFC29, V2A_Sound_SingleLoopedPitchbend(0x00BA, 0x0100, 0x03E8, 0x00C8, 0x3F, 3)); // Zak 55
- CRCToSound(0xED773699, V2A_Sound_Special_ManiacDing(0x00B4, 0x0020, 0x012C, 8, 4)); // Zak 3
- CRCToSound(0x0BF59774, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x00F8, 0x00F7, 8, 1)); // Zak 72
- CRCToSound(0x656FFEDE, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x00C4, 0x00C3, 8, 1)); // Zak 73
- CRCToSound(0xFC4D41E5, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x00A5, 0x00A4, 8, 1)); // Zak 74
- CRCToSound(0xC0DD2089, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x009C, 0x009B, 8, 1)); // Zak 75
- CRCToSound(0x627DFD92, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x008B, 0x008A, 8, 1)); // Zak 76
- CRCToSound(0x703E05C1, V2A_Sound_Special_ZakStereoDing(0x00BE, 0x0020, 0x007C, 0x007B, 8, 1)); // Zak 77
- CRCToSound(0xB0F77006, V2A_Sound_Special_Zak52(0x00B0, 0x01BC)); // Zak 52
- CRCToSound(0x5AE9D6A7, V2A_Sound_Special_ZakAirplane(0x00CA, 0x22A4, 0x0113, 0x0227)); // Zak 109
- CRCToSound(0xABE0D3B0, V2A_Sound_Special_ZakAirplane(0x00CE, 0x22A4, 0x0227, 0x0113)); // Zak 105
- CRCToSound(0x788CC749, V2A_Sound_Special_Zak71(0x00C8, 0x0B37)); // Zak 71
- CRCToSound(0x2E2AB1FA, V2A_Sound_Special_Zak99(0x00D4, 0x04F0, 0x0FE3, 0x0080, 0x3F)); // Zak 99
- CRCToSound(0x1304CF20, V2A_Sound_Special_ManiacTypewriter(0x00DC, 0x0624, 0x023C, 0x3C, 2, (const uint8 *)"\x14\x11", false)); // Zak 79
- CRCToSound(0xAE68ED91, V2A_Sound_Special_Zak54(0x00D4, 0x1A25, 0x1E1E, 0x0B80, 0x01F4)); // Zak 54
- CRCToSound(0xA4F40F97, V2A_Sound_Special_Zak61(0x00E4, 0x0020)); // Zak 61
- CRCToSound(0x348F85CE, V2A_Sound_Special_Zak62(0x00E4, 0x0020)); // Zak 62
- CRCToSound(0xD473AB86, V2A_Sound_Special_ManiacTypewriter(0x0122, 0x03E8, 0x00BE, 0x3F, 7, (const uint8 *)"\x0F\x0B\x04\x0F\x1E\x0F\x66", false)); // Zak 46
- CRCToSound(0x84A0BA90, V2A_Sound_Special_Zak110(0x0126, 0x0040, 0x0136, 0x0080, 0x007C, 0x0087)); // Zak 110
- CRCToSound(0x92680D9F, V2A_Sound_Special_Zak32(0x0140, 0x0150, 0x0010, 0x0010)); // Zak 32
- CRCToSound(0xABFFDB02, V2A_Sound_Special_Zak86(0x01A2, 0x2BAE)); // Zak 86
- CRCToSound(0x41045447, V2A_Sound_Special_Zak98(0x017A, 0x0020)); // Zak 98
- CRCToSound(0xC8EEBD34, V2A_Sound_Special_Zak82(0x01A6, 0x3900)); // Zak 82
- CRCToSound(0x42F9469F, V2A_Sound_Music(0x05F6, 0x0636, 0x0456, 0x0516, 0x05D6, 0x05E6, 0x0A36, true)); // Zak 96
- CRCToSound(0x038BBD78, V2A_Sound_Music(0x054E, 0x05CE, 0x044E, 0x04BE, 0x052E, 0x053E, 0x0BCE, true)); // Zak 85
- CRCToSound(0x06FFADC5, V2A_Sound_Music(0x0626, 0x0686, 0x0446, 0x04F6, 0x0606, 0x0616, 0x0C86, true)); // Zak 87
- CRCToSound(0xCE20ECF0, V2A_Sound_Music(0x0636, 0x0696, 0x0446, 0x0576, 0x0616, 0x0626, 0x0E96, true)); // Zak 114
- CRCToSound(0xBDA01BB6, V2A_Sound_Music(0x0678, 0x06B8, 0x0458, 0x0648, 0x0658, 0x0668, 0x0EB8, false)); // Zak 33
- CRCToSound(0x59976529, V2A_Sound_Music(0x088E, 0x092E, 0x048E, 0x05EE, 0x074E, 0x07EE, 0x112E, true)); // Zak 49
- CRCToSound(0xED1EED02, V2A_Sound_Music(0x08D0, 0x0950, 0x0440, 0x07E0, 0x08B0, 0x08C0, 0x1350, false)); // Zak 112
- CRCToSound(0x5A16C037, V2A_Sound_Music(0x634A, 0x64CA, 0x049A, 0x18FA, 0x398A, 0x511A, 0x6CCA, false)); // Zak 95
- return NULL;
-}
-
-Player_V2A::Player_V2A(ScummEngine *scumm, Audio::Mixer *mixer) {
- int i;
- _vm = scumm;
-
- InitCRC();
-
- for (i = 0; i < V2A_MAXSLOTS; i++) {
- _slot[i].id = 0;
- _slot[i].sound = NULL;
- }
-
- _mod = new Player_MOD(mixer);
- _mod->setUpdateProc(update_proc, this, 60);
-}
-
-Player_V2A::~Player_V2A() {
- delete _mod;
-}
-
-void Player_V2A::setMusicVolume(int vol) {
- _mod->setMusicVolume(vol);
-}
-
-int Player_V2A::getSoundSlot(int id) const {
- int i;
- for (i = 0; i < V2A_MAXSLOTS; i++) {
- if (_slot[i].id == id)
- break;
- }
- if (i == V2A_MAXSLOTS) {
- if (id == 0)
- warning("player_v2a - out of sound slots");
- return -1;
- }
- return i;
-}
-
-void Player_V2A::stopAllSounds() {
- for (int i = 0; i < V2A_MAXSLOTS; i++) {
- if (!_slot[i].id)
- continue;
- _slot[i].sound->stop();
- delete _slot[i].sound;
- _slot[i].sound = NULL;
- _slot[i].id = 0;
- }
-}
-
-void Player_V2A::stopSound(int nr) {
- int i;
- if (nr == 0)
- return;
- i = getSoundSlot(nr);
- if (i == -1)
- return;
- _slot[i].sound->stop();
- delete _slot[i].sound;
- _slot[i].sound = NULL;
- _slot[i].id = 0;
-}
-
-void Player_V2A::startSound(int nr) {
- assert(_vm);
- byte *data = _vm->getResourceAddress(rtSound, nr);
- assert(data);
- uint32 crc = GetCRC(data + 0x0A, READ_BE_UINT16(data + 0x08));
- V2A_Sound *snd = findSound(crc);
- if (snd == NULL) {
- warning("player_v2a - sound %i not recognized yet (crc %08X)", nr, crc);
- return;
- }
- stopSound(nr);
- int i = getSoundSlot();
- if (i == -1) {
- delete snd;
- return;
- }
- _slot[i].id = nr;
- _slot[i].sound = snd;
- _slot[i].sound->start(_mod, nr, data);
-}
-
-void Player_V2A::update_proc(void *param) {
- ((Player_V2A *)param)->updateSound();
-}
-
-void Player_V2A::updateSound() {
- int i;
- for (i = 0; i < V2A_MAXSLOTS; i++) {
- if ((_slot[i].id) && (!_slot[i].sound->update())) {
- _slot[i].sound->stop();
- delete _slot[i].sound;
- _slot[i].sound = NULL;
- _slot[i].id = 0;
- }
- }
-}
-
-int Player_V2A::getMusicTimer() {
- return 0; // FIXME - need to keep track of playing music resources
-}
-
-int Player_V2A::getSoundStatus(int nr) const {
- for (int i = 0; i < V2A_MAXSLOTS; i++) {
- if (_slot[i].id == nr)
- return 1;
- }
- return 0;
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v2a.h b/engines/scumm/player/v2a.h
deleted file mode 100644
index cc2f4a7362..0000000000
--- a/engines/scumm/player/v2a.h
+++ /dev/null
@@ -1,73 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V2A_H
-#define SCUMM_PLAYER_V2A_H
-
-#include "common/scummsys.h"
-#include "scumm/music.h"
-#include "scumm/player/mod.h"
-
-class Mixer;
-
-namespace Scumm {
-
-class ScummEngine;
-class V2A_Sound;
-
-/**
- * Scumm V2 Amiga sound/music driver.
- */
-class Player_V2A : public MusicEngine {
-public:
- Player_V2A(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_V2A();
-
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getMusicTimer();
- virtual int getSoundStatus(int sound) const;
-
-private:
- enum {
- V2A_MAXSLOTS = 8
- };
-
- struct soundSlot {
- int id;
- V2A_Sound *sound;
- };
-
- ScummEngine *_vm;
- Player_MOD *_mod;
- soundSlot _slot[V2A_MAXSLOTS];
-
- int getSoundSlot(int id = 0) const;
- static void update_proc(void *param);
- void updateSound();
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v2base.cpp b/engines/scumm/player/v2base.cpp
deleted file mode 100644
index 4b20cfc910..0000000000
--- a/engines/scumm/player/v2base.cpp
+++ /dev/null
@@ -1,654 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "scumm/player/v2base.h"
-#include "scumm/scumm.h"
-
-#define FREQ_HZ 236 // Don't change!
-
-#define MAX_OUTPUT 0x7fff
-
-namespace Scumm {
-
-const uint8 note_lengths[] = {
- 0,
- 0, 0, 2,
- 0, 3, 4,
- 5, 6, 8,
- 9, 12, 16,
- 18, 24, 32,
- 36, 48, 64,
- 72, 96
-};
-
-static const uint16 hull_offsets[] = {
- 0, 12, 24, 36, 48, 60,
- 72, 88, 104, 120, 136, 256,
- 152, 164, 180
-};
-
-static const int16 hulls[] = {
- // hull 0
- 3, -1, 0, 0, 0, 0, 0, 0,
- 0, -1, 0, 0,
- // hull 1 (staccato)
- 3, -1, 0, 32, 0, -1, 0, 0,
- 0, -1, 0, 0,
- // hull 2 (legato)
- 3, -1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,
- // hull 3 (staccatissimo)
- 3, -1, 0, 2, 0, -1, 0, 0,
- 0, -1, 0, 0,
- // hull 4
- 3, -1, 0, 6, 0, -1, 0, 0,
- 0, -1, 0, 0,
- // hull 5
- 3, -1, 0, 16, 0, -1, 0, 0,
- 0, -1, 0, 0,
- // hull 6
- (int16) 60000, -1, -1000, 20, 0, 0, 0, 0,
- (int16) 40000, -1, -5000, 5, 0, -1, 0, 0,
- // hull 7
- (int16) 50000, -1, 0, 8, 30000, -1, 0, 0,
- 28000, -1, -5000, 5, 0, -1, 0, 0,
- // hull 8
- (int16) 60000, -1, -2000, 16, 0, 0, 0, 0,
- 28000, -1, -6000, 5, 0, -1, 0, 0,
- // hull 9
- (int16) 55000, -1, 0, 8, (int16) 35000, -1, 0, 0,
- (int16) 40000, -1, -2000, 10, 0, -1, 0, 0,
- // hull 10
- (int16) 60000, -1, 0, 4, -2000, 8, 0, 0,
- (int16) 40000, -1, -6000, 5, 0, -1, 0, 0,
- // hull 12
- 0, -1, 150, 340, -150, 340, 0, -1,
- 0, -1, 0, 0,
- // hull 13 == 164
- 20000, -1, 4000, 7, 1000, 15, 0, 0,
- (int16) 35000, -1, -2000, 15, 0, -1, 0, 0,
-
- // hull 14 == 180
- (int16) 35000, -1, 500, 20, 0, 0, 0, 0,
- (int16) 45000, -1, -500, 60, 0, -1, 0, 0,
-
- // hull misc = 196
- (int16) 44000, -1, -4400, 10, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 53000, -1, -5300, 10, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 63000, -1, -6300, 10, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 44000, -1, -1375, 32, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 53000, -1, -1656, 32, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- // hull 11 == 256
- (int16) 63000, -1, -1968, 32, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 44000, -1, - 733, 60, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 53000, -1, - 883, 60, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 63000, -1, -1050, 60, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 44000, -1, - 488, 90, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 53000, -1, - 588, 90, 0, -1, 0, 0,
- 0, -1, 0, 0,
-
- (int16) 63000, -1, - 700, 90, 0, -1, 0, 0,
- 0, -1, 0, 0
-};
-
-static const uint16 freqmod_lengths[] = {
- 0x1000, 0x1000, 0x20, 0x2000, 0x1000
-};
-
-static const uint16 freqmod_offsets[] = {
- 0, 0x100, 0x200, 0x302, 0x202
-};
-
-static const int8 freqmod_table[0x502] = {
- 0, 3, 6, 9, 12, 15, 18, 21,
- 24, 27, 30, 33, 36, 39, 42, 45,
- 48, 51, 54, 57, 59, 62, 65, 67,
- 70, 73, 75, 78, 80, 82, 85, 87,
- 89, 91, 94, 96, 98, 100, 102, 103,
- 105, 107, 108, 110, 112, 113, 114, 116,
- 117, 118, 119, 120, 121, 122, 123, 123,
- 124, 125, 125, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 126, 126, 125, 125,
- 124, 123, 123, 122, 121, 120, 119, 118,
- 117, 116, 114, 113, 112, 110, 108, 107,
- 105, 103, 102, 100, 98, 96, 94, 91,
- 89, 87, 85, 82, 80, 78, 75, 73,
- 70, 67, 65, 62, 59, 57, 54, 51,
- 48, 45, 42, 39, 36, 33, 30, 27,
- 24, 21, 18, 15, 12, 9, 6, 3,
- 0, -3, -6, -9, -12, -15, -18, -21,
- -24, -27, -30, -33, -36, -39, -42, -45,
- -48, -51, -54, -57, -59, -62, -65, -67,
- -70, -73, -75, -78, -80, -82, -85, -87,
- -89, -91, -94, -96, -98,-100,-102,-103,
- -105,-107,-108,-110,-112,-113,-114,-116,
- -117,-118,-119,-120,-121,-122,-123,-123,
- -124,-125,-125,-126,-126,-126,-126,-126,
- -126,-126,-126,-126,-126,-126,-125,-125,
- -124,-123,-123,-122,-121,-120,-119,-118,
- -117,-116,-114,-113,-112,-110,-108,-107,
- -105,-103,-102,-100, -98, -96, -94, -91,
- -89, -87, -85, -82, -80, -78, -75, -73,
- -70, -67, -65, -62, -59, -57, -54, -51,
- -48, -45, -42, -39, -36, -33, -30, -27,
- -24, -21, -18, -15, -12, -9, -6, -3,
-
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
- -128,-127,-126,-125,-124,-123,-122,-121,
- -120,-119,-118,-117,-116,-115,-114,-113,
- -112,-111,-110,-109,-108,-107,-106,-105,
- -104,-103,-102,-101,-100, -99, -98, -97,
- -96, -95, -94, -93, -92, -91, -90, -89,
- -88, -87, -86, -85, -84, -83, -82, -81,
- -80, -79, -78, -77, -76, -75, -74, -73,
- -72, -71, -70, -69, -68, -67, -66, -65,
- -64, -63, -62, -61, -60, -59, -58, -57,
- -56, -55, -54, -53, -52, -51, -50, -49,
- -48, -47, -46, -45, -44, -43, -42, -41,
- -40, -39, -38, -37, -36, -35, -34, -33,
- -32, -31, -30, -29, -28, -27, -26, -25,
- -24, -23, -22, -21, -20, -19, -18, -17,
- -16, -15, -14, -13, -12, -11, -10, -9,
- -8, -7, -6, -5, -4, -3, -2, -1,
-
- -120, 120,
-
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- -120,-120,-120,-120,-120,-120,-120,-120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120,
-
- 41, 35, -66,-124, -31, 108, -42, -82,
- 82,-112, 73, -15, -15, -69, -23, -21,
- -77, -90, -37, 60,-121, 12, 62,-103,
- 36, 94, 13, 28, 6, -73, 71, -34,
- -77, 18, 77, -56, 67, -69,-117, -90,
- 31, 3, 90, 125, 9, 56, 37, 31,
- 93, -44, -53, -4,-106, -11, 69, 59,
- 19, 13,-119, 10, 28, -37, -82, 50,
- 32,-102, 80, -18, 64, 120, 54, -3,
- 18, 73, 50, -10, -98, 125, 73, -36,
- -83, 79, 20, -14, 68, 64, 102, -48,
- 107, -60, 48, -73, 50, 59, -95, 34,
- -10, 34,-111, -99, -31,-117, 31, -38,
- -80, -54,-103, 2, -71, 114, -99, 73,
- 44,-128, 126, -59,-103, -43, -23,-128,
- -78, -22, -55, -52, 83, -65, 103, -42,
- -65, 20, -42, 126, 45, -36,-114, 102,
- -125, -17, 87, 73, 97, -1, 105,-113,
- 97, -51, -47, 30, -99,-100, 22, 114,
- 114, -26, 29, -16,-124, 79, 74, 119,
- 2, -41, -24, 57, 44, 83, -53, -55,
- 18, 30, 51, 116, -98, 12, -12, -43,
- -44, -97, -44, -92, 89, 126, 53, -49,
- 50, 34, -12, -52, -49, -45,-112, 45,
- 72, -45,-113, 117, -26, -39, 29, 42,
- -27, -64, -9, 43, 120,-127,-121, 68,
- 14, 95, 80, 0, -44, 97,-115, -66,
- 123, 5, 21, 7, 59, 51,-126, 31,
- 24, 112,-110, -38, 100, 84, -50, -79,
- -123, 62, 105, 21, -8, 70, 106, 4,
- -106, 115, 14, -39, 22, 47, 103, 104,
- -44, -9, 74, 74, -48, 87, 104, 118,
- -6, 22, -69, 17, -83, -82, 36,-120,
- 121, -2, 82, -37, 37, 67, -27, 60,
- -12, 69, -45, -40, 40, -50, 11, -11,
- -59, 96, 89, 61,-105, 39,-118, 89,
- 118, 45, -48, -62, -55, -51, 104, -44,
- 73, 106, 121, 37, 8, 97, 64, 20,
- -79, 59, 106, -91, 17, 40, -63,-116,
- -42, -87, 11,-121,-105,-116, 47, -15,
- 21, 29,-102,-107, -63,-101, -31, -64,
- 126, -23, -88,-102, -89,-122, -62, -75,
- 84, -65,-102, -25, -39, 35, -47, 85,
- -112, 56, 40, -47, -39, 108, -95, 102,
- 94, 78, -31, 48,-100, -2, -39, 113,
- -97, -30, -91, -30, 12,-101, -76, 71,
- 101, 56, 42, 70,-119, -87,-126, 121,
- 122, 118, 120, -62, 99, -79, 38, -33,
- -38, 41, 109, 62, 98, -32,-106, 18,
- 52, -65, 57, -90, 63,-119, 94, -15,
- 109, 14, -29, 108, 40, -95, 30, 32,
- 29, -53, -62, 3, 63, 65, 7,-124,
- 15, 20, 5, 101, 27, 40, 97, -55,
- -59, -25, 44,-114, 70, 54, 8, -36,
- -13, -88,-115, -2, -66, -14, -21, 113,
- -1, -96, -48, 59, 117, 6,-116, 126,
- -121, 120, 115, 77, -48, -66,-126, -66,
- -37, -62, 70, 65, 43,-116, -6, 48,
- 127, 112, -16, -89, 84,-122, 50,-107,
- -86, 91, 104, 19, 11, -26, -4, -11,
- -54, -66, 125, -97,-119,-118, 65, 27,
- -3, -72, 79, 104, -10, 114, 123, 20,
- -103, -51, -45, 13, -16, 68, 58, -76,
- -90, 102, 83, 51, 11, -53, -95, 16
-};
-
-static const uint16 spk_freq_table[12] = {
- 36484, 34436, 32503, 30679, 28957, 27332,
- 25798, 24350, 22983, 21693, 20476, 19326
-};
-
-static const uint16 pcjr_freq_table[12] = {
- 65472, 61760, 58304, 55040, 52032, 49024,
- 46272, 43648, 41216, 38912, 36736, 34624
-};
-
-
-Player_V2Base::Player_V2Base(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr)
- : _vm(scumm),
- _mixer(mixer),
- _pcjr(pcjr),
- _sampleRate(_mixer->getOutputRate()) {
-
- _isV3Game = (scumm->_game.version >= 3);
-
- _header_len = (scumm->_game.features & GF_OLD_BUNDLE) ? 4 : 6;
-
- // Initialize sound queue
- _current_nr = _next_nr = 0;
- _current_data = _next_data = 0;
-
- // Initialize channel code
- for (int i = 0; i < 4; ++i)
- clear_channel(i);
-
- _next_tick = 0;
- _tick_len = (_sampleRate << FIXP_SHIFT) / FREQ_HZ;
-
- // Initialize V3 music timer
- _music_timer_ctr = _music_timer = 0;
- _ticks_per_music_timer = 65535;
-
- if (_pcjr) {
- _freqs_table = pcjr_freq_table;
- } else {
- _freqs_table = spk_freq_table;
- }
-}
-
-Player_V2Base::~Player_V2Base() {
-}
-
-void Player_V2Base::chainSound(int nr, byte *data) {
- int offset = _header_len + (_pcjr ? 10 : 2);
-
- _current_nr = nr;
- _current_data = data;
-
- for (int i = 0; i < 4; i++) {
- clear_channel(i);
-
- _channels[i].d.music_script_nr = nr;
- if (data) {
- _channels[i].d.next_cmd = READ_LE_UINT16(data + offset + 2 * i);
- if (_channels[i].d.next_cmd) {
- _channels[i].d.time_left = 1;
- }
- }
- }
- _music_timer = 0;
-}
-
-void Player_V2Base::chainNextSound() {
- if (_next_nr) {
- chainSound(_next_nr, _next_data);
- _next_nr = 0;
- _next_data = 0;
- }
-}
-
-// TODO: Merge stopAllSounds, stopSound() and startSound(), using some overriding
-// perhaps? Player_V2CMS's implementations start like that of Player_V2
-// but then add some MIDI related stuff.
-
-void Player_V2Base::clear_channel(int i) {
- ChannelInfo *channel = &_channels[i];
- memset(channel, 0, sizeof(ChannelInfo));
-}
-
-int Player_V2Base::getMusicTimer() {
- if (_isV3Game)
- return _music_timer;
- else
- return _channels[0].d.music_timer;
-}
-
-void Player_V2Base::execute_cmd(ChannelInfo *channel) {
- uint16 value;
- int16 offset;
- uint8 *script_ptr;
- ChannelInfo * current_channel;
- ChannelInfo * dest_channel;
-
- current_channel = channel;
-
- if (channel->d.next_cmd == 0)
- goto check_stopped;
- script_ptr = &_current_data[channel->d.next_cmd];
-
- for (;;) {
- uint8 opcode = *script_ptr++;
- if (opcode >= 0xf8) {
- switch (opcode) {
- case 0xf8: // set hull curve
- debug(7, "channels[%d]: hull curve %2d",
- (uint)(channel - _channels), *script_ptr);
- channel->d.hull_curve = hull_offsets[*script_ptr / 2];
- script_ptr++;
- break;
-
- case 0xf9: // set freqmod curve
- debug(7, "channels[%d]: freqmod curve %2d",
- (uint)(channel - _channels), *script_ptr);
- channel->d.freqmod_table = freqmod_offsets[*script_ptr / 4];
- channel->d.freqmod_modulo = freqmod_lengths[*script_ptr / 4];
- script_ptr++;
- break;
-
- case 0xfd: // clear other channel
- value = READ_LE_UINT16 (script_ptr) / sizeof (ChannelInfo);
- debug(7, "clear channel %d", value);
- script_ptr += 2;
- // In Indy3, when traveling to Venice a command is
- // issued to clear channel 4. So we introduce a 4th
- // channel, which is never used. All OOB accesses are
- // mapped to this channel.
- //
- // The original game had room for 8 channels, but only
- // channels 0-3 are read, changes to other channels
- // had no effect.
- if (value >= ARRAYSIZE (_channels))
- value = 4;
- channel = &_channels[value];
- // fall through
-
- case 0xfa: // clear current channel
- if (opcode == 0xfa)
- debug(7, "clear channel");
- channel->d.next_cmd = 0;
- channel->d.base_freq = 0;
- channel->d.freq_delta = 0;
- channel->d.freq = 0;
- channel->d.volume = 0;
- channel->d.volume_delta = 0;
- channel->d.inter_note_pause = 0;
- channel->d.transpose = 0;
- channel->d.hull_curve = 0;
- channel->d.hull_offset = 0;
- channel->d.hull_counter = 0;
- channel->d.freqmod_table = 0;
- channel->d.freqmod_offset = 0;
- channel->d.freqmod_incr = 0;
- channel->d.freqmod_multiplier = 0;
- channel->d.freqmod_modulo = 0;
- break;
-
- case 0xfb: // ret from subroutine
- debug(7, "ret from sub");
- script_ptr = _retaddr;
- break;
-
- case 0xfc: // call subroutine
- offset = READ_LE_UINT16 (script_ptr);
- debug(7, "subroutine %d", offset);
- script_ptr += 2;
- _retaddr = script_ptr;
- script_ptr = _current_data + offset;
- break;
-
- case 0xfe: // loop music
- opcode = *script_ptr++;
- offset = READ_LE_UINT16 (script_ptr);
- script_ptr += 2;
- debug(7, "loop if %d to %d", opcode, offset);
- if (!channel->array[opcode / 2] || --channel->array[opcode/2])
- script_ptr += offset;
- break;
-
- case 0xff: // set parameter
- opcode = *script_ptr++;
- value = READ_LE_UINT16 (script_ptr);
- channel->array[opcode / 2] = value;
- debug(7, "channels[%d]: set param %2d = %5d",
- (uint)(channel - _channels), opcode, value);
- script_ptr += 2;
- if (opcode == 14) {
- /* tempo var */
- _ticks_per_music_timer = 125;
- }
- if (opcode == 0)
- goto end;
- break;
- }
- } else { // opcode < 0xf8
- for (;;) {
- int16 note, octave;
- int is_last_note;
- dest_channel = &_channels[(opcode >> 5) & 3];
-
- if (!(opcode & 0x80)) {
-
- int tempo = channel->d.tempo;
- if (!tempo)
- tempo = 1;
- channel->d.time_left = tempo * note_lengths[opcode & 0x1f];
-
- note = *script_ptr++;
- is_last_note = note & 0x80;
- note &= 0x7f;
- if (note == 0x7f) {
- debug(8, "channels[%d]: pause %d",
- (uint)(channel - _channels), channel->d.time_left);
- goto end;
- }
- } else {
-
- channel->d.time_left = ((opcode & 7) << 8) | *script_ptr++;
-
- if ((opcode & 0x10)) {
- debug(8, "channels[%d]: pause %d",
- (uint)(channel - _channels), channel->d.time_left);
- goto end;
- }
-
- is_last_note = 0;
- note = (*script_ptr++) & 0x7f;
- }
-
- debug(8, "channels[%d]: @%04x note: %3d+%d len: %2d hull: %d mod: %d/%d/%d %s",
- (uint)(dest_channel - channel), script_ptr ? (uint)(script_ptr - _current_data - 2) : 0,
- note, (signed short) dest_channel->d.transpose, channel->d.time_left,
- dest_channel->d.hull_curve, dest_channel->d.freqmod_table,
- dest_channel->d.freqmod_incr,dest_channel->d.freqmod_multiplier,
- is_last_note ? "last":"");
-
- uint16 myfreq;
- dest_channel->d.time_left = channel->d.time_left;
- dest_channel->d.note_length =
- channel->d.time_left - dest_channel->d.inter_note_pause;
- note += dest_channel->d.transpose;
- while (note < 0)
- note += 12;
- octave = note / 12;
- note = note % 12;
- dest_channel->d.hull_offset = 0;
- dest_channel->d.hull_counter = 1;
- if (_pcjr && dest_channel == &_channels[3]) {
- dest_channel->d.hull_curve = 196 + note * 12;
- myfreq = 384 - 64 * octave;
- } else {
- myfreq = _freqs_table[note] >> octave;
- }
- dest_channel->d.freq = dest_channel->d.base_freq = myfreq;
- if (is_last_note)
- goto end;
- opcode = *script_ptr++;
- }
- }
- }
-
-end:
- channel = current_channel;
- if (channel->d.time_left) {
- channel->d.next_cmd = script_ptr - _current_data;
- return;
- }
-
- channel->d.next_cmd = 0;
-
-check_stopped:
- int i;
- for (i = 0; i < 4; i++) {
- if (_channels[i].d.time_left)
- return;
- }
-
- _current_nr = 0;
- _current_data = 0;
- chainNextSound();
-}
-
-void Player_V2Base::next_freqs(ChannelInfo *channel) {
- channel->d.volume += channel->d.volume_delta;
- channel->d.base_freq += channel->d.freq_delta;
-
- channel->d.freqmod_offset += channel->d.freqmod_incr;
- if (channel->d.freqmod_offset > channel->d.freqmod_modulo)
- channel->d.freqmod_offset -= channel->d.freqmod_modulo;
-
- channel->d.freq =
- (int) (freqmod_table[channel->d.freqmod_table + (channel->d.freqmod_offset >> 4)])
- * (int) channel->d.freqmod_multiplier / 256
- + channel->d.base_freq;
-
- debug(9, "Freq: %d/%d, %d/%d/%d*%d %d",
- channel->d.base_freq, (int16)channel->d.freq_delta,
- channel->d.freqmod_table, channel->d.freqmod_offset,
- channel->d.freqmod_incr, channel->d.freqmod_multiplier,
- channel->d.freq);
-
- if (channel->d.note_length && !--channel->d.note_length) {
- channel->d.hull_offset = 16;
- channel->d.hull_counter = 1;
- }
-
- if (!--channel->d.time_left) {
- execute_cmd(channel);
- }
-
- if (channel->d.hull_counter && !--channel->d.hull_counter) {
- for (;;) {
- const int16 *hull_ptr = hulls
- + channel->d.hull_curve + channel->d.hull_offset / 2;
- if (hull_ptr[1] == -1) {
- channel->d.volume = hull_ptr[0];
- if (hull_ptr[0] == 0)
- channel->d.volume_delta = 0;
- channel->d.hull_offset += 4;
- } else {
- channel->d.volume_delta = hull_ptr[0];
- channel->d.hull_counter = hull_ptr[1];
- channel->d.hull_offset += 4;
- break;
- }
- }
- }
-}
-
-void Player_V2Base::nextTick() {
- for (int i = 0; i < 4; i++) {
- if (!_channels[i].d.time_left)
- continue;
- next_freqs(&_channels[i]);
- }
- if (_music_timer_ctr++ >= _ticks_per_music_timer) {
- _music_timer_ctr = 0;
- _music_timer++;
- }
-}
-
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v2base.h b/engines/scumm/player/v2base.h
deleted file mode 100644
index eb9ed941ca..0000000000
--- a/engines/scumm/player/v2base.h
+++ /dev/null
@@ -1,145 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V2BASE_H
-#define SCUMM_PLAYER_V2BASE_H
-
-#include "common/scummsys.h"
-#include "common/mutex.h"
-#include "scumm/music.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-namespace Scumm {
-
-class ScummEngine;
-
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
-struct channel_data {
- uint16 time_left; // 00
- uint16 next_cmd; // 02
- uint16 base_freq; // 04
- uint16 freq_delta; // 06
- uint16 freq; // 08
- uint16 volume; // 10
- uint16 volume_delta; // 12
- uint16 tempo; // 14
- uint16 inter_note_pause; // 16
- uint16 transpose; // 18
- uint16 note_length; // 20
- uint16 hull_curve; // 22
- uint16 hull_offset; // 24
- uint16 hull_counter; // 26
- uint16 freqmod_table; // 28
- uint16 freqmod_offset; // 30
- uint16 freqmod_incr; // 32
- uint16 freqmod_multiplier; // 34
- uint16 freqmod_modulo; // 36
- uint16 unknown[4]; // 38 - 44
- uint16 music_timer; // 46
- uint16 music_script_nr; // 48
-} PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
-/**
- * Common base class for Player_V2 and Player_V2CMS.
- */
-class Player_V2Base : public Audio::AudioStream, public MusicEngine {
-public:
- Player_V2Base(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr);
- virtual ~Player_V2Base();
-
- // MusicEngine API
-// virtual void setMusicVolume(int vol);
-// virtual void startSound(int sound);
-// virtual void stopSound(int sound);
-// virtual void stopAllSounds();
- virtual int getMusicTimer();
-// virtual int getSoundStatus(int sound) const;
-
- // AudioStream API
-/*
- int readBuffer(int16 *buffer, const int numSamples) {
- do_mix(buffer, numSamples / 2);
- return numSamples;
- }
-*/
- virtual bool isStereo() const { return true; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _sampleRate; }
-
-protected:
- enum {
- FIXP_SHIFT = 16
- };
-
- bool _isV3Game;
- Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
- ScummEngine *_vm;
-
- bool _pcjr;
- int _header_len;
-
- const uint32 _sampleRate;
- uint32 _next_tick;
- uint32 _tick_len;
-
- int _current_nr;
- byte *_current_data;
- int _next_nr;
- byte *_next_data;
- byte *_retaddr;
-
- Common::Mutex _mutex;
-
- union ChannelInfo {
- channel_data d;
- uint16 array[sizeof(channel_data)/2];
- };
-
- ChannelInfo _channels[5];
-
-private:
- int _music_timer;
- int _music_timer_ctr;
- int _ticks_per_music_timer;
-
- const uint16 *_freqs_table;
-
-protected:
- virtual void nextTick();
- virtual void clear_channel(int i);
- virtual void chainSound(int nr, byte *data);
- virtual void chainNextSound();
-
- void execute_cmd(ChannelInfo *channel);
- void next_freqs(ChannelInfo *channel);
-};
-
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v2cms.cpp b/engines/scumm/player/v2cms.cpp
deleted file mode 100644
index 30ca238860..0000000000
--- a/engines/scumm/player/v2cms.cpp
+++ /dev/null
@@ -1,787 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "scumm/player/v2cms.h"
-#include "scumm/scumm.h"
-#include "audio/mididrv.h"
-#include "audio/mixer.h"
-#include "audio/softsynth/cms.h"
-
-namespace Scumm {
-
-Player_V2CMS::Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer)
- : Player_V2Base(scumm, mixer, true), _cmsVoicesBase(), _cmsVoices(),
- _cmsChips(), _midiDelay(0), _octaveMask(0), _looping(0), _tempo(0),
- _tempoSum(0), _midiData(0), _midiSongBegin(0), _musicTimer(0),
- _musicTimerTicks(0), _voiceTimer(0), _loadedMidiSong(0),
- _outputTableReady(0), _midiChannel(), _midiChannelUse() {
- setMusicVolume(255);
-
- memset(_sfxFreq, 0xFF, sizeof(_sfxFreq));
- memset(_sfxAmpl, 0x00, sizeof(_sfxAmpl));
- memset(_sfxOctave, 0x66, sizeof(_sfxOctave));
-
- _cmsVoices[0].amplitudeOutput = &_cmsChips[0].ampl[0];
- _cmsVoices[0].freqOutput = &_cmsChips[0].freq[0];
- _cmsVoices[0].octaveOutput = &_cmsChips[0].octave[0];
- _cmsVoices[1].amplitudeOutput = &_cmsChips[0].ampl[1];
- _cmsVoices[1].freqOutput = &_cmsChips[0].freq[1];
- _cmsVoices[1].octaveOutput = &_cmsChips[0].octave[0];
- _cmsVoices[2].amplitudeOutput = &_cmsChips[0].ampl[2];
- _cmsVoices[2].freqOutput = &_cmsChips[0].freq[2];
- _cmsVoices[2].octaveOutput = &_cmsChips[0].octave[1];
- _cmsVoices[3].amplitudeOutput = &_cmsChips[0].ampl[3];
- _cmsVoices[3].freqOutput = &_cmsChips[0].freq[3];
- _cmsVoices[3].octaveOutput = &_cmsChips[0].octave[1];
- _cmsVoices[4].amplitudeOutput = &_cmsChips[1].ampl[0];
- _cmsVoices[4].freqOutput = &_cmsChips[1].freq[0];
- _cmsVoices[4].octaveOutput = &_cmsChips[1].octave[0];
- _cmsVoices[5].amplitudeOutput = &_cmsChips[1].ampl[1];
- _cmsVoices[5].freqOutput = &_cmsChips[1].freq[1];
- _cmsVoices[5].octaveOutput = &_cmsChips[1].octave[0];
- _cmsVoices[6].amplitudeOutput = &_cmsChips[1].ampl[2];
- _cmsVoices[6].freqOutput = &_cmsChips[1].freq[2];
- _cmsVoices[6].octaveOutput = &_cmsChips[1].octave[1];
- _cmsVoices[7].amplitudeOutput = &_cmsChips[1].ampl[3];
- _cmsVoices[7].freqOutput = &_cmsChips[1].freq[3];
- _cmsVoices[7].octaveOutput = &_cmsChips[1].octave[1];
-
- // inits the CMS Emulator like in the original
- _cmsEmu = new CMSEmulator(_sampleRate);
- for (int i = 0, cmsPort = 0x220; i < 2; cmsPort += 2, ++i) {
- for (int off = 0; off < 13; ++off) {
- _cmsEmu->portWrite(cmsPort+1, _cmsInitData[off*2]);
- _cmsEmu->portWrite(cmsPort, _cmsInitData[off*2+1]);
- }
- }
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-Player_V2CMS::~Player_V2CMS() {
- Common::StackLock lock(_mutex);
-
- _mixer->stopHandle(_soundHandle);
- delete _cmsEmu;
-}
-
-void Player_V2CMS::setMusicVolume(int vol) {
-}
-
-int Player_V2CMS::getMusicTimer() {
- return _midiData ? _musicTimer : Player_V2Base::getMusicTimer();
-}
-
-void Player_V2CMS::stopAllSounds() {
- Common::StackLock lock(_mutex);
-
- for (int i = 0; i < 4; i++) {
- clear_channel(i);
- }
- _next_nr = _current_nr = 0;
- _next_data = _current_data = 0;
- _midiData = 0;
- _midiSongBegin = 0;
- _midiDelay = 0;
- _musicTimer = _musicTimerTicks = 0;
- offAllChannels();
-}
-
-void Player_V2CMS::stopSound(int nr) {
- Common::StackLock lock(_mutex);
-
- if (_next_nr == nr) {
- _next_nr = 0;
- _next_data = 0;
- }
- if (_current_nr == nr) {
- for (int i = 0; i < 4; i++) {
- clear_channel(i);
- }
- _current_nr = 0;
- _current_data = 0;
- chainNextSound();
- }
- if (_loadedMidiSong == nr) {
- _midiData = 0;
- _midiSongBegin = 0;
- _midiDelay = 0;
- offAllChannels();
- }
-}
-
-void Player_V2CMS::startSound(int nr) {
- Common::StackLock lock(_mutex);
-
- byte *data = _vm->getResourceAddress(rtSound, nr);
- assert(data);
-
- if (data[6] == 0x80) {
- _musicTimer = _musicTimerTicks = 0;
- loadMidiData(data, nr);
- } else {
- int cprio = _current_data ? *(_current_data + _header_len) : 0;
- int prio = *(data + _header_len);
- int nprio = _next_data ? *(_next_data + _header_len) : 0;
-
- int restartable = *(data + _header_len + 1);
-
- if (!_current_nr || cprio <= prio) {
- int tnr = _current_nr;
- int tprio = cprio;
- byte *tdata = _current_data;
-
- chainSound(nr, data);
- nr = tnr;
- prio = tprio;
- data = tdata;
- restartable = data ? *(data + _header_len + 1) : 0;
- }
-
- if (!_current_nr) {
- nr = 0;
- _next_nr = 0;
- _next_data = 0;
- }
-
- if (nr != _current_nr
- && restartable
- && (!_next_nr
- || nprio <= prio)) {
-
- _next_nr = nr;
- _next_data = data;
- }
- }
-}
-
-void Player_V2CMS::loadMidiData(byte *data, int sound) {
- memset(_midiChannelUse, 0, sizeof(_midiChannelUse));
- memset(_midiChannel, 0, sizeof(_midiChannel));
-
- _tempo = data[7];
- _looping = data[8];
-
- byte channels = data[14];
- byte curChannel = 0;
- byte *voice2 = data + 23;
-
- for (; channels != 0; ++curChannel, --channels, voice2 += 16) {
- if (*(data + 15 + curChannel)) {
- byte channel = *(data + 15 + curChannel) - 1;
- _midiChannelUse[channel] = 1;
-
- Voice *voiceDef = &_cmsVoicesBase[channel];
-
- byte attackDecay = voice2[10];
- voiceDef->attack = _attackRate[attackDecay >> 4];
- voiceDef->decay = _decayRate[attackDecay & 0x0F];
- byte sustainRelease = voice2[11];
- voiceDef->sustain = _sustainRate[sustainRelease >> 4];
- voiceDef->release = _releaseRate[sustainRelease & 0x0F];
-
- if (voice2[3] & 0x40) {
- voiceDef->vibrato = 0x0301;
- if (voice2[13] & 0x40) {
- voiceDef->vibrato = 0x0601;
- }
- } else {
- voiceDef->vibrato = 0;
- }
-
- if (voice2[8] & 0x80) {
- voiceDef->vibrato2 = 0x0506;
- if (voice2[13] & 0x80) {
- voiceDef->vibrato2 = 0x050C;
- }
- } else {
- voiceDef->vibrato2 = 0;
- }
-
- if ((voice2[8] & 0x0F) > 1) {
- voiceDef->octadd = 0x01;
- } else {
- voiceDef->octadd = 0x00;
- }
- }
- }
-
- for (int i = 0; i < 8; ++i) {
- _cmsVoices[i].chanNumber = 0xFF;
- _cmsVoices[i].curVolume = 0;
- _cmsVoices[i].nextVoice = 0;
- }
-
- _midiDelay = 0;
- memset(_cmsChips, 0, sizeof(MusicChip)*2);
- _midiData = data + 151;
- _midiSongBegin = _midiData + data[9];
-
- _loadedMidiSong = sound;
-}
-
-int Player_V2CMS::getSoundStatus(int nr) const {
- return _current_nr == nr || _next_nr == nr || _loadedMidiSong == nr;
-}
-
-void Player_V2CMS::processMidiData() {
- byte *currentData = _midiData;
- byte command = 0x00;
- int16 temp = 0;
-
- ++_musicTimerTicks;
- if (_musicTimerTicks > 60) {
- _musicTimerTicks = 0;
- ++_musicTimer;
- }
-
- if (!_midiDelay) {
- while (true) {
- if ((command = *currentData++) == 0xFF) {
- if ((command = *currentData++) == 0x2F) {
- if (_looping == 0) {
- currentData = _midiData = _midiSongBegin;
- continue;
- }
- _midiData = _midiSongBegin = 0;
- _midiDelay = 0;
- _loadedMidiSong = 0;
- offAllChannels();
- return;
- } else {
- if (command == 0x58) {
- currentData += 6;
- }
- }
- } else {
- _lastMidiCommand = command;
- if (command < 0x90) {
- clearNote(currentData);
- } else {
- playNote(currentData);
- }
- }
-
- temp = command = *currentData++;
- if (command & 0x80) {
- temp = (command & 0x7F) << 8;
- command = *currentData++;
- temp |= (command << 1);
- temp >>= 1;
- }
- temp >>= 1;
- int lastBit = temp & 1;
- temp >>= 1;
- temp += lastBit;
-
- if (temp)
- break;
- }
- _midiData = currentData;
- _midiDelay = temp;
- }
-
- --_midiDelay;
- if (_midiDelay < 0)
- _midiDelay = 0;
-
- return;
-}
-
-int Player_V2CMS::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
-
- uint step = 1;
- int len = numSamples / 2;
-
- // maybe this needs a complete rewrite
- do {
- if (!(_next_tick >> FIXP_SHIFT)) {
- if (_midiData) {
- --_voiceTimer;
- if (!(_voiceTimer & 0x01))
- playVoice();
-
- int newTempoSum = _tempo + _tempoSum;
- _tempoSum = newTempoSum & 0xFF;
- if (newTempoSum > 0xFF)
- processMidiData();
- } else {
- nextTick();
- play();
- }
- _next_tick += _tick_len;
- }
-
- step = len;
- if (step > (_next_tick >> FIXP_SHIFT))
- step = (_next_tick >> FIXP_SHIFT);
- _cmsEmu->readBuffer(buffer, step);
- buffer += 2 * step;
- _next_tick -= step << FIXP_SHIFT;
- } while (len -= step);
-
- return numSamples;
-}
-
-void Player_V2CMS::playVoice() {
- if (_outputTableReady) {
- playMusicChips(_cmsChips);
- _outputTableReady = 0;
- }
-
- _octaveMask = 0xF0;
- Voice2 *voice = 0;
- for (int i = 0; i < 8; ++i) {
- voice = &_cmsVoices[i];
- _octaveMask = ~_octaveMask;
-
- if (voice->chanNumber != 0xFF) {
- processChannel(voice);
- } else {
- if (!voice->curVolume) {
- *(voice->amplitudeOutput) = 0;
- }
-
- int volume = voice->curVolume - voice->releaseRate;
- if (volume < 0)
- volume = 0;
-
- voice->curVolume = volume;
- *(voice->amplitudeOutput) = ((volume >> 4) | (volume & 0xF0)) & voice->channel;
- ++_outputTableReady;
- }
- }
-}
-
-void Player_V2CMS::processChannel(Voice2 *channel) {
- ++_outputTableReady;
- switch (channel->nextProcessState) {
- case Voice2::kEnvelopeAttack:
- processAttack(channel);
- break;
-
- case Voice2::kEnvelopeDecay:
- processDecay(channel);
- break;
-
- case Voice2::kEnvelopeSustain:
- processSustain(channel);
- break;
-
- case Voice2::kEnvelopeRelease:
- processRelease(channel);
- break;
- }
-}
-
-void Player_V2CMS::processRelease(Voice2 *channel) {
- int newVolume = channel->curVolume - channel->releaseRate;
- if (newVolume < 0)
- newVolume = 0;
-
- channel->curVolume = newVolume;
- processVibrato(channel);
-}
-
-void Player_V2CMS::processAttack(Voice2 *channel) {
- int newVolume = channel->curVolume + channel->attackRate;
- if (newVolume > channel->maxAmpl) {
- channel->curVolume = channel->maxAmpl;
- channel->nextProcessState = Voice2::kEnvelopeDecay;
- } else {
- channel->curVolume = newVolume;
- }
-
- processVibrato(channel);
-}
-
-void Player_V2CMS::processDecay(Voice2 *channel) {
- int newVolume = channel->curVolume - channel->decayRate;
- if (newVolume <= channel->sustainRate) {
- channel->curVolume = channel->sustainRate;
- channel->nextProcessState = Voice2::kEnvelopeSustain;
- } else {
- channel->curVolume = newVolume;
- }
-
- processVibrato(channel);
-}
-
-void Player_V2CMS::processSustain(Voice2 *channel) {
- if (channel->unkVibratoRate) {
- int16 volume = channel->curVolume + channel->unkRate;
- if (volume & 0xFF00) {
- volume = int8(volume >> 8);
- volume = -volume;
- }
-
- channel->curVolume = volume;
- --channel->unkCount;
- if (!channel->unkCount) {
- channel->unkRate = -channel->unkRate;
- channel->unkCount = (channel->unkVibratoDepth & 0x0F) << 1;
- }
- }
- processVibrato(channel);
-}
-
-void Player_V2CMS::processVibrato(Voice2 *channel) {
- if (channel->vibratoRate) {
- int16 temp = channel->curFreq + channel->curVibratoRate;
- channel->curOctave += (temp & 0xFF00) >> 8;
- channel->curFreq = temp & 0xFF;
-
- --channel->curVibratoUnk;
- if (!channel->curVibratoUnk) {
- channel->curVibratoRate = -channel->curVibratoRate;
- channel->curVibratoUnk = (channel->vibratoDepth & 0x0F) << 1;
- }
- }
-
- byte *output = channel->amplitudeOutput;
- *output = ((channel->curVolume >> 4) | (channel->curVolume & 0xF0)) & channel->channel;
- output = channel->freqOutput;
- *output = channel->curFreq;
- output = channel->octaveOutput;
- *output = (((channel->curOctave << 4) | (channel->curOctave & 0x0F)) & _octaveMask) | ((~_octaveMask) & *output);
-}
-
-void Player_V2CMS::offAllChannels() {
- for (int cmsPort = 0x220, i = 0; i < 2; cmsPort += 2, ++i) {
- for (int off = 1; off <= 10; ++off) {
- _cmsEmu->portWrite(cmsPort+1, _cmsInitData[off*2]);
- _cmsEmu->portWrite(cmsPort, _cmsInitData[off*2+1]);
- }
- }
-}
-
-Player_V2CMS::Voice2 *Player_V2CMS::getFreeVoice() {
- Voice2 *curVoice = 0;
- Voice2 *selected = 0;
- uint8 volume = 0xFF;
-
- for (int i = 0; i < 8; ++i) {
- curVoice = &_cmsVoices[i];
-
- if (curVoice->chanNumber == 0xFF) {
- if (!curVoice->curVolume) {
- selected = curVoice;
- break;
- }
-
- if (curVoice->curVolume < volume) {
- selected = curVoice;
- volume = selected->curVolume;
- }
- }
- }
-
- if (selected) {
- selected->chanNumber = _lastMidiCommand & 0x0F;
-
- uint8 channel = selected->chanNumber;
- Voice2 *oldChannel = _midiChannel[channel];
- _midiChannel[channel] = selected;
- selected->nextVoice = oldChannel;
- }
-
- return selected;
-}
-
-void Player_V2CMS::playNote(byte *&data) {
- byte channel = _lastMidiCommand & 0x0F;
- if (_midiChannelUse[channel]) {
- Voice2 *freeVoice = getFreeVoice();
- if (freeVoice) {
- Voice *voice = &_cmsVoicesBase[freeVoice->chanNumber];
- freeVoice->attackRate = voice->attack;
- freeVoice->decayRate = voice->decay;
- freeVoice->sustainRate = voice->sustain;
- freeVoice->releaseRate = voice->release;
- freeVoice->octaveAdd = voice->octadd;
- freeVoice->vibratoRate = freeVoice->curVibratoRate = voice->vibrato & 0xFF;
- freeVoice->vibratoDepth = freeVoice->curVibratoUnk = voice->vibrato >> 8;
- freeVoice->unkVibratoRate = freeVoice->unkRate = voice->vibrato2 & 0xFF;
- freeVoice->unkVibratoDepth = freeVoice->unkCount = voice->vibrato2 >> 8;
- freeVoice->maxAmpl = 0xFF;
-
- uint8 rate = freeVoice->attackRate;
- uint8 volume = freeVoice->curVolume >> 1;
-
- if (rate < volume)
- rate = volume;
-
- rate -= freeVoice->attackRate;
- freeVoice->curVolume = rate;
- freeVoice->playingNote = *data;
-
- int effectiveNote = freeVoice->playingNote + 3;
- if (effectiveNote < 0 || effectiveNote >= ARRAYSIZE(_midiNotes)) {
- warning("Player_V2CMS::playNote: Note %d out of bounds", effectiveNote);
- effectiveNote = CLIP<int>(effectiveNote, 0, ARRAYSIZE(_midiNotes) - 1);
- }
-
- int octave = _midiNotes[effectiveNote].baseOctave + freeVoice->octaveAdd - 3;
- if (octave < 0)
- octave = 0;
- if (octave > 7)
- octave = 7;
- if (!octave)
- ++octave;
- freeVoice->curOctave = octave;
- freeVoice->curFreq = _midiNotes[effectiveNote].frequency;
- freeVoice->curVolume = 0;
- freeVoice->nextProcessState = Voice2::kEnvelopeAttack;
- if (!(_lastMidiCommand & 1))
- freeVoice->channel = 0xF0;
- else
- freeVoice->channel = 0x0F;
- }
- }
- data += 2;
-}
-
-Player_V2CMS::Voice2 *Player_V2CMS::getPlayVoice(byte param) {
- byte channelNum = _lastMidiCommand & 0x0F;
- Voice2 *curVoice = _midiChannel[channelNum];
-
- if (curVoice) {
- Voice2 *prevVoice = 0;
- while (true) {
- if (curVoice->playingNote == param)
- break;
-
- prevVoice = curVoice;
- curVoice = curVoice->nextVoice;
- if (!curVoice)
- return 0;
- }
-
- if (prevVoice)
- prevVoice->nextVoice = curVoice->nextVoice;
- else
- _midiChannel[channelNum] = curVoice->nextVoice;
- }
-
- return curVoice;
-}
-
-void Player_V2CMS::clearNote(byte *&data) {
- Voice2 *voice = getPlayVoice(*data);
- if (voice) {
- voice->chanNumber = 0xFF;
- voice->nextVoice = 0;
- voice->nextProcessState = Voice2::kEnvelopeRelease;
- }
- data += 2;
-}
-
-void Player_V2CMS::play() {
- _octaveMask = 0xF0;
- channel_data *chan = &_channels[0].d;
-
- byte noiseGen = 3;
-
- for (int i = 1; i <= 4; ++i) {
- if (chan->time_left) {
- uint16 freq = chan->freq;
-
- if (i == 4) {
- if ((freq >> 8) & 0x40) {
- noiseGen = freq & 0xFF;
- } else {
- noiseGen = 3;
- _sfxFreq[0] = _sfxFreq[3];
- _sfxOctave[0] = (_sfxOctave[0] & 0xF0) | ((_sfxOctave[1] & 0xF0) >> 4);
- }
- } else {
- if (freq == 0) {
- freq = 0xFFC0;
- }
-
- int cmsOct = 2;
- int freqOct = 0x8000;
-
- while (true) {
- if (freq >= freqOct) {
- break;
- }
- freqOct >>= 1;
- ++cmsOct;
- if (cmsOct == 8) {
- --cmsOct;
- freq = 1024;
- break;
- }
- }
- byte oct = cmsOct << 4;
- oct |= cmsOct;
-
- oct &= _octaveMask;
- oct |= (~_octaveMask) & _sfxOctave[(i & 3) >> 1];
- _sfxOctave[(i & 3) >> 1] = oct;
-
- freq >>= -(cmsOct - 9);
- _sfxFreq[i & 3] = (-(freq - 511)) & 0xFF;
- }
- _sfxAmpl[i & 3] = _volumeTable[chan->volume >> 12];
- } else {
- _sfxAmpl[i & 3] = 0;
- }
-
- chan = &_channels[i].d;
- _octaveMask ^= 0xFF;
- }
-
- // with the high nibble of the volumeReg value
- // the right channels amplitude is set
- // with the low value the left channels amplitude
- _cmsEmu->portWrite(0x221, 0);
- _cmsEmu->portWrite(0x220, _sfxAmpl[0]);
- _cmsEmu->portWrite(0x221, 1);
- _cmsEmu->portWrite(0x220, _sfxAmpl[1]);
- _cmsEmu->portWrite(0x221, 2);
- _cmsEmu->portWrite(0x220, _sfxAmpl[2]);
- _cmsEmu->portWrite(0x221, 3);
- _cmsEmu->portWrite(0x220, _sfxAmpl[3]);
- _cmsEmu->portWrite(0x221, 8);
- _cmsEmu->portWrite(0x220, _sfxFreq[0]);
- _cmsEmu->portWrite(0x221, 9);
- _cmsEmu->portWrite(0x220, _sfxFreq[1]);
- _cmsEmu->portWrite(0x221, 10);
- _cmsEmu->portWrite(0x220, _sfxFreq[2]);
- _cmsEmu->portWrite(0x221, 11);
- _cmsEmu->portWrite(0x220, _sfxFreq[3]);
- _cmsEmu->portWrite(0x221, 0x10);
- _cmsEmu->portWrite(0x220, _sfxOctave[0]);
- _cmsEmu->portWrite(0x221, 0x11);
- _cmsEmu->portWrite(0x220, _sfxOctave[1]);
- _cmsEmu->portWrite(0x221, 0x14);
- _cmsEmu->portWrite(0x220, 0x3E);
- _cmsEmu->portWrite(0x221, 0x15);
- _cmsEmu->portWrite(0x220, 0x01);
- _cmsEmu->portWrite(0x221, 0x16);
- _cmsEmu->portWrite(0x220, noiseGen);
-}
-
-void Player_V2CMS::playMusicChips(const MusicChip *table) {
- int cmsPort = 0x21E;
-
- do {
- cmsPort += 2;
- _cmsEmu->portWrite(cmsPort+1, 0);
- _cmsEmu->portWrite(cmsPort, table->ampl[0]);
- _cmsEmu->portWrite(cmsPort+1, 1);
- _cmsEmu->portWrite(cmsPort, table->ampl[1]);
- _cmsEmu->portWrite(cmsPort+1, 2);
- _cmsEmu->portWrite(cmsPort, table->ampl[2]);
- _cmsEmu->portWrite(cmsPort+1, 3);
- _cmsEmu->portWrite(cmsPort, table->ampl[3]);
- _cmsEmu->portWrite(cmsPort+1, 8);
- _cmsEmu->portWrite(cmsPort, table->freq[0]);
- _cmsEmu->portWrite(cmsPort+1, 9);
- _cmsEmu->portWrite(cmsPort, table->freq[1]);
- _cmsEmu->portWrite(cmsPort+1, 10);
- _cmsEmu->portWrite(cmsPort, table->freq[2]);
- _cmsEmu->portWrite(cmsPort+1, 11);
- _cmsEmu->portWrite(cmsPort, table->freq[3]);
- _cmsEmu->portWrite(cmsPort+1, 0x10);
- _cmsEmu->portWrite(cmsPort, table->octave[0]);
- _cmsEmu->portWrite(cmsPort+1, 0x11);
- _cmsEmu->portWrite(cmsPort, table->octave[1]);
- _cmsEmu->portWrite(cmsPort+1, 0x14);
- _cmsEmu->portWrite(cmsPort, 0x3F);
- _cmsEmu->portWrite(cmsPort+1, 0x15);
- _cmsEmu->portWrite(cmsPort, 0x00);
- ++table;
- } while ((cmsPort & 2) == 0);
-}
-
-const Player_V2CMS::MidiNote Player_V2CMS::_midiNotes[132] = {
- { 3, 0 }, { 31, 0 }, { 58, 0 }, { 83, 0 },
- { 107, 0 }, { 130, 0 }, { 151, 0 }, { 172, 0 },
- { 191, 0 }, { 209, 0 }, { 226, 0 }, { 242, 0 },
- { 3, 1 }, { 31, 1 }, { 58, 1 }, { 83, 1 },
- { 107, 1 }, { 130, 1 }, { 151, 1 }, { 172, 1 },
- { 191, 1 }, { 209, 1 }, { 226, 1 }, { 242, 1 },
- { 3, 2 }, { 31, 2 }, { 58, 2 }, { 83, 2 },
- { 107, 2 }, { 130, 2 }, { 151, 2 }, { 172, 2 },
- { 191, 2 }, { 209, 2 }, { 226, 2 }, { 242, 2 },
- { 3, 3 }, { 31, 3 }, { 58, 3 }, { 83, 3 },
- { 107, 3 }, { 130, 3 }, { 151, 3 }, { 172, 3 },
- { 191, 3 }, { 209, 3 }, { 226, 3 }, { 242, 3 },
- { 3, 4 }, { 31, 4 }, { 58, 4 }, { 83, 4 },
- { 107, 4 }, { 130, 4 }, { 151, 4 }, { 172, 4 },
- { 191, 4 }, { 209, 4 }, { 226, 4 }, { 242, 4 },
- { 3, 5 }, { 31, 5 }, { 58, 5 }, { 83, 5 },
- { 107, 5 }, { 130, 5 }, { 151, 5 }, { 172, 5 },
- { 191, 5 }, { 209, 5 }, { 226, 5 }, { 242, 5 },
- { 3, 6 }, { 31, 6 }, { 58, 6 }, { 83, 6 },
- { 107, 6 }, { 130, 6 }, { 151, 6 }, { 172, 6 },
- { 191, 6 }, { 209, 6 }, { 226, 6 }, { 242, 6 },
- { 3, 7 }, { 31, 7 }, { 58, 7 }, { 83, 7 },
- { 107, 7 }, { 130, 7 }, { 151, 7 }, { 172, 7 },
- { 191, 7 }, { 209, 7 }, { 226, 7 }, { 242, 7 },
- { 3, 8 }, { 31, 8 }, { 58, 8 }, { 83, 8 },
- { 107, 8 }, { 130, 8 }, { 151, 8 }, { 172, 8 },
- { 191, 8 }, { 209, 8 }, { 226, 8 }, { 242, 8 },
- { 3, 9 }, { 31, 9 }, { 58, 9 }, { 83, 9 },
- { 107, 9 }, { 130, 9 }, { 151, 9 }, { 172, 9 },
- { 191, 9 }, { 209, 9 }, { 226, 9 }, { 242, 9 },
- { 3, 10 }, { 31, 10 }, { 58, 10 }, { 83, 10 },
- { 107, 10 }, { 130, 10 }, { 151, 10 }, { 172, 10 },
- { 191, 10 }, { 209, 10 }, { 226, 10 }, { 242, 10 }
-};
-
-const byte Player_V2CMS::_attackRate[16] = {
- 0, 2, 4, 7, 14, 26, 48, 82,
- 128, 144, 160, 176, 192, 208, 224, 255
-};
-
-const byte Player_V2CMS::_decayRate[16] = {
- 0, 1, 2, 3, 4, 6, 12, 24,
- 48, 96, 192, 215, 255, 255, 255, 255
-};
-
-const byte Player_V2CMS::_sustainRate[16] = {
- 255, 180, 128, 96, 80, 64, 56, 48,
- 42, 36, 32, 28, 24, 20, 16, 0
-};
-
-const byte Player_V2CMS::_releaseRate[16] = {
- 0, 1, 2, 4, 6, 9, 14, 22,
- 36, 56, 80, 100, 120, 140, 160, 255
-};
-
-const byte Player_V2CMS::_volumeTable[16] = {
- 0x00, 0x10, 0x10, 0x11, 0x11, 0x21, 0x22, 0x22,
- 0x33, 0x44, 0x55, 0x66, 0x88, 0xAA, 0xCC, 0xFF
-};
-
-const byte Player_V2CMS::_cmsInitData[26] = {
- 0x1C, 0x02,
- 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
- 0x14, 0x3F, 0x15, 0x00, 0x16, 0x00, 0x18, 0x00, 0x19, 0x00, 0x1C, 0x01
-};
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v2cms.h b/engines/scumm/player/v2cms.h
deleted file mode 100644
index d022a64a5f..0000000000
--- a/engines/scumm/player/v2cms.h
+++ /dev/null
@@ -1,177 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V2CMS_H
-#define SCUMM_PLAYER_V2CMS_H
-
-#include "scumm/player/v2base.h" // for channel_data
-
-class CMSEmulator;
-
-namespace Scumm {
-
-/**
- * Scumm V2 CMS/Gameblaster MIDI driver.
- */
-class Player_V2CMS : public Player_V2Base {
-public:
- Player_V2CMS(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_V2CMS();
-
- // MusicEngine API
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getMusicTimer();
- virtual int getSoundStatus(int sound) const;
-
- // AudioStream API
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo() const { return true; }
-
-private:
- struct Voice {
- byte attack;
- byte decay;
- byte sustain;
- byte release;
- byte octadd;
- int16 vibrato;
- int16 vibrato2;
- int16 noise;
- };
-
- struct Voice2 {
- byte *amplitudeOutput;
- byte *freqOutput;
- byte *octaveOutput;
-
- uint8 channel;
- int8 sustainLevel;
- uint8 attackRate;
- uint8 maxAmpl;
- uint8 decayRate;
- uint8 sustainRate;
- uint8 releaseRate;
- uint8 releaseTime;
- int8 vibratoRate;
- int8 vibratoDepth;
-
- int8 curVibratoRate;
- int8 curVibratoUnk;
-
- int8 unkVibratoRate;
- int8 unkVibratoDepth;
-
- int8 unkRate;
- int8 unkCount;
-
- enum EnvelopeState {
- kEnvelopeAttack,
- kEnvelopeDecay,
- kEnvelopeSustain,
- kEnvelopeRelease
- };
-
- EnvelopeState nextProcessState;
- uint8 curVolume;
- uint8 curOctave;
- uint8 curFreq;
-
- int8 octaveAdd;
-
- int8 playingNote;
- Voice2 *nextVoice;
-
- byte chanNumber;
- };
-
- struct MusicChip {
- byte ampl[4];
- byte freq[4];
- byte octave[2];
- };
-
- Voice _cmsVoicesBase[16];
- Voice2 _cmsVoices[8];
- MusicChip _cmsChips[2];
-
- uint8 _tempo;
- uint8 _tempoSum;
- byte _looping;
- byte _octaveMask;
- int16 _midiDelay;
- Voice2 *_midiChannel[16];
- byte _midiChannelUse[16];
- byte *_midiData;
- byte *_midiSongBegin;
-
- int _loadedMidiSong;
-
- byte _sfxFreq[4], _sfxAmpl[4], _sfxOctave[2];
-
- byte _lastMidiCommand;
- uint _outputTableReady;
- byte _voiceTimer;
-
- int _musicTimer, _musicTimerTicks;
-
- void loadMidiData(byte *data, int sound);
- void play();
-
- void processChannel(Voice2 *channel);
- void processRelease(Voice2 *channel);
- void processAttack(Voice2 *channel);
- void processDecay(Voice2 *channel);
- void processSustain(Voice2 *channel);
- void processVibrato(Voice2 *channel);
-
- void playMusicChips(const MusicChip *table);
- void playNote(byte *&data);
- void clearNote(byte *&data);
- void offAllChannels();
- void playVoice();
- void processMidiData();
-
- Voice2 *getFreeVoice();
- Voice2 *getPlayVoice(byte param);
-
- struct MidiNote {
- byte frequency;
- byte baseOctave;
- };
-
- static const MidiNote _midiNotes[132];
- static const byte _attackRate[16];
- static const byte _decayRate[16];
- static const byte _sustainRate[16];
- static const byte _releaseRate[16];
- static const byte _volumeTable[16];
- static const byte _cmsInitData[26];
-
- CMSEmulator *_cmsEmu;
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v3a.cpp b/engines/scumm/player/v3a.cpp
deleted file mode 100644
index b91bd49e6e..0000000000
--- a/engines/scumm/player/v3a.cpp
+++ /dev/null
@@ -1,357 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-
-#include "engines/engine.h"
-#include "scumm/player/v3a.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-static const uint16 note_freqs[4][12] = {
- {0x06B0, 0x0650, 0x05F4, 0x05A0, 0x054C, 0x0500, 0x04B8, 0x0474, 0x0434, 0x03F8, 0x03C0, 0x0388},
- {0x0358, 0x0328, 0x02FA, 0x02D0, 0x02A6, 0x0280, 0x025C, 0x023A, 0x021A, 0x01FC, 0x01E0, 0x01C4},
- {0x01AC, 0x0194, 0x017D, 0x0168, 0x0153, 0x0140, 0x012E, 0x011D, 0x010D, 0x00FE, 0x00F0, 0x00E2},
- {0x00D6, 0x00CA, 0x00BE, 0x00B4, 0x00A9, 0x00A0, 0x0097, 0x008E, 0x0086, 0x007F, 0x00F0, 0x00E2}
-};
-
-Player_V3A::Player_V3A(ScummEngine *scumm, Audio::Mixer *mixer) {
- int i;
- _vm = scumm;
- for (i = 0; i < V3A_MAXMUS; i++) {
- _mus[i].id = 0;
- _mus[i].dur = 0;
- }
- for (i = 0; i < V3A_MAXSFX; i++) {
- _sfx[i].id = 0;
- _sfx[i].dur = 0;
- }
-
- _curSong = 0;
- _songData = NULL;
- _songPtr = 0;
- _songDelay = 0;
-
- _music_timer = 0;
-
- _isinit = false;
-
- _mod = new Player_MOD(mixer);
- _mod->setUpdateProc(update_proc, this, 60);
-}
-
-Player_V3A::~Player_V3A() {
- int i;
- delete _mod;
- if (_isinit) {
- for (i = 0; _wavetable[i] != NULL; i++) {
- for (int j = 0; j < 6; j++) {
- free(_wavetable[i]->_idat[j]);
- free(_wavetable[i]->_ldat[j]);
- }
- free(_wavetable[i]);
- }
- free(_wavetable);
- }
-}
-
-void Player_V3A::setMusicVolume (int vol) {
- _mod->setMusicVolume(vol);
-}
-
-int Player_V3A::getMusChan (int id) const {
- int i;
- for (i = 0; i < V3A_MAXMUS; i++) {
- if (_mus[i].id == id)
- break;
- }
- if (i == V3A_MAXMUS) {
- if (id == 0)
- warning("player_v3a - out of music channels");
- return -1;
- }
- return i;
-}
-int Player_V3A::getSfxChan (int id) const {
- int i;
- for (i = 0; i < V3A_MAXSFX; i++) {
- if (_sfx[i].id == id)
- break;
- }
- if (i == V3A_MAXSFX) {
- if (id == 0)
- warning("player_v3a - out of sfx channels");
- return -1;
- }
- return i;
-}
-
-void Player_V3A::stopAllSounds() {
- int i;
- for (i = 0; i < V3A_MAXMUS; i++) {
- if (_mus[i].id)
- _mod->stopChannel(_mus[i].id);
- _mus[i].id = 0;
- _mus[i].dur = 0;
- }
- _curSong = 0;
- _songPtr = 0;
- _songDelay = 0;
- _songData = NULL;
- for (i = 0; i < V3A_MAXSFX; i++) {
- if (_sfx[i].id)
- _mod->stopChannel(_sfx[i].id | 0x100);
- _sfx[i].id = 0;
- _sfx[i].dur = 0;
- }
-}
-
-void Player_V3A::stopSound(int nr) {
- int i;
- if (nr == 0) { // Amiga Loom does this near the end, when Chaos casts SILENCE on Hetchel
- stopAllSounds();
- return;
- }
- if (nr == _curSong) {
- for (i = 0; i < V3A_MAXMUS; i++) {
- if (_mus[i].id)
- _mod->stopChannel(_mus[i].id);
- _mus[i].id = 0;
- _mus[i].dur = 0;
- }
- _curSong = 0;
- _songPtr = 0;
- _songDelay = 0;
- _songData = NULL;
- } else {
- i = getSfxChan(nr);
- if (i != -1) {
- _mod->stopChannel(nr | 0x100);
- _sfx[i].id = 0;
- _sfx[i].dur = 0;
- }
- }
-}
-
-void Player_V3A::startSound(int nr) {
- assert(_vm);
- byte *data = _vm->getResourceAddress(rtSound, nr);
- assert(data);
-
- if ((_vm->_game.id != GID_INDY3) && (_vm->_game.id != GID_LOOM))
- error("player_v3a - unknown game");
-
- if (!_isinit) {
- int i;
- unsigned char *ptr;
- int offset = 4;
- int numInstruments;
-
- if (_vm->_game.id == GID_INDY3) {
- ptr = _vm->getResourceAddress(rtSound, 83);
- numInstruments = 12;
- } else {
- ptr = _vm->getResourceAddress(rtSound, 79);
- numInstruments = 9;
- }
- assert(ptr);
- _wavetable = (instData **)malloc((numInstruments + 1) * sizeof(void *));
- for (i = 0; i < numInstruments; i++) {
- _wavetable[i] = (instData *)malloc(sizeof(instData));
- for (int j = 0; j < 6; j++) {
- int off, len;
- off = READ_BE_UINT16(ptr + offset + 0);
- _wavetable[i]->_ilen[j] = len = READ_BE_UINT16(ptr + offset + 2);
- if (len) {
- _wavetable[i]->_idat[j] = (char *)malloc(len);
- memcpy(_wavetable[i]->_idat[j],ptr + off,len);
- } else _wavetable[i]->_idat[j] = NULL;
- off = READ_BE_UINT16(ptr + offset + 4);
- _wavetable[i]->_llen[j] = len = READ_BE_UINT16(ptr + offset + 6);
- if (len) {
- _wavetable[i]->_ldat[j] = (char *)malloc(len);
- memcpy(_wavetable[i]->_ldat[j],ptr + off,len);
- } else _wavetable[i]->_ldat[j] = NULL;
- _wavetable[i]->_oct[j] = READ_BE_UINT16(ptr + offset + 8);
- offset += 10;
- }
- if (_vm->_game.id == GID_INDY3) {
- _wavetable[i]->_pitadjust = 0;
- offset += 2;
- } else {
- _wavetable[i]->_pitadjust = READ_BE_UINT16(ptr + offset + 2);
- offset += 4;
- }
- }
- _wavetable[i] = NULL;
- _isinit = true;
- }
-
- if (getSoundStatus(nr))
- stopSound(nr); // if a sound is playing, restart it
-
- if (data[26]) {
- if (_curSong)
- stopSound(_curSong);
- _curSong = nr;
- _songData = data;
- _songPtr = 0x1C;
- _songDelay = 1;
- _music_timer = 0;
- } else {
- int size = READ_BE_UINT16(data + 12);
- int rate = 3579545 / READ_BE_UINT16(data + 20);
- char *sound = (char *)malloc(size);
- int vol = (data[24] << 1) | (data[24] >> 5); // if I boost this to 0-255, it gets too loud and starts to clip
- memcpy(sound, data + READ_BE_UINT16(data + 8), size);
- int loopStart = 0, loopEnd = 0;
- int loopcount = data[27];
- if (loopcount > 1) {
- loopStart = READ_BE_UINT16(data + 10) - READ_BE_UINT16(data + 8);
- loopEnd = READ_BE_UINT16(data + 14);
- }
- int i = getSfxChan();
- if (i == -1) {
- free(sound);
- return;
- }
- _sfx[i].id = nr;
- _sfx[i].dur = 1 + loopcount * 60 * size / rate;
- if (READ_BE_UINT16(data + 16)) {
- _sfx[i].rate = READ_BE_UINT16(data + 20) << 16;
- _sfx[i].delta = (int32)READ_BE_UINT32(data + 32);
- _sfx[i].dur = READ_BE_UINT32(data + 40);
- } else {
- _sfx[i].delta = 0;
- }
- _mod->startChannel(nr | 0x100, sound, size, rate, vol, loopStart, loopEnd);
- }
-}
-
-void Player_V3A::update_proc(void *param) {
- ((Player_V3A *)param)->playMusic();
-}
-
-void Player_V3A::playMusic() {
- int i;
- for (i = 0; i < V3A_MAXMUS; i++) {
- if (_mus[i].id) {
- _mus[i].dur--;
- if (_mus[i].dur)
- continue;
- _mod->stopChannel(_mus[i].id);
- _mus[i].id = 0;
- }
- }
- for (i = 0; i < V3A_MAXSFX; i++) {
- if (_sfx[i].id) {
- if (_sfx[i].delta) {
- uint16 oldrate = _sfx[i].rate >> 16;
- _sfx[i].rate += _sfx[i].delta;
- if (_sfx[i].rate < (55 << 16))
- _sfx[i].rate = 55 << 16; // at rates below 55, frequency
- uint16 newrate = _sfx[i].rate >> 16; // exceeds 65536, which is bad
- if (oldrate != newrate)
- _mod->setChannelFreq(_sfx[i].id | 0x100, 3579545 / newrate);
- }
- _sfx[i].dur--;
- if (_sfx[i].dur)
- continue;
- _mod->stopChannel(_sfx[i].id | 0x100);
- _sfx[i].id = 0;
- }
- }
-
- _music_timer++;
- if (!_curSong)
- return;
- if (_songDelay && --_songDelay)
- return;
- if (_songPtr == 0) {
- // at the end of the song, and it wasn't looped - kill it
- _curSong = 0;
- return;
- }
- while (1) {
- int inst, pit, vol, dur, oct;
- inst = _songData[_songPtr++];
- if ((inst & 0xF0) != 0x80) {
- // tune is at the end - figure out what's still playing
- // and see how long we have to wait until we stop/restart
- for (i = 0; i < V3A_MAXMUS; i++) {
- if (_songDelay < _mus[i].dur)
- _songDelay = _mus[i].dur;
- }
- if (inst == 0xFB) // it's a looped song, restart it afterwards
- _songPtr = 0x1C;
- else _songPtr = 0; // otherwise, terminate it
- break;
- }
- inst &= 0xF;
- pit = _songData[_songPtr++];
- vol = _songData[_songPtr++] & 0x7F; // if I boost this to 0-255, it gets too loud and starts to clip
- dur = _songData[_songPtr++];
- if (pit == 0) {
- _songDelay = dur;
- break;
- }
- pit += _wavetable[inst]->_pitadjust;
- oct = (pit / 12) - 2;
- pit = pit % 12;
- if (oct < 0)
- oct = 0;
- if (oct > 5)
- oct = 5;
- int rate = 3579545 / note_freqs[_wavetable[inst]->_oct[oct]][pit];
- if (!_wavetable[inst]->_llen[oct])
- dur = _wavetable[inst]->_ilen[oct] * 60 / rate;
- char *data = (char *)malloc(_wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct]);
- if (_wavetable[inst]->_idat[oct])
- memcpy(data, _wavetable[inst]->_idat[oct], _wavetable[inst]->_ilen[oct]);
- if (_wavetable[inst]->_ldat[oct])
- memcpy(data + _wavetable[inst]->_ilen[oct], _wavetable[inst]->_ldat[oct], _wavetable[inst]->_llen[oct]);
-
- i = getMusChan();
- if (i == -1) {
- free(data);
- return;
- }
- _mus[i].id = i + 1;
- _mus[i].dur = dur + 1;
- _mod->startChannel(_mus[i].id, data, _wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct], rate, vol,
- _wavetable[inst]->_ilen[oct], _wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct]);
- }
-}
-
-int Player_V3A::getMusicTimer() {
- return _music_timer / 30;
-}
-
-int Player_V3A::getSoundStatus(int nr) const {
- if (nr == _curSong)
- return 1;
- if (getSfxChan(nr) != -1)
- return 1;
- return 0;
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v3a.h b/engines/scumm/player/v3a.h
deleted file mode 100644
index 0869c3398c..0000000000
--- a/engines/scumm/player/v3a.h
+++ /dev/null
@@ -1,101 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V3A_H
-#define SCUMM_PLAYER_V3A_H
-
-#include "common/scummsys.h"
-#include "scumm/music.h"
-#include "scumm/player/mod.h"
-
-class Mixer;
-
-namespace Scumm {
-
-class ScummEngine;
-
-/**
- * Scumm V3 Amiga sound/music driver.
- */
-class Player_V3A : public MusicEngine {
-public:
- Player_V3A(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_V3A();
-
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getMusicTimer();
- virtual int getSoundStatus(int sound) const;
-
-private:
- enum {
- V3A_MAXMUS = 24,
- V3A_MAXSFX = 16
- };
-
- struct musChan {
- int id;
- int dur;
- };
-
- struct sfxChan {
- int id;
- int dur;
- uint32 rate;
- int32 delta;
- };
-
- struct instData {
- char *_idat[6];
- uint16 _ilen[6];
- char *_ldat[6];
- uint16 _llen[6];
- uint16 _oct[6];
- int16 _pitadjust;
- };
-
- ScummEngine *_vm;
- Player_MOD *_mod;
-
- musChan _mus[V3A_MAXMUS];
- sfxChan _sfx[V3A_MAXSFX];
-
- int _curSong;
- uint8 *_songData;
- uint16 _songPtr;
- uint16 _songDelay;
- int _music_timer;
- bool _isinit;
-
- instData **_wavetable;
-
- int getMusChan (int id = 0) const;
- int getSfxChan (int id = 0) const;
- static void update_proc(void *param);
- void playMusic();
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v3m.cpp b/engines/scumm/player/v3m.cpp
deleted file mode 100644
index b910b36a18..0000000000
--- a/engines/scumm/player/v3m.cpp
+++ /dev/null
@@ -1,214 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-/*
- We have the following information from Lars Christensen (lechimp) and
- Jamieson Christian (jamieson630):
-
- RESOURCE DATA
- LE 2 bytes Resource size
- 2 bytes Unknown
- 2 bytes 'so'
- 14 bytes Unknown
- BE 2 bytes Instrument for Stream 1
- BE 2 bytes Instrument for Stream 2
- BE 2 bytes Instrument for Stream 3
- BE 2 bytes Instrument for Stream 4
- BE 2 bytes Instrument for Stream 5
- BE 2 bytes Offset to Stream 1
- BE 2 bytes Offset to Stream 2
- BE 2 bytes Offset to Stream 3
- BE 2 bytes Offset to Stream 4
- BE 2 bytes Offset to Stream 5
- ? bytes The streams
-
- STREAM DATA
- BE 2 bytes Unknown (always 1?)
- 2 bytes Unknown (always 0?)
- BE 2 bytes Number of events in stream
- ? bytes Stream data
-
- Each stream event is exactly 3 bytes, therefore one can
- assert that numEvents == (streamSize - 6) / 3. The
- polyphony of a stream appears to be 1; in other words, only
- one note at a time can be playing in each stream. The next
- event is not executed until the current note (or rest) is
- finished playing; therefore, note duration also serves as the
- time delta between events.
-
- FOR EACH EVENTS
- BE 2 bytes Note duration
- 1 byte Note number to play (0 = rest/silent)
-
- Oh, and quick speculation -- Stream 1 may be used for a
- single-voice interleaved version of the music, where Stream 2-
- 5 represent a version of the music in up to 4-voice
- polyphony, one voice per stream. I postulate thus because
- the first stream of the Mac Loom theme music contains
- interleaved voices, whereas the second stream seemed to
- contain only the pizzicato bottom-end harp. Stream 5, in this
- example, is empty, so if my speculation is correct, this
- particular musical number supports 3-voice polyphony at
- most. I must check out Streams 3 and 4 to see what they
- contain.
-
- ==========
-
- The instruments appear to be identified by their resource IDs:
-
- 1000 Dual Harp
- 10895 harp1
- 11445 strings1
- 11548 silent
- 13811 staff1
- 15703 brass1
- 16324 flute1
- 25614 accordian 1
- 28110 f horn1
- 29042 bassoon1
-*/
-
-#include "common/macresman.h"
-#include "common/translation.h"
-#include "engines/engine.h"
-#include "gui/message.h"
-#include "scumm/player/v3m.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-Player_V3M::Player_V3M(ScummEngine *scumm, Audio::Mixer *mixer)
- : Player_Mac(scumm, mixer, 5, 0x1E, true) {
- assert(_vm->_game.id == GID_LOOM);
-
- // Channel 0 seems to be what was played on low-end macs, that couldn't
- // handle multi-channel music and play the game at the same time. I'm
- // not sure if stream 4 is ever used, but let's use it just in case.
-}
-
-// \xAA is a trademark glyph in Mac OS Roman. We try that, but also the Windows
-// version, the UTF-8 version, and just plain without in case the file system
-// can't handle exotic characters like that.
-
-static const char *loomFileNames[] = {
- "Loom\xAA",
- "Loom\x99",
- "Loom\xE2\x84\xA2",
- "Loom"
-};
-
-bool Player_V3M::checkMusicAvailable() {
- Common::MacResManager resource;
-
- for (int i = 0; i < ARRAYSIZE(loomFileNames); i++) {
- if (resource.exists(loomFileNames[i])) {
- return true;
- }
- }
-
- GUI::MessageDialog dialog(_(
- "Could not find the 'Loom' Macintosh executable to read the\n"
- "instruments from. Music will be disabled."), _("OK"));
- dialog.runModal();
- return false;
-}
-
-bool Player_V3M::loadMusic(const byte *ptr) {
- Common::MacResManager resource;
- bool found = false;
-
- for (int i = 0; i < ARRAYSIZE(loomFileNames); i++) {
- if (resource.open(loomFileNames[i])) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- return false;
- }
-
- if (ptr[4] != 's' || ptr[5] != 'o') {
- // Like the original we ignore all sound resources which do not have
- // a 'so' tag in them.
- // See bug #3602239 ("Mac Loom crashes using opening spell on
- // gravestone") for a case where this is required. Loom Mac tries to
- // play resource 11 here. This resource is no Mac sound resource
- // though, it is a PC Speaker resource. A test with the original
- // interpreter also has shown that no sound is played while the
- // screen is shaking.
- debug(5, "Player_V3M::loadMusic: Skipping unknown music type %02X%02X", ptr[4], ptr[5]);
- resource.close();
- return false;
- }
-
- uint i;
- for (i = 0; i < 5; i++) {
- int instrument = READ_BE_UINT16(ptr + 20 + 2 * i);
- int offset = READ_BE_UINT16(ptr + 30 + 2 * i);
-
- _channel[i]._looped = false;
- _channel[i]._length = READ_BE_UINT16(ptr + offset + 4) * 3;
- _channel[i]._data = ptr + offset + 6;
- _channel[i]._pos = 0;
- _channel[i]._pitchModifier = 0;
- _channel[i]._velocity = 0;
- _channel[i]._remaining = 0;
- _channel[i]._notesLeft = true;
-
- Common::SeekableReadStream *stream = resource.getResource(RES_SND, instrument);
- if (_channel[i].loadInstrument(stream)) {
- debug(6, "Player_V3M::loadMusic: Channel %d - Loaded Instrument %d (%s)", i, instrument, resource.getResName(RES_SND, instrument).c_str());
- } else {
- resource.close();
- return false;
- }
- }
-
- resource.close();
- return true;
-}
-
-bool Player_V3M::getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity) {
- _channel[ch]._instrument.newNote();
- if (_channel[ch]._pos >= _channel[ch]._length) {
- if (!_channel[ch]._looped) {
- _channel[ch]._notesLeft = false;
- return false;
- }
- _channel[ch]._pos = 0;
- }
- uint16 duration = READ_BE_UINT16(&_channel[ch]._data[_channel[ch]._pos]);
- byte note = _channel[ch]._data[_channel[ch]._pos + 2];
- samples = durationToSamples(duration);
- if (note > 0) {
- pitchModifier = noteToPitchModifier(note, &_channel[ch]._instrument);
- velocity = 127;
- } else {
- pitchModifier = 0;
- velocity = 0;
- }
- _channel[ch]._pos += 3;
- return true;
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v3m.h b/engines/scumm/player/v3m.h
deleted file mode 100644
index 609ab8a9d7..0000000000
--- a/engines/scumm/player/v3m.h
+++ /dev/null
@@ -1,54 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V3M_H
-#define SCUMM_PLAYER_V3M_H
-
-#include "common/scummsys.h"
-#include "common/util.h"
-#include "common/mutex.h"
-#include "scumm/music.h"
-#include "scumm/player/mac.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-class Mixer;
-
-namespace Scumm {
-
-class ScummEngine;
-
-/**
- * Scumm V3 Macintosh music driver.
- */
-class Player_V3M : public Player_Mac {
-public:
- Player_V3M(ScummEngine *scumm, Audio::Mixer *mixer);
-
- virtual bool checkMusicAvailable();
- virtual bool loadMusic(const byte *ptr);
- virtual bool getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity);
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v4a.cpp b/engines/scumm/player/v4a.cpp
deleted file mode 100644
index de1301ee4c..0000000000
--- a/engines/scumm/player/v4a.cpp
+++ /dev/null
@@ -1,190 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "engines/engine.h"
-#include "scumm/player/v4a.h"
-#include "scumm/scumm.h"
-
-#include "common/file.h"
-
-namespace Scumm {
-
-Player_V4A::Player_V4A(ScummEngine *scumm, Audio::Mixer *mixer)
- : _vm(scumm),
- _mixer(mixer),
- _tfmxMusic(_mixer->getOutputRate(), true),
- _tfmxSfx(_mixer->getOutputRate(), true),
- _musicHandle(),
- _sfxHandle(),
- _musicId(),
- _sfxSlots(),
- _initState(0),
- _signal(0) {
-
- assert(scumm);
- assert(mixer);
- assert(_vm->_game.id == GID_MONKEY_VGA);
- _tfmxMusic.setSignalPtr(&_signal, 1);
-}
-
-bool Player_V4A::init() {
- if (_vm->_game.id != GID_MONKEY_VGA)
- error("player_v4a - unknown game");
-
- Common::File fileMdat, fileSample;
-
- if (fileMdat.open("music.dat") && fileSample.open("sample.dat")) {
- // explicitly request that no instance delets the resources automatically
- if (_tfmxMusic.load(fileMdat, fileSample, false)) {
- _tfmxSfx.setModuleData(_tfmxMusic);
- return true;
- }
- } else
- warning("player_v4a: couldnt load one of the music resources: music.dat, sample.dat");
-
- return false;
-}
-
-Player_V4A::~Player_V4A() {
- _mixer->stopHandle(_musicHandle);
- _mixer->stopHandle(_sfxHandle);
- _tfmxMusic.freeResources();
-}
-
-void Player_V4A::setMusicVolume(int vol) {
- debug(5, "player_v4a: setMusicVolume %i", vol);
-}
-
-void Player_V4A::stopAllSounds() {
- debug(5, "player_v4a: stopAllSounds");
- if (_initState > 0) {
- _tfmxMusic.stopSong();
- _signal = 0;
- _musicId = 0;
-
- _tfmxSfx.stopSong();
- clearSfxSlots();
- } else
- _mixer->stopHandle(_musicHandle);
-}
-
-void Player_V4A::stopSound(int nr) {
- debug(5, "player_v4a: stopSound %d", nr);
- if (nr == 0)
- return;
- if (nr == _musicId) {
- _musicId = 0;
- if (_initState > 0)
- _tfmxMusic.stopSong();
- else
- _mixer->stopHandle(_musicHandle);
- _signal = 0;
- } else {
- const int chan = getSfxChan(nr);
- if (chan != -1) {
- setSfxSlot(chan, 0);
- _tfmxSfx.stopMacroEffect(chan);
- }
- }
-}
-
-void Player_V4A::startSound(int nr) {
- static const int8 monkeyCommands[52] = {
- -1, -2, -3, -4, -5, -6, -7, -8,
- -9, -10, -11, -12, -13, -14, 18, 17,
- -17, -18, -19, -20, -21, -22, -23, -24,
- -25, -26, -27, -28, -29, -30, -31, -32,
- -33, 16, -35, 0, 1, 2, 3, 7,
- 8, 10, 11, 4, 5, 14, 15, 12,
- 6, 13, 9, 19
- };
-
- const byte *ptr = _vm->getResourceAddress(rtSound, nr);
- assert(ptr);
-
- const int val = ptr[9];
- if (val < 0 || val >= ARRAYSIZE(monkeyCommands)) {
- warning("player_v4a: illegal Songnumber %i", val);
- return;
- }
-
- if (!_initState)
- _initState = init() ? 1 : -1;
-
- if (_initState < 0)
- return;
-
- int index = monkeyCommands[val];
- const byte type = ptr[6];
- if (index < 0) { // SoundFX
- index = -index - 1;
- debug(3, "player_v4a: play %d: custom %i - %02X", nr, index, type);
-
- // start an empty Song so timing is setup
- if (_tfmxSfx.getSongIndex() < 0)
- _tfmxSfx.doSong(0x18);
-
- const int chan = _tfmxSfx.doSfx((uint16)index);
- if (chan >= 0 && chan < ARRAYSIZE(_sfxSlots))
- setSfxSlot(chan, nr, type);
- else
- warning("player_v4a: custom %i is not of required type", index);
-
- // the Tfmx-player never "ends" the output by itself, so this should be threadsafe
- if (!_mixer->isSoundHandleActive(_sfxHandle))
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, &_tfmxSfx, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
-
- } else { // Song
- debug(3, "player_v4a: play %d: song %i - %02X", nr, index, type);
- if (ptr[6] != 0x7F)
- warning("player_v4a: Song has wrong type");
-
- _tfmxMusic.doSong(index);
- _signal = 2;
-
- // the Tfmx-player never "ends" the output by itself, so this should be threadsafe
- if (!_mixer->isSoundHandleActive(_musicHandle))
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, &_tfmxMusic, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
- _musicId = nr;
- }
-}
-
-int Player_V4A::getMusicTimer() {
- // A workaround if the modplayer couldnt load the datafiles - just return a number big enough to pass all tests
- if (_initState < 0)
- return 2000;
- if (_musicId) {
- // The titlesong (and a few others) is running with ~70 ticks per second and the scale seems to be based on that.
- // The Game itself doesnt get the timing from the Tfmx Player however, so we just use the elapsed time
- // 357 ~ 1000 * 25 * (1 / 70)
- return _mixer->getSoundElapsedTime(_musicHandle) / 357;
- }
- return 0;
-}
-
-int Player_V4A::getSoundStatus(int nr) const {
- // For music the game queues a variable the Tfmx Player sets through a special command.
- // For sfx there seems to be no way to queue them, and the game doesnt try to.
- return (nr == _musicId) ? _signal : 0;
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v4a.h b/engines/scumm/player/v4a.h
deleted file mode 100644
index d01c70f295..0000000000
--- a/engines/scumm/player/v4a.h
+++ /dev/null
@@ -1,96 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V4A_H
-#define SCUMM_PLAYER_V4A_H
-
-#include "common/scummsys.h"
-#include "common/util.h"
-#include "scumm/music.h"
-#include "audio/mixer.h"
-#include "audio/mods/tfmx.h"
-
-class Mixer;
-
-namespace Scumm {
-
-class ScummEngine;
-
-/**
- * Scumm V4 Amiga sound/music driver.
- */
-class Player_V4A : public MusicEngine {
-public:
- Player_V4A(ScummEngine *scumm, Audio::Mixer *mixer);
- virtual ~Player_V4A();
-
- virtual void setMusicVolume(int vol);
- virtual void startSound(int sound);
- virtual void stopSound(int sound);
- virtual void stopAllSounds();
- virtual int getMusicTimer();
- virtual int getSoundStatus(int sound) const;
-
-private:
- ScummEngine *const _vm;
- Audio::Mixer *const _mixer;
-
- Audio::Tfmx _tfmxMusic;
- Audio::Tfmx _tfmxSfx;
- Audio::SoundHandle _musicHandle;
- Audio::SoundHandle _sfxHandle;
-
- int _musicId;
- uint16 _signal;
-
- struct SfxChan {
- int id;
-// byte type;
- } _sfxSlots[4];
-
- int8 _initState; // < 0: failed, 0: uninitialized, > 0: initialized
-
- int getSfxChan(int id) const {
- for (int i = 0; i < ARRAYSIZE(_sfxSlots); ++i)
- if (_sfxSlots[i].id == id)
- return i;
- return -1;
- }
-
- void setSfxSlot(int channel, int id, byte type = 0) {
- _sfxSlots[channel].id = id;
-// _sfxSlots[channel].type = type;
- }
-
- void clearSfxSlots() {
- for (int i = 0; i < ARRAYSIZE(_sfxSlots); ++i){
- _sfxSlots[i].id = 0;
-// _sfxSlots[i].type = 0;
- }
- }
-
- bool init();
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/engines/scumm/player/v5m.cpp b/engines/scumm/player/v5m.cpp
deleted file mode 100644
index 8a2b7f6814..0000000000
--- a/engines/scumm/player/v5m.cpp
+++ /dev/null
@@ -1,246 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-/*
- From Markus Magnuson (superqult) we got this information:
- Mac0
- ---
- 4 bytes - 'SOUN'
- BE 4 bytes - block length
-
- 4 bytes - 'Mac0'
- BE 4 bytes - (blockLength - 27)
- 28 bytes - ???
-
- do this three times (once for each channel):
- 4 bytes - 'Chan'
- BE 4 bytes - channel length
- 4 bytes - instrument name (e.g. 'MARI')
-
- do this for ((chanLength-24)/4) times:
- 2 bytes - note duration
- 1 byte - note value
- 1 byte - note velocity
-
- 4 bytes - ???
- 4 bytes - 'Loop'/'Done'
- 4 bytes - ???
-
- 1 byte - 0x09
- ---
-
- The instruments presumably correspond to the snd resource names in the
- Monkey Island executable:
-
- Instruments
- "MARI" - MARIMBA
- "PLUC" - PLUCK
- "HARM" - HARMONIC
- "PIPE" - PIPEORGAN
- "TROM" - TROMBONE
- "STRI" - STRINGS
- "HORN" - HORN
- "VIBE" - VIBES
- "SHAK" - SHAKUHACHI
- "PANP" - PANPIPE
- "WHIS" - WHISTLE
- "ORGA" - ORGAN3
- "BONG" - BONGO
- "BASS" - BASS
-
- ---
-
- Note values <= 1 are silent.
-*/
-
-#include "common/macresman.h"
-#include "common/translation.h"
-#include "engines/engine.h"
-#include "gui/message.h"
-#include "scumm/player/v5m.h"
-#include "scumm/scumm.h"
-
-namespace Scumm {
-
-Player_V5M::Player_V5M(ScummEngine *scumm, Audio::Mixer *mixer)
- : Player_Mac(scumm, mixer, 3, 0x07, false) {
- assert(_vm->_game.id == GID_MONKEY);
-}
-
-// Try both with and without underscore in the filename, because hfsutils may
-// turn the space into an underscore. At least, it did for me.
-
-static const char *monkeyIslandFileNames[] = {
- "Monkey Island",
- "Monkey_Island"
-};
-
-bool Player_V5M::checkMusicAvailable() {
- Common::MacResManager resource;
-
- for (int i = 0; i < ARRAYSIZE(monkeyIslandFileNames); i++) {
- if (resource.exists(monkeyIslandFileNames[i])) {
- return true;
- }
- }
-
- GUI::MessageDialog dialog(_(
- "Could not find the 'Monkey Island' Macintosh executable to read the\n"
- "instruments from. Music will be disabled."), _("OK"));
- dialog.runModal();
- return false;
-}
-
-bool Player_V5M::loadMusic(const byte *ptr) {
- Common::MacResManager resource;
- bool found = false;
- uint i;
-
- for (i = 0; i < ARRAYSIZE(monkeyIslandFileNames); i++) {
- if (resource.open(monkeyIslandFileNames[i])) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- return false;
- }
-
- ptr += 8;
- // TODO: Decipher the unknown bytes in the header. For now, skip 'em
- ptr += 28;
-
- Common::MacResIDArray idArray = resource.getResIDArray(RES_SND);
-
- // Load the three channels and their instruments
- for (i = 0; i < 3; i++) {
- assert(READ_BE_UINT32(ptr) == MKTAG('C', 'h', 'a', 'n'));
- uint32 len = READ_BE_UINT32(ptr + 4);
- uint32 instrument = READ_BE_UINT32(ptr + 8);
-
- _channel[i]._length = len - 20;
- _channel[i]._data = ptr + 12;
- _channel[i]._looped = (READ_BE_UINT32(ptr + len - 8) == MKTAG('L', 'o', 'o', 'p'));
- _channel[i]._pos = 0;
- _channel[i]._pitchModifier = 0;
- _channel[i]._velocity = 0;
- _channel[i]._remaining = 0;
- _channel[i]._notesLeft = true;
-
- for (uint j = 0; j < idArray.size(); j++) {
- Common::String name = resource.getResName(RES_SND, idArray[j]);
- if (instrument == READ_BE_UINT32(name.c_str())) {
- debug(6, "Player_V5M::loadMusic: Channel %d: Loading instrument '%s'", i, name.c_str());
- Common::SeekableReadStream *stream = resource.getResource(RES_SND, idArray[j]);
-
- if (!_channel[i].loadInstrument(stream)) {
- resource.close();
- return false;
- }
-
- break;
- }
- }
-
- ptr += len;
- }
-
- resource.close();
-
- // The last note of each channel is just zeroes. We will adjust this
- // note so that all the channels end at the same time.
-
- uint32 samples[3];
- uint32 maxSamples = 0;
- for (i = 0; i < 3; i++) {
- samples[i] = 0;
- for (uint j = 0; j < _channel[i]._length; j += 4) {
- samples[i] += durationToSamples(READ_BE_UINT16(&_channel[i]._data[j]));
- }
- if (samples[i] > maxSamples) {
- maxSamples = samples[i];
- }
- }
-
- for (i = 0; i < 3; i++) {
- _lastNoteSamples[i] = maxSamples - samples[i];
- }
-
- return true;
-}
-
-bool Player_V5M::getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity) {
- if (_channel[ch]._pos >= _channel[ch]._length) {
- if (!_channel[ch]._looped) {
- _channel[ch]._notesLeft = false;
- return false;
- }
- // FIXME: Jamieson630: The jump seems to be happening
- // too quickly! There should maybe be a pause after
- // the last Note Off? But I couldn't find one in the
- // MI1 Lookout music, where I was hearing problems.
- _channel[ch]._pos = 0;
- }
- uint16 duration = READ_BE_UINT16(&_channel[ch]._data[_channel[ch]._pos]);
- byte note = _channel[ch]._data[_channel[ch]._pos + 2];
- samples = durationToSamples(duration);
-
- if (note != 1) {
- _channel[ch]._instrument.newNote();
- }
-
- if (note > 1) {
- pitchModifier = noteToPitchModifier(note, &_channel[ch]._instrument);
- velocity = _channel[ch]._data[_channel[ch]._pos + 3];
- } else if (note == 1) {
- // This is guesswork, but Monkey Island uses two different
- // "special" note values: 0, which is clearly a rest, and 1
- // which is... I thought at first it was a "soft" key off, to
- // fade out the note, but listening to the music in a Mac
- // emulator (which unfortunately doesn't work all that well),
- // I hear no trace of fading out.
- //
- // It could mean "change the volume on the current note", but
- // I can't hear that either, and it always seems to use the
- // exact same velocity on this note.
- //
- // So it appears it really just is a "hold the current note",
- // but why? Couldn't they just have made the original note
- // longer?
-
- pitchModifier = _channel[ch]._pitchModifier;
- velocity = _channel[ch]._velocity;
- } else {
- pitchModifier = 0;
- velocity = 0;
- }
-
- _channel[ch]._pos += 4;
-
- if (_channel[ch]._pos >= _channel[ch]._length) {
- samples = _lastNoteSamples[ch];
- }
- return true;
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/player/v5m.h b/engines/scumm/player/v5m.h
deleted file mode 100644
index ed51943226..0000000000
--- a/engines/scumm/player/v5m.h
+++ /dev/null
@@ -1,57 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef SCUMM_PLAYER_V5M_H
-#define SCUMM_PLAYER_V5M_H
-
-#include "common/scummsys.h"
-#include "common/util.h"
-#include "common/mutex.h"
-#include "scumm/music.h"
-#include "scumm/player/mac.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-
-class Mixer;
-
-namespace Scumm {
-
-class ScummEngine;
-
-/**
- * Scumm V5 Macintosh music driver.
- */
-class Player_V5M : public Player_Mac {
-public:
- Player_V5M(ScummEngine *scumm, Audio::Mixer *mixer);
-
- virtual bool checkMusicAvailable();
- virtual bool loadMusic(const byte *ptr);
- virtual bool getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity);
-
-private:
- uint32 _lastNoteSamples[3];
-};
-
-} // End of namespace Scumm
-
-#endif