[Scummvm-cvs-logs] SF.net SVN: scummvm:[42736] scummvm/trunk/engines/scumm

Kirben at users.sourceforge.net Kirben at users.sourceforge.net
Sat Jul 25 07:39:57 CEST 2009


Revision: 42736
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42736&view=rev
Author:   Kirben
Date:     2009-07-25 05:39:57 +0000 (Sat, 25 Jul 2009)

Log Message:
-----------
Add patch #2816140 - MM C64 Costume Animation.

Modified Paths:
--------------
    scummvm/trunk/engines/scumm/actor.cpp
    scummvm/trunk/engines/scumm/actor.h
    scummvm/trunk/engines/scumm/costume.cpp
    scummvm/trunk/engines/scumm/costume.h
    scummvm/trunk/engines/scumm/script_v0.cpp

Modified: scummvm/trunk/engines/scumm/actor.cpp
===================================================================
--- scummvm/trunk/engines/scumm/actor.cpp	2009-07-25 04:36:43 UTC (rev 42735)
+++ scummvm/trunk/engines/scumm/actor.cpp	2009-07-25 05:39:57 UTC (rev 42736)
@@ -527,9 +527,15 @@
 	if (_moving & MF_TURN) {
 		new_dir = updateActorDirection(false);
 		// FIXME: is this correct?
-		if (_facing != new_dir)
+		if (_facing != new_dir) {
+			
+			// Actor never stops walking when an object has been selected without this
+			if (_vm->_game.version ==0)
+				_moving = 0;
+			
 			setDirection(new_dir);
-		else
+
+		} else
 			_moving = 0;
 		return;
 	}
@@ -817,6 +823,16 @@
 	if (_costume == 0)
 		return;
 
