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 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; }
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 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; }
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::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; }
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(); } }
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; }