aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/resource.cpp152
-rw-r--r--engines/sci/resource.h36
-rw-r--r--engines/sci/sfx/music.cpp141
-rw-r--r--engines/sci/sfx/music.h6
-rw-r--r--engines/sci/sfx/soundcmd.cpp2
5 files changed, 178 insertions, 159 deletions
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index c8b109f070..14a72af1b0 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -1808,89 +1808,105 @@ bool ResourceManager::hasSci1Voc900() {
return offset == res->size;
}
-SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan) : _resMan(resMan) {
- Resource *res = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true);
- if (!res)
+SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) {
+ Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true);
+ int trackNr, channelNr;
+ if (!resource)
return;
- _innerResource = res;
-
- byte *ptr = res->data, *p1;
- tagChannel *pCh;
- // count # of tracks
- nTracks = 0;
- while ((*ptr++) != 0xFF) {
- nTracks++;
- while (*ptr != 0xFF)
- ptr += 6;
- ptr++;
- }
- aTracks = new tagTrack[nTracks];
- ptr = res->data;
- for (int i = 0; i < nTracks; i++) {
- // SCI01/SCI1/SCI11
- // Track info starts with track-type:BYTE
- // Then track-information gets appeneded Unknown:WORD, TrackOffset:WORD, TrackSize:WORD
- // 0xFF:BYTE as terminator to end that track and begin with another track-type
- // track-type 0xFF means end-of-tracks
-
- aTracks[i].type = (kTrackType) * ptr++;
- // counting # of channels used
- p1 = ptr;
- aTracks[i].nChannels = 0;
- while (*p1 != 0xFF) {
- p1 += 6;
- aTracks[i].nChannels++;
+ _innerResource = resource;
+
+ byte *data = resource->data, *data2;
+ Channel *channel;
+
+ switch (_soundVersion) {
+ case SCI_VERSION_0_EARLY:
+ error("SCI0 sound data currently not supported");
+ break;
+
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_LATE:
+ // count # of tracks
+ _trackCount = 0;
+ while ((*data++) != 0xFF) {
+ _trackCount++;
+ while (*data != 0xFF)
+ data += 6;
+ data++;
}
- aTracks[i].aChannels = new tagChannel[aTracks[i].nChannels];
- if (aTracks[i].type != 0xF0) // digital track marker - not supported at time
- {
- aTracks[i].nDigital = 0xFF; // meanwhile - no ditigal channel associated
- for (int j = 0; j < aTracks[i].nChannels; j++) {
- pCh = &aTracks[i].aChannels[j];
- pCh->unk = READ_LE_UINT16(ptr);
- pCh->ptr = res->data + READ_LE_UINT16(ptr + 2) + 2;
- pCh->size = READ_LE_UINT16(ptr + 4) - 2; // not counting channel header
- pCh->number = *(pCh->ptr - 2);
- pCh->poly = *(pCh->ptr - 1);
- pCh->time = pCh->prev = 0;
- if (pCh->number == 0xFE) // digital channel
- aTracks[i].nDigital = j;
- ptr += 6;
+ _tracks = new Track[_trackCount];
+ data = resource->data;
+ for (trackNr = 0; trackNr < _trackCount; trackNr++) {
+ // SCI01/SCI1/SCI11
+ // Track info starts with track-type:BYTE
+ // Then channel-information gets appeneded Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD
+ // 0xFF:BYTE as terminator to end that track and begin with another track-type
+ // track-type 0xFF means end-of-tracks
+
+ _tracks[trackNr].type = (TrackType) *data++;
+ // counting # of channels used
+ data2 = data;
+ _tracks[trackNr].channelCount = 0;
+ while (*data2 != 0xFF) {
+ data2 += 6;
+ _tracks[trackNr].channelCount++;
}
- } else {
- // Skip over digital track
- ptr += 6;
+ _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount];
+ if (_tracks[trackNr].type != 0xF0) { // digital track marker - not supported at time
+ _tracks[trackNr].nDigital = 0xFF; // meanwhile - no ditigal channel associated
+ for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) {
+ channel = &_tracks[trackNr].channels[channelNr];
+ channel->unk = READ_LE_UINT16(data);
+ channel->data = resource->data + READ_LE_UINT16(data + 2) + 2;
+ channel->size = READ_LE_UINT16(data + 4) - 2; // not counting channel header
+ channel->number = *(channel->data - 2);
+ channel->poly = *(channel->data - 1);
+ channel->time = channel->prev = 0;
+ if (channel->number == 0xFE) // digital channel
+ _tracks[trackNr].nDigital = channelNr;
+ data += 6;
+ }
+ } else {
+ // Skip over digital track
+ data += 6;
+ }
+ data++; // skipping 0xFF that closes channels list
}
- ptr++; // skipping 0xFF that closes channels list
- }
- /*
- digital track ->ptr points to header:
- [w] sample rate
- [w] size
- [w] ? 00 00 maybe compression flag
- [w] ? size again - decompressed size maybe
- */
+ /*
+ digital track ->ptr points to header:
+ [w] sample rate
+ [w] size
+ [w] ? 00 00 maybe compression flag
+ [w] ? size again - decompressed size maybe
+ */
+ break;
+ }
}
//----------------------------------------------------
SoundResource::~SoundResource() {
- for (int i = 0; i < nTracks; i++)
- delete[] aTracks[i].aChannels;
- delete[] aTracks;
+ for (int trackNr = 0; trackNr < _trackCount; trackNr++)
+ delete[] _tracks[trackNr].channels;
+ delete[] _tracks;
_resMan->unlockResource(_innerResource);
}
//----------------------------------------------------
-SoundResource::tagTrack* SoundResource::getTrackByNumber(uint16 number) {
- if (/*number >= 0 &&*/number < nTracks)
- return &aTracks[number];
+SoundResource::Track* SoundResource::getTrackByNumber(uint16 number) {
+ if (_soundVersion == SCI_VERSION_0_EARLY)
+ return &_tracks[0];
+
+ if (/*number >= 0 &&*/number < _trackCount)
+ return &_tracks[number];
return NULL;
}
-SoundResource::tagTrack* SoundResource::getTrackByType(kTrackType type) {
- for (int i = 0; i < nTracks; i++) {
- if (aTracks[i].type == type)
- return &aTracks[i];
+SoundResource::Track* SoundResource::getTrackByType(TrackType type) {
+ if (_soundVersion == SCI_VERSION_0_EARLY)
+ return &_tracks[0];
+
+ for (int trackNr = 0; trackNr < _trackCount; trackNr++) {
+ if (_tracks[trackNr].type == type)
+ return &_tracks[trackNr];
}
return NULL;
}
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 914b75cd1e..ef0674badd 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -429,40 +429,42 @@ protected:
class SoundResource {
public:
- enum kTrackType {
- kTrackAdlib = 0,
- kTrackGameBlaster = 9,
- kTrackMT32 = 12,
- kTrackSpeaker = 18,
- kTrackTandy = 19
+ enum TrackType {
+ TRACKTYPE_ADLIB = 0,
+ TRACKTYPE_GAMEBLASTER = 9,
+ TRACKTYPE_MT32 = 12,
+ TRACKTYPE_SPEAKER = 18,
+ TRACKTYPE_TANDY = 19,
+ TRACKTYPE_NONE = 255
};
- struct tagChannel {
+ struct Channel {
byte number;
byte poly;
uint16 unk;
uint16 size;
- byte *ptr;
+ byte *data;
long time;
byte prev;
};
- struct tagTrack {
- kTrackType type;
+ struct Track {
+ TrackType type;
byte nDigital;
- byte nChannels;
- tagChannel *aChannels;
+ byte channelCount;
+ Channel *channels;
uint sz;
};
public:
- SoundResource(uint32 resNumber, ResourceManager *resMan);
+ SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion);
~SoundResource();
- tagTrack *getTrackByNumber(uint16 number);
- tagTrack *getTrackByType(kTrackType type);
+ Track *getTrackByNumber(uint16 number);
+ Track *getTrackByType(TrackType type);
private:
- byte nTracks;
- tagTrack *aTracks;
+ SciVersion _soundVersion;
+ int _trackCount;
+ Track *_tracks;
Resource *_innerResource;
ResourceManager *_resMan;
};
diff --git a/engines/sci/sfx/music.cpp b/engines/sci/sfx/music.cpp
index c011a66a3d..6111655d62 100644
--- a/engines/sci/sfx/music.cpp
+++ b/engines/sci/sfx/music.cpp
@@ -282,46 +282,46 @@ void SciMusic::loadPatchMT32() {
//----------------------------------------
void SciMusic::soundInitSnd(MusicEntry *pSnd) {
- //_mutex.lock();
+ SoundResource::Track *track = NULL;
- SoundResource::tagTrack *pTrack = NULL;
+ //_mutex.lock();
switch (_midiType) {
case MD_PCSPK:
- pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackSpeaker);
+ track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_SPEAKER);
break;
case MD_PCJR:
- pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackTandy);
+ track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_TANDY);
break;
case MD_ADLIB:
- pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackAdlib);
+ track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB);
break;
case MD_MT32:
- pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackMT32);
+ track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_MT32);
break;
default:
break;
}
// attempting to select default MT-32/Roland track
- if (!pTrack)
- pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackMT32);
- if (pTrack) {
+ if (!track)
+ track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_MT32);
+ if (track) {
// if MIDI device is selected but there is no digital track in sound resource
// try to use adlib's digital sample if possible
- if (_midiType <= MD_MT32 && pTrack->nDigital == 0xFF && _bMultiMidi) {
- if (pSnd->soundRes->getTrackByType(SoundResource::kTrackAdlib)->nDigital != 0xFF)
- pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackAdlib);
+ if (_midiType <= MD_MT32 && track->nDigital == 0xFF && _bMultiMidi) {
+ if (pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB)->nDigital != 0xFF)
+ track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB);
}
// play digital sample
- if (pTrack->nDigital != 0xFF) {
- byte *pdata = pTrack->aChannels[pTrack->nDigital].ptr;
- int rate = READ_LE_UINT16(pdata);
- uint32 size = READ_LE_UINT16(pdata + 2);
- assert(READ_LE_UINT16(pdata + 4) == 0); // Possibly a compression flag
- //assert(READ_LE_UINT16(pdata + 6) == size);
+ if (track->nDigital != 0xFF) {
+ byte *channelData = track->channels[track->nDigital].data;
+ int rate = READ_LE_UINT16(channelData);
+ uint32 size = READ_LE_UINT16(channelData + 2);
+ assert(READ_LE_UINT16(channelData + 4) == 0); // Possibly a compression flag
+ //assert(READ_LE_UINT16(channelData + 6) == size);
if (pSnd->pStreamAud)
delete pSnd->pStreamAud;
- pSnd->pStreamAud = Audio::makeLinearInputStream(pdata + 8, size, rate,
+ pSnd->pStreamAud = Audio::makeLinearInputStream(channelData + 8, size, rate,
Audio::Mixer::FLAG_UNSIGNED, 0, 0);
pSnd->hCurrentAud = Audio::SoundHandle();
} else {
@@ -331,7 +331,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
pSnd->pMidiParser->setMidiDriver(_pMidiDrv);
pSnd->pMidiParser->setTimerRate(_dwTempo);
}
- pSnd->pMidiParser->loadMusic(pTrack, pSnd);
+ pSnd->pMidiParser->loadMusic(track, pSnd);
}
}
@@ -482,7 +482,7 @@ void SciMusic::soundSetMasterVolume(uint16 vol) {
//
MidiParser_SCI::MidiParser_SCI() :
MidiParser() {
- _pMidiData = NULL;
+ _mixedData = NULL;
// mididata contains delta in 1/60th second
// values of ppqn and tempo are found experimentally and may be wrong
_ppqn = 1;
@@ -493,15 +493,15 @@ MidiParser_SCI::~MidiParser_SCI() {
unloadMusic();
}
//---------------------------------------------
-bool MidiParser_SCI::loadMusic(SoundResource::tagTrack *ptrack, MusicEntry *psnd) {
+bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd) {
unloadMusic();
- _pTrack = ptrack;
+ _track = track;
_pSnd = psnd;
setVolume(psnd->volume);
midiMixChannels();
_num_tracks = 1;
- _tracks[0] = _pMidiData;
+ _tracks[0] = _mixedData;
setTrack(0);
_loopTick = 0;
return true;
@@ -511,9 +511,9 @@ void MidiParser_SCI::unloadMusic() {
allNotesOff();
resetTracking();
_num_tracks = 0;
- if (_pMidiData) {
- delete[] _pMidiData;
- _pMidiData = NULL;
+ if (_mixedData) {
+ delete[] _mixedData;
+ _mixedData = NULL;
}
}
@@ -629,13 +629,13 @@ byte MidiParser_SCI::midiGetNextChannel(long ticker) {
byte curr = 0xFF;
long closest = ticker + 1000000, next = 0;
- for (int i = 0; i < _pTrack->nChannels; i++) {
- if (_pTrack->aChannels[i].time == -1) // channel ended
+ for (int i = 0; i < _track->channelCount; i++) {
+ if (_track->channels[i].time == -1) // channel ended
continue;
- next = *_pTrack->aChannels[i].ptr; // when the next event shoudl occur
+ next = *_track->channels[i].data; // when the next event shoudl occur
if (next == 0xF8) // 0xF8 means 240 ticks delay
next = 240;
- next += _pTrack->aChannels[i].time;
+ next += _track->channels[i].time;
if (next < closest) {
curr = i;
closest = next;
@@ -646,79 +646,80 @@ byte MidiParser_SCI::midiGetNextChannel(long ticker) {
}
//----------------------------------------
byte *MidiParser_SCI::midiMixChannels() {
- int lSize = 0;
- byte **pDataPtr = new byte *[_pTrack->nChannels];
- for (int i = 0; i < _pTrack->nChannels; i++) {
- pDataPtr[i] = _pTrack->aChannels[i].ptr;
- _pTrack->aChannels[i].time = 0;
- _pTrack->aChannels[i].prev = 0;
- lSize += _pTrack->aChannels[i].size;
+ int totalSize = 0;
+ byte **dataPtr = new byte *[_track->channelCount];
+
+ for (int i = 0; i < _track->channelCount; i++) {
+ dataPtr[i] = _track->channels[i].data;
+ _track->channels[i].time = 0;
+ _track->channels[i].prev = 0;
+ totalSize += _track->channels[i].size;
}
- byte *pOutData = new byte[lSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data
- _pMidiData = pOutData;
+ byte *mixedData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data
+ _mixedData = mixedData;
long ticker = 0;
byte curr, delta;
byte cmd, par1, global_prev = 0;
long new_delta;
- SoundResource::tagChannel *pCh;
+ SoundResource::Channel *channel;
while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still active channel
- pCh = &_pTrack->aChannels[curr];
- delta = *pCh->ptr++;
- pCh->time += (delta == 0xF8 ? 240 : delta); // when the comamnd is supposed to occur
+ channel = &_track->channels[curr];
+ delta = *channel->data++;
+ channel->time += (delta == 0xF8 ? 240 : delta); // when the comamnd is supposed to occur
if (delta == 0xF8)
continue;
- new_delta = pCh->time - ticker;
+ new_delta = channel->time - ticker;
ticker += new_delta;
- cmd = *pCh->ptr++;
+ cmd = *channel->data++;
if (cmd != 0xFC) {
// output new delta
while (new_delta > 240) {
- *pOutData++ = 0xF8;
+ *mixedData++ = 0xF8;
new_delta -= 240;
}
- *pOutData++ = (byte)new_delta;
+ *mixedData++ = (byte)new_delta;
}
switch (cmd) {
case 0xF0: // sysEx
- *pOutData++ = cmd;
+ *mixedData++ = cmd;
do {
- par1 = *pCh->ptr++;
- *pOutData++ = par1; // out
+ par1 = *channel->data++;
+ *mixedData++ = par1; // out
} while (par1 != 0xF7);
break;
case 0xFC: // end channel
- pCh->time = -1; // FIXME
+ channel->time = -1; // FIXME
break;
default: // MIDI command
if (cmd & 0x80)
- par1 = *pCh->ptr++;
+ par1 = *channel->data++;
else {// running status
par1 = cmd;
- cmd = pCh->prev;
+ cmd = channel->prev;
}
if (cmd != global_prev)
- *pOutData++ = cmd; // out cmd
- *pOutData++ = par1;// pout par1
+ *mixedData++ = cmd; // out cmd
+ *mixedData++ = par1;// pout par1
if (nMidiParams[(cmd >> 4) - 8] == 2)
- *pOutData++ = *pCh->ptr++; // out par2
- pCh->prev = cmd;
+ *mixedData++ = *channel->data++; // out par2
+ channel->prev = cmd;
global_prev = cmd;
}// switch(cmd)
}// while (curr)
// mixing finished. inserting stop event
- *pOutData++ = 0;
- *pOutData++ = 0xFF;
- *pOutData++ = 0x2F;
- *pOutData++ = 0x00;
- *pOutData++ = 0x00;
+ *mixedData++ = 0;
+ *mixedData++ = 0xFF;
+ *mixedData++ = 0x2F;
+ *mixedData++ = 0x00;
+ *mixedData++ = 0x00;
- for (int i = 0; i < _pTrack->nChannels; i++)
- _pTrack->aChannels[i].ptr = pDataPtr[i];
+ for (int channelNr = 0; channelNr < _track->channelCount; channelNr++)
+ _track->channels[channelNr].data = dataPtr[channelNr];
- delete[] pDataPtr;
- return _pMidiData;
+ delete[] dataPtr;
+ return _mixedData;
}
void MidiParser_SCI::setVolume(byte bVolume) {
@@ -728,9 +729,9 @@ void MidiParser_SCI::setVolume(byte bVolume) {
_volume = bVolume;
// sending volume change to all active channels
- for (int i = 0; i < _pTrack->nChannels; i++)
- if (_pTrack->aChannels[i].number <= 0xF)
- _driver->send(0xB0 + _pTrack->aChannels[i].number, 7, _volume);
+ for (int i = 0; i < _track->channelCount; i++)
+ if (_track->channels[i].number <= 0xF)
+ _driver->send(0xB0 + _track->channels[i].number, 7, _volume);
}
}
} // end of namespace SCI
diff --git a/engines/sci/sfx/music.h b/engines/sci/sfx/music.h
index 5fc6ea8325..91ca0626f2 100644
--- a/engines/sci/sfx/music.h
+++ b/engines/sci/sfx/music.h
@@ -160,7 +160,7 @@ class MidiParser_SCI : public MidiParser {
public:
MidiParser_SCI();
~MidiParser_SCI();
- bool loadMusic(SoundResource::tagTrack *ptrack, MusicEntry *psnd);
+ bool loadMusic(SoundResource::Track *track, MusicEntry *psnd);
bool loadMusic(byte *, uint32) {
return false;
}
@@ -177,8 +177,8 @@ protected:
void parseNextEvent(EventInfo &info);
byte *midiMixChannels();
byte midiGetNextChannel(long ticker);
- byte *_pMidiData;
- SoundResource::tagTrack *_pTrack;
+ byte *_mixedData;
+ SoundResource::Track *_track;
MusicEntry *_pSnd;
uint32 _loopTick;
byte _volume;
diff --git a/engines/sci/sfx/soundcmd.cpp b/engines/sci/sfx/soundcmd.cpp
index 98d4b53f74..2a153e6076 100644
--- a/engines/sci/sfx/soundcmd.cpp
+++ b/engines/sci/sfx/soundcmd.cpp
@@ -288,7 +288,7 @@ void SoundCommandParser::cmdInitHandle(reg_t obj, int16 value) {
newSound->soundRes = 0;
newSound->resnum = number;
if (number && _resMan->testResource(ResourceId(kResourceTypeSound, number)))
- newSound->soundRes = new SoundResource(number, _resMan);
+ newSound->soundRes = new SoundResource(number, _resMan, _doSoundVersion);
newSound->soundObj = obj;
newSound->loop = GET_SEL32V(_segMan, obj, loop) == 0xFFFF ? 1 : 0;
newSound->prio = GET_SEL32V(_segMan, obj, pri) & 0xFF;