+	// V0 MM
+	if (_vm->_game.version == 0) {
+		if (_moving)
+			_vm->_costumeLoader->costumeDecodeData(this, _walkFrame, 0);
+		else
+			_vm->_costumeLoader->costumeDecodeData(this, _standFrame, 0);
+		_needRedraw = true;
+		return;
+	}
+
 	// Update the costume for the new direction (and mark the actor for redraw)
 	aMask = 0x8000;
 	for (i = 0; i < 16; i++, aMask >>= 1) {
@@ -1224,9 +1240,12 @@
 
 	_vm->ensureResourceLoaded(rtCostume, _costume);
 
-	if (_vm->_game.version <= 2) {
+	if (_vm->_game.version == 0) {
 		_cost.reset();
 		startAnimActor(_standFrame);
+	} else if (_vm->_game.version <= 2) {
+		_cost.reset();
+		startAnimActor(_standFrame);
 		startAnimActor(_initFrame);
 		startAnimActor(_talkStopFrame);
 	} else {
@@ -1380,6 +1399,13 @@
 	Actor** end = _sortedActors + numactors;
 	for (Actor** ac = _sortedActors; ac != end; ++ac) {
 		Actor* a = *ac;
+		
+		// V0 MM: 0x057B
+		if (_game.version == 0) {
+			ActorC64 *A = (ActorC64*) a;
+			if ((A->_speaking & 1))
+				A->_speaking ^= 0xFE;
+		}
 		// Draw and animate the actors, except those w/o a costume.
 		// Note: We could 'optimize' this a little bit by only putting
 		// actors with a costume into the _sortedActors array in the
@@ -1572,6 +1598,8 @@
 		// we need to shift it 8 pixels to the left
 		if (_facing == 90)
 			bcr->_actorX -= 8;
+	} else if (_vm->_game.version == 0) {
+			bcr->_actorX += 12;
 	} else if (_vm->_game.version <= 2) {
 		// HACK: We have to adjust the x position by one strip (8 pixels) in
 		// V2 games. However, it is not quite clear to me why. And to fully
@@ -1703,6 +1731,12 @@
 	case 4:				// turn to new direction
 		turnToDirection(dir);
 		break;
+	case 64:
+		if (_vm->_game.version == 0) {
+			_moving &= ~MF_TURN;
+			setDirection(dir);
+			break;
+		}
 	default:
 		if (_vm->_game.version <= 2)
 			startAnimActor(anim / 4);
@@ -2167,21 +2201,38 @@
 	}
 }
 
-static const char* v0ActorNames[7] = {
+static const char* v0ActorNames[0x19] = {
 	"Syd",
 	"Razor",
 	"Dave",
 	"Michael",
 	"Bernard",
 	"Wendy",
-	"Jeff"
+	"Jeff",
+	"",
+	"Dr Fred",
+	"Nurse Edna",
+	"Weird Ed",
+	"Dead Cousin Ted",
+	"Purple Tentacle",
+	"Green Tentacle",
+	"Meteor",
+	"Plant",
+	"",
+	"",
+	"",
+	"",
+	"",
+	"",
+	"Sandy"
 };
 
 const byte *Actor::getActorName() {
-	const byte *ptr;
+	const byte *ptr = NULL;
 
 	if (_vm->_game.version == 0) {
-		ptr = (const byte *)v0ActorNames[_number - 1];
+		if (_number)
+			ptr = (const byte *)v0ActorNames[_number - 1];
 	} else {
 		ptr = _vm->getResourceAddress(rtActorName, _number);
 	}

Modified: scummvm/trunk/engines/scumm/actor.h
===================================================================
--- scummvm/trunk/engines/scumm/actor.h	2009-07-25 04:36:43 UTC (rev 42735)
+++ scummvm/trunk/engines/scumm/actor.h	2009-07-25 05:39:57 UTC (rev 42736)
@@ -380,11 +380,15 @@
 
 class ActorC64 : public Actor_v2 {
 public:
-	// FIXME: This flag is never saved, which might lead to broken save states.
+	// FIXME: These vars are never saved, which might lead to broken save states.
 	byte _miscflags;
+	byte _speaking, _speakingPrev;
+	byte _costCommand, _costFrame;
 
 public:
-	ActorC64(ScummEngine *scumm, int id) : Actor_v2(scumm, id) {}
+	ActorC64(ScummEngine *scumm, int id) : Actor_v2(scumm, id) {
+		 _speaking = _speakingPrev = _costCommand = _costFrame = 0;
+	}
 	virtual void initActor(int mode) {
 		Actor_v2::initActor(mode);
 		if (mode == -1) {

Modified: scummvm/trunk/engines/scumm/costume.cpp
===================================================================
--- scummvm/trunk/engines/scumm/costume.cpp	2009-07-25 04:36:43 UTC (rev 42735)
+++ scummvm/trunk/engines/scumm/costume.cpp	2009-07-25 05:39:57 UTC (rev 42736)
@@ -1040,27 +1040,26 @@
 	if (limb >= 8)
 		return 0;
 
+	if (a->_cost.start[limb] == 0xFFFF)
+		return 0;
+
 	if (limb == 0) {
 		_draw_top = 200;
 		_draw_bottom = 0;
 	}
+	
+	bool flipped = (a->_cost.start[limb] & 0x80) != 0;
+	byte frameStart = _loaded._frameOffsets[a->_cost.frame[limb]];
+	byte frame = _loaded._frameOffsets[frameStart + a->_cost.curpos[limb]];
+	if (frame == 0xFF)
+		return 0;
 
-	// TODO:
-	// get out how animations are handled
-	byte state = a->_moving != 0 ? 0 : 1;
-	byte unk1 = (_loaded._animCmds + (state*32) + newDirToOldDir(a->getFacing()) * 8)[limb];
-	byte unk2 = _loaded._frameOffsets[_loaded._frameOffsets[limb] + (unk1 & 0x7f)];
-	bool flipped = (unk1 & 0x80) != 0;
+	byte ptrLow = _loaded._baseptr[frame];
+	byte ptrHigh = ptrLow + _loaded._dataOffsets[4];
+	int frameOffset = (_loaded._baseptr[ptrHigh] << 8) + _loaded._baseptr[ptrLow + 2];			// 0x23EF / 0x2400
 
-	byte p1 = _loaded._frameOffsets[unk2];
-	byte temp1 = _loaded._baseptr[p1];
-	byte temp2 = temp1 + _loaded._dataOffsets[4];
-	int offL = _loaded._baseptr[temp1 + 2];
-	int offH = _loaded._baseptr[temp2];
-	int off = (offH << 8) + offL;
+	const byte *data = _loaded._baseptr + frameOffset;
 
-	const byte *data = _loaded._baseptr + off;
-
 	// Set up the palette data
 	byte palette[4] = { 0, 0, 0, 0 };
 	if (_vm->getCurrentLights() & LIGHTMODE_actor_use_colors) {
@@ -1077,8 +1076,8 @@
 	int offsetY = *data++;
 	// these two fields seems to be most times zero
 	// byte6 was one time 255 in one costume I tried
-//	int byte5 = *data++;
-//	int byte6 = *data++;
+//	int byte5 = *data++;		// 0x1F80			// This value is never used
+//	int byte6 = *data++;		// 0x1F86			// This value is subtracted from ?actor drawy? at 0x2383
 //	debug(3, "byte5: %d", byte5);
 //	debug(3, "byte6: %d", byte6);
 	data += 2;
@@ -1091,17 +1090,13 @@
 
 	if (flipped) {
 		if (offsetX)
-			xpos += (offsetX-1) * 8;
+			xpos += (offsetX - 1) * 8;
 	} else {
 		xpos += offsetX * 8;
 	}
 
-	// + 4 could be commented, because maybe the _actorX position is
-	// wrong, I looked at the scumm-c64 interpreter by lloyd
-	// and there Bernhard is directly on the right in the intro
-	// but here in ScummVM he is 4 pixel left of the other position.
-	xpos += _actorX - (a->_width / 2) + 4;
-	ypos += _actorY - _loaded._maxHeight;
+	xpos += _actorX - (a->_width / 2);
+	ypos += (_actorY - _loaded._maxHeight) + 1;		// +1 as we appear to be 1 pixel away from the original interpreter
 
 	// This code is very similar to procC64()
 	for (int y = 0; y < height; ++y) {
@@ -1111,9 +1106,9 @@
 			int realX = 0;
 			if (flipped) {
 				if (offsetX == 0||offsetX == 1) {
-					realX = width-(x+1);
+					realX = width-(x + 1);
 				} else if (offsetX == 2) {
-					realX = width-(x+2);
+					realX = width-(x + 2);
 				}
 			} else {
 				realX = x;
@@ -1134,10 +1129,8 @@
 	}
 
 	_draw_top = MIN(_draw_top, ypos);
-	_draw_bottom = MAX(_draw_bottom, ypos+height);
-	// if +4 above is NOT commented, here "+(flipped ? 4 : 0)" can be commented out
-	// and other way round
-	_vm->markRectAsDirty(kMainVirtScreen, xpos, xpos+(width*8)/*+(flipped ? 4 : 0)*/, ypos, ypos+height, _actorID);
+	_draw_bottom = MAX(_draw_bottom, ypos + height);
+	_vm->markRectAsDirty(kMainVirtScreen, xpos, xpos + (width * 8), ypos, ypos + height, _actorID);
 
 	return 0;
 }
@@ -1151,6 +1144,7 @@
 
 void C64CostumeLoader::loadCostume(int id) {
 	const byte *ptr = _vm->getResourceAddress(rtCostume, id);
+
 	_id = id;
 	_baseptr = ptr + 9;
 
@@ -1165,33 +1159,152 @@
 	_animCmds = _baseptr + READ_LE_UINT16(ptr + 7);
 
 	_maxHeight = 0;
-	for (int i = 0; i < 8; ++i) {
-		int pid = _frameOffsets[_frameOffsets[i]];
-		byte p1 = _frameOffsets[pid];
-		byte b = _baseptr[p1];
-		byte c = b + _dataOffsets[4];
-		int offL = _baseptr[b + 2];
-		int offH = _baseptr[c];
-		int off = (offH << 8) + offL;
-		const byte *data = _baseptr + off;
+}
 
-		if (data[3] > _maxHeight) {
-			_maxHeight = data[3];		// data[3] is libs's Y offset
+void C64CostumeLoader::frameUpdate(ActorC64 *a, int cmd ) {
+	byte limbFrames = 0;
+
+	// Each costume-command has 8 limbs  (0x2622)
+	cmd <<= 3;
+
+	for (int limb = 0, pos = 0; limb < 8; ++limb, pos = 0) {
+		// get a limb frames ptr from the costume command
+		limbFrames = ((_animCmds + cmd)[limb]);
+		
+		// Dont change limb if entry is invalid
+		if (limbFrames == 0xFF)
+			continue;
+
+		// Has limb frames ptr changed since last update?
+		if (a->_cost.start[limb] == limbFrames)
+			continue;
+
+		// Set new limb command addresses
+		a->_cost.start[limb]	= limbFrames;
+		a->_cost.frame[limb]	= _frameOffsets[limb] + (limbFrames & 0x7f);			// limb animation-frames ptr
+
+		// Get first entry of a limbs' frames
+		byte frameStart = _frameOffsets[ a->_cost.frame[limb]];
+
+		// Loop each frame in this limb until we reach the end marker
+		while (pos != 0xFF) {	// This is just so we dont overflow
+			byte frame = _frameOffsets[frameStart + pos];
+
+			// Each animation-frame until we find end
+			if (frame == 0xFF)
+				break;
+			
+			byte ptrLow = _baseptr[frame];
+			byte ptrHigh = ptrLow + _dataOffsets[4];
+			int  frameOffset = (_baseptr[ptrHigh] << 8) + _baseptr[ptrLow + 2];			// 0x23EF / 0x2400
+
+			const byte *data = _baseptr + frameOffset;
+			
+			if (data[3] > _maxHeight)
+				_maxHeight = data[3] + 1;
+
+			++pos;
 		}
+
+		// Set ending position of limb frames
+		a->_cost.end[limb] = pos - 1;
+		a->_cost.curpos[limb] = 0;
 	}
-	++_maxHeight;
 }
 
+// based on 0x2BCA, doesn't match disassembly because 'oldDir' variable
+// is not the same value as stored in the original interpreter
+int C64CostumeLoader::dirToDirStop( int oldDir ) {
+	switch (oldDir) {
+		case 0:
+			return 4;	// Left
+		case 1:
+			return 5;	// Right
+		case 2:
+			return 6;	// Face Camera
+		case 3:
+			return 7;	// Face Away
+	}
+	// shouldnt' be reached
+	return 4;
+}
+
+void C64CostumeLoader::actorSpeak(ActorC64 *a, int &cmd) {
+	if ((a->_speaking & 0x80))
+		cmd += 0x0C;
+	else
+		cmd += 0x10;
+}
+
 void C64CostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) {
+	ActorC64 *A = (ActorC64*) a;
+	int dir = newDirToOldDir(a->getFacing());
+	int command = dir;
+	
+	loadCostume(a->_costume); 
+
+	// Enable/Disable speaking flag
+	if (frame == a->_talkStartFrame) {
+		A->_speaking = 1;
+		return;
+	}
+	if (frame == a->_talkStopFrame) {
+		A->_speaking = 0;
+		return;
+	}
+
+	// Different command for stand frame
+	if (frame == a->_standFrame)
+		command = dirToDirStop(dir);	
+
+	// Update the limb frames
+	frameUpdate(A, command);
+
+	// Keep current command/frame mode
+	A->_costCommand = dir;
+	A->_costFrame = frame;
+
+	// Update 'speaking' frames?
+	if (A->_speaking) {
+		command = dir;	// Incase standing frame was set as cmd
+		actorSpeak(A, command);
+
+		// Update the limb speak frames
+		frameUpdate(A, command);
+	}
 }
 
 byte C64CostumeLoader::increaseAnims(Actor *a) {
-	return 0;
-}
+	ActorC64 *A = (ActorC64*) a;
+	
+	// check if the actor speak flag has changed since last frame increase
+	if (A->_speaking != A->_speakingPrev) {
+		int cmd = A->_costCommand;
+		A->_speakingPrev = A->_speaking;
 
-byte C64CostumeLoader::increaseAnim(Actor *a, int slot) {
-	return 0;
+		// Update to use speak frame
+		if (A->_speaking & 0x80) {
+			actorSpeak(A, cmd);
+
+		} else {
+			// Update to use stand frame
+			if (A->_costFrame == A->_standFrame)
+				cmd = dirToDirStop(cmd);
+		}
+
+		// Update the limb frames
+		frameUpdate(A, cmd);
+	}
+
+	// increase each frame pos
+	for (int limb = 0; limb < 8; ++limb) {
+		if (a->_cost.curpos[limb] < a->_cost.end[limb])
+			a->_cost.curpos[limb]++;
+		else
+			a->_cost.curpos[limb] = 0;
+	}
+
+	return 1;
 }
 
-
 } // End of namespace Scumm

Modified: scummvm/trunk/engines/scumm/costume.h
===================================================================
--- scummvm/trunk/engines/scumm/costume.h	2009-07-25 04:36:43 UTC (rev 42735)
+++ scummvm/trunk/engines/scumm/costume.h	2009-07-25 05:39:57 UTC (rev 42736)
@@ -79,8 +79,12 @@
 	byte increaseAnims(Actor *a);
 
 	int _maxHeight;
+
 protected:
-	byte increaseAnim(Actor *a, int slot);
+	void actorSpeak(ActorC64 *a, int &cmd);
+	int dirToDirStop( int oldDir );
+	void frameUpdate(ActorC64 *A, int cmd);
+	
 };
 
 class ClassicCostumeRenderer : public BaseCostumeRenderer {

Modified: scummvm/trunk/engines/scumm/script_v0.cpp
===================================================================
--- scummvm/trunk/engines/scumm/script_v0.cpp	2009-07-25 04:36:43 UTC (rev 42735)
+++ scummvm/trunk/engines/scumm/script_v0.cpp	2009-07-25 05:39:57 UTC (rev 42736)
@@ -666,7 +666,19 @@
 	int unk = fetchScriptByte();
 	debug(0,"o_animateActor: unk %d", unk);
 
-	Actor *a = derefActor(act, "o_animateActor");
+	ActorC64 *a = (ActorC64*) derefActor(act, "o_animateActor");
+
+	// 0x6993
+	if (anim == 0xFE) {
+		a->_speaking = 0x80;	// Enabled, but not switching
+		return;
+	}
+	// 0x69A3
+	if (anim == 0xFD) {
+		a->_speaking = 0x00;
+		return;
+	}
+
 	a->animateActor(anim);
 }
 
@@ -738,8 +750,13 @@
 	byte act = getVarOrDirectByte(PARAM_1);
 	byte mask = getVarOrDirectByte(PARAM_2);
 	byte mod = getVarOrDirectByte(PARAM_3);
+	
+	// 0x63ED
+	if (act >= _numActors)
+		return;
 
 	ActorC64 *a = (ActorC64 *)derefActor(act, "o_setActorBitVar");
+
 	if (mod)
 		a->_miscflags |= mask;
 	else


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list