uint SoundChannel::play(uint soundNum, uint repeats, uint notify) { stop(); if (repeats == 0) return 1; // Find a sound of the given name Audio::AudioStream *stream; Common::File f; Common::String nameSnd = Common::String::format("sound%u.snd", soundNum); Common::String nameWav = Common::String::format("sound%u.wav", soundNum); Common::String nameAiff = Common::String::format("sound%u.aiff", soundNum); #ifdef USE_MAD Common::String nameMp3 = Common::String::format("sound%u.mp3", soundNum); #endif if (f.exists(nameSnd) && f.open(nameSnd)) { if (f.readUint16BE() != (f.size() - 2)) error("Invalid sound filesize"); repeats = f.readByte(); f.skip(1); uint freq = f.readUint16BE(); f.skip(2); uint size = f.readUint16BE(); Common::SeekableReadStream *s = f.readStream(size); stream = Audio::makeRawStream(s, freq, Audio::FLAG_UNSIGNED); #ifdef USE_MAD } else if (f.exists(nameMp3) && f.open(nameMp3)) { Common::SeekableReadStream *s = f.readStream(f.size()); stream = Audio::makeMP3Stream(s, DisposeAfterUse::YES); #endif } else if (f.exists(nameWav) && f.open(nameWav)) { Common::SeekableReadStream *s = f.readStream(f.size()); stream = Audio::makeWAVStream(s, DisposeAfterUse::YES); } else if (f.exists(nameAiff) && f.open(nameAiff)) { Common::SeekableReadStream *s = f.readStream(f.size()); stream = Audio::makeAIFFStream(s, DisposeAfterUse::YES); } else { warning("Could not find sound %u", soundNum); return 1; } _soundNum = soundNum; _notify = notify; // Set up a repeat if multiple repeats are specified if (repeats > 1) { Audio::RewindableAudioStream *rwStream = dynamic_cast<Audio::RewindableAudioStream *>(stream); assert(rwStream); stream = new Audio::LoopingAudioStream(rwStream, repeats, DisposeAfterUse::YES); } // Start playing the audio g_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, stream); return 0; }
void Music::loadSoundEffect(const Common::String filename, bool loop, bool waitTillFinished) { stopSoundEffect(); Common::File *file = _vm->_resource->openDataFile(filename, MKTAG('D', 'I', 'F', 'F')); if (!file) return; _vm->_anim->_doBlack = false; uint32 magicBytes = file->readUint32LE(); if (magicBytes != 1219009121) { warning("readSound: Bad signature, skipping"); return; } uint32 soundTag = file->readUint32LE(); uint32 soundSize = file->readUint32LE(); if (soundTag != 0) return; file->skip(soundSize); // skip the header while (soundTag != 65535) { _vm->updateEvents(); soundTag = file->readUint32LE(); soundSize = file->readUint32LE() - 8; if ((soundTag == 30) || (soundTag == 31)) { if (waitTillFinished) { while (isSoundEffectActive()) { _vm->updateEvents(); _vm->waitTOF(); } } file->skip(4); uint16 sampleRate = file->readUint16LE(); file->skip(2); playSoundEffect(sampleRate, soundSize, loop, file); } else if (soundTag == 65535) { if (waitTillFinished) { while (isSoundEffectActive()) { _vm->updateEvents(); _vm->waitTOF(); } } } else file->skip(soundSize); } }
/** * Loads the contents of the mort.dat data file */ Common::ErrorCode MortevielleEngine::loadMortDat() { Common::File f; // Open the mort.dat file if (!f.open(MORT_DAT)) { Common::String msg = Common::String::format(_("Unable to locate the '%s' engine data file."), MORT_DAT); GUIErrorMessage(msg); return Common::kReadingFailed; } // Validate the data file header char fileId[4]; f.read(fileId, 4); if (strncmp(fileId, "MORT", 4) != 0) { Common::String msg = Common::String::format(_("The '%s' engine data file is corrupt."), MORT_DAT); GUIErrorMessage(msg); return Common::kReadingFailed; } // Check the version int majVer = f.readByte(); int minVer = f.readByte(); if (majVer < MORT_DAT_REQUIRED_VERSION) { Common::String msg = Common::String::format( _("Incorrect version of the '%s' engine data file found. Expected %d.%d but got %d.%d."), MORT_DAT, MORT_DAT_REQUIRED_VERSION, 0, majVer, minVer); GUIErrorMessage(msg); return Common::kReadingFailed; } // Loop to load resources from the data file while (f.pos() < f.size()) { // Get the Id and size of the next resource char dataType[4]; int dataSize; f.read(dataType, 4); dataSize = f.readUint16LE(); if (!strncmp(dataType, "FONT", 4)) { // Font resource _screenSurface->readFontData(f, dataSize); } else if (!strncmp(dataType, "SSTR", 4)) { readStaticStrings(f, dataSize, kStaticStrings); } else if ((!strncmp(dataType, "GSTR", 4)) && (!_txxFileFl)) { readStaticStrings(f, dataSize, kGameStrings); } else if (!strncmp(dataType, "VERB", 4)) { _menu->readVerbNums(f, dataSize); } else { // Unknown section f.skip(dataSize); } } // Close the file f.close(); assert(_engineStrings.size() > 0); return Common::kNoError; }
void writeSoundNames(const char *sourceFilename, Common::File &target, uint offset) { Common::File source; if (!source.open(sourceFilename)) { error("Unable to open '%s'", sourceFilename); } source.seek(offset); // Count the sounds uint count = 0; while (1) { uint32 id = source.readUint32LE(); if (!id) break; source.skip(32); count++; } target.writeLong(count); source.seek(offset); for (uint i = 0; i < count; i++) { uint32 id = source.readUint32LE(); char name[32]; source.read(name, sizeof(name)); target.writeLong(id); target.write(name, sizeof(name)); } source.close(); }
/** * Loads the contents of the mort.dat data file */ Common::ErrorCode MortevielleEngine::loadMortDat() { Common::File f; // Open the mort.dat file if (!f.open(MORT_DAT)) { GUIErrorMessage("Could not locate 'mort.dat'."); return Common::kReadingFailed; } // Validate the data file header char fileId[4]; f.read(fileId, 4); if (strncmp(fileId, "MORT", 4) != 0) { GUIErrorMessage("The located mort.dat data file is invalid"); return Common::kReadingFailed; } // Check the version if (f.readByte() < MORT_DAT_REQUIRED_VERSION) { GUIErrorMessage("The located mort.dat data file is too old, please download an updated version on scummvm.org"); return Common::kReadingFailed; } f.readByte(); // Minor version // Loop to load resources from the data file while (f.pos() < f.size()) { // Get the Id and size of the next resource char dataType[4]; int dataSize; f.read(dataType, 4); dataSize = f.readUint16LE(); if (!strncmp(dataType, "FONT", 4)) { // Font resource _screenSurface.readFontData(f, dataSize); } else if (!strncmp(dataType, "SSTR", 4)) { readStaticStrings(f, dataSize, kStaticStrings); } else if ((!strncmp(dataType, "GSTR", 4)) && (!_txxFileFl)) { readStaticStrings(f, dataSize, kGameStrings); } else if (!strncmp(dataType, "VERB", 4)) { _menu.readVerbNums(f, dataSize); } else { // Unknown section f.skip(dataSize); } } // Close the file f.close(); assert(_engineStrings.size() > 0); return Common::kNoError; }
/** * Read in a static strings block, and if the language matches, load up the static strings */ void MortevielleEngine::readStaticStrings(Common::File &f, int dataSize, DataType dataType) { // Figure out what language Id is needed byte desiredLanguageId; switch(getLanguage()) { case Common::EN_ANY: desiredLanguageId = MORTDAT_LANG_ENGLISH; break; case Common::FR_FRA: desiredLanguageId = MORTDAT_LANG_FRENCH; break; case Common::DE_DEU: desiredLanguageId = MORTDAT_LANG_GERMAN; break; default: warning("Language not supported, switching to English"); desiredLanguageId = MORTDAT_LANG_ENGLISH; break; } // Read in the language byte languageId = f.readByte(); --dataSize; // If the language isn't correct, then skip the entire block if (languageId != desiredLanguageId) { f.skip(dataSize); return; } // Load in each of the strings while (dataSize > 0) { Common::String s; char ch; while ((ch = (char)f.readByte()) != '\0') s += ch; if (dataType == kStaticStrings) _engineStrings.push_back(s); else if (dataType == kGameStrings) _gameStrings.push_back(s); dataSize -= s.size() + 1; } assert(dataSize == 0); }
Font::Font(Common::String filename) { const uint32 headerFont = MKTAG('T', 'F', 'F', '\0'); Common::File stream; stream.open(filename); uint32 header = stream.readUint32BE(); if (header != headerFont) error("Invalid resource - %s", filename.c_str()); stream.skip(4); // total memory _count = stream.readUint16LE(); _first = stream.readUint16LE(); _last = stream.readUint16LE(); _width = stream.readUint16LE(); _height = stream.readUint16LE(); _fontSurface.create(_width * _count, _height, ::Graphics::PixelFormat::createFormatCLUT8()); byte cur; int bitIndex = 7; byte *p; cur = stream.readByte(); for (uint n = 0; n < _count; n++) { for (uint y = 0; y < _height; y++) { p = (byte *)_fontSurface.getBasePtr(n * _width, y); for (uint x = n * _width; x < n * _width + _width; x++) { *p++ = (cur & (1 << bitIndex)) ? 0 : 0xFF; bitIndex--; if (bitIndex < 0) { bitIndex = 7; cur = stream.readByte(); } } } } }
TextFont *Resource::getFont(const Common::String fileName) { // TODO: Add support for the font format of the Amiga version Common::File *dataFile = openDataFile(fileName, MKTAG('V', 'G', 'A', 'F')); uint32 headerSize = 4 + 2 + 256 * 3 + 4; uint32 fileSize = dataFile->size(); if (fileSize <= headerSize) return nullptr; TextFont *textfont = new TextFont(); textfont->_dataLength = fileSize - headerSize; textfont->_height = dataFile->readUint16LE(); dataFile->read(textfont->_widths, 256); for (int i = 0; i < 256; i++) textfont->_offsets[i] = dataFile->readUint16LE(); dataFile->skip(4); textfont->_data = new byte[textfont->_dataLength + 4]; dataFile->read(textfont->_data, textfont->_dataLength); delete dataFile; return textfont; }
void TopMenu::loadBmpArr(Common::File &in) { arraySize = in.readUint16BE(); delete arrayBmp; arrayBmp = new Graphics::Surface *[arraySize * 2]; for (int i = 0; i < arraySize; i++) { uint16 bmpSize = in.readUint16BE(); uint32 filPos = in.pos(); Common::SeekableSubReadStream stream(&in, filPos, filPos + bmpSize); arrayBmp[i * 2] = Graphics::ImageDecoder::loadFile(stream, g_system->getOverlayFormat()); arrayBmp[i * 2 + 1] = new Graphics::Surface(); arrayBmp[i * 2 + 1]->create(arrayBmp[i * 2]->w * 2, arrayBmp[i * 2]->h * 2, arrayBmp[i * 2]->bytesPerPixel); byte *src = (byte *)arrayBmp[i * 2]->pixels; byte *dst = (byte *)arrayBmp[i * 2 + 1]->pixels; for (int j = 0; j < arrayBmp[i * 2]->h; j++) { src = (byte *)arrayBmp[i * 2]->getBasePtr(0, j); dst = (byte *)arrayBmp[i * 2 + 1]->getBasePtr(0, j * 2); for (int k = arrayBmp[i * 2]->w; k > 0; k--) { for (int m = arrayBmp[i * 2]->bytesPerPixel; m > 0; m--) { *dst++ = *src++; } src -= arrayBmp[i * 2]->bytesPerPixel; for (int m = arrayBmp[i * 2]->bytesPerPixel; m > 0; m--) { *dst++ = *src++; } } src = (byte *)arrayBmp[i * 2 + 1]->getBasePtr(0, j * 2); dst = (byte *)arrayBmp[i * 2 + 1]->getBasePtr(0, j * 2 + 1); for (int k = arrayBmp[i * 2 + 1]->pitch; k > 0; k--) { *dst++ = *src++; } } in.skip(bmpSize); } }
/** * Draw background animation * @remarks Originally called 'show_one' */ void Background::draw(int16 destX, int16 destY, byte sprId) { assert(sprId < 40); if (_sprites[sprId]._x > kOnDisk) { if (destX < 0) { destX = _sprites[sprId]._x * 8; destY = _sprites[sprId]._y; } drawSprite(destX, destY, _sprites[sprId]); } else { Common::File f; if (!f.open(_filename)) // Filename was set in loadBackgroundSprites(). return; // We skip because some rooms don't have sprites in the background. f.seek(_offsets[sprId]); SpriteType sprite; sprite._type = (PictureType)(f.readByte()); sprite._x = f.readSint16LE(); sprite._y = f.readSint16LE(); sprite._width = f.readSint16LE(); sprite._height = f.readSint16LE(); sprite._size = f.readSint32LE(); f.skip(2); // Natural and Memorize are used in Load() sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._width * 8, sprite._height + 1); if (destX < 0) { destX = sprite._x * 8; destY = sprite._y; } drawSprite(destX, destY, sprite); sprite._picture.free(); f.close(); } }
InstallShieldCabinet::InstallShieldCabinet(const Common::String &filename) : _installShieldFilename(filename) { Common::File installShieldFile; if (!installShieldFile.open(_installShieldFilename)) { warning("InstallShieldCabinet::InstallShieldCabinet(): Could not find the archive file %s", _installShieldFilename.c_str()); return; } // Note that we only support a limited subset of cabinet files // Only single cabinet files and ones without data shared between // cabinets. // Check for the magic uint32 if (installShieldFile.readUint32LE() != 0x28635349) { warning("InstallShieldCabinet::InstallShieldCabinet(): Magic ID doesn't match"); return; } uint32 version = installShieldFile.readUint32LE(); if (version != 0x01000004) { warning("Unsupported CAB version %08x", version); return; } /* uint32 volumeInfo = */ installShieldFile.readUint32LE(); uint32 cabDescriptorOffset = installShieldFile.readUint32LE(); /* uint32 cabDescriptorSize = */ installShieldFile.readUint32LE(); installShieldFile.seek(cabDescriptorOffset); installShieldFile.skip(12); uint32 fileTableOffset = installShieldFile.readUint32LE(); installShieldFile.skip(4); uint32 fileTableSize = installShieldFile.readUint32LE(); uint32 fileTableSize2 = installShieldFile.readUint32LE(); uint32 directoryCount = installShieldFile.readUint32LE(); installShieldFile.skip(8); uint32 fileCount = installShieldFile.readUint32LE(); if (fileTableSize != fileTableSize2) warning("file table sizes do not match"); // We're ignoring file groups and components since we // should not need them. Moving on to the files... installShieldFile.seek(cabDescriptorOffset + fileTableOffset); uint32 fileTableCount = directoryCount + fileCount; uint32 *fileTableOffsets = new uint32[fileTableCount]; for (uint32 i = 0; i < fileTableCount; i++) fileTableOffsets[i] = installShieldFile.readUint32LE(); for (uint32 i = directoryCount; i < fileCount + directoryCount; i++) { installShieldFile.seek(cabDescriptorOffset + fileTableOffset + fileTableOffsets[i]); uint32 nameOffset = installShieldFile.readUint32LE(); /* uint32 directoryIndex = */ installShieldFile.readUint32LE(); // First read in data needed by us to get at the file data FileEntry entry; entry.flags = installShieldFile.readUint16LE(); entry.uncompressedSize = installShieldFile.readUint32LE(); entry.compressedSize = installShieldFile.readUint32LE(); installShieldFile.skip(20); entry.offset = installShieldFile.readUint32LE(); // Then let's get the string installShieldFile.seek(cabDescriptorOffset + fileTableOffset + nameOffset); Common::String fileName; char c = installShieldFile.readByte(); while (c) { fileName += c; c = installShieldFile.readByte(); } _map[fileName] = entry; } delete[] fileTableOffsets; }
ADDetectedGame DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { // TODO: Handle Mac fallback // reset fallback description Director::DirectorGameDescription *desc = &s_fallbackDesc; desc->desc.gameId = "director"; desc->desc.extra = ""; desc->desc.language = Common::UNK_LANG; desc->desc.flags = ADGF_NO_FLAGS; desc->desc.platform = Common::kPlatformWindows; desc->desc.guiOptions = GUIO0(); desc->desc.filesDescriptions[0].fileName = 0; desc->version = 0; desc->gameID = Director::GID_GENERIC; for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) continue; Common::String fileName = file->getName(); fileName.toLowercase(); if (!fileName.hasSuffix(".exe")) continue; Common::File f; if (!f.open(*file)) continue; f.seek(-4, SEEK_END); uint32 offset = f.readUint32LE(); if (f.eos() || offset == 0 || offset >= (uint32)(f.size() - 4)) continue; f.seek(offset); uint32 tag = f.readUint32LE(); switch (tag) { case MKTAG('3', '9', 'J', 'P'): desc->version = 4; break; case MKTAG('P', 'J', '9', '5'): desc->version = 5; break; case MKTAG('P', 'J', '0', '0'): desc->version = 7; break; default: // Prior to version 4, there was no tag here. So we'll use a bit of a // heuristic to detect. The first field is the entry count, of which // there should only be one. if ((tag & 0xFFFF) != 1) continue; f.skip(3); uint32 mmmSize = f.readUint32LE(); if (f.eos() || mmmSize == 0) continue; byte fileNameSize = f.readByte(); if (f.eos()) continue; f.skip(fileNameSize); byte directoryNameSize = f.readByte(); if (f.eos()) continue; f.skip(directoryNameSize); if (f.pos() != f.size() - 4) continue; // Assume v3 at this point (for now at least) desc->version = 3; } strncpy(s_fallbackFileNameBuffer, fileName.c_str(), 50); s_fallbackFileNameBuffer[50] = '\0'; desc->desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer; warning("Director fallback detection D%d", desc->version); return ADDetectedGame(&desc->desc); } return ADDetectedGame(); }
/** * Opens and inits all MIDI sequence files. */ void OpenMidiFiles() { Common::File midiStream; if (TinselV0) { // The early demo version of DW1 doesn't have MIDI } else if (TinselV2) { // DW2 uses a different music mechanism } else if (TinselV1Mac) { // open MIDI sequence file in binary mode if (!midiStream.open(MIDI_FILE)) error(CANNOT_FIND_FILE, MIDI_FILE); uint32 curTrack = 1; uint32 songLength = 0; int32 fileSize = midiStream.size(); // Init for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++) g_midiOffsets[i] = 0; midiStream.skip(4); // skip file header while (!midiStream.eos() && !midiStream.err() && midiStream.pos() != fileSize) { assert(curTrack < ARRAYSIZE(g_midiOffsets)); g_midiOffsets[curTrack] = midiStream.pos(); //debug("%d: %d", curTrack, g_midiOffsets[curTrack]); songLength = midiStream.readUint32BE(); midiStream.skip(songLength); curTrack++; } midiStream.close(); } else { if (g_midiBuffer.pDat) // already allocated return; // open MIDI sequence file in binary mode if (!midiStream.open(MIDI_FILE)) error(CANNOT_FIND_FILE, MIDI_FILE); // get length of the largest sequence g_midiBuffer.size = midiStream.readUint32LE(); if (midiStream.eos() || midiStream.err()) error(FILE_IS_CORRUPT, MIDI_FILE); if (g_midiBuffer.size) { // allocate a buffer big enough for the largest MIDI sequence if ((g_midiBuffer.pDat = (uint8 *)malloc(g_midiBuffer.size)) != NULL) { // clear out the buffer memset(g_midiBuffer.pDat, 0, g_midiBuffer.size); } } // Now scan through the contents of the MIDI file to find the offset // of each individual track, in order to create a mapping from MIDI // offset to track number, for the enhanced MIDI soundtrack. // The first song is always at position 4. The subsequent ones are // calculated dynamically. uint32 curOffset = 4; uint32 curTrack = 0; uint32 songLength = 0; // Init for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++) g_midiOffsets[i] = 0; while (!midiStream.eos() && !midiStream.err()) { if (curOffset + (4 * curTrack) >= (uint32)midiStream.size()) break; assert(curTrack < ARRAYSIZE(g_midiOffsets)); g_midiOffsets[curTrack] = curOffset + (4 * curTrack); //debug("%d: %d", curTrack, midiOffsets[curTrack]); songLength = midiStream.readUint32LE(); curOffset += songLength; midiStream.skip(songLength); curTrack++; } midiStream.close(); } }
/** * Play Sequence type 2 */ void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) { byte *screenP; int frameNumber; Common::File f; for (;;) { if (_vm->shouldQuit()) return; _vm->_events->_mouseFl = false; screenP = _vm->_graphicsMan->_backBuffer; if (!f.open(file)) error("File not found - %s", file.c_str()); f.skip(6); f.read(_vm->_graphicsMan->_palette, 800); f.skip(4); size_t nbytes = f.readUint32LE(); f.skip(14); f.read(screenP, nbytes); if (skipSeqFl) { _vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette); } else { _vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette); _vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); } _vm->_events->_rateCounter = 0; _vm->_events->_escKeyFl = false; _vm->_soundMan->loadAnimSound(); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { do { _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } while (!_vm->shouldQuit() && !_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate1); } break; } if (!_vm->_events->_escKeyFl) { _vm->_events->_rateCounter = 0; frameNumber = 0; while (!_vm->shouldQuit()) { _vm->_soundMan->playAnimSound(frameNumber++); byte imageStr[17]; if (f.read(imageStr, 16) != 16) break; imageStr[16] = 0; if (strncmp((const char *)imageStr, "IMAGE=", 6)) break; f.read(screenP, READ_LE_UINT32(imageStr + 8)); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { do { _vm->_events->refreshEvents(); } while (!_vm->shouldQuit() && !_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate2); } _vm->_events->_rateCounter = 0; if (*screenP != kByteStop) _vm->_graphicsMan->copyVideoVbe16a(screenP); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); _vm->_soundMan->checkSoundEnd(); } } if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { // Wait for third rate delay do { _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } while (!_vm->shouldQuit() && !_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate3); } _vm->_events->_rateCounter = 0; if (_vm->_graphicsMan->_fadingFl) { byte *ptra = _vm->_globals->allocMemory(307200); f.seek(6); f.read(_vm->_graphicsMan->_palette, 800); f.skip(4); size_t nbytes = f.readUint32LE(); f.skip(14); f.read(screenP, nbytes); memcpy(ptra, screenP, 307200); for (;;) { byte imageStr[17]; if (f.read(imageStr, 16) != 16) break; imageStr[16] = 0; if (strncmp((const char *)imageStr, "IMAGE=", 6)) break; f.read(screenP, READ_LE_UINT32(imageStr + 8)); if (*screenP != kByteStop) _vm->_graphicsMan->copyWinscanVbe(screenP, ptra); } _vm->_graphicsMan->fadeOutDefaultLength(ptra); ptra = _vm->_globals->freeMemory(ptra); } _vm->_graphicsMan->_fadingFl = false; f.close(); _vm->_events->_mouseFl = true; }
/** * Play Animation * @param filename Filename of animation to play * @param rate1 Delay amount before starting animation * @param rate2 Delay amount between animation frames * @param rate3 Delay amount after animation finishes */ void AnimationManager::playAnim(const Common::String &filename, uint32 rate1, uint32 rate2, uint32 rate3, bool skipSeqFl) { Common::File f; if (_vm->shouldQuit()) return; _vm->_events->mouseOff(); byte *screenP = _vm->_graphicsMan->_backBuffer; Common::String tmpStr; // The Windows 95 demo only contains the interlaced version of the BOMBE1 and BOMBE2 videos if (_vm->getPlatform() == Common::kPlatformWindows && _vm->getIsDemo() && filename == "BOMBE1A.ANM") tmpStr = "BOMBE1.ANM"; else if (_vm->getPlatform() == Common::kPlatformWindows && _vm->getIsDemo() && filename == "BOMBE2A.ANM") tmpStr = "BOMBE2.ANM"; else tmpStr = filename; if (!f.open(tmpStr)) error("File not found - %s", tmpStr.c_str()); f.skip(6); f.read(_vm->_graphicsMan->_palette, 800); f.skip(4); size_t nbytes = f.readUint32LE(); f.skip(14); f.read(screenP, nbytes); if (_clearAnimationFl) _vm->_graphicsMan->clearScreen(); if (skipSeqFl) { _vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette); } else { _vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette); _vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); } _vm->_events->_rateCounter = 0; _vm->_events->_escKeyFl = false; _vm->_soundMan->loadAnimSound(); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { // Do pre-animation delay do { if (_vm->_events->_escKeyFl) break; _vm->_events->refreshEvents(); } while (!_vm->shouldQuit() && _vm->_events->_rateCounter < rate1); } if (!_vm->_events->_escKeyFl) { _vm->_events->_rateCounter = 0; int frameNumber = 0; while (!_vm->shouldQuit()) { ++frameNumber; _vm->_soundMan->playAnimSound(frameNumber); byte imageStr[17]; // Read frame header if (f.read(imageStr, 16) != 16) break; imageStr[16] = 0; if (strncmp((const char *)imageStr, "IMAGE=", 6)) break; f.read(screenP, READ_LE_UINT32(imageStr + 8)); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { do { if (_vm->_events->_escKeyFl) break; _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } while (!_vm->shouldQuit() && _vm->_events->_rateCounter < rate2); } if (!_vm->_events->_escKeyFl) { _vm->_events->_rateCounter = 0; if (*screenP != kByteStop) _vm->_graphicsMan->copyVideoVbe16(screenP); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); _vm->_soundMan->checkSoundEnd(); } } } if (_vm->_globals->_eventMode == EVENTMODE_IGNORE && !_vm->_events->_escKeyFl) { // Do post-animation delay do { if (_vm->_events->_escKeyFl) break; _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } while (_vm->_events->_rateCounter < rate3); } if (!_vm->_events->_escKeyFl) { _vm->_events->_rateCounter = 0; _vm->_soundMan->checkSoundEnd(); } if (_vm->_graphicsMan->_fadingFl) { byte *screenCopy = _vm->_globals->allocMemory(307200); f.seek(6); f.read(_vm->_graphicsMan->_palette, 800); f.skip(4); nbytes = f.readUint32LE(); f.skip(14); f.read(screenP, nbytes); memcpy(screenCopy, screenP, 307200); for (;;) { byte imageStr[17]; if (f.read(imageStr, 16) != 16) break; imageStr[16] = 0; if (strncmp((const char *)imageStr, "IMAGE=", 6)) break; f.read(screenP, READ_LE_UINT32(imageStr + 8)); if (*screenP != kByteStop) _vm->_graphicsMan->copyWinscanVbe3(screenP, screenCopy); } _vm->_graphicsMan->fadeOutDefaultLength(screenCopy); _vm->_globals->freeMemory(screenCopy); } _vm->_graphicsMan->_fadingFl = false; f.close(); _vm->_graphicsMan->_skipVideoLockFl = false; _vm->_events->mouseOn(); }
/** * Play sequence */ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, uint32 rate2, uint32 rate3, bool skipEscFl, bool skipSeqFl, bool noColFl) { if (_vm->shouldQuit()) return; _vm->_events->_mouseFl = false; if (!noColFl) { _vm->_events->refreshScreenAndEvents(); _vm->_graphicsMan->backupScreen(); if (!_vm->_graphicsMan->_lineNbr) _vm->_graphicsMan->_scrollOffset = 0; } byte *screenP = _vm->_graphicsMan->_backBuffer; Common::File f; if (!f.open(file)) error("Error opening file - %s", file.c_str()); f.skip(6); f.read(_vm->_graphicsMan->_palette, 800); f.skip(4); size_t nbytes = f.readUint32LE(); f.skip(14); f.read(screenP, nbytes); if (skipSeqFl) { if (!_vm->getIsDemo()) { _vm->_graphicsMan->setColorPercentage(252, 100, 100, 100); _vm->_graphicsMan->setColorPercentage(253, 100, 100, 100); _vm->_graphicsMan->setColorPercentage(251, 100, 100, 100); _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0); } _vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette); } else { _vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); } bool skipFl = false; if (noColFl) _vm->_graphicsMan->fadeInDefaultLength(screenP); _vm->_events->_rateCounter = 0; _vm->_events->_escKeyFl = false; _vm->_soundMan->loadAnimSound(); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { do { if (_vm->shouldQuit() || (_vm->_events->_escKeyFl && !skipEscFl)) { skipFl = true; break; } _vm->_events->_escKeyFl = false; _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } while (_vm->_events->_rateCounter < rate1); } _vm->_events->_rateCounter = 0; if (!skipFl) { int soundNumber = 0; for (;;) { ++soundNumber; _vm->_soundMan->playAnimSound(soundNumber); byte imageStr[17]; if (f.read(imageStr, 16) != 16) break; imageStr[16] = 0; if (strncmp((const char *)imageStr, "IMAGE=", 6)) break; f.read(screenP, READ_LE_UINT32(imageStr + 8)); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { do { if (_vm->shouldQuit() || (_vm->_events->_escKeyFl && !skipEscFl)) { skipFl = true; break; } _vm->_events->_escKeyFl = false; _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } while (_vm->_events->_rateCounter < rate2); } if (skipFl) break; _vm->_events->_rateCounter = 0; if (*screenP != kByteStop) _vm->_graphicsMan->copyVideoVbe16a(screenP); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); _vm->_soundMan->checkSoundEnd(); } } if (_vm->_globals->_eventMode == EVENTMODE_IGNORE && !skipFl) { do { if (_vm->shouldQuit() || (_vm->_events->_escKeyFl && !skipEscFl)) { skipFl = true; break; } _vm->_events->_escKeyFl = false; _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } while (_vm->_events->_rateCounter < rate3); } if (!skipFl) _vm->_events->_rateCounter = 0; _vm->_graphicsMan->_skipVideoLockFl = false; f.close(); if (!noColFl) { _vm->_graphicsMan->restoreScreen(); _vm->_events->_mouseFl = true; } }
/** * Play Animation, type 2 */ void AnimationManager::playAnim2(const Common::String &filename, uint32 rate1, uint32 rate2, uint32 rate3) { int oldScrollPosX = 0; byte *screenP = NULL; Common::File f; if (_vm->shouldQuit()) return; _vm->_events->mouseOff(); while (!_vm->shouldQuit()) { memcpy(_vm->_graphicsMan->_oldPalette, _vm->_graphicsMan->_palette, 769); _vm->_graphicsMan->backupScreen(); if (!_vm->_graphicsMan->_lineNbr) _vm->_graphicsMan->_scrollOffset = 0; screenP = _vm->_graphicsMan->_backBuffer; if (!f.open(filename)) error("Error opening file - %s", filename.c_str()); f.skip(6); f.read(_vm->_graphicsMan->_palette, 800); f.skip(4); size_t nbytes = f.readUint32LE(); f.skip(14); f.read(screenP, nbytes); _vm->_graphicsMan->clearPalette(); oldScrollPosX = _vm->_graphicsMan->_scrollPosX; _vm->_graphicsMan->setScreenWidth(SCREEN_WIDTH); _vm->_graphicsMan->scrollScreen(0); _vm->_graphicsMan->clearScreen(); _vm->_graphicsMan->_maxX = SCREEN_WIDTH; _vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette); _vm->_graphicsMan->display8BitRect(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); _vm->_events->_rateCounter = 0; _vm->_events->_escKeyFl = false; _vm->_soundMan->loadAnimSound(); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { while (!_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate1) { _vm->_events->refreshEvents(); } } break; } if (!_vm->_events->_escKeyFl) { _vm->_events->_rateCounter = 0; int frameNumber = 0; for (;;) { if (_vm->_events->_escKeyFl) break; ++frameNumber; _vm->_soundMan->playAnimSound(frameNumber); byte imageStr[17]; if (f.read(imageStr, 16) != 16) break; imageStr[16] = 0; if (strncmp((const char *)imageStr, "IMAGE=", 6)) break; f.read(screenP, READ_LE_UINT32(imageStr + 8)); if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { while (!_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate2) { _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } } _vm->_events->_rateCounter = 0; if (*screenP != kByteStop) _vm->_graphicsMan->copyVideoVbe16(screenP); _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->updateScreen(); _vm->_soundMan->checkSoundEnd(); } if (_vm->_globals->_eventMode == EVENTMODE_IGNORE) { while (!_vm->_events->_escKeyFl && _vm->_events->_rateCounter < rate3) { _vm->_events->refreshEvents(); _vm->_soundMan->checkSoundEnd(); } } } _vm->_graphicsMan->_skipVideoLockFl = false; f.close(); if (_vm->_graphicsMan->_fadingFl) { f.seek(6); f.read(_vm->_graphicsMan->_palette, 800); f.skip(4); size_t nbytes = f.readUint32LE(); f.skip(14); f.read(screenP, nbytes); byte *ptra = _vm->_globals->allocMemory(307200); memcpy(ptra, screenP, 307200); for (;;) { byte imageStr[17]; if (f.read(imageStr, 16) != 16) break; imageStr[16] = 0; if (strncmp((const char *)imageStr, "IMAGE=", 6)) break; f.read(screenP, READ_LE_UINT32(imageStr + 8)); if (*screenP != kByteStop) _vm->_graphicsMan->copyWinscanVbe3(screenP, ptra); } _vm->_graphicsMan->fadeOutDefaultLength(ptra); ptra = _vm->_globals->freeMemory(ptra); } _vm->_graphicsMan->_fadingFl = false; _vm->_graphicsMan->restoreScreen(); memcpy(_vm->_graphicsMan->_palette, _vm->_graphicsMan->_oldPalette, 769); _vm->_graphicsMan->clearPalette(); _vm->_graphicsMan->clearScreen(); _vm->_graphicsMan->_scrollPosX = oldScrollPosX; _vm->_graphicsMan->scrollScreen(oldScrollPosX); if (_vm->_graphicsMan->_largeScreenFl) { _vm->_graphicsMan->setScreenWidth(2 * SCREEN_WIDTH); _vm->_graphicsMan->_maxX = 2 * SCREEN_WIDTH; _vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_frontBuffer, _vm->_events->_startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); } else { _vm->_graphicsMan->setScreenWidth(SCREEN_WIDTH); _vm->_graphicsMan->_maxX = SCREEN_WIDTH; _vm->_graphicsMan->clearScreen(); _vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_frontBuffer, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); } _vm->_graphicsMan->addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsMan->fadeInShort(); _vm->_graphicsMan->updateScreen(); _vm->_events->mouseOn(); }
/** * Opens and inits all MIDI sequence files. */ void OpenMidiFiles() { Common::File midiStream; // Demo version has no midi file // Also, Discworld PSX uses still unsupported psx SEQ format for music... if ((_vm->getFeatures() & GF_DEMO) || (TinselVersion == TINSEL_V2) || TinselV1PSX) return; if (midiBuffer.pDat) // already allocated return; // open MIDI sequence file in binary mode if (!midiStream.open(MIDI_FILE)) error(CANNOT_FIND_FILE, MIDI_FILE); // gen length of the largest sequence midiBuffer.size = midiStream.readUint32LE(); if (midiStream.eos() || midiStream.err()) error(FILE_IS_CORRUPT, MIDI_FILE); if (midiBuffer.size) { // allocate a buffer big enough for the largest MIDI sequence if ((midiBuffer.pDat = (uint8 *)malloc(midiBuffer.size)) != NULL) { // clear out the buffer memset(midiBuffer.pDat, 0, midiBuffer.size); // VMM_lock(midiBuffer.pDat, midiBuffer.size); } else { //mSeqHandle = NULL; } } // Now scan through the contents of the MIDI file to find the offset // of each individual track, in order to create a mapping from MIDI // offset to track number, for the enhanced MIDI soundtrack. // The first song is always at position 4. The subsequent ones are // calculated dynamically. uint32 curOffset = 4; uint32 curTrack = 0; uint32 songLength = 0; // Init for (int i = 0; i < ARRAYSIZE(midiOffsets); i++) midiOffsets[i] = 0; while (!midiStream.eos() && !midiStream.err()) { if (curOffset + (4 * curTrack) >= (uint32)midiStream.size()) break; assert(curTrack < ARRAYSIZE(midiOffsets)); midiOffsets[curTrack] = curOffset + (4 * curTrack); //debug("%d: %d", curTrack, midiOffsets[curTrack]); songLength = midiStream.readUint32LE(); curOffset += songLength; midiStream.skip(songLength); curTrack++; } midiStream.close(); }
void Menu::readVerbNums(Common::File &f, int dataSize) { // Figure out what language Id is needed byte desiredLanguageId; switch(_vm->getLanguage()) { case Common::EN_ANY: desiredLanguageId = MORTDAT_LANG_ENGLISH; break; case Common::FR_FRA: desiredLanguageId = MORTDAT_LANG_FRENCH; break; case Common::DE_DEU: desiredLanguageId = MORTDAT_LANG_GERMAN; break; default: warning("Language not supported, switching to English"); desiredLanguageId = MORTDAT_LANG_ENGLISH; break; } // Read in the language byte languageId = f.readByte(); --dataSize; // If the language isn't correct, then skip the entire block if (languageId != desiredLanguageId) { f.skip(dataSize); return; } assert(dataSize == 52); _opcodeAttach = f.readUint16LE(); _opcodeWait = f.readUint16LE(); _opcodeForce = f.readUint16LE(); _opcodeSleep = f.readUint16LE(); _opcodeListen = f.readUint16LE(); _opcodeEnter = f.readUint16LE(); _opcodeClose = f.readUint16LE(); _opcodeSearch = f.readUint16LE(); _opcodeKnock = f.readUint16LE(); _opcodeScratch = f.readUint16LE(); _opcodeRead = f.readUint16LE(); _opcodeEat = f.readUint16LE(); _opcodePlace = f.readUint16LE(); _opcodeOpen = f.readUint16LE(); _opcodeTake = f.readUint16LE(); _opcodeLook = f.readUint16LE(); _opcodeSmell = f.readUint16LE(); _opcodeSound = f.readUint16LE(); _opcodeLeave = f.readUint16LE(); _opcodeLift = f.readUint16LE(); _opcodeTurn = f.readUint16LE(); _opcodeSHide = f.readUint16LE(); _opcodeSSearch = f.readUint16LE(); _opcodeSRead = f.readUint16LE(); _opcodeSPut = f.readUint16LE(); _opcodeSLook = f.readUint16LE(); _actionMenu[0]._menuId = OPCODE_NONE >> 8; _actionMenu[0]._actionId = OPCODE_NONE & 0xFF; _actionMenu[1]._menuId = _opcodeSHide >> 8; _actionMenu[1]._actionId = _opcodeSHide & 0xFF; _actionMenu[2]._menuId = _opcodeAttach >> 8; _actionMenu[2]._actionId = _opcodeAttach & 0xFF; _actionMenu[3]._menuId = _opcodeForce >> 8; _actionMenu[3]._actionId = _opcodeForce & 0xFF; _actionMenu[4]._menuId = _opcodeSleep >> 8; _actionMenu[4]._actionId = _opcodeSleep & 0xFF; _actionMenu[5]._menuId = _opcodeEnter >> 8; _actionMenu[5]._actionId = _opcodeEnter & 0xFF; _actionMenu[6]._menuId = _opcodeClose >> 8; _actionMenu[6]._actionId = _opcodeClose & 0xFF; _actionMenu[7]._menuId = _opcodeKnock >> 8; _actionMenu[7]._actionId = _opcodeKnock & 0xFF; _actionMenu[8]._menuId = _opcodeEat >> 8; _actionMenu[8]._actionId = _opcodeEat & 0xFF; _actionMenu[9]._menuId = _opcodePlace >> 8; _actionMenu[9]._actionId = _opcodePlace & 0xFF; _actionMenu[10]._menuId = _opcodeOpen >> 8; _actionMenu[10]._actionId = _opcodeOpen & 0xFF; _actionMenu[11]._menuId = _opcodeLeave >> 8; _actionMenu[11]._actionId = _opcodeLeave & 0xFF; }