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