Beispiel #1
0
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);


}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}