diff options
| author | Paul Gilbert | 2010-05-31 12:10:30 +0000 | 
|---|---|---|
| committer | Paul Gilbert | 2010-05-31 12:10:30 +0000 | 
| commit | 088e6456ea4d009b8ab0c91176c84dce34a8ea41 (patch) | |
| tree | 0789fe834b9a6fd72ff90d276ec9912c4556134f | |
| parent | 3f4302214c334a590b8428fe7ae32c76e64b6ed5 (diff) | |
| download | scummvm-rg350-088e6456ea4d009b8ab0c91176c84dce34a8ea41.tar.gz scummvm-rg350-088e6456ea4d009b8ab0c91176c84dce34a8ea41.tar.bz2 scummvm-rg350-088e6456ea4d009b8ab0c91176c84dce34a8ea41.zip | |
In progress work implementing the animation player
svn-id: r49347
| -rw-r--r-- | engines/m4/animation.cpp | 466 | ||||
| -rw-r--r-- | engines/m4/animation.h | 107 | ||||
| -rw-r--r-- | engines/m4/assets.cpp | 25 | ||||
| -rw-r--r-- | engines/m4/assets.h | 3 | ||||
| -rw-r--r-- | engines/m4/console.cpp | 57 | ||||
| -rw-r--r-- | engines/m4/console.h | 3 | ||||
| -rw-r--r-- | engines/m4/m4.cpp | 4 | ||||
| -rw-r--r-- | engines/m4/m4.h | 1 | ||||
| -rw-r--r-- | engines/m4/mads_views.cpp | 32 | ||||
| -rw-r--r-- | engines/m4/mads_views.h | 34 | 
10 files changed, 538 insertions, 194 deletions
| diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index fe46e121f0..4b6be82fad 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -31,177 +31,397 @@ namespace M4 {  // TODO: this code needs cleanup -Animation::Animation(MadsM4Engine *vm) { -	_vm = vm; +MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _view(view) {  	_playing = false; +	_font = NULL; +	_unk1 = 0; +	_skipLoad = false; +	_unkIndex = -1; +	_messageCtr= 0;  } -void Animation::loadFullScreen(const char *filename) { -	_vm->_palette->deleteAllRanges(); -	load(filename); +MadsAnimation::~MadsAnimation() { +	delete _font;  } -void Animation::load(const char *filename) { -	MadsPack anim(filename, _vm); +void MadsAnimation::load(const Common::String &filename) { +	MadsPack anim(filename.c_str(), _vm); +	bool madsRes = filename[0] == '*';  	char buffer[20]; +	int streamIndex = 1;  	// Chunk 1: header  	// header -	// TODO: there are some unknown fields here, plus we don't read -	// the entire chunk +  	Common::SeekableReadStream *animStream = anim.getItemStream(0); -	Common::SeekableReadStream *spriteSeriesStream; -	//printf("Chunk 0, size %i\n", animStream->size()); -	_seriesCount = animStream->readUint16LE(); -	_frameCount = animStream->readUint16LE(); -	_frameEntryCount = animStream->readUint16LE(); -	// Unknown -	for (int i = 0; i < 43; i++) -		animStream->readByte(); +	int spriteListCount = animStream->readUint16LE(); +	int miscEntriesCount = animStream->readUint16LE(); +	int frameEntryCount = animStream->readUint16LE(); +	int messagesCount = animStream->readUint16LE(); +	animStream->skip(1); +	_flags = animStream->readByte(); + +	animStream->skip(2); +	_animMode = animStream->readUint16LE(); +	assert(_animMode != 4); +	_roomNumber = animStream->readUint16LE(); +	_field12 = animStream->readUint16LE() != 0; +	animStream->skip(4); +	_spriteListIndex = animStream->readUint16LE(); +	_scrollX = animStream->readUint16LE(); +	_scrollY = animStream->readSint16LE(); +	animStream->skip(10); +	 +	animStream->read(buffer, 13); +	_field24 = Common::String(buffer, 13); + +	for (int i = 0; i < 10; ++i) { +		animStream->read(buffer, 13); +		_spriteSetNames[i] = Common::String(buffer, 13); +	} -	_spriteSeriesNames = new Common::String[_seriesCount]; -	printf("%i sprite series\n", _seriesCount); +	animStream->skip(81); +	animStream->read(buffer, 13); +	_lbmFilename = Common::String(buffer, 13); +	animStream->read(buffer, 13); +	_spritesFilename = Common::String(buffer, 13); +	animStream->skip(48); +	animStream->read(buffer, 13); +	_soundName = Common::String(buffer, 13); +	animStream->skip(26); +	animStream->read(buffer, 13); +	Common::String fontResource(buffer, 13); + +	// TODO: Based on a weird usage of a flags word, a secondary method gets called here. +	// Figure out secondary method, and when/if it's called + +	// Initialise the reference list +	for (int i = 0; i < spriteListCount; ++i) +		_spriteListIndexes.push_back(-1); -	// TODO: for now, we only load the first sprite series -	if (_seriesCount > 1) -		printf("TODO: Anim has %i sprite series, for now, we only load the first one\n", _seriesCount); -	_seriesCount = 1;		// TODO +	delete animStream; -	for (int i = 0; i < _seriesCount; i++) { -		animStream->read(buffer, 13); -		_spriteSeriesNames[i] = Common::String(buffer); -		//printf("%03d: %s\n", i, _spriteSeriesNames[i].c_str()); - -		spriteSeriesStream = _vm->res()->get(_spriteSeriesNames[i].c_str()); -		_spriteSeries = new SpriteAsset(_vm, spriteSeriesStream, -										spriteSeriesStream->size(), _spriteSeriesNames[i].c_str()); -		_vm->res()->toss(_spriteSeriesNames[i].c_str()); - -		// Adjust the palette of the sprites in the sprite series -		// so that they can be displayed on screen correctly -		RGBList *palData = new RGBList(_spriteSeries->getColorCount(), _spriteSeries->getPalette(), true); -		_vm->_palette->addRange(palData); - -		for (int k = 0; k < _spriteSeries->getCount(); k++) { -			M4Sprite *spr = _spriteSeries->getFrame(k); -			spr->translate(palData);		// sprite pixel translation +	if (messagesCount > 0) { +		// Chunk 2 +		// Following is a list of any messages for the animation + +		Common::SeekableReadStream *animStream = anim.getItemStream(streamIndex++); + +		for (int i = 0; i < messagesCount; ++i) { +			AnimMessage rec; +			animStream->read(rec.msg, 70); +			rec.pos.x = animStream->readUint16LE(); +			rec.pos.y = animStream->readUint16LE(); +			animStream->readUint16LE(); +			rec.rgb1.r = animStream->readByte(); +			rec.rgb1.g = animStream->readByte(); +			rec.rgb1.b = animStream->readByte(); +			rec.rgb2.r = animStream->readByte(); +			rec.rgb2.g = animStream->readByte(); +			rec.rgb2.b = animStream->readByte(); +			rec.kernelMsgIndex = animStream->readUint16LE(); +			animStream->skip(6); +			rec.startFrame = animStream->readUint16LE(); +			rec.endFrame = animStream->readUint16LE(); +			animStream->readUint16LE(); + +			_messages.push_back(rec);  		} + +		delete animStream;  	} -	//printf("End pos: %i\n", animStream->pos()); +	if (frameEntryCount > 0) { +		// Chunk 3: animation frame info +		animStream = anim.getItemStream(streamIndex++); + +		for (int i = 0; i < frameEntryCount; i++) { +			AnimFrameEntry rec; +			rec.frameNumber = animStream->readUint16LE(); +			rec.seqIndex = animStream->readByte(); +			rec.spriteSlot.frameNumber = animStream->readUint16LE(); +			rec.spriteSlot.xp = animStream->readUint16LE(); +			rec.spriteSlot.yp = animStream->readUint16LE(); +			rec.spriteSlot.depth = animStream->readUint16LE(); +			rec.spriteSlot.scale = animStream->readUint16LE(); + +			_frameEntries.push_back(rec); +		} + +		delete animStream; +	} -	delete animStream; +	if (miscEntriesCount > 0) { +		// Chunk 4: Misc Data +		animStream = anim.getItemStream(streamIndex); -	// ------------------ - -	// Chunk 2: anim info -	AnimationFrame frame; -	animStream = anim.getItemStream(1); -	//printf("Chunk 1, size %i\n", animStream->size()); - -	_frameEntries = new AnimationFrame[_frameEntryCount]; - -	for (int i = 0; i < _frameEntryCount; i++) { - -		frame.animFrameIndex = animStream->readUint16LE(); -		frame.u = animStream->readByte(); -		frame.seriesIndex = animStream->readByte(); -		frame.seriesFrameIndex = animStream->readUint16LE(); -		frame.x = animStream->readUint16LE(); -		frame.y = animStream->readUint16LE(); -		frame.v = animStream->readByte(); -		frame.w = animStream->readByte(); - -		_frameEntries[i] = frame; - -		/* -		printf( -		"animFrameIndex = %4d, " -		"u = %3d, " -		"seriesIndex = %3d, " -		"seriesFrameIndex = %6d, " -		"x = %3d, " -		"y = %3d, " -		"v = %3d, " -		"w = %3d\n", - -		frame.animFrameIndex, -		frame.u, -		frame.seriesIndex, -		frame.seriesFrameIndex, -		frame.x, -		frame.y, -		frame.v, -		frame.w -		); -		*/ -	} -	//printf("End pos: %i\n", animStream->pos()); +		for (int i = 0; i < miscEntriesCount; ++i) { +			AnimMiscEntry rec; +			rec.soundNum = animStream->readUint16LE(); +			rec.numTicks = animStream->readUint16LE(); +			rec.posAdjust.x = animStream->readUint16LE(); +			rec.posAdjust.y = animStream->readUint16LE(); +			animStream->readUint16LE(); -	delete animStream; +			_miscEntries.push_back(rec); +		} -	// Chunk 3: unknown (seems to be sound data?) -	// TODO -} +		delete animStream; +	} -Animation::~Animation() { -	//delete[] _spriteSeriesNames; -	//delete[] _spriteSeries; -	//delete[] _frameEntries; +	// If the animation specifies a font, then load it for access +	if (_flags & ANIM_CUSTOM_FONT) { +		Common::String fontName; +		if (madsRes) +			fontName += "*"; +		fontName += fontResource; + +		_font = _vm->_font->getFont(fontName); +	} + +	// Load all the sprite sets for the animation +	for (int i = 0; i < spriteListCount; ++i) { +		_spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str()); +	} + + +	if (_field12) { +		Common::String resName; +		if (madsRes) +			resName += "*"; +		resName += _spriteSetNames[_spriteListIndex]; +		 +		_spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str()); +	} + +	// TODO: Unknown section about handling palette entries - I think it's adjusting sprite sets +	// to the palette of the game screen + +	// Process the sprite list indexes to remap them to the actual sprite list indexes +	  } -void Animation::start() { -	_curFrame = 0; -	_curFrameEntry = 0; +void MadsAnimation::start() { +	_currentFrame = 0; +	_oldFrameEntry = 0;  	//for (int i = 0; i < _seriesCount; i++) {  		//_spriteSeries[i] = new SpriteSeries((char*)_spriteSeriesNames[i].c_str());  	//}  	_playing = true; -	updateAnim(); +	update();  } -bool Animation::updateAnim() { +bool MadsAnimation::update() {  	if (!_playing)  		return true; -	// Get the scene background surface -	M4Surface *bg = _vm->_scene->getBackgroundSurface(); +	if (_field12) { +		int spriteListIndex = _spriteListIndexes[_spriteListIndex]; +		int newIndex = -1; +		 +		for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) { +			if (_frameEntries[idx].frameNumber > _currentFrame) +				break; +			if (_frameEntries[idx].spriteSlot.spriteListIndex == spriteListIndex) +				newIndex = _frameEntries[idx].spriteSlot.frameNumber; +		} + +		if (newIndex >= 0) +			load1(newIndex); +	} + +	// If it's not time for the next frame, then exit +	if (_madsVm->_currentTimer < _nextFrameTimer) +		return false; -	while (_frameEntries[_curFrameEntry].animFrameIndex == _curFrame) { -		AnimationFrame *frame = &_frameEntries[_curFrameEntry]; -		int seriesFrameIndex = (frame->seriesFrameIndex & 0x7FFF) - 1; +	// Loop checks for any prior animation sprite slots to be expired +	for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) { +		if ((_view->_spriteSlots[slotIndex].seqIndex >= 0x80) && +			(_view->_spriteSlots[slotIndex].seqIndex <= 0xFD)) { +			// Flag the frame as animation sprite slot +			_view->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE; +		} +	} + +	// Validate the current frame +	if (_currentFrame > (int)_miscEntries.size()) { +		// Is the animation allowed to be repeated? +		if (_resetFlag) { +			_currentFrame = 0; +			_oldFrameEntry = 0; +		} else { +			_unk1 = true; +			return true; +		} +	} + +	// Handle starting any sound for this frame +	AnimMiscEntry &misc = _miscEntries[_currentFrame]; +	if (misc.soundNum) +		_vm->_sound->playSound(misc.soundNum); + +	bool screenChanged = false; -		// Write the sprite onto the screen -		M4Sprite *spr = _spriteSeries->getFrame(seriesFrameIndex); +	// Handle any scrolling of the screen surface +	if ((_scrollX != 0) || (_scrollY != 0)) { +		_view->_bgSurface->scrollX(_scrollX); +		_view->_bgSurface->scrollY(_scrollY); -		// FIXME: correct x, y -		spr->copyTo(bg, frame->x, frame->y, (int)spr->getTransparentColor()); +		screenChanged = true; +	} -		// HACK: wait a bit -		g_system->delayMillis(100); +	// Handle any offset adjustment for sprites as of this frame +	if (_view->_posAdjust.x != misc.posAdjust.x) { +		misc.posAdjust.x = _view->_posAdjust.x; +		screenChanged = true; +	} +	if (_view->_posAdjust.y != misc.posAdjust.y) { +		misc.posAdjust.y = _view->_posAdjust.y; +		screenChanged = true; +	} +	if (screenChanged) { +		// Signal the entire screen needs refreshing +		_view->_spriteSlots.fullRefresh(); +	} -		//printf("_curFrameEntry = %d\n", _curFrameEntry); -		_curFrameEntry++; +	int spriteSlotsMax = _view->_spriteSlots.startIndex; + +	// Main frame animation loop - frames get animated by being placed, as necessary, into the +	// main sprite slot array +	while ((uint)_oldFrameEntry < _frameEntries.size()) { +		if (_frameEntries[_oldFrameEntry].frameNumber > _currentFrame) +			break; +		else if (_frameEntries[_oldFrameEntry].frameNumber == _currentFrame) { +			// Found the correct frame  +			int spriteSlotIndex = 0; +			int index = 0; + +			for (;;) { +				if ((spriteSlotIndex == 0) && (index < spriteSlotsMax)) { +					int seqIndex = _frameEntries[_oldFrameEntry].seqIndex - _view->_spriteSlots[index].seqIndex; +					if (seqIndex == 0x80) { +						if (_view->_spriteSlots[index] == _frameEntries[_oldFrameEntry].spriteSlot) +							_view->_spriteSlots[index].spriteType = SPRITE_ZERO; +					} +					++index; +					continue; +				}  +				 +				if (spriteSlotIndex == 0) { +					int slotIndex = _view->_spriteSlots.getIndex(); +					_view->_spriteSlots[slotIndex].copy(_frameEntries[_oldFrameEntry].spriteSlot); +					_view->_spriteSlots[slotIndex].seqIndex += 0x80; +					 +					SpriteAsset &spriteSet = _view->_spriteSlots.getSprite( +						_view->_spriteSlots[slotIndex].spriteListIndex); + +					_view->_spriteSlots[slotIndex].spriteType = (spriteSet.getAssetType() == 0) ? +						SPRITE_FOUR : SPRITE_ZERO; +				} +				break; +			} +		} +		 +		++_oldFrameEntry;  	} -	//printf("_curFrame = %d\n", _curFrame); +	// Handle the display of any messages +	for (uint idx = 0; idx < _messages.size(); ++idx) { +		if (_messages[idx].kernelMsgIndex >= 0) { +			// Handle currently active message +			if ((_currentFrame < _messages[idx].startFrame) || (_currentFrame > _messages[idx].endFrame)) { +				_view->_kernelMessages.remove(_messages[idx].kernelMsgIndex); +				_messages[idx].kernelMsgIndex = -1; +				--_messageCtr; +			} +		} else if ((_currentFrame >= _messages[idx].startFrame) && (_currentFrame <= _messages[idx].endFrame)) { +			// Start displaying the message +			AnimMessage &me = _messages[idx]; + +			// The colour index to use is dependant on how many messages are currently on-screen +			uint8 colIndex; +			switch (_messageCtr) { +			case 1: +				colIndex = 252; +				break; +			case 2: +				colIndex = 16; +				break; +			default: +				colIndex = 250; +				break; +			} + +			_vm->_palette->setEntry(colIndex, me.rgb1.r, me.rgb1.g, me.rgb1.b); +			_vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b); + +			// Add a kernel message to display the given text +			me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 101, 0, 0, INDEFINITE_TIMEOUT, me.msg); +			++_messageCtr; +		} +	} -	_curFrame++; -	if (_curFrame >= _frameCount)		// anim done +	// Move to the next frame +	_currentFrame++; +	if (_currentFrame >= (int)_miscEntries.size()) { +		// Animation is complete  		stop(); -	return _curFrame >= _frameCount; +		if (_abortTimers != 0) { +			_view->_abortTimers = _abortTimers; +			_view->_abortTimersMode = _abortMode; + +			if (_abortMode != ABORTMODE_1) { +				// Copy the noun list +				for (int i = 0; i < 3; ++i) +					_madsVm->scene()->actionNouns[i] = _actionNouns[i]; +			} +		} +	} + +	int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1); +	_nextFrameTimer = _madsVm->_currentTimer + _miscEntries[frameNum].numTicks; + +	return _currentFrame >= (int)_miscEntries.size();  } -void Animation::stop() { +void MadsAnimation::stop() {  	_playing = false; +} -	for (int i = 0; i < _seriesCount; i++) { -		// TODO: cleanup -		//delete _spriteSeries[i]; -		//_spriteSeries[i] = NULL; +void MadsAnimation::setCurrentFrame(int frameNumber) { +	_currentFrame = frameNumber; +	_oldFrameEntry = 0; +	_unk1 = 0; +} + +void MadsAnimation::load1(int frameNumber) { +	if (_skipLoad) +		return; + +	Common::Point pt; +	int listIndex = _spriteListIndexes[_spriteListIndex]; +	SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex); + +	if (_unkIndex < 0) { +		M4Surface *frame = spriteSet.getFrame(0); +		pt.x = frame->bounds().left; +		pt.y = frame->bounds().top; +	} else { +		pt.x = _unkList[_unkIndex].x; +		pt.y = _unkList[_unkIndex].y; +		_unkIndex = 1 - _unkIndex;  	} + +	if (proc1(spriteSet, pt, frameNumber)) +		error("proc1 failure"); + + +} + +bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) { +	return 0;  }  } // End of namespace M4 diff --git a/engines/m4/animation.h b/engines/m4/animation.h index c8be7f5cb3..b7e88f0871 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -29,39 +29,90 @@  #include "m4/m4.h"  #include "m4/graphics.h"  #include "m4/assets.h" +#include "m4/mads_views.h" +#include "common/array.h"  namespace M4 { -struct AnimationFrame { -    uint16 animFrameIndex; -    byte u; -    byte seriesIndex; -    uint16 seriesFrameIndex; -    uint16 x, y; -    byte v, w; +class MadsView; +class SpriteSlotSubset; + +class AnimMessage { +public: +	char msg[70]; +	Common::Point pos; +	RGB8 rgb1, rgb2; +	int kernelMsgIndex; + +	int startFrame, endFrame; +}; + +class AnimFrameEntry { +public: +	int frameNumber; +	int seqIndex; +	SpriteSlotSubset spriteSlot;  }; -class Animation { -    public: -		Animation(MadsM4Engine *vm); -        ~Animation(); - -        void load(const char *filename); -		void loadFullScreen(const char *filename); -        void start(); -        bool updateAnim(); -        void stop(); - -    private: -		bool _playing; -		MadsM4Engine *_vm; -        int _seriesCount; -        int _frameCount; -        int _frameEntryCount; -        AnimationFrame *_frameEntries; -        Common::String *_spriteSeriesNames; -        SpriteAsset *_spriteSeries; -        int _curFrame, _curFrameEntry; +class AnimMiscEntry { +public: +	int soundNum; +	int numTicks; +	Common::Point posAdjust; +}; + +#define ANIM_SPRITE_SET_SIZE 50 + +enum MadsAnimationFlags {ANIM_CUSTOM_FONT = 0x20}; + +class MadsAnimation: public Animation { +private: +	bool _playing; +	MadsView *_view; + +	int _spriteListCount; +	Common::Array<AnimMessage> _messages; +	Common::Array<AnimFrameEntry> _frameEntries; +	Common::Array<AnimMiscEntry> _miscEntries; +	Font *_font; + +	uint8 _flags; +	int _animMode; +	int _roomNumber; +	bool _field12; +	int _spriteListIndex; +	int _scrollX; +	int _scrollY; +	Common::String _field24; +	Common::String _spriteSetNames[10]; +	Common::String _lbmFilename; +	Common::String _spritesFilename; +	Common::String _soundName; +	Common::Array<int> _spriteListIndexes; + +    int _currentFrame, _oldFrameEntry; +	bool _resetFlag; +	int _unk1; +	bool _skipLoad; +	int _unkIndex; +	Common::Point _unkList[2]; +	uint32 _nextFrameTimer; +	int _messageCtr; +	int _abortTimers; +	AbortTimerMode _abortMode; +	uint16 _actionNouns[3]; + +	void load1(int frameNumber); +	bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber); +public: +	MadsAnimation(MadsM4Engine *vm, MadsView *view); +    ~MadsAnimation(); + +    virtual void load(const Common::String &filename); +    virtual void start(); +    virtual bool update(); +    virtual void stop(); +	virtual void setCurrentFrame(int frameNumber);  };  } // End of namespace M4 diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index 14857e6f2b..91c371dec5 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -30,13 +30,13 @@  namespace M4 { -BaseAsset::BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : _vm(vm) { +BaseAsset::BaseAsset(MadsM4Engine *vm) : _vm(vm) {  }  BaseAsset::~BaseAsset() {  } -MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) { +MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {  	uint32 stateCount = stream->readUint32LE();  	for (uint32 curState = 0; curState < stateCount; curState++) {  		uint32 stateOffset = stream->readUint32LE(); @@ -61,7 +61,7 @@ uint32 MachineAsset::getStateOffset(uint32 state) {  	return _stateTable[state];  } -SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) { +SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {  	_localVarCount = stream->readUint32LE();  	_codeSize = size - 4;  	_code = new byte[_codeSize]; @@ -78,7 +78,7 @@ void SequenceAsset::getCode(byte *&code, uint32 &codeSize) {  } -DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) { +DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {  	_recCount = stream->readUint32LE();  	_recSize = stream->readUint32LE(); @@ -98,7 +98,8 @@ long *DataAsset::getRow(int index) {  	return &_data[_recSize * index];  } -SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : BaseAsset(vm, stream, size, name) { +SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) :  +			BaseAsset(vm) {  	_stream = stream;  	_palInterface = NULL;  	_paletteData = NULL; @@ -110,6 +111,20 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i  	}  } +SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) { +	_stream = vm->res()->get(name); +	_palInterface = NULL; +	_paletteData = NULL; + +	if (_vm->isM4()) { +		loadM4SpriteAsset(vm, _stream, true); +	} else { +		loadMadsSpriteAsset(vm, _stream); +	} + +	vm->res()->toss(name); +} +  SpriteAsset::~SpriteAsset() {  	if (_palInterface) {  		// Internally stored palette translation data, so release it diff --git a/engines/m4/assets.h b/engines/m4/assets.h index cd0ae6ba78..816a8dcff0 100644 --- a/engines/m4/assets.h +++ b/engines/m4/assets.h @@ -49,7 +49,7 @@ class Palette;  class BaseAsset {  public: -	BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name); +	BaseAsset(MadsM4Engine *vm);  	~BaseAsset();  	const Common::String getName() const { return _name; }  protected: @@ -103,6 +103,7 @@ struct SpriteAssetFrame {  class SpriteAsset : public BaseAsset {  public:  	SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false); +	SpriteAsset(MadsM4Engine *vm, const char *name);  	~SpriteAsset();  	void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream);  	void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream); diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp index 0c2e80df0e..d568584d30 100644 --- a/engines/m4/console.cpp +++ b/engines/m4/console.cpp @@ -47,7 +47,6 @@ Console::Console(MadsM4Engine *vm) : GUI::Debugger() {  	DCmd_Register("start_conv",		WRAP_METHOD(Console, cmdStartConversation));  	DCmd_Register("textview",		WRAP_METHOD(Console, cmdShowTextview));  	DCmd_Register("animview",		WRAP_METHOD(Console, cmdShowAnimview)); -	DCmd_Register("anim",			WRAP_METHOD(Console, cmdPlayAnimation));  }  Console::~Console() { @@ -247,33 +246,6 @@ bool Console::cmdShowAnimview(int argc, const char **argv) {  	return false;  } -bool Console::cmdPlayAnimation(int argc, const char **argv) { -	View *view = _vm->_viewManager->getView(VIEWID_SCENE); -	if (view == NULL) { -		DebugPrintf("The scene view isn't currently active\n"); -	} else if (argc != 2 && argc != 3) { -		DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]); -		DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n"); -	} else { -		char resourceName[20]; -		strncpy(resourceName, argv[1], 15); -		resourceName[15] = '\0'; -		if (!strchr(resourceName, '.')) -			strcat(resourceName, ".AA"); - -		_vm->_viewManager->moveToFront(view); -		if (argc == 3 && atoi(argv[2]) == 1) -			_vm->_animation->loadFullScreen(resourceName); -		else -			_vm->_animation->load(resourceName); -		_vm->_animation->start(); -		view->restore(0, 0, view->width(), view->height()); -		return false; -	} - -	return true; -} -  /*--------------------------------------------------------------------------*/  MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) { @@ -282,6 +254,7 @@ MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {  	DCmd_Register("object",			WRAP_METHOD(MadsConsole, cmdObject));  	DCmd_Register("message",		WRAP_METHOD(MadsConsole, cmdMessage));  	DCmd_Register("scene_info",		WRAP_METHOD(MadsConsole, cmdSceneInfo)); +	DCmd_Register("anim",			WRAP_METHOD(MadsConsole, cmdPlayAnimation));  }  bool MadsConsole::cmdObject(int argc, const char **argv) { @@ -386,6 +359,34 @@ bool MadsConsole::cmdSceneInfo(int argc, const char **argv) {  	return true;  } +bool MadsConsole::cmdPlayAnimation(int argc, const char **argv) { +	View *view = _vm->_viewManager->getView(VIEWID_SCENE); +	if (view == NULL) { +		DebugPrintf("The scene view isn't currently active\n"); +	} else if (argc != 2 && argc != 3) { +		DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]); +		DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n"); +	} else { +		char resourceName[20]; +		strncpy(resourceName, argv[1], 15); +		resourceName[15] = '\0'; +		if (!strchr(resourceName, '.')) +			strcat(resourceName, ".AA"); + +		_vm->_viewManager->moveToFront(view); +		if (argc == 3 && atoi(argv[2]) == 1) +			_madsVm->scene()->_sceneAnimation.loadFullScreen(resourceName); +		else +			_madsVm->scene()->_sceneAnimation.load(resourceName); +		_madsVm->scene()->_sceneAnimation.start(); + +		view->restore(0, 0, view->width(), view->height()); +		return false; +	} + +	return true; +} +  /*--------------------------------------------------------------------------*/  M4Console::M4Console(M4Engine *vm): Console(vm) { diff --git a/engines/m4/console.h b/engines/m4/console.h index b592f041cf..53a47dada9 100644 --- a/engines/m4/console.h +++ b/engines/m4/console.h @@ -50,7 +50,6 @@ private:  	bool cmdStartConversation(int argc, const char **argv);  	bool cmdShowTextview(int argc, const char **argv);  	bool cmdShowAnimview(int argc, const char **argv); -	bool cmdPlayAnimation(int argc, const char **argv);  public:  	Console(MadsM4Engine *vm); @@ -64,6 +63,8 @@ private:  	bool cmdObject(int argc, const char **argv);  	bool cmdMessage(int argc, const char **argv);  	bool cmdSceneInfo(int argc, const char **argv); +	bool cmdPlayAnimation(int argc, const char **argv); +  public:  	MadsConsole(MadsEngine *vm);  	virtual ~MadsConsole() {} diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 2024138f67..da271b10c9 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -145,7 +145,6 @@ MadsM4Engine::~MadsM4Engine() {  	delete _script;  	delete _ws;  	delete _random; -	delete _animation;  	delete _palette;  } @@ -184,7 +183,6 @@ Common::Error MadsM4Engine::run() {  	_sound = new Sound(this, _mixer, 255);  	_script = new ScriptInterpreter(this);  	_ws = new WoodScript(this); -	_animation = new Animation(this);  	//_callbacks = new Callbacks(this);  	_random = new Common::RandomSource();  	g_eventRec.registerRandomSource(*_random, "m4"); @@ -581,8 +579,6 @@ Common::Error MadsEngine::run() {  	while (!_events->quitFlag) {  		eventHandler(); -		_animation->updateAnim(); -  		if (g_system->getMillis() >= nextFrame) {  			nextFrame = g_system->getMillis() + GAME_FRAME_DELAY;  			++_currentTimer; diff --git a/engines/m4/m4.h b/engines/m4/m4.h index 23204f2228..9937107668 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -200,7 +200,6 @@ public:  	Rails *_rails;  	ScriptInterpreter *_script;  	WoodScript *_ws; -	Animation *_animation;  	Common::RandomSource *_random;  	Scene *scene() { return _scene; } diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 3b5ba9e24c..e66b1d8d41 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -24,6 +24,7 @@   */  #include "m4/m4_views.h" +#include "m4/animation.h"  #include "m4/dialogs.h"  #include "m4/events.h"  #include "m4/font.h" @@ -43,6 +44,22 @@ static const int SCROLLER_DELAY = 200;  //-------------------------------------------------------------------------- +bool MadsSpriteSlot::operator==(const SpriteSlotSubset &other) const { +	return (spriteListIndex == other.spriteListIndex) && (frameNumber == other.frameNumber) && +		(xp == other.xp) && (yp == other.yp) && (depth == other.depth) && (scale == other.scale); +} + +void MadsSpriteSlot::copy(const SpriteSlotSubset &other) { +	spriteListIndex = other.spriteListIndex; +	frameNumber = other.frameNumber; +	xp = other.xp; +	yp = other.yp; +	depth = other.depth; +	scale = other.scale; +} + +//-------------------------------------------------------------------------- +  MadsSpriteSlots::MadsSpriteSlots(MadsView &owner): _owner(owner) {  	for (int i = 0; i < SPRITE_SLOTS_SIZE; ++i) {  		MadsSpriteSlot rec; @@ -74,6 +91,7 @@ int MadsSpriteSlots::addSprites(const char *resName) {  	Common::SeekableReadStream *data = _vm->res()->get(resName);  	SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName);  	spriteSet->translate(_madsVm->_palette); +	assert(spriteSet != NULL);  	_sprites.push_back(SpriteList::value_type(spriteSet));  	_vm->res()->toss(resName); @@ -1125,8 +1143,20 @@ void MadsSequenceList::setAnimRange(int seqIndex, int startVal, int endVal) {  //-------------------------------------------------------------------------- +Animation::Animation(MadsM4Engine *vm): _vm(vm) { +} + +void Animation::loadFullScreen(const Common::String &filename) { +	_vm->_palette->deleteAllRanges(); +	load(filename); +} + +//-------------------------------------------------------------------------- +  MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this), -		_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) { +		_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this), +		// FIXME: There's probably a cleaner way to do this, and I don't think the destructor is ever called +		_sceneAnimation(*new MadsAnimation(_vm, this)) {  	_textSpacing = -1;  	_ticksAmount = 3;  	_newTimeout = 0; diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 1661bac3df..6d6d576263 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -43,6 +43,16 @@ class MadsView;  enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2}; +class SpriteSlotSubset { +public: +	int spriteListIndex; +	int frameNumber; +	int xp; +	int yp; +	int depth; +	int scale; +}; +  class MadsSpriteSlot {  public:  	int spriteType; @@ -55,12 +65,16 @@ public:  	int scale;  	MadsSpriteSlot() { } + +	bool operator==(const SpriteSlotSubset &other) const; +	void copy(const SpriteSlotSubset &other);  };  #define SPRITE_SLOTS_SIZE 50  enum SpriteIdSpecial { -	BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, FOREGROUND_SPRITE = 1, EXPIRED_SPRITE = -1 +	BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, EXPIRED_SPRITE = -1, SPRITE_ZERO = 0, FOREGROUND_SPRITE = 1, +	SPRITE_FOUR = 4  };  typedef Common::Array<Common::SharedPtr<SpriteAsset> > SpriteList; @@ -138,7 +152,7 @@ public:  };  #define TIMED_TEXT_SIZE 10 -#define TEXT_4A_SIZE 30 +#define INDEFINITE_TIMEOUT 9999999  enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_OWNER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10,   	KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80}; @@ -352,10 +366,26 @@ public:  	void setAnimRange(int seqIndex, int startVal, int endVal);  }; +class Animation { +protected: +	MadsM4Engine *_vm; +public: +	Animation(MadsM4Engine *vm); +	void loadFullScreen(const Common::String &filename); + +	virtual void load(const Common::String &filename) = 0; +    virtual void start() = 0; +    virtual bool update() = 0; +    virtual void stop() = 0; +	virtual void setCurrentFrame(int frameNumber) = 0; +}; +	 +  class MadsView {  private:  	View *_view;  public: +	Animation &_sceneAnimation;  	MadsSpriteSlots _spriteSlots;  	MadsTextDisplay _textDisplay;  	MadsKernelMessageList _kernelMessages; | 
