diff options
| author | Marisa-Chan | 2014-06-13 21:43:04 +0700 | 
|---|---|---|
| committer | Marisa-Chan | 2014-06-13 21:43:04 +0700 | 
| commit | 45589950c0fb1a449351e6a00ef10d42290d8bae (patch) | |
| tree | 44e4eedcb7e69d5fc386155b000ed038af07251d /engines/mads/scene_data.cpp | |
| parent | 48360645dcd5f8fddb135b6e31ae5cae4be8d77f (diff) | |
| parent | 5c005ad3a3f1df0bc968c85c1cf0fc48e36ab0b2 (diff) | |
| download | scummvm-rg350-45589950c0fb1a449351e6a00ef10d42290d8bae.tar.gz scummvm-rg350-45589950c0fb1a449351e6a00ef10d42290d8bae.tar.bz2 scummvm-rg350-45589950c0fb1a449351e6a00ef10d42290d8bae.zip  | |
Merge remote-tracking branch 'upstream/master' into zvision
Conflicts:
	engines/zvision/animation/rlf_animation.cpp
	engines/zvision/animation_control.h
	engines/zvision/core/console.cpp
	engines/zvision/core/events.cpp
	engines/zvision/cursors/cursor.cpp
	engines/zvision/cursors/cursor_manager.cpp
	engines/zvision/cursors/cursor_manager.h
	engines/zvision/fonts/truetype_font.cpp
	engines/zvision/graphics/render_manager.cpp
	engines/zvision/graphics/render_manager.h
	engines/zvision/inventory/inventory_manager.h
	engines/zvision/inventory_manager.h
	engines/zvision/meta_animation.h
	engines/zvision/module.mk
	engines/zvision/scripting/actions.cpp
	engines/zvision/scripting/control.h
	engines/zvision/scripting/controls/animation_control.cpp
	engines/zvision/scripting/controls/animation_control.h
	engines/zvision/scripting/controls/input_control.cpp
	engines/zvision/scripting/controls/lever_control.cpp
	engines/zvision/scripting/controls/timer_node.cpp
	engines/zvision/scripting/controls/timer_node.h
	engines/zvision/scripting/puzzle.h
	engines/zvision/scripting/scr_file_handling.cpp
	engines/zvision/scripting/script_manager.cpp
	engines/zvision/scripting/script_manager.h
	engines/zvision/sidefx.cpp
	engines/zvision/sound/zork_raw.cpp
	engines/zvision/sound/zork_raw.h
	engines/zvision/video/video.cpp
	engines/zvision/video/zork_avi_decoder.h
	engines/zvision/zvision.cpp
	engines/zvision/zvision.h
