2009-04-01 11:03:06 +00:00
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common/endian.h"
|
|
|
|
|
|
|
|
#include "cruise/cruise.h"
|
|
|
|
#include "cruise/cruise_main.h"
|
|
|
|
#include "cruise/sound.h"
|
|
|
|
#include "cruise/volume.h"
|
|
|
|
|
|
|
|
namespace Cruise {
|
|
|
|
|
|
|
|
MusicPlayer::MusicPlayer(): _looping(false), _isPlaying(false), _songPlayed(false) {
|
|
|
|
_songPointer = NULL;
|
|
|
|
_masterVolume = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
MusicPlayer::~MusicPlayer() {
|
|
|
|
stop();
|
|
|
|
if (_songPointer != NULL)
|
|
|
|
free(_songPointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::setVolume(int volume) {
|
|
|
|
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
|
|
|
|
|
|
|
|
if (_masterVolume == volume)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_masterVolume = volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::stop() {
|
|
|
|
_isPlaying = false;
|
|
|
|
_songPlayed = songLoaded();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::pause() {
|
|
|
|
setVolume(-1);
|
|
|
|
_isPlaying = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::resume() {
|
|
|
|
setVolume(_masterVolume);
|
|
|
|
_isPlaying = true;
|
|
|
|
_songPlayed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::doSync(Common::Serializer &s) {
|
|
|
|
// synchronise current music name, if any, state, and position
|
2009-05-19 11:23:13 +00:00
|
|
|
s.syncBytes((byte *)_musicName, 33);
|
2009-04-01 11:03:06 +00:00
|
|
|
uint16 v = (uint16)songLoaded();
|
|
|
|
s.syncAsSint16LE(v);
|
|
|
|
s.syncAsSint16LE(_songPlayed);
|
|
|
|
s.syncAsSint16LE(_looping);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::loadSong(const char *name) {
|
|
|
|
char tempName[20], baseName[20];
|
|
|
|
uint8 *sampleData;
|
|
|
|
|
|
|
|
if (songLoaded())
|
|
|
|
removeSong();
|
|
|
|
|
|
|
|
// Load the correct file
|
|
|
|
int fileIdx = findFileInDisks(name);
|
|
|
|
if (fileIdx < 0) return;
|
|
|
|
|
|
|
|
int unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2;
|
|
|
|
_songPointer = (byte *)malloc(unpackedSize);
|
|
|
|
assert(_songPointer);
|
|
|
|
|
|
|
|
if (volumePtrToFileDescriptor[fileIdx].size + 2 != unpackedSize) {
|
|
|
|
uint8 *packedBuffer = (uint8 *)mallocAndZero(volumePtrToFileDescriptor[fileIdx].size + 2);
|
|
|
|
|
|
|
|
loadPackedFileToMem(fileIdx, packedBuffer);
|
|
|
|
|
|
|
|
uint32 realUnpackedSize = READ_BE_UINT32(packedBuffer + volumePtrToFileDescriptor[fileIdx].size - 4);
|
|
|
|
|
|
|
|
delphineUnpack(_songPointer, packedBuffer, volumePtrToFileDescriptor[fileIdx].size);
|
|
|
|
_songSize = realUnpackedSize;
|
|
|
|
|
|
|
|
free(packedBuffer);
|
|
|
|
} else {
|
|
|
|
loadPackedFileToMem(fileIdx, _songPointer);
|
|
|
|
_songSize = unpackedSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(_musicName, name);
|
|
|
|
|
|
|
|
// Get the details of the song
|
|
|
|
// TODO: Figure this out for sure for use in actually playing song
|
2009-04-05 07:51:31 +00:00
|
|
|
//int size = *(_songPointer + 470);
|
2009-04-01 14:00:17 +00:00
|
|
|
//int speed = 244 - *(_songPointer + 471);
|
|
|
|
//int musicSpeed = (speed * 100) / 1060;
|
2009-04-01 11:03:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Get the file without the extension
|
|
|
|
strcpy(baseName, name);
|
2009-05-12 19:24:11 +00:00
|
|
|
char *p = strchr(baseName, '.');
|
|
|
|
if (p)
|
|
|
|
*p = '\0';
|
2009-04-01 11:03:06 +00:00
|
|
|
|
|
|
|
// Get the instruments states file
|
|
|
|
strcpy(tempName, baseName);
|
|
|
|
strcat(tempName, ".IST");
|
|
|
|
|
|
|
|
fileIdx = findFileInDisks(tempName);
|
2009-04-01 14:00:17 +00:00
|
|
|
if (fileIdx >= 0) {
|
2009-04-01 11:03:06 +00:00
|
|
|
// TODO: Figure out instrument state usage
|
|
|
|
uint8 instrumentState[15];
|
|
|
|
loadPackedFileToMem(fileIdx, instrumentState);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int instrumentCtr = 0; instrumentCtr < 15; ++instrumentCtr) {
|
|
|
|
if (_vm->mt32()) {
|
|
|
|
// Handle loading Roland instrument data
|
|
|
|
strcpy(tempName, baseName);
|
|
|
|
strcat(tempName, ".H32");
|
|
|
|
|
|
|
|
sampleData = loadInstrument(tempName, instrumentCtr);
|
|
|
|
if (sampleData) {
|
|
|
|
int v = *sampleData;
|
|
|
|
if ((v >= 128) && (v < 192))
|
|
|
|
patchMidi(0x80000L + (instrumentCtr * 512), sampleData + 1, 254);
|
|
|
|
|
|
|
|
// TODO: Currently I'm freeing the instrument data immediately. The original
|
|
|
|
// holds onto the sample data, so it may actually still be needed
|
|
|
|
free(sampleData);
|
|
|
|
}
|
|
|
|
} else if (_vm->adlib()) {
|
|
|
|
// Handle loading Adlib instrument data
|
|
|
|
strcpy(tempName, baseName);
|
|
|
|
strcat(tempName, ".ADL");
|
|
|
|
|
|
|
|
fileIdx = findFileInDisks(tempName);
|
|
|
|
if (fileIdx >= 0) {
|
|
|
|
sampleData = (byte *)malloc(volumePtrToFileDescriptor[fileIdx].extSize + 2);
|
|
|
|
assert(sampleData);
|
|
|
|
loadPackedFileToMem(fileIdx, sampleData);
|
|
|
|
|
|
|
|
// TODO: Make use of sample data
|
|
|
|
|
|
|
|
free(sampleData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_songPlayed = false;
|
|
|
|
_isPlaying = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::startSong() {
|
|
|
|
if (songLoaded()) {
|
|
|
|
// Start playing song here
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::removeSong() {
|
|
|
|
if (isPlaying())
|
|
|
|
stop();
|
|
|
|
|
|
|
|
if (_songPointer) {
|
|
|
|
free(_songPointer);
|
|
|
|
_songPointer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
_songPlayed = false;
|
|
|
|
|
|
|
|
strcpy(_musicName, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::fadeSong() {
|
|
|
|
// TODO: Implement fading properly
|
|
|
|
stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MusicPlayer::patchMidi(uint32 adr, const byte *data, int size) {
|
|
|
|
// TODO: Handle patching midi
|
|
|
|
}
|
|
|
|
|
|
|
|
byte *MusicPlayer::loadInstrument(const char *name, int i) {
|
|
|
|
// Find the resource
|
|
|
|
int fileIdx = findFileInDisks(name);
|
|
|
|
if (fileIdx < 0) {
|
|
|
|
warning("Instrument '%s' not found", name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int size = volumePtrToFileDescriptor[fileIdx].extSize;
|
|
|
|
|
|
|
|
// Get the data
|
|
|
|
byte *tmp = (byte *)malloc(size);
|
|
|
|
assert(tmp);
|
|
|
|
loadPackedFileToMem(fileIdx, tmp);
|
|
|
|
|
|
|
|
// Create a copy of the resource that's 22 bytes smaller
|
|
|
|
byte *result = (byte *)malloc(size - 22);
|
|
|
|
assert(result);
|
|
|
|
Common::copy(tmp, tmp + size - 22, result);
|
|
|
|
|
|
|
|
free(tmp);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // End of namespace Cruise
|