mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 06:08:35 +00:00
synced imuse digital with local tree
svn-id: r12187
This commit is contained in:
parent
2c2ae5f59f
commit
8fd123992d
@ -26,6 +26,7 @@
|
||||
#include "scumm/akos.h"
|
||||
#include "scumm/bomp.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/sound.h"
|
||||
|
||||
namespace Scumm {
|
||||
@ -1328,7 +1329,7 @@ void ScummEngine::akos_queCommand(byte cmd, Actor *a, int param_1, int param_2)
|
||||
case 3:
|
||||
if (param_1 != 0) {
|
||||
if (_features & GF_DIGI_IMUSE)
|
||||
_sound->playSound(param_1);
|
||||
_imuseDigital->startSfx(param_1);
|
||||
else
|
||||
_sound->addSoundToQueue(param_1);
|
||||
}
|
||||
|
@ -1,83 +0,0 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2002-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#ifndef BUNDLE_H
|
||||
#define BUNDLE_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class Bundle {
|
||||
|
||||
private:
|
||||
|
||||
struct CompTable {
|
||||
int32 offset;
|
||||
int32 size;
|
||||
int32 codec;
|
||||
};
|
||||
|
||||
struct BundleAudioTable {
|
||||
char filename[13];
|
||||
int32 size;
|
||||
int32 offset;
|
||||
};
|
||||
|
||||
CompTable *_compVoiceTable;
|
||||
CompTable *_compMusicTable;
|
||||
BundleAudioTable *_bundleVoiceTable;
|
||||
BundleAudioTable *_bundleMusicTable;
|
||||
int32 _numVoiceFiles;
|
||||
int32 _numMusicFiles;
|
||||
int32 _lastSong;
|
||||
|
||||
byte _destImcTable[93];
|
||||
uint32 _destImcTable2[5697];
|
||||
|
||||
File _voiceFile;
|
||||
File _musicFile;
|
||||
|
||||
void initializeImcTables();
|
||||
|
||||
int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 size);
|
||||
|
||||
int32 decompressVoiceSampleByIndex(int32 index, byte **comp_final);
|
||||
int32 decompressMusicSampleByIndex(int32 index, int32 number, byte *comp_final);
|
||||
int32 getNumberOfMusicSamplesByIndex(int32 index);
|
||||
|
||||
public:
|
||||
Bundle();
|
||||
~Bundle();
|
||||
|
||||
bool openVoiceFile(const char *filename, const char *directory);
|
||||
bool openMusicFile(const char *filename, const char *directory);
|
||||
void closeVoiceFile();
|
||||
void closeMusicFile();
|
||||
|
||||
int32 decompressVoiceSampleByName(const char *name, byte **comp_final);
|
||||
int32 decompressMusicSampleByName(const char *name, int32 number, byte *comp_final);
|
||||
int32 getNumberOfMusicSamplesByName(const char *name);
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
@ -1,149 +0,0 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001 Ludvig Strigeus
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IMUSE_DIGI_H
|
||||
#define IMUSE_DIGI_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "scumm/music.h"
|
||||
#include "sound/mixer.h"
|
||||
|
||||
class AudioStream;
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
#define MAX_DIGITAL_CHANNELS 8
|
||||
#define MAX_IMUSE_JUMPS 50
|
||||
#define MAX_IMUSE_REGIONS 50
|
||||
#define MAX_IMUSE_MARKERS 50
|
||||
|
||||
class ScummEngine;
|
||||
class Bundle;
|
||||
|
||||
/**
|
||||
* iMuse Digital Implementation for SCUMM v7 and higher.
|
||||
*/
|
||||
class IMuseDigital : public MusicEngine {
|
||||
private:
|
||||
|
||||
struct _region {
|
||||
uint32 start; // begin of region
|
||||
uint32 length; // lenght of region
|
||||
};
|
||||
|
||||
struct _jump {
|
||||
uint32 start; // jump start position
|
||||
uint32 dest; // jump to dest position
|
||||
uint32 hookId; // id of hook
|
||||
uint32 fadeDelay; // fade delay in ms
|
||||
};
|
||||
|
||||
struct _marker {
|
||||
char name[256]; // name of marker
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
int8 pan; // pan
|
||||
int32 vol; // volume
|
||||
int32 volFadeDest; //
|
||||
int32 volFadeStep; //
|
||||
int32 volFadeDelay; //
|
||||
bool volFadeUsed; //
|
||||
|
||||
_region region[MAX_IMUSE_REGIONS];
|
||||
_marker marker[MAX_IMUSE_MARKERS];
|
||||
_jump jump[MAX_IMUSE_JUMPS];
|
||||
int32 offsetStop;
|
||||
int32 numJumps;
|
||||
int32 numRegions;
|
||||
int32 numMarkers;
|
||||
|
||||
int idSound;
|
||||
bool used;
|
||||
bool started;
|
||||
PlayingSoundHandle handle;
|
||||
AudioStream *stream;
|
||||
|
||||
Channel();
|
||||
};
|
||||
|
||||
Channel _channel[MAX_DIGITAL_CHANNELS];
|
||||
|
||||
ScummEngine *_scumm;
|
||||
bool _pause;
|
||||
|
||||
static void timer_handler(void *refConf);
|
||||
void callback();
|
||||
|
||||
//
|
||||
// Bundle music
|
||||
//
|
||||
const char *_nameBundleMusic;
|
||||
const char *_newNameBundleMusic;
|
||||
byte _musicDisk;
|
||||
byte _voiceDisk;
|
||||
int32 _currentSampleBundleMusic;
|
||||
int32 _numberSamplesBundleMusic;
|
||||
int32 _offsetSampleBundleMusic;
|
||||
int32 _offsetBufBundleMusic;
|
||||
byte *_musicBundleBufFinal;
|
||||
byte *_musicBundleBufOutput;
|
||||
bool _pauseBundleMusic;
|
||||
PlayingSoundHandle _bundleMusicTrack;
|
||||
bool _musicBundleToBeChanged;
|
||||
int32 _bundleMusicSampleBits;
|
||||
int32 _outputMixerSize;
|
||||
int32 _bundleSampleChannels;
|
||||
int32 _bundleMusicPosition;
|
||||
|
||||
static void music_handler(void *refCon);
|
||||
void bundleMusicHandler();
|
||||
|
||||
void playBundleMusic(const char *song);
|
||||
|
||||
public:
|
||||
int32 _bundleSongPosInMs;
|
||||
Bundle *_bundle; // FIXME: should be protected but is used by ScummEngine::askForDisk
|
||||
|
||||
void pauseBundleMusic(bool state);
|
||||
void stopBundleMusic();
|
||||
void playBundleSound(const char *sound);
|
||||
|
||||
void startSound(int sound, byte *voiceBundleData, AudioStream *input);
|
||||
|
||||
public:
|
||||
IMuseDigital(ScummEngine *scumm);
|
||||
~IMuseDigital();
|
||||
|
||||
void setMasterVolume(int vol) {}
|
||||
|
||||
void startSound(int sound) { startSound(sound, 0, 0); }
|
||||
void stopSound(int sound);
|
||||
void stopAllSounds();
|
||||
void pause(bool pause);
|
||||
void parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h);
|
||||
int getSoundStatus(int sound) const;
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
1
scumm/imuse_digi/.cvsignore
Normal file
1
scumm/imuse_digi/.cvsignore
Normal file
@ -0,0 +1 @@
|
||||
.deps
|
576
scumm/imuse_digi/dimuse.cpp
Normal file
576
scumm/imuse_digi/dimuse.cpp
Normal file
@ -0,0 +1,576 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "common/timer.h"
|
||||
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/sound.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/imuse_digi/dimuse_bndmgr.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
IMuseDigital::Track::Track()
|
||||
: idSound(-1), used(false), stream(NULL) {
|
||||
}
|
||||
|
||||
void IMuseDigital::timer_handler(void *refCon) {
|
||||
IMuseDigital *imuseDigital = (IMuseDigital *)refCon;
|
||||
imuseDigital->callback();
|
||||
}
|
||||
|
||||
IMuseDigital::IMuseDigital(ScummEngine *scumm)
|
||||
: _scumm(scumm) {
|
||||
_pause = false;
|
||||
_sound = new ImuseDigiSndMgr(_scumm);
|
||||
_scumm->_timer->installTimerProc(timer_handler, 1000000 / 25, this);
|
||||
_curMusicId = -1;
|
||||
}
|
||||
|
||||
IMuseDigital::~IMuseDigital() {
|
||||
_scumm->_timer->removeTimerProc(timer_handler);
|
||||
stopAllSounds();
|
||||
delete _sound;
|
||||
}
|
||||
|
||||
void IMuseDigital::callback() {
|
||||
int l = 0;
|
||||
|
||||
if (_pause || !_scumm)
|
||||
return;
|
||||
|
||||
for (l = 0; l < MAX_DIGITAL_TRACKS;l ++) {
|
||||
if (_track[l].used) {
|
||||
if (_track[l].stream2) {
|
||||
if (!_track[l].handle.isActive() && _track[l].started) {
|
||||
debug(5, "IMuseDigital::callback(): stoped sound: %d", _track[l].idSound);
|
||||
delete _track[l].stream2;
|
||||
_track[l].stream2 = NULL;
|
||||
_track[l].used = false;
|
||||
continue;
|
||||
}
|
||||
} else if (_track[l].stream) {
|
||||
if (_track[l].toBeRemoved) {
|
||||
debug(5, "IMuseDigital::callback(): stoped sound: %d", _track[l].idSound);
|
||||
if (_track[l].stream)
|
||||
_track[l].stream->finish();
|
||||
_track[l].stream = NULL;
|
||||
_sound->closeSound(_track[l].soundHandle);
|
||||
_track[l].used = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (_track[l].volFadeUsed) {
|
||||
if (_track[l].volFadeStep < 0) {
|
||||
if (_track[l].vol > _track[l].volFadeDest) {
|
||||
_track[l].vol += _track[l].volFadeStep;
|
||||
if (_track[l].vol < _track[l].volFadeDest) {
|
||||
_track[l].vol = _track[l].volFadeDest;
|
||||
_track[l].volFadeUsed = false;
|
||||
}
|
||||
if (_track[l].vol == 0) {
|
||||
_track[l].toBeRemoved = true;
|
||||
}
|
||||
}
|
||||
} else if (_track[l].volFadeStep > 0) {
|
||||
if (_track[l].vol < _track[l].volFadeDest) {
|
||||
_track[l].vol += _track[l].volFadeStep;
|
||||
if (_track[l].vol > _track[l].volFadeDest) {
|
||||
_track[l].vol = _track[l].volFadeDest;
|
||||
_track[l].volFadeUsed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug(5, "Fade: sound(%d), Vol(%d)", _track[l].idSound, _track[l].vol / 1000);
|
||||
}
|
||||
|
||||
int pan = (_track[l].pan != 64) ? 2 * _track[l].pan - 127 : 0;
|
||||
|
||||
if (_scumm->_mixer->isReady()) {
|
||||
if (_track[l].stream2) {
|
||||
if (!_track[l].started) {
|
||||
_track[l].started = true;
|
||||
_scumm->_mixer->playInputStream(&_track[l].handle, _track[l].stream2, true, _track[l].vol / 1000, _track[l].pan, -1, false);
|
||||
} else {
|
||||
_scumm->_mixer->setChannelVolume(_track[l].handle, _track[l].vol / 1000);
|
||||
_scumm->_mixer->setChannelPan(_track[l].handle, pan);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (_track[l].stream) {
|
||||
int32 mixer_size = _track[l].pullSize;
|
||||
byte *data = NULL;
|
||||
int32 result = 0;
|
||||
|
||||
if (_track[l].stream->endOfData())
|
||||
mixer_size *= 2;
|
||||
|
||||
do {
|
||||
if (_sound->getBits(_track[l].soundHandle) == 12) {
|
||||
byte *ptr = NULL;
|
||||
mixer_size += _track[l].mod;
|
||||
int length = (((mixer_size * 3) / 4) / 3) * 3;
|
||||
_track[l].mod = ((mixer_size * 3) / 4) - length;
|
||||
mixer_size = length;
|
||||
|
||||
int32 offset = (_track[l].regionOffset * 3) / 4;
|
||||
result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &ptr, offset, mixer_size);
|
||||
int32 result2 = BundleCodecs::decode12BitsSample(ptr, &data, result);
|
||||
result = (result * 4) / 3;
|
||||
if (result != result2) {
|
||||
debug(5, "result: %d, result2: %d", result, result2);
|
||||
result &= ~1;
|
||||
}
|
||||
mixer_size = (mixer_size * 4) / 3;
|
||||
free(ptr);
|
||||
} else if (_sound->getBits(_track[l].soundHandle) == 16) {
|
||||
result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size);
|
||||
if (_sound->getChannels(_track[l].soundHandle) == 2) {
|
||||
if (result & 3)
|
||||
result &= ~2;
|
||||
}
|
||||
if (_sound->getChannels(_track[l].soundHandle) == 1) {
|
||||
if (result & 1)
|
||||
result &= ~1;
|
||||
}
|
||||
} else if (_sound->getBits(_track[l].soundHandle) == 8) {
|
||||
result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size);
|
||||
if (_sound->getChannels(_track[l].soundHandle) == 2) {
|
||||
if (result & 1)
|
||||
result &= ~1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_scumm->_mixer->isReady()) {
|
||||
_scumm->_mixer->setChannelVolume(_track[l].handle, _track[l].vol / 1000);
|
||||
_scumm->_mixer->setChannelPan(_track[l].handle, pan);
|
||||
_track[l].stream->append(data, result);
|
||||
_track[l].regionOffset += result;
|
||||
_track[l].trackOffset += result;
|
||||
free(data);
|
||||
}
|
||||
|
||||
if (_sound->isEndOfRegion(_track[l].soundHandle, _track[l].curRegion)) {
|
||||
switchToNextRegion(l);
|
||||
if (_track[l].toBeRemoved)
|
||||
break;
|
||||
}
|
||||
mixer_size -= result;
|
||||
assert(mixer_size >= 0);
|
||||
} while (mixer_size != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::switchToNextRegion(int track) {
|
||||
// TODO - finish
|
||||
int num_regions = _sound->getNumRegions(_track[track].soundHandle);
|
||||
if (++_track[track].curRegion == num_regions) {
|
||||
_track[track].toBeRemoved = true;
|
||||
return;
|
||||
}
|
||||
_track[track].regionOffset = 0;
|
||||
}
|
||||
|
||||
void IMuseDigital::startSound(int soundId, char *soundName, int soundType, int soundGroup, AudioStream *input) {
|
||||
debug(5, "IMuseDigital::startSound(%d)", soundId);
|
||||
int l;
|
||||
|
||||
for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if (!_track[l].used && !_track[l].handle.isActive()) {
|
||||
_track[l].pan = 64;
|
||||
_track[l].vol = 127 * 1000;
|
||||
_track[l].volFadeDest = 0;
|
||||
_track[l].volFadeStep = 0;
|
||||
_track[l].volFadeDelay = 0;
|
||||
_track[l].volFadeUsed = false;
|
||||
_track[l].idSound = soundId;
|
||||
_track[l].started = false;
|
||||
_track[l].soundGroup = soundGroup;
|
||||
_track[l].curHookId = 0;
|
||||
_track[l].curRegion = 0;
|
||||
_track[l].regionOffset = 0;
|
||||
_track[l].trackOffset = 0;
|
||||
_track[l].mod = 0;
|
||||
_track[l].toBeRemoved = false;
|
||||
|
||||
int bits = 0, freq = 0, channels = 0, mixerFlags = 0;
|
||||
|
||||
if (input) {
|
||||
// Do nothing here, we already have an audio stream
|
||||
} else {
|
||||
if (soundName == NULL)
|
||||
_track[l].soundHandle = _sound->openSound(soundId, NULL, soundType, soundGroup);
|
||||
else
|
||||
_track[l].soundHandle = _sound->openSound(0, soundName, soundType, soundGroup);
|
||||
|
||||
if (_track[l].soundHandle == NULL)
|
||||
return;
|
||||
|
||||
bits = _sound->getBits(_track[l].soundHandle);
|
||||
channels = _sound->getChannels(_track[l].soundHandle);
|
||||
freq = _sound->getFreq(_track[l].soundHandle);
|
||||
|
||||
if (channels == 2) {
|
||||
mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
|
||||
_track[l].pullSize = freq * 2;
|
||||
} else {
|
||||
_track[l].pullSize = freq;
|
||||
}
|
||||
|
||||
if (bits == 12) {
|
||||
mixerFlags |= SoundMixer::FLAG_16BITS;
|
||||
_track[l].pullSize *= 2;
|
||||
} else if (bits == 16) {
|
||||
mixerFlags |= SoundMixer::FLAG_16BITS;
|
||||
_track[l].pullSize *= 2;
|
||||
} else if (bits == 8) {
|
||||
mixerFlags |= SoundMixer::FLAG_UNSIGNED;
|
||||
} else
|
||||
error("IMuseDigital::startSound(): Can't handle %d bit samples", bits);
|
||||
|
||||
_track[l].pullSize /= 25; // We want a "frame rate" of 25 audio blocks per second
|
||||
if (soundGroup == IMUSE_MUSIC)
|
||||
_curMusicId = soundId;
|
||||
}
|
||||
|
||||
if (input) {
|
||||
_track[l].stream2 = input;
|
||||
_track[l].stream = NULL;
|
||||
} else {
|
||||
_track[l].stream2 = NULL;
|
||||
_track[l].stream = makeAppendableAudioStream(freq, mixerFlags, 100000);
|
||||
_scumm->_mixer->playInputStream(&_track[l].handle, _track[l].stream, true, _track[l].vol / 1000, _track[l].pan, -1, false);
|
||||
}
|
||||
|
||||
_track[l].used = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
warning("IMuseDigital::startSound(): All slots are full");
|
||||
}
|
||||
|
||||
void IMuseDigital::stopMusic() {
|
||||
debug(5, "IMuseDigital::stopMusic()");
|
||||
for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if ((_track[l].idSound == _curMusicId) && _track[l].used) {
|
||||
if (_track[l].stream) {
|
||||
_track[l].toBeRemoved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_curMusicId = -1;
|
||||
}
|
||||
|
||||
void IMuseDigital::stopSound(int soundId) {
|
||||
debug(5, "IMuseDigital::stopSound(%d)", soundId);
|
||||
for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if ((_track[l].idSound == soundId) && _track[l].used) {
|
||||
if (_track[l].stream) {
|
||||
_track[l].toBeRemoved = true;
|
||||
}
|
||||
else if (_track[l].stream2)
|
||||
_scumm->_mixer->stopHandle(_track[l].handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::stopAllSounds() {
|
||||
debug(5, "IMuseDigital::stopAllSounds");
|
||||
for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if (_track[l].used) {
|
||||
if (_track[l].stream) {
|
||||
_track[l].toBeRemoved = true;
|
||||
} else if (_track[l].stream2)
|
||||
_scumm->_mixer->stopHandle(_track[l].handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::pause(bool p) {
|
||||
for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if (_track[l].used) {
|
||||
_scumm->_mixer->pauseHandle(_track[l].handle, p);
|
||||
}
|
||||
}
|
||||
_pause = p;
|
||||
}
|
||||
|
||||
void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) {
|
||||
int cmd = a;
|
||||
int sample = b;
|
||||
int sub_cmd = c;
|
||||
int chan = -1;
|
||||
int l, r;
|
||||
|
||||
if (!cmd)
|
||||
return;
|
||||
|
||||
switch (cmd) {
|
||||
case 10: // ImuseStopAllSounds
|
||||
debug(5, "ImuseStopAllSounds()");
|
||||
stopAllSounds();
|
||||
break;
|
||||
case 12: // ImuseSetParam
|
||||
switch (sub_cmd) {
|
||||
case 0x500: // set priority - could be ignored
|
||||
break;
|
||||
case 0x600: // set volume
|
||||
debug(5, "ImuseSetParam (0x600), sample(%d), volume(%d)", sample, d);
|
||||
for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if ((_track[l].idSound == sample) && _track[l].used) {
|
||||
_track[l].vol = d * 1000;
|
||||
// if (_track[l].volFadeUsed)
|
||||
// _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * _track[chan].volFadeDelay);
|
||||
}
|
||||
}
|
||||
if (l == -1) {
|
||||
debug(5, "ImuseSetParam (0x600), sample(%d) not exist in channels", sample);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x700: // set pan
|
||||
debug(5, "ImuseSetParam (0x700), sample(%d), pan(%d)", sample, d);
|
||||
for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if ((_track[l].idSound == sample) && _track[l].used) {
|
||||
_track[l].pan = d;
|
||||
}
|
||||
}
|
||||
if (l == -1) {
|
||||
debug(5, "ImuseSetParam (0x700), sample(%d) not exist in channels", sample);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 14: // ImuseFadeParam
|
||||
switch (sub_cmd) {
|
||||
case 0x600: // set new volume with fading
|
||||
debug(5, "ImuseFadeParam - fade sample(%d), to volume(%d) with 60hz ticks(%d)", sample, d, e);
|
||||
if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
|
||||
stopSound(sample);
|
||||
return;
|
||||
}
|
||||
for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if ((_track[l].idSound == sample) && _track[l].used) {
|
||||
_track[l].volFadeDelay = e;
|
||||
_track[l].volFadeDest = d * 1000;
|
||||
_track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * e);
|
||||
_track[l].volFadeUsed = true;
|
||||
debug(5, "ImuseFadeParam: vol %d, volDest %d, step %d", _track[l].vol, d * 1000, _track[l].volFadeStep);
|
||||
}
|
||||
}
|
||||
if (chan == -1) {
|
||||
debug(5, "ImuseFadeParam (0x600), sample %d not exist in channels", sample);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x1000: // ImuseSetState
|
||||
debug(5, "ImuseSetState (%d)", b);
|
||||
if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
|
||||
if (b == 1)
|
||||
startMusic(1);
|
||||
else {
|
||||
if (getSoundStatus(2) == 0)
|
||||
startMusic(2);
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_DIG) {
|
||||
if (b == 1000) { // STATE_NULL
|
||||
stopMusic();
|
||||
return;
|
||||
}
|
||||
for (l = 0; _digStateMusicMap[l].room != -1; l++) {
|
||||
if (_digStateMusicMap[l].room == b) {
|
||||
int music = _digStateMusicMap[l].table_index;
|
||||
debug(5, "Play imuse music: %s, %s, %s", _digStateMusicTable[music].name, _digStateMusicTable[music].title, _digStateMusicTable[music].filename);
|
||||
if (_digStateMusicTable[music].filename[0] != 0) {
|
||||
startMusic((char *)_digStateMusicTable[music].filename, _digStateMusicTable[music].id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((_scumm->_gameId == GID_CMI) && (_scumm->_features & GF_DEMO)) {
|
||||
if (b == 2) {
|
||||
startMusic("in1.imx", 2002);
|
||||
} else if (b == 4) {
|
||||
startMusic("in2.imx", 2004);
|
||||
} else if (b == 8) {
|
||||
startMusic("out1.imx", 2008);
|
||||
} else if (b == 9) {
|
||||
startMusic("out2.imx", 2009);
|
||||
} else if (b == 16) {
|
||||
startMusic("gun.imx", 2016);
|
||||
} else {
|
||||
warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, this->_scumm->_currentRoom);
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_CMI) {
|
||||
if (b == 1000) { // STATE_NULL
|
||||
stopMusic();
|
||||
return;
|
||||
}
|
||||
for (l = 0; _comiStateMusicTable[l].id != -1; l++) {
|
||||
if ((_comiStateMusicTable[l].id == b)) {
|
||||
debug(5, "Play imuse music: %s, %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].title, _comiStateMusicTable[l].filename);
|
||||
if (_comiStateMusicTable[l].filename[0] != 0) {
|
||||
startMusic((char *)_comiStateMusicTable[l].filename, b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_FT) {
|
||||
for (l = 0;; l++) {
|
||||
if (_ftStateMusicTable[l].index == -1) {
|
||||
return;
|
||||
}
|
||||
if (_ftStateMusicTable[l].index == b) {
|
||||
debug(5, "Play imuse music: %s, %s", _ftStateMusicTable[l].name, _ftStateMusicTable[l].audioname);
|
||||
if (_ftStateMusicTable[l].audioname[0] != 0) {
|
||||
for (r = 0; r < _scumm->_numAudioNames; r++) {
|
||||
if (strcmp(_ftStateMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
|
||||
startMusic(r);
|
||||
parseScriptCmds(12, r, 0x600, _ftStateMusicTable[l].volume, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x1001: // ImuseSetSequence
|
||||
debug(5, "ImuseSetSequence (%d)", b);
|
||||
if (_scumm->_gameId == GID_DIG) {
|
||||
for (l = 0; _digSeqMusicTable[l].room != -1; l++) {
|
||||
if (_digSeqMusicTable[l].room == b) {
|
||||
debug(5, "Play imuse music: %s, %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].title, _digSeqMusicTable[l].filename);
|
||||
if (_digSeqMusicTable[l].filename[0] != 0) {
|
||||
startMusic((char *)_digSeqMusicTable[l].filename, b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_CMI) {
|
||||
for (l = 0; _comiSeqMusicTable[l].id != -1; l++) {
|
||||
if (_comiSeqMusicTable[l].id == b) {
|
||||
debug(5, "Play imuse music: %s, %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].title, _comiSeqMusicTable[l].filename);
|
||||
if (_comiSeqMusicTable[l].filename[0] != 0) {
|
||||
startMusic((char *)_comiSeqMusicTable[l].filename, b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_FT) {
|
||||
for (l = 0; _ftSeqMusicTable[l].index != -1; l++) {
|
||||
if (_ftSeqMusicTable[l].index == b) {
|
||||
debug(5, "Play imuse music: %s, %s", _ftSeqMusicTable[l].name, _ftSeqMusicTable[l].audioname);
|
||||
if (_ftSeqMusicTable[l].audioname[0] != 0) {
|
||||
for (r = 0; r < _scumm->_numAudioNames; r++) {
|
||||
if (strcmp(_ftSeqMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
|
||||
startMusic(r);
|
||||
parseScriptCmds(12, r, 0x600, _ftSeqMusicTable[l].volume, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x1002: // ImuseSetCuePoint
|
||||
debug(5, "ImuseSetCuePoint (%d)", b);
|
||||
// TODO
|
||||
break;
|
||||
case 0x1003: // ImuseSetAttribute
|
||||
debug(5, "ImuseSetAttribute (%d, %d)", b, c);
|
||||
// TODO
|
||||
break;
|
||||
case 0x2000: // ImuseSetMasterSFXVolume
|
||||
debug(5, "ImuseSetMasterSFXVolume (%d)", b);
|
||||
// TODO
|
||||
break;
|
||||
case 0x2001: // ImuseSetMasterVoiceVolume
|
||||
debug(5, "ImuseSetMasterVoiceVolume (%d)", b);
|
||||
// TODO
|
||||
break;
|
||||
case 0x2002: // ImuseSetMasterMusicVolume
|
||||
debug(5, "ImuseSetMasterMusicVolume (%d)", b);
|
||||
// TODO
|
||||
break;
|
||||
default:
|
||||
warning("IMuseDigital::doCommand DEFAULT command %d", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
int IMuseDigital::getSoundStatus(int sound) const {
|
||||
debug(5, "IMuseDigital::getSoundStatus(%d)", sound);
|
||||
for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
|
||||
if ((_track[l].idSound == sound) && _track[l].used) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IMuseDigital::closeBundleFiles() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
int32 IMuseDigital::getCurMusicPosInMs() {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 IMuseDigital::getCurVoiceLipSyncWidth() {
|
||||
// TODO
|
||||
return _scumm->_rnd.getRandomNumber(255);
|
||||
}
|
||||
|
||||
int32 IMuseDigital::getCurVoiceLipSyncHeight() {
|
||||
// TODO
|
||||
return _scumm->_rnd.getRandomNumber(255);
|
||||
}
|
||||
|
||||
int32 IMuseDigital::getCurMusicLipSyncWidth() {
|
||||
// TODO
|
||||
return _scumm->_rnd.getRandomNumber(255);
|
||||
}
|
||||
|
||||
int32 IMuseDigital::getCurMusicLipSyncHeight() {
|
||||
// TODO
|
||||
return _scumm->_rnd.getRandomNumber(255);
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
154
scumm/imuse_digi/dimuse.h
Normal file
154
scumm/imuse_digi/dimuse.h
Normal file
@ -0,0 +1,154 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#ifndef IMUSE_DIGI_H
|
||||
#define IMUSE_DIGI_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/imuse_digi/dimuse_bndmgr.h"
|
||||
#include "scumm/imuse_digi/dimuse_sndmgr.h"
|
||||
#include "scumm/music.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/audiostream.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
#define MAX_DIGITAL_TRACKS 16
|
||||
|
||||
class IMuseDigital : public MusicEngine {
|
||||
private:
|
||||
|
||||
struct Track {
|
||||
int8 pan; // pan
|
||||
int32 vol; // volume
|
||||
int32 volFadeDest; //
|
||||
int32 volFadeStep; //
|
||||
int32 volFadeDelay; //
|
||||
bool volFadeUsed; //
|
||||
|
||||
int idSound;
|
||||
bool used;
|
||||
bool toBeRemoved;
|
||||
bool started;
|
||||
int32 regionOffset;
|
||||
int32 trackOffset;
|
||||
int curRegion;
|
||||
int curHookId;
|
||||
int soundGroup;
|
||||
void *soundHandle;
|
||||
int32 pullSize;
|
||||
int mod;
|
||||
PlayingSoundHandle handle;
|
||||
AppendableAudioStream *stream;
|
||||
AudioStream *stream2;
|
||||
|
||||
Track();
|
||||
};
|
||||
|
||||
Track _track[MAX_DIGITAL_TRACKS];
|
||||
|
||||
ScummEngine *_scumm;
|
||||
ImuseDigiSndMgr *_sound;
|
||||
bool _pause;
|
||||
int _curMusicId;
|
||||
|
||||
static void timer_handler(void *refConf);
|
||||
void callback();
|
||||
void switchToNextRegion(int track);
|
||||
void startSound(int soundId, char *soundName, int soundType, int soundGroup, AudioStream *input);
|
||||
|
||||
public:
|
||||
IMuseDigital(ScummEngine *scumm);
|
||||
~IMuseDigital();
|
||||
|
||||
void startVoice(int soundId, AudioStream *input)
|
||||
{ debug(0, "startVoiceStream(%d)", soundId); startSound(soundId, NULL, 0, IMUSE_VOICE, input); }
|
||||
void startVoice(int soundId)
|
||||
{ debug(0, "startVoiceBundle(%d)", soundId); startSound(soundId, NULL, IMUSE_BUNDLE, IMUSE_VOICE, NULL); }
|
||||
void startVoice(int soundId, char *soundName)
|
||||
{ debug(0, "startVoiceBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOICE, NULL); }
|
||||
void startMusic(int soundId)
|
||||
{ debug(0, "startMusicResource(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_MUSIC, NULL); }
|
||||
void startMusic(char *soundName, int soundId)
|
||||
{ debug(0, "startMusicBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_MUSIC, NULL); }
|
||||
void startSfx(int soundId)
|
||||
{ debug(0, "startSfx(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_SFX, NULL); }
|
||||
void startSound(int soundId)
|
||||
{ error("MusicEngine::startSound() Should be never called"); }
|
||||
|
||||
void setMasterVolume(int vol) {}
|
||||
void stopMusic();
|
||||
void stopSound(int soundId);
|
||||
void stopAllSounds();
|
||||
void pause(bool pause);
|
||||
void parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h);
|
||||
int getSoundStatus(int sound) const;
|
||||
int32 getCurMusicPosInMs();
|
||||
int32 getCurVoiceLipSyncWidth();
|
||||
int32 getCurVoiceLipSyncHeight();
|
||||
int32 getCurMusicLipSyncWidth();
|
||||
int32 getCurMusicLipSyncHeight();
|
||||
|
||||
void closeBundleFiles();
|
||||
};
|
||||
|
||||
struct imuse_music_table {
|
||||
int room;
|
||||
int id;
|
||||
int unk1;
|
||||
int unk2;
|
||||
int unk3;
|
||||
int unk4;
|
||||
char name[30];
|
||||
char title[30];
|
||||
char filename[13];
|
||||
};
|
||||
|
||||
struct imuse_music_map {
|
||||
int room;
|
||||
int table_index;
|
||||
int unk1;
|
||||
int unk2;
|
||||
int unk3;
|
||||
int unk4;
|
||||
};
|
||||
|
||||
struct imuse_ft_music_table {
|
||||
int index;
|
||||
char audioname[15];
|
||||
int unk1;
|
||||
int volume;
|
||||
char name[30];
|
||||
};
|
||||
|
||||
extern imuse_music_map _digStateMusicMap[];
|
||||
extern const imuse_music_table _digStateMusicTable[];
|
||||
extern const imuse_music_table _digSeqMusicTable[];
|
||||
extern const imuse_music_table _comiStateMusicTable[];
|
||||
extern const imuse_music_table _comiSeqMusicTable[];
|
||||
extern const imuse_ft_music_table _ftStateMusicTable[];
|
||||
extern const imuse_ft_music_table _ftSeqMusicTable[];
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
179
scumm/imuse_digi/dimuse_bndmgr.cpp
Normal file
179
scumm/imuse_digi/dimuse_bndmgr.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/imuse_digi/dimuse_bndmgr.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
BundleMgr::BundleMgr() {
|
||||
_compTable = NULL;
|
||||
_bundleTable = NULL;
|
||||
_numFiles = 0;
|
||||
_curSample = -1;
|
||||
}
|
||||
|
||||
BundleMgr::~BundleMgr() {
|
||||
free(_bundleTable);
|
||||
free(_compTable);
|
||||
}
|
||||
|
||||
bool BundleMgr::openFile(const char *filename, const char *directory) {
|
||||
int32 tag, offset;
|
||||
|
||||
if (_file.isOpen())
|
||||
return true;
|
||||
|
||||
if (_file.open(filename, directory) == false) {
|
||||
warning("BundleMgr::openFile() Can't open bundle file: %s", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
tag = _file.readUint32BE();
|
||||
offset = _file.readUint32BE();
|
||||
_numFiles = _file.readUint32BE();
|
||||
|
||||
_bundleTable = (AudioTable *) malloc(_numFiles * sizeof(AudioTable));
|
||||
|
||||
_file.seek(offset, SEEK_SET);
|
||||
|
||||
for (int32 i = 0; i < _numFiles; i++) {
|
||||
char name[13], c;
|
||||
int32 z = 0;
|
||||
int32 z2;
|
||||
|
||||
for (z2 = 0; z2 < 8; z2++)
|
||||
if ((c = _file.readByte()) != 0)
|
||||
name[z++] = c;
|
||||
name[z++] = '.';
|
||||
for (z2 = 0; z2 < 4; z2++)
|
||||
if ((c = _file.readByte()) != 0)
|
||||
name[z++] = c;
|
||||
name[z] = '\0';
|
||||
strcpy(_bundleTable[i].filename, name);
|
||||
_bundleTable[i].offset = _file.readUint32BE();
|
||||
_bundleTable[i].size = _file.readUint32BE();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BundleMgr::closeFile() {
|
||||
if (_file.isOpen()) {
|
||||
_file.close();
|
||||
free(_bundleTable);
|
||||
_bundleTable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int32 BundleMgr::decompressSampleByCurIndex(int32 offset, int32 size, byte **comp_final, int header_size) {
|
||||
return decompressSampleByIndex(_curSample, offset, size, comp_final, header_size);
|
||||
}
|
||||
|
||||
int32 BundleMgr::decompressSampleByIndex(int32 index, int32 offset, int32 size, byte **comp_final, int header_size) {
|
||||
int32 i, tag, num, final_size, output_size;
|
||||
byte *comp_input, *comp_output;
|
||||
|
||||
if (index != -1)
|
||||
_curSample = index;
|
||||
|
||||
if (_file.isOpen() == false) {
|
||||
warning("BundleMgr::decompressSampleByIndex() File is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_file.seek(_bundleTable[index].offset, SEEK_SET);
|
||||
tag = _file.readUint32BE();
|
||||
num = _file.readUint32BE();
|
||||
_file.readUint32BE();
|
||||
_file.readUint32BE();
|
||||
|
||||
if (tag != MKID_BE('COMP')) {
|
||||
warning("BundleMgr::decompressSampleByIndex() Compressed sound %d invalid (%s)", index, tag2str(tag));
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(_compTable);
|
||||
_compTable = (CompTable *)malloc(sizeof(CompTable) * num);
|
||||
for (i = 0; i < num; i++) {
|
||||
_compTable[i].offset = _file.readUint32BE();
|
||||
_compTable[i].size = _file.readUint32BE();
|
||||
_compTable[i].codec = _file.readUint32BE();
|
||||
_file.readUint32BE();
|
||||
}
|
||||
|
||||
int first_block = (offset + header_size) / 0x2000;
|
||||
int last_block = (offset + size + header_size - 1) / 0x2000;
|
||||
|
||||
comp_output = (byte *)malloc(0x2000);
|
||||
*comp_final = (byte *)malloc(0x2000 * (1 + last_block - first_block));
|
||||
final_size = 0;
|
||||
|
||||
int skip = offset - (first_block * 0x2000) + header_size;
|
||||
|
||||
for (i = first_block; i <= last_block; i++) {
|
||||
assert(size);
|
||||
// CMI hack: one more zero byte at the end of input buffer
|
||||
comp_input = (byte *)malloc(_compTable[i].size + 1);
|
||||
comp_input[_compTable[i].size] = 0;
|
||||
|
||||
_file.seek(_bundleTable[index].offset + _compTable[i].offset, SEEK_SET);
|
||||
_file.read(comp_input, _compTable[i].size);
|
||||
|
||||
output_size = BundleCodecs::decompressCodec(_compTable[i].codec, comp_input, comp_output, _compTable[i].size);
|
||||
assert(output_size <= 0x2000);
|
||||
if ((header_size != 0) && (skip > header_size))
|
||||
output_size -= skip;
|
||||
if (output_size > size)
|
||||
output_size = size;
|
||||
memcpy(*comp_final + final_size, comp_output + skip, output_size);
|
||||
final_size += output_size;
|
||||
size -= output_size;
|
||||
if (skip > 0)
|
||||
skip = 0;
|
||||
|
||||
free(comp_input);
|
||||
}
|
||||
free(comp_output);
|
||||
|
||||
return final_size;
|
||||
}
|
||||
|
||||
int32 BundleMgr::decompressSampleByName(const char *name, int32 offset, int32 size, byte **comp_final) {
|
||||
int32 final_size = 0, i;
|
||||
|
||||
if (_file.isOpen() == false) {
|
||||
warning("BundleMgr::decompressSampleByName() File is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < _numFiles; i++) {
|
||||
if (!scumm_stricmp(name, _bundleTable[i].filename)) {
|
||||
final_size = decompressSampleByIndex(i, offset, size, comp_final, 0);
|
||||
return final_size;
|
||||
}
|
||||
}
|
||||
debug(2, "BundleMgr::decompressSampleByName() Failed finding voice %s", name);
|
||||
return final_size;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
72
scumm/imuse_digi/dimuse_bndmgr.h
Normal file
72
scumm/imuse_digi/dimuse_bndmgr.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#ifndef BUNDLE_MGR_H
|
||||
#define BUNDLE_MGR_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class BundleMgr {
|
||||
|
||||
private:
|
||||
|
||||
struct CompTable {
|
||||
int32 offset;
|
||||
int32 size;
|
||||
int32 codec;
|
||||
};
|
||||
|
||||
struct AudioTable {
|
||||
char filename[13];
|
||||
int32 size;
|
||||
int32 offset;
|
||||
};
|
||||
|
||||
CompTable *_compTable;
|
||||
AudioTable *_bundleTable;
|
||||
int32 _numFiles;
|
||||
int32 _curSample;
|
||||
File _file;
|
||||
|
||||
public:
|
||||
BundleMgr();
|
||||
~BundleMgr();
|
||||
|
||||
bool openFile(const char *filename, const char *directory);
|
||||
void closeFile();
|
||||
int32 decompressSampleByName(const char *name, int32 offset, int32 size, byte **comp_final);
|
||||
int32 decompressSampleByIndex(int32 index, int32 offset, int32 size, byte **comp_final, int header_size);
|
||||
int32 decompressSampleByCurIndex(int32 offset, int32 size, byte **comp_final, int header_size);
|
||||
};
|
||||
|
||||
namespace BundleCodecs {
|
||||
|
||||
uint32 decode12BitsSample(byte *src, byte **dst, uint32 size);
|
||||
void initializeImcTables();
|
||||
int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size);
|
||||
|
||||
} // End of namespace BundleCodecs
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2002-2004 The ScummVM project
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -20,11 +20,33 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/bundle.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
namespace BundleCodecs {
|
||||
|
||||
uint32 decode12BitsSample(byte *src, byte **dst, uint32 size) {
|
||||
uint32 loop_size = size / 3;
|
||||
uint32 s_size = loop_size * 4;
|
||||
byte *ptr = *dst = (byte *)malloc(s_size);
|
||||
|
||||
uint32 tmp;
|
||||
while (loop_size--) {
|
||||
byte v1 = *src++;
|
||||
byte v2 = *src++;
|
||||
byte v3 = *src++;
|
||||
tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000;
|
||||
WRITE_BE_UINT16(ptr, tmp); ptr += 2;
|
||||
tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000;
|
||||
WRITE_BE_UINT16(ptr, tmp); ptr += 2;
|
||||
}
|
||||
return s_size;
|
||||
}
|
||||
|
||||
static byte _destImcTable[93];
|
||||
static uint32 _destImcTable2[5697];
|
||||
|
||||
#ifdef __PALM_OS__
|
||||
static const int16 *imcTable;
|
||||
#else
|
||||
@ -97,30 +119,7 @@ static const byte imxShortTable[] = {
|
||||
0, 0, 1, 3, 7, 15, 31, 63
|
||||
};
|
||||
|
||||
|
||||
Bundle::Bundle() {
|
||||
_compVoiceTable = NULL;
|
||||
_compMusicTable = NULL;
|
||||
|
||||
_bundleVoiceTable = NULL;
|
||||
_bundleMusicTable = NULL;
|
||||
|
||||
_numVoiceFiles = 0;
|
||||
_numMusicFiles = 0;
|
||||
|
||||
_lastSong = -1;
|
||||
|
||||
initializeImcTables();
|
||||
}
|
||||
|
||||
Bundle::~Bundle() {
|
||||
free(_bundleVoiceTable);
|
||||
free(_bundleMusicTable);
|
||||
free(_compVoiceTable);
|
||||
free(_compMusicTable);
|
||||
}
|
||||
|
||||
void Bundle::initializeImcTables() {
|
||||
void initializeImcTables() {
|
||||
int32 destTablePos = 0;
|
||||
int32 imcTable1Pos = 0;
|
||||
do {
|
||||
@ -163,279 +162,6 @@ void Bundle::initializeImcTables() {
|
||||
} while (++imcTable1Pos <= 88);
|
||||
}
|
||||
}
|
||||
|
||||
bool Bundle::openVoiceFile(const char *filename, const char *directory) {
|
||||
int32 tag, offset;
|
||||
|
||||
if (_voiceFile.isOpen())
|
||||
return true;
|
||||
|
||||
if (_voiceFile.open(filename, directory) == false) {
|
||||
warning("Bundle: Can't open voice bundle file: %s", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
tag = _voiceFile.readUint32BE();
|
||||
offset = _voiceFile.readUint32BE();
|
||||
_numVoiceFiles = _voiceFile.readUint32BE();
|
||||
|
||||
_bundleVoiceTable = (BundleAudioTable *) malloc(_numVoiceFiles * sizeof(BundleAudioTable));
|
||||
|
||||
_voiceFile.seek(offset, SEEK_SET);
|
||||
|
||||
for (int32 i = 0; i < _numVoiceFiles; i++) {
|
||||
char name[13], c;
|
||||
int32 z = 0;
|
||||
int32 z2;
|
||||
|
||||
for (z2 = 0; z2 < 8; z2++)
|
||||
if ((c = _voiceFile.readByte()) != 0)
|
||||
name[z++] = c;
|
||||
name[z++] = '.';
|
||||
for (z2 = 0; z2 < 4; z2++)
|
||||
if ((c = _voiceFile.readByte()) != 0)
|
||||
name[z++] = c;
|
||||
name[z] = '\0';
|
||||
strcpy(_bundleVoiceTable[i].filename, name);
|
||||
_bundleVoiceTable[i].offset = _voiceFile.readUint32BE();
|
||||
_bundleVoiceTable[i].size = _voiceFile.readUint32BE();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Bundle::closeVoiceFile() {
|
||||
if (_voiceFile.isOpen()) {
|
||||
_voiceFile.close();
|
||||
free(_bundleVoiceTable);
|
||||
_bundleVoiceTable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Bundle::openMusicFile(const char *filename, const char *directory) {
|
||||
int32 tag, offset;
|
||||
|
||||
if (_musicFile.isOpen())
|
||||
return true;
|
||||
|
||||
if (_musicFile.open(filename, directory) == false) {
|
||||
warning("Bundle: Can't open music bundle file: %s", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
tag = _musicFile.readUint32BE();
|
||||
offset = _musicFile.readUint32BE();
|
||||
_numMusicFiles = _musicFile.readUint32BE();
|
||||
|
||||
_bundleMusicTable = (BundleAudioTable *) malloc(_numMusicFiles * sizeof(BundleAudioTable));
|
||||
|
||||
_musicFile.seek(offset, SEEK_SET);
|
||||
|
||||
for (int32 i = 0; i < _numMusicFiles; i++) {
|
||||
char name[13], c;
|
||||
int z = 0;
|
||||
int z2;
|
||||
|
||||
for (z2 = 0; z2 < 8; z2++)
|
||||
if ((c = _musicFile.readByte()) != 0)
|
||||
name[z++] = c;
|
||||
name[z++] = '.';
|
||||
for (z2 = 0; z2 < 4; z2++)
|
||||
if ((c = _musicFile.readByte()) != 0)
|
||||
name[z++] = c;
|
||||
name[z] = '\0';
|
||||
strcpy(_bundleMusicTable[i].filename, name);
|
||||
_bundleMusicTable[i].offset = _musicFile.readUint32BE();
|
||||
_bundleMusicTable[i].size = _musicFile.readUint32BE();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Bundle::closeMusicFile() {
|
||||
if (_musicFile.isOpen()) {
|
||||
_musicFile.close();
|
||||
free(_bundleMusicTable);
|
||||
_bundleMusicTable = NULL;
|
||||
_lastSong = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32 Bundle::decompressVoiceSampleByIndex(int32 index, byte **comp_final) {
|
||||
int32 i, tag, num, final_size, output_size;
|
||||
byte *comp_input, *comp_output;
|
||||
|
||||
if (_voiceFile.isOpen() == false) {
|
||||
warning("Bundle: voice file is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_voiceFile.seek(_bundleVoiceTable[index].offset, SEEK_SET);
|
||||
tag = _voiceFile.readUint32BE();
|
||||
num = _voiceFile.readUint32BE();
|
||||
_voiceFile.readUint32BE();
|
||||
_voiceFile.readUint32BE();
|
||||
|
||||
if (tag != MKID_BE('COMP')) {
|
||||
warning("Bundle: Compressed sound %d invalid (%s)", index, tag2str(tag));
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(_compVoiceTable);
|
||||
_compVoiceTable = (CompTable *)malloc(sizeof(CompTable) * num);
|
||||
for (i = 0; i < num; i++) {
|
||||
_compVoiceTable[i].offset = _voiceFile.readUint32BE();
|
||||
_compVoiceTable[i].size = _voiceFile.readUint32BE();
|
||||
_compVoiceTable[i].codec = _voiceFile.readUint32BE();
|
||||
_voiceFile.readUint32BE();
|
||||
}
|
||||
|
||||
final_size = 0;
|
||||
|
||||
comp_output = (byte *)malloc(0x2000);
|
||||
|
||||
*comp_final = (byte *)malloc(0x2000 * num);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
// CMI hack: one more zero byte at the end of input buffer
|
||||
comp_input = (byte *)malloc(_compVoiceTable[i].size + 1);
|
||||
comp_input[_compVoiceTable[i].size] = 0;
|
||||
|
||||
_voiceFile.seek(_bundleVoiceTable[index].offset + _compVoiceTable[i].offset, SEEK_SET);
|
||||
_voiceFile.read(comp_input, _compVoiceTable[i].size);
|
||||
|
||||
output_size = decompressCodec(_compVoiceTable[i].codec, comp_input, comp_output, _compVoiceTable[i].size);
|
||||
assert(output_size <= 0x2000);
|
||||
memcpy(*comp_final + final_size, comp_output, output_size);
|
||||
final_size += output_size;
|
||||
|
||||
free(comp_input);
|
||||
}
|
||||
free(comp_output);
|
||||
|
||||
return final_size;
|
||||
}
|
||||
|
||||
int32 Bundle::decompressMusicSampleByIndex(int32 index, int32 number, byte *comp_final) {
|
||||
int final_size;
|
||||
byte *comp_input;
|
||||
|
||||
if (_musicFile.isOpen() == false) {
|
||||
warning("Bundle: music file is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_lastSong != index) {
|
||||
int i, tag, num;
|
||||
_musicFile.seek(_bundleMusicTable[index].offset, SEEK_SET);
|
||||
tag = _musicFile.readUint32BE();
|
||||
num = _musicFile.readUint32BE();
|
||||
_musicFile.readUint32BE();
|
||||
_musicFile.readUint32BE();
|
||||
|
||||
if (tag != MKID_BE('COMP')) {
|
||||
warning("Bundle: Compressed sound %d invalid (%s)", index, tag2str(tag));
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(_compMusicTable);
|
||||
_compMusicTable = (CompTable *)malloc(sizeof(CompTable) * num);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
_compMusicTable[i].offset = _musicFile.readUint32BE();
|
||||
_compMusicTable[i].size = _musicFile.readUint32BE();
|
||||
_compMusicTable[i].codec = _musicFile.readUint32BE();
|
||||
_musicFile.readUint32BE();
|
||||
}
|
||||
|
||||
_lastSong = index;
|
||||
}
|
||||
|
||||
// CMI hack: one more zero byte at the end of input buffer
|
||||
comp_input = (byte *)malloc(_compMusicTable[number].size + 1);
|
||||
comp_input[_compMusicTable[number].size] = 0;
|
||||
|
||||
_musicFile.seek(_bundleMusicTable[index].offset + _compMusicTable[number].offset, SEEK_SET);
|
||||
_musicFile.read(comp_input, _compMusicTable[number].size);
|
||||
|
||||
final_size = decompressCodec(_compMusicTable[number].codec, comp_input, comp_final, _compMusicTable[number].size);
|
||||
|
||||
free(comp_input);
|
||||
|
||||
return final_size;
|
||||
}
|
||||
|
||||
int32 Bundle::decompressVoiceSampleByName(const char *name, byte **comp_final) {
|
||||
int32 final_size = 0, i;
|
||||
|
||||
if (_voiceFile.isOpen() == false) {
|
||||
warning("Bundle: voice file is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < _numVoiceFiles; i++) {
|
||||
if (!scumm_stricmp(name, _bundleVoiceTable[i].filename)) {
|
||||
final_size = decompressVoiceSampleByIndex(i, comp_final);
|
||||
return final_size;
|
||||
}
|
||||
}
|
||||
debug(2, "Failed finding voice %s", name);
|
||||
return final_size;
|
||||
}
|
||||
|
||||
int32 Bundle::decompressMusicSampleByName(const char *name, int32 number, byte *comp_final) {
|
||||
int32 final_size = 0, i;
|
||||
|
||||
if (!name) {
|
||||
warning("Bundle: decompressMusicSampleByName called with no name!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_musicFile.isOpen() == false) {
|
||||
warning("Bundle: music file is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < _numMusicFiles; i++) {
|
||||
if (!scumm_stricmp(name, _bundleMusicTable[i].filename)) {
|
||||
final_size = decompressMusicSampleByIndex(i, number, comp_final);
|
||||
return final_size;
|
||||
}
|
||||
}
|
||||
warning("Couldn't find sample %s", name);
|
||||
return final_size;
|
||||
}
|
||||
|
||||
int32 Bundle::getNumberOfMusicSamplesByIndex(int32 index) {
|
||||
if (_musicFile.isOpen() == false) {
|
||||
warning("Bundle: music file is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_musicFile.seek(_bundleMusicTable[index].offset, SEEK_SET);
|
||||
_musicFile.readUint32BE();
|
||||
return _musicFile.readUint32BE();
|
||||
}
|
||||
|
||||
int32 Bundle::getNumberOfMusicSamplesByName(const char *name) {
|
||||
int32 number = 0, i;
|
||||
|
||||
if (_musicFile.isOpen() == false) {
|
||||
warning("Bundle: music file is not open!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < _numMusicFiles; i++) {
|
||||
if (!scumm_stricmp(name, _bundleMusicTable[i].filename)) {
|
||||
number = getNumberOfMusicSamplesByIndex(i);
|
||||
return number;
|
||||
}
|
||||
}
|
||||
warning("Couldn't find numsample %s", name);
|
||||
return number;
|
||||
}
|
||||
|
||||
#define NextBit \
|
||||
do { \
|
||||
bit = mask & 1; \
|
||||
@ -483,7 +209,7 @@ static int32 compDecode(byte *src, byte *dst) {
|
||||
}
|
||||
#undef NextBit
|
||||
|
||||
int32 Bundle::decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size) {
|
||||
int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size) {
|
||||
int32 output_size, channels;
|
||||
int32 offset1, offset2, offset3, length, k, c, s, j, r, t, z;
|
||||
byte *src, *t_table, *p, *ptr;
|
||||
@ -946,7 +672,7 @@ int32 Bundle::decompressCodec(int32 codec, byte *comp_input, byte *comp_output,
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("Bundle: Unknown codec %d!", (int)codec);
|
||||
error("BundleCodecs::decompressCodec() Unknown codec %d!", (int)codec);
|
||||
output_size = 0;
|
||||
break;
|
||||
}
|
||||
@ -954,19 +680,19 @@ int32 Bundle::decompressCodec(int32 codec, byte *comp_input, byte *comp_output,
|
||||
return output_size;
|
||||
}
|
||||
|
||||
} // End of namespace BundleCodecs
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#ifdef __PALM_OS__
|
||||
#include "scumm_globals.h"
|
||||
|
||||
_GINIT(Bundle)
|
||||
_GSETPTR(Scumm::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM)
|
||||
_GINIT(BundleCodecs)
|
||||
_GSETPTR(Scumm::BundleCodecs::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM)
|
||||
_GEND
|
||||
|
||||
_GRELEASE(Bundle)
|
||||
_GRELEASE(BundleCodecs)
|
||||
_GRELEASEPTR(GBVARS_IMCTABLE_INDEX, GBVARS_SCUMM)
|
||||
_GEND
|
||||
|
||||
#endif
|
||||
|
||||
|
462
scumm/imuse_digi/dimuse_sndmgr.cpp
Normal file
462
scumm/imuse_digi/dimuse_sndmgr.cpp
Normal file
@ -0,0 +1,462 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/util.h"
|
||||
#include "sound/voc.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/imuse_digi/dimuse_sndmgr.h"
|
||||
#include "scumm/imuse_digi/dimuse_bndmgr.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) {
|
||||
memset(&_sounds, 0, sizeof(_sounds));
|
||||
_scumm = scumm;
|
||||
_mutex = g_system->create_mutex();
|
||||
_disk = 0;
|
||||
_accessFree = true;
|
||||
BundleCodecs::initializeImcTables();
|
||||
}
|
||||
|
||||
ImuseDigiSndMgr::~ImuseDigiSndMgr() {
|
||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||
closeSound(&_sounds[l]);
|
||||
}
|
||||
}
|
||||
|
||||
void ImuseDigiSndMgr::waitForFreeAccess() {
|
||||
Common::StackLock lock(_mutex);
|
||||
while (!_accessFree) {
|
||||
}
|
||||
}
|
||||
|
||||
void ImuseDigiSndMgr::lock() {
|
||||
Common::StackLock lock(_mutex);
|
||||
waitForFreeAccess();
|
||||
_accessFree = false;
|
||||
}
|
||||
|
||||
void ImuseDigiSndMgr::unlock() {
|
||||
Common::StackLock lock(_mutex);
|
||||
_accessFree = true;
|
||||
}
|
||||
|
||||
void ImuseDigiSndMgr::prepareSound(byte *ptr, int slot) {
|
||||
Common::StackLock lock(_mutex);
|
||||
if (READ_UINT32(ptr) == MKID('Crea')) {
|
||||
int size, rate, loops;
|
||||
_sounds[slot].resPtr = readVOCFromMemory(ptr, size, rate, loops);
|
||||
_sounds[slot].freeResPtr = true;
|
||||
_sounds[slot].bits = 8;
|
||||
_sounds[slot].freq = rate;
|
||||
_sounds[slot].channels = 1;
|
||||
_sounds[slot].region[0].length = size;
|
||||
_sounds[slot].numRegions++;
|
||||
_sounds[slot].numJumps++;
|
||||
} else if (READ_UINT32(ptr) == MKID('iMUS')) {
|
||||
uint32 tag;
|
||||
int32 size = 0;
|
||||
byte *s_ptr = ptr;
|
||||
|
||||
ptr += 16;
|
||||
do {
|
||||
tag = READ_BE_UINT32(ptr); ptr += 4;
|
||||
switch(tag) {
|
||||
case MKID_BE('FRMT'):
|
||||
ptr += 12;
|
||||
_sounds[slot].bits = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].freq = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].channels = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
case MKID_BE('TEXT'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
if (_sounds[slot].numMarkers >= MAX_IMUSE_MARKERS) {
|
||||
warning("ImuseDigiSndMgr::prepareSound() Not enough space for Marker");
|
||||
ptr += size;
|
||||
break;
|
||||
}
|
||||
strcpy(_sounds[slot].marker[_sounds[slot].numMarkers].name, (char *)ptr + 4);
|
||||
_sounds[slot].numMarkers++;
|
||||
ptr += size;
|
||||
break;
|
||||
case MKID_BE('REGN'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
if (_sounds[slot].numRegions >= MAX_IMUSE_REGIONS) {
|
||||
warning("ImuseDigiSndMgr::prepareSound() Not enough space for Region");
|
||||
ptr += 8;
|
||||
break;
|
||||
}
|
||||
_sounds[slot].region[_sounds[slot].numRegions].offset = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].region[_sounds[slot].numRegions].length = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].numRegions++;
|
||||
break;
|
||||
case MKID_BE('STOP'):
|
||||
ptr += 4;
|
||||
_sounds[slot].offsetStop = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
case MKID_BE('JUMP'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
if (_sounds[slot].numJumps >= MAX_IMUSE_JUMPS) {
|
||||
warning("ImuseDigiSndMgr::prepareSound() Not enough space for Jump");
|
||||
ptr += size;
|
||||
break;
|
||||
}
|
||||
_sounds[slot].jump[_sounds[slot].numJumps].offset = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].jump[_sounds[slot].numJumps].dest = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].jump[_sounds[slot].numJumps].hookId = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].jump[_sounds[slot].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_sounds[slot].numJumps++;
|
||||
break;
|
||||
case MKID_BE('SYNC'):
|
||||
size = READ_BE_UINT32(ptr); ptr += size + 4;
|
||||
break;
|
||||
case MKID_BE('DATA'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
default:
|
||||
error("ImuseDigiSndMgr::prepareSound() Unknown sfx header '%s'", tag2str(tag));
|
||||
}
|
||||
} while (tag != MKID_BE('DATA'));
|
||||
_sounds[slot].offsetData = ptr - s_ptr;
|
||||
} else {
|
||||
error("ImuseDigiSndMgr::prepareSound(): Unknown sound format");
|
||||
}
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::allocSlot() {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||
if (!_sounds[l].inUse) {
|
||||
_sounds[l].inUse = true;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ImuseDigiSndMgr::openMusicBundle(int slot) {
|
||||
Common::StackLock lock(_mutex);
|
||||
bool result = false;
|
||||
|
||||
_sounds[slot]._bundle = new BundleMgr();
|
||||
if (_scumm->_gameId == GID_CMI) {
|
||||
if (_scumm->_features & GF_DEMO) {
|
||||
result = _sounds[slot]._bundle->openFile("music.bun", _scumm->getGameDataPath());
|
||||
} else {
|
||||
char musicfile[20];
|
||||
sprintf(musicfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
|
||||
if (_disk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
|
||||
_sounds[slot]._bundle->closeFile();
|
||||
|
||||
result = _sounds[slot]._bundle->openFile(musicfile, _scumm->getGameDataPath());
|
||||
|
||||
if (result == false)
|
||||
result = _sounds[slot]._bundle->openFile("music.bun", _scumm->getGameDataPath());
|
||||
_disk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_DIG)
|
||||
result = _sounds[slot]._bundle->openFile("digmusic.bun", _scumm->getGameDataPath());
|
||||
else
|
||||
error("ImuseDigiSndMgr::openMusicBundle() Don't know which bundle file to load");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ImuseDigiSndMgr::openVoiceBundle(int slot) {
|
||||
Common::StackLock lock(_mutex);
|
||||
bool result = false;
|
||||
|
||||
_sounds[slot]._bundle = new BundleMgr();
|
||||
if (_scumm->_gameId == GID_CMI) {
|
||||
if (_scumm->_features & GF_DEMO) {
|
||||
result = _sounds[slot]._bundle->openFile("voice.bun", _scumm->getGameDataPath());
|
||||
} else {
|
||||
char voxfile[20];
|
||||
sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
|
||||
if (_disk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
|
||||
_sounds[slot]._bundle->closeFile();
|
||||
|
||||
result = _sounds[slot]._bundle->openFile(voxfile, _scumm->getGameDataPath());
|
||||
|
||||
if (result == false)
|
||||
result = _sounds[slot]._bundle->openFile("voice.bun", _scumm->getGameDataPath());
|
||||
_disk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_DIG)
|
||||
result = _sounds[slot]._bundle->openFile("digvoice.bun", _scumm->getGameDataPath());
|
||||
else
|
||||
error("ImuseDigiSndMgr::openVoiceBundle() Don't know which bundle file to load");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void *ImuseDigiSndMgr::openSound(int32 soundId, char *soundName, int soundType, int soundGroup) {
|
||||
assert(soundId >= 0);
|
||||
assert(soundType);
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
|
||||
int slot = allocSlot();
|
||||
if (slot == -1) {
|
||||
error("ImuseDigiSndMgr::openSound() can't alloc free sound slot");
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
byte *ptr = NULL;
|
||||
|
||||
if (soundName == NULL) {
|
||||
if ((soundType == IMUSE_RESOURCE)) {
|
||||
ptr = _scumm->getResourceAddress(rtSound, soundId);
|
||||
if (ptr == NULL) {
|
||||
closeSound(&_sounds[slot]);
|
||||
unlock();
|
||||
return NULL;
|
||||
}
|
||||
_sounds[slot].resPtr = ptr;
|
||||
result = true;
|
||||
} else if (soundType == IMUSE_BUNDLE) {
|
||||
if (soundGroup == IMUSE_VOICE)
|
||||
result = openVoiceBundle(slot);
|
||||
else if (soundGroup == IMUSE_MUSIC)
|
||||
result = openMusicBundle(slot);
|
||||
else
|
||||
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
|
||||
_sounds[slot]._bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0);
|
||||
} else {
|
||||
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
|
||||
}
|
||||
} else if (soundName != NULL) {
|
||||
if (soundType == IMUSE_BUNDLE) {
|
||||
if (soundGroup == IMUSE_VOICE)
|
||||
result = openVoiceBundle(slot);
|
||||
else if (soundGroup == IMUSE_MUSIC)
|
||||
result = openMusicBundle(slot);
|
||||
else
|
||||
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
|
||||
_sounds[slot]._bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr);
|
||||
} else {
|
||||
error("ImuseDigiSndMgr::openSound() Don't know how load sound: %s", soundName);
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
if (ptr == NULL) {
|
||||
closeSound(&_sounds[slot]);
|
||||
unlock();
|
||||
return NULL;
|
||||
}
|
||||
prepareSound(ptr, slot);
|
||||
void *soundHandle = &_sounds[slot];
|
||||
unlock();
|
||||
return soundHandle;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ImuseDigiSndMgr::closeSound(void *soundHandle) {
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||
if (&_sounds[l] == soundHandle) {
|
||||
if (_sounds[l].freeResPtr)
|
||||
free(_sounds[l].resPtr);
|
||||
if (_sounds[l]._bundle)
|
||||
delete _sounds[l]._bundle;
|
||||
memset(&_sounds[l], 0, sizeof(soundStruct));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ImuseDigiSndMgr::checkForProperHandle(void *soundHandle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||
if (soundHandle == &_sounds[l])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getFreq(void *soundHandle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
int result = ((soundStruct *)soundHandle)->freq;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getBits(void *soundHandle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
int result = ((soundStruct *)soundHandle)->bits;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getChannels(void *soundHandle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
int result = ((soundStruct *)soundHandle)->channels;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ImuseDigiSndMgr::isEndOfRegion(void *soundHandle, int region) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
assert(region >= 0 && region < ((soundStruct *)soundHandle)->numRegions);
|
||||
bool result = ((soundStruct *)soundHandle)->endFlag;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getNumRegions(void *soundHandle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
int result = ((soundStruct *)soundHandle)->numRegions;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getNumJumps(void *soundHandle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
int result = ((soundStruct *)soundHandle)->numJumps;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getNumMarkers(void *soundHandle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
int result = ((soundStruct *)soundHandle)->numMarkers;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getJumpIdByRegion(void *soundHandle, int number) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
assert(number >= 0 && number < ((soundStruct *)soundHandle)->numRegions);
|
||||
for (int l = 0; l < ((soundStruct *)soundHandle)->numJumps; l++) {
|
||||
if (((soundStruct *)soundHandle)->jump[number].offset == ((soundStruct *)soundHandle)->region[l].offset)
|
||||
unlock();
|
||||
return l;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getJumpDestRegionId(void *soundHandle, int number) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps);
|
||||
for (int l = 0; l < ((soundStruct *)soundHandle)->numRegions; l++) {
|
||||
if (((soundStruct *)soundHandle)->jump[number].dest == ((soundStruct *)soundHandle)->region[l].offset) {
|
||||
unlock();
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
unlock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getJumpHookId(void *soundHandle, int number) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps);
|
||||
int result = ((soundStruct *)soundHandle)->jump[number].hookId;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImuseDigiSndMgr::getJumpFade(void *soundHandle, int number) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps);
|
||||
unlock();
|
||||
return ((soundStruct *)soundHandle)->jump[number].fadeDelay;
|
||||
}
|
||||
|
||||
char *ImuseDigiSndMgr::getMarker(void *soundHandle, int number) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
assert(number >= 0 && number < ((soundStruct *)soundHandle)->numMarkers);
|
||||
char *result = (char *)(((soundStruct *)soundHandle)->marker[number].name);
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int32 ImuseDigiSndMgr::getDataFromRegion(void *soundHandle, int region, byte **buf, int32 offset, int32 size) {
|
||||
Common::StackLock lock(_mutex);
|
||||
ImuseDigiSndMgr::lock();
|
||||
assert(soundHandle && checkForProperHandle(soundHandle));
|
||||
assert(buf && offset >= 0 && size >= 0);
|
||||
assert(region >= 0 && region < ((soundStruct *)soundHandle)->numRegions);
|
||||
|
||||
int32 region_offset = ((soundStruct *)soundHandle)->region[region].offset;
|
||||
int32 region_length = ((soundStruct *)soundHandle)->region[region].length;
|
||||
int32 offset_data = ((soundStruct *)soundHandle)->offsetData;
|
||||
int32 start = region_offset - offset_data;
|
||||
|
||||
if (offset + size + offset_data > region_length) {
|
||||
size = region_length - offset;
|
||||
((soundStruct *)soundHandle)->endFlag = true;
|
||||
} else {
|
||||
((soundStruct *)soundHandle)->endFlag = false;
|
||||
}
|
||||
|
||||
int header_size = ((soundStruct *)soundHandle)->offsetData;
|
||||
|
||||
if (((soundStruct *)soundHandle)->_bundle) {
|
||||
// *buf = (byte *)malloc(size);
|
||||
// memset(*buf, 0, size);
|
||||
size = ((soundStruct *)soundHandle)->_bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size);
|
||||
} else if (((soundStruct *)soundHandle)->resPtr) {
|
||||
byte *ptr = ((soundStruct *)soundHandle)->resPtr;
|
||||
*buf = (byte *)malloc(size);
|
||||
// warning("%d, %d, %d", start + header_size + offset, region_offset + region_length, size);
|
||||
memcpy(*buf, ptr + start + offset + header_size, size);
|
||||
}
|
||||
|
||||
unlock();
|
||||
return size;
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
126
scumm/imuse_digi/dimuse_sndmgr.h
Normal file
126
scumm/imuse_digi/dimuse_sndmgr.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2001-2004 The ScummVM project
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* $Header$
|
||||
*/
|
||||
|
||||
#ifndef IMUSE_DIGI_SNDMGR_H
|
||||
#define IMUSE_DIGI_SNDMGR_H
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
class ScummEngine;
|
||||
class BundleMgr;
|
||||
|
||||
class ImuseDigiSndMgr {
|
||||
public:
|
||||
|
||||
#define MAX_IMUSE_SOUNDS 20
|
||||
#define MAX_IMUSE_JUMPS 50
|
||||
#define MAX_IMUSE_REGIONS 50
|
||||
#define MAX_IMUSE_MARKERS 50
|
||||
|
||||
#define IMUSE_RESOURCE 1
|
||||
#define IMUSE_BUNDLE 2
|
||||
#define IMUSE_VOICE 1
|
||||
#define IMUSE_SFX 2
|
||||
#define IMUSE_MUSIC 3
|
||||
|
||||
private:
|
||||
struct _region {
|
||||
int32 offset; // offset of region
|
||||
int32 length; // lenght of region
|
||||
};
|
||||
|
||||
struct _jump {
|
||||
int32 offset; // jump offset position
|
||||
int32 dest; // jump to dest position
|
||||
int hookId; // id of hook
|
||||
int fadeDelay; // fade delay in ms
|
||||
};
|
||||
|
||||
struct _marker {
|
||||
char name[256]; // name of marker
|
||||
};
|
||||
|
||||
struct soundStruct {
|
||||
int freq; // frequency
|
||||
int channels; // stereo or mono
|
||||
int bits; // 8, 12, 16
|
||||
int numJumps; // number of Jumps
|
||||
int numRegions; // number of Regions
|
||||
int numMarkers; // number of Markers
|
||||
int32 offsetStop; // end offset in source data
|
||||
bool endFlag;
|
||||
bool inUse;
|
||||
byte *allData;
|
||||
int32 offsetData;
|
||||
byte *resPtr;
|
||||
bool freeResPtr;
|
||||
BundleMgr *_bundle;
|
||||
_region region[MAX_IMUSE_REGIONS];
|
||||
_marker marker[MAX_IMUSE_MARKERS];
|
||||
_jump jump[MAX_IMUSE_JUMPS];
|
||||
} _sounds[MAX_IMUSE_SOUNDS];
|
||||
|
||||
bool checkForProperHandle(void *soundHandle);
|
||||
int allocSlot();
|
||||
void prepareSound(byte *ptr, int slot);
|
||||
|
||||
ScummEngine *_scumm;
|
||||
OSystem::MutexRef _mutex;
|
||||
byte _disk;
|
||||
bool _accessFree;
|
||||
|
||||
void waitForFreeAccess();
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
bool openMusicBundle(int slot);
|
||||
bool openVoiceBundle(int slot);
|
||||
|
||||
public:
|
||||
|
||||
ImuseDigiSndMgr(ScummEngine *scumm);
|
||||
~ImuseDigiSndMgr();
|
||||
|
||||
void *openSound(int32 soundId, char *soundName, int soundType, int soundGroup);
|
||||
void closeSound(void *soundHandle);
|
||||
|
||||
int getFreq(void *soundHandle);
|
||||
int getBits(void *soundHandle);
|
||||
int getChannels(void *soundHandle);
|
||||
bool isEndOfRegion(void *soundHandle, int region);
|
||||
int getNumRegions(void *soundHandle);
|
||||
int getNumJumps(void *soundHandle);
|
||||
int getNumMarkers(void *soundHandle);
|
||||
int getJumpIdByRegion(void *soundHandle, int number);
|
||||
int getJumpDestRegionId(void *soundHandle, int number);
|
||||
int getJumpHookId(void *soundHandle, int number);
|
||||
int getJumpFade(void *soundHandle, int number);
|
||||
char *getMarker(void *soundHandle, int number);
|
||||
|
||||
int32 getDataFromRegion(void *soundHandle, int region, byte **buf, int32 offset, int32 size);
|
||||
};
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#endif
|
@ -19,50 +19,11 @@
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "common/timer.h"
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/bundle.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/sound.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/voc.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
|
||||
namespace Scumm {
|
||||
|
||||
struct imuse_music_table {
|
||||
int room;
|
||||
int id;
|
||||
int unk1;
|
||||
int unk2;
|
||||
int unk3;
|
||||
int unk4;
|
||||
char name[30];
|
||||
char title[30];
|
||||
char filename[13];
|
||||
};
|
||||
|
||||
struct imuse_music_map {
|
||||
int room;
|
||||
int table_index;
|
||||
int unk1;
|
||||
int unk2;
|
||||
int unk3;
|
||||
int unk4;
|
||||
};
|
||||
|
||||
#ifdef __PALM_OS__
|
||||
// these games are currently not supported under PalmOS so we can save this space
|
||||
// to prevent full data segement
|
||||
static const imuse_music_map *_digStateMusicMap;
|
||||
static const imuse_music_table *_digStateMusicTable;
|
||||
static const imuse_music_table *_comiStateMusicTable;
|
||||
static const imuse_music_table *_comiSeqMusicTable;
|
||||
static const imuse_music_table *_digSeqMusicTable;
|
||||
#else
|
||||
static const imuse_music_map _digStateMusicMap[] = {
|
||||
imuse_music_map _digStateMusicMap[] = {
|
||||
{0, 0, 0, 0, 0, 0 },
|
||||
{1, 0, 0, 0, 0, 0 },
|
||||
{2, 2, 0, 0, 0, 0 },
|
||||
@ -180,7 +141,7 @@ static const imuse_music_map _digStateMusicMap[] = {
|
||||
{-1, 1, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const imuse_music_table _digStateMusicTable[] = {
|
||||
const imuse_music_table _digStateMusicTable[] = {
|
||||
{0, 1000, 0, 0, 0, 0, "STATE_NULL", "", ""},
|
||||
{1, 1001, 0, 0, 0, 0, "stateNoChange", "", ""},
|
||||
{2, 1100, 0, 3, 2, 0, "stateAstShip", "Asteroid (amb-ship)", "ASTERO~1.IMU"},
|
||||
@ -248,7 +209,7 @@ static const imuse_music_table _digStateMusicTable[] = {
|
||||
{-1, -1, 0, 0, 0, 0, "", "", ""}
|
||||
};
|
||||
|
||||
static const imuse_music_table _digSeqMusicTable[] = {
|
||||
const imuse_music_table _digSeqMusicTable[] = {
|
||||
{0, 2000, 0, 0, 0, 0, "SEQ_NULL", "", "" },
|
||||
{0, 2005, 0, 0, 0, 0, "seqLogo", "", "" },
|
||||
{0, 2010, 0, 0, 0, 0, "seqIntro", "", "" },
|
||||
@ -319,7 +280,7 @@ static const imuse_music_table _digSeqMusicTable[] = {
|
||||
{-1, -1, 0, 0, 0, 0, "", "", "" }
|
||||
};
|
||||
|
||||
static const imuse_music_table _comiStateMusicTable[] = {
|
||||
const imuse_music_table _comiStateMusicTable[] = {
|
||||
{0, 1000, 0, 0, 0, 0, "STATE_NULL", "", ""},
|
||||
{0, 1001, 0, 0, 0, 0, "stateNoChange", "", ""},
|
||||
{0, 1098, 0, 3, 0, 0, "stateCredits1", "1098-Credits1", "1098-C~1.IMX"},
|
||||
@ -416,7 +377,7 @@ static const imuse_music_table _comiStateMusicTable[] = {
|
||||
{-1, -1, 0, 0, 0, 0, "", "", ""}
|
||||
};
|
||||
|
||||
static const imuse_music_table _comiSeqMusicTable[] = {
|
||||
const imuse_music_table _comiSeqMusicTable[] = {
|
||||
{0, 2000, 0, 0, 0, 0, "SEQ_NULL", "", ""},
|
||||
{0, 2100, 0, 0, 0, 0, "seqINTRO", "", ""},
|
||||
{0, 2105, 0, 3, 0, 0, "seqInterlude1", "2105-Interlude1", "2105-I~1.IMX"},
|
||||
@ -509,23 +470,7 @@ static const imuse_music_table _comiSeqMusicTable[] = {
|
||||
{-1, -1, 0, 0, 0, 0, "", "", ""}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct imuse_ft_music_table {
|
||||
int index;
|
||||
char audioname[15];
|
||||
int unk1;
|
||||
int volume;
|
||||
char name[30];
|
||||
};
|
||||
|
||||
#ifdef __PALM_OS__
|
||||
// these games are currently not supported under PalmOS so we can save this space
|
||||
// to prevent full data segement
|
||||
static const imuse_ft_music_table *_ftStateMusicTable;
|
||||
static const imuse_ft_music_table *_ftSeqMusicTable;
|
||||
#else
|
||||
static const imuse_ft_music_table _ftStateMusicTable[] = {
|
||||
const imuse_ft_music_table _ftStateMusicTable[] = {
|
||||
{0, "", 0, 0, "STATE_NULL" },
|
||||
{1, "", 4, 127, "stateKstandOutside" },
|
||||
{2, "kinside", 2, 127, "stateKstandInside" },
|
||||
@ -578,7 +523,7 @@ static const imuse_ft_music_table _ftStateMusicTable[] = {
|
||||
{-1, "", 0, 0, "" }
|
||||
};
|
||||
|
||||
static const imuse_ft_music_table _ftSeqMusicTable[] = {
|
||||
const imuse_ft_music_table _ftSeqMusicTable[] = {
|
||||
{0, "", 2, 127, "SEQ_NULL" },
|
||||
{1, "opening", 2, 127, "seqLogo" },
|
||||
{2, "barbeat", 2, 127, "seqOpenFlick" },
|
||||
@ -634,817 +579,5 @@ static const imuse_ft_music_table _ftSeqMusicTable[] = {
|
||||
{52, "bornbad", 2, 127, "seqCredits" },
|
||||
{-1, "", 0, 0, "" }
|
||||
};
|
||||
#endif
|
||||
|
||||
static uint32 decode12BitsSample(byte *src, byte **dst, uint32 size) {
|
||||
uint32 loop_size = size / 3;
|
||||
uint32 s_size = loop_size * 4;
|
||||
byte *ptr = *dst = (byte *)malloc(s_size);
|
||||
|
||||
uint32 tmp;
|
||||
while (loop_size--) {
|
||||
byte v1 = *src++;
|
||||
byte v2 = *src++;
|
||||
byte v3 = *src++;
|
||||
tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000;
|
||||
WRITE_BE_UINT16(ptr, tmp); ptr += 2;
|
||||
tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000;
|
||||
WRITE_BE_UINT16(ptr, tmp); ptr += 2;
|
||||
}
|
||||
return s_size;
|
||||
}
|
||||
|
||||
IMuseDigital::Channel::Channel()
|
||||
: idSound(-1), used(false), stream(0) {
|
||||
}
|
||||
|
||||
void IMuseDigital::timer_handler(void *refCon) {
|
||||
IMuseDigital *imuseDigital = (IMuseDigital *)refCon;
|
||||
imuseDigital->callback();
|
||||
}
|
||||
|
||||
IMuseDigital::IMuseDigital(ScummEngine *scumm)
|
||||
: _scumm(scumm) {
|
||||
_pause = false;
|
||||
|
||||
_nameBundleMusic = "";
|
||||
_musicBundleBufFinal = NULL;
|
||||
_musicBundleBufOutput = NULL;
|
||||
_musicDisk = 0;
|
||||
|
||||
_bundle = new Bundle();
|
||||
|
||||
_scumm->_timer->installTimerProc(timer_handler, 1000000 / 25, this);
|
||||
}
|
||||
|
||||
IMuseDigital::~IMuseDigital() {
|
||||
_scumm->_timer->removeTimerProc(timer_handler);
|
||||
stopBundleMusic();
|
||||
|
||||
for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
_scumm->_mixer->stopHandle(_channel[l].handle);
|
||||
delete _channel[l].stream;
|
||||
_channel[l].stream = 0;
|
||||
}
|
||||
|
||||
delete _bundle;
|
||||
}
|
||||
|
||||
void IMuseDigital::callback() {
|
||||
int l = 0;
|
||||
|
||||
if (_pause || !_scumm)
|
||||
return;
|
||||
|
||||
for (l = 0; l < MAX_DIGITAL_CHANNELS;l ++) {
|
||||
if (_channel[l].used) {
|
||||
assert(_channel[l].stream);
|
||||
|
||||
if (!_channel[l].handle.isActive() && _channel[l].started) {
|
||||
debug(5, "IMuseDigital::callback(): stopped sound: %d", _channel[l].idSound);
|
||||
delete _channel[l].stream;
|
||||
_channel[l].stream = 0;
|
||||
_channel[l].used = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_channel[l].volFadeUsed) {
|
||||
if (_channel[l].volFadeStep < 0) {
|
||||
if (_channel[l].vol > _channel[l].volFadeDest) {
|
||||
_channel[l].vol += _channel[l].volFadeStep;
|
||||
if (_channel[l].vol < _channel[l].volFadeDest) {
|
||||
_channel[l].vol = _channel[l].volFadeDest;
|
||||
_channel[l].volFadeUsed = false;
|
||||
}
|
||||
if (_channel[l].vol == 0) {
|
||||
_scumm->_mixer->stopHandle(_channel[l].handle);
|
||||
}
|
||||
}
|
||||
} else if (_channel[l].volFadeStep > 0) {
|
||||
if (_channel[l].vol < _channel[l].volFadeDest) {
|
||||
_channel[l].vol += _channel[l].volFadeStep;
|
||||
if (_channel[l].vol > _channel[l].volFadeDest) {
|
||||
_channel[l].vol = _channel[l].volFadeDest;
|
||||
_channel[l].volFadeUsed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug(5, "Fade: sound(%d), Vol(%d)", _channel[l].idSound, _channel[l].vol / 1000);
|
||||
}
|
||||
|
||||
if (_scumm->_mixer->isReady()) {
|
||||
int pan = (_channel[l].pan != 64) ? 2 * _channel[l].pan - 127 : 0;
|
||||
if (!_channel[l].started) {
|
||||
_channel[l].started = true;
|
||||
_scumm->_mixer->playInputStream(&_channel[l].handle, _channel[l].stream, true, _channel[l].vol / 1000, _channel[l].pan, -1, false);
|
||||
} else {
|
||||
_scumm->_mixer->setChannelVolume(_channel[l].handle, _channel[l].vol / 1000);
|
||||
_scumm->_mixer->setChannelPan(_channel[l].handle, pan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::startSound(int sound, byte *voiceBundleData, AudioStream *input) {
|
||||
debug(5, "IMuseDigital::startSound(%d)", sound);
|
||||
int l, r;
|
||||
|
||||
for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if (!_channel[l].used && !_channel[l].handle.isActive()) {
|
||||
byte *ptr, *s_ptr;
|
||||
if (sound != kTalkSoundID) {
|
||||
s_ptr = ptr = _scumm->getResourceAddress(rtSound, sound);
|
||||
if (ptr == NULL) {
|
||||
warning("IMuseDigital::startSound(%d) NULL resource pointer", sound);
|
||||
return;
|
||||
}
|
||||
} else if (voiceBundleData) {
|
||||
s_ptr = ptr = voiceBundleData;
|
||||
} else if (input) {
|
||||
s_ptr = ptr = 0;
|
||||
} else {
|
||||
error("IMuseDigital::startSound() unknown condition");
|
||||
}
|
||||
_channel[l].pan = 64;
|
||||
_channel[l].vol = 127 * 1000;
|
||||
_channel[l].volFadeDest = 0;
|
||||
_channel[l].volFadeStep = 0;
|
||||
_channel[l].volFadeDelay = 0;
|
||||
_channel[l].volFadeUsed = false;
|
||||
|
||||
_channel[l].numJumps = 0;
|
||||
_channel[l].numRegions = 0;
|
||||
_channel[l].numMarkers = 0;
|
||||
|
||||
_channel[l].idSound = sound;
|
||||
|
||||
if (input) {
|
||||
// Do nothing here, we already have an audio stream
|
||||
} else if (READ_UINT32(ptr) == MKID('Crea')) {
|
||||
// Create an AudioStream
|
||||
input = makeVOCStream(ptr);
|
||||
} else if (READ_UINT32(ptr) == MKID('iMUS')) {
|
||||
uint32 tag;
|
||||
int32 size = 0;
|
||||
|
||||
int freq, channels, bits;
|
||||
int mixerFlags;
|
||||
byte *data;
|
||||
|
||||
ptr += 16;
|
||||
freq = channels = bits = 0;
|
||||
do {
|
||||
tag = READ_BE_UINT32(ptr); ptr += 4;
|
||||
switch(tag) {
|
||||
case MKID_BE('FRMT'):
|
||||
ptr += 12;
|
||||
bits = READ_BE_UINT32(ptr); ptr += 4;
|
||||
freq = READ_BE_UINT32(ptr); ptr += 4;
|
||||
channels = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
case MKID_BE('TEXT'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
if (_channel[l].numMarkers >= MAX_IMUSE_MARKERS) {
|
||||
warning("IMuseDigital::startSound() Not enough space for Marker");
|
||||
ptr += size;
|
||||
break;
|
||||
}
|
||||
strcpy(_channel[l].marker[_channel[l].numMarkers].name, (char *)ptr + 4);
|
||||
_channel[l].numMarkers++;
|
||||
ptr += size;
|
||||
break;
|
||||
case MKID_BE('REGN'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
if (_channel[l].numRegions >= MAX_IMUSE_REGIONS) {
|
||||
warning("IMuseDigital::startSound() Not enough space for Region");
|
||||
ptr += 8;
|
||||
break;
|
||||
}
|
||||
_channel[l].region[_channel[l].numRegions].start = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_channel[l].region[_channel[l].numRegions].length = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_channel[l].numRegions++;
|
||||
break;
|
||||
case MKID_BE('STOP'):
|
||||
ptr += 4;
|
||||
_channel[l].offsetStop = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
case MKID_BE('JUMP'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
if (_channel[l].numJumps >= MAX_IMUSE_JUMPS) {
|
||||
warning("IMuseDigital::startSound() Not enough space for Jump");
|
||||
ptr += size;
|
||||
break;
|
||||
}
|
||||
_channel[l].jump[_channel[l].numJumps].start = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_channel[l].jump[_channel[l].numJumps].dest = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_channel[l].jump[_channel[l].numJumps].hookId = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_channel[l].jump[_channel[l].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_channel[l].numJumps++;
|
||||
break;
|
||||
case MKID_BE('SYNC'):
|
||||
size = READ_BE_UINT32(ptr); ptr += size + 4;
|
||||
break;
|
||||
case MKID_BE('DATA'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
default:
|
||||
error("IMuseDigital::startSound(%d) Unknown sfx header '%s'", sound, tag2str(tag));
|
||||
}
|
||||
} while (tag != MKID_BE('DATA'));
|
||||
|
||||
if ((sound == kTalkSoundID) && voiceBundleData) {
|
||||
if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) {
|
||||
Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound");
|
||||
freq = (freq * a->talkFrequency) / 256;
|
||||
_channel[l].pan = a->talkPan;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 header_size = ptr - s_ptr;
|
||||
|
||||
_channel[l].offsetStop -= header_size;
|
||||
if (bits == 12) {
|
||||
_channel[l].offsetStop = (_channel[l].offsetStop / 3) * 4;
|
||||
}
|
||||
for (r = 0; r < _channel[l].numRegions; r++) {
|
||||
_channel[l].region[r].start -= header_size;
|
||||
if (bits == 12) {
|
||||
_channel[l].region[r].start = (_channel[l].region[r].start / 3) * 4;
|
||||
_channel[l].region[r].length = (_channel[l].region[r].length / 3) * 4;
|
||||
}
|
||||
}
|
||||
if (_channel[l].numJumps > 0) {
|
||||
for (r = 0; r < _channel[l].numJumps; r++) {
|
||||
_channel[l].jump[r].start -= header_size;
|
||||
_channel[l].jump[r].dest -= header_size;
|
||||
if (bits == 12) {
|
||||
_channel[l].jump[r].start = (_channel[l].jump[r].start / 3) * 4;
|
||||
_channel[l].jump[r].dest = (_channel[l].jump[r].dest / 3) * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(channels == 1 || channels == 2);
|
||||
|
||||
if (channels == 2) {
|
||||
// FIXME / TODO: Is FLAG_REVERSE_STEREO really needed here?
|
||||
// How do we know that it is needed? If we indeed have reasons
|
||||
// to believe that it is needed, those should be documented in
|
||||
// a comment here. And if the channels are reversed, then we
|
||||
// might just swap them right here, instead of using the mixer
|
||||
// flag - since we copy the data around anyway, swapping the
|
||||
// channels should be little extra work (in fact, none for
|
||||
// mono data, which includes the 12 bit compressed format).
|
||||
|
||||
mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
|
||||
} else {
|
||||
mixerFlags = 0;
|
||||
}
|
||||
|
||||
if (bits == 12) {
|
||||
mixerFlags |= SoundMixer::FLAG_16BITS;
|
||||
size = decode12BitsSample(ptr, &data, size);
|
||||
} else if (bits == 16) {
|
||||
mixerFlags |= SoundMixer::FLAG_16BITS;
|
||||
|
||||
// FIXME: For some weird reasons, sometimes we get an odd size, even though
|
||||
// the data is supposed to be in 16 bit format... that makes no sense...
|
||||
size &= ~1;
|
||||
|
||||
data = (byte *)malloc(size);
|
||||
memcpy(data, ptr, size);
|
||||
} else if (bits == 8) {
|
||||
mixerFlags |= SoundMixer::FLAG_UNSIGNED;
|
||||
|
||||
data = (byte *)malloc(size);
|
||||
memcpy(data, ptr, size);
|
||||
} else
|
||||
error("IMuseDigital::startSound(): Can't handle %d bit samples", bits);
|
||||
|
||||
// Create an AudioStream
|
||||
input = makeLinearInputStream(freq, mixerFlags | SoundMixer::FLAG_AUTOFREE, data, size, 0, 0);
|
||||
} else {
|
||||
error("IMuseDigital::startSound(): Unknown sound format");
|
||||
}
|
||||
|
||||
// Set the audio stream for this new channel
|
||||
_channel[l].stream = input;
|
||||
|
||||
_channel[l].started = false;
|
||||
_channel[l].used = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
warning("IMuseDigital::startSound(): All slots are full");
|
||||
}
|
||||
|
||||
void IMuseDigital::stopSound(int sound) {
|
||||
debug(5, "IMuseDigital::stopSound(%d)", sound);
|
||||
for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if ((_channel[l].idSound == sound) && _channel[l].used) {
|
||||
_scumm->_mixer->stopHandle(_channel[l].handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::stopAllSounds() {
|
||||
debug(5, "IMuseDigital::stopAllSounds");
|
||||
for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if (_channel[l].used) {
|
||||
_scumm->_mixer->stopHandle(_channel[l].handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::pause(bool p) {
|
||||
for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if (_channel[l].used) {
|
||||
_scumm->_mixer->pauseHandle(_channel[l].handle, p);
|
||||
}
|
||||
}
|
||||
_pause = p;
|
||||
pauseBundleMusic(p);
|
||||
}
|
||||
|
||||
void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) {
|
||||
int cmd = a;
|
||||
int sample = b;
|
||||
int sub_cmd = c;
|
||||
int chan = -1;
|
||||
int l, r;
|
||||
|
||||
if (!cmd)
|
||||
return;
|
||||
|
||||
switch (cmd) {
|
||||
case 10: // ImuseStopAllSounds
|
||||
debug(5, "ImuseStopAllSounds()");
|
||||
stopAllSounds();
|
||||
break;
|
||||
case 12: // ImuseSetParam
|
||||
switch (sub_cmd) {
|
||||
case 0x500: // set priority - could be ignored
|
||||
break;
|
||||
case 0x600: // set volume
|
||||
debug(5, "ImuseSetParam (0x600), sample(%d), volume(%d)", sample, d);
|
||||
for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if ((_channel[l].idSound == sample) && _channel[l].used) {
|
||||
_channel[l].vol = d * 1000;
|
||||
// if (_channel[l].volFadeUsed)
|
||||
// _channel[l].volFadeStep = (_channel[l].volFadeDest - _channel[l].vol) * 60 * 40 / (1000 * _channel[chan].volFadeDelay);
|
||||
}
|
||||
}
|
||||
if (l == -1) {
|
||||
debug(5, "ImuseSetParam (0x600), sample(%d) not exist in channels", sample);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x700: // set pan
|
||||
debug(5, "ImuseSetParam (0x700), sample(%d), pan(%d)", sample, d);
|
||||
for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if ((_channel[l].idSound == sample) && _channel[l].used) {
|
||||
_channel[l].pan = d;
|
||||
}
|
||||
}
|
||||
if (l == -1) {
|
||||
debug(5, "ImuseSetParam (0x700), sample(%d) not exist in channels", sample);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 14: // ImuseFadeParam
|
||||
switch (sub_cmd) {
|
||||
case 0x600: // set new volume with fading
|
||||
debug(5, "ImuseFadeParam - fade sample(%d), to volume(%d) with 60hz ticks(%d)", sample, d, e);
|
||||
if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
|
||||
stopSound(sample);
|
||||
return;
|
||||
}
|
||||
for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if ((_channel[l].idSound == sample) && _channel[l].used) {
|
||||
_channel[l].volFadeDelay = e;
|
||||
_channel[l].volFadeDest = d * 1000;
|
||||
_channel[l].volFadeStep = (_channel[l].volFadeDest - _channel[l].vol) * 60 * 40 / (1000 * e);
|
||||
_channel[l].volFadeUsed = true;
|
||||
debug(5, "ImuseFadeParam: vol %d, volDest %d, step %d", _channel[l].vol, d * 1000, _channel[l].volFadeStep);
|
||||
}
|
||||
}
|
||||
if (chan == -1) {
|
||||
debug(5, "ImuseFadeParam (0x600), sample %d not exist in channels", sample);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x1000: // ImuseSetState
|
||||
debug(5, "ImuseSetState (%d)", b);
|
||||
if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
|
||||
if (b == 1)
|
||||
startSound(1);
|
||||
else {
|
||||
if (getSoundStatus(2) == 0)
|
||||
startSound(2);
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_DIG) {
|
||||
if (b == 1000) { // STATE_NULL
|
||||
stopBundleMusic();
|
||||
return;
|
||||
}
|
||||
for (l = 0; _digStateMusicMap[l].room != -1; l++) {
|
||||
if (_digStateMusicMap[l].room == b) {
|
||||
int music = _digStateMusicMap[l].table_index;
|
||||
debug(5, "Play imuse music: %s, %s, %s", _digStateMusicTable[music].name, _digStateMusicTable[music].title, _digStateMusicTable[music].filename);
|
||||
if ((_digStateMusicTable[music].filename[0] != 0) &&
|
||||
(strcmp(_digStateMusicTable[_digStateMusicTable[music].unk3].filename, _nameBundleMusic) != 0) ) {
|
||||
playBundleMusic(_digStateMusicTable[music].filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((_scumm->_gameId == GID_CMI) && (_scumm->_features & GF_DEMO)) {
|
||||
if (b == 2) {
|
||||
playBundleMusic("in1.imx");
|
||||
} else if (b == 4) {
|
||||
playBundleMusic("in2.imx");
|
||||
} else if (b == 8) {
|
||||
playBundleMusic("out1.imx");
|
||||
} else if (b == 9) {
|
||||
playBundleMusic("out2.imx");
|
||||
} else if (b == 16) {
|
||||
playBundleMusic("gun.imx");
|
||||
} else {
|
||||
warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, this->_scumm->_currentRoom);
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_CMI) {
|
||||
if (b == 1000) { // STATE_NULL
|
||||
stopBundleMusic();
|
||||
return;
|
||||
}
|
||||
for (l = 0; _comiStateMusicTable[l].id != -1; l++) {
|
||||
if ((_comiStateMusicTable[l].id == b)) {
|
||||
debug(5, "Play imuse music: %s, %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].title, _comiStateMusicTable[l].filename);
|
||||
if (_comiStateMusicTable[l].filename[0] != 0) {
|
||||
playBundleMusic(_comiStateMusicTable[l].filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_FT) {
|
||||
for (l = 0;; l++) {
|
||||
if (_ftStateMusicTable[l].index == -1) {
|
||||
return;
|
||||
}
|
||||
if (_ftStateMusicTable[l].index == b) {
|
||||
debug(5, "Play imuse music: %s, %s", _ftStateMusicTable[l].name, _ftStateMusicTable[l].audioname);
|
||||
if (_ftStateMusicTable[l].audioname[0] != 0) {
|
||||
for (r = 0; r < _scumm->_numAudioNames; r++) {
|
||||
if (strcmp(_ftStateMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
|
||||
startSound(r);
|
||||
parseScriptCmds(12, r, 1536, _ftStateMusicTable[l].volume, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x1001: // ImuseSetSequence
|
||||
debug(5, "ImuseSetSequence (%d)", b);
|
||||
if (_scumm->_gameId == GID_DIG) {
|
||||
for (l = 0; _digSeqMusicTable[l].room != -1; l++) {
|
||||
if (_digSeqMusicTable[l].room == b) {
|
||||
debug(5, "Play imuse music: %s, %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].title, _digSeqMusicTable[l].filename);
|
||||
if (_digSeqMusicTable[l].filename[0] != 0) {
|
||||
playBundleMusic(_digSeqMusicTable[l].filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_CMI) {
|
||||
for (l = 0; _comiSeqMusicTable[l].id != -1; l++) {
|
||||
if (_comiSeqMusicTable[l].id == b) {
|
||||
debug(5, "Play imuse music: %s, %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].title, _comiSeqMusicTable[l].filename);
|
||||
if (_comiSeqMusicTable[l].filename[0] != 0) {
|
||||
playBundleMusic(_comiSeqMusicTable[l].filename);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_FT) {
|
||||
for (l = 0; _ftSeqMusicTable[l].index != -1; l++) {
|
||||
if (_ftSeqMusicTable[l].index == b) {
|
||||
debug(5, "Play imuse music: %s, %s", _ftSeqMusicTable[l].name, _ftSeqMusicTable[l].audioname);
|
||||
if (_ftSeqMusicTable[l].audioname[0] != 0) {
|
||||
for (r = 0; r < _scumm->_numAudioNames; r++) {
|
||||
if (strcmp(_ftSeqMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
|
||||
// startSound(r);
|
||||
// parseScriptCmds(12, r, 1536, _ftSeqMusicTable[l].volume, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x1002: // ImuseSetCuePoint
|
||||
debug(5, "ImuseSetCuePoint (%d)", b);
|
||||
break;
|
||||
case 0x1003: // ImuseSetAttribute
|
||||
debug(5, "ImuseSetAttribute (%d, %d)", b, c);
|
||||
break;
|
||||
case 0x2000: // ImuseSetMasterSFXVolume
|
||||
debug(5, "ImuseSetMasterSFXVolume (%d)", b);
|
||||
break;
|
||||
case 0x2001: // ImuseSetMasterVoiceVolume
|
||||
debug(5, "ImuseSetMasterVoiceVolume (%d)", b);
|
||||
break;
|
||||
case 0x2002: // ImuseSetMasterMusicVolume
|
||||
debug(5, "ImuseSetMasterMusicVolume (%d)", b);
|
||||
break;
|
||||
default:
|
||||
warning("IMuseDigital::doCommand DEFAULT command %d", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
int IMuseDigital::getSoundStatus(int sound) const {
|
||||
debug(5, "IMuseDigital::getSoundStatus(%d)", sound);
|
||||
for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
|
||||
if ((_channel[l].idSound == sound) && _channel[l].used) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IMuseDigital::music_handler(void *refCon) {
|
||||
((IMuseDigital *)refCon)->bundleMusicHandler();
|
||||
}
|
||||
|
||||
#define BUNDLE_MUSIC_ITER_PER_SEC 10
|
||||
|
||||
void IMuseDigital::playBundleMusic(const char *song) {
|
||||
if (!_scumm->_mixer->isReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_nameBundleMusic[0] == 0) {
|
||||
if (_scumm->_gameId == GID_CMI) {
|
||||
_outputMixerSize = (22050 * 2 * 2);
|
||||
|
||||
char bunfile[20];
|
||||
if (_scumm->_features & GF_DEMO) {
|
||||
if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) {
|
||||
_outputMixerSize = 0;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
sprintf(bunfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
|
||||
if (_musicDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
|
||||
_bundle->closeMusicFile();
|
||||
|
||||
if (_bundle->openMusicFile(bunfile, _scumm->getGameDataPath()) == false) {
|
||||
if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) {
|
||||
_outputMixerSize = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_musicDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
|
||||
}
|
||||
} else {
|
||||
_outputMixerSize = ((22050 * 2 * 2) / 4) * 3;
|
||||
|
||||
if (_bundle->openMusicFile("digmusic.bun", _scumm->getGameDataPath()) == false)
|
||||
return;
|
||||
}
|
||||
_musicBundleBufFinal = (byte *)malloc(_outputMixerSize);
|
||||
_musicBundleBufOutput = (byte *)malloc(((_outputMixerSize / 0x2000) + 1) * _outputMixerSize);
|
||||
_currentSampleBundleMusic = 0;
|
||||
_offsetSampleBundleMusic = 0;
|
||||
_offsetBufBundleMusic = 0;
|
||||
_bundleMusicPosition = 0;
|
||||
_bundleSongPosInMs = 0;
|
||||
_pauseBundleMusic = false;
|
||||
_musicBundleToBeChanged = false;
|
||||
_numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(song);
|
||||
_nameBundleMusic = song;
|
||||
_outputMixerSize /= BUNDLE_MUSIC_ITER_PER_SEC;
|
||||
_scumm->_timer->installTimerProc(&music_handler, 1000000 / BUNDLE_MUSIC_ITER_PER_SEC, this);
|
||||
} else if (strcmp(_nameBundleMusic, song) != 0) {
|
||||
_newNameBundleMusic = song;
|
||||
_musicBundleToBeChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::pauseBundleMusic(bool state) {
|
||||
_pauseBundleMusic = state;
|
||||
}
|
||||
|
||||
void IMuseDigital::stopBundleMusic() {
|
||||
// First stop the music timer
|
||||
_scumm->_timer->removeTimerProc(&music_handler);
|
||||
_nameBundleMusic = "";
|
||||
_scumm->_mixer->stopHandle(_bundleMusicTrack);
|
||||
if (_musicBundleBufFinal) {
|
||||
free(_musicBundleBufFinal);
|
||||
_musicBundleBufFinal = NULL;
|
||||
}
|
||||
if (_musicBundleBufOutput) {
|
||||
free(_musicBundleBufOutput);
|
||||
_musicBundleBufOutput = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void IMuseDigital::bundleMusicHandler() {
|
||||
byte *ptr;
|
||||
int32 l, num = _numberSamplesBundleMusic, length, k;
|
||||
int32 rate = 22050;
|
||||
int32 tag, size = -1, header_size = 0;
|
||||
|
||||
if (_pauseBundleMusic)
|
||||
return;
|
||||
|
||||
if (_musicBundleToBeChanged) {
|
||||
_nameBundleMusic = _newNameBundleMusic;
|
||||
_numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(_nameBundleMusic);
|
||||
_currentSampleBundleMusic = 0;
|
||||
_offsetSampleBundleMusic = 0;
|
||||
_offsetBufBundleMusic = 0;
|
||||
_musicBundleToBeChanged = false;
|
||||
_bundleMusicPosition = 0;
|
||||
_bundleSongPosInMs = 0;
|
||||
}
|
||||
|
||||
ptr = _musicBundleBufOutput;
|
||||
|
||||
for (k = 0, l = _currentSampleBundleMusic; l < num && (_offsetSampleBundleMusic < _outputMixerSize + header_size); k++) {
|
||||
length = _bundle->decompressMusicSampleByName(_nameBundleMusic, l, (_musicBundleBufOutput + ((k * 0x2000) + _offsetBufBundleMusic)));
|
||||
_offsetSampleBundleMusic += length;
|
||||
|
||||
if (l == 0) {
|
||||
tag = READ_BE_UINT32(ptr); ptr += 4;
|
||||
if (tag != MKID_BE('iMUS')) {
|
||||
error("Decompressing bundle song failed (unknown tag '%s')", tag2str(tag));
|
||||
}
|
||||
|
||||
ptr += 12;
|
||||
while (tag != MKID_BE('DATA')) {
|
||||
tag = READ_BE_UINT32(ptr); ptr += 4;
|
||||
switch(tag) {
|
||||
case MKID_BE('FRMT'):
|
||||
ptr += 12;
|
||||
_bundleMusicSampleBits = READ_BE_UINT32(ptr); ptr += 4;
|
||||
rate = READ_BE_UINT32(ptr); ptr += 4;
|
||||
_bundleSampleChannels = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
case MKID_BE('TEXT'):
|
||||
case MKID_BE('REGN'):
|
||||
case MKID_BE('STOP'):
|
||||
case MKID_BE('JUMP'):
|
||||
case MKID_BE('SYNC'):
|
||||
size = READ_BE_UINT32(ptr); ptr += size + 4;
|
||||
break;
|
||||
case MKID_BE('DATA'):
|
||||
size = READ_BE_UINT32(ptr); ptr += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Unknown sound header '%s'", tag2str(tag));
|
||||
}
|
||||
}
|
||||
if (size < 0) {
|
||||
error("Decompressing sound failed (missing size field)");
|
||||
}
|
||||
header_size = (ptr - _musicBundleBufOutput);
|
||||
}
|
||||
|
||||
l++;
|
||||
_currentSampleBundleMusic = l;
|
||||
|
||||
}
|
||||
|
||||
if (_offsetSampleBundleMusic >= _outputMixerSize + header_size) {
|
||||
memcpy(_musicBundleBufFinal, (_musicBundleBufOutput + header_size), _outputMixerSize);
|
||||
_offsetBufBundleMusic = _offsetSampleBundleMusic - _outputMixerSize - header_size;
|
||||
memcpy(_musicBundleBufOutput, (_musicBundleBufOutput + (_outputMixerSize + header_size)), _offsetBufBundleMusic);
|
||||
_offsetSampleBundleMusic = _offsetBufBundleMusic;
|
||||
}
|
||||
|
||||
if (_currentSampleBundleMusic == num) {
|
||||
_currentSampleBundleMusic = 0;
|
||||
_offsetSampleBundleMusic = 0;
|
||||
_offsetBufBundleMusic = 0;
|
||||
_bundleMusicPosition = 0;
|
||||
_bundleSongPosInMs = 0;
|
||||
}
|
||||
|
||||
ptr = _musicBundleBufFinal;
|
||||
|
||||
byte *buffer = NULL;
|
||||
uint32 final_size;
|
||||
if (_bundleMusicSampleBits == 12) {
|
||||
final_size = decode12BitsSample(ptr, &buffer, _outputMixerSize);
|
||||
} else if (_bundleMusicSampleBits == 16) {
|
||||
buffer = (byte *)malloc(_outputMixerSize);
|
||||
final_size = _outputMixerSize;
|
||||
memcpy(buffer, ptr, _outputMixerSize);
|
||||
} else {
|
||||
warning("IMuseDigital::bundleMusicHandler TODO: more newStream options...");
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute the position in the song in milliseconds (in brief: _outputMixerSize
|
||||
// gives the number of bytes used for one second, so if we compute the value of
|
||||
// (_bundleMusicPosition / _outputMixerSize), that is an offset in seconds;
|
||||
// multiplying that by 1000 gives milliseconds).
|
||||
_bundleSongPosInMs = 1000 * _bundleMusicPosition / (_outputMixerSize * BUNDLE_MUSIC_ITER_PER_SEC);
|
||||
_bundleMusicPosition += final_size;
|
||||
if (!_bundleMusicTrack.isActive())
|
||||
_scumm->_mixer->newStream(&_bundleMusicTrack, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO, 300000);
|
||||
_scumm->_mixer->appendStream(_bundleMusicTrack, buffer, final_size);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
void IMuseDigital::playBundleSound(const char *sound) {
|
||||
byte *ptr = 0;
|
||||
bool result;
|
||||
|
||||
if (!_scumm->_mixer->isReady())
|
||||
return;
|
||||
|
||||
if (_scumm->_gameId == GID_CMI) {
|
||||
if (_scumm->_features & GF_DEMO) {
|
||||
result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath());
|
||||
} else {
|
||||
char voxfile[20];
|
||||
sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
|
||||
if (_voiceDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
|
||||
_bundle->closeVoiceFile();
|
||||
|
||||
result = _bundle->openVoiceFile(voxfile, _scumm->getGameDataPath());
|
||||
|
||||
if (result == false)
|
||||
result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath());
|
||||
_voiceDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
|
||||
}
|
||||
} else if (_scumm->_gameId == GID_DIG)
|
||||
result = _bundle->openVoiceFile("digvoice.bun", _scumm->getGameDataPath());
|
||||
else
|
||||
error("Don't know which bundle file to load");
|
||||
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
if (_scumm->_gameId == GID_CMI) {
|
||||
char name[20];
|
||||
strcpy(name, sound);
|
||||
if (!(_scumm->_features & GF_DEMO)) // CMI demo does not have .IMX for voice but does for music...
|
||||
strcat(name, ".IMX");
|
||||
_bundle->decompressVoiceSampleByName(name, &ptr);
|
||||
} else {
|
||||
_bundle->decompressVoiceSampleByName(sound, &ptr);
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
stopSound(kTalkSoundID);
|
||||
startSound(kTalkSoundID, ptr, 0);
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Scumm
|
||||
|
||||
#ifdef __PALM_OS__
|
||||
#include "scumm_globals.h"
|
||||
|
||||
_GINIT(IMuseDigital)
|
||||
_GSETPTR(Scumm::_digStateMusicMap, GBVARS_DIGSTATEMUSICMAP_INDEX, Scumm::imuse_music_map , GBVARS_SCUMM)
|
||||
_GSETPTR(Scumm::_digStateMusicTable, GBVARS_DIGSTATEMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
|
||||
_GSETPTR(Scumm::_comiStateMusicTable, GBVARS_COMISTATEMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
|
||||
_GSETPTR(Scumm::_comiSeqMusicTable, GBVARS_COMISEQMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
|
||||
_GSETPTR(Scumm::_digSeqMusicTable, GBVARS_DIGSEQMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
|
||||
_GSETPTR(Scumm::_ftStateMusicTable, GBVARS_FTSTATEMUSICTABLE_INDEX, Scumm::imuse_ft_music_table , GBVARS_SCUMM)
|
||||
_GSETPTR(Scumm::_ftSeqMusicTable, GBVARS_FTSEQMUSICTABLE_INDEX, Scumm::imuse_ft_music_table , GBVARS_SCUMM)
|
||||
_GEND
|
||||
|
||||
_GRELEASE(IMuseDigital)
|
||||
_GRELEASEPTR(GBVARS_DIGSTATEMUSICMAP_INDEX , GBVARS_SCUMM)
|
||||
_GRELEASEPTR(GBVARS_DIGSTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
|
||||
_GRELEASEPTR(GBVARS_COMISTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
|
||||
_GRELEASEPTR(GBVARS_COMISEQMUSICTABLE_INDEX , GBVARS_SCUMM)
|
||||
_GRELEASEPTR(GBVARS_DIGSEQMUSICTABLE_INDEX , GBVARS_SCUMM)
|
||||
_GRELEASEPTR(GBVARS_FTSTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
|
||||
_GRELEASEPTR(GBVARS_FTSEQMUSICTABLE_INDEX , GBVARS_SCUMM)
|
||||
_GEND
|
||||
|
||||
#endif
|
@ -23,10 +23,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "common/map.h"
|
||||
#include "common/str.h"
|
||||
#include "scumm/bundle.h"
|
||||
#include "scumm/dialogs.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/object.h"
|
||||
#include "scumm/resource.h"
|
||||
#include "scumm/scumm.h"
|
||||
@ -228,8 +227,7 @@ void ScummEngine::askForDisk(const char *filename, int disknum) {
|
||||
if (_version == 8) {
|
||||
char result;
|
||||
|
||||
_imuseDigital->_bundle->closeVoiceFile();
|
||||
_imuseDigital->_bundle->closeMusicFile();
|
||||
_imuseDigital->closeBundleFiles();
|
||||
|
||||
#ifdef MACOSX
|
||||
sprintf(buf, "Cannot find file: '%s'\nPlease insert disc %d.\nHit OK to retry, Cancel to exit", filename, disknum);
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/charset.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/object.h"
|
||||
#include "scumm/resource.h"
|
||||
@ -125,8 +125,6 @@ bool ScummEngine::loadState(int slot, bool compat, SaveFileManager *mgr) {
|
||||
memcpy(_saveLoadName, hdr.name, sizeof(hdr.name));
|
||||
|
||||
_sound->stopAllSounds();
|
||||
if (_imuseDigital)
|
||||
_imuseDigital->stopBundleMusic();
|
||||
_sound->stopCD();
|
||||
|
||||
_sound->pauseSounds(true);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/charset.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/intern.h"
|
||||
#include "scumm/object.h"
|
||||
#include "scumm/resource.h"
|
||||
@ -936,7 +937,7 @@ void ScummEngine_v6::o6_startSound() {
|
||||
pop(); // offset which seems to always be zero
|
||||
|
||||
if (_features & GF_DIGI_IMUSE)
|
||||
_sound->playSound(pop());
|
||||
_imuseDigital->startSfx(pop());
|
||||
else
|
||||
_sound->addSoundToQueue(pop());
|
||||
}
|
||||
@ -947,7 +948,7 @@ void ScummEngine_v6::o6_stopSound() {
|
||||
|
||||
void ScummEngine_v6::o6_startMusic() {
|
||||
if (_features & GF_DIGI_IMUSE)
|
||||
_sound->playSound(pop());
|
||||
error("o6_startMusic() It shouldn't be called here for imuse digital");
|
||||
else
|
||||
_sound->addSoundToQueue(pop());
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/akos.h"
|
||||
#include "scumm/charset.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/intern.h"
|
||||
#include "scumm/object.h"
|
||||
#include "scumm/resource.h"
|
||||
@ -1444,14 +1444,9 @@ void ScummEngine_v8::o8_kernelGetFunctions() {
|
||||
break;
|
||||
}
|
||||
case 0xDA: // lipSyncWidth
|
||||
push(_imuseDigital->getCurVoiceLipSyncWidth());
|
||||
case 0xDB: // lipSyncHeight
|
||||
{
|
||||
// TODO - get lip sync data for the currently active voice
|
||||
// HACK - return random values for now, to make things look half decent
|
||||
int val = _rnd.getRandomNumber(255);
|
||||
// warning("o8_kernelGetFunctions: lipSync(case 0x%x, len %d, val %d)", args[0], len, val);
|
||||
push(val);
|
||||
}
|
||||
push(_imuseDigital->getCurVoiceLipSyncHeight());
|
||||
break;
|
||||
case 0xDC: // actorTalkAnimation
|
||||
{
|
||||
@ -1482,18 +1477,12 @@ void ScummEngine_v8::o8_kernelGetFunctions() {
|
||||
}
|
||||
break;
|
||||
case 0xE1: // imGetMusicPosition
|
||||
warning("o8_kernelGetFunctions: imGetMusicPosition(stub)");
|
||||
// FIXME - get this stuff to be properly implemented
|
||||
push(_imuseDigital->_bundleSongPosInMs);
|
||||
push(_imuseDigital->getCurMusicPosInMs());
|
||||
break;
|
||||
case 0xE2: // musicLipSyncWidth
|
||||
push(_imuseDigital->getCurMusicLipSyncWidth());
|
||||
case 0xE3: // musicLipSyncHeight
|
||||
{
|
||||
// TODO - get lip sync data for the currently active music
|
||||
int val = _rnd.getRandomNumber(255);
|
||||
// warning("o8_kernelGetFunctions: musicLipSync(case 0x%x, len %d, val %d)", args[0], len, val);
|
||||
push(val);
|
||||
}
|
||||
push(_imuseDigital->getCurMusicLipSyncHeight());
|
||||
break;
|
||||
default:
|
||||
error("o8_kernelGetFunctions: default case 0x%x (len = %d)", args[0], len);
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "scumm/costume.h"
|
||||
#include "scumm/debugger.h"
|
||||
#include "scumm/dialogs.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/intern.h"
|
||||
#include "scumm/object.h"
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "scumm/sound.h"
|
||||
#include "scumm/resource.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
|
||||
#include "scumm/smush/smush_player.h"
|
||||
#include "scumm/smush/chunk_type.h"
|
||||
@ -5914,30 +5914,16 @@ bool Insane::smlayer_isSoundRunning(int32 sound) {
|
||||
}
|
||||
|
||||
bool Insane::smlayer_startSound1(int32 sound) {
|
||||
// FIXME: original startSound parameters:
|
||||
// startSound(id, 40, 1);
|
||||
// second param is priority in imuse,
|
||||
// third param set sound to group volume in imuse
|
||||
// (0 - master, 1-sfx, 2-voice, 3 - music,
|
||||
// 4 - background music)
|
||||
// there are no equivalents in scummvm
|
||||
if (smlayer_loadSound(sound, 0, 2)) {
|
||||
_scumm->_sound->playSound(readArray(_numberArray, sound));
|
||||
_scumm->_imuseDigital->startSfx(readArray(_numberArray, sound));
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Insane::smlayer_startSound2(int32 sound) {
|
||||
// FIXME: original startSound parameters:
|
||||
// startSound(id, 126, 2);
|
||||
// second param is priority in imuse,
|
||||
// third param set sound to group volume in imuse
|
||||
// (0 - master, 1-sfx, 2-voice, 3 - music,
|
||||
// 4 - background music)
|
||||
// there are no equivalents in scummvm
|
||||
if (smlayer_loadSound(sound, 0, 2)) {
|
||||
_scumm->_sound->playSound(readArray(_numberArray, sound));
|
||||
_scumm->_imuseDigital->startSfx(readArray(_numberArray, sound));
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "common/timer.h"
|
||||
|
||||
#include "scumm/bomp.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/sound.h"
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/imuse.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/scumm.h"
|
||||
#include "scumm/sound.h"
|
||||
|
||||
@ -126,11 +126,6 @@ void Sound::playSound(int soundID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_scumm->_features & GF_DIGI_IMUSE) {
|
||||
_scumm->_musicEngine->startSound(soundID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Support for SFX in Monkey Island 1, Mac version
|
||||
// This is rather hackish right now, but works OK. SFX are not sounding
|
||||
// 100% correct, though, not sure right now what is causing this.
|
||||
@ -815,7 +810,6 @@ void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle,
|
||||
|
||||
AudioStream *input;
|
||||
|
||||
|
||||
if (file_size > 0) {
|
||||
if (_vorbis_mode) {
|
||||
#ifdef USE_VORBIS
|
||||
@ -831,7 +825,8 @@ void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle,
|
||||
}
|
||||
|
||||
if (_scumm->_imuseDigital) {
|
||||
_scumm->_imuseDigital->startSound(kTalkSoundID, 0, input);
|
||||
_scumm->_imuseDigital->stopSound(kTalkSoundID);
|
||||
_scumm->_imuseDigital->startVoice(kTalkSoundID, input);
|
||||
} else {
|
||||
_scumm->_mixer->playInputStream(handle, input, false, 255, 0, id);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/charset.h"
|
||||
#include "scumm/dialogs.h"
|
||||
#include "scumm/imuse_digi.h"
|
||||
#include "scumm/imuse_digi/dimuse.h"
|
||||
#include "scumm/verbs.h"
|
||||
#include "scumm/sound.h"
|
||||
|
||||
@ -921,7 +921,10 @@ const byte *ScummEngine::translateTextAndPlaySpeech(const byte *ptr) {
|
||||
pointer[j] = 0;
|
||||
|
||||
// Play speech
|
||||
_imuseDigital->playBundleSound(pointer);
|
||||
if (!(_features & GF_DEMO) && (_gameId == GID_CMI)) // CMI demo does not have .IMX for voice
|
||||
strcat(pointer, ".IMX");
|
||||
_imuseDigital->stopSound(kTalkSoundID);
|
||||
_imuseDigital->startVoice(kTalkSoundID, pointer);
|
||||
|
||||
ptr = _transText;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user