diff --git a/engines/dreamweb/dreambase.h b/engines/dreamweb/dreambase.h index 99cb8476e17b..6263adfe60f6 100644 --- a/engines/dreamweb/dreambase.h +++ b/engines/dreamweb/dreambase.h @@ -69,13 +69,18 @@ class DreamBase { uint8 getNumber(const Frame *charSet, const uint8 *string, uint16 maxWidth, bool centered, uint16 *offset); uint8 kernChars(uint8 firstChar, uint8 secondChar, uint8 width); + // from sound.cpp + void volumeAdjust(); + void cancelCh0(); + void cancelCh1(); + void loadRoomsSample(); + // from stubs.cpp void crosshair(); void showBlink(); void dumpBlink(); void dumpPointer(); void showRyanPage(); - void volumeAdjust(); // from vgagrafx.cpp uint8 _workspace[(0x1000 + 2) * 16]; diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index df39c4dfd6f5..451d8ff13d09 100644 --- a/engines/dreamweb/dreamweb.cpp +++ b/engines/dreamweb/dreamweb.cpp @@ -30,9 +30,6 @@ #include "common/timer.h" #include "common/util.h" -#include "audio/mixer.h" -#include "audio/decoders/raw.h" - #include "graphics/palette.h" #include "graphics/surface.h" @@ -377,170 +374,6 @@ void DreamWebEngine::cls() { _system->fillScreen(0); } -void DreamWebEngine::playSound(uint8 channel, uint8 id, uint8 loops) { - debug(1, "playSound(%u, %u, %u)", channel, id, loops); - - int bank = 0; - bool speech = false; - Audio::Mixer::SoundType type = channel == 0? - Audio::Mixer::kMusicSoundType: Audio::Mixer::kSFXSoundType; - - if (id >= 12) { - id -= 12; - bank = 1; - if (id == 50) { - speech = true; - type = Audio::Mixer::kSpeechSoundType; - } - } - const SoundData &data = _soundData[bank]; - - Audio::SeekableAudioStream *raw; - if (!speech) { - if (id >= data.samples.size() || data.samples[id].size == 0) { - warning("invalid sample #%u played", id); - return; - } - - const Sample &sample = data.samples[id]; - uint8 *buffer = (uint8 *)malloc(sample.size); - if (!buffer) - error("out of memory: cannot allocate memory for sound(%u bytes)", sample.size); - memcpy(buffer, data.data.begin() + sample.offset, sample.size); - - raw = Audio::makeRawStream( - buffer, - sample.size, 22050, Audio::FLAG_UNSIGNED); - } else { - uint8 *buffer = (uint8 *)malloc(_speechData.size()); - if (!buffer) - error("out of memory: cannot allocate memory for sound(%u bytes)", _speechData.size()); - memcpy(buffer, _speechData.begin(), _speechData.size()); - raw = Audio::makeRawStream( - buffer, - _speechData.size(), 22050, Audio::FLAG_UNSIGNED); - - } - - Audio::AudioStream *stream; - if (loops > 1) { - stream = new Audio::LoopingAudioStream(raw, loops < 255? loops: 0); - } else - stream = raw; - - if (_mixer->isSoundHandleActive(_channelHandle[channel])) - _mixer->stopHandle(_channelHandle[channel]); - _mixer->playStream(type, &_channelHandle[channel], stream); -} - -void DreamWebEngine::stopSound(uint8 channel) { - debug(1, "stopSound(%u)", channel); - assert(channel == 0 || channel == 1); - _mixer->stopHandle(_channelHandle[channel]); - if (channel == 0) - _channel0 = 0; - else - _channel1 = 0; -} - -bool DreamWebEngine::loadSpeech(const Common::String &filename) { - if (ConfMan.getBool("speech_mute")) - return false; - - Common::File file; - if (!file.open("speech/" + filename)) - return false; - - debug(1, "loadSpeech(%s)", filename.c_str()); - - uint size = file.size(); - _speechData.resize(size); - file.read(_speechData.begin(), size); - file.close(); - return true; -} - -void DreamWebEngine::soundHandler() { - _base.data.byte(DreamGen::kSubtitles) = ConfMan.getBool("subtitles"); - _base.volumeAdjust(); - - uint volume = _base.data.byte(DreamGen::kVolume); - //.vol file loaded into soundbuf:0x4000 - //volume table at (volume * 0x100 + 0x3f00) - //volume value could be from 1 to 7 - //1 - 0x10-0xff - //2 - 0x1f-0xdf - //3 - 0x2f-0xd0 - //4 - 0x3e-0xc1 - //5 - 0x4d-0xb2 - //6 - 0x5d-0xa2 - //7 - 0x6f-0x91 - if (volume >= 8) - volume = 7; - volume = (8 - volume) * Audio::Mixer::kMaxChannelVolume / 8; - _mixer->setChannelVolume(_channelHandle[0], volume); - - uint8 ch0 = _base.data.byte(DreamGen::kCh0playing); - if (ch0 == 255) - ch0 = 0; - uint8 ch1 = _base.data.byte(DreamGen::kCh1playing); - if (ch1 == 255) - ch1 = 0; - uint8 ch0loop = _base.data.byte(DreamGen::kCh0repeat); - - if (_channel0 != ch0) { - _channel0 = ch0; - if (ch0) { - playSound(0, ch0, ch0loop); - } - } - if (_channel1 != ch1) { - _channel1 = ch1; - if (ch1) { - playSound(1, ch1, 1); - } - } - if (!_mixer->isSoundHandleActive(_channelHandle[0])) { - _base.data.byte(DreamGen::kCh0playing) = 255; - _channel0 = 0; - } - if (!_mixer->isSoundHandleActive(_channelHandle[1])) { - _base.data.byte(DreamGen::kCh1playing) = 255; - _channel1 = 0; - } - -} - -void DreamWebEngine::loadSounds(uint bank, const Common::String &filename) { - debug(1, "loadSounds(%u, %s)", bank, filename.c_str()); - Common::File file; - if (!file.open(filename)) { - warning("cannot open %s", filename.c_str()); - return; - } - - uint8 header[0x60]; - file.read(header, sizeof(header)); - uint tablesize = READ_LE_UINT16(header + 0x32); - debug(1, "table size = %u", tablesize); - - SoundData &soundData = _soundData[bank]; - soundData.samples.resize(tablesize / 6); - uint total = 0; - for(uint i = 0; i < tablesize / 6; ++i) { - uint8 entry[6]; - Sample &sample = soundData.samples[i]; - file.read(entry, sizeof(entry)); - sample.offset = entry[0] * 0x4000 + READ_LE_UINT16(entry + 1); - sample.size = READ_LE_UINT16(entry + 3) * 0x800; - total += sample.size; - debug(1, "offset: %08x, size: %u", sample.offset, sample.size); - } - soundData.data.resize(total); - file.read(soundData.data.begin(), total); - file.close(); -} - uint8 DreamWebEngine::modifyChar(uint8 c) const { if (c < 128) return c; diff --git a/engines/dreamweb/module.mk b/engines/dreamweb/module.mk index 304daf6036bd..398f0b8db006 100644 --- a/engines/dreamweb/module.mk +++ b/engines/dreamweb/module.mk @@ -13,6 +13,7 @@ MODULE_OBJS := \ people.o \ print.o \ saveload.o \ + sound.o \ sprite.o \ stubs.o \ talk.o \ diff --git a/engines/dreamweb/sound.cpp b/engines/dreamweb/sound.cpp new file mode 100644 index 000000000000..16f562a840cd --- /dev/null +++ b/engines/dreamweb/sound.cpp @@ -0,0 +1,306 @@ +/* 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 "dreamweb/dreamweb.h" +#include "dreamweb/dreamgen.h" + +#include "audio/mixer.h" +#include "audio/decoders/raw.h" + +#include "common/config-manager.h" + +namespace DreamGen { + +void DreamGenContext::loadSpeech() { + cancelCh1(); + data.byte(kSpeechloaded) = 0; + createName(); + const char *name = (const char *)data.ptr(di, 13); + //warning("name = %s", name); + if (engine->loadSpeech(name)) + data.byte(kSpeechloaded) = 1; +} + +void DreamBase::volumeAdjust() { + if (data.byte(kVolumedirection) == 0) + return; + if (data.byte(kVolume) != data.byte(kVolumeto)) { + data.byte(kVolumecount) += 64; + // Only modify the volume every 256/64 = 4th time around + if (data.byte(kVolumecount) == 0) + data.byte(kVolume) += data.byte(kVolumedirection); + } else { + data.byte(kVolumedirection) = 0; + } +} + +void DreamGenContext::playChannel0(uint8 index, uint8 repeat) { + if (data.byte(kSoundint) == 255) + return; + + data.byte(kCh0playing) = index; + Sound *soundBank; + if (index >= 12) { + soundBank = (Sound *)getSegment(data.word(kSounddata2)).ptr(0, 0); + index -= 12; + } else + soundBank = (Sound *)getSegment(data.word(kSounddata)).ptr(0, 0); + + data.byte(kCh0repeat) = repeat; + data.word(kCh0emmpage) = soundBank[index].emmPage; + data.word(kCh0offset) = soundBank[index].offset(); + data.word(kCh0blockstocopy) = soundBank[index].blockCount(); + if (repeat) { + data.word(kCh0oldemmpage) = data.word(kCh0emmpage); + data.word(kCh0oldoffset) = data.word(kCh0offset); + data.word(kCh0oldblockstocopy) = data.word(kCh0blockstocopy); + } +} + +void DreamGenContext::playChannel0() { + playChannel0(al, ah); +} + +void DreamGenContext::playChannel1(uint8 index) { + if (data.byte(kSoundint) == 255) + return; + if (data.byte(kCh1playing) == 7) + return; + + data.byte(kCh1playing) = index; + Sound *soundBank; + if (index >= 12) { + soundBank = (Sound *)getSegment(data.word(kSounddata2)).ptr(0, 0); + index -= 12; + } else + soundBank = (Sound *)getSegment(data.word(kSounddata)).ptr(0, 0); + + data.word(kCh1emmpage) = soundBank[index].emmPage; + data.word(kCh1offset) = soundBank[index].offset(); + data.word(kCh1blockstocopy) = soundBank[index].blockCount(); +} + +void DreamGenContext::playChannel1() { + playChannel1(al); +} + +void DreamBase::cancelCh0() { + data.byte(kCh0repeat) = 0; + data.word(kCh0blockstocopy) = 0; + data.byte(kCh0playing) = 255; + engine->stopSound(0); +} + +void DreamBase::cancelCh1() { + data.word(kCh1blockstocopy) = 0; + data.byte(kCh1playing) = 255; + engine->stopSound(1); +} + +void DreamBase::loadRoomsSample() { + uint8 sample = data.byte(kRoomssample); + + if (sample == 255 || data.byte(kCurrentsample) == sample) + return; // loaded already + + assert(sample < 100); + Common::String sampleName = Common::String::format("DREAMWEB.V%02d", sample); + + uint8 ch0 = data.byte(kCh0playing); + if (ch0 >= 12 && ch0 != 255) + cancelCh0(); + uint8 ch1 = data.byte(kCh1playing); + if (ch1 >= 12) + cancelCh1(); + engine->loadSounds(1, sampleName.c_str()); +} + +} // End of namespace DreamGen + + +namespace DreamWeb { + +void DreamWebEngine::playSound(uint8 channel, uint8 id, uint8 loops) { + debug(1, "playSound(%u, %u, %u)", channel, id, loops); + + int bank = 0; + bool speech = false; + Audio::Mixer::SoundType type = channel == 0? + Audio::Mixer::kMusicSoundType: Audio::Mixer::kSFXSoundType; + + if (id >= 12) { + id -= 12; + bank = 1; + if (id == 50) { + speech = true; + type = Audio::Mixer::kSpeechSoundType; + } + } + const SoundData &data = _soundData[bank]; + + Audio::SeekableAudioStream *raw; + if (!speech) { + if (id >= data.samples.size() || data.samples[id].size == 0) { + warning("invalid sample #%u played", id); + return; + } + + const Sample &sample = data.samples[id]; + uint8 *buffer = (uint8 *)malloc(sample.size); + if (!buffer) + error("out of memory: cannot allocate memory for sound(%u bytes)", sample.size); + memcpy(buffer, data.data.begin() + sample.offset, sample.size); + + raw = Audio::makeRawStream( + buffer, + sample.size, 22050, Audio::FLAG_UNSIGNED); + } else { + uint8 *buffer = (uint8 *)malloc(_speechData.size()); + if (!buffer) + error("out of memory: cannot allocate memory for sound(%u bytes)", _speechData.size()); + memcpy(buffer, _speechData.begin(), _speechData.size()); + raw = Audio::makeRawStream( + buffer, + _speechData.size(), 22050, Audio::FLAG_UNSIGNED); + + } + + Audio::AudioStream *stream; + if (loops > 1) { + stream = new Audio::LoopingAudioStream(raw, loops < 255? loops: 0); + } else + stream = raw; + + if (_mixer->isSoundHandleActive(_channelHandle[channel])) + _mixer->stopHandle(_channelHandle[channel]); + _mixer->playStream(type, &_channelHandle[channel], stream); +} + +void DreamWebEngine::stopSound(uint8 channel) { + debug(1, "stopSound(%u)", channel); + assert(channel == 0 || channel == 1); + _mixer->stopHandle(_channelHandle[channel]); + if (channel == 0) + _channel0 = 0; + else + _channel1 = 0; +} + +bool DreamWebEngine::loadSpeech(const Common::String &filename) { + if (ConfMan.getBool("speech_mute")) + return false; + + Common::File file; + if (!file.open("speech/" + filename)) + return false; + + debug(1, "loadSpeech(%s)", filename.c_str()); + + uint size = file.size(); + _speechData.resize(size); + file.read(_speechData.begin(), size); + file.close(); + return true; +} + +void DreamWebEngine::soundHandler() { + _base.data.byte(DreamGen::kSubtitles) = ConfMan.getBool("subtitles"); + _base.volumeAdjust(); + + uint volume = _base.data.byte(DreamGen::kVolume); + //.vol file loaded into soundbuf:0x4000 + //volume table at (volume * 0x100 + 0x3f00) + //volume value could be from 1 to 7 + //1 - 0x10-0xff + //2 - 0x1f-0xdf + //3 - 0x2f-0xd0 + //4 - 0x3e-0xc1 + //5 - 0x4d-0xb2 + //6 - 0x5d-0xa2 + //7 - 0x6f-0x91 + if (volume >= 8) + volume = 7; + volume = (8 - volume) * Audio::Mixer::kMaxChannelVolume / 8; + _mixer->setChannelVolume(_channelHandle[0], volume); + + uint8 ch0 = _base.data.byte(DreamGen::kCh0playing); + if (ch0 == 255) + ch0 = 0; + uint8 ch1 = _base.data.byte(DreamGen::kCh1playing); + if (ch1 == 255) + ch1 = 0; + uint8 ch0loop = _base.data.byte(DreamGen::kCh0repeat); + + if (_channel0 != ch0) { + _channel0 = ch0; + if (ch0) { + playSound(0, ch0, ch0loop); + } + } + if (_channel1 != ch1) { + _channel1 = ch1; + if (ch1) { + playSound(1, ch1, 1); + } + } + if (!_mixer->isSoundHandleActive(_channelHandle[0])) { + _base.data.byte(DreamGen::kCh0playing) = 255; + _channel0 = 0; + } + if (!_mixer->isSoundHandleActive(_channelHandle[1])) { + _base.data.byte(DreamGen::kCh1playing) = 255; + _channel1 = 0; + } + +} + +void DreamWebEngine::loadSounds(uint bank, const Common::String &filename) { + debug(1, "loadSounds(%u, %s)", bank, filename.c_str()); + Common::File file; + if (!file.open(filename)) { + warning("cannot open %s", filename.c_str()); + return; + } + + uint8 header[0x60]; + file.read(header, sizeof(header)); + uint tablesize = READ_LE_UINT16(header + 0x32); + debug(1, "table size = %u", tablesize); + + SoundData &soundData = _soundData[bank]; + soundData.samples.resize(tablesize / 6); + uint total = 0; + for(uint i = 0; i < tablesize / 6; ++i) { + uint8 entry[6]; + Sample &sample = soundData.samples[i]; + file.read(entry, sizeof(entry)); + sample.offset = entry[0] * 0x4000 + READ_LE_UINT16(entry + 1); + sample.size = READ_LE_UINT16(entry + 3) * 0x800; + total += sample.size; + debug(1, "offset: %08x, size: %u", sample.offset, sample.size); + } + soundData.data.resize(total); + file.read(soundData.data.begin(), total); + file.close(); +} + +} // End of namespace DreamWeb diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp index 839665dd67b3..834aa850f419 100644 --- a/engines/dreamweb/stubs.cpp +++ b/engines/dreamweb/stubs.cpp @@ -1005,16 +1005,6 @@ void DreamGenContext::deallocateMem(uint16 segment) { } } -void DreamGenContext::loadSpeech() { - cancelCh1(); - data.byte(kSpeechloaded) = 0; - createName(); - const char *name = (const char *)data.ptr(di, 13); - //warning("name = %s", name); - if (engine->loadSpeech(name)) - data.byte(kSpeechloaded) = 1; -} - void DreamGenContext::DOSReturn() { if (data.byte(kCommandtype) != 250) { data.byte(kCommandtype) = 250; @@ -1097,19 +1087,6 @@ void DreamGenContext::lockMon() { } } -void DreamGenContext::cancelCh0() { - data.byte(kCh0repeat) = 0; - data.word(kCh0blockstocopy) = 0; - data.byte(kCh0playing) = 255; - engine->stopSound(0); -} - -void DreamGenContext::cancelCh1() { - data.word(kCh1blockstocopy) = 0; - data.byte(kCh1playing) = 255; - engine->stopSound(1); -} - void DreamGenContext::makeBackOb(SetObject *objData) { if (data.byte(kNewobs) == 0) return; @@ -2313,24 +2290,6 @@ void DreamGenContext::loadRoom() { getDimension(); } -void DreamGenContext::loadRoomsSample() { - uint8 sample = data.byte(kRoomssample); - - if (sample == 255 || data.byte(kCurrentsample) == sample) - return; // loaded already - - assert(sample < 100); - Common::String sampleName = Common::String::format("DREAMWEB.V%02d", sample); - - uint8 ch0 = data.byte(kCh0playing); - if (ch0 >= 12 && ch0 != 255) - cancelCh0(); - uint8 ch1 = data.byte(kCh1playing); - if (ch1 >= 12) - cancelCh1(); - engine->loadSounds(1, sampleName.c_str()); -} - void DreamGenContext::readSetData() { data.word(kCharset1) = standardLoad("DREAMWEB.C00"); @@ -2364,69 +2323,6 @@ Frame * DreamGenContext::tempGraphics3() { return (Frame *)getSegment(data.word(kTempgraphics3)).ptr(0, 0); } -void DreamBase::volumeAdjust() { - if (data.byte(kVolumedirection) == 0) - return; - if (data.byte(kVolume) != data.byte(kVolumeto)) { - data.byte(kVolumecount) += 64; - // Only modify the volume every 256/64 = 4th time around - if (data.byte(kVolumecount) == 0) - data.byte(kVolume) += data.byte(kVolumedirection); - } else { - data.byte(kVolumedirection) = 0; - } -} - -void DreamGenContext::playChannel0(uint8 index, uint8 repeat) { - if (data.byte(kSoundint) == 255) - return; - - data.byte(kCh0playing) = index; - Sound *soundBank; - if (index >= 12) { - soundBank = (Sound *)getSegment(data.word(kSounddata2)).ptr(0, 0); - index -= 12; - } else - soundBank = (Sound *)getSegment(data.word(kSounddata)).ptr(0, 0); - - data.byte(kCh0repeat) = repeat; - data.word(kCh0emmpage) = soundBank[index].emmPage; - data.word(kCh0offset) = soundBank[index].offset(); - data.word(kCh0blockstocopy) = soundBank[index].blockCount(); - if (repeat) { - data.word(kCh0oldemmpage) = data.word(kCh0emmpage); - data.word(kCh0oldoffset) = data.word(kCh0offset); - data.word(kCh0oldblockstocopy) = data.word(kCh0blockstocopy); - } -} - -void DreamGenContext::playChannel0() { - playChannel0(al, ah); -} - -void DreamGenContext::playChannel1(uint8 index) { - if (data.byte(kSoundint) == 255) - return; - if (data.byte(kCh1playing) == 7) - return; - - data.byte(kCh1playing) = index; - Sound *soundBank; - if (index >= 12) { - soundBank = (Sound *)getSegment(data.word(kSounddata2)).ptr(0, 0); - index -= 12; - } else - soundBank = (Sound *)getSegment(data.word(kSounddata)).ptr(0, 0); - - data.word(kCh1emmpage) = soundBank[index].emmPage; - data.word(kCh1offset) = soundBank[index].offset(); - data.word(kCh1blockstocopy) = soundBank[index].blockCount(); -} - -void DreamGenContext::playChannel1() { - playChannel1(al); -} - void DreamGenContext::findRoomInLoc() { uint8 x = data.byte(kMapx) / 11; uint8 y = data.byte(kMapy) / 10; diff --git a/engines/dreamweb/stubs.h b/engines/dreamweb/stubs.h index 73fa7a62ef6b..ea2a74d37f5e 100644 --- a/engines/dreamweb/stubs.h +++ b/engines/dreamweb/stubs.h @@ -133,8 +133,6 @@ RoomPaths *getRoomsPaths(); void makeBackOb(SetObject *objData); void lockMon(); - void cancelCh0(); - void cancelCh1(); void plotReel(); Reel *getReelStart(); void dealWithSpecial(uint8 firstParam, uint8 secondParam); @@ -293,7 +291,6 @@ void intro2Text(); void intro3Text(); void readSetData(); - void loadRoomsSample(); void fadeupYellows(); void fadeupMonFirst(); void printLogo();