diff options
-rw-r--r-- | engines/engine.cpp | 1 | ||||
-rw-r--r-- | engines/gob/gob.h | 6 | ||||
-rw-r--r-- | engines/sci/engine/file.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/file.h | 4 | ||||
-rw-r--r-- | engines/sci/engine/kevent.cpp | 28 | ||||
-rw-r--r-- | engines/sci/engine/kfile.cpp | 30 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 2 | ||||
-rw-r--r-- | engines/sci/sound/audio.cpp | 57 | ||||
-rw-r--r-- | engines/tony/sound.cpp | 146 | ||||
-rw-r--r-- | engines/tony/sound.h | 7 |
10 files changed, 232 insertions, 51 deletions
diff --git a/engines/engine.cpp b/engines/engine.cpp index d8563666b9..475cc77064 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -40,7 +40,6 @@ #include "common/str.h" #include "common/error.h" #include "common/list.h" -#include "common/list_intern.h" #include "common/memstream.h" #include "common/scummsys.h" #include "common/taskbar.h" diff --git a/engines/gob/gob.h b/engines/gob/gob.h index aefc63c707..730d393906 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -25,7 +25,6 @@ #include "common/random.h" #include "common/system.h" -#include "common/savefile.h" #include "graphics/pixelformat.h" @@ -33,10 +32,6 @@ #include "gob/console.h" -namespace GUI { -class StaticTextWidget; -} - /** * This is the namespace of the Gob engine. * @@ -75,7 +70,6 @@ class PalAnim; class Scenery; class Util; class SaveLoad; -class GobConsole; class PreGob; #define WRITE_VAR_UINT32(var, val) _vm->_inter->_variables->writeVar32(var, val) diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index 623caec856..49e6e1716d 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -129,7 +129,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u } FileHandle *getFileFromHandle(EngineState *s, uint handle) { - if (handle == 0 || handle == VIRTUALFILE_HANDLE) { + if (handle == 0 || handle >= VIRTUALFILE_HANDLE_START) { error("Attempt to use invalid file handle (%d)", handle); return 0; } diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h index 052eb735e9..f43958c5ab 100644 --- a/engines/sci/engine/file.h +++ b/engines/sci/engine/file.h @@ -41,8 +41,10 @@ enum { MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */ }; -#define VIRTUALFILE_HANDLE 200 +#define VIRTUALFILE_HANDLE_START 32000 +#define VIRTUALFILE_HANDLE_SCI32SAVE 32100 #define PHANTASMAGORIA_SAVEGAME_INDEX "phantsg.dir" +#define VIRTUALFILE_HANDLE_SCIAUDIO 32300 struct SavegameDesc { int16 id; diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index eb052dd24e..beaad2628a 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -42,6 +42,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { reg_t obj = argv[1]; SciEvent curEvent; int modifier_mask = getSciVersion() <= SCI_VERSION_01 ? SCI_KEYMOD_ALL : SCI_KEYMOD_NO_FOOLOCK; + uint16 modifiers = 0; SegManager *segMan = s->_segMan; Common::Point mousePos; @@ -110,6 +111,26 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x); writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y); + // Get current keyboard modifiers, only keep relevant bits + modifiers = curEvent.modifiers & modifier_mask; + if (g_sci->getPlatform() == Common::kPlatformDOS) { + // We are supposed to emulate SCI running in DOS + + // We set the higher byte of the modifiers to 02h + // Original SCI also did that indirectly, because it asked BIOS for shift status + // via AH=0x02 INT16, which then sets the shift flags in AL + // AH is supposed to be destroyed in that case and it's not defined that 0x02 + // is still in it on return. The value of AX was then set into the modifiers selector. + // At least one fan-made game (Betrayed Alliance) requires 0x02 to be in the upper byte, + // otherwise the darts game (script 111) will not work properly. + + // It seems Sierra fixed this behaviour (effectively bug) in the SCI1 keyboard driver. + // SCI32 also resets the upper byte. + if (getSciVersion() <= SCI_VERSION_01) { + modifiers |= 0x0200; + } + } + //s->_gui->moveCursor(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y); switch (curEvent.type) { @@ -125,7 +146,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { writeSelectorValue(segMan, obj, SELECTOR(message), curEvent.character); // We only care about the translated character - writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask); + writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers); break; case SCI_EVENT_MOUSE_RELEASE: @@ -149,10 +170,11 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { default: break; } + modifiers |= extra_bits; // add these additional bits to the mix writeSelectorValue(segMan, obj, SELECTOR(type), curEvent.type); writeSelectorValue(segMan, obj, SELECTOR(message), 0); - writeSelectorValue(segMan, obj, SELECTOR(modifiers), (curEvent.modifiers | extra_bits) & modifier_mask); + writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers); s->r_acc = make_reg(0, 1); } break; @@ -161,7 +183,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { // Return a null event writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_NONE); writeSelectorValue(segMan, obj, SELECTOR(message), 0); - writeSelectorValue(segMan, obj, SELECTOR(modifiers), curEvent.modifiers & modifier_mask); + writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers); s->r_acc = NULL_REG; } diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 61ac76d0a7..80bd683dcd 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -258,16 +258,21 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { } debugC(kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode); + if (name.hasPrefix("sciAudio\\")) { + // fan-made sciAudio extension, don't create those files and instead return a virtual handle + return make_reg(0, VIRTUALFILE_HANDLE_SCIAUDIO); + } + #ifdef ENABLE_SCI32 if (name == PHANTASMAGORIA_SAVEGAME_INDEX) { if (s->_virtualIndexFile) { - return make_reg(0, VIRTUALFILE_HANDLE); + return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE); } else { Common::String englishName = g_sci->getSciLanguageString(name, K_LANG_ENGLISH); Common::String wrappedName = g_sci->wrapFilename(englishName); if (!g_sci->getSaveFileManager()->listSavefiles(wrappedName).empty()) { s->_virtualIndexFile = new VirtualIndexFile(wrappedName); - return make_reg(0, VIRTUALFILE_HANDLE); + return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE); } } } @@ -320,7 +325,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { s->_virtualIndexFile->write("\0", 1); s->_virtualIndexFile->write("\0", 1); // Spot description (empty) s->_virtualIndexFile->seek(0, SEEK_SET); - return make_reg(0, VIRTUALFILE_HANDLE); + return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE); } } #endif @@ -346,12 +351,17 @@ reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { uint16 handle = argv[0].toUint16(); #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { + if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) { s->_virtualIndexFile->close(); return SIGNAL_REG; } #endif + if (handle >= VIRTUALFILE_HANDLE_START) { + // it's a virtual handle? ignore it + return SIGNAL_REG; + } + FileHandle *f = getFileFromHandle(s, handle); if (f) { f->close(); @@ -373,7 +383,7 @@ reg_t kFileIOReadRaw(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size); #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { + if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) { bytesRead = s->_virtualIndexFile->read(buf, size); } else { #endif @@ -403,7 +413,7 @@ reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size); #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { + if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) { s->_virtualIndexFile->write(buf, size); success = true; } else { @@ -480,7 +490,7 @@ reg_t kFileIOReadString(EngineState *s, int argc, reg_t *argv) { uint32 bytesRead; #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) + if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) bytesRead = s->_virtualIndexFile->readLine(buf, maxsize); else #endif @@ -503,7 +513,7 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { // We skip creating these files, and instead handle the calls // directly. Since the sciAudio calls are only creating text files, // this is probably the most straightforward place to handle them. - if (handle == 0xFFFF && str.hasPrefix("(sciAudio")) { + if (handle == VIRTUALFILE_HANDLE_SCIAUDIO) { Common::List<ExecStack>::const_iterator iter = s->_executionStack.reverse_begin(); iter--; // sciAudio iter--; // sciAudio child @@ -512,7 +522,7 @@ reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) { } #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) { + if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) { s->_virtualIndexFile->write(str.c_str(), str.size()); return NULL_REG; } @@ -539,7 +549,7 @@ reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence); #ifdef ENABLE_SCI32 - if (handle == VIRTUALFILE_HANDLE) + if (handle == VIRTUALFILE_HANDLE_SCI32SAVE) return make_reg(0, s->_virtualIndexFile->seek(offset, whence)); #endif diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 9628e8ac97..61aeb00ac3 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -23,7 +23,7 @@ #include "common/algorithm.h" #include "common/events.h" #include "common/keyboard.h" -#include "common/list_intern.h" +#include "common/list.h" #include "common/str.h" #include "common/system.h" #include "common/textconsole.h" diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 8c029cf502..57f0415285 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -79,15 +79,23 @@ void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan Common::String command = segMan->getString(commandReg); if (command == "play" || command == "playx") { -#ifdef USE_MAD reg_t fileNameReg = readSelector(segMan, sciAudioObject, kernel->findSelector("fileName")); Common::String fileName = segMan->getString(fileNameReg); - int16 loopCount = (int16)readSelectorValue(segMan, sciAudioObject, kernel->findSelector("loopCount")); - // When loopCount is -1, we treat it as infinite looping, else no looping is done. - // This is observed by game scripts, which can set loopCount to all sorts of random values. + reg_t loopCountReg = readSelector(segMan, sciAudioObject, kernel->findSelector("loopCount")); + Common::String loopCountStr = segMan->getString(loopCountReg); + int16 loopCount = atoi(loopCountStr.c_str()); + // Adjust loopCount for ScummVM's LoopingAudioStream semantics - loopCount = (loopCount == -1) ? 0 : 1; + if (loopCount == -1) { + loopCount = 0; // loop endlessly + } else if (loopCount >= 0) { + // sciAudio loopCount == 0 -> play 1 time -> ScummVM's loopCount should be 1 + // sciAudio loopCount == 1 -> play 2 times -> ScummVM's loopCount should be 2 + loopCount++; + } else { + loopCount = 1; // play once in case the value makes no sense + } // Determine sound type Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType; @@ -96,20 +104,51 @@ void AudioPlayer::handleFanmadeSciAudio(reg_t sciAudioObject, SegManager *segMan else if (fileName.hasPrefix("speech")) soundType = Audio::Mixer::kSpeechSoundType; - Common::File *sciAudio = new Common::File(); + // Determine compression + uint32 audioCompressionType = 0; + if ((fileName.hasSuffix(".mp3")) || (fileName.hasSuffix(".sciAudio")) || (fileName.hasSuffix(".sciaudio"))) { + audioCompressionType = MKTAG('M','P','3',' '); + } else if (fileName.hasSuffix(".wav")) { + audioCompressionType = MKTAG('W','A','V',' '); + } else if (fileName.hasSuffix(".aiff")) { + audioCompressionType = MKTAG('A','I','F','F'); + } else { + error("sciAudio: unsupported file type"); + } + + Common::File *sciAudioFile = new Common::File(); // Replace backwards slashes for (uint i = 0; i < fileName.size(); i++) { if (fileName[i] == '\\') fileName.setChar('/', i); } - sciAudio->open("sciAudio/" + fileName); + sciAudioFile->open("sciAudio/" + fileName); + + Audio::RewindableAudioStream *audioStream = nullptr; + + switch (audioCompressionType) { + case MKTAG('M','P','3',' '): +#ifdef USE_MAD + audioStream = Audio::makeMP3Stream(sciAudioFile, DisposeAfterUse::YES); +#endif + break; + case MKTAG('W','A','V',' '): + audioStream = Audio::makeWAVStream(sciAudioFile, DisposeAfterUse::YES); + break; + case MKTAG('A','I','F','F'): + audioStream = Audio::makeAIFFStream(sciAudioFile, DisposeAfterUse::YES); + break; + default: + break; + } - Audio::SeekableAudioStream *audioStream = Audio::makeMP3Stream(sciAudio, DisposeAfterUse::YES); + if (!audioStream) { + error("sciAudio: requested compression not compiled into ScummVM"); + } // We only support one audio handle _mixer->playStream(soundType, &_audioHandle, Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audioStream, loopCount)); -#endif } else if (command == "stop") { _mixer->stopHandle(_audioHandle); } else { diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp index faf91c1fc5..73205655b0 100644 --- a/engines/tony/sound.cpp +++ b/engines/tony/sound.cpp @@ -28,7 +28,9 @@ #include "audio/audiostream.h" #include "audio/decoders/adpcm.h" -#include "audio/decoders/raw.h" +#include "audio/decoders/flac.h" +#include "audio/decoders/mp3.h" +#include "audio/decoders/vorbis.h" #include "audio/decoders/wave.h" #include "common/textconsole.h" #include "tony/game.h" @@ -49,6 +51,18 @@ static int remapVolume(int volume) { return (int)((double)Audio::Mixer::kMaxChannelVolume * pow(10.0, dsvol / 2000.0) + 0.5); } +// Another obvious rip from gob engine. Hi DrMcCoy! +Common::String setExtension(const Common::String &str, const Common::String &ext) { + if (str.empty()) + return str; + + const char *dot = strrchr(str.c_str(), '.'); + if (dot) + return Common::String(str.c_str(), dot - str.c_str()) + ext; + + return str + ext; +} + /****************************************************************************\ * FPSOUND Methods \****************************************************************************/ @@ -226,22 +240,59 @@ bool FPSfx::loadFile(const char *fileName) { if (!_soundSupported) return true; + SoundCodecs codec = FPCODEC_UNKNOWN; + Common::File file; - if (!file.open(fileName)) { + if (file.open(fileName)) + codec = FPCODEC_ADPCM; + else if (file.open(setExtension(fileName, ".MP3"))) + codec = FPCODEC_MP3; + else if (file.open(setExtension(fileName, ".OGG"))) + codec = FPCODEC_OGG; + else if (file.open(setExtension(fileName, ".FLA"))) + codec = FPCODEC_FLAC; + else { warning("FPSfx::LoadFile(): Cannot open sfx file!"); return false; } - if (file.readUint32BE() != MKTAG('A', 'D', 'P', 0x10)) { - warning("FPSfx::LoadFile(): Invalid ADP header!"); + Common::SeekableReadStream *buffer; + switch (codec) { + case FPCODEC_ADPCM: { + if (file.readUint32BE() != MKTAG('A', 'D', 'P', 0x10)) { + warning("FPSfx::LoadFile(): Invalid ADP header!"); + return false; + } + + uint32 rate = file.readUint32LE(); + uint32 channels = file.readUint32LE(); + + buffer = file.readStream(file.size() - file.pos()); + _rewindableStream = Audio::makeADPCMStream(buffer, DisposeAfterUse::YES, 0, Audio::kADPCMDVI, rate, channels); + } + break; + case FPCODEC_MP3: +#ifdef USE_MAD + buffer = file.readStream(file.size()); + _rewindableStream = Audio::makeMP3Stream(buffer, DisposeAfterUse::YES); +#endif + break; + case FPCODEC_OGG: +#ifdef USE_VORBIS + buffer = file.readStream(file.size()); + _rewindableStream = Audio::makeVorbisStream(buffer, DisposeAfterUse::YES); +#endif + break; + case FPCODEC_FLAC: + buffer = file.readStream(file.size()); +#ifdef USE_FLAC + _rewindableStream = Audio::makeFLACStream(buffer, DisposeAfterUse::YES); +#endif + break; + default: return false; } - uint32 rate = file.readUint32LE(); - uint32 channels = file.readUint32LE(); - - Common::SeekableReadStream *buffer = file.readStream(file.size() - file.pos()); - _rewindableStream = Audio::makeADPCMStream(buffer, DisposeAfterUse::YES, 0, Audio::kADPCMDVI, rate, channels); _fileLoaded = true; return true; } @@ -457,7 +508,7 @@ void FPStream::release() { * Opens a file stream * * @param fileName Filename to be opened - * @param codec CODEC to be used to uncompress samples + * @param bufSize Buffer size * * @returns True is everything is OK, False otherwise */ @@ -468,13 +519,32 @@ bool FPStream::loadFile(const Common::String &fileName, int bufSize) { if (_fileLoaded) unloadFile(); + SoundCodecs codec = FPCODEC_UNKNOWN; + // Open the file stream for reading - if (!_file.open(fileName)) { - // Fallback: try with an extra '0' prefix - if (!_file.open("0" + fileName)) - return false; + if (_file.open(fileName)) + codec = FPCODEC_ADPCM; + else if (_file.open(setExtension(fileName, ".MP3"))) + codec = FPCODEC_MP3; + else if (_file.open(setExtension(fileName, ".OGG"))) + codec = FPCODEC_OGG; + else if (_file.open(setExtension(fileName, ".FLA"))) + codec = FPCODEC_FLAC; + // Fallback: try with an extra '0' prefix + else if (_file.open("0" + fileName)) { + codec = FPCODEC_ADPCM; warning("FPStream::loadFile(): Fallback from %s to %s", fileName.c_str(), _file.getName()); - } + } else if (_file.open(setExtension("0" + fileName, ".MP3"))) { + codec = FPCODEC_MP3; + warning("FPStream::loadFile(): Fallback from %s to %s", fileName.c_str(), _file.getName()); + } else if (_file.open(setExtension("0" + fileName, ".OGG"))) { + codec = FPCODEC_OGG; + warning("FPStream::loadFile(): Fallback from %s to %s", fileName.c_str(), _file.getName()); + } else if (_file.open(setExtension("0" + fileName, ".FLA"))) { + codec = FPCODEC_FLAC; + warning("FPStream::loadFile(): Fallback from %s to %s", fileName.c_str(), _file.getName()); + } else + return false; // Save the size of the stream _size = _file.size(); @@ -482,9 +552,51 @@ bool FPStream::loadFile(const Common::String &fileName, int bufSize) { #ifdef __amigaos4__ // HACK: AmigaOS 4 has weird performance problems with reading in the audio thread, // so we read the whole stream into memory. - _rewindableStream = Audio::makeADPCMStream(_file.readStream(_size), DisposeAfterUse::YES, 0, Audio::kADPCMDVI, 44100, 2); + switch (codec) { + case FPCODEC_ADPCM: + _rewindableStream = Audio::makeADPCMStream(_file.readStream(_size), DisposeAfterUse::YES, 0, Audio::kADPCMDVI, 44100, 2); + break; + case FPCODEC_MP3: +#ifdef USE_MAD + _rewindableStream = Audio::makeMP3Stream(&_file, DisposeAfterUse::YES); +#endif + break; + case FPCODEC_OGG: +#ifdef USE_VORBIS + _rewindableStream = Audio::makeVorbisStream(&_file, DisposeAfterUse::YES); +#endif + break; + case FPCODEC_FLAC: +#ifdef USE_FLAC + _rewindableStream = Audio::makeFLACStream(&_file, DisposeAfterUse::YES); +#endif + break; + default: + break; + } #else - _rewindableStream = Audio::makeADPCMStream(&_file, DisposeAfterUse::NO, 0, Audio::kADPCMDVI, 44100, 2); + switch (codec) { + case FPCODEC_ADPCM: + _rewindableStream = Audio::makeADPCMStream(&_file, DisposeAfterUse::NO, 0, Audio::kADPCMDVI, 44100, 2); + break; + case FPCODEC_MP3: +#ifdef USE_MAD + _rewindableStream = Audio::makeMP3Stream(&_file, DisposeAfterUse::NO); +#endif + break; + case FPCODEC_OGG: +#ifdef USE_VORBIS + _rewindableStream = Audio::makeVorbisStream(&_file, DisposeAfterUse::NO); +#endif + break; + case FPCODEC_FLAC: +#ifdef USE_FLAC + _rewindableStream = Audio::makeFLACStream(&_file, DisposeAfterUse::NO); +#endif + break; + default: + break; + } #endif // All done diff --git a/engines/tony/sound.h b/engines/tony/sound.h index 2ea1162d98..206935f314 100644 --- a/engines/tony/sound.h +++ b/engines/tony/sound.h @@ -45,8 +45,11 @@ class FPStream; class FPSfx; enum SoundCodecs { - FPCODEC_RAW, - FPCODEC_ADPCM + FPCODEC_UNKNOWN, + FPCODEC_ADPCM, + FPCODEC_MP3, + FPCODEC_OGG, + FPCODEC_FLAC }; /** |