diff options
Diffstat (limited to 'engines/groovie')
-rw-r--r-- | engines/groovie/detection.cpp | 14 | ||||
-rw-r--r-- | engines/groovie/groovie.cpp | 41 | ||||
-rw-r--r-- | engines/groovie/groovie.h | 8 | ||||
-rw-r--r-- | engines/groovie/music.cpp | 103 | ||||
-rw-r--r-- | engines/groovie/music.h | 20 | ||||
-rw-r--r-- | engines/groovie/player.cpp | 19 | ||||
-rw-r--r-- | engines/groovie/player.h | 8 | ||||
-rw-r--r-- | engines/groovie/resource.cpp | 2 | ||||
-rw-r--r-- | engines/groovie/resource.h | 4 | ||||
-rw-r--r-- | engines/groovie/script.cpp | 10 | ||||
-rw-r--r-- | engines/groovie/script.h | 3 | ||||
-rw-r--r-- | engines/groovie/vdx.cpp | 8 |
12 files changed, 222 insertions, 18 deletions
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index 78ecac8dbb..87ad534c96 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -111,6 +111,20 @@ static const GroovieGameDescription gameDescriptions[] = { kGroovieT7G, 0 }, + { + { + "t7g", "", + { + { "script.grv", 0, "d1b8033b40aa67c076039881eccce90d", 16659}, + { "gu16.m4a", 0, NULL, 2051214 }, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, Common::kPlatformIOS, ADGF_NO_FLAGS, + Common::GUIO_NOMIDI + }, + kGroovieT7G, 0 + }, + #ifdef ENABLE_GROOVIE2 // The 11th Hour DOS English { diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 508049e1a0..9027262a0c 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -54,6 +54,15 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) : SearchMan.addSubDirectoryMatching(gameDataDir, "media"); SearchMan.addSubDirectoryMatching(gameDataDir, "system"); + _modeSpeed = kGroovieSpeedNormal; + if (ConfMan.hasKey("t7g_speed")) { + Common::String speed = ConfMan.get("t7g_speed"); + if (speed.equals("im_an_ios")) + _modeSpeed = kGroovieSpeediOS; + else if (speed.equals("tweaked")) + _modeSpeed = kGroovieSpeedTweaked; + } + // Initialize the custom debug levels DebugMan.addDebugChannel(kGroovieDebugAll, "All", "Debug everything"); DebugMan.addDebugChannel(kGroovieDebugVideo, "Video", "Debug video and audio playback"); @@ -141,10 +150,20 @@ Common::Error GroovieEngine::run() { } // Create the music player - if (getPlatform() == Common::kPlatformMacintosh) + switch (getPlatform()) { + case Common::kPlatformMacintosh: + // TODO: The 11th Hour Mac uses QuickTime MIDI files + // Right now, since the XMIDI are present and it is still detected as + // the DOS version, we don't have to do anything here. _musicPlayer = new MusicPlayerMac(this); - else + break; + case Common::kPlatformIOS: + _musicPlayer = new MusicPlayerMPEG4(this); + break; + default: _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample"); + break; + } // Load volume levels syncSoundSettings(); @@ -207,17 +226,19 @@ Common::Error GroovieEngine::run() { _script->directGameLoad(slot); } - // Check that the game files and the audio tracks aren't together run from - // the same cd - checkCD(); - // Game timer counter uint16 tmr = 0; - // Initialize the CD - int cd_num = ConfMan.getInt("cdrom"); - if (cd_num >= 0) - _system->getAudioCDManager()->openCD(cd_num); + // Check that the game files and the audio tracks aren't together run from + // the same cd + if (getPlatform() != Common::kPlatformIOS) { + checkCD(); + + // Initialize the CD + int cd_num = ConfMan.getInt("cdrom"); + if (cd_num >= 0) + _system->getAudioCDManager()->openCD(cd_num); + } while (!shouldQuit()) { // Give the debugger a chance to act diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index 0ac9c4b956..eb64cfc60a 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -72,6 +72,12 @@ enum DebugLevels { // the current limitation is 32 debug levels (1 << 31 is the last one) }; +enum GameSpeed { + kGroovieSpeedNormal, + kGroovieSpeediOS, + kGroovieSpeedTweaked +}; + struct GroovieGameDescription; class GroovieEngine : public Engine { @@ -110,6 +116,8 @@ public: Common::MacResManager *_macResFork; + GameSpeed _modeSpeed; + private: const GroovieGameDescription *_gameDescription; Debugger *_debugger; diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index b8a78d9f56..26b3458037 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -31,6 +31,7 @@ #include "common/macresman.h" #include "common/memstream.h" #include "common/textconsole.h" +#include "audio/audiostream.h" #include "audio/midiparser.h" namespace Groovie { @@ -92,6 +93,7 @@ void MusicPlayer::playCD(uint8 track) { } else if ((track == 98) && (_prevCDtrack == 3)) { // Track 98 is used as a hack to stop the credits song g_system->getAudioCDManager()->stop(); + stopCreditsIOS(); return; } @@ -124,6 +126,8 @@ void MusicPlayer::playCD(uint8 track) { playSong((19 << 10) | 36); // XMI.GJD, file 36 } else if (track == 3) { // TODO: Credits MIDI fallback + if (_vm->getPlatform() == Common::kPlatformIOS) + playCreditsIOS(); } } } @@ -224,6 +228,20 @@ void MusicPlayer::unload() { _isPlaying = false; } +void MusicPlayer::playCreditsIOS() { + Audio::AudioStream *stream = Audio::SeekableAudioStream::openStreamFile("7th_Guest_Dolls_from_Hell_OC_ReMix"); + + if (!stream) { + warning("Could not find '7th_Guest_Dolls_from_Hell_OC_ReMix' audio file"); + return; + } + + _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_handleCreditsIOS, stream); +} + +void MusicPlayer::stopCreditsIOS() { + _vm->_system->getMixer()->stopHandle(_handleCreditsIOS); +} // MusicPlayerMidi @@ -747,4 +765,89 @@ Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadS return new Common::MemoryReadStream(output, size, DisposeAfterUse::YES); } +MusicPlayerMPEG4::MusicPlayerMPEG4(GroovieEngine *vm) : MusicPlayer(vm) { + vm->getTimerManager()->installTimerProc(&onTimer, 50 * 1000, this); +} + +MusicPlayerMPEG4::~MusicPlayerMPEG4() { + _vm->getTimerManager()->removeTimerProc(&onTimer); +} + +void MusicPlayerMPEG4::updateVolume() { + // Just set the mixer volume for the music sound type + _vm->_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _userVolume * _gameVolume / 100); +} + +void MusicPlayerMPEG4::unload() { + MusicPlayer::unload(); + + _vm->_system->getMixer()->stopHandle(_handle); +} + +bool MusicPlayerMPEG4::load(uint32 fileref, bool loop) { + // Find correct filename + ResInfo info; + _vm->_resMan->getResInfo(fileref, info); + uint len = info.filename.size(); + if (len < 4) + return false; // This shouldn't actually occur + /* + 19462 door + 19463 ?? + 19464 ?? + 19465 puzzle? + 19466 cake + 19467 maze + 19468 ambient (but not 69, amb b. odd) + 19470 puzzle + 19471 + 19473 + 19475 coffins or blood pump + 19476 blood pump or coffins + 19493 + 19499 chapel + 19509 downstair ambient + 19510 bedroom 'skip 3 and 5' puzzle (should loop from partway?) + 19514 + 19515 bathroom drain teeth + */ + if ((fileref >= 19462 && fileref <= 19468) || + fileref == 19470 || fileref == 19471 || + fileref == 19473 || fileref == 19475 || + fileref == 19476 || fileref == 19493 || + fileref == 19499 || fileref == 19509 || + fileref == 19510 || fileref == 19514 || + fileref == 19515) + loop = true; // XMIs for these refs self-loop + + // iOS port provides alternative intro sequence music + if (info.filename == "gu39.xmi") { + info.filename = "intro"; + } else if (info.filename == "gu32.xmi") { + info.filename = "foyer"; + } else { + // Remove the extension + info.filename.deleteLastChar(); + info.filename.deleteLastChar(); + info.filename.deleteLastChar(); + info.filename.deleteLastChar(); + } + + // Create the audio stream + Audio::AudioStream *audStream = Audio::SeekableAudioStream::openStreamFile(info.filename); + + if (!audStream) { + warning("Could not play audio file '%s'", info.filename.c_str()); + return false; + } + + // Loop if requested + if (loop) + audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0); + + // Play! + _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_handle, audStream); + return true; +} + } // End of Groovie namespace diff --git a/engines/groovie/music.h b/engines/groovie/music.h index fa4150a83b..5ef6a8e076 100644 --- a/engines/groovie/music.h +++ b/engines/groovie/music.h @@ -26,6 +26,7 @@ #include "common/array.h" #include "common/mutex.h" #include "audio/mididrv.h" +#include "audio/mixer.h" class MidiParser; @@ -59,6 +60,11 @@ private: uint16 _backgroundDelay; + // T7G iOS credits mp3 stream + void playCreditsIOS(); + void stopCreditsIOS(); + Audio::SoundHandle _handleCreditsIOS; + // Volume fading uint32 _fadingStartTime; uint16 _fadingStartVolume; @@ -157,6 +163,20 @@ private: Common::SeekableReadStream *decompressMidi(Common::SeekableReadStream *stream); }; +class MusicPlayerMPEG4 : public MusicPlayer { +public: + MusicPlayerMPEG4(GroovieEngine *vm); + ~MusicPlayerMPEG4(); + +protected: + void updateVolume(); + bool load(uint32 fileref, bool loop); + void unload(); + +private: + Audio::SoundHandle _handle; +}; + } // End of Groovie namespace #endif // GROOVIE_MUSIC_H diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp index 11318d2e94..e2a1ff3d56 100644 --- a/engines/groovie/player.cpp +++ b/engines/groovie/player.cpp @@ -28,18 +28,19 @@ namespace Groovie { VideoPlayer::VideoPlayer(GroovieEngine *vm) : - _vm(vm), _syst(vm->_system), _file(NULL), _audioStream(NULL) { + _vm(vm), _syst(vm->_system), _file(NULL), _audioStream(NULL), _fps(0), _overrideSpeed(false) { } bool VideoPlayer::load(Common::SeekableReadStream *file, uint16 flags) { _file = file; _flags = flags; + _overrideSpeed = false; _audioStream = NULL; - uint16 fps = loadInternal(); + _fps = loadInternal(); - if (fps != 0) { - _millisBetweenFrames = 1000 / fps; + if (_fps != 0) { + setOverrideSpeed(_overrideSpeed); _begunPlaying = false; return true; } else { @@ -48,6 +49,16 @@ bool VideoPlayer::load(Common::SeekableReadStream *file, uint16 flags) { } } +void VideoPlayer::setOverrideSpeed(bool isOverride) { + _overrideSpeed = isOverride; + if (_fps != 0) { + if (isOverride) + _millisBetweenFrames = 1000 / 26; + else + _millisBetweenFrames = 1000 / _fps; + } +} + bool VideoPlayer::playFrame() { bool end = true; diff --git a/engines/groovie/player.h b/engines/groovie/player.h index c6d927f2c0..d8135a99b2 100644 --- a/engines/groovie/player.h +++ b/engines/groovie/player.h @@ -45,15 +45,21 @@ protected: virtual uint16 loadInternal() = 0; virtual bool playFrameInternal() = 0; + void setOverrideSpeed(bool isOverride); + bool getOverrideSpeed() const { return _overrideSpeed; } + GroovieEngine *_vm; OSystem *_syst; Common::SeekableReadStream *_file; uint16 _flags; Audio::QueuingAudioStream *_audioStream; - + + private: // Synchronization stuff bool _begunPlaying; + bool _overrideSpeed; + uint16 _fps; uint16 _millisBetweenFrames; uint32 _lastFrameTime; diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp index 05359342f8..10cf24a589 100644 --- a/engines/groovie/resource.cpp +++ b/engines/groovie/resource.cpp @@ -173,6 +173,7 @@ bool ResMan_t7g::getResInfo(uint32 fileRef, ResInfo &resInfo) { char resname[12]; rlFile->read(resname, 12); debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %12s", resname); + resInfo.filename = resname; // Read the resource information resInfo.offset = rlFile->readUint32LE(); @@ -281,6 +282,7 @@ bool ResMan_v2::getResInfo(uint32 fileRef, ResInfo &resInfo) { char resname[12]; rlFile.read(resname, 12); debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %12s", resname); + resInfo.filename = resname; // 6 padding bytes? (it looks like they're always 0) diff --git a/engines/groovie/resource.h b/engines/groovie/resource.h index 2c215917cc..33e15e6b98 100644 --- a/engines/groovie/resource.h +++ b/engines/groovie/resource.h @@ -33,6 +33,7 @@ struct ResInfo { uint16 gjd; uint32 offset; uint32 size; + Common::String filename; }; class ResMan { @@ -40,11 +41,12 @@ public: virtual ~ResMan() {} Common::SeekableReadStream *open(uint32 fileRef); + virtual uint32 getRef(Common::String name, Common::String scriptname = "") = 0; + virtual bool getResInfo(uint32 fileRef, ResInfo &resInfo) = 0; protected: Common::Array<Common::String> _gjds; - virtual bool getResInfo(uint32 fileRef, ResInfo &resInfo) = 0; uint16 _lastGjd; }; diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index 3bd90a042e..b52a8723fc 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -65,8 +65,9 @@ static void debugScript(int level, bool nl, const char *s, ...) { Script::Script(GroovieEngine *vm, EngineVersion version) : _code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm), - _videoFile(NULL), _videoRef(0), _staufsMove(NULL), - _random("GroovieScripts") { + _videoFile(NULL), _videoRef(0), _staufsMove(NULL), _lastCursor(0xff), + _version(version), _random("GroovieScripts") { + // Initialize the opcode set depending on the engine version switch (version) { case kGroovieT7G: @@ -385,6 +386,7 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) { // If clicked with the mouse, jump to the specified address if (_mouseClicked) { + _lastCursor = cursor; _inputAction = address; } } @@ -584,6 +586,10 @@ bool Script::playvideofromref(uint32 fileref) { if (_videoFile) { _videoRef = fileref; + // If teeth cursor, and in main script, mark video prefer low-speed + // filename check as sometimes teeth used for puzzle movements (bishops) + if (_version == kGroovieT7G && _lastCursor == 7 && _scriptFile == "script.grv") + _bitflags |= (1 << 15); _vm->_videoPlayer->load(_videoFile, _bitflags); } else { error("Couldn't open file"); diff --git a/engines/groovie/script.h b/engines/groovie/script.h index 95da96487e..8cd790af5e 100644 --- a/engines/groovie/script.h +++ b/engines/groovie/script.h @@ -72,6 +72,9 @@ private: Common::RandomSource _random; bool _firstbit; + uint8 _lastCursor; + + EngineVersion _version; // Script filename (for debugging purposes) Common::String _scriptFile; diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp index ae1e9eebb3..b3fcf462b2 100644 --- a/engines/groovie/vdx.cpp +++ b/engines/groovie/vdx.cpp @@ -86,6 +86,11 @@ uint16 VDXPlayer::loadInternal() { _flagEight = ((_flags & (1 << 8)) != 0); _flagNine = ((_flags & (1 << 9)) != 0); + // Enable highspeed if we're not obeying fps, and not marked as special + // This will be disabled in chunk audio if we're actually an audio vdx + if ( _vm->_modeSpeed == kGroovieSpeediOS || (_vm->_modeSpeed == kGroovieSpeedTweaked && ((_flags & (1 << 15)) == 0))) + setOverrideSpeed(true); + if (_flagOnePrev && !_flagOne && !_flagEight) { _flagSeven = true; } @@ -522,6 +527,9 @@ void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colors, uint16 imageWidth) } void VDXPlayer::chunkSound(Common::ReadStream *in) { + if (getOverrideSpeed()) + setOverrideSpeed(false); + if (!_audioStream) { _audioStream = Audio::makeQueuingAudioStream(22050, false); Audio::SoundHandle sound_handle; |