bool Console::cmdLoadSound(int argc, const char **argv) { if (!Common::File::exists(argv[1])) { debugPrintf("File does not exist\n"); return true; } if (argc == 2) { Audio::AudioStream *soundStream = makeRawZorkStream(argv[1], _engine); Audio::SoundHandle handle; _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false); } else if (argc == 4) { int isStereo = atoi(argv[3]); Common::File *file = new Common::File(); if (!_engine->getSearchManager()->openFile(*file, argv[1])) { warning("File not found: %s", argv[1]); return true; } Audio::AudioStream *soundStream = makeRawZorkStream(file, atoi(argv[2]), isStereo == 0 ? false : true); Audio::SoundHandle handle; _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false); } else { debugPrintf("Use %s <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n", argv[0]); return true; } return true; }
Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) { Common::File *file = new Common::File(); assert(file->open(filePath)); Common::String fileName = getFileName(filePath); fileName.toLowercase(); SoundParams soundParams; if (engine->getGameId() == GID_NEMESIS) { for (int i = 0; i < 6; ++i) { if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == (fileName[6])) soundParams = RawZorkStream::_zNemSoundParamLookupTable[i]; } } else if (engine->getGameId() == GID_GRANDINQUISITOR) { for (int i = 0; i < 6; ++i) { if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == (fileName[7])) soundParams = RawZorkStream::_zgiSoundParamLookupTable[i]; } } if (soundParams.packed) { return makeRawZorkStream(wrapBufferedSeekableReadStream(file, 2048, DisposeAfterUse::YES), soundParams.rate, soundParams.stereo, DisposeAfterUse::YES); } else { byte flags = 0; if (soundParams.stereo) flags |= Audio::FLAG_STEREO; return Audio::makeRawStream(file, soundParams.rate, flags, DisposeAfterUse::YES); } }
SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto) : ScriptingEffect(engine, key, SCRIPTING_EFFECT_AUDIO) { _syncto = syncto; _sub = NULL; Audio::RewindableAudioStream *audioStream = NULL; if (filename.contains(".wav")) { Common::File *file = new Common::File(); if (_engine->getSearchManager()->openFile(*file, filename)) { audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); } } else { audioStream = makeRawZorkStream(filename, _engine); } _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream); Common::String subname = filename; subname.setChar('s', subname.size() - 3); subname.setChar('u', subname.size() - 2); subname.setChar('b', subname.size() - 1); if (_engine->getSearchManager()->hasFile(subname)) _sub = new Subtitle(_engine, subname); }
Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) { Common::File *file = new Common::File(); Common::String actualName = filePath; bool found = engine->getSearchManager()->openFile(*file, actualName); bool isRaw = actualName.hasSuffix(".raw"); if ((!found && isRaw) || (found && isRaw && file->size() < 10)) { if (found) file->close(); // Check for an audio patch (.src) actualName.setChar('s', actualName.size() - 3); actualName.setChar('r', actualName.size() - 2); actualName.setChar('c', actualName.size() - 1); if (!engine->getSearchManager()->openFile(*file, actualName)) return NULL; } else if (!found && !isRaw) { return NULL; } // Get the file name Common::StringTokenizer tokenizer(actualName, "/\\"); Common::String fileName; while (!tokenizer.empty()) { fileName = tokenizer.nextToken(); } fileName.toLowercase(); const SoundParams *soundParams = NULL; if (engine->getGameId() == GID_NEMESIS) { for (int i = 0; i < 32; ++i) { if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == (fileName[6])) soundParams = &RawZorkStream::_zNemSoundParamLookupTable[i]; } } else if (engine->getGameId() == GID_GRANDINQUISITOR) { for (int i = 0; i < 24; ++i) { if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == (fileName[7])) soundParams = &RawZorkStream::_zgiSoundParamLookupTable[i]; } } if (soundParams == NULL) return NULL; if (soundParams->packed) { return makeRawZorkStream(wrapBufferedSeekableReadStream(file, 2048, DisposeAfterUse::YES), soundParams->rate, soundParams->stereo, DisposeAfterUse::YES); } else { byte flags = 0; if (soundParams->bits16) flags |= Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN; if (soundParams->stereo) flags |= Audio::FLAG_STEREO; return Audio::makePCMStream(file, soundParams->rate, flags, DisposeAfterUse::YES); } }
bool Console::cmdRawToWav(int argc, const char **argv) { if (argc != 3) { debugPrintf("Use %s <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n", argv[0]); return true; } Common::File file; if (!_engine->getSearchManager()->openFile(file, argv[1])) { warning("File not found: %s", argv[1]); return true; } Audio::AudioStream *audioStream = makeRawZorkStream(argv[1], _engine); Common::DumpFile output; output.open(argv[2]); output.writeUint32BE(MKTAG('R', 'I', 'F', 'F')); output.writeUint32LE(file.size() * 2 + 36); output.writeUint32BE(MKTAG('W', 'A', 'V', 'E')); output.writeUint32BE(MKTAG('f', 'm', 't', ' ')); output.writeUint32LE(16); output.writeUint16LE(1); uint16 numChannels; if (audioStream->isStereo()) { numChannels = 2; output.writeUint16LE(2); } else { numChannels = 1; output.writeUint16LE(1); } output.writeUint32LE(audioStream->getRate()); output.writeUint32LE(audioStream->getRate() * numChannels * 2); output.writeUint16LE(numChannels * 2); output.writeUint16LE(16); output.writeUint32BE(MKTAG('d', 'a', 't', 'a')); output.writeUint32LE(file.size() * 2); int16 *buffer = new int16[file.size()]; audioStream->readBuffer(buffer, file.size()); #ifndef SCUMM_LITTLE_ENDIAN for (int i = 0; i < file.size(); ++i) buffer[i] = TO_LE_16(buffer[i]); #endif output.write(buffer, file.size() * 2); delete[] buffer; return true; }
MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume) : MusicNodeBASE(engine, key, SCRIPTING_EFFECT_AUDIO) { _loop = loop; _volume = volume; _crossfade = false; _crossfadeTarget = 0; _crossfadeTime = 0; _attenuate = 0; _pantrack = false; _pantrackPosition = 0; _sub = NULL; _stereo = false; _loaded = false; Audio::RewindableAudioStream *audioStream = NULL; if (filename.contains(".wav")) { Common::File *file = new Common::File(); if (_engine->getSearchManager()->openFile(*file, filename)) { audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); } } else { audioStream = makeRawZorkStream(filename, _engine); } if (audioStream) { _stereo = audioStream->isStereo(); if (_loop) { Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES); _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume); } else { _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume); } if (_key != StateKey_NotSet) _engine->getScriptManager()->setStateValue(_key, 1); // Change filename.raw into filename.sub Common::String subname = filename; subname.setChar('s', subname.size() - 3); subname.setChar('u', subname.size() - 2); subname.setChar('b', subname.size() - 1); if (_engine->getSearchManager()->hasFile(subname)) _sub = new Subtitle(_engine, subname); _loaded = true; } }
bool ActionMusic::execute(ZVision *engine) { Audio::RewindableAudioStream *audioStream; if (_fileName.contains(".wav")) { Common::File *file = new Common::File(); if (file->open(_fileName)) { audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); } } else { audioStream = makeRawZorkStream(_fileName, engine); } if (_loop) { Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES); engine->_mixer->playStream(_soundType, 0, loopingAudioStream, -1, _volume); } else { engine->_mixer->playStream(_soundType, 0, audioStream, -1, _volume); } return true; }
Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, ZVision *engine) { Common::File *file = new Common::File(); assert(file->open(filePath)); Common::String fileName = getFileName(filePath); fileName.toLowercase(); SoundParams soundParams = { ' ', 0, false, false }; bool foundParams = false; char fileIdentifier = (engine->getGameId() == GID_NEMESIS) ? fileName[6] : fileName[7]; if (engine->getGameId() == GID_NEMESIS) { for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zNemSoundParamLookupTable); ++i) { if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == fileIdentifier) { soundParams = RawZorkStream::_zNemSoundParamLookupTable[i]; foundParams = true; } } } else if (engine->getGameId() == GID_GRANDINQUISITOR) { for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zgiSoundParamLookupTable); ++i) { if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == fileIdentifier) { soundParams = RawZorkStream::_zgiSoundParamLookupTable[i]; foundParams = true; } } } if (!foundParams) error("Unable to find sound params for file '%s'. File identifier is '%c'", filePath.c_str(), fileIdentifier); if (soundParams.packed) { return makeRawZorkStream(wrapBufferedSeekableReadStream(file, 2048, DisposeAfterUse::YES), soundParams.rate, soundParams.stereo, DisposeAfterUse::YES); } else { byte flags = 0; if (soundParams.stereo) flags |= Audio::FLAG_STEREO; return Audio::makeRawStream(file, soundParams.rate, flags, DisposeAfterUse::YES); } }
void convertRawToWav(const Common::String &inputFile, ZVision *engine, const Common::String &outputFile) { Common::File file; if (!file.open(inputFile)) return; Audio::AudioStream *audioStream = makeRawZorkStream(inputFile, engine); Common::DumpFile output; output.open(outputFile); output.writeUint32BE(MKTAG('R', 'I', 'F', 'F')); output.writeUint32LE(file.size() * 2 + 36); output.writeUint32BE(MKTAG('W', 'A', 'V', 'E')); output.writeUint32BE(MKTAG('f', 'm', 't', ' ')); output.writeUint32LE(16); output.writeUint16LE(1); uint16 numChannels; if (audioStream->isStereo()) { numChannels = 2; output.writeUint16LE(2); } else { numChannels = 1; output.writeUint16LE(1); } output.writeUint32LE(audioStream->getRate()); output.writeUint32LE(audioStream->getRate() * numChannels * 2); output.writeUint16LE(numChannels * 2); output.writeUint16LE(16); output.writeUint32BE(MKTAG('d', 'a', 't', 'a')); output.writeUint32LE(file.size() * 2); int16 *buffer = new int16[file.size()]; audioStream->readBuffer(buffer, file.size()); output.write(buffer, file.size() * 2); delete[] buffer; }
void ZVision::cheatCodes(uint8 key) { Location loc = _scriptManager->getCurrentLocation(); // Do not process cheat codes while in the game menus if (loc.world == 'g' && loc.room == 'j') return; pushKeyToCheatBuf(key); if (getGameId() == GID_GRANDINQUISITOR) { if (checkCode("IMNOTDEAF")) { // Unknown cheat _renderManager->showDebugMsg(Common::String::format("IMNOTDEAF cheat or debug, not implemented")); } if (checkCode("3100OPB")) { _renderManager->showDebugMsg(Common::String::format("Current location: %c%c%c%c", _scriptManager->getStateValue(StateKey_World), _scriptManager->getStateValue(StateKey_Room), _scriptManager->getStateValue(StateKey_Node), _scriptManager->getStateValue(StateKey_View))); } if (checkCode("KILLMENOW")) { _scriptManager->changeLocation('g', 'j', 'd', 'e', 0); _scriptManager->setStateValue(2201, 35); } if (checkCode("MIKESPANTS")) { _scriptManager->changeLocation('g', 'j', 't', 'm', 0); } // There are 3 more cheats in script files: // - "WHOAMI": gjcr.scr // - "HUISOK": hp1e.scr // - "EAT ME": uh1f.scr } else if (getGameId() == GID_NEMESIS) { if (checkCode("CHLOE")) { _scriptManager->changeLocation('t', 'm', '2', 'g', 0); _scriptManager->setStateValue(224, 1); } if (checkCode("77MASSAVE")) { _renderManager->showDebugMsg(Common::String::format("Current location: %c%c%c%c", _scriptManager->getStateValue(StateKey_World), _scriptManager->getStateValue(StateKey_Room), _scriptManager->getStateValue(StateKey_Node), _scriptManager->getStateValue(StateKey_View))); } if (checkCode("IDKFA")) { _scriptManager->changeLocation('t', 'w', '3', 'f', 0); _scriptManager->setStateValue(249, 1); } if (checkCode("309NEWDORMA")) { _scriptManager->changeLocation('g', 'j', 'g', 'j', 0); } if (checkCode("HELLOSAILOR")) { Audio::AudioStream *soundStream; if (loc == "vb10") { soundStream = makeRawZorkStream("v000hpta.raw", this); } else { soundStream = makeRawZorkStream("v000hnta.raw", this); } Audio::SoundHandle handle; _mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream); } } if (checkCode("FRAME")) { Common::String fpsStr = Common::String::format("FPS: %d", getFPS()); _renderManager->showDebugMsg(fpsStr); } if (checkCode("COMPUTERARCH")) _renderManager->showDebugMsg("COMPUTERARCH: var-viewer not implemented"); // This cheat essentially toggles the GOxxxx cheat below if (checkCode("XYZZY")) _scriptManager->setStateValue(StateKey_DebugCheats, 1 - _scriptManager->getStateValue(StateKey_DebugCheats)); if (_scriptManager->getStateValue(StateKey_DebugCheats) == 1) if (checkCode("GO????")) _scriptManager->changeLocation(getBufferedKey(3), getBufferedKey(2), getBufferedKey(1), getBufferedKey(0), 0); // Show the Venus screen when "?" or "/" is pressed while inside the temple world if (_scriptManager->getStateValue(StateKey_VenusEnable) == 1) if (getBufferedKey(0) == 0xBF && _scriptManager->getStateValue(StateKey_World) == 't') _scriptManager->changeLocation('g', 'j', 'h', 'e', 0); }
Audio::RewindableAudioStream *makeRawZorkStream(const byte *buffer, uint32 size, int rate, bool stereo, DisposeAfterUse::Flag disposeAfterUse) { return makeRawZorkStream(new Common::MemoryReadStream(buffer, size, disposeAfterUse), rate, stereo, DisposeAfterUse::YES); }