[Scummvm-git-logs] scummvm master -> 434d1f37f9398b6a7a1b08cd5464a1d5ecccdc41
aquadran
aquadran at gmail.com
Fri Dec 25 04:27:20 UTC 2020
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
434d1f37f9 SCUMM: COMI: implement iMUSE crossfades between regions (#2672)
Commit: 434d1f37f9398b6a7a1b08cd5464a1d5ecccdc41
https://github.com/scummvm/scummvm/commit/434d1f37f9398b6a7a1b08cd5464a1d5ecccdc41
Author: AndywinXp (andywinxp at gmail.com)
Date: 2020-12-25T05:27:17+01:00
Commit Message:
SCUMM: COMI: implement iMUSE crossfades between regions (#2672)
* SCUMM: COMI: implement region crossfades after JUMP instruction
* SCUMM: COMI: best attempt at fixing part 3 song crossfades
* SCUMM: COMI: generalise loop shift handling to remove hacks
Changed paths:
engines/scumm/imuse_digi/dimuse.cpp
engines/scumm/imuse_digi/dimuse.h
engines/scumm/imuse_digi/dimuse_script.cpp
engines/scumm/imuse_digi/dimuse_sndmgr.cpp
engines/scumm/imuse_digi/dimuse_tables.cpp
engines/scumm/imuse_digi/dimuse_tables.h
engines/scumm/imuse_digi/dimuse_track.cpp
engines/scumm/imuse_digi/dimuse_track.h
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index 1ea5aff8a5..7110b827ce 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -30,6 +30,7 @@
#include "scumm/imuse_digi/dimuse_bndmgr.h"
#include "scumm/imuse_digi/dimuse_codecs.h"
#include "scumm/imuse_digi/dimuse_track.h"
+#include "scumm/imuse_digi/dimuse_tables.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
@@ -103,6 +104,10 @@ void IMuseDigital::resetState() {
_radioChatterSFX = 0;
_triggerUsed = false;
_speechIsPlaying = false;
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ _scheduledCrossfades[l].scheduled = false;
+ _scheduledCrossfades[l].isJumpToLoop = false;
+ }
}
static void syncWithSerializer(Common::Serializer &s, Track &t) {
@@ -177,6 +182,24 @@ void IMuseDigital::saveLoadEarly(Common::Serializer &s) {
continue;
}
+ if (_vm->_game.id == GID_CMI) {
+ if (track->soundId / 1000 == 1) { // State
+ for (l = 0; _comiStateMusicTable[l].soundId != -1; l++) {
+ if ((_comiStateMusicTable[l].soundId == track->soundId)) {
+ track->loopShiftType = _comiStateMusicTable[l].shiftLoop;
+ break;
+ }
+ }
+ } else if (track->soundId / 1000 == 2) { // Sequence
+ for (l = 0; _comiSeqMusicTable[l].soundId != -1; l++) {
+ if ((_comiSeqMusicTable[l].soundId == track->soundId)) {
+ track->loopShiftType = _comiSeqMusicTable[l].shiftLoop;
+ break;
+ }
+ }
+ }
+ }
+
track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc);
track->dataOffset = _sound->getRegionOffset(track->soundDesc, track->curRegion);
int bits = _sound->getBits(track->soundDesc);
@@ -204,9 +227,65 @@ void IMuseDigital::saveLoadEarly(Common::Serializer &s) {
}
}
+void IMuseDigital::runScheduledCrossfades() {
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_scheduledCrossfades[l].scheduled) {
+ _scheduledCrossfades[l].scheduled = false;
+ Track *oldTrack = _track[l];
+
+ int newTrackId = -1;
+
+ oldTrack->volFadeDelay = _scheduledCrossfades[l].fadeDelay;
+ if (oldTrack->volGroupId == IMUSE_VOLGRP_MUSIC) {
+ newTrackId = startMusicWithOtherPos(oldTrack->soundName, oldTrack->soundId, oldTrack->curHookId, 127, oldTrack);
+ } else {
+ newTrackId = startSound(oldTrack->soundId, "", IMUSE_RESOURCE, IMUSE_VOLGRP_SFX, NULL, 0, _scheduledCrossfades[l].volumeBefJump, oldTrack->soundPriority, oldTrack);
+ }
+
+ if (newTrackId == -1) {
+ debug(5, "IMuseDigital::runScheduledCrossfades(): couldn't allocate crossfade for sound %d", oldTrack->soundId);
+ return;
+ }
+
+ Track *newTrack = _track[newTrackId];
+ newTrack->curRegion = _scheduledCrossfades[l].destRegion;
+
+ // WORKAROUND for some files having a little bit earlier
+ // loop point set in their iMUSE map; keep in mind we're considering
+ // regionOffset -= (oldTrack->feedSize / _callbackFps) as NO SHIFT.
+ // In COMI we're currently using 4 shift types.
+ if (newTrack->volGroupId == IMUSE_VOLGRP_SFX || !_scheduledCrossfades[l].isJumpToLoop) {
+ newTrack->regionOffset = 0;
+ } else if (_scheduledCrossfades[l].isJumpToLoop) {
+ switch (newTrack->loopShiftType) {
+ case 0:
+ newTrack->regionOffset -= (oldTrack->feedSize / _callbackFps);
+ break;
+ case 1:
+ newTrack->regionOffset = 0;
+ break;
+ case 2:
+ newTrack->regionOffset -= (oldTrack->feedSize / _callbackFps) + (oldTrack->feedSize / _callbackFps) / 2 + 2;
+ break;
+ case 3:
+ newTrack->regionOffset -= (oldTrack->feedSize / _callbackFps) - (oldTrack->feedSize / _callbackFps) / 2 + 2;
+ break;
+ case 4:
+ newTrack->regionOffset -= ((oldTrack->feedSize / _callbackFps) / 3) * 2;
+ break;
+ }
+ }
+
+ newTrack->dataOffset = _scheduledCrossfades[l].destDataOffset;
+ oldTrack->alreadyCrossfading = true; // We set this so to avoid duplicate crossfades
+ handleComiFadeOut(oldTrack, _scheduledCrossfades[l].fadeDelay);
+ }
+ }
+}
+
void IMuseDigital::callback() {
Common::StackLock lock(_mutex, "IMuseDigital::callback()");
-
+ runScheduledCrossfades();
_speechIsPlaying = false;
// Check for any track playing a speech line
if (_vm->_game.id == GID_CMI) {
@@ -419,6 +498,8 @@ void IMuseDigital::callback() {
if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {
switchToNextRegion(track);
+ if (_scheduledCrossfades[track->trackId].scheduled)
+ break;
if (!track->stream) // Seems we reached the end of the stream
break;
}
@@ -439,6 +520,10 @@ void IMuseDigital::callback() {
// This allows for a fallback to pan = 64 (center) and volume = 127 (full)
if (track->speakingActor != nullptr) {
effVol = track->speakingActor->_talkVolume;
+ // Even though we fixed this in IMuseDigital::setVolume(),
+ // some sounds might be started without even calling that function
+ if (effVol > 127)
+ effVol /= 2;
effVol = int(round(effVol * 1.04));
effPan = (track->speakingActor->_talkPan != 64) ? 2 * track->speakingActor->_talkPan - 127 : 0;
}
@@ -504,20 +589,51 @@ void IMuseDigital::switchToNextRegion(Track *track) {
}
int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
- if (jumpId != -1) {
+ if ((_vm->_game.id != GID_CMI && jumpId != -1) || (_vm->_game.id == GID_CMI && jumpId != -1 && !track->alreadyCrossfading)) {
int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
assert(region != -1);
int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
assert(sampleHookId != -1);
+
+ bool isJumpToStart = (soundDesc->jump[jumpId].dest == soundDesc->marker[2].pos && !scumm_stricmp(soundDesc->marker[2].ptr, "start"));
+ bool isJumpToLoop = false;
+ if (!isJumpToStart) {
+ for (int m = 0; m < soundDesc->numMarkers; m++) {
+ if (soundDesc->jump[jumpId].dest == soundDesc->marker[m].pos) {
+ Common::String markerDesc = soundDesc->marker[m].ptr;
+ if (markerDesc.contains("loop")) {
+ isJumpToLoop = true;
+ }
+ break;
+ }
+ }
+ }
+
debug(5, "SwToNeReg(trackId:%d) - JUMP found - sound:%d, track hookId:%d, data hookId:%d", track->trackId, track->soundId, track->curHookId, sampleHookId);
if (track->curHookId == sampleHookId) {
int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
debug(5, "SwToNeReg(trackId:%d) - sound(%d) match hookId", track->trackId, track->soundId);
if (fadeDelay) {
- // COMI specific: jump to new region without true crossfades; this is not true to the original interpreter,
- // but crossfading between regions in the correct way requires an implementation which is more complex.
- // Leaving as is, for now.
- if (_vm->_game.id != GID_CMI) {
+ // If there's a fade time, it means we have to CROSSFADE the jump.
+ // To do this we schedule a crossfade to happen at the next callback call;
+ // the reason for the scheduling is due to the fact that calling the
+ // crossfade immediately causes inconsistencies (and this crashes ImuseDigiSndMgr::getDataFromRegion())
+ if (_vm->_game.id == GID_CMI) {
+ // Block crossfades when the track is already fading down; this prevents edge cases where a crossfade
+ // between two tracks with the same attribPos (like sounds 1202, 1203 and 1204) is happening at the
+ // same time as a loop; the result is that the former is prioritized and the latter
+ // is executed without a crossfade. Also, avoid music crossfades for start markers, these are just plain
+ // dangerous and useless since there's already a fade in for those.
+ if (!track->volFadeUsed && !(track->volFadeStep < 0) && !(isJumpToStart && track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+ _scheduledCrossfades[track->trackId].scheduled = true;
+ _scheduledCrossfades[track->trackId].destRegion = region;
+ _scheduledCrossfades[track->trackId].destDataOffset = _sound->getRegionOffset(soundDesc, region);
+ _scheduledCrossfades[track->trackId].fadeDelay = fadeDelay;
+ _scheduledCrossfades[track->trackId].destHookId = track->curHookId;
+ _scheduledCrossfades[track->trackId].volumeBefJump = track->vol / 1000;
+ _scheduledCrossfades[track->trackId].isJumpToLoop = isJumpToLoop;
+ }
+ } else {
debug(5, "SwToNeReg(trackId:%d) - call cloneToFadeOutTrack(delay:%d)", track->trackId, fadeDelay);
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
if (fadeTrack) {
@@ -526,16 +642,18 @@ void IMuseDigital::switchToNextRegion(Track *track) {
debug(5, "SwToNeReg(trackId:%d) - sound(%d) faded track, select region %d, curHookId: %d", fadeTrack->trackId, fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId);
fadeTrack->curHookId = 0;
}
- }
+ }
}
- track->curRegion = region;
+ if (_vm->_game.id != GID_CMI || !_scheduledCrossfades[track->trackId].scheduled)
+ track->curRegion = region;
+
debug(5, "SwToNeReg(trackId:%d) - sound(%d) jump to region %d, curHookId: %d", track->trackId, track->soundId, track->curRegion, track->curHookId);
track->curHookId = 0;
} else {
// Check if the jump led to a "start" marker; if so, we have to enforce it anyway.
// Fixes bug/edge-case #11956;
// Go see ImuseDigiSndMgr::getJumpIdByRegionAndHookId(...) for further information.
- if (_vm->_game.id == GID_CMI && soundDesc->jump[jumpId].dest == soundDesc->marker[2].pos && !scumm_stricmp(soundDesc->marker[2].ptr, "start")) {
+ if (_vm->_game.id == GID_CMI && isJumpToStart) {
track->curRegion = region;
debug(5, "SwToNeReg(trackId:%d) - Enforced sound(%d) jump to region %d marked with a \"start\" marker, hookId(%d)", track->trackId, track->soundId, track->curRegion, track->curHookId);
} else {
diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h
index 12871efd06..9f255f882a 100644
--- a/engines/scumm/imuse_digi/dimuse.h
+++ b/engines/scumm/imuse_digi/dimuse.h
@@ -69,6 +69,18 @@ private:
TriggerParams _triggerParams;
bool _triggerUsed;
+ struct ScheduledCrossfade {
+ bool scheduled;
+ int destRegion;
+ int destDataOffset;
+ int fadeDelay;
+ int destHookId;
+ int volumeBefJump;
+ bool isJumpToLoop;
+ };
+
+ ScheduledCrossfade _scheduledCrossfades[MAX_DIGITAL_TRACKS];
+
Track *_track[MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS];
Common::Mutex _mutex;
@@ -94,7 +106,7 @@ private:
void callback();
void switchToNextRegion(Track *track);
int allocSlot(int priority);
- void startSound(int soundId, const char *soundName, int soundType, int volGroupId, Audio::AudioStream *input, int hookId, int volume, int priority, Track *otherTrack);
+ int startSound(int soundId, const char *soundName, int soundType, int volGroupId, Audio::AudioStream *input, int hookId, int volume, int priority, Track *otherTrack);
void selectVolumeGroup(int soundId, int volGroupId);
int32 getPosInMs(int soundId);
@@ -133,16 +145,17 @@ public:
void setAudioNames(int32 num, char *names);
- void startVoice(int soundId, Audio::AudioStream *input);
- void startVoice(int soundId, const char *soundName);
- void startMusic(int soundId, int volume);
- void startMusic(const char *soundName, int soundId, int hookId, int volume);
- void startMusicWithOtherPos(const char *soundName, int soundId, int hookId, int volume, Track *otherTrack);
- void startSfx(int soundId, int priority);
+ int startVoice(int soundId, Audio::AudioStream *input);
+ int startVoice(int soundId, const char *soundName);
+ int startMusic(int soundId, int volume);
+ int startMusic(const char *soundName, int soundId, int hookId, int volume);
+ int startMusicWithOtherPos(const char *soundName, int soundId, int hookId, int volume, Track *otherTrack);
+ int startSfx(int soundId, int priority);
void startSound(int sound) override
{ error("IMuseDigital::startSound(int) should be never called"); }
void saveLoadEarly(Common::Serializer &ser);
+ void runScheduledCrossfades();
void resetState();
void setRadioChatterSFX(bool state) {
_radioChatterSFX = state;
diff --git a/engines/scumm/imuse_digi/dimuse_script.cpp b/engines/scumm/imuse_digi/dimuse_script.cpp
index c906a927c2..4ab89c7cc0 100644
--- a/engines/scumm/imuse_digi/dimuse_script.cpp
+++ b/engines/scumm/imuse_digi/dimuse_script.cpp
@@ -212,34 +212,34 @@ void IMuseDigital::refreshScripts() {
}
}
-void IMuseDigital::startVoice(int soundId, Audio::AudioStream *input) {
+int IMuseDigital::startVoice(int soundId, Audio::AudioStream *input) {
debug(5, "startVoiceStream(%d)", soundId);
- startSound(soundId, "", 0, IMUSE_VOLGRP_VOICE, input, 0, 127, 127, NULL);
+ return startSound(soundId, "", 0, IMUSE_VOLGRP_VOICE, input, 0, 127, 127, NULL);
}
-void IMuseDigital::startVoice(int soundId, const char *soundName) {
+int IMuseDigital::startVoice(int soundId, const char *soundName) {
debug(5, "startVoiceBundle(%s, %d)", soundName, soundId);
- startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_VOICE, NULL, 0, 127, 127, NULL);
+ return startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_VOICE, NULL, 0, 127, 127, NULL);
}
-void IMuseDigital::startMusic(int soundId, int volume) {
+int IMuseDigital::startMusic(int soundId, int volume) {
debug(5, "startMusicResource(%d)", soundId);
- startSound(soundId, "", IMUSE_RESOURCE, IMUSE_VOLGRP_MUSIC, NULL, 0, volume, 126, NULL);
+ return startSound(soundId, "", IMUSE_RESOURCE, IMUSE_VOLGRP_MUSIC, NULL, 0, volume, 126, NULL);
}
-void IMuseDigital::startMusic(const char *soundName, int soundId, int hookId, int volume) {
+int IMuseDigital::startMusic(const char *soundName, int soundId, int hookId, int volume) {
debug(5, "startMusicBundle(%s, soundId:%d, hookId:%d)", soundName, soundId, hookId);
- startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_MUSIC, NULL, hookId, volume, 126, NULL);
+ return startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_MUSIC, NULL, hookId, volume, 126, NULL);
}
-void IMuseDigital::startMusicWithOtherPos(const char *soundName, int soundId, int hookId, int volume, Track *otherTrack) {
+int IMuseDigital::startMusicWithOtherPos(const char *soundName, int soundId, int hookId, int volume, Track *otherTrack) {
debug(5, "startMusicWithOtherPos(%s, soundId:%d, hookId:%d, oldSoundId:%d)", soundName, soundId, hookId, otherTrack->soundId);
- startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_MUSIC, NULL, hookId, volume, 126, otherTrack);
+ return startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOLGRP_MUSIC, NULL, hookId, volume, 126, otherTrack);
}
-void IMuseDigital::startSfx(int soundId, int priority) {
+int IMuseDigital::startSfx(int soundId, int priority) {
debug(5, "startSfx(%d)", soundId);
- startSound(soundId, "", IMUSE_RESOURCE, IMUSE_VOLGRP_SFX, NULL, 0, 127, priority, NULL);
+ return startSound(soundId, "", IMUSE_RESOURCE, IMUSE_VOLGRP_SFX, NULL, 0, 127, priority, NULL);
}
void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width, int32 &height) {
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
index ffd020a3fe..80be6000b2 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -653,7 +653,13 @@ int ImuseDigiSndMgr::getJumpFade(SoundDesc *soundDesc, int number) {
int32 ImuseDigiSndMgr::getDataFromRegion(SoundDesc *soundDesc, int region, byte **buf, int32 offset, int32 size) {
debug(6, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundDesc->numRegions);
assert(checkForProperHandle(soundDesc));
- assert(buf && offset >= 0 && size >= 0);
+
+ // In COMI we allow at least -size*2 as offset, since music
+ // tracks need that in order to be realigned after crossfades
+ if (_vm->_game.id == GID_CMI)
+ assert(buf && offset >= -(size * 2) && size >= 0);
+ else
+ assert(buf && offset >= 0 && size >= 0);
assert(region >= 0 && region < soundDesc->numRegions);
int32 region_offset = soundDesc->region[region].offset;
diff --git a/engines/scumm/imuse_digi/dimuse_tables.cpp b/engines/scumm/imuse_digi/dimuse_tables.cpp
index 9bbafb8278..b88f2e1a1e 100644
--- a/engines/scumm/imuse_digi/dimuse_tables.cpp
+++ b/engines/scumm/imuse_digi/dimuse_tables.cpp
@@ -284,214 +284,214 @@ const imuseDigTable _digSeqMusicTable[] = {
};
const imuseComiTable _comiStateMusicTable[] = {
- {0, 1000, "STATE_NULL", 0, 0, 0, ""}, /* 00 */
- {0, 1001, "stateNoChange", 0, 0, 0, ""}, /* 01 */
- {3, 1098, "stateCredits1", 0, 0, 60, "1098-C~1.IMX"}, /* 02 */
- {3, 1099, "stateMenu", 0, 0, 60, "1099-M~1.IMX"}, /* 03 */
- {3, 1100, "stateHold1", 4, 0, 60, "1100-H~1.IMX"}, /* 04 */
- {3, 1101, "stateWaterline1", 4, 0, 60, "1101-W~1.IMX"}, /* 05 */
- {3, 1102, "stateHold2", 6, 1, 60, "1102-H~1.IMX"}, /* 06 */
- {3, 1103, "stateWaterline2", 6, 0, 60, "1103-W~1.IMX"}, /* 07 */
- {3, 1104, "stateCannon", 0, 0, 60, "1104-C~1.IMX"}, /* 08 */
- {3, 1105, "stateTreasure", 0, 0, 60, "1105-T~1.IMX"}, /* 09 */
- {3, 1200, "stateFortBase", 10, 1, 60, "1200-F~1.IMX"}, /* 10 */
- {3, 1201, "statePreFort", 10, 1, 60, "1201-P~1.IMX"}, /* 11 */
- {3, 1202, "statePreVooOut", 12, 0, 60, "1202-P~1.IMX"}, /* 12 */
- {3, 1203, "statePreVooIn", 12, 0, 60, "1203-P~1.IMX"}, /* 13 */
- {3, 1204, "statePreVooLady", 12, 0, 60, "1204-P~1.IMX"}, /* 14 */
- {3, 1205, "stateVoodooOut", 0, 0, 60, "1205-V~1.IMX"}, /* 15 */
- {3, 1210, "stateVoodooIn", 0, 0, 60, "1210-V~1.IMX"}, /* 16 */
- {12,1212, "stateVoodooInAlt", 0, 1, 42, "1210-V~1.IMX"}, /* 17 */
- {3, 1215, "stateVoodooLady", 0, 0, 60, "1215-V~1.IMX"}, /* 18 */
- {3, 1219, "statePrePlundermap", 0, 0, 60, "1219-P~1.IMX"}, /* 19 */
- {3, 1220, "statePlundermap", 0, 0, 60, "1220-P~1.IMX"}, /* 20 */
- {3, 1222, "statePreCabana", 0, 0, 60, "1222-P~1.IMX"}, /* 21 */
- {3, 1223, "stateCabana", 0, 0, 60, "1223-C~1.IMX"}, /* 22 */
- {3, 1224, "statePostCabana", 23, 0, 60, "1224-P~1.IMX"}, /* 23 */
- {3, 1225, "stateBeachClub", 23, 0, 60, "1225-B~1.IMX"}, /* 24 */
- {3, 1230, "stateCliff", 0, 0, 60, "1230-C~1.IMX"}, /* 25 */
- {3, 1232, "stateBelly", 0, 0, 48, "1232-B~1.IMX"}, /* 26 */
- {3, 1235, "stateQuicksand", 0, 0, 60, "1235-Q~1.IMX"}, /* 27 */
- {3, 1240, "stateDangerBeach", 0, 0, 48, "1240-D~1.IMX"}, /* 28 */
- {12,1241, "stateDangerBeachAlt",0, 2, 48, "1240-D~1.IMX"}, /* 29 */
- {3, 1245, "stateRowBoat", 0, 0, 60, "1245-R~1.IMX"}, /* 30 */
- {3, 1247, "stateAlongside", 0, 0, 48, "1247-A~1.IMX"}, /* 31 */
- {12,1248, "stateAlongsideAlt", 0, 1, 48, "1247-A~1.IMX"}, /* 32 */
- {3, 1250, "stateChimpBoat", 0, 0, 30, "1250-C~1.IMX"}, /* 33 */
- {3, 1255, "stateMrFossey", 0, 0, 48, "1255-M~1.IMX"}, /* 34 */
- {3, 1259, "statePreTown", 0, 0, 60, "1259-P~1.IMX"}, /* 35 */
- {3, 1260, "stateTown", 0, 0, 60, "1260-T~1.IMX"}, /* 36 */
- {3, 1264, "statePreMeadow", 0, 0, 60, "1264-P~1.IMX"}, /* 37 */
- {3, 1265, "stateMeadow", 0, 0, 60, "1265-M~1.IMX"}, /* 38 */
- {3, 1266, "stateMeadowAmb", 0, 0, 60, "1266-M~1.IMX"}, /* 39 */
- {3, 1270, "stateWardrobePre", 40, 0, 60, "1270-W~1.IMX"}, /* 40 */
- {3, 1272, "statePreShow", 40, 0, 60, "1272-P~1.IMX"}, /* 41 */
- {3, 1274, "stateWardrobeShow", 42, 0, 60, "1274-W~1.IMX"}, /* 42 */
- {3, 1276, "stateShow", 42, 0, 60, "1276-S~1.IMX"}, /* 43 */
- {3, 1277, "stateWardrobeJug", 44, 0, 60, "1277-W~1.IMX"}, /* 44 */
- {3, 1278, "stateJuggling", 44, 0, 60, "1278-J~1.IMX"}, /* 45 */
- {3, 1279, "statePostShow", 0, 0, 60, "1279-P~1.IMX"}, /* 46 */
- {3, 1280, "stateChickenShop", 0, 0, 60, "1280-C~1.IMX"}, /* 47 */
- {3, 1285, "stateBarberShop", 48, 0, 60, "1285-B~1.IMX"}, /* 48 */
- {3, 1286, "stateVanHelgen", 48, 0, 60, "1286-V~1.IMX"}, /* 49 */
- {3, 1287, "stateBill", 48, 0, 60, "1287-B~1.IMX"}, /* 50 */
- {3, 1288, "stateHaggis", 48, 0, 60, "1288-H~1.IMX"}, /* 51 */
- {3, 1289, "stateRottingham", 48, 0, 60, "1289-R~1.IMX"}, /* 52 */
- {3, 1305, "stateDeck", 0, 0, 60, "1305-D~1.IMX"}, /* 53 */
- {3, 1310, "stateCombatMap", 0, 0, 60, "1310-C~1.IMX"}, /* 54 */
- {3, 1320, "stateShipCombat", 0, 0, 60, "1320-S~1.IMX"}, /* 55 */
- {3, 1325, "stateSwordfight", 0, 0, 60, "1325-S~1.IMX"}, /* 56 */
- {3, 1327, "stateSwordRott", 0, 0, 60, "1327-S~1.IMX"}, /* 57 */
- {3, 1330, "stateTownEdge", 0, 0, 60, "1330-T~1.IMX"}, /* 58 */
- {3, 1335, "stateSwordLose", 0, 0, 60, "1335-S~1.IMX"}, /* 59 */
- {3, 1340, "stateSwordWin", 0, 0, 60, "1340-S~1.IMX"}, /* 60 */
- {3, 1345, "stateGetMap", 0, 0, 60, "1345-G~1.IMX"}, /* 61 */
- {3, 1400, "stateWreckBeach", 0, 0, 60, "1400-W~1.IMX"}, /* 62 */
- {3, 1405, "stateBloodMap", 63, 0, 60, "1405-B~1.IMX"}, /* 63 */
- {3, 1410, "stateClearing", 0, 0, 60, "1410-C~1.IMX"}, /* 64 */
- {3, 1415, "stateLighthouse", 63, 0, 60, "1415-L~1.IMX"}, /* 65 */
- {3, 1420, "stateVillage", 66, 0, 60, "1420-V~1.IMX"}, /* 66 */
- {3, 1423, "stateVolcano", 66, 0, 60, "1423-V~1.IMX"}, /* 67 */
- {3, 1425, "stateAltar", 66, 0, 60, "1425-A~1.IMX"}, /* 68 */
- {3, 1430, "stateHotelOut", 0, 0, 60, "1430-H~1.IMX"}, /* 69 */
- {3, 1435, "stateHotelBar", 70, 0, 60, "1435-H~1.IMX"}, /* 70 */
- {3, 1440, "stateHotelIn", 70, 0, 60, "1440-H~1.IMX"}, /* 71 */
- {3, 1445, "stateTarotLady", 70, 0, 60, "1445-T~1.IMX"}, /* 72 */
- {3, 1447, "stateGoodsoup", 70, 0, 60, "1447-G~1.IMX"}, /* 73 */
- {3, 1448, "stateGuestRoom", 0, 0, 60, "1448-G~1.IMX"}, /* 74 */
- {3, 1450, "stateWindmill", 63, 0, 60, "1450-W~1.IMX"}, /* 75 */
- {3, 1455, "stateCemetary", 0, 0, 60, "1455-C~1.IMX"}, /* 76 */
- {3, 1460, "stateCrypt", 77, 0, 60, "1460-C~1.IMX"}, /* 77 */
- {3, 1463, "stateGraveDigger", 77, 0, 60, "1463-G~1.IMX"}, /* 78 */
- {3, 1465, "stateMonkey1", 0, 0, 60, "1465-M~1.IMX"}, /* 79 */
- {3, 1475, "stateStanDark", 0, 0, 60, "1475-S~1.IMX"}, /* 80 */
- {3, 1477, "stateStanLight", 0, 0, 60, "1477-S~1.IMX"}, /* 81 */
- {3, 1480, "stateEggBeach", 63, 0, 60, "1480-E~1.IMX"}, /* 82 */
- {3, 1485, "stateSkullIsland", 0, 0, 60, "1485-S~1.IMX"}, /* 83 */
- {3, 1490, "stateSmugglersCave", 0, 0, 60, "1490-S~1.IMX"}, /* 84 */
- {3, 1500, "stateLeChuckTalk", 0, 0, 60, "1500-L~1.IMX"}, /* 85 */
- {3, 1505, "stateCarnival", 0, 0, 60, "1505-C~1.IMX"}, /* 86 */
- {3, 1511, "stateHang", 87, 0, 60, "1511-H~1.IMX"}, /* 87 */
- {3, 1512, "stateRum", 87, 0, 60, "1512-RUM.IMX"}, /* 88 */
- {3, 1513, "stateTorture", 87, 0, 60, "1513-T~1.IMX"}, /* 89 */
- {3, 1514, "stateSnow", 87, 0, 60, "1514-S~1.IMX"}, /* 90 */
- {3, 1515, "stateCredits", 0, 0, 60, "1515-C~1.IMX"}, /* 91 */
- {3, 1520, "stateCarnAmb", 0, 0, 60, "1520-C~1.IMX"}, /* 92 */
- {0, -1, "", 0, 0, 0, ""}
+ {0, 1000, "STATE_NULL", 0, 0, 0, "" , 0}, /* 00 */
+ {0, 1001, "stateNoChange", 0, 0, 0, "" , 0}, /* 01 */
+ {3, 1098, "stateCredits1", 0, 0, 60, "1098-C~1.IMX", 0}, /* 02 */
+ {3, 1099, "stateMenu", 0, 0, 60, "1099-M~1.IMX", 0}, /* 03 */
+ {3, 1100, "stateHold1", 4, 0, 60, "1100-H~1.IMX", 0}, /* 04 */
+ {3, 1101, "stateWaterline1", 4, 0, 60, "1101-W~1.IMX", 0}, /* 05 */
+ {3, 1102, "stateHold2", 6, 1, 60, "1102-H~1.IMX", 1}, /* 06 */
+ {3, 1103, "stateWaterline2", 6, 0, 60, "1103-W~1.IMX", 1}, /* 07 */
+ {3, 1104, "stateCannon", 0, 0, 60, "1104-C~1.IMX", 0}, /* 08 */
+ {3, 1105, "stateTreasure", 0, 0, 60, "1105-T~1.IMX", 0}, /* 09 */
+ {3, 1200, "stateFortBase", 10, 1, 60, "1200-F~1.IMX", 0}, /* 10 */
+ {3, 1201, "statePreFort", 10, 1, 60, "1201-P~1.IMX", 0}, /* 11 */
+ {3, 1202, "statePreVooOut", 12, 0, 60, "1202-P~1.IMX", 0}, /* 12 */
+ {3, 1203, "statePreVooIn", 12, 0, 60, "1203-P~1.IMX", 0}, /* 13 */
+ {3, 1204, "statePreVooLady", 12, 0, 60, "1204-P~1.IMX", 0}, /* 14 */
+ {3, 1205, "stateVoodooOut", 0, 0, 60, "1205-V~1.IMX", 0}, /* 15 */
+ {3, 1210, "stateVoodooIn", 0, 0, 60, "1210-V~1.IMX", 0}, /* 16 */
+ {12,1212, "stateVoodooInAlt", 0, 1, 42, "1210-V~1.IMX", 0}, /* 17 */
+ {3, 1215, "stateVoodooLady", 0, 0, 60, "1215-V~1.IMX", 0}, /* 18 */
+ {3, 1219, "statePrePlundermap", 0, 0, 60, "1219-P~1.IMX", 0}, /* 19 */
+ {3, 1220, "statePlundermap", 0, 0, 60, "1220-P~1.IMX", 0}, /* 20 */
+ {3, 1222, "statePreCabana", 0, 0, 60, "1222-P~1.IMX", 0}, /* 21 */
+ {3, 1223, "stateCabana", 0, 0, 60, "1223-C~1.IMX", 0}, /* 22 */
+ {3, 1224, "statePostCabana", 23, 0, 60, "1224-P~1.IMX", 0}, /* 23 */
+ {3, 1225, "stateBeachClub", 23, 0, 60, "1225-B~1.IMX", 0}, /* 24 */
+ {3, 1230, "stateCliff", 0, 0, 60, "1230-C~1.IMX", 0}, /* 25 */
+ {3, 1232, "stateBelly", 0, 0, 48, "1232-B~1.IMX", 0}, /* 26 */
+ {3, 1235, "stateQuicksand", 0, 0, 60, "1235-Q~1.IMX", 0}, /* 27 */
+ {3, 1240, "stateDangerBeach", 0, 0, 48, "1240-D~1.IMX", 0}, /* 28 */
+ {12,1241, "stateDangerBeachAlt",0, 2, 48, "1240-D~1.IMX", 0}, /* 29 */
+ {3, 1245, "stateRowBoat", 0, 0, 60, "1245-R~1.IMX", 0}, /* 30 */
+ {3, 1247, "stateAlongside", 0, 0, 48, "1247-A~1.IMX", 0}, /* 31 */
+ {12,1248, "stateAlongsideAlt", 0, 1, 48, "1247-A~1.IMX", 0}, /* 32 */
+ {3, 1250, "stateChimpBoat", 0, 0, 30, "1250-C~1.IMX", 1}, /* 33 */
+ {3, 1255, "stateMrFossey", 0, 0, 48, "1255-M~1.IMX", 0}, /* 34 */
+ {3, 1259, "statePreTown", 0, 0, 60, "1259-P~1.IMX", 0}, /* 35 */
+ {3, 1260, "stateTown", 0, 0, 60, "1260-T~1.IMX", 1}, /* 36 */
+ {3, 1264, "statePreMeadow", 0, 0, 60, "1264-P~1.IMX", 0}, /* 37 */
+ {3, 1265, "stateMeadow", 0, 0, 60, "1265-M~1.IMX", 0}, /* 38 */
+ {3, 1266, "stateMeadowAmb", 0, 0, 60, "1266-M~1.IMX", 0}, /* 39 */
+ {3, 1270, "stateWardrobePre", 40, 0, 60, "1270-W~1.IMX", 0}, /* 40 */
+ {3, 1272, "statePreShow", 40, 0, 60, "1272-P~1.IMX", 0}, /* 41 */
+ {3, 1274, "stateWardrobeShow", 42, 0, 60, "1274-W~1.IMX", 0}, /* 42 */
+ {3, 1276, "stateShow", 42, 0, 60, "1276-S~1.IMX", 0}, /* 43 */
+ {3, 1277, "stateWardrobeJug", 44, 0, 60, "1277-W~1.IMX", 0}, /* 44 */
+ {3, 1278, "stateJuggling", 44, 0, 60, "1278-J~1.IMX", 0}, /* 45 */
+ {3, 1279, "statePostShow", 0, 0, 60, "1279-P~1.IMX", 0}, /* 46 */
+ {3, 1280, "stateChickenShop", 0, 0, 60, "1280-C~1.IMX", 1}, /* 47 */
+ {3, 1285, "stateBarberShop", 48, 0, 60, "1285-B~1.IMX", 0}, /* 48 */
+ {3, 1286, "stateVanHelgen", 48, 0, 60, "1286-V~1.IMX", 0}, /* 49 */
+ {3, 1287, "stateBill", 48, 0, 60, "1287-B~1.IMX", 0}, /* 50 */
+ {3, 1288, "stateHaggis", 48, 0, 60, "1288-H~1.IMX", 0}, /* 51 */
+ {3, 1289, "stateRottingham", 48, 0, 60, "1289-R~1.IMX", 0}, /* 52 */
+ {3, 1305, "stateDeck", 0, 0, 60, "1305-D~1.IMX", 0}, /* 53 */
+ {3, 1310, "stateCombatMap", 0, 0, 60, "1310-C~1.IMX", 0}, /* 54 */
+ {3, 1320, "stateShipCombat", 0, 0, 60, "1320-S~1.IMX", 1}, /* 55 */
+ {3, 1325, "stateSwordfight", 0, 0, 60, "1325-S~1.IMX", 1}, /* 56 */
+ {3, 1327, "stateSwordRott", 0, 0, 60, "1327-S~1.IMX", 0}, /* 57 */
+ {3, 1330, "stateTownEdge", 0, 0, 60, "1330-T~1.IMX", 1}, /* 58 */
+ {3, 1335, "stateSwordLose", 0, 0, 60, "1335-S~1.IMX", 0}, /* 59 */
+ {3, 1340, "stateSwordWin", 0, 0, 60, "1340-S~1.IMX", 0}, /* 60 */
+ {3, 1345, "stateGetMap", 0, 0, 60, "1345-G~1.IMX", 0}, /* 61 */
+ {3, 1400, "stateWreckBeach", 0, 0, 60, "1400-W~1.IMX", 0}, /* 62 */
+ {3, 1405, "stateBloodMap", 63, 0, 60, "1405-B~1.IMX", 0}, /* 63 */
+ {3, 1410, "stateClearing", 0, 0, 60, "1410-C~1.IMX", 0}, /* 64 */
+ {3, 1415, "stateLighthouse", 63, 0, 60, "1415-L~1.IMX", 0}, /* 65 */
+ {3, 1420, "stateVillage", 66, 0, 60, "1420-V~1.IMX", 0}, /* 66 */
+ {3, 1423, "stateVolcano", 66, 0, 60, "1423-V~1.IMX", 0}, /* 67 */
+ {3, 1425, "stateAltar", 66, 0, 60, "1425-A~1.IMX", 0}, /* 68 */
+ {3, 1430, "stateHotelOut", 0, 0, 60, "1430-H~1.IMX", 0}, /* 69 */
+ {3, 1435, "stateHotelBar", 70, 0, 60, "1435-H~1.IMX", 0}, /* 70 */
+ {3, 1440, "stateHotelIn", 70, 0, 60, "1440-H~1.IMX", 0}, /* 71 */
+ {3, 1445, "stateTarotLady", 70, 0, 60, "1445-T~1.IMX", 0}, /* 72 */
+ {3, 1447, "stateGoodsoup", 70, 0, 60, "1447-G~1.IMX", 0}, /* 73 */
+ {3, 1448, "stateGuestRoom", 0, 0, 60, "1448-G~1.IMX", 0}, /* 74 */
+ {3, 1450, "stateWindmill", 63, 0, 60, "1450-W~1.IMX", 0}, /* 75 */
+ {3, 1455, "stateCemetary", 0, 0, 60, "1455-C~1.IMX", 0}, /* 76 */
+ {3, 1460, "stateCrypt", 77, 0, 60, "1460-C~1.IMX", 0}, /* 77 */
+ {3, 1463, "stateGraveDigger", 77, 0, 60, "1463-G~1.IMX", 0}, /* 78 */
+ {3, 1465, "stateMonkey1", 0, 0, 60, "1465-M~1.IMX", 0}, /* 79 */
+ {3, 1475, "stateStanDark", 0, 0, 60, "1475-S~1.IMX", 0}, /* 80 */
+ {3, 1477, "stateStanLight", 0, 0, 60, "1477-S~1.IMX", 1}, /* 81 */
+ {3, 1480, "stateEggBeach", 63, 0, 60, "1480-E~1.IMX", 0}, /* 82 */
+ {3, 1485, "stateSkullIsland", 0, 0, 60, "1485-S~1.IMX", 0}, /* 83 */
+ {3, 1490, "stateSmugglersCave", 0, 0, 60, "1490-S~1.IMX", 0}, /* 84 */
+ {3, 1500, "stateLeChuckTalk", 0, 0, 60, "1500-L~1.IMX", 0}, /* 85 */
+ {3, 1505, "stateCarnival", 0, 0, 60, "1505-C~1.IMX", 0}, /* 86 */
+ {3, 1511, "stateHang", 87, 0, 60, "1511-H~1.IMX", 0}, /* 87 */
+ {3, 1512, "stateRum", 87, 0, 60, "1512-RUM.IMX", 0}, /* 88 */
+ {3, 1513, "stateTorture", 87, 0, 60, "1513-T~1.IMX", 0}, /* 89 */
+ {3, 1514, "stateSnow", 87, 0, 60, "1514-S~1.IMX", 0}, /* 90 */
+ {3, 1515, "stateCredits", 0, 0, 60, "1515-C~1.IMX", 0}, /* 91 */
+ {3, 1520, "stateCarnAmb", 0, 0, 60, "1520-C~1.IMX", 0}, /* 92 */
+ {0, -1, "", 0, 0, 0, "", 0}
};
const imuseComiTable _comiSeqMusicTable[] = {
- {0, 2000, "SEQ_NULL", 0, 0, 0, ""},
- {0, 2100, "seqINTRO", 0, 0, 0, ""},
- {3, 2105, "seqInterlude1", 0, 0, 60, "2105-I~1.IMX"},
- {8, 2110, "seqLastBoat", 0, 1, 0, ""},
- {0, 2115, "seqSINK_SHIP", 0, 0, 0, ""},
- {0, 2120, "seqCURSED_RING", 0, 0, 60, ""},
- {3, 2200, "seqInterlude2", 0, 0, 60, "2200-I~1.IMX"},
- {3, 2210, "seqKidnapped", 0, 0, 60, "2210-K~1.IMX"},
- {8, 2220, "seqSnakeVomits", 0, 1, 0, ""},
- {8, 2222, "seqPopBalloon", 0, 1, 0, ""},
- {3, 2225, "seqDropBalls", 0, 0, 60, "2225-D~1.IMX"},
- {4, 2232, "seqArriveBarber", 0, 0, 60, "2232-A~1.IMX"},
- {3, 2233, "seqAtonal", 0, 0, 60, "2233-A~1.IMX"},
- {3, 2235, "seqShaveHead1", 0, 0, 60, "2235-S~1.IMX"},
- {2, 2236, "seqShaveHead2", 0, 2, 60, "2235-S~1.IMX"},
- {3, 2245, "seqCaberLose", 0, 0, 60, "2245-C~1.IMX"},
- {3, 2250, "seqCaberWin", 0, 0, 60, "2250-C~1.IMX"},
- {3, 2255, "seqDuel1", 0, 0, 60, "2255-D~1.IMX"},
- {2, 2256, "seqDuel2", 0, 2, 60, "2255-D~1.IMX"},
- {2, 2257, "seqDuel3", 0, 3, 60, "2255-D~1.IMX"},
- {3, 2260, "seqBlowUpTree1", 0, 0, 60, "2260-B~1.IMX"},
- {2, 2261, "seqBlowUpTree2", 0, 2, 60, "2260-B~1.IMX"},
- {3, 2275, "seqMonkeys", 0, 0, 60, "2275-M~1.IMX"},
- {9, 2277, "seqAttack", 0, 1, 0, ""},
- {3, 2285, "seqSharks", 0, 0, 60, "2285-S~1.IMX"},
- {3, 2287, "seqTowelWalk", 0, 0, 60, "2287-T~1.IMX"},
- {0, 2293, "seqNICE_BOOTS", 0, 0, 0, ""},
- {0, 2295, "seqBIG_BONED", 0, 0, 0, ""},
- {3, 2300, "seqToBlood", 0, 0, 60, "2300-T~1.IMX"},
- {3, 2301, "seqInterlude3", 0, 0, 60, "2301-I~1.IMX"},
- {3, 2302, "seqRott1", 0, 0, 60, "2302-R~1.IMX"},
- {2, 2304, "seqRott2", 0, 2, 60, "2302-R~1.IMX"},
- {2, 2305, "seqRott2b", 0,21, 60, "2302-R~1.IMX"},
- {2, 2306, "seqRott3", 0, 3, 60, "2302-R~1.IMX"},
- {2, 2308, "seqRott4", 0, 4, 60, "2302-R~1.IMX"},
- {2, 2309, "seqRott5", 0, 5, 60, "2302-R~1.IMX"},
- {3, 2311, "seqVerse1", 0, 0, 60, "2311-S~1.IMX"},
- {2, 2312, "seqVerse2", 0, 2, 60, "2311-S~1.IMX"},
- {2, 2313, "seqVerse3", 0, 3, 60, "2311-S~1.IMX"},
- {2, 2314, "seqVerse4", 0, 4, 60, "2311-S~1.IMX"},
- {2, 2315, "seqVerse5", 0, 5, 60, "2311-S~1.IMX"},
- {2, 2316, "seqVerse6", 0, 6, 60, "2311-S~1.IMX"},
- {2, 2317, "seqVerse7", 0, 7, 60, "2311-S~1.IMX"},
- {2, 2318, "seqVerse8", 0, 8, 60, "2311-S~1.IMX"},
- {2, 2319, "seqSongEnd", 0, 9, 60, "2311-S~1.IMX"},
- {2, 2336, "seqRiposteLose", 0, 0, 60, "2336-R~1.IMX"},
- {2, 2337, "seqRiposteWin", 0, 0, 60, "2337-R~1.IMX"},
- {2, 2338, "seqInsultLose", 0, 0, 60, "2338-I~1.IMX"},
- {2, 2339, "seqInsultWin", 0, 0, 60, "2339-I~1.IMX"},
- {3, 2340, "seqSwordLose", 0, 0, 60, "1335-S~1.IMX"},
- {3, 2345, "seqSwordWin", 0, 0, 60, "1340-S~1.IMX"},
- {3, 2347, "seqGetMap", 0, 0, 60, "1345-G~1.IMX"},
- {3, 2400, "seqInterlude4", 0, 0, 60, "2400-I~1.IMX"},
- {0, 2405, "seqSHIPWRECK", 0, 0, 0, ""},
- {3, 2408, "seqFakeCredits", 0, 0, 60, "2408-F~1.IMX"},
- {3, 2410, "seqPassOut", 0, 0, 60, "2410-P~1.IMX"},
- {3, 2414, "seqGhostTalk", 0, 0, 60, "2414-G~1.IMX"},
- {2, 2415, "seqGhostWedding", 0, 1, 60, "2414-G~1.IMX"},
- {3, 2420, "seqEruption", 0, 0, 60, "2420-E~1.IMX"},
- {3, 2425, "seqSacrifice", 0, 0, 60, "2425-S~1.IMX"},
- {2, 2426, "seqSacrificeEnd", 0, 1, 60, "2425-S~1.IMX"},
- {3, 2430, "seqScareDigger", 0, 0, 60, "2430-S~1.IMX"},
- {3, 2445, "seqSkullArrive", 0, 0, 60, "2445-S~1.IMX"},
- {3, 2450, "seqFloat", 0, 0, 60, "2450-C~1.IMX"},
- {2, 2451, "seqFall", 0, 1, 60, "2450-C~1.IMX"},
- {2, 2452, "seqUmbrella", 0, 2, 60, "2450-C~1.IMX"},
- {3, 2460, "seqFight", 0, 0, 60, "2460-F~1.IMX"},
- {0, 2465, "seqLAVE_RIDE", 0, 0, 0, ""},
- {0, 2470, "seqMORE_SLAW", 0, 0, 0, ""},
- {0, 2475, "seqLIFT_CURSE", 0, 0, 0, ""},
- {3, 2500, "seqInterlude5", 0, 0, 60, "2500-I~1.IMX"},
- {3, 2502, "seqExitSkycar", 0, 0, 60, "2502-E~1.IMX"},
- {3, 2504, "seqGrow1", 0, 0, 60, "2504-G~1.IMX"},
- {2, 2505, "seqGrow2", 0, 1, 60, "2504-G~1.IMX"},
- {3, 2508, "seqInterlude6", 0, 0, 60, "2508-I~1.IMX"},
- {0, 2515, "seqFINALE", 0, 0, 0, ""},
- {3, 2520, "seqOut", 0, 0, 60, "2520-OUT.IMX"},
- {3, 2530, "seqZap1a", 0, 0, 60, "2530-Z~1.IMX"},
- {2, 2531, "seqZap1b", 0, 1, 60, "2530-Z~1.IMX"},
- {2, 2532, "seqZap1c", 0, 2, 60, "2530-Z~1.IMX"},
- {2, 2540, "seqZap2a", 0, 0, 60, "2540-Z~1.IMX"},
- {2, 2541, "seqZap2b", 0, 1, 60, "2540-Z~1.IMX"},
- {2, 2542, "seqZap2c", 0, 2, 60, "2540-Z~1.IMX"},
- {3, 2550, "seqZap3a", 0, 0, 60, "2550-Z~1.IMX"},
- {2, 2551, "seqZap3b", 0, 1, 60, "2550-Z~1.IMX"},
- {2, 2552, "seqZap3c", 0, 2, 60, "2550-Z~1.IMX"},
- {3, 2560, "seqZap4a", 0, 0, 60, "2560-Z~1.IMX"},
- {2, 2561, "seqZap4b", 0, 1, 60, "2560-Z~1.IMX"},
- {2, 2562, "seqZap4c", 0, 2, 60, "2560-Z~1.IMX"},
- {0, -1, "", 0, 0, 0, ""}
+ {0, 2000, "SEQ_NULL", 0, 0, 0, "" , 0},
+ {0, 2100, "seqINTRO", 0, 0, 0, "" , 0},
+ {3, 2105, "seqInterlude1", 0, 0, 60, "2105-I~1.IMX", 0},
+ {8, 2110, "seqLastBoat", 0, 1, 0, "" , 0},
+ {0, 2115, "seqSINK_SHIP", 0, 0, 0, "" , 0},
+ {0, 2120, "seqCURSED_RING", 0, 0, 60, "" , 0},
+ {3, 2200, "seqInterlude2", 0, 0, 60, "2200-I~1.IMX", 0},
+ {3, 2210, "seqKidnapped", 0, 0, 60, "2210-K~1.IMX", 0},
+ {8, 2220, "seqSnakeVomits", 0, 1, 0, "" , 0},
+ {8, 2222, "seqPopBalloon", 0, 1, 0, "" , 0},
+ {3, 2225, "seqDropBalls", 0, 0, 60, "2225-D~1.IMX", 0},
+ {4, 2232, "seqArriveBarber", 0, 0, 60, "2232-A~1.IMX", 0},
+ {3, 2233, "seqAtonal", 0, 0, 60, "2233-A~1.IMX", 0},
+ {3, 2235, "seqShaveHead1", 0, 0, 60, "2235-S~1.IMX", 0},
+ {2, 2236, "seqShaveHead2", 0, 2, 60, "2235-S~1.IMX", 0},
+ {3, 2245, "seqCaberLose", 0, 0, 60, "2245-C~1.IMX", 0},
+ {3, 2250, "seqCaberWin", 0, 0, 60, "2250-C~1.IMX", 0},
+ {3, 2255, "seqDuel1", 0, 0, 60, "2255-D~1.IMX", 0},
+ {2, 2256, "seqDuel2", 0, 2, 60, "2255-D~1.IMX", 0},
+ {2, 2257, "seqDuel3", 0, 3, 60, "2255-D~1.IMX", 0},
+ {3, 2260, "seqBlowUpTree1", 0, 0, 60, "2260-B~1.IMX", 0},
+ {2, 2261, "seqBlowUpTree2", 0, 2, 60, "2260-B~1.IMX", 0},
+ {3, 2275, "seqMonkeys", 0, 0, 60, "2275-M~1.IMX", 0},
+ {9, 2277, "seqAttack", 0, 1, 0, "" , 0},
+ {3, 2285, "seqSharks", 0, 0, 60, "2285-S~1.IMX", 0},
+ {3, 2287, "seqTowelWalk", 0, 0, 60, "2287-T~1.IMX", 0},
+ {0, 2293, "seqNICE_BOOTS", 0, 0, 0, "" , 0},
+ {0, 2295, "seqBIG_BONED", 0, 0, 0, "" , 0},
+ {3, 2300, "seqToBlood", 0, 0, 60, "2300-T~1.IMX", 0},
+ {3, 2301, "seqInterlude3", 0, 0, 60, "2301-I~1.IMX", 0},
+ {3, 2302, "seqRott1", 0, 0, 60, "2302-R~1.IMX", 0},
+ {2, 2304, "seqRott2", 0, 2, 60, "2302-R~1.IMX", 0},
+ {2, 2305, "seqRott2b", 0,21, 60, "2302-R~1.IMX", 0},
+ {2, 2306, "seqRott3", 0, 3, 60, "2302-R~1.IMX", 0},
+ {2, 2308, "seqRott4", 0, 4, 60, "2302-R~1.IMX", 0},
+ {2, 2309, "seqRott5", 0, 5, 60, "2302-R~1.IMX", 0},
+ {3, 2311, "seqVerse1", 0, 0, 60, "2311-S~1.IMX", 3},
+ {2, 2312, "seqVerse2", 0, 2, 60, "2311-S~1.IMX", 2},
+ {2, 2313, "seqVerse3", 0, 3, 60, "2311-S~1.IMX", 2},
+ {2, 2314, "seqVerse4", 0, 4, 60, "2311-S~1.IMX", 4},
+ {2, 2315, "seqVerse5", 0, 5, 60, "2311-S~1.IMX", 2},
+ {2, 2316, "seqVerse6", 0, 6, 60, "2311-S~1.IMX", 2},
+ {2, 2317, "seqVerse7", 0, 7, 60, "2311-S~1.IMX", 3},
+ {2, 2318, "seqVerse8", 0, 8, 60, "2311-S~1.IMX", 2},
+ {2, 2319, "seqSongEnd", 0, 9, 60, "2311-S~1.IMX", 2},
+ {2, 2336, "seqRiposteLose", 0, 0, 60, "2336-R~1.IMX", 0},
+ {2, 2337, "seqRiposteWin", 0, 0, 60, "2337-R~1.IMX", 0},
+ {2, 2338, "seqInsultLose", 0, 0, 60, "2338-I~1.IMX", 1},
+ {2, 2339, "seqInsultWin", 0, 0, 60, "2339-I~1.IMX", 1},
+ {3, 2340, "seqSwordLose", 0, 0, 60, "1335-S~1.IMX", 0},
+ {3, 2345, "seqSwordWin", 0, 0, 60, "1340-S~1.IMX", 0},
+ {3, 2347, "seqGetMap", 0, 0, 60, "1345-G~1.IMX", 0},
+ {3, 2400, "seqInterlude4", 0, 0, 60, "2400-I~1.IMX", 0},
+ {0, 2405, "seqSHIPWRECK", 0, 0, 0, "" , 0},
+ {3, 2408, "seqFakeCredits", 0, 0, 60, "2408-F~1.IMX", 0},
+ {3, 2410, "seqPassOut", 0, 0, 60, "2410-P~1.IMX", 0},
+ {3, 2414, "seqGhostTalk", 0, 0, 60, "2414-G~1.IMX", 0},
+ {2, 2415, "seqGhostWedding", 0, 1, 60, "2414-G~1.IMX", 0},
+ {3, 2420, "seqEruption", 0, 0, 60, "2420-E~1.IMX", 0},
+ {3, 2425, "seqSacrifice", 0, 0, 60, "2425-S~1.IMX", 0},
+ {2, 2426, "seqSacrificeEnd", 0, 1, 60, "2425-S~1.IMX", 0},
+ {3, 2430, "seqScareDigger", 0, 0, 60, "2430-S~1.IMX", 0},
+ {3, 2445, "seqSkullArrive", 0, 0, 60, "2445-S~1.IMX", 0},
+ {3, 2450, "seqFloat", 0, 0, 60, "2450-C~1.IMX", 1},
+ {2, 2451, "seqFall", 0, 1, 60, "2450-C~1.IMX", 0},
+ {2, 2452, "seqUmbrella", 0, 2, 60, "2450-C~1.IMX", 0},
+ {3, 2460, "seqFight", 0, 0, 60, "2460-F~1.IMX", 0},
+ {0, 2465, "seqLAVE_RIDE", 0, 0, 0, "" , 0},
+ {0, 2470, "seqMORE_SLAW", 0, 0, 0, "" , 0},
+ {0, 2475, "seqLIFT_CURSE", 0, 0, 0, "" , 0},
+ {3, 2500, "seqInterlude5", 0, 0, 60, "2500-I~1.IMX", 0},
+ {3, 2502, "seqExitSkycar", 0, 0, 60, "2502-E~1.IMX", 0},
+ {3, 2504, "seqGrow1", 0, 0, 60, "2504-G~1.IMX", 0},
+ {2, 2505, "seqGrow2", 0, 1, 60, "2504-G~1.IMX", 0},
+ {3, 2508, "seqInterlude6", 0, 0, 60, "2508-I~1.IMX", 0},
+ {0, 2515, "seqFINALE", 0, 0, 0, "" , 0},
+ {3, 2520, "seqOut", 0, 0, 60, "2520-OUT.IMX", 0},
+ {3, 2530, "seqZap1a", 0, 0, 60, "2530-Z~1.IMX", 0},
+ {2, 2531, "seqZap1b", 0, 1, 60, "2530-Z~1.IMX", 0},
+ {2, 2532, "seqZap1c", 0, 2, 60, "2530-Z~1.IMX", 0},
+ {2, 2540, "seqZap2a", 0, 0, 60, "2540-Z~1.IMX", 0},
+ {2, 2541, "seqZap2b", 0, 1, 60, "2540-Z~1.IMX", 0},
+ {2, 2542, "seqZap2c", 0, 2, 60, "2540-Z~1.IMX", 0},
+ {3, 2550, "seqZap3a", 0, 0, 60, "2550-Z~1.IMX", 0},
+ {2, 2551, "seqZap3b", 0, 1, 60, "2550-Z~1.IMX", 0},
+ {2, 2552, "seqZap3c", 0, 2, 60, "2550-Z~1.IMX", 0},
+ {3, 2560, "seqZap4a", 0, 0, 60, "2560-Z~1.IMX", 0},
+ {2, 2561, "seqZap4b", 0, 1, 60, "2560-Z~1.IMX", 0},
+ {2, 2562, "seqZap4c", 0, 2, 60, "2560-Z~1.IMX", 0},
+ {0, -1, "", 0, 0, 0, "" , 0}
};
const imuseComiTable _comiDemoStateMusicTable[] = {
- { 0, 1000, "STATE_NULL", 0, 0, 0, "" }, /* 00 */
- { 0, 1001, "stateNoChange", 0, 0, 0, "" }, /* 01 */
- { 3, 1100, "stateHold1", 2, 0, 60, "in1.imx" }, /* 02 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 03 */
- { 3, 1120, "stateHold2", 4, 0, 60, "in2.imx" }, /* 04 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 05 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 06 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 07 */
- { 3, 1140, "stateWaterline1", 2, 0, 60, "out1.imx" }, /* 08 */
- { 3, 1150, "stateWaterline2", 4, 0, 60, "out2.imx" }, /* 09 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 10 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 11 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 12 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 13 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 14 */
- { 0, 1001, "empty", 0, 0, 0, "" }, /* 15 */
- { 3, 1210, "stateCannon", 4, 0, 60, "gun.imx" }, /* 16 */
- { 0, -1, "", 0, 0, 0, "" }
+ {0, 1000, "STATE_NULL", 0, 0, 0, "", 0}, /* 00 */
+ {0, 1001, "stateNoChange", 0, 0, 0, "", 0}, /* 01 */
+ {3, 1100, "stateHold1", 2, 0, 60, "in1.imx", 0}, /* 02 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 03 */
+ {3, 1120, "stateHold2", 4, 0, 60, "in2.imx", 0}, /* 04 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 05 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 06 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 07 */
+ {3, 1140, "stateWaterline1", 2, 0, 60, "out1.imx", 0}, /* 08 */
+ {3, 1150, "stateWaterline2", 4, 0, 60, "out2.imx", 0}, /* 09 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 10 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 11 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 12 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 13 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 14 */
+ {0, 1001, "empty", 0, 0, 0, "", 0}, /* 15 */
+ {3, 1210, "stateCannon", 4, 0, 60, "gun.imx", 0}, /* 16 */
+ {0, -1, "", 0, 0, 0, "", 0}
};
const imuseFtStateTable _ftStateMusicTable[] = {
diff --git a/engines/scumm/imuse_digi/dimuse_tables.h b/engines/scumm/imuse_digi/dimuse_tables.h
index 1c981d8124..404030adf1 100644
--- a/engines/scumm/imuse_digi/dimuse_tables.h
+++ b/engines/scumm/imuse_digi/dimuse_tables.h
@@ -53,6 +53,7 @@ struct imuseComiTable {
byte hookId;
int16 fadeOutDelay;
char filename[13];
+ int shiftLoop;
};
diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp
index ebd2fa2a9e..f81adc2caa 100644
--- a/engines/scumm/imuse_digi/dimuse_track.cpp
+++ b/engines/scumm/imuse_digi/dimuse_track.cpp
@@ -29,6 +29,7 @@
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse_digi/dimuse_bndmgr.h"
#include "scumm/imuse_digi/dimuse_track.h"
+#include "scumm/imuse_digi/dimuse_tables.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
@@ -79,14 +80,14 @@ int IMuseDigital::allocSlot(int priority) {
return trackId;
}
-void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, int volGroupId, Audio::AudioStream *input, int hookId, int volume, int priority, Track *otherTrack) {
+int IMuseDigital::startSound(int soundId, const char *soundName, int soundType, int volGroupId, Audio::AudioStream *input, int hookId, int volume, int priority, Track *otherTrack) {
Common::StackLock lock(_mutex, "IMuseDigital::startSound()");
debug(5, "IMuseDigital::startSound(%d) - begin func", soundId);
int l = allocSlot(priority);
if (l == -1) {
warning("IMuseDigital::startSound() Can't start sound - no free slots");
- return;
+ return -1;
}
debug(5, "IMuseDigital::startSound(%d, trackId:%d)", soundId, l);
@@ -105,6 +106,24 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
track->soundType = soundType;
track->trackId = l;
+ if (_vm->_game.id == GID_CMI) {
+ if (track->soundId / 1000 == 1) { // State
+ for (l = 0; _comiStateMusicTable[l].soundId != -1; l++) {
+ if ((_comiStateMusicTable[l].soundId == track->soundId)) {
+ track->loopShiftType = _comiStateMusicTable[l].shiftLoop;
+ break;
+ }
+ }
+ } else if (track->soundId / 1000 == 2) { // Sequence
+ for (l = 0; _comiSeqMusicTable[l].soundId != -1; l++) {
+ if ((_comiSeqMusicTable[l].soundId == track->soundId)) {
+ track->loopShiftType = _comiSeqMusicTable[l].shiftLoop;
+ break;
+ }
+ }
+ }
+ }
+
int bits = 0, freq = 0, channels = 0;
track->souStreamUsed = (input != 0);
@@ -120,7 +139,7 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
track->soundDesc = _sound->openSound(soundId, soundName, soundType, volGroupId, 2);
if (!track->soundDesc)
- return;
+ return -1;
track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc);
@@ -193,6 +212,8 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
}
track->used = true;
+
+ return track->trackId;
}
void IMuseDigital::setPriority(int soundId, int priority) {
@@ -213,6 +234,9 @@ void IMuseDigital::setVolume(int soundId, int volume) {
Common::StackLock lock(_mutex, "IMuseDigital::setVolume()");
debug(5, "IMuseDigital::setVolume(%d, %d)", soundId, volume);
+ if (_vm->_game.id == GID_CMI && volume > 127)
+ volume = volume / 2;
+
for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
Track *track = _track[l];
if (track->used && !track->toBeRemoved && (track->soundId == soundId)) {
diff --git a/engines/scumm/imuse_digi/dimuse_track.h b/engines/scumm/imuse_digi/dimuse_track.h
index 9cad1c1fc6..5b8f10af17 100644
--- a/engines/scumm/imuse_digi/dimuse_track.h
+++ b/engines/scumm/imuse_digi/dimuse_track.h
@@ -45,35 +45,36 @@ enum {
};
struct Track {
- int trackId; // used to identify track by value (0-15)
-
- int8 pan; // panning value of sound
- int32 vol; // volume level (values 0-127 * 1000)
- int32 volFadeDest; // volume level which fading target (values 0-127 * 1000)
- int32 volFadeStep; // delta of step while changing volume at each imuse callback
- int32 volFadeDelay; // time in ms how long fading volume must be
- bool volFadeUsed; // flag if fading is in progress
- int32 gainReduction; // amount of volume to subtract
- int32 gainRedFadeDest; // target of fade for gain reduction
- bool gainRedFadeUsed; // flag if fading is in progress
- int32 soundId; // sound id used by scumm script
- char soundName[15]; // sound name but also filename of sound in bundle data
- bool used; // flag mean that track is used
- bool toBeRemoved; // flag mean that track need to be free
- bool souStreamUsed; // flag mean that track use stream from sou file
- bool sndDataExtComp; // flag mean that sound data is compressed by scummvm tools
- int32 soundPriority; // priority level of played sound (0-127)
- int32 regionOffset; // offset to sound data relative to begining of current region
- int32 dataOffset; // offset to sound data relative to begining of 'DATA' chunk
- int32 curRegion; // id of current used region
- int32 curHookId; // id of current used hook id
- int32 volGroupId; // id of volume group (IMUSE_VOLGRP_VOICE, IMUSE_VOLGRP_SFX, IMUSE_VOLGRP_MUSIC)
- int32 soundType; // type of sound data (IMUSE_BUNDLE, IMUSE_RESOURCE)
- int32 feedSize; // size of sound data needed to be filled at each callback iteration
- int32 dataMod12Bit; // value used between all callback to align 12 bit source of data
- int32 mixerFlags; // flags for sound mixer's channel (kFlagStereo, kFlag16Bits, kFlagUnsigned)
- bool littleEndian; // Endianness: default is big for original files and native for recompressed ones
-
+ int trackId; // used to identify track by value (0-15)
+
+ int8 pan; // panning value of sound
+ int32 vol; // volume level (values 0-127 * 1000)
+ int32 volFadeDest; // volume level which fading target (values 0-127 * 1000)
+ int32 volFadeStep; // delta of step while changing volume at each imuse callback
+ int32 volFadeDelay; // time in ms how long fading volume must be
+ bool volFadeUsed; // flag if fading is in progress
+ int32 gainReduction; // amount of volume to subtract
+ int32 gainRedFadeDest; // target of fade for gain reduction
+ bool gainRedFadeUsed; // flag if fading is in progress
+ bool alreadyCrossfading; // used by COMI to check if this track is already running a crossfade
+ int loopShiftType; // currently used by COMI to check if the loop point for this track has to be shifted
+ int32 soundId; // sound id used by scumm script
+ char soundName[15]; // sound name but also filename of sound in bundle data
+ bool used; // flag mean that track is used
+ bool toBeRemoved; // flag mean that track need to be free
+ bool souStreamUsed; // flag mean that track use stream from sou file
+ bool sndDataExtComp; // flag mean that sound data is compressed by scummvm tools
+ int32 soundPriority; // priority level of played sound (0-127)
+ int32 regionOffset; // offset to sound data relative to begining of current region
+ int32 dataOffset; // offset to sound data relative to begining of 'DATA' chunk
+ int32 curRegion; // id of current used region
+ int32 curHookId; // id of current used hook id
+ int32 volGroupId; // id of volume group (IMUSE_VOLGRP_VOICE, IMUSE_VOLGRP_SFX, IMUSE_VOLGRP_MUSIC)
+ int32 soundType; // type of sound data (IMUSE_BUNDLE, IMUSE_RESOURCE)
+ int32 feedSize; // size of sound data needed to be filled at each callback iteration
+ int32 dataMod12Bit; // value used between all callback to align 12 bit source of data
+ int32 mixerFlags; // flags for sound mixer's channel (kFlagStereo, kFlag16Bits, kFlagUnsigned)
+ bool littleEndian; // Endianness: default is big for original files and native for recompressed ones
ImuseDigiSndMgr::SoundDesc *soundDesc; // sound handle used by iMuse sound manager
Audio::SoundHandle mixChanHandle; // sound mixer's channel handle
Audio::QueuingAudioStream *stream; // sound mixer's audio stream handle for *.la1 and *.bun
@@ -93,6 +94,8 @@ struct Track {
gainReduction = 0;
gainRedFadeDest = 127 * 290; // About 4 dB of gain reduction
gainRedFadeUsed = false;
+ alreadyCrossfading = false;
+ loopShiftType = 0;
soundId = 0;
memset(soundName, 0, sizeof(soundName));
used = false;
More information about the Scummvm-git-logs
mailing list