aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/ksound.cpp103
-rw-r--r--engines/sci/engine/state.cpp3
-rw-r--r--engines/sci/engine/state.h5
3 files changed, 110 insertions, 1 deletions
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 01f20d2f4e..95facc75b0 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -31,6 +31,7 @@
#include "sci/engine/kernel.h"
#include "sci/engine/vm.h" // for Object
+#include "sound/audiocd.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
@@ -112,7 +113,8 @@ enum AudioCommands {
kSciAudioPosition = 6, /* Return current position in audio stream */
kSciAudioRate = 7, /* Return audio rate */
kSciAudioVolume = 8, /* Return audio volume */
- kSciAudioLanguage = 9 /* Return audio language */
+ kSciAudioLanguage = 9, /* Return audio language */
+ kSciAudioCD = 10 /* Plays SCI1.1 CD audio */
};
enum AudioSyncCommands {
@@ -1023,10 +1025,107 @@ reg_t kDoSound(EngineState *s, int argc, reg_t *argv) {
}
}
+reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) {
+ switch (argv[0].toUint16()) {
+ case kSciAudioWPlay:
+ case kSciAudioPlay: {
+ if (getSciVersion() == SCI_VERSION_1_1) {
+ // King's Quest VI CD Audio format
+ if (argc < 2)
+ return NULL_REG;
+
+ uint16 track = argv[1].toUint16() - 1;
+ uint32 startFrame = 0;
+ uint32 totalFrames = 0;
+
+ if (argc > 2)
+ startFrame = argv[2].toUint16() * 75;
+
+ if (argc > 3)
+ totalFrames = argv[3].toUint16() * 75;
+
+ AudioCD.play(track, 1, startFrame, totalFrames);
+ return make_reg(0, 1);
+ } else {
+ // Jones in the Fast Lane CD Audio format
+ if (argc != 2)
+ error("kDoCdAudio(%d) called with %d args", argv[0].toUint16(), argc);
+
+ AudioCD.stop();
+
+ Common::File audioMap;
+ if(!audioMap.open("cdaudio.map"))
+ error("Could not open cdaudio.map");
+
+ uint16 sample = argv[1].toUint16();
+ uint32 length = 0;
+
+ while (audioMap.pos() < audioMap.size()) {
+ uint16 res = audioMap.readUint16LE();
+ uint32 startFrame = audioMap.readUint16LE();
+ startFrame += audioMap.readByte() << 16;
+ audioMap.readByte(); // Unknown, always 0x20
+ length = audioMap.readUint16LE();
+ length += audioMap.readByte() << 16;
+ audioMap.readByte(); // Unknown, always 0x00
+
+ if (res == sample) {
+ AudioCD.play(1, 1, startFrame, length);
+ s->_audioCdStart = g_system->getMillis();
+ break;
+ }
+ }
+
+ audioMap.close();
+
+ return make_reg(0, length * 60 / 75); // return sample length in ticks
+ }
+ }
+ case kSciAudioStop:
+ AudioCD.stop();
+
+ if (getSciVersion() == SCI_VERSION_1_1)
+ return make_reg(0, 1);
+
+ break;
+ case kSciAudioPause:
+ warning("Can't pause CD Audio");
+ break;
+ case kSciAudioResume:
+ // This seems to be hacked up to update the CD instead of resuming
+ // audio like kDoAudio does.
+ AudioCD.updateCD();
+ break;
+ case kSciAudioPosition:
+ // Return -1 if the sample is done playing. Converting to frames to compare.
+ if (((g_system->getMillis() - s->_audioCdStart) * 75 / 1000) >= (uint32)AudioCD.getStatus().duration)
+ return SIGNAL_REG;
+
+ // Return the position otherwise (in ticks).
+ return make_reg(0, (g_system->getMillis() - s->_audioCdStart) * 60 / 1000);
+ case kSciAudioRate: // No need to set the audio rate
+ case kSciAudioVolume: // The speech setting isn't used by CD Audio
+ case kSciAudioLanguage: // No need to set the language
+ break;
+ case kSciAudioCD:
+ // Init
+ return make_reg(0, 1);
+ default:
+ warning("kCdDoAudio: Unhandled case %d", argv[0].toUint16());
+ }
+
+ return s->r_acc;
+}
+
/**
* Used for speech playback and digital soundtracks in CD games
*/
reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
+ // JonesCD uses different functions based on the cdaudio.map file
+ // to use red book tracks.
+ if (s->usesCdTrack())
+ return kDoCdAudio(s, argc, argv);
+
Audio::Mixer *mixer = g_system->getMixer();
switch (argv[0].toUint16()) {
@@ -1076,6 +1175,8 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) {
s->resMan->setAudioLanguage(argv[1].toSint16());
}
break;
+ case kSciAudioCD:
+ return kDoCdAudio(s, argc - 1, argv + 1);
default:
warning("kDoAudio: Unhandled case %d", argv[0].toUint16());
}
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 331c1a5d5b..1d0eb18a7d 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -114,6 +114,9 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc,
_lofsType = SCI_VERSION_AUTODETECT;
_gfxFunctionsType = SCI_VERSION_AUTODETECT;
_moveCountType = kMoveCountUninitialized;
+
+ _audioCdStart = 0;
+ _usesCdTrack = Common::File::exists("cdaudio.map");
}
EngineState::~EngineState() {
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index f1498ac561..a6ddd4019a 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -264,6 +264,8 @@ public:
MoveCountType detectMoveCountType();
bool handleMoveCount() { return detectMoveCountType() == kIncrementMoveCount; }
+
+ bool usesCdTrack() { return _usesCdTrack; }
/* Debugger data: */
Breakpoint *bp_list; /**< List of breakpoints */
@@ -283,12 +285,15 @@ public:
EngineState *successor; /**< Successor of this state: Used for restoring */
Common::String getLanguageString(const char *str, kLanguage lang) const;
+
+ uint32 _audioCdStart;
private:
SciVersion _doSoundType, _setCursorType, _lofsType, _gfxFunctionsType;
MoveCountType _moveCountType;
kLanguage charToLanguage(const char c) const;
int methodChecksum(reg_t objAddress, Selector sel, int offset, uint size) const;
uint16 firstRetOffset(reg_t objectAddress) const;
+ bool _usesCdTrack;
};
/**