void Model::loadEMI(Common::MemoryReadStream &ms) { char name[64]; int nameLength = ms.readUint32LE(); assert(nameLength < 64); ms.read(name, nameLength); // skip over some unkown floats ms.seek(48, SEEK_CUR); _numMaterials = ms.readUint32LE(); _materials = new Material*[_numMaterials]; _materialNames = new char[_numMaterials][32]; for (int i = 0; i < _numMaterials; i++) { nameLength = ms.readUint32LE(); assert(nameLength < 32); ms.read(_materialNames[i], nameLength); // I'm not sure what specialty mateials are, but they are handled differently. if (memcmp(_materialNames[i], "specialty", 9) == 0) { _materials[i] = 0; } else { loadMaterial(i, 0); } ms.seek(4, SEEK_CUR); } ms.seek(4, SEEK_CUR); }
bool Node::dumpFaceMask(uint16 index, int face, DirectorySubEntry::ResourceType type) { static const int32 kMaskSize = 640 * 640; byte *mask = new byte[kMaskSize]; memset(mask, 0, kMaskSize); uint32 headerOffset = 0; uint32 dataOffset = 0; const DirectorySubEntry *maskDesc = _vm->getFileDescription(0, index, face, type); if (!maskDesc) { delete[] mask; return false; } Common::MemoryReadStream *maskStream = maskDesc->getData(); while (headerOffset < 400) { int blockX = (headerOffset / sizeof(dataOffset)) % 10; int blockY = (headerOffset / sizeof(dataOffset)) / 10; maskStream->seek(headerOffset, SEEK_SET); dataOffset = maskStream->readUint32LE(); headerOffset = maskStream->pos(); if (dataOffset != 0) { maskStream->seek(dataOffset, SEEK_SET); for(int i = 63; i >= 0; i--) { int x = 0; byte numValues = maskStream->readByte(); for (int j = 0; j < numValues; j++) { byte repeat = maskStream->readByte(); byte value = maskStream->readByte(); for (int k = 0; k < repeat; k++) { mask[((blockY * 64) + i) * 640 + blockX * 64 + x] = value; x++; } } } } } delete maskStream; Common::DumpFile outFile; outFile.open(Common::String::format("dump/%d-%d.masku_%d", index, face, type)); outFile.write(mask, kMaskSize); outFile.close(); delete[] mask; return true; }
void AnimationResource::load(byte *source, int size) { Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); sourceS->readUint32LE(); sourceS->readUint32LE(); sourceS->readUint16LE(); _flags = sourceS->readUint16LE(); _width = sourceS->readUint16LE(); _height = sourceS->readUint16LE(); sourceS->readUint32LE(); uint16 frameCount = sourceS->readUint16LE(); sourceS->readUint16LE(); sourceS->readUint16LE(); for (uint16 i = 0; i < frameCount; i++) { sourceS->seek(26 + i * 4); uint32 frameOffs = sourceS->readUint32LE(); sourceS->seek(frameOffs); sourceS->readUint32LE(); sourceS->readUint32LE(); uint16 frameWidth = sourceS->readUint16LE(); uint16 frameHeight = sourceS->readUint16LE(); uint16 cmdOffs = sourceS->readUint16LE(); sourceS->readUint16LE(); uint16 pixelOffs = sourceS->readUint16LE(); sourceS->readUint16LE(); uint16 maskOffs = sourceS->readUint16LE(); sourceS->readUint16LE(); uint16 lineSize = sourceS->readUint16LE(); Graphics::Surface *frame = new Graphics::Surface(); frame->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8()); decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, 0, 0, 0, _flags & 1); _frames.push_back(frame); } delete sourceS; }
void Sound::playMovieSound(int32 res, int type) { Audio::SoundHandle *handle; if (type == kLeadInSound) handle = &_leadInHandle; else handle = &_leadOutHandle; if (_vm->_mixer->isSoundHandleActive(*handle)) { _vm->_mixer->stopHandle(*handle); } byte *data = _vm->_resman->openResource(res); uint32 len = _vm->_resman->fetchLen(res); assert(_vm->_resman->fetchType(data) == WAV_FILE); // We want to close the resource right away, so to be safe we make a // private copy of the sound; byte *soundData = (byte *)malloc(len); if (soundData) { memcpy(soundData, data, len); Common::MemoryReadStream *stream = new Common::MemoryReadStream(soundData, len, DisposeAfterUse::YES); // In PSX version we have nothing to skip here, as data starts // right away. if (!Sword2Engine::isPsx()) { stream->seek(ResHeader::size()); } Audio::RewindableAudioStream *input = 0; if (Sword2Engine::isPsx()) { input = Audio::makeVagStream(stream); } else { input = Audio::makeWAVStream(stream, DisposeAfterUse::YES); } _vm->_mixer->playStream( Audio::Mixer::kMusicSoundType, handle, input, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, false, isReverseStereo()); } else { warning("Sound::playMovieSound: Could not allocate %d bytes\n", len); } _vm->_resman->closeResource(res); }
void LocString::readString(uint32 languageID, Common::SeekableReadStream &stream) { uint32 length = stream.readUint32LE(); std::pair<StringMap::iterator, bool> s = _strings.insert(std::make_pair(languageID, "")); if (length == 0) return; Common::MemoryReadStream *data = stream.readStream(length); Common::MemoryReadStream *parsed = LangMan.preParseColorCodes(*data); Common::Encoding encoding = LangMan.getEncodingLocString(LangMan.getLanguageGendered(languageID)); if (encoding == Common::kEncodingInvalid) encoding = Common::kEncodingUTF8; try { s.first->second = Common::readString(*parsed, encoding); } catch (...) { parsed->seek(0); s.first->second = Common::readString(*parsed, Common::kEncodingCP1252); } delete parsed; delete data; }
bool CGEEngine::loadGame(int slotNumber, SavegameHeader *header, bool tiny) { debugC(1, kCGEDebugEngine, "CGEEngine::loadgame(%d, header, %s)", slotNumber, tiny ? "true" : "false"); Common::MemoryReadStream *readStream; SavegameHeader saveHeader; if (slotNumber == -1) { // Loading the data for the initial game state EncryptedStream file = EncryptedStream(this, kSavegame0Name); int size = file.size(); byte *dataBuffer = (byte *)malloc(size); file.read(dataBuffer, size); readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES); } else { // Open up the savegame file Common::String slotName = generateSaveName(slotNumber); Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slotName); // Read the data into a data buffer int size = saveFile->size(); byte *dataBuffer = (byte *)malloc(size); saveFile->read(dataBuffer, size); readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES); delete saveFile; } // Check to see if it's a ScummVM savegame or not char buffer[kSavegameStrSize + 1]; readStream->read(buffer, kSavegameStrSize + 1); if (strncmp(buffer, savegameStr, kSavegameStrSize + 1) != 0) { // It's not, so rewind back to the start readStream->seek(0); if (header) // Header wanted where none exists, so return false return false; } else { // Found header if (!readSavegameHeader(readStream, saveHeader)) { delete readStream; return false; } if (header) { *header = saveHeader; delete readStream; return true; } // Delete the thumbnail saveHeader.thumbnail->free(); delete saveHeader.thumbnail; } // Get in the savegame syncGame(readStream, NULL, tiny); delete readStream; return true; }
int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h, int *hotspot_x, int *hotspot_y, int *keycolor, byte **pal, int *palSize) { Win32CursorIconFileDir dir; Win32CursorIconFileDirEntry *entries = NULL; uint32 offset; uint32 c, d; int completed; int matched = 0; Common::MemoryReadStream *in = new Common::MemoryReadStream(data, datasize); if (!in->read(&dir, sizeof(Win32CursorIconFileDir)- sizeof(Win32CursorIconFileDirEntry))) goto cleanup; fix_win32_cursor_icon_file_dir_endian(&dir); if (dir.reserved != 0) { error("not an icon or cursor file (reserved non-zero)"); goto cleanup; } if (dir.type != 1 && dir.type != 2) { error("not an icon or cursor file (wrong type)"); goto cleanup; } entries = (Win32CursorIconFileDirEntry *)malloc(dir.count * sizeof(Win32CursorIconFileDirEntry)); for (c = 0; c < dir.count; c++) { if (!in->read(&entries[c], sizeof(Win32CursorIconFileDirEntry))) goto cleanup; fix_win32_cursor_icon_file_dir_entry_endian(&entries[c]); if (entries[c].reserved != 0) error("reserved is not zero"); } offset = sizeof(Win32CursorIconFileDir) + (dir.count - 1) * (sizeof(Win32CursorIconFileDirEntry)); for (completed = 0; completed < dir.count; ) { uint32 min_offset = 0x7fffffff; int previous = completed; for (c = 0; c < dir.count; c++) { if (entries[c].dib_offset == offset) { Win32BitmapInfoHeader bitmap; Win32RGBQuad *palette = NULL; uint32 palette_count = 0; uint32 image_size, mask_size; uint32 width, height; byte *image_data = NULL, *mask_data = NULL; byte *row = NULL; if (!in->read(&bitmap, sizeof(Win32BitmapInfoHeader))) goto local_cleanup; fix_win32_bitmap_info_header_endian(&bitmap); if (bitmap.size < sizeof(Win32BitmapInfoHeader)) { error("bitmap header is too short"); goto local_cleanup; } if (bitmap.compression != 0) { error("compressed image data not supported"); goto local_cleanup; } if (bitmap.x_pels_per_meter != 0) error("x_pels_per_meter field in bitmap should be zero"); if (bitmap.y_pels_per_meter != 0) error("y_pels_per_meter field in bitmap should be zero"); if (bitmap.clr_important != 0) error("clr_important field in bitmap should be zero"); if (bitmap.planes != 1) error("planes field in bitmap should be one"); if (bitmap.size != sizeof(Win32BitmapInfoHeader)) { uint32 skip = bitmap.size - sizeof(Win32BitmapInfoHeader); error("skipping %d bytes of extended bitmap header", skip); in->seek(skip, SEEK_CUR); } offset += bitmap.size; if (bitmap.clr_used != 0 || bitmap.bit_count < 24) { palette_count = (bitmap.clr_used != 0 ? bitmap.clr_used : 1 << bitmap.bit_count); palette = (Win32RGBQuad *)malloc(sizeof(Win32RGBQuad) * palette_count); if (!in->read(palette, sizeof(Win32RGBQuad) * palette_count)) goto local_cleanup; offset += sizeof(Win32RGBQuad) * palette_count; } width = bitmap.width; height = ABS(bitmap.height)/2; image_size = height * ROW_BYTES(width * bitmap.bit_count); mask_size = height * ROW_BYTES(width); if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)", entries[c].dib_size, (int)(bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) ); image_data = (byte *)malloc(image_size); if (!in->read(image_data, image_size)) goto local_cleanup; mask_data = (byte *)malloc(mask_size); if (!in->read(mask_data, mask_size)) goto local_cleanup; offset += image_size; offset += mask_size; completed++; matched++; *hotspot_x = entries[c].hotspot_x; *hotspot_y = entries[c].hotspot_y; *w = width; *h = height; *keycolor = 0; *cursor = (byte *)malloc(width * height); row = (byte *)malloc(width * 4); for (d = 0; d < height; d++) { uint32 x; uint32 y = (bitmap.height < 0 ? d : height - d - 1); uint32 imod = y * (image_size / height) * 8 / bitmap.bit_count; uint32 mmod = y * (mask_size / height) * 8; for (x = 0; x < width; x++) { uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count); // We set up cursor palette for default cursor, so use it if (!simple_vec(mask_data, x + mmod, 1)) { if (color) { cursor[0][width * d + x] = 254; // white } else { cursor[0][width * d + x] = 253; // black } } else { cursor[0][width * d + x] = 255; // transparent } /* if (bitmap.bit_count <= 16) { if (color >= palette_count) { error("color out of range in image data"); goto local_cleanup; } row[4*x+0] = palette[color].red; row[4*x+1] = palette[color].green; row[4*x+2] = palette[color].blue; } else { row[4*x+0] = (color >> 16) & 0xFF; row[4*x+1] = (color >> 8) & 0xFF; row[4*x+2] = (color >> 0) & 0xFF; } if (bitmap.bit_count == 32) row[4*x+3] = (color >> 24) & 0xFF; else row[4*x+3] = simple_vec(mask_data, x + mmod, 1) ? 0 : 0xFF; */ } } free(row); free(palette); if (image_data != NULL) { free(image_data); free(mask_data); } continue; local_cleanup: free(row); free(palette); if (image_data != NULL) { free(image_data); free(mask_data); } goto cleanup; } else { if (entries[c].dib_offset > offset) min_offset = MIN(min_offset, entries[c].dib_offset); } } if (previous == completed) { if (min_offset < offset) { error("offset of bitmap header incorrect (too low)"); goto cleanup; } assert(min_offset != 0x7fffffff); debugC(DEBUG_RESOURCE, "skipping %d bytes of garbage at %d", min_offset-offset, offset); in->seek(min_offset - offset, SEEK_CUR); offset = min_offset; } } free(entries); return matched; cleanup: free(entries); return -1; }