void MenuResource::load(byte *source, int size) { _strings.clear(); Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); sourceS->skip(4); // skip "MENU" uint16 count = sourceS->readUint16LE(); for (uint16 i = 0; i < count; i++) { uint16 offs = sourceS->readUint16LE(); const char *string = (const char*)(source + offs); _strings.push_back(string); debug(2, "%02d: %s\n", i, string); } delete sourceS; }
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); }
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); }
GTEST_TEST_F(LanguageManager, preParseColorCodes) { static const byte kColorString [] = "<c""\xAB""\xCD""\xEF"">Foobar</c>"; static const byte kPreparsedString[] = "<cABCDEFFF>Foobar</c>"; Common::MemoryReadStream stream(kColorString); Common::MemoryReadStream *preparsed = LangMan.preParseColorCodes(stream); ASSERT_NE(preparsed, static_cast<Common::MemoryReadStream *>(0)); ASSERT_EQ(preparsed->size(), sizeof(kPreparsedString)); for (size_t i = 0; i < sizeof(kPreparsedString); i++) EXPECT_EQ(preparsed->readChar(), kPreparsedString[i]) << "At index " << i; delete preparsed; }
GTEST_TEST(MemoryReadStream, readStream) { static const byte data[3] = { 0x12, 0x34, 0x56 }; Common::MemoryReadStream stream(data); Common::MemoryReadStream *streamRead = stream.readStream(ARRAYSIZE(data)); EXPECT_EQ(streamRead->size(), ARRAYSIZE(data)); for (size_t i = 0; i < ARRAYSIZE(data); i++) EXPECT_EQ(streamRead->readByte(), data[i]) << "At index " << i; delete streamRead; stream.seek(0); EXPECT_THROW(stream.readStream(ARRAYSIZE(data) + 1), Common::Exception); }
bool CGE2Engine::loadGame(int slotNumber) { Common::MemoryReadStream *readStream; // 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, kSavegameStr, kSavegameStrSize + 1) != 0) { delete readStream; return false; } else { SavegameHeader saveHeader; if (!readSavegameHeader(readStream, saveHeader)) { delete readStream; return false; } // Delete the thumbnail saveHeader.thumbnail->free(); delete saveHeader.thumbnail; } resetGame(); // Get in the savegame syncGame(readStream, nullptr); delete readStream; loadHeroes(); return true; }
void ObjectMan::loadObjectNames() { DisplayMan &dispMan = *_vm->_displayMan; _objectIconForMousePointer = new byte[16 * 16]; char *objectNames = new char[dispMan.getCompressedDataSize(k556_ObjectNamesGraphicIndice) + k199_ObjectNameCount]; Common::MemoryReadStream stream = dispMan.getCompressedData(k556_ObjectNamesGraphicIndice); for (uint16 objNameIndex = 0; objNameIndex < k199_ObjectNameCount; ++objNameIndex) { _objectNames[objNameIndex] = objectNames; byte tmpByte; for (tmpByte = stream.readByte(); !(tmpByte & 0x80); tmpByte = stream.readByte()) // last char of object name has 7th bit on *objectNames++ = tmpByte; // write while not last char *objectNames++ = tmpByte & 0x7F; // write without the 7th bit *objectNames++ = '\0'; // terminate string } }
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; }
bool Console::Cmd_Extract(int argc, const char **argv) { if (argc != 5) { DebugPrintf("Extract a file from the game's archives\n"); DebugPrintf("Usage :\n"); DebugPrintf("extract [room] [node id] [face number] [object type]\n"); return true; } // Room names are uppercase Common::String room = Common::String(argv[1]); room.toUppercase(); uint16 id = atoi(argv[2]); uint16 face = atoi(argv[3]); DirectorySubEntry::ResourceType type = (DirectorySubEntry::ResourceType) atoi(argv[4]); const DirectorySubEntry *desc = _vm->getFileDescription(room.c_str(), id, face, type); if (!desc) { DebugPrintf("File with room %s, id %d, face %d and type %d does not exist\n", room.c_str(), id, face, type); return true; } Common::MemoryReadStream *s = desc->getData(); Common::String filename = Common::String::format("node%s_%d_face%d.%d", room.c_str(), id, face, type); Common::DumpFile f; f.open(filename); uint8 *buf = new uint8[s->size()]; s->read(buf, s->size()); f.write(buf, s->size()); delete[] buf; f.close(); delete s; DebugPrintf("File '%s' successfully written\n", filename.c_str()); return true; }
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; }
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; }
if (!audioRes) { warning("Failed to find audio entry %i", number); return NULL; } } else { audioRes = _resMan->findResource(ResourceId(kResourceTypeAudio36, volume, number), false); if (!audioRes) { warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (number >> 24) & 0xff, (number >> 16) & 0xff, (number >> 8) & 0xff, number & 0xff); return NULL; } } // Load the data into a MemoryReadStream. The AudioStream here cannot rely on // memory from the resource manager. Common::MemoryReadStream srcStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); Common::ScopedPtr<Common::SeekableReadStream> stream(srcStream.readStream(srcStream.size())); byte audioFlags; uint32 audioCompressionType = audioRes->getAudioCompressionType(); Audio::SeekableAudioStream *audioSeekStream = 0; if (audioCompressionType) { #if (defined(USE_MAD) || defined(USE_VORBIS) || defined(USE_FLAC)) switch (audioCompressionType) { case MKTAG('M','P','3',' '): #ifdef USE_MAD audioSeekStream = Audio::makeMP3Stream(stream.release(), DisposeAfterUse::YES); #endif break; case MKTAG('O','G','G',' '):
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; }
void PictureResource::loadRaw(byte *source, int size) { // Loads a "raw" picture as used in RtZ, LGoP2, Manhole:N&E and Rodney's Funscreen Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); _hasPalette = (sourceS->readByte() != 0); byte cmdFlags = sourceS->readByte(); byte pixelFlags = sourceS->readByte(); byte maskFlags = sourceS->readByte(); uint16 cmdOffs = sourceS->readUint16LE(); uint16 pixelOffs = sourceS->readUint16LE(); uint16 maskOffs = sourceS->readUint16LE(); uint16 lineSize = sourceS->readUint16LE(); /*uint16 u = */sourceS->readUint16LE(); uint16 width = sourceS->readUint16LE(); uint16 height = sourceS->readUint16LE(); if (cmdFlags || pixelFlags || maskFlags) { warning("PictureResource::loadRaw() Graphic has flags set (%d, %d, %d)", cmdFlags, pixelFlags, maskFlags); } _paletteColorCount = (cmdOffs - 18) / 3; // 18 = sizeof header debug(2, "width = %d; height = %d\n", width, height); if (_hasPalette) { _picturePalette = new byte[_paletteColorCount * 3]; sourceS->read(_picturePalette, _paletteColorCount * 3); } _picture = new Graphics::Surface(); _picture->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags); delete sourceS; }
void Costume::loadEMI(Common::MemoryReadStream &ms, Costume *prevCost) { Common::List<Component *>components; _numChores = ms.readUint32LE(); _chores = new Chore[_numChores]; for (int i = 0; i < _numChores; i++) { uint32 nameLength; Component *prevComponent = NULL; nameLength = ms.readUint32LE(); ms.read(_chores[i]._name, nameLength); float length; ms.read(&length, 4); _chores[i]._length = (int)length; _chores[i]._owner = this; _chores[i]._numTracks = ms.readUint32LE(); _chores[i]._tracks = new ChoreTrack[_chores[i]._numTracks]; for (int k = 0; k < _chores[i]._numTracks; k++) { int componentNameLength = ms.readUint32LE(); assert(componentNameLength < 64); char name[64]; ms.read(name, componentNameLength); ms.readUint32LE(); int parentID = ms.readUint32LE(); if (parentID == -1 && prevCost) { MainModelComponent *mmc; // However, only the first item can actually share the // node hierarchy with the previous costume, so flag // that component so it knows what to do if (i == 0) parentID = -2; prevComponent = prevCost->_components[0]; mmc = dynamic_cast<MainModelComponent *>(prevComponent); // Make sure that the component is valid if (!mmc) prevComponent = NULL; } // Actually load the appropriate component Component *component = loadComponentEMI(parentID < 0 ? NULL : _components[parentID], parentID, name, prevComponent); //Component *component = loadComponentEMI(name, parent); components.push_back(component); ChoreTrack &track = _chores[i]._tracks[k]; track.numKeys = ms.readUint32LE(); track.keys = new TrackKey[track.numKeys]; // this is probably wrong track.compID = 0; for (int j = 0; j < track.numKeys; j++) { float time, value; ms.read(&time, 4); ms.read(&value, 4); track.keys[j].time = (int)time; track.keys[j].value = (int)value; } } //_chores[i]._tracks->compID; } _numComponents = components.size(); _components = new Component *[_numComponents]; int i = 0; for (Common::List<Component *>::iterator it = components.begin(); it != components.end(); ++it, ++i) { _components[i] = *it; if (!_components[i]) continue; _components[i]->setCostume(this); _components[i]->init(); } }
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 PictureResource::loadChunked(byte *source, int size) { // Loads a "chunked" picture as used in Manhole EGA Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size); byte cmdFlags = 0, pixelFlags = 0, maskFlags = 0; uint16 cmdOffs = 0, pixelOffs = 0, maskOffs = 0; uint16 lineSize = 0, width = 0, height = 0; sourceS->skip(36); // skip the "Flex" header _hasPalette = false; while (!sourceS->eos()) { uint32 chunkType = sourceS->readUint32BE(); uint32 chunkSize = sourceS->readUint32BE(); if (sourceS->eos()) break; debug(0, "chunkType = %08X; chunkSize = %d", chunkType, chunkSize); if (chunkType == MKTAG('R','e','c','t')) { debug(0, "Rect"); sourceS->skip(4); height = sourceS->readUint16BE(); width = sourceS->readUint16BE(); debug(0, "width = %d; height = %d", width, height); } else if (chunkType == MKTAG('f','M','a','p')) { debug(0, "fMap"); lineSize = sourceS->readUint16BE(); sourceS->skip(11); cmdFlags = sourceS->readByte(); cmdOffs = sourceS->pos(); sourceS->skip(chunkSize - 14); debug(0, "lineSize = %d; cmdFlags = %d; cmdOffs = %04X", lineSize, cmdFlags, cmdOffs); } else if (chunkType == MKTAG('f','L','C','o')) { debug(0, "fLCo"); sourceS->skip(9); pixelFlags = sourceS->readByte(); pixelOffs = sourceS->pos(); sourceS->skip(chunkSize - 10); debug(0, "pixelFlags = %d; pixelOffs = %04X", pixelFlags, pixelOffs); } else if (chunkType == MKTAG('f','P','i','x')) { debug(0, "fPix"); sourceS->skip(9); maskFlags = sourceS->readByte(); maskOffs = sourceS->pos(); sourceS->skip(chunkSize - 10); debug(0, "maskFlags = %d; maskOffs = %04X", maskFlags, maskOffs); } else if (chunkType == MKTAG('f','G','C','o')) { debug(0, "fGCo"); _hasPalette = true; _paletteColorCount = chunkSize / 3; _picturePalette = new byte[_paletteColorCount * 3]; sourceS->read(_picturePalette, _paletteColorCount * 3); } else { error("PictureResource::loadChunked() Invalid chunk %08X at %08X", chunkType, sourceS->pos()); } } if (!cmdOffs || !pixelOffs /*|| !maskOffs*/ || !lineSize || !width || !height) { error("PictureResource::loadChunked() Error parsing the picture data, one or more chunks/parameters are missing"); } _picture = new Graphics::Surface(); _picture->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags); delete sourceS; }