scummvm/engines/kyra/sound/sound_pc98_darkmoon.cpp
2023-12-24 13:19:25 +01:00

234 lines
6.1 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef ENABLE_EOB
#include "kyra/sound/sound_intern.h"
#include "kyra/resource/resource.h"
#include "kyra/sound/drivers/capcom98.h"
#include "common/config-manager.h"
namespace Kyra {
SoundPC98_Darkmoon::SoundPC98_Darkmoon(KyraEngine_v1 *vm, MidiDriver::DeviceHandle dev, Audio::Mixer *mixer) : Sound(vm, mixer),
_vm(vm), _driver(nullptr), _soundData(nullptr), _currentResourceSet(-1), _ready(false), _dev(dev), _drvType(kPC98), _lastTrack(-1) {
memset(&_resInfo, 0, sizeof(_resInfo));
_soundData = new uint8[20600];
memset(_soundData, 0, 20600);
_fileBuffer = new uint8[10500];
memset(_fileBuffer, 0, 10500);
MusicType type = MidiDriver::getMusicType(dev);
if (type == MT_MT32)
_drvType = kMidiMT32;
else if (type == MT_GM)
_drvType = kMidiGM;
}
SoundPC98_Darkmoon::~SoundPC98_Darkmoon() {
delete _driver;
delete[] _soundData;
delete[] _fileBuffer;
for (int i = 0; i < 3; i++)
initAudioResourceInfo(i, nullptr);
}
Sound::kType SoundPC98_Darkmoon::getMusicType() const {
return _drvType;
}
Sound::kType SoundPC98_Darkmoon::getSfxType() const {
return kPC98;
}
bool SoundPC98_Darkmoon::init() {
_driver = new CapcomPC98AudioDriver(_mixer, _dev);
_ready = (_soundData && _driver && _driver->isUsable());
return _ready;
}
void SoundPC98_Darkmoon::initAudioResourceInfo(int set, void *info) {
if (set < kMusicIntro || set > kMusicFinale)
return;
delete _resInfo[set];
_resInfo[set] = info ? new SoundResourceInfo_PC(*(SoundResourceInfo_PC*)info) : nullptr;
}
void SoundPC98_Darkmoon::selectAudioResourceSet(int set) {
if (set < kMusicIntro || set > kMusicFinale || set == _currentResourceSet || !_ready)
return;
if (_resInfo[set])
_currentResourceSet = set;
}
void SoundPC98_Darkmoon::loadSoundFile(uint file) {
if (!_ready)
return;
if (file < res()->fileListSize)
loadSoundFile(res()->fileList[file]);
}
void SoundPC98_Darkmoon::loadSoundFile(const Common::Path &name) {
if (!_ready)
return;
haltTrack();
stopAllSoundEffects();
Common::Path path(name);
path.appendInPlace(_drvType == kPC98 ? ".SDO" : ".SDM");
if (!_ready || _soundFileLoaded == path)
return;
Common::SeekableReadStream *in = _vm->resource()->createReadStream(path);
if (!in)
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
uint16 sz = in->readUint16LE();
uint8 cmp = in->readByte();
in->seek(1, SEEK_CUR);
uint32 outSize = in->readUint32LE();
if ((cmp == 0 && outSize > 10500) || (cmp != 0 && outSize > 20600))
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
sz -= in->pos();
in->seek(2, SEEK_CUR);
memset(_fileBuffer, 0, 10500);
uint16 readSize = in->read(_fileBuffer, 10500);
assert(sz == readSize);
delete in;
memset(_soundData, 0, 20600);
if (cmp == 0) {
memcpy(_soundData, _fileBuffer, outSize);
} else if (cmp == 3) {
Screen::decodeFrame3(_fileBuffer, _soundData, outSize, true);
} else if (cmp == 4) {
Screen::decodeFrame4(_fileBuffer, _soundData, outSize);
} else {
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
}
uint16 instrOffs = READ_LE_UINT16(_soundData);
if (instrOffs >= 20600)
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", path.toString().c_str());
_driver->loadFMInstruments(_soundData + instrOffs);
_driver->reset();
}
void SoundPC98_Darkmoon::playTrack(uint8 track) {
if (track == 0 || track == 2)
_lastTrack = track;
playSoundEffect(track, 127);
}
void SoundPC98_Darkmoon::haltTrack() {
if (!_ready)
return;
_driver->stopSong();
_lastTrack = -1;
}
bool SoundPC98_Darkmoon::isPlaying() const {
return _ready && _driver && _driver->songIsPlaying();
}
void SoundPC98_Darkmoon::playSoundEffect(uint16 track, uint8 vol) {
if (!_ready)
return;
if (track == 0 || track == 2) {
restartBackgroundMusic();
return;
}
const uint8 *data = getData(track);
if (!data)
return;
if (track < 52 || track > 67) {
if (_sfxEnabled)
_driver->startSoundEffect(data, vol);
} else if (_musicEnabled) {
_lastTrack = track;
_driver->startSong(data, vol, false);
}
}
void SoundPC98_Darkmoon::stopAllSoundEffects() {
if (_ready)
_driver->stopSoundEffect();
}
void SoundPC98_Darkmoon::beginFadeOut() {
_driver->fadeOut();
}
void SoundPC98_Darkmoon::pause(bool paused) {
if (_ready && paused)
_driver->allNotesOff();
}
int SoundPC98_Darkmoon::checkTrigger() {
return _driver ? _driver->checkSoundMarker() : 99;
}
void SoundPC98_Darkmoon::restartBackgroundMusic() {
if (_lastTrack == -1) {
haltTrack();
stopAllSoundEffects();
} else {
_lastTrack = -1;
const uint8 *data = getData(0);
if (!data)
return;
if (_musicEnabled)
_driver->startSong(data, 127, true);
}
}
const uint8 *SoundPC98_Darkmoon::getData(uint16 track) const {
if (!_ready || track >= 120)
return nullptr;
uint16 offset = READ_LE_UINT16(&_soundData[(track + 1) << 1]);
return (offset < 20600) ? &_soundData[offset] : nullptr;
}
void SoundPC98_Darkmoon::updateVolumeSettings() {
if (!_driver || !_ready)
return;
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
_driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
_driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
}
} // End of namespace Kyra
#endif