Пример #1
0
void ActorType::load(byte *dataStart, Common::SeekableReadStream &stream) {
	_actorTypeId = stream.readUint32LE();
	_surfInfo.load(stream);
	uint32 pointsConfigOffs = stream.readUint32LE();
	uint namedPointsCount = stream.readUint16LE();
	stream.skip(2); // Skip padding
	uint32 namedPointsOffs = stream.readUint32LE();
	_color.r = stream.readByte();
	_color.g = stream.readByte();
	_color.b = stream.readByte();
	stream.readByte(); // Skip padding
	_scale = stream.readByte();
	_priority = stream.readByte();
	_value1E = stream.readUint16LE();
	_pathWalkPointsIndex = stream.readUint16LE();
	_scaleLayerIndex = stream.readUint16LE();
	_pathWalkRectIndex = stream.readUint16LE();
	_priorityLayerIndex = stream.readUint16LE();
	_regionLayerIndex = stream.readUint16LE();
	_flags = stream.readUint16LE();
	_pointsConfig = dataStart + pointsConfigOffs;
	stream.seek(namedPointsOffs);
	_namedPoints.load(namedPointsCount, stream);
	debug(5, "ActorType::load() _actorTypeId: %08X; _color(%d,%d,%d); _scale: %d; _priority: %d; _value1E: %d",
		_actorTypeId, _color.r, _color.g, _color.b, _scale, _priority, _value1E);
	debug(5, "ActorType::load() _pathWalkPointsIndex: %d; _scaleLayerIndex: %d; _pathWalkRectIndex: %d",
		_pathWalkPointsIndex, _scaleLayerIndex, _pathWalkRectIndex);
	debug(5, "ActorType::load() _priorityLayerIndex: %d; _regionLayerIndex: %d; _flags: %04X",
		_priorityLayerIndex, _regionLayerIndex,_flags);
}
Пример #2
0
void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool animImages) {
	loadPalette(stream);

	int streamSize = stream.size();
	while (stream.pos() < streamSize) {
		ImageFrame frame;
		frame._width = stream.readUint16LE() + 1;
		frame._height = stream.readUint16LE() + 1;
		frame._paletteBase = stream.readByte();

		if (animImages) {
			// Animation cutscene image files use a 16-bit x offset
			frame._offset.x = stream.readUint16LE();
			frame._rleEncoded = (frame._offset.x & 0xff) == 1;
			frame._offset.y = stream.readByte();
		} else {
			// Standard image files have a separate byte for the RLE flag, and an 8-bit X offset
			frame._rleEncoded = stream.readByte() == 1;
			frame._offset.x = stream.readByte();
			frame._offset.y = stream.readByte();
		}

		frame._rleEncoded = !skipPalette && frame._rleEncoded;

		if (frame._paletteBase) {
			// Nibble packed frame data
			frame._size = (frame._width * frame._height) / 2;
		} else if (frame._rleEncoded) {
			// This size includes the header size, which we subtract
			frame._size = stream.readUint16LE() - 11;
			frame._rleMarker = stream.readByte();
		} else {
			// Uncompressed data
			frame._size = frame._width * frame._height;
		}

		// Load data for frame and decompress it
		byte *data = new byte[frame._size + 4];
		stream.read(data, frame._size);
		Common::fill(data + frame._size, data + frame._size + 4, 0);
		frame.decompressFrame(data, IS_ROSE_TATTOO);
		delete[] data;

		push_back(frame);
	}
}
Пример #3
0
bool TGADecoder::readDataRLE(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth) {
	// RLE-TrueColor / RLE-Black/White
	if (imageType == TYPE_RLE_TRUECOLOR || imageType == TYPE_RLE_BW || imageType == TYPE_RLE_CMAP) {
		_surface.create(_surface.w, _surface.h, _format);
		uint32 count = _surface.w * _surface.h;
		byte *data = (byte *)_surface.getPixels();

		while (count > 0) {
			uint32 header = tga.readByte();
			byte type = (header & 0x80) >> 7;
			uint32 rleCount = (header & 0x7F) + 1;

			// RLE-packet
			if (type == 1) {
				if (pixelDepth == 32 && imageType == TYPE_RLE_TRUECOLOR) {
					uint32 color = tga.readUint32LE();
					while (rleCount-- > 0) {
						*((uint32 *)data) = color;
						data += 4;
						count--;
					}
				} else if (pixelDepth == 24 && imageType == TYPE_RLE_TRUECOLOR) {
					byte r = tga.readByte();
					byte g = tga.readByte();
					byte b = tga.readByte();
					while (rleCount-- > 0) {
#ifdef SCUMM_LITTLE_ENDIAN
						*data++ = r;
						*data++ = g;
						*data++ = b;
#else
						*data++ = b;
						*data++ = g;
						*data++ = r;
#endif
						count--;
					}
				} else if (pixelDepth == 16 && imageType == TYPE_RLE_TRUECOLOR) {
					const uint16 rgb = tga.readUint16LE();
					while (rleCount-- > 0) {
						*((uint16 *)data) = rgb;
						data += 2;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_BW) {
					byte color = tga.readByte();
					while (rleCount-- > 0) {
						*data++ = color;
						*data++ = color;
						*data++ = color;
						*data++ = color;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_CMAP) {
					byte index = tga.readByte();
					while (rleCount-- > 0) {
						*data++ = index;
						count--;
					}
				} else {
					warning("Unhandled pixel-depth for image-type 10");
					return false;
				}
				// Raw-packet
			} else if (type == 0) {
				if (pixelDepth == 32 && imageType == TYPE_RLE_TRUECOLOR) {
					while (rleCount-- > 0) {
						uint32 color = tga.readUint32LE();
						*((uint32 *)data) = color;
						data += 4;
						count--;
					}
				} else if (pixelDepth == 24 && imageType == TYPE_RLE_TRUECOLOR) {
					while (rleCount-- > 0) {
						byte r = tga.readByte();
						byte g = tga.readByte();
						byte b = tga.readByte();
#ifdef SCUMM_LITTLE_ENDIAN
						*data++ = r;
						*data++ = g;
						*data++ = b;
#else
						*data++ = b;
						*data++ = g;
						*data++ = r;
#endif
						count--;
					}
				} else if (pixelDepth == 16 && imageType == TYPE_RLE_TRUECOLOR) {
					while (rleCount-- > 0) {
						*((uint16 *)data) = tga.readUint16LE();
						data += 2;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_BW) {
					while (rleCount-- > 0) {
						byte color = tga.readByte();
						*data++ = color;
						*data++ = color;
						*data++ = color;
						*data++ = color;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_CMAP) {
					while (rleCount-- > 0) {
						byte index = tga.readByte();
						*data++ = index;
						count--;
					}
				} else {
					warning("Unhandled pixel-depth for image-type 10");
					return false;
				}
			} else {
				warning("Unknown header for RLE-packet %d", type);
				return false;
			}
		}
	} else {
Пример #4
0
bool PersistenceService::saveGame(uint slotID, const Common::String &screenshotFilename) {
	// FIXME: This code is a hack which bypasses the savefile API,
	// and should eventually be removed.

	// Überprüfen, ob die Slot-ID zulässig ist.
	if (slotID >= SLOT_COUNT) {
		error("Tried to save to an invalid slot (%d). Only slot ids form 0 to %d are allowed.", slotID, SLOT_COUNT - 1);
		return false;
	}

	// Dateinamen erzeugen.
	Common::String filename = generateSavegameFilename(slotID);

	// Spielstanddatei öffnen und die Headerdaten schreiben.
	Common::SaveFileManager *sfm = g_system->getSavefileManager();
	Common::OutSaveFile *file = sfm->openForSaving(filename);

	file->writeString(FILE_MARKER);
	file->writeByte(0);
	file->writeString(VERSIONID);
	file->writeByte(0);

	char buf[20];
	snprintf(buf, 20, "%d", VERSIONNUM);
	file->writeString(buf);
	file->writeByte(0);

	TimeDate dt;
	g_system->getTimeAndDate(dt);
	file->writeString(formatTimestamp(dt));
	file->writeByte(0);

	if (file->err()) {
		error("Unable to write header data to savegame file \"%s\".", filename.c_str());
	}

	// Alle notwendigen Module persistieren.
	OutputPersistenceBlock writer;
	bool success = true;
	success &= Kernel::getInstance()->getScript()->persist(writer);
	success &= RegionRegistry::instance().persist(writer);
	success &= Kernel::getInstance()->getGfx()->persist(writer);
	success &= Kernel::getInstance()->getSfx()->persist(writer);
	success &= Kernel::getInstance()->getInput()->persist(writer);
	if (!success) {
		error("Unable to persist modules for savegame file \"%s\".", filename.c_str());
	}

	// Write the save game data uncompressed, since the final saved game will be
	// compressed anyway.
	char sBuffer[10];
	snprintf(sBuffer, 10, "%u", writer.getDataSize());
	file->writeString(sBuffer);
	file->writeByte(0);
	snprintf(sBuffer, 10, "%u", writer.getDataSize());
	file->writeString(sBuffer);
	file->writeByte(0);
	file->write(writer.getData(), writer.getDataSize());

	// Get the screenshot
	Common::SeekableReadStream *thumbnail = Kernel::getInstance()->getGfx()->getThumbnail();

	if (thumbnail) {
		byte *buffer = new byte[FILE_COPY_BUFFER_SIZE];
		thumbnail->seek(0, SEEK_SET);
		while (!thumbnail->eos()) {
			int bytesRead = thumbnail->read(&buffer[0], FILE_COPY_BUFFER_SIZE);
			file->write(&buffer[0], bytesRead);
		}

		delete[] buffer;
	} else {
		warning("The screenshot file \"%s\" does not exist. Savegame is written without a screenshot.", filename.c_str());
	}

	file->finalize();
	delete file;

	// Savegameinformationen für diesen Slot aktualisieren.
	_impl->readSlotSavegameInformation(slotID);

	// Empty the cache, to remove old thumbnails
	Kernel::getInstance()->getResourceManager()->emptyThumbnailCache();

	// Erfolg signalisieren.
	return true;
}
Пример #5
0
int TattooMap::show() {
	Debugger &debugger = *_vm->_debugger;
	Events &events = *_vm->_events;
	Music &music = *_vm->_music;
	Resources &res = *_vm->_res;
	TattooScene &scene = *(TattooScene *)_vm->_scene;
	Screen &screen = *_vm->_screen;
	int result = 0;

	// Check if we need to keep track of how many times player has been to the map
	for (uint idx = 0; idx < scene._sceneTripCounters.size(); ++idx) {
		SceneTripEntry &entry = scene._sceneTripCounters[idx];

		if (entry._sceneNumber == OVERHEAD_MAP || entry._sceneNumber == OVERHEAD_MAP2) {
			if (--entry._numTimes == 0) {
				_vm->setFlagsDirect(entry._flag);
				scene._sceneTripCounters.remove_at(idx);
			}
		}
	}

	if (music._midiOption) {
		// See if Holmes or Watson is the active character	
		Common::String song;
		if (_vm->readFlags(FLAG_PLAYER_IS_HOLMES))
			// Player is Holmes
			song = "Cue9";
		else if (_vm->readFlags(FLAG_ALT_MAP_MUSIC))
			song = "Cue8";
		else
			song = "Cue7";

		if (music.loadSong(song)) {
			music.setMIDIVolume(music._musicVolume);
			if (music._musicOn)
				music.startSong();
		}
	}

	screen.initPaletteFade(1364485);
	
	// Load the custom mouse cursors for the map
	ImageFile cursors("omouse.vgs");
	events.setCursor(cursors[0]._frame);
	events.warpMouse(Common::Point(SHERLOCK_SCREEN_WIDTH / 2, SHERLOCK_SCREEN_HEIGHT / 2));

	// Load the data for the map
	_iconImages = new ImageFile("mapicons.vgs");
	loadData();

	// Load the palette
	Common::SeekableReadStream *stream = res.load("map.pal");
	stream->read(screen._cMap, PALETTE_SIZE);
	screen.translatePalette(screen._cMap);
	delete stream;

	// Load the map image and draw it to the back buffer
	ImageFile *map = new ImageFile("map.vgs");
	screen._backBuffer1.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2);
	screen._backBuffer1.blitFrom((*map)[0], Common::Point(0, 0));
	delete map;

	screen.clear();
	screen.setPalette(screen._cMap);
	drawMapIcons();

	// Copy the map drawn in the back buffer to the secondary back buffer
	screen._backBuffer2.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2);
	screen._backBuffer2.blitFrom(screen._backBuffer1);

	// Display the built map to the screen
	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);

	// Set initial scroll position
	_targetScroll = _bigPos;
	screen._currentScroll = Common::Point(-1, -1);

	do {
		// Allow for event processing and get the current mouse position
		events.pollEventsAndWait();
		events.setButtonState();
		Common::Point mousePos = events.screenMousePos();

		if (debugger._showAllLocations == LOC_REFRESH) {
			drawMapIcons();
			screen.slamArea(screen._currentScroll.x, screen._currentScroll.y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_WIDTH);
		}

		checkMapNames(true);

		if (mousePos.x < (SHERLOCK_SCREEN_WIDTH / 6))
			_targetScroll.x -= 2 * SCROLL_SPEED * (SHERLOCK_SCREEN_WIDTH / 6 - mousePos.x) / (SHERLOCK_SCREEN_WIDTH / 6);
		if (mousePos.x > (SHERLOCK_SCREEN_WIDTH * 5 / 6))
			_targetScroll.x += 2 * SCROLL_SPEED * (mousePos.x - (SHERLOCK_SCREEN_WIDTH * 5 / 6)) / (SHERLOCK_SCREEN_WIDTH / 6);
		if (mousePos.y < (SHERLOCK_SCREEN_HEIGHT / 6))
			_targetScroll.y -= 2 * SCROLL_SPEED * (SHERLOCK_SCREEN_HEIGHT / 6 - mousePos.y) / (SHERLOCK_SCREEN_HEIGHT / 6);
		if (mousePos.y > (SHERLOCK_SCREEN_HEIGHT * 5 / 6))
			_targetScroll.y += 2 * SCROLL_SPEED * (mousePos.y - SHERLOCK_SCREEN_HEIGHT * 5 / 6) / (SHERLOCK_SCREEN_HEIGHT / 6);

		if (_targetScroll.x < 0)
			_targetScroll.x = 0;
		if ((_targetScroll.x + SHERLOCK_SCREEN_WIDTH) > screen._backBuffer1.w())
			_targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
		if (_targetScroll.y < 0)
			_targetScroll.y = 0;
		if ((_targetScroll.y + SHERLOCK_SCREEN_HEIGHT) > screen._backBuffer1.h())
			_targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;

		// Check the keyboard
		if (events.kbHit()) {
			Common::KeyState keyState = events.getKey();

			switch (keyState.keycode) {
			case Common::KEYCODE_HOME:
			case Common::KEYCODE_KP7:
				_targetScroll.x = 0;
				_targetScroll.y = 0;
				break;

			case Common::KEYCODE_END:
			case Common::KEYCODE_KP1:
				_targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
				_targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
				break;

			case Common::KEYCODE_PAGEUP:
			case Common::KEYCODE_KP9:
				_targetScroll.y -= SHERLOCK_SCREEN_HEIGHT;
				if (_targetScroll.y < 0)
					_targetScroll.y = 0;
				break;

			case Common::KEYCODE_PAGEDOWN:
			case Common::KEYCODE_KP3:
				_targetScroll.y += SHERLOCK_SCREEN_HEIGHT;
				if (_targetScroll.y > (screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT))
					_targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
				break;

			case Common::KEYCODE_SPACE:
				events._pressed = false;
				events._oldButtons = 0;
				events._released = true;
				break;

			default:
				break;
			}
		}

		// Handle any scrolling of the map
		if (screen._currentScroll != _targetScroll) {
			// If there is a Text description being displayed, restore the area under it
			_mapTooltip.erase();

			screen._currentScroll = _targetScroll;

			checkMapNames(false);
			screen.slamArea(_targetScroll.x, _targetScroll.y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
		}

		// Handling if a location has been clicked on
		if (events._released && _bgFound != -1) {
			// If there is a Text description being displayed, restore the area under it
			_mapTooltip.erase();

			// Save the current scroll position on the map
			_bigPos = screen._currentScroll;

			showCloseUp(_bgFound);
			result = _bgFound + 1;
		}
	} while (!result && !_vm->shouldQuit());

	music.stopMusic();
	events.clearEvents();
	_mapTooltip.banishWindow();

	// Reset the back buffers back to standard size
	screen._backBuffer1.create(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
	screen._backBuffer2.create(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);

	return result;
}
Пример #6
0
void TXB::readHeader(Common::SeekableReadStream &txb, bool &needDeSwizzle) {
	// Number of bytes for the pixel data in one full image
	uint32 dataSize = txb.readUint32LE();

	_dataSize = dataSize;

	txb.skip(4); // Some float

	// Image dimensions
	uint32 width  = txb.readUint16LE();
	uint32 height = txb.readUint16LE();

	// How's the pixel data encoded?
	byte encoding    = txb.readByte();
	// Number of mip maps in the image
	byte mipMapCount = txb.readByte();

	txb.skip(2); // Unknown (Always 0x0101 on 0x0A and 0x0C types, 0x0100 on 0x09?)
	txb.skip(4); // Some float
	txb.skip(108); // Reserved

	needDeSwizzle = false;

	uint32 minDataSize, mipMapSize;
	if        (encoding == kEncodingBGRA) {
		// Raw BGRA

		needDeSwizzle = true;

		_compressed = false;
		_hasAlpha   = true;
		_format     = kPixelFormatBGRA;
		_formatRaw  = kPixelFormatRGBA8;
		_dataType   = kPixelDataType8;

		minDataSize = 4;
		mipMapSize  = width * height * 4;

	} else if (encoding == kEncodingDXT1) {
		// S3TC DXT1

		_compressed = true;
		_hasAlpha   = false;
		_format     = kPixelFormatBGR;
		_formatRaw  = kPixelFormatDXT1;
		_dataType   = kPixelDataType8;

		minDataSize = 8;
		mipMapSize  = width * height / 2;

	} else if (encoding == kEncodingDXT5) {
		// S3TC DXT5

		_compressed = true;
		_hasAlpha   = true;
		_format     = kPixelFormatBGRA;
		_formatRaw  = kPixelFormatDXT5;
		_dataType   = kPixelDataType8;

		minDataSize = 16;
		mipMapSize  = width * height;

	} else if (encoding == 0x09)
		// TODO: This seems to be some compression with 8bit per pixel. No min
		//       data size; 2*2 and 1*1 mipmaps seem to be just that big.
		//       Image data doesn't seem to be simple grayscale, paletted,
		//       RGB2222 or RGB332 data either.
		throw Common::Exception("Unsupported TXB encoding 0x09");
	 else
		throw Common::Exception("Unknown TXB encoding 0x%02X (%dx%d, %d, %d)",
				encoding, width, height, mipMapCount, dataSize);

	_mipMaps.reserve(mipMapCount);
	for (uint32 i = 0; i < mipMapCount; i++) {
		MipMap *mipMap = new MipMap;

		mipMap->width  = MAX<uint32>(width,  1);
		mipMap->height = MAX<uint32>(height, 1);

		if (((width < 4) || (height < 4)) && (width != height))
			// Invalid mipmap dimensions
			break;

		mipMap->size = MAX<uint32>(mipMapSize, minDataSize);

		mipMap->data = 0;

		if (dataSize < mipMap->size) {
			// Wouldn't fit
			delete mipMap;
			break;
		}

		dataSize -= mipMap->size;

		_mipMaps.push_back(mipMap);

		width      >>= 1;
		height     >>= 1;
		mipMapSize >>= 2;

		if ((width < 1) && (height < 1))
			break;
	}

}
Пример #7
0
bool Animation::loadStream(Common::SeekableReadStream &stream) {
	stream.skip(2); // skip not used x and y coord diff
	_loopCount = stream.readUint16LE();
	_phaseCount = stream.readUint16LE();
	stream.skip(2); // skip _frameCount here
	_baseX = stream.readUint16LE();
	_baseY = stream.readUint16LE();
	uint32 phaseTableOffset = stream.readUint32LE();
	uint32 tableOfFrameOffsets = stream.pos();

	stream.seek(phaseTableOffset);
	Phase tempPhase;
	_frameCount = 0;
	for (int phase = 0; phase < _phaseCount; phase++) {
		tempPhase._phaseOffsetX = stream.readSint16LE();
		tempPhase._phaseOffsetY = stream.readSint16LE();
		tempPhase._phaseToFrameIndex = stream.readUint16LE();
		if (tempPhase._phaseToFrameIndex > _frameCount) {
			_frameCount = tempPhase._phaseToFrameIndex;
		}
		_phaseList.push_back(tempPhase);
		stream.skip(2);
	}
	if (_phaseCount) {
		_frameCount++;
	}

	Frame tempFrame;
	for (int frame = 0; frame < _frameCount; frame++) {
		stream.seek(tableOfFrameOffsets + frame * 4);
		uint32 frameInfoOffset = stream.readUint32LE();
		stream.seek(frameInfoOffset);
		uint16 frameWidth = stream.readUint16LE();
		uint16 frameHeight = stream.readUint16LE();
		uint32 frameDataPos = stream.pos();
		uint32 frameDataOffset = stream.readUint32BE();

		tempFrame._surface = new Graphics::Surface();
		tempFrame._surface->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8());
		if (frameDataOffset == MKTAG('m', 'a', 's', 'm')) {
			tempFrame._isCompressed = true;
			tempFrame._dataSize = stream.readUint32LE();
			tempFrame._compressedData = (byte *)malloc(tempFrame._dataSize);
			stream.read(tempFrame._compressedData, tempFrame._dataSize);
		} else {
			tempFrame._isCompressed = false;
			tempFrame._dataSize = 0;
			tempFrame._compressedData = nullptr;
			stream.seek(frameDataPos);
			for (uint16 i = 0; i < frameHeight; i++) {
				stream.read(tempFrame._surface->getBasePtr(0, i), frameWidth);
			}
		}
		_frameList.push_back(tempFrame);
	}

	return true;
}
Пример #8
0
Common::Point GameModule::readPoint(Common::SeekableReadStream &s) {
	Common::Point p;
	p.x = s.readUint16LE();
	p.y = s.readUint16LE();
	return p;
}
Пример #9
0
void GameModule::loadAnimations(Common::SeekableReadStream &s) {
	debug(0, "GameModule::loadAnimations()");

	s.seek(0x168);
	_animationsCount = s.readUint32LE();
	uint32 offs = s.readUint32LE();
	_animations = new Animation[_animationsCount];
	for (int i = 0; i < _animationsCount; ++i) {
		Animation &anim = _animations[i];
		s.seek(offs + i * 20);
		anim.frameCount = s.readUint32LE();
		uint32 frameSpriteIndicesOffs = s.readUint32LE();
		uint32 frameTicksOffs = s.readUint32LE();
		uint32 frameRects1Offs = s.readUint32LE();
		uint32 frameRects2Offs = s.readUint32LE();
		anim.frameSpriteIndices = new int[anim.frameCount];
		s.seek(frameSpriteIndicesOffs);
		for (int j = 0; j < anim.frameCount; ++j)
			anim.frameSpriteIndices[j] = s.readUint32LE();
		anim.frameTicks = new int16[anim.frameCount];
		s.seek(frameTicksOffs);
		for (int j = 0; j < anim.frameCount; ++j)
			anim.frameTicks[j] = s.readUint16LE();
		anim.frameRects1 = new Common::Rect[anim.frameCount];
		s.seek(frameRects1Offs);
		for (int j = 0; j < anim.frameCount; ++j)
			anim.frameRects1[j] = readRect(s);
		anim.frameRects2 = new Common::Rect[anim.frameCount];
		s.seek(frameRects2Offs);
		for (int j = 0; j < anim.frameCount; ++j)
			anim.frameRects2[j] = readRect(s);
	}
}
Пример #10
0
void CUP_Player::handleRGBS(Common::SeekableReadStream &dataStream, uint32 dataSize) {
	dataStream.read(_paletteData, 256 * 3);
	_paletteChanged = true;
}
Пример #11
0
/*
	Island Sections (Num Entries HQR - 3 / 6 = Total Sections available)
		3 (0) - Objects layout
		4 (1) - Objects data
		5 (2) - Quads (2 triangles)
		6 (3) - Texture UV mapping
		7 (4) - Height Maps
		8 (5) - Intensity
*/
void Island::loadIslandSection(int sectionIdx, int entryIdx) {
	// 7 (4) - Height Maps
	int16 heightmap[65][65];
	Common::SeekableReadStream *stream = _ile->createReadStreamForIndex(entryIdx + 4);
	_sectionsLayout = new byte[256];
	stream->read(heightmap, 65*65);
	delete stream;

	// 6 (3) - Texture UV mapping
	GroundTextureInfo *textureInfo;
	stream = _ile->createReadStreamForIndex(entryIdx + 3);
	textureInfo = new GroundTextureInfo[stream->size() / 12];
	stream->read(textureInfo, 65*65);
	delete stream;

	// 8 (5) - Intensity
	byte intensity[65][65];
	stream = _ile->createReadStreamForIndex(entryIdx + 5);
	stream->read(intensity, 65*65);
	delete stream;

	// 5 (2) - Quads (2 triangles)
	GroundSquare squares[64][64];
	stream = _ile->createReadStreamForIndex(entryIdx + 2);
	stream->read(squares, 64 * 64 * 8);
	delete stream;

	// Parse data
	int16 maxHeight = 0;
	
	Common::Array<float> vertices;
	vertices.reserve(9 * 64 * 64 * 4 * 2);
	
	Common::Array<uint16> faces;
	faces.reserve(6 * 64 * 64);

	// Vertex Count - In order of verts that make tris
	uint16  idx = 0;
	uint16 uvOrder[6] = {0, 1, 2, 2, 0, 1};
	uint16 idxOrder1[6] = {0, 2, 3, 0, 3, 1};
	uint16 idxOrder2[6] = {0, 2, 1, 1, 2, 3};

	// For Every QUAD
	for (int32 x = 0; x < 64; ++x)
	{
		for (int32 y = 0; y < 64; ++y)
		{
			// Pass the pointer from the quad database to this quad (2 triangles passed)
			GroundTriangle *tri = squares[x][y].triangle;
			// Orientation
			uint16 *idxOrder = (tri[0].orientation == 0) ? idxOrder1 : idxOrder2;

			// For both tris in this quad...
			for (int32 t = 0; t < 2; ++t)
			{
				// Data Usage for this Tri
				int mdMax = 0;

				if (tri[t].useColor)
					mdMax++;
				if (tri[t].useTexture)
					mdMax++;

				// For all the data usage in this tri
				for (int32 md = 0; md < mdMax; ++md)
				{
					// For each vertex, offset by triangle num in quad
					for (int32 i = 3 * t; i < (3 + 3 * t); ++i)
					{
						int32 xi = x + idxOrder[i] / 2;
						int32 yi = y + idxOrder[i] % 2;

						// Vertex position
						vertices.push_back(((float)(xi) - 32) / 0x20);
						vertices.push_back(((float)(heightmap[xi][yi])) / 0x4000);
						vertices.push_back(((float)(64 - yi) - 32) / 0x20);

						if (heightmap[xi][yi] > maxHeight)
							maxHeight = heightmap[xi][yi];

						// Vertex color and UV
						if (tri[t].useTexture && (mdMax < 2 || md == 1))
						{
							float intens = intensity[xi][yi] / 16.0f + 0.3;
							
							if (intens > 1.0)
								intens = 1.0;

							vertices.push_back(intens);
							vertices.push_back(intens);
							vertices.push_back(intens);
							vertices.push_back(1.0);
							vertices.push_back((textureInfo[tri[t].textureIndex].uv[uvOrder[i]].u / 65535.0f) * 0.5);
							vertices.push_back(textureInfo[tri[t].textureIndex].uv[uvOrder[i]].v / 65535.0f);

						}
						else if (mdMax < 2 || md == 0)
						{
							byte colorIdx = (tri[t].textureBank * 16) + intensity[xi][yi];
							
							// TODO get palette RGB components for colorIdx
							float r = 0;
							float g = 0;
							float b = 0;

							vertices.push_back(r);
							vertices.push_back(g);
							vertices.push_back(b);
							vertices.push_back(1.0);
							vertices.push_back(0.75f);
							vertices.push_back(0.5f);
						}
					}

					/* Index */
					faces.push_back(idx);
					faces.push_back(idx + 1);
					faces.push_back(idx + 2);
					idx += 3;
				}
			}
		}

	}

	delete [] textureInfo;
}
Пример #12
0
void CUP_Player::handleHEAD(Common::SeekableReadStream &dataStream, uint32 dataSize) {
	_playbackRate = dataStream.readUint16LE();
	_width = dataStream.readUint16LE();
	_height = dataStream.readUint16LE();
}
Пример #13
0
void ComposerEngine::loadLibrary(uint id) {
	if (getGameType() == GType_ComposerV1 && !_libraries.empty()) {
		// kill the previous page, starting with any scripts running on it

		for (Common::List<OldScript *>::iterator i = _oldScripts.begin(); i != _oldScripts.end(); i++)
			delete *i;
		_oldScripts.clear();

		Library *library = &_libraries.front();
		unloadLibrary(library->_id);
	}

	Common::String filename;

	if (getGameType() == GType_ComposerV1) {
		if (!id || _bookGroup.empty())
			filename = getStringFromConfig("Common", "StartPage");
		else
			filename = getStringFromConfig(_bookGroup, Common::String::format("%d", id));
		filename = mangleFilename(filename);

		// bookGroup is the basename of the path.
		// TODO: tidy this up.
		_bookGroup.clear();
		for (uint i = 0; i < filename.size(); i++) {
			if (filename[i] == '~' || filename[i] == '/' || filename[i] == ':')
				continue;
			for (uint j = 0; j < filename.size(); j++) {
				if (filename[j] == '/') {
					_bookGroup.clear();
					continue;
				}
				if (filename[j] == '.')
					break;
				_bookGroup += filename[j];
			}
			break;
		}
	} else {
		if (!id)
			id = atoi(getStringFromConfig("Common", "StartUp").c_str());
		filename = getFilename("Libs", id);
	}

	Library library;

	library._id = id;
	library._archive = new ComposerArchive();
	if (!library._archive->openFile(filename))
		error("failed to open '%s'", filename.c_str());
	_libraries.push_front(library);

	Library &newLib = _libraries.front();

	Common::Array<uint16> buttonResources = library._archive->getResourceIDList(ID_BUTN);
	for (uint i = 0; i < buttonResources.size(); i++) {
		uint16 buttonId = buttonResources[i];
		Common::SeekableReadStream *stream = library._archive->getResource(ID_BUTN, buttonId);
		Button button(stream, buttonId, getGameType());

		bool inserted = false;
		for (Common::List<Button>::iterator b = newLib._buttons.begin(); b != newLib._buttons.end(); b++) {
			if (button._zorder < b->_zorder)
				continue;
			newLib._buttons.insert(b, button);
			inserted = true;
			break;
		}
		if (!inserted)
			newLib._buttons.push_back(button);
	}

	Common::Array<uint16> ambientResources = library._archive->getResourceIDList(ID_AMBI);
	for (uint i = 0; i < ambientResources.size(); i++) {
		Common::SeekableReadStream *stream = library._archive->getResource(ID_AMBI, ambientResources[i]);
		Button button(stream);
		newLib._buttons.insert(newLib._buttons.begin(), button);
	}

	Common::Array<uint16> accelResources = library._archive->getResourceIDList(ID_ACEL);
	for (uint i = 0; i < accelResources.size(); i++) {
		Common::SeekableReadStream *stream = library._archive->getResource(ID_ACEL, accelResources[i]);
		KeyboardHandler handler;
		handler.keyId = stream->readUint16LE();
		handler.modifierId = stream->readUint16LE();
		handler.scriptId = stream->readUint16LE();
		newLib._keyboardHandlers.push_back(handler);
	}

	Common::Array<uint16> randResources = library._archive->getResourceIDList(ID_RAND);
	for (uint i = 0; i < randResources.size(); i++) {
		Common::SeekableReadStream *stream = library._archive->getResource(ID_RAND, randResources[i]);
		Common::Array<RandomEvent> &events = _randomEvents[randResources[i]];
		uint16 count = stream->readUint16LE();
		for (uint j = 0; j < count; j++) {
			RandomEvent random;
			random.scriptId = stream->readUint16LE();
			random.weight = stream->readUint16LE();
			events.push_back(random);
		}
		delete stream;
	}

	// add background sprite, if it exists
	if (hasResource(ID_BMAP, 1000))
		setBackground(1000);

	// TODO: better CTBL logic
	loadCTBL(1000, 100);

	// Run the startup script.
	runScript(1000, 0, 0, 0);

	_mouseEnabled = true;
	onMouseMove(_lastMousePos);

	runEvent(kEventLoad, id, 0, 0);
}
Пример #14
0
void DrasculaEngine::screenSaver() {
	int xr, yr;
	byte *copia, *ghost;
	float coeff = 0, coeff2 = 0;
	int count = 0;
	int count2 = 0;
	int tempLine[320];
	int tempRow[200];

	hideCursor();

	clearRoom();

	loadPic("sv.alg", bgSurface, HALF_PAL);

	// inicio_ghost();
	copia = (byte *)malloc(64000);
	ghost = (byte *)malloc(65536);

	// carga_ghost();
	Common::SeekableReadStream *stream = _archives.open("ghost.drv");
	if (!stream)
		error("Cannot open file ghost.drv");

	stream->read(ghost, 65536);
	delete stream;

	updateEvents();
	xr = mouseX;
	yr = mouseY;

	for (;;) {
		// efecto(bgSurface);

		memcpy(copia, bgSurface, 64000);
		coeff += 0.1f;
		coeff2 = coeff;

		if (++count > 319)
			count = 0;

		for (int i = 0; i < 320; i++) {
			tempLine[i] = (int)(sin(coeff2) * 16);
			coeff2 += 0.02f;
			tempLine[i] = checkWrapY(tempLine[i]);
		}

		coeff2 = coeff;
		for (int i = 0; i < 200; i++) {
			tempRow[i] = (int)(sin(coeff2) * 16);
			coeff2 += 0.02f;
			tempRow[i] = checkWrapX(tempRow[i]);
		}

		if (++count2 > 199)
			count2 = 0;

		int x1_, y1_, off1, off2;

		byte *screenBuffer = (byte *)_system->lockScreen()->pixels;
		for (int i = 0; i < 200; i++) {
			for (int j = 0; j < 320; j++) {
				x1_ = j + tempRow[i];
				x1_ = checkWrapX(x1_);

				y1_ = i + count2;
				y1_ = checkWrapY(y1_);

				off1 = 320 * y1_ + x1_;

				x1_ = j + count;
				x1_ = checkWrapX(x1_);

				y1_ = i + tempLine[j];
				y1_ = checkWrapY(y1_);
				off2 = 320 * y1_ + x1_;

				screenBuffer[320 * i + j] = ghost[bgSurface[off2] + (copia[off1] << 8)];
			}
		}

		_system->unlockScreen();
		_system->updateScreen();

		_system->delayMillis(20);

		// end of efecto()

		updateEvents();
		if (rightMouseButton == 1 || leftMouseButton == 1)
			break;
		if (mouseX != xr)
			break;
		if (mouseY != yr)
			break;
	}
	// fin_ghost();
	free(copia);
	free(ghost);

	loadPic(roomNumber, bgSurface, HALF_PAL);
	showCursor();
}
Пример #15
0
/**
 * Savegame format detector
 * @param fHandle Savefile to check
 * @return Savegame format on success, ANIMSIZE_UNKNOWN on failure
 *
 * This function seeks through the savefile and tries to determine the
 * savegame format it uses. There's a miniscule chance that the detection
 * algorithm could get confused and think that the file uses both the older
 * and the newer format but that is such a remote possibility that I wouldn't
 * worry about it at all.
 *
 * Also detects the temporary Operation Stealth savegame format now.
 */
enum CineSaveGameFormat detectSaveGameFormat(Common::SeekableReadStream &fHandle) {
    const uint32 prevStreamPos = fHandle.pos();

    // First check for the temporary Operation Stealth savegame format.
    fHandle.seek(0);
    ChunkHeader hdr;
    loadChunkHeader(fHandle, hdr);
    fHandle.seek(prevStreamPos);
    if (hdr.id == TEMP_OS_FORMAT_ID) {
        return TEMP_OS_FORMAT;
    }

    // Ok, so the savegame isn't using the temporary Operation Stealth savegame format.
    // Let's check for the plain Future Wars savegame format and its different versions then.
    // The animDataTable begins at savefile position 0x2315.
    // Each animDataTable entry takes 23 bytes in older saves (Revisions 21772-31443)
    // and 30 bytes in the save format after that (Revision 31444 and onwards).
    // There are 255 entries in the animDataTable in both of the savefile formats.
    static const uint animDataTableStart = 0x2315;
    static const uint animEntriesCount = 255;
    static const uint oldAnimEntrySize = 23;
    static const uint newAnimEntrySize = 30;
    static const uint animEntrySizeChoices[] = {oldAnimEntrySize, newAnimEntrySize};
    Common::Array<uint> animEntrySizeMatches;

    // Try to walk through the savefile using different animDataTable entry sizes
    // and make a list of all the successful entry sizes.
    for (uint i = 0; i < ARRAYSIZE(animEntrySizeChoices); i++) {
        // 206 = 2 * 50 * 2 + 2 * 3 (Size of global and object script entries)
        // 20 = 4 * 2 + 2 * 6 (Size of overlay and background incrust entries)
        static const uint sizeofScreenParams = 2 * 6;
        static const uint globalScriptEntrySize = 206;
        static const uint objectScriptEntrySize = 206;
        static const uint overlayEntrySize = 20;
        static const uint bgIncrustEntrySize = 20;
        static const uint chainEntrySizes[] = {
            globalScriptEntrySize,
            objectScriptEntrySize,
            overlayEntrySize,
            bgIncrustEntrySize
        };

        uint animEntrySize = animEntrySizeChoices[i];
        // Jump over the animDataTable entries and the screen parameters
        int32 newPos = animDataTableStart + animEntrySize * animEntriesCount + sizeofScreenParams;
        // Check that there's data left after the point we're going to jump to
        if (newPos >= fHandle.size()) {
            continue;
        }
        fHandle.seek(newPos);

        // Jump over the remaining items in the savegame file
        // (i.e. the global scripts, object scripts, overlays and background incrusts).
        bool chainWalkSuccess = true;
        for (uint chainIndex = 0; chainIndex < ARRAYSIZE(chainEntrySizes); chainIndex++) {
            // Read entry count and jump over the entries
            int entryCount = fHandle.readSint16BE();
            newPos = fHandle.pos() + chainEntrySizes[chainIndex] * entryCount;
            // Check that we didn't go past the end of file.
            // Note that getting exactly to the end of file is acceptable.
            if (newPos > fHandle.size()) {
                chainWalkSuccess = false;
                break;
            }
            fHandle.seek(newPos);
        }

        // If we could walk the chain successfully and
        // got exactly to the end of file then we've got a match.
        if (chainWalkSuccess && fHandle.pos() == fHandle.size()) {
            // We found a match, let's save it
            animEntrySizeMatches.push_back(animEntrySize);
        }
    }

    // Check that we got only one entry size match.
    // If we didn't, then return an error.
    enum CineSaveGameFormat result = ANIMSIZE_UNKNOWN;
    if (animEntrySizeMatches.size() == 1) {
        const uint animEntrySize = animEntrySizeMatches[0];
        assert(animEntrySize == oldAnimEntrySize || animEntrySize == newAnimEntrySize);
        if (animEntrySize == oldAnimEntrySize) {
            result = ANIMSIZE_23;
        } else { // animEntrySize == newAnimEntrySize
            // Check data and mask pointers in all of the animDataTable entries
            // to see whether we've got the version with the broken data and mask pointers or not.
            // In the broken format all data and mask pointers were always zero.
            static const uint relativeDataPos = 2 * 4;
            bool pointersIntact = false;
            for (uint i = 0; i < animEntriesCount; i++) {
                fHandle.seek(animDataTableStart + i * animEntrySize + relativeDataPos);
                uint32 data = fHandle.readUint32BE();
                uint32 mask = fHandle.readUint32BE();
                if ((data != 0) || (mask != 0)) {
                    pointersIntact = true;
                    break;
                }
            }
            result = (pointersIntact ? ANIMSIZE_30_PTRS_INTACT : ANIMSIZE_30_PTRS_BROKEN);
        }
    } else if (animEntrySizeMatches.size() > 1) {
        warning("Savegame format detector got confused by input data. Detecting savegame to be using an unknown format");
    } else { // animEtrySizeMatches.size() == 0
        debug(3, "Savegame format detector was unable to detect savegame's format");
    }

    fHandle.seek(prevStreamPos);
    return result;
}
Пример #16
0
void GameModule::loadActions(Common::SeekableReadStream &s) {
	debug(0, "GameModule::loadActions()");

	s.seek(0x180);
	_actionsCount = s.readUint32LE();
	uint32 offs = s.readUint32LE();
	_actions = new Action[_actionsCount];
	for (int i = 0; i < _actionsCount; ++i) {
		s.seek(offs + i * 72);
		debug(0, "Action(%d) offs: %08X", i, offs + i * 72);
		_actions[i].conditions = readConditions(s);
		for (int j = 0; j < 8; ++j) {
			_actions[i].results.actionResults[j].kind = s.readByte();
			_actions[i].results.actionResults[j].value1 = s.readByte();
			_actions[i].results.actionResults[j].value2 = s.readUint16LE();
		}
		const int actionListCount = s.readUint32LE();
		const uint32 actionListOffs = s.readUint32LE();
		s.seek(actionListOffs);
		for (int j = 0; j < actionListCount; ++j) {
			ActionCommand actionCommand;
			actionCommand.cmd = s.readUint16LE();
			actionCommand.sceneObjectIndex = s.readUint16LE();
			actionCommand.timeStamp = s.readUint32LE();
			actionCommand.walkDest = readPoint(s);
			actionCommand.param = s.readUint32LE();
			_actions[i].actionCommands.push_back(actionCommand);
		}
	}
}
Пример #17
0
/**
 * Load animDataTable from save
 * @param fHandle Savefile open for reading
 * @param saveGameFormat The used savegame format
 * @todo Add Operation Stealth savefile support
 *
 * Unlike the old code, this one actually rebuilds the table one frame
 * at a time.
 */
void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat) {
    int16 foundFileIdx;
    char *animName, part[256], name[10];

    strcpy(part, currentPartName);

    // We only support these variations of the savegame format at the moment.
    assert(saveGameFormat == ANIMSIZE_23 || saveGameFormat == ANIMSIZE_30_PTRS_INTACT);

    const int entrySize = ((saveGameFormat == ANIMSIZE_23) ? 23 : 30);
    const int fileStartPos = fHandle.pos();

    for(int resourceIndex=0; resourceIndex<NUM_MAX_ANIMDATA; resourceIndex++) {
        // Seek to the start of the current animation's entry
        fHandle.seek(fileStartPos + resourceIndex * entrySize);
        // Read in the current animation entry
        fHandle.readUint16BE(); // width
        fHandle.readUint16BE();
        fHandle.readUint16BE(); // bpp
        fHandle.readUint16BE(); // height

        bool validPtr = false;
        // Handle variables only present in animation entries of size 30
        if (entrySize == 30) {
            validPtr = (fHandle.readUint32BE() != 0); // Read data pointer
            fHandle.readUint32BE(); // Discard mask pointer
        }

        foundFileIdx = fHandle.readSint16BE();
        int16 frameIndex = fHandle.readSint16BE(); // frame
        fHandle.read(name, 10);

        // Handle variables only present in animation entries of size 23
        if (entrySize == 23) {
            validPtr = (fHandle.readByte() != 0);
        }

        // Don't try to load invalid entries.
        if (foundFileIdx < 0 || !validPtr) {
            //resourceIndex++; // Jump over the invalid entry
            continue;
        }

        // Alright, the animation entry looks to be valid so let's start handling it...
        if (strcmp(currentPartName, name) != 0) {
            closePart();
            loadPart(name);
        }

        animName = g_cine->_partBuffer[foundFileIdx].partName;
        loadRelatedPalette(animName); // Is this for Future Wars only?
        loadResource(animName, resourceIndex, frameIndex);
    }

    loadPart(part);

    // Make sure we jump over all the animation entries
    fHandle.seek(fileStartPos + NUM_MAX_ANIMDATA * entrySize);
}
Пример #18
0
bool loadCommandVariables(Common::SeekableReadStream &in) {
    for (int i = 0; i < 4; i++) {
        commandVar3[i] = in.readUint16BE();
    }
    return !(in.eos() || in.err());
}
Пример #19
0
InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
	: Control(engine, key, CONTROL_INPUT),
	  _nextTabstop(0),
	  _focused(false),
	  _textChanged(false),
	  _cursorOffset(0),
	  _enterPressed(false),
	  _readOnly(false),
	  _txtWidth(0),
	  _animation(NULL) {
	// Loop until we find the closing brace
	Common::String line = stream.readLine();
	trimCommentsAndWhiteSpace(&line);
	Common::String param;
	Common::String values;
	getParams(line, param, values);

	while (!stream.eos() && !line.contains('}')) {
		if (param.matchString("rectangle", true)) {
			int x1;
			int y1;
			int x2;
			int y2;

			sscanf(values.c_str(), "%d %d %d %d", &x1, &y1, &x2, &y2);

			_textRectangle = Common::Rect(x1, y1, x2, y2);
		} else if (param.matchString("aux_hotspot", true)) {
			int x1;
			int y1;
			int x2;
			int y2;

			sscanf(values.c_str(), "%d %d %d %d", &x1, &y1, &x2, &y2);

			_headerRectangle = Common::Rect(x1, y1, x2, y2);
		} else if (param.matchString("string_init", true)) {
			uint fontFormatNumber;

			sscanf(values.c_str(), "%u", &fontFormatNumber);

			_stringInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber));
		} else if (param.matchString("chooser_init_string", true)) {
			uint fontFormatNumber;

			sscanf(values.c_str(), "%u", &fontFormatNumber);

			_stringChooserInit.readAllStyle(_engine->getStringManager()->getTextLine(fontFormatNumber));
		} else if (param.matchString("next_tabstop", true)) {
			sscanf(values.c_str(), "%u", &_nextTabstop);
		} else if (param.matchString("cursor_dimensions", true)) {
			// Ignore, use the dimensions in the animation file
		} else if (param.matchString("cursor_animation_frames", true)) {
			// Ignore, use the frame count in the animation file
		} else if (param.matchString("cursor_animation", true)) {
			char fileName[25];

			sscanf(values.c_str(), "%25s %*u", fileName);

			_animation = new MetaAnimation(fileName, _engine);
			_frame = -1;
			_frameDelay = 0;
		} else if (param.matchString("focus", true)) {
			_focused = true;
			_engine->getScriptManager()->setFocusControlKey(_key);
		} else if (param.matchString("venus_id", true)) {
			_venusId = atoi(values.c_str());
		}

		line = stream.readLine();
		trimCommentsAndWhiteSpace(&line);
		getParams(line, param, values);
	}
}
Пример #20
0
bool loadSeqList(Common::SeekableReadStream &in) {
    uint size = in.readUint16BE();
    SeqListElement tmp;
    for (uint i = 0; i < size; i++) {
        tmp.var4   = in.readSint16BE();
        tmp.objIdx = in.readUint16BE();
        tmp.var8   = in.readSint16BE();
        tmp.frame  = in.readSint16BE();
        tmp.varC   = in.readSint16BE();
        tmp.varE   = in.readSint16BE();
        tmp.var10  = in.readSint16BE();
        tmp.var12  = in.readSint16BE();
        tmp.var14  = in.readSint16BE();
        tmp.var16  = in.readSint16BE();
        tmp.var18  = in.readSint16BE();
        tmp.var1A  = in.readSint16BE();
        tmp.var1C  = in.readSint16BE();
        tmp.var1E  = in.readSint16BE();
        g_cine->_seqList.push_back(tmp);
    }
    return !(in.eos() || in.err());
}
Пример #21
0
void Font::setFontM4(const char *filename) {
	Common::SeekableReadStream *fontFile = _vm->res()->openFile(filename);

	if (fontFile->readUint32LE() != MKTAG('F','O','N','T')) {
		debugCN(kDebugGraphics, "Font::Font: FONT tag expected\n");
		return;
	}

	_maxHeight = fontFile->readByte();
	_maxWidth = fontFile->readByte();
	uint32 fontSize = fontFile->readUint32LE();

	//debugCN(kDebugGraphics, "Font::Font: _maxWidth = %d, _maxHeight = %d, fontSize = %d\n", _maxWidth, _maxHeight, fontSize);

	if (fontFile->readUint32LE() != MKTAG('W','I','D','T')) {
		debugCN(kDebugGraphics, "Font::Font: WIDT tag expected\n");
		return;
	}

	_charWidths = new uint8[256];
	fontFile->read(_charWidths, 256);

	if (fontFile->readUint32LE() != MKTAG('O','F','F','S')) {
		debugCN(kDebugGraphics, "Font::Font: OFFS tag expected\n");
		return;
	}

	_charOffs = new uint16[256];

	for (int i = 0; i < 256; i++)
		_charOffs[i] = fontFile->readUint16LE();

	if (fontFile->readUint32LE() != MKTAG('P','I','X','S')) {
		debugCN(kDebugGraphics, "Font::Font: PIXS tag expected\n");
		return;
	}

	_charData = new uint8[fontSize];
	fontFile->read(_charData, fontSize);

	_vm->res()->toss(filename);
}
Пример #22
0
bool loadZoneQuery(Common::SeekableReadStream &in) {
    for (int i = 0; i < 16; i++) {
        g_cine->_zoneQuery[i] = in.readUint16BE();
    }
    return !(in.eos() || in.err());
}
Пример #23
0
void TattooMap::loadData() {
	Resources &res = *_vm->_res;
	char c;

	Common::SeekableReadStream *stream = res.load("map.txt");

	_data.resize(100);
	for (uint idx = 0; idx < _data.size(); ++idx)
		_data[idx].clear();

	do
	{
		// Find the start of the number
		do {
			c = stream->readByte();
			if (stream->pos() >= stream->size())
				return;
		} while (c < '0' || c > '9');

		// Get the scene number
		Common::String locStr;
		locStr += c;
		while ((c = stream->readByte()) != '.')
			locStr += c;
		MapEntry &mapEntry = _data[atoi(locStr.c_str()) - 1];

		// Get the location name
		while (stream->readByte() != '"')
			;

		while ((c = stream->readByte()) != '"')
			mapEntry._description += c;

		// Find the ( specifying the (X,Y) position of the Icon
		while (stream->readByte() != '(')
			;

		// Get the X Position of the icon
		Common::String numStr;
		while ((c = stream->readByte()) != ',')
			numStr += c;
		mapEntry.x = atoi(numStr.c_str());

		// Get the Y position of the icon
		numStr = "";
		while ((c = stream->readByte()) != ')')
			numStr += c;
		mapEntry.y = atoi(numStr.c_str());

		// Find and get the location's icon number
		while (stream->readByte() != '#')
			;

		Common::String iconStr;
		while (stream->pos() < stream->size() && (c = stream->readByte()) != '\r')
			iconStr += c;

		mapEntry._iconNum = atoi(iconStr.c_str()) - 1;
	} while (stream->pos() < stream->size());

	delete stream;
}
Пример #24
0
bool loadChunkHeader(Common::SeekableReadStream &in, ChunkHeader &header) {
    header.id      = in.readUint32BE();
    header.version = in.readUint32BE();
    header.size    = in.readUint32BE();
    return !(in.eos() || in.err());
}
Пример #25
0
void TitanicEngine::setRoomNames() {
	Common::SeekableReadStream *r = g_vm->_filesManager->getResource("TEXT/ROOM_NAMES");
	while (r->pos() < r->size())
		_roomNames.push_back(readStringFromStream(r));
	delete r;
}
Пример #26
0
bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) {
    char musicName[13];
    char bgNames[8][13];

    // First check the temporary Operation Stealth savegame format header.
    ChunkHeader hdr;
    loadChunkHeader(in, hdr);
    if (hdr.id != TEMP_OS_FORMAT_ID) {
        warning("loadTempSaveOS: File has incorrect identifier. Not loading savegame");
        return false;
    } else if (hdr.version > CURRENT_OS_SAVE_VER) {
        warning("loadTempSaveOS: Detected newer format version. Not loading savegame");
        return false;
    } else if ((int)hdr.version < (int)CURRENT_OS_SAVE_VER) {
        warning("loadTempSaveOS: Detected older format version. Trying to load nonetheless. Things may break");
    } else { // hdr.id == TEMP_OS_FORMAT_ID && hdr.version == CURRENT_OS_SAVE_VER
        debug(3, "loadTempSaveOS: Found correct header (Both the identifier and version number match).");
    }

    // There shouldn't be any data in the header's chunk currently so it's an error if there is.
    if (hdr.size > 0) {
        warning("loadTempSaveOS: Format header's chunk seems to contain data so format is incorrect. Not loading savegame");
        return false;
    }

    // Ok, so we've got a correct header for a temporary Operation Stealth savegame.
    // Let's start loading the plain savegame data then.
    currentDisk = in.readUint16BE();
    in.read(currentPartName, 13);
    in.read(currentPrcName, 13);
    in.read(currentRelName, 13);
    in.read(currentMsgName, 13);

    // Load the 8 background names.
    for (uint i = 0; i < 8; i++) {
        in.read(bgNames[i], 13);
    }

    in.read(currentCtName, 13);

    // Moved the loading of current procedure, relation,
    // backgrounds and Ct here because if they were at the
    // end of this function then the global scripts loading
    // made an array out of bounds access. In the original
    // game's disassembly these aren't here but at the end.
    // The difference is probably in how we handle loading
    // the global scripts and some other things (i.e. the
    // loading routines aren't exactly the same and subtle
    // semantic differences result in having to do things
    // in a different order).
    {
        // Not sure if this is needed with Operation Stealth...
        checkDataDisk(currentDisk);

        if (strlen(currentPrcName)) {
            loadPrc(currentPrcName);
        }

        if (strlen(currentRelName)) {
            loadRel(currentRelName);
        }

        // Load first background (Uses loadBg)
        if (strlen(bgNames[0])) {
            loadBg(bgNames[0]);
        }

        // Add backgrounds 1-7 (Uses addBackground)
        for (int i = 1; i < 8; i++) {
            if (strlen(bgNames[i])) {
                addBackground(bgNames[i], i);
            }
        }

        if (strlen(currentCtName)) {
            loadCtOS(currentCtName);
        }
    }

    loadObjectTable(in);
    renderer->restorePalette(in, hdr.version);
    g_cine->_globalVars.load(in, NUM_MAX_VAR);
    loadZoneData(in);
    loadCommandVariables(in);
    char tempCommandBuffer[kMaxCommandBufferSize];
    in.read(tempCommandBuffer, kMaxCommandBufferSize);
    g_cine->_commandBuffer = tempCommandBuffer;
    renderer->setCommand(g_cine->_commandBuffer);
    loadZoneQuery(in);

    // TODO: Use the loaded string (Current music name (String, 13 bytes)).
    in.read(musicName, 13);

    // TODO: Use the loaded value (Is music loaded? (Uint16BE, Boolean)).
    in.readUint16BE();

    // TODO: Use the loaded value (Is music playing? (Uint16BE, Boolean)).
    in.readUint16BE();

    renderer->_cmdY      = in.readUint16BE();
    in.readUint16BE(); // Some unknown variable that seems to always be zero
    allowPlayerInput     = in.readUint16BE();
    playerCommand        = in.readUint16BE();
    commandVar1          = in.readUint16BE();
    isDrawCommandEnabled = in.readUint16BE();
    var5                 = in.readUint16BE();
    var4                 = in.readUint16BE();
    var3                 = in.readUint16BE();
    var2                 = in.readUint16BE();
    commandVar2          = in.readUint16BE();
    renderer->_messageBg = in.readUint16BE();

    // TODO: Use the loaded value (adBgVar1 (Uint16BE)).
    in.readUint16BE();

    currentAdditionalBgIdx = in.readSint16BE();
    currentAdditionalBgIdx2 = in.readSint16BE();

    // TODO: Check whether the scroll value really gets used correctly after this.
    // Note that the backgrounds are loaded only later than this value is set.
    renderer->setScroll(in.readUint16BE());

    // TODO: Use the loaded value (adBgVar0 (Uint16BE). Maybe this means bgVar0?).
    in.readUint16BE();

    disableSystemMenu = in.readUint16BE();

    // TODO: adBgVar1 = 1 here

    // Load the animDataTable entries
    in.readUint16BE(); // Entry count (255 in the PC version of Operation Stealth).
    in.readUint16BE(); // Entry size (36 in the PC version of Operation Stealth).
    loadResourcesFromSave(in, ANIMSIZE_30_PTRS_INTACT);

    loadScreenParams(in);
    loadGlobalScripts(in);
    loadObjectScripts(in);
    loadSeqList(in);
    loadOverlayList(in);
    loadBgIncrustFromSave(in);

    // Left this here instead of moving it earlier in this function with
    // the other current value loadings (e.g. loading of current procedure,
    // current backgrounds etc). Mostly emulating the way we've handled
    // Future Wars savegames and hoping that things work out.
    if (strlen(currentMsgName)) {
        loadMsg(currentMsgName);
    }

    // TODO: Add current music loading and playing here
    // TODO: Palette handling?

    if (in.pos() == in.size()) {
        debug(3, "loadTempSaveOS: Loaded the whole savefile.");
    } else {
        warning("loadTempSaveOS: Loaded the savefile but didn't exhaust it completely. Something was left over");
    }

    return !(in.eos() || in.err());
}
Пример #27
0
// Additional information found from http://paulbourke.net/dataformats/tga/
// With some details from the link referenced in the header.
bool TGADecoder::readData(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth) {
	// TrueColor
	if (imageType == TYPE_TRUECOLOR) {
		_surface.create(_surface.w, _surface.h, _format);

		if (pixelDepth == 16) {
			for (int i = 0; i < _surface.h; i++) {
				uint16 *dst;
				if (!_originTop) {
					dst = (uint16 *)_surface.getBasePtr(0, _surface.h - i - 1);
				} else {
					dst = (uint16 *)_surface.getBasePtr(0, i);
				}
				for (int j = 0; j < _surface.w; j++) {
					*dst++ = tga.readUint16LE();
				}
			}
		} else if (pixelDepth == 32) {
			for (int i = 0; i < _surface.h; i++) {
				uint32 *dst;
				if (!_originTop) {
					dst = (uint32 *)_surface.getBasePtr(0, _surface.h - i - 1);
				} else {
					dst = (uint32 *)_surface.getBasePtr(0, i);
				}
				for (int j = 0; j < _surface.w; j++) {
					*dst++ = tga.readUint32LE();
				}
			}
		} else if (pixelDepth == 24) {
			for (int i = 0; i < _surface.h; i++) {
				byte *dst;
				if (!_originTop) {
					dst = (byte *)_surface.getBasePtr(0, _surface.h - i - 1);
				} else {
					dst = (byte *)_surface.getBasePtr(0, i);
				}
				for (int j = 0; j < _surface.w; j++) {
					byte r = tga.readByte();
					byte g = tga.readByte();
					byte b = tga.readByte();
#ifdef SCUMM_LITTLE_ENDIAN
					*dst++ = r;
					*dst++ = g;
					*dst++ = b;
#else
					*dst++ = b;
					*dst++ = g;
					*dst++ = r;
#endif
				}
			}
		}
		// Black/White
	} else if (imageType == TYPE_BW) {
		_surface.create(_surface.w, _surface.h, _format);

		byte *data  = (byte *)_surface.getPixels();
		uint32 count = _surface.w * _surface.h;

		while (count-- > 0) {
			byte g = tga.readByte();
			*data++ = g;
			*data++ = g;
			*data++ = g;
			*data++ = g;
		}
	}
	return true;
}
Пример #28
0
bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFormat saveGameFormat) {
    char bgName[13];

    // At savefile position 0x0000:
    currentDisk = in.readUint16BE();

    // At 0x0002:
    in.read(currentPartName, 13);
    // At 0x000F:
    in.read(currentDatName, 13);

    // At 0x001C:
    musicIsPlaying = in.readSint16BE();

    // At 0x001E:
    in.read(currentPrcName, 13);
    // At 0x002B:
    in.read(currentRelName, 13);
    // At 0x0038:
    in.read(currentMsgName, 13);
    // At 0x0045:
    in.read(bgName, 13);
    // At 0x0052:
    in.read(currentCtName, 13);

    checkDataDisk(currentDisk);

    if (strlen(currentPartName)) {
        loadPart(currentPartName);
    }

    if (strlen(currentPrcName)) {
        loadPrc(currentPrcName);
    }

    if (strlen(currentRelName)) {
        loadRel(currentRelName);
    }

    if (strlen(bgName)) {
        loadBg(bgName);
    }

    if (strlen(currentCtName)) {
        loadCtFW(currentCtName);
    }

    // At 0x005F:
    loadObjectTable(in);

    // At 0x2043 (i.e. 0x005F + 2 * 2 + 255 * 32):
    renderer->restorePalette(in, 0);

    // At 0x2083 (i.e. 0x2043 + 16 * 2 * 2):
    g_cine->_globalVars.load(in, NUM_MAX_VAR);

    // At 0x2281 (i.e. 0x2083 + 255 * 2):
    loadZoneData(in);

    // At 0x22A1 (i.e. 0x2281 + 16 * 2):
    loadCommandVariables(in);

    // At 0x22A9 (i.e. 0x22A1 + 4 * 2):
    char tempCommandBuffer[kMaxCommandBufferSize];
    in.read(tempCommandBuffer, kMaxCommandBufferSize);
    g_cine->_commandBuffer = tempCommandBuffer;
    renderer->setCommand(g_cine->_commandBuffer);

    // At 0x22F9 (i.e. 0x22A9 + 0x50):
    renderer->_cmdY = in.readUint16BE();

    // At 0x22FB:
    bgVar0 = in.readUint16BE();
    // At 0x22FD:
    allowPlayerInput = in.readUint16BE();
    // At 0x22FF:
    playerCommand = in.readSint16BE();
    // At 0x2301:
    commandVar1 = in.readSint16BE();
    // At 0x2303:
    isDrawCommandEnabled = in.readUint16BE();
    // At 0x2305:
    var5 = in.readUint16BE();
    // At 0x2307:
    var4 = in.readUint16BE();
    // At 0x2309:
    var3 = in.readUint16BE();
    // At 0x230B:
    var2 = in.readUint16BE();
    // At 0x230D:
    commandVar2 = in.readSint16BE();

    // At 0x230F:
    renderer->_messageBg = in.readUint16BE();

    // At 0x2311:
    in.readUint16BE();
    // At 0x2313:
    in.readUint16BE();

    // At 0x2315:
    loadResourcesFromSave(in, saveGameFormat);

    loadScreenParams(in);
    loadGlobalScripts(in);
    loadObjectScripts(in);
    loadOverlayList(in);
    loadBgIncrustFromSave(in);

    if (strlen(currentMsgName)) {
        loadMsg(currentMsgName);
    }

    if (strlen(currentDatName)) {
        g_sound->loadMusic(currentDatName);
        if (musicIsPlaying) {
            g_sound->playMusic();
        }
    }

    return !(in.eos() || in.err());
}
Пример #29
0
bool TGADecoder::readHeader(Common::SeekableReadStream &tga, byte &imageType, byte &pixelDepth) {
	if (!tga.seek(0)) {
		warning("Failed reading TGA-file");
		return false;
	}

	// TGAs have an optional "id" string in the header
	uint32 idLength = tga.readByte();

	// Number of colors in the color map / palette
	int hasColorMap = tga.readByte();

	// Image type. See header for numeric constants
	imageType = tga.readByte();

	switch (imageType) {
	case TYPE_CMAP:
	case TYPE_TRUECOLOR:
	case TYPE_BW:
	case TYPE_RLE_CMAP:
	case TYPE_RLE_TRUECOLOR:
	case TYPE_RLE_BW:
		break;
	default:
		warning("Unsupported image type: %d", imageType);
		return false;
	}

	// Color map specifications
	if (hasColorMap == 0) {
		tga.skip(5);
	} else {
		_colorMapOrigin = tga.readUint16LE();
		_colorMapLength = tga.readUint16LE();
		_colorMapEntryLength = tga.readByte();
	}
	// Origin-defintions
	tga.skip(2 + 2);

	// Image dimensions
	_surface.w = tga.readUint16LE();
	_surface.h = tga.readUint16LE();

	// Bits per pixel
	pixelDepth = tga.readByte();
	_surface.format.bytesPerPixel = pixelDepth / 8;

	// Image descriptor
	byte imgDesc = tga.readByte();
	int attributeBits = imgDesc & 0x0F;
	assert((imgDesc & 0x10) == 0);
	_originTop = (imgDesc & 0x20);

	// Interleaving is not handled at this point
	//int interleave = (imgDesc & 0xC);
	if (imageType == TYPE_CMAP || imageType == TYPE_RLE_CMAP) {
		if (pixelDepth == 8) {
			_format = Graphics::PixelFormat::createFormatCLUT8();
		} else {
			warning("Unsupported index-depth: %d", pixelDepth);
			return false;
		}
	} else if (imageType == TYPE_TRUECOLOR || imageType == TYPE_RLE_TRUECOLOR) {
		if (pixelDepth == 24) {
			_format = Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
		} else if (pixelDepth == 32) {
			// HACK: According to the spec, attributeBits should determine the amount
			// of alpha-bits, however, as the game files that use this decoder seems
			// to ignore that fact, we force the amount to 8 for 32bpp files for now.
			_format = Graphics::PixelFormat(4, 8, 8, 8, /* attributeBits */ 8, 16, 8, 0, 24);
		} else if (pixelDepth == 16) {
			// 16bpp TGA is ARGB1555
			_format = Graphics::PixelFormat(2, 5, 5, 5, attributeBits, 10, 5, 0, 15);
		} else {
			warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth);
			return false;
		}
	} else if (imageType == TYPE_BW || imageType == TYPE_RLE_BW) {
		if (pixelDepth == 8) {
			_format = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
		} else {
			warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth);
			return false;
		}

	} else {
		warning("Unsupported image type: %d", imageType);
		return false;
	}

	// Skip the id string
	tga.skip(idLength);

	if (hasColorMap) {
		return readColorMap(tga, imageType, pixelDepth);
	}
	return true;
}
Пример #30
0
bool WinCursor::readFromStream(Common::SeekableReadStream &stream) {
	clear();

	_hotspotX = stream.readUint16LE();
	_hotspotY = stream.readUint16LE();

	// Check header size
	if (stream.readUint32LE() != 40)
		return false;

	// Check dimensions
	_width = stream.readUint32LE();
	_height = stream.readUint32LE() / 2;

	if (_width & 3) {
		// Cursors should always be a power of 2
		// Of course, it wouldn't be hard to handle but if we have no examples...
		warning("Non-divisible-by-4 width cursor found");
		return false;
	}

	// Color planes
	if (stream.readUint16LE() != 1)
		return false;

	// Only 1bpp and 8bpp supported
	uint16 bitsPerPixel = stream.readUint16LE();
	if (bitsPerPixel != 1 && bitsPerPixel != 8)
		return false;

	// Compression
	if (stream.readUint32LE() != 0)
		return false;

	// Image size + X resolution + Y resolution
	stream.skip(12);

	uint32 numColors = stream.readUint32LE();

	// If the color count is 0, then it uses up the maximum amount
	if (numColors == 0)
		numColors = 1 << bitsPerPixel;

	// Reading the palette
	stream.seek(40 + 4);
	for (uint32 i = 0 ; i < numColors; i++) {
		_palette[i * 3 + 2] = stream.readByte();
		_palette[i * 3 + 1] = stream.readByte();
		_palette[i * 3    ] = stream.readByte();
		stream.readByte();
	}

	// Reading the bitmap data
	uint32 dataSize = stream.size() - stream.pos();
	byte *initialSource = new byte[dataSize];
	stream.read(initialSource, dataSize);

	// Parse the XOR map
	const byte *src = initialSource;
	_surface = new byte[_width * _height];
	byte *dest = _surface + _width * (_height - 1);
	uint32 imagePitch = _width * bitsPerPixel / 8;

	for (uint32 i = 0; i < _height; i++) {
		byte *rowDest = dest;

		if (bitsPerPixel == 1) {
			// 1bpp
			for (uint16 j = 0; j < (_width / 8); j++) {
				byte p = src[j];

				for (int k = 0; k < 8; k++, rowDest++, p <<= 1) {
					if ((p & 0x80) == 0x80)
						*rowDest = 1;
					else
						*rowDest = 0;
				}
			}
		} else {
			// 8bpp
			memcpy(rowDest, src, _width);
		}

		dest -= _width;
		src += imagePitch;
	}

	// Calculate our key color
	if (numColors < 256) {
		// If we're not using the maximum colors in a byte, we can fit it in
		_keyColor = numColors;
	} else {
		// HACK: Try to find a color that's not being used so it can become
		// our keycolor. It's quite impossible to fit 257 entries into 256...
		for (uint32 i = 0; i < 256; i++) {
			for (int j = 0; j < _width * _height; j++) {
				// TODO: Also check to see if the space is transparent

				if (_surface[j] == i)
					break;

				if (j == _width * _height - 1) {
					_keyColor = i;
					i = 256;
					break;
				}
			}
		}
	}

	// Now go through and apply the AND map to get the transparency
	uint32 andWidth = (_width + 7) / 8;
	src += andWidth * (_height - 1);

	for (uint32 y = 0; y < _height; y++) {
		for (uint32 x = 0; x < _width; x++)
			if (src[x / 8] & (1 << (7 - x % 8)))
				_surface[y * _width + x] = _keyColor;

		src -= andWidth;
	}

	delete[] initialSource;
	return true;
}