Diffstat (limited to 'engines/mads/scene_data.cpp')
| -rw-r--r-- | engines/mads/scene_data.cpp | 463 | 
1 files changed, 463 insertions, 0 deletions
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp new file mode 100644 index 0000000000..1494f62d7a --- /dev/null +++ b/engines/mads/scene_data.cpp @@ -0,0 +1,463 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "mads/scene_data.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/screen.h" +#include "mads/resources.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +KernelMessage::KernelMessage() { +	_flags = 0; +	_sequenceIndex = 0; +	_color1 = 0; +	_color2 = 0; +	_msgOffset = 0; +	_numTicks = 0; +	_frameTimer2 = 0; +	_frameTimer = 0; +	_timeout = 0; +	_trigger = 0; +	_abortMode = SEQUENCE_TRIGGER_PARSER; +	_actionDetails._verbId = VERB_NONE; +	_actionDetails._objectNameId = 0; +	_actionDetails._indirectObjectId = 0; +	_textDisplayIndex = 0; +} + +/*------------------------------------------------------------------------*/ + +void ARTHeader::load(Common::SeekableReadStream *f, bool isV2) { +	if (!isV2) { +		// Read in dimensions of image +		_width = f->readUint16LE(); +		_height = f->readUint16LE(); +	} + +	// Read in palette information +	int palCount = f->readUint16LE(); +	for (int i = 0; i < palCount; ++i) { +		RGB6 rgb; +		rgb.load(f); +		_palette.push_back(rgb); +	} +	f->skip(6 * (256 - palCount)); + +	// Read palette animations +	int cycleCount = f->readUint16LE(); +	for (int i = 0; i < cycleCount; ++i) { +		PaletteCycle cycle; +		cycle._colorCount = f->readByte(); +		cycle._firstListColor = f->readByte(); +		cycle._firstColorIndex = f->readByte(); +		cycle._ticks = f->readByte(); + +		_paletteCycles.push_back(cycle); +	} +} + +/*------------------------------------------------------------------------*/ + +void SceneInfo::SpriteInfo::load(Common::SeekableReadStream *f) { +	f->skip(3); +	_spriteSetIndex = f->readByte(); +	f->skip(2); +	_position.x = f->readSint16LE(); +	_position.y = f->readSint16LE(); +	_depth = f->readByte(); +	_scale = f->readByte(); +} + +/*------------------------------------------------------------------------*/ + +SceneInfo::SceneInfo(MADSEngine *vm) : _vm(vm) { +	_sceneId = 0; +	_artFileNum = 0; +	_depthStyle = 0; +	_width = 0; +	_height = 0; +	_yBandsEnd = 0; +	_yBandsStart = 0; +	_maxScale = 0; +	_minScale = 0; +	_field4A = 0; +	_usageIndex = 0; +	for (int i = 0; i < 15; ++i) +		_depthList[i] = 0; +} + +SceneInfo *SceneInfo::init(MADSEngine *vm) { +	switch (vm->getGameID()) { +	case GType_RexNebular: +		return new Nebular::SceneInfoNebular(vm); +	case GType_Dragonsphere: +		return new Dragonsphere::SceneInfoDragonsphere(vm); +	case GType_Phantom: +		return new Phantom::SceneInfoPhantom(vm); +	default: +		error("SceneInfo: Unknown game"); +	} + +	return nullptr; +} + +void SceneInfo::load(int sceneId, int variant, const Common::String &resName, +		int flags, DepthSurface &depthSurface, MSurface &bgSurface) { +	bool sceneFlag = sceneId >= 0; + +	// Figure out the resource to use +	Common::String resourceName; +	if (sceneFlag) { +		resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".DAT"); +	} else { +		resourceName = "*" + Resources::formatResource(resName, resName); +	} + +	// Open the scene info resource for access +	File infoFile(resourceName); +	MadsPack infoPack(&infoFile); + +	// Read in basic data +	Common::SeekableReadStream *infoStream = infoPack.getItemStream(0); +	if (_vm->getGameID() == GType_RexNebular) { +		_sceneId = infoStream->readUint16LE(); +	} else { +		infoStream->skip(6);	// actual scene ID (string) +		_sceneId = sceneId; +	} + +	// TODO: The following isn't quite right for V2 games (it's all 0) +	_artFileNum = infoStream->readUint16LE(); +	_depthStyle = infoStream->readUint16LE(); +	_width = infoStream->readUint16LE(); +	_height = infoStream->readUint16LE(); + +	// HACK for V2 games (for now) +	if (_vm->getGameID() != GType_RexNebular) { +		_width = 320; +		_height = 156; +	} + +	infoStream->skip(24); + +	int nodeCount = infoStream->readUint16LE(); +	_yBandsEnd = infoStream->readUint16LE(); +	_yBandsStart = infoStream->readUint16LE(); +	_maxScale = infoStream->readUint16LE(); +	_minScale = infoStream->readUint16LE(); +	for (int i = 0; i < DEPTH_BANDS_SIZE; ++i) +		_depthList[i] = infoStream->readUint16LE(); +	_field4A = infoStream->readUint16LE(); + +	// Load the set of objects that are associated with the scene +	for (int i = 0; i < 20; ++i) { +		WalkNode node; +		node.load(infoStream); + +		if (i < nodeCount) +			_nodes.push_back(node); +	} + +	int spriteSetsCount  = infoStream->readUint16LE(); +	int spriteInfoCount = infoStream->readUint16LE(); + +	// Load in sprite sets +	Common::StringArray setNames; +	for (int i = 0; i < 10; ++i) { +		char name[64]; +		infoStream->read(name, 64); + +		if (i < spriteSetsCount) +			setNames.push_back(Common::String(name)); +	} + +	// Load in sprite draw information +	Common::Array<SpriteInfo> spriteInfo; +	// TODO: The following isn't quite right for V2 games +	if (_vm->getGameID() == GType_RexNebular) { +		for (int i = 0; i < 50; ++i) { +			SpriteInfo info; +			info.load(infoStream); + +			if (i < spriteInfoCount) +				spriteInfo.push_back(info); +		} +	} +	delete infoStream; + +	int width = _width; +	int height = _height; + +	if (!bgSurface.getPixels()) { +		bgSurface.setSize(width, height); +	} + +	if (_depthStyle == 2) +		width >>= 2; +	if (!depthSurface.getPixels()) { +		depthSurface.setSize(width, height); +	} + +	if (_vm->getGameID() == GType_RexNebular) { +		// Load the depth surface with the scene codes +		Common::SeekableReadStream *depthStream = infoPack.getItemStream(variant + 1); +		loadCodes(depthSurface, depthStream); +		delete depthStream; +	} + +	infoFile.close(); + +	if (_vm->getGameID() == GType_RexNebular) { +		loadMadsV1Background(sceneId, resName, flags, bgSurface); +		loadPalette(sceneId, _artFileNum, resName, flags, bgSurface); +	} else { +		loadMadsV2Background(sceneId, resName, flags, bgSurface); +		loadPalette(sceneId, sceneId, resName, flags, bgSurface); +	} + +	Common::Array<SpriteAsset *> spriteSets; +	Common::Array<int> usageList; + +	// TODO: The following isn't quite right for V2 games +	if (_vm->getGameID() == GType_RexNebular) { +		for (uint i = 0; i < setNames.size(); ++i) { +			Common::String setResName; +			if (sceneFlag || resName.hasPrefix("*")) +				setResName += "*"; +			setResName += setNames[i]; + +			SpriteAsset *sprites = new SpriteAsset(_vm, setResName, flags); +			spriteSets.push_back(sprites); +			usageList.push_back(sprites->_usageIndex); +		} +	} + +	_vm->_palette->_paletteUsage.updateUsage(usageList, _usageIndex); + +	for (uint i = 0; i < spriteInfo.size(); ++i) { +		SpriteInfo &si = spriteInfo[i]; +		SpriteAsset *asset = spriteSets[si._spriteSetIndex]; +		assert(asset && _depthStyle != 2); + +		MSprite *spr = asset->getFrame(asset->getCount() - 1); +		bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface,  +			si._scale, spr->getTransparencyIndex()); +	} + +	// Free the sprite sets +	for (int i = (int)spriteSets.size() - 1; i >= 0; --i) { +		_vm->_palette->_paletteUsage.resetPalFlags(spriteSets[i]->_usageIndex); +		delete spriteSets[i]; +	} +} + +void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, MSurface &bgSurface) { +	bool sceneFlag = sceneId >= 0; +	Common::String resourceName; +	bool isV2 = (_vm->getGameID() != GType_RexNebular); +	Common::String extension = !isV2 ? ".ART" : ".TT"; +	int paletteStream = !isV2 ? 0 : 2; + +	// Get the ART resource +	if (sceneFlag) { +		resourceName = Resources::formatName(RESPREFIX_RM, artFileNum, extension); +	} else { +		resourceName = "*" + Resources::formatResource(resName, resName); +	} + +	// Load in the ART header and palette +	File artFile(resourceName); +	MadsPack artResource(&artFile); +	Common::SeekableReadStream *stream = artResource.getItemStream(paletteStream); + +	ARTHeader artHeader; +	artHeader.load(stream, isV2); +	delete stream; + +	// Copy out the palette animation data +	for (uint i = 0; i < artHeader._paletteCycles.size(); ++i) +		_paletteCycles.push_back(artHeader._paletteCycles[i]); + +	if (!(flags & 1)) { +		if (!_vm->_palette->_paletteUsage.empty()) { +			_vm->_palette->_paletteUsage.getKeyEntries(artHeader._palette); +			_vm->_palette->_paletteUsage.prioritize(artHeader._palette); +		} + +		_usageIndex = _vm->_palette->_paletteUsage.process(artHeader._palette, +			(flags & 0xF800) | 0x8000); +		if (_usageIndex > 0) { +			_vm->_palette->_paletteUsage.transform(artHeader._palette); + +			for (uint i = 0; i < _paletteCycles.size(); ++i) { +				byte listColor = _paletteCycles[i]._firstListColor; +				_paletteCycles[i]._firstColorIndex = artHeader._palette[listColor]._palIndex; +			} +		} +	} + +	if (!(flags & 1)) { +		// Translate the background to use the correct palette indexes +		bgSurface.translate(artHeader._palette); +	} +} + +void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) { +	bool sceneFlag = sceneId >= 0; +	Common::String resourceName; +	Common::SeekableReadStream *stream; + +	// Get the ART resource +	if (sceneFlag) { +		resourceName = Resources::formatName(RESPREFIX_RM, _artFileNum, ".ART"); +	} else { +		resourceName = "*" + Resources::formatResource(resName, resName); +	} + +	// Load in the ART data +	File artFile(resourceName); +	MadsPack artResource(&artFile); + +	// Read in the background surface data +	assert(_width == bgSurface.w && _height == bgSurface.h); +	stream = artResource.getItemStream(1); +	stream->read(bgSurface.getPixels(), bgSurface.w * bgSurface.h); + +	// Close the ART file +	delete stream; +	artFile.close(); +} + +void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) { +	Common::String tileMapResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".MM"); +	File tileMapFile(tileMapResourceName); +	MadsPack tileMapPack(&tileMapFile); +	Common::SeekableReadStream *mapStream = tileMapPack.getItemStream(0); + +	// Get the details of the tiles and map +	mapStream->readUint32LE(); +	int tileCountX = mapStream->readUint16LE(); +	int tileCountY = mapStream->readUint16LE(); +	int tileWidthMap = mapStream->readUint16LE(); +	int tileHeightMap = mapStream->readUint16LE(); +	int screenWidth = mapStream->readUint16LE(); +	int screenHeight = mapStream->readUint16LE(); +	int tileCountMap = tileCountX * tileCountY; +	delete mapStream; + +	// Obtain tile map information +	typedef Common::List<Common::SharedPtr<MSurface> > TileSetList; +	typedef TileSetList::iterator TileSetIterator; +	TileSetList tileSet; +	uint16 *tileMap = new uint16[tileCountMap]; +	mapStream = tileMapPack.getItemStream(1); +	for (int i = 0; i < tileCountMap; ++i) +		tileMap[i] = mapStream->readUint16LE(); +	delete mapStream; +	tileMapFile.close(); + +	// -------------------------------------------------------------------------------- + +	// Tile data, which needs to be kept compressed, as the tile map offsets refer to +	// the compressed data. Each tile is then uncompressed separately +	Common::String tileDataResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".TT"); +	File tileDataFile(tileDataResourceName); +	MadsPack tileDataPack(&tileDataFile); +	Common::SeekableReadStream *tileDataUncomp = tileDataPack.getItemStream(0); + +	// Validate that the data matches between the tiles and tile map file and is valid +	int tileCount = tileDataUncomp->readUint16LE(); +	int tileWidth = tileDataUncomp->readUint16LE(); +	int tileHeight = tileDataUncomp->readUint16LE(); +	delete tileDataUncomp; +	assert(tileCountMap == tileCount); +	assert(tileWidth == tileWidthMap); +	assert(tileHeight == tileHeightMap); +	assert(screenWidth == _width); +	assert(screenHeight <= _height); + +	// -------------------------------------------------------------------------------- + +	// Get tile data + +	tileDataUncomp = tileDataPack.getItemStream(1); +	FabDecompressor fab; +	uint32 compressedTileDataSize = 0; + +	for (int i = 0; i < tileCount; i++) { +		tileDataUncomp->seek(i * 4, SEEK_SET); +		uint32 tileOfs = tileDataUncomp->readUint32LE(); +		MSurface* newTile = new MSurface(tileWidth, tileHeight); + +		if (i == tileCount - 1) +			compressedTileDataSize = tileDataFile.size() - tileOfs; +		else +			compressedTileDataSize = tileDataUncomp->readUint32LE() - tileOfs; + +		//debugCN(kDebugGraphics, "Tile: %i, compressed size: %i\n", i, compressedTileDataSize); + +		newTile->empty(); + +		byte *compressedTileData = new byte[compressedTileDataSize]; + +		tileDataFile.seek(tileDataPack.getDataOffset() + tileOfs, SEEK_SET); +		tileDataFile.read(compressedTileData, compressedTileDataSize); + +		fab.decompress(compressedTileData, compressedTileDataSize, (byte*)newTile->getPixels(), tileWidth * tileHeight); +		tileSet.push_back(TileSetList::value_type(newTile)); +		delete[] compressedTileData; +	} + +	delete tileDataUncomp; + +	// -------------------------------------------------------------------------------- + +	// Loop through the mapping data to place the tiles on the screen + +	uint16 *tIndex = &tileMap[0]; +	for (int y = 0; y < tileCountY; y++) { +		for (int x = 0; x < tileCountX; x++) { +			int tileIndex = *tIndex++; +			assert(tileIndex < tileCount); +			TileSetIterator tile = tileSet.begin(); +			for (int i = 0; i < tileIndex; i++) +				++tile; +			((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight)); +		} +	} +	tileSet.clear(); +	tileDataFile.close(); +} + +/*------------------------------------------------------------------------*/ + +SceneLogic::SceneLogic(MADSEngine *vm) : _vm(vm) { +	_scene = &_vm->_game->_scene; +} + +} // End of namespace MADS  | 
