1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #ifdef ENABLE_EOB
24
25 #include "kyra/sound/drivers/segacd.h"
26 #include "kyra/sound/sound_intern.h"
27 #include "kyra/resource/resource.h"
28 #include "common/config-manager.h"
29 #include "backends/audiocd/audiocd.h"
30
31 namespace Kyra {
32
SoundSegaCD_EoB(KyraEngine_v1 * vm,Audio::Mixer * mixer)33 SoundSegaCD_EoB::SoundSegaCD_EoB(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer),
34 _vm(vm), _driver(0), _fmData(0), _lastSoundEffect(-1), _ready(false) {
35 memset(_pcmOffsets, 0, sizeof(_pcmOffsets));
36 memset(_fmOffsets, 0, sizeof(_fmOffsets));
37 }
38
~SoundSegaCD_EoB()39 SoundSegaCD_EoB::~SoundSegaCD_EoB() {
40 delete _driver;
41 delete[] _fmData;
42 }
43
getMusicType() const44 Sound::kType SoundSegaCD_EoB::getMusicType() const {
45 return kSegaCD;
46 }
47
init()48 bool SoundSegaCD_EoB::init() {
49 _driver = new SegaAudioDriver(_mixer);
50 g_system->getAudioCDManager()->open();
51
52 loadPCMData();
53 loadFMData();
54
55 _ready = true;
56
57 return true;
58 }
59
playTrack(uint8 track)60 void SoundSegaCD_EoB::playTrack(uint8 track) {
61 if (!_ready)
62 return;
63
64 if (!_musicEnabled) {
65 haltTrack();
66 return;
67 }
68
69 int loop = track >> 6;
70 track &= 0x7F;
71
72 g_system->getAudioCDManager()->play(track - 1, loop - 1, 0, 0);
73 g_system->getAudioCDManager()->update();
74 }
75
haltTrack()76 void SoundSegaCD_EoB::haltTrack() {
77 if (!_ready)
78 return;
79 g_system->getAudioCDManager()->stop();
80 }
81
playSoundEffect(uint16 track,uint8 volume)82 void SoundSegaCD_EoB::playSoundEffect(uint16 track, uint8 volume) {
83 if (!_sfxEnabled || !_ready)
84 return;
85
86 uint8 flags = track >> 8;
87 track &= 0xFF;
88
89 if (flags & 0x80) {
90 track--;
91 assert(track < ARRAYSIZE(_pcmOffsets));
92 for (uint8 i = 0; i < 8; ++i)
93 _driver->startPCMSound(i, _pcmOffsets[track]);
94
95 } else {
96 uint8 snd = (flags & 0x40) ? track : _fmTrackMap[track];
97 if (snd == 0 || snd > 135)
98 return;
99
100 _driver->startFMSound(&_fmData[_fmOffsets[snd - 1]], volume, (SegaAudioDriver::PrioFlags)flags);
101 _lastSoundEffect = track;
102 }
103 }
104
isPlaying() const105 bool SoundSegaCD_EoB::isPlaying() const {
106 return g_system->getAudioCDManager()->isPlaying();
107 }
108
updateVolumeSettings()109 void SoundSegaCD_EoB::updateVolumeSettings() {
110 if (!_driver || !_ready)
111 return;
112
113 bool mute = false;
114 if (ConfMan.hasKey("mute"))
115 mute = ConfMan.getBool("mute");
116
117 _driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
118 _driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
119 }
120
loadPCMData()121 void SoundSegaCD_EoB::loadPCMData() {
122 uint32 dataSize;
123 uint8 *data1 = _vm->resource()->fileData("PCM", &dataSize);
124 if (!data1)
125 error("SoundSegaCD_EoB::loadPCMData: File not found: '%s'", "PCM");
126
127 uint8 *data2 = new uint8[0x100];
128 memset(data2, 0xFF, 0x100);
129 data2[0] = 0x80;
130
131 for (int i = 0; i < ARRAYSIZE(_pcmOffsets); ++i)
132 _pcmOffsets[i] = data1[(i << 2) + 2];
133
134 _driver->loadPCMData(0, data1 + 64, dataSize - 64);
135 _driver->loadPCMData(0xFF00, data2, 0x100);
136
137 delete[] data1;
138 delete[] data2;
139 }
140
loadFMData()141 void SoundSegaCD_EoB::loadFMData() {
142 Common::SeekableReadStreamEndian *in = _vm->resource()->createEndianAwareReadStream("FMSE");
143 if (!in)
144 error("SoundSegaCD_EoB::loadFMData: File not found: '%s'", "FMSE");
145
146 for (int i = 0; i < ARRAYSIZE(_fmOffsets); ++i)
147 _fmOffsets[i] = (in->readUint32() - ARRAYSIZE(_fmOffsets) * 4) & 0xFFFF;
148
149 uint32 dataSize = in->size() - in->pos();
150 uint8 *data = new uint8[dataSize];
151 in->read(data, dataSize);
152 delete[] _fmData;
153 _fmData = data;
154
155 delete in;
156 }
157
158 const uint8 SoundSegaCD_EoB::_fmTrackMap[140] = {
159 0x00, 0x05, 0x40, 0x01, 0x02, 0x02, 0x06, 0x07, 0x12, 0x0a,
160 0x11, 0x1f, 0x1e, 0x12, 0x09, 0x0c, 0x0b, 0x17, 0x21, 0x0d,
161 0x00, 0x14, 0x00, 0x16, 0x00, 0x00, 0x26, 0x0f, 0x13, 0x10,
162 0x00, 0x00, 0x27, 0x00, 0x1a, 0x28, 0x39, 0x46, 0x33, 0x4a,
163 0x3b, 0x48, 0x33, 0x47, 0x38, 0x4d, 0x3e, 0x45, 0x36, 0x41,
164 0x3a, 0x49, 0x46, 0x38, 0x44, 0x37, 0x42, 0x34, 0x4b, 0x3c,
165 0x41, 0x3b, 0x40, 0x38, 0x47, 0x39, 0x4d, 0x35, 0x4c, 0x3d,
166 0x4e, 0x3d, 0x42, 0x43, 0x36, 0x32, 0x00, 0x60, 0x1f, 0x82,
167 0x1c, 0x29, 0x00, 0x00, 0x00, 0x65, 0x24, 0x60, 0x62, 0x6d,
168 0x00, 0x78, 0x70, 0x74, 0x7e, 0x7d, 0x66, 0x81, 0x6a, 0x67,
169 0x80, 0x68, 0x64, 0x6c, 0x77, 0x77, 0x77, 0x61, 0x61, 0x61,
170 0x71, 0x79, 0x7f, 0x73, 0x7a, 0x7b, 0x71, 0x7c, 0x6e, 0x0e,
171 0x75, 0x76, 0x78, 0x6b, 0x30, 0x2f, 0x03, 0x04, 0x23, 0x2b,
172 0x5a, 0x1a, 0x1c, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
173 };
174
175 } // End of namespace Kyra
176
177 #endif // ENABLE_EOB
178