diff options
| author | Nicola Mettifogo | 2007-08-16 17:28:18 +0000 | 
|---|---|---|
| committer | Nicola Mettifogo | 2007-08-16 17:28:18 +0000 | 
| commit | f0f46113ee103e922ecde5f32652a482899c7e61 (patch) | |
| tree | f64d178e1ac84dc135fef556c4ba53b944a24fdf | |
| parent | c987d6aaf0744e088c3119d7270e8a02ad47044a (diff) | |
| download | scummvm-rg350-f0f46113ee103e922ecde5f32652a482899c7e61.tar.gz scummvm-rg350-f0f46113ee103e922ecde5f32652a482899c7e61.tar.bz2 scummvm-rg350-f0f46113ee103e922ecde5f32652a482899c7e61.zip | |
Changed more parsing routines to use tables instead of switch statements.
svn-id: r28637
| -rw-r--r-- | engines/parallaction/animation.cpp | 155 | ||||
| -rw-r--r-- | engines/parallaction/commands.cpp | 193 | ||||
| -rw-r--r-- | engines/parallaction/commands.h | 11 | ||||
| -rw-r--r-- | engines/parallaction/dialogue.cpp | 6 | ||||
| -rw-r--r-- | engines/parallaction/location.cpp | 77 | ||||
| -rw-r--r-- | engines/parallaction/parallaction.cpp | 67 | ||||
| -rw-r--r-- | engines/parallaction/parallaction.h | 79 | ||||
| -rw-r--r-- | engines/parallaction/parser.cpp | 3 | ||||
| -rw-r--r-- | engines/parallaction/staticres.cpp | 31 | ||||
| -rw-r--r-- | engines/parallaction/zone.cpp | 120 | ||||
| -rw-r--r-- | engines/parallaction/zone.h | 1 | 
11 files changed, 490 insertions, 253 deletions
| diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp index 7e51cb9826..c73617ce35 100644 --- a/engines/parallaction/animation.cpp +++ b/engines/parallaction/animation.cpp @@ -68,80 +68,109 @@ Animation *Parallaction::findAnimation(const char *name) {  	return NULL;  } +DECLARE_ANIM_PARSER(invalid) { +	error("unknown statement '%s' in animation %s", _tokens[0], _locAnimParseCtxt.a->_label._text); +} -Animation *Parallaction::parseAnimation(Script& script, AnimationList &list, char *name) { -//	printf("parseAnimation(%s)\n", name); -	Animation *vD0 = new Animation; +DECLARE_ANIM_PARSER(script) { +	_locAnimParseCtxt.a->_scriptName = strdup(_tokens[1]); +} -	vD0->_label._text = (char*)malloc(strlen(name)+1); -	strcpy(vD0->_label._text, name); -	list.push_front(vD0); +DECLARE_ANIM_PARSER(commands) { +	 parseCommands(*_locAnimParseCtxt.script, _locAnimParseCtxt.a->_commands); +} -	fillBuffers(script, true); -	while (scumm_stricmp(_tokens[0], "endanimation")) { -//		printf("token[0] = %s\n", _tokens[0]); -		if (!scumm_stricmp(_tokens[0], "script")) { -			loadProgram(vD0, _tokens[1]); -		} -		if (!scumm_stricmp(_tokens[0], "commands")) { -			 parseCommands(script, vD0->_commands); -		} -		if (!scumm_stricmp(_tokens[0], "type")) { -			if (_tokens[2][0] != '\0') { -				vD0->_type = ((4 + _objectsNames->lookup(_tokens[2])) << 16) & 0xFFFF0000; -			} -			int16 _si = _zoneTypeNames->lookup(_tokens[1]); -			if (_si != Table::notFound) { -				vD0->_type |= 1 << (_si-1); -				if (((vD0->_type & 0xFFFF) != kZoneNone) && ((vD0->_type & 0xFFFF) != kZoneCommand)) { -					parseZoneTypeBlock(script, vD0); -				} -			} -		} -		if (!scumm_stricmp(_tokens[0], "label")) { -			renderLabel(&vD0->_label._cnv, _tokens[1]); -		} -		if (!scumm_stricmp(_tokens[0], "flags")) { -			uint16 _si = 1; - -			do { -				byte _al = _zoneFlagNames->lookup(_tokens[_si]); -				_si++; -				vD0->_flags |= 1 << (_al - 1); -			} while (!scumm_stricmp(_tokens[_si++], "|")); -		} -		if (!scumm_stricmp(_tokens[0], "file")) { -			char vC8[200]; -			strcpy(vC8, _tokens[1]); -			if (_engineFlags & kEngineTransformedDonna) { -				if (!scumm_stricmp(_tokens[1], "donnap") || !scumm_stricmp(_tokens[1], "donnapa")) { -					strcat(vC8, "tras"); -				} -			} -			vD0->_cnv = _disk->loadFrames(vC8); -		} -		if (!scumm_stricmp(_tokens[0], "position")) { -			vD0->_left = atoi(_tokens[1]); -			vD0->_top = atoi(_tokens[2]); -			vD0->_z = atoi(_tokens[3]); +DECLARE_ANIM_PARSER(type) { +	if (_tokens[2][0] != '\0') { +		_locAnimParseCtxt.a->_type = ((4 + _objectsNames->lookup(_tokens[2])) << 16) & 0xFFFF0000; +	} +	int16 _si = _zoneTypeNames->lookup(_tokens[1]); +	if (_si != Table::notFound) { +		_locAnimParseCtxt.a->_type |= 1 << (_si-1); +		if (((_locAnimParseCtxt.a->_type & 0xFFFF) != kZoneNone) && ((_locAnimParseCtxt.a->_type & 0xFFFF) != kZoneCommand)) { +			parseZoneTypeBlock(*_locAnimParseCtxt.script, _locAnimParseCtxt.a);  		} -		if (!scumm_stricmp(_tokens[0], "moveto")) { -			vD0->_moveTo.x = atoi(_tokens[1]); -			vD0->_moveTo.y = atoi(_tokens[2]); +	} + +	_locAnimParseCtxt.end = true; +} + + +DECLARE_ANIM_PARSER(label) { +	renderLabel(&_locAnimParseCtxt.a->_label._cnv, _tokens[1]); +} + + +DECLARE_ANIM_PARSER(flags) { +	uint16 _si = 1; + +	do { +		byte _al = _zoneFlagNames->lookup(_tokens[_si]); +		_si++; +		_locAnimParseCtxt.a->_flags |= 1 << (_al - 1); +	} while (!scumm_stricmp(_tokens[_si++], "|")); +} + + +DECLARE_ANIM_PARSER(file) { +	char vC8[200]; +	strcpy(vC8, _tokens[1]); +	if (_engineFlags & kEngineTransformedDonna) { +		if (!scumm_stricmp(_tokens[1], "donnap") || !scumm_stricmp(_tokens[1], "donnapa")) { +			strcat(vC8, "tras");  		} +	} +	_locAnimParseCtxt.a->_cnv = _disk->loadFrames(vC8); +} + + +DECLARE_ANIM_PARSER(position) { +	_locAnimParseCtxt.a->_left = atoi(_tokens[1]); +	_locAnimParseCtxt.a->_top = atoi(_tokens[2]); +	_locAnimParseCtxt.a->_z = atoi(_tokens[3]); +} + + +DECLARE_ANIM_PARSER(moveto) { +	_locAnimParseCtxt.a->_moveTo.x = atoi(_tokens[1]); +	_locAnimParseCtxt.a->_moveTo.y = atoi(_tokens[2]); +} + + +DECLARE_ANIM_PARSER(endanimation) { +	_locAnimParseCtxt.end = true; +} +Animation *Parallaction::parseAnimation(Script& script, AnimationList &list, char *name) { +//	printf("parseAnimation(%s)\n", name); + +	Animation *a = new Animation; + +	a->_label._text = strdup(name); + +	list.push_front(a); + +	_locAnimParseCtxt.a = a; +	_locAnimParseCtxt.end = false; +	_locAnimParseCtxt.script = &script; + +	do {  		fillBuffers(script, true); -	} -	vD0->_oldPos.x = -1000; -	vD0->_oldPos.y = -1000; +		int index = _locationAnimStmt->lookup(_tokens[0]); +		(this->*_locationAnimParsers[index])(); + +	} while (!_locAnimParseCtxt.end); -	vD0->_flags |= 0x1000000; +	a->_oldPos.x = -1000; +	a->_oldPos.y = -1000; -	return vD0; +	a->_flags |= 0x1000000; + +	return a;  } @@ -690,6 +719,7 @@ void Parallaction::sortAnimations() {  Animation::Animation() {  	_cnv = NULL;  	_program = NULL; +	_scriptName = 0;  	_frame = 0;  	_z = 0;  } @@ -698,6 +728,9 @@ Animation::~Animation() {  	if (_program)  		delete _program; +	if (_scriptName) +		free(_scriptName); +  	if (_cnv)  		delete _cnv;  } diff --git a/engines/parallaction/commands.cpp b/engines/parallaction/commands.cpp index 978cc6c3f8..0654ef4934 100644 --- a/engines/parallaction/commands.cpp +++ b/engines/parallaction/commands.cpp @@ -47,7 +47,9 @@ namespace Parallaction {  #define CMD_MOVE			15  #define CMD_STOP			16 -DECLARE_COMMAND_PARSER(Flags) { +DECLARE_COMMAND_PARSER(flags) { +	createCommand(_lookup); +  	if (_globalTable->lookup(_tokens[1]) == Table::notFound) {  		do {  			char _al = _localFlagNames->lookup(_tokens[_cmdParseCtxt.nextToken]); @@ -64,10 +66,15 @@ DECLARE_COMMAND_PARSER(Flags) {  		} while (!scumm_stricmp(_tokens[_cmdParseCtxt.nextToken++], "|"));  		_cmdParseCtxt.nextToken--;  	} + +	parseCommandFlags(); +	addCommand();  } -DECLARE_COMMAND_PARSER(Animation) { +DECLARE_COMMAND_PARSER(animation) { +	createCommand(_lookup); +  	_cmdParseCtxt.cmd->u._animation = findAnimation(_tokens[_cmdParseCtxt.nextToken]);  	_cmdParseCtxt.nextToken++;  	if (_cmdParseCtxt.cmd->u._animation == NULL) { @@ -75,124 +82,170 @@ DECLARE_COMMAND_PARSER(Animation) {  		_forwardedCommands[_numForwards] = _cmdParseCtxt.cmd;  		_numForwards++;  	} + +	parseCommandFlags(); +	addCommand();  } -DECLARE_COMMAND_PARSER(Zone) { +DECLARE_COMMAND_PARSER(zone) { +	createCommand(_lookup); +  	_cmdParseCtxt.cmd->u._zone = findZone(_tokens[_cmdParseCtxt.nextToken]);  	_cmdParseCtxt.nextToken++; + +	parseCommandFlags(); +	addCommand();  } -DECLARE_COMMAND_PARSER(Location) { +DECLARE_COMMAND_PARSER(location) { +	createCommand(_lookup); +  	_cmdParseCtxt.cmd->u._string = (char*)malloc(strlen(_tokens[_cmdParseCtxt.nextToken])+1);  	strcpy(_cmdParseCtxt.cmd->u._string, _tokens[_cmdParseCtxt.nextToken]);  	_cmdParseCtxt.nextToken++; + +	parseCommandFlags(); +	addCommand();  } -DECLARE_COMMAND_PARSER(Drop) { +DECLARE_COMMAND_PARSER(drop) { +	createCommand(_lookup); +  	_cmdParseCtxt.cmd->u._object = _objectsNames->lookup(_tokens[_cmdParseCtxt.nextToken]);  	_cmdParseCtxt.nextToken++; + +	parseCommandFlags(); +	addCommand();  } -DECLARE_COMMAND_PARSER(Call) { +DECLARE_COMMAND_PARSER(call) { +	createCommand(_lookup); +  	_cmdParseCtxt.cmd->u._callable = _callableNames->lookup(_tokens[_cmdParseCtxt.nextToken]) - 1;  	_cmdParseCtxt.nextToken++; + +	parseCommandFlags(); +	addCommand();  } -DECLARE_COMMAND_PARSER(Null) { +DECLARE_COMMAND_PARSER(null) {  } -DECLARE_COMMAND_PARSER(Move) { +DECLARE_COMMAND_PARSER(move) { +	createCommand(_lookup); +  	_cmdParseCtxt.cmd->u._move._x = atoi(_tokens[_cmdParseCtxt.nextToken]);  	_cmdParseCtxt.nextToken++;  	_cmdParseCtxt.cmd->u._move._y = atoi(_tokens[_cmdParseCtxt.nextToken]);  	_cmdParseCtxt.nextToken++; + +	parseCommandFlags(); +	addCommand();  } -DECLARE_COMMAND_PARSER(Invalid) { +DECLARE_COMMAND_PARSER(invalid) {  	error("Can't parse unknown command '%s'", _tokens[0]);  } -void Parallaction::parseCommands(Script &script, CommandList& list) { +DECLARE_COMMAND_PARSER(endcommands) { +	_cmdParseCtxt.end = true; +} -	fillBuffers(script, true); +void Parallaction::parseCommandFlags() { -	while (scumm_stricmp(_tokens[0], "ENDCOMMANDS") && scumm_stricmp(_tokens[0], "ENDZONE")) { +	int _si = _cmdParseCtxt.nextToken; +	Command *cmd = _cmdParseCtxt.cmd; -		Command *cmd = new Command; +	if (!scumm_stricmp(_tokens[_si], "flags")) { +		_si++; -		cmd->_id = _commandsNames->lookup(_tokens[0]); +		do { +			if (!scumm_stricmp(_tokens[_si], "exit") || !scumm_stricmp(_tokens[_si], "exittrap")) { +				cmd->_flagsOn |= kFlagsExit; +			} else +			if (!scumm_stricmp(_tokens[_si], "enter") || !scumm_stricmp(_tokens[_si], "entertrap")) { +				cmd->_flagsOn |= kFlagsEnter; +			} else +			if (!scumm_strnicmp(_tokens[_si], "no", 2)) { +				byte _al = _localFlagNames->lookup(&_tokens[_si][2]); +				cmd->_flagsOff |= 1 << (_al - 1); +			} else { +				byte _al = _localFlagNames->lookup(_tokens[_si]); +				cmd->_flagsOn |= 1 << (_al - 1); +			} -		_cmdParseCtxt.nextToken = 1; -		_cmdParseCtxt.cmd = cmd; +			_si++; -		(this->*_commandParsers[cmd->_id])(); +		} while (!scumm_stricmp(_tokens[_si++], "|")); -		int _si = _cmdParseCtxt.nextToken; +	} + +	if (!scumm_stricmp(_tokens[_si], "gflags")) { +		_si++; +		cmd->_flagsOn |= kFlagsGlobal; + +		do { +			if (!scumm_stricmp(_tokens[_si], "exit")) { +				cmd->_flagsOn |= kFlagsExit; +			} else +			if (!scumm_stricmp(_tokens[_si], "enter")) { +				cmd->_flagsOn |= kFlagsEnter; +			} else +			if (!scumm_strnicmp(_tokens[_si], "no", 2)) { +				byte _al = _globalTable->lookup(&_tokens[_si][2]); +				cmd->_flagsOff |= 1 << (_al - 1); +			} else { +				byte _al = _globalTable->lookup(_tokens[_si]); +				cmd->_flagsOn |= 1 << (_al - 1); +			} -		if (!scumm_stricmp(_tokens[_si], "flags")) {  			_si++; -			do { -				if (!scumm_stricmp(_tokens[_si], "exit") || !scumm_stricmp(_tokens[_si], "exittrap")) { -					cmd->_flagsOn |= kFlagsExit; -				} else -				if (!scumm_stricmp(_tokens[_si], "enter") || !scumm_stricmp(_tokens[_si], "entertrap")) { -					cmd->_flagsOn |= kFlagsEnter; -				} else -				if (!scumm_strnicmp(_tokens[_si], "no", 2)) { -					byte _al = _localFlagNames->lookup(&_tokens[_si][2]); -					cmd->_flagsOff |= 1 << (_al - 1); -				} else { -					byte _al = _localFlagNames->lookup(_tokens[_si]); -					cmd->_flagsOn |= 1 << (_al - 1); -				} - -				_si++; - -			} while (!scumm_stricmp(_tokens[_si++], "|")); +		} while (!scumm_stricmp(_tokens[_si++], "|")); -		} +	} -		if (!scumm_stricmp(_tokens[_si], "gflags")) { -			_si++; -			cmd->_flagsOn |= kFlagsGlobal; - -			do { -				if (!scumm_stricmp(_tokens[_si], "exit")) { -					cmd->_flagsOn |= kFlagsExit; -				} else -				if (!scumm_stricmp(_tokens[_si], "enter")) { -					cmd->_flagsOn |= kFlagsEnter; -				} else -				if (!scumm_strnicmp(_tokens[_si], "no", 2)) { -					byte _al = _globalTable->lookup(&_tokens[_si][2]); -					cmd->_flagsOff |= 1 << (_al - 1); -				} else { -					byte _al = _globalTable->lookup(_tokens[_si]); -					cmd->_flagsOn |= 1 << (_al - 1); -				} - -				_si++; - -			} while (!scumm_stricmp(_tokens[_si++], "|")); +	_si = _cmdParseCtxt.nextToken; -		} +} + +void Parallaction::addCommand() { + +	// FIXME: implement a proper parseCommands for BRA +	if (getGameType() == GType_BRA) +		delete _cmdParseCtxt.cmd; +	else +		_cmdParseCtxt.list->push_front(_cmdParseCtxt.cmd);	// NOTE: command lists are written backwards in scripts + +} -		// FIXME: implement a proper parseCommands for BRA -		if (getGameType() == GType_BRA) -			delete cmd; -		else -			list.push_front(cmd);	// NOTE: command lists are written backwards in scripts +void Parallaction::createCommand(uint id) { +	_cmdParseCtxt.nextToken = 1; +	_cmdParseCtxt.cmd = new Command; +	_cmdParseCtxt.cmd->_id = id; + +} + +void Parallaction::parseCommands(Script &script, CommandList& list) { + +	_cmdParseCtxt.list = &list; +	_cmdParseCtxt.end = false; + +	do {  		fillBuffers(script, true); -	} +		_lookup = _commandsNames->lookup(_tokens[0]); +		(this->*_commandParsers[_lookup])(); + +	} while (!_cmdParseCtxt.end); +  }  DECLARE_COMMAND_OPCODE(invalid) { @@ -220,7 +273,7 @@ DECLARE_COMMAND_OPCODE(clear) {  DECLARE_COMMAND_OPCODE(start) { -	_cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActing; +	_cmdRunCtxt.cmd->u._animation->_flags |= kFlagsActing;  } @@ -319,7 +372,7 @@ DECLARE_COMMAND_OPCODE(move) {  DECLARE_COMMAND_OPCODE(stop) { -	_cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsActing; +	_cmdRunCtxt.cmd->u._animation->_flags &= ~kFlagsActing;  } @@ -366,8 +419,6 @@ Command::Command() {  Command::~Command() { -	if (_id == CMD_LOCATION) free(u._string); -  }  } // namespace Parallaction diff --git a/engines/parallaction/commands.h b/engines/parallaction/commands.h index 64510afc13..6db194d8c7 100644 --- a/engines/parallaction/commands.h +++ b/engines/parallaction/commands.h @@ -46,7 +46,7 @@ struct Animation;  // TODO: turn this into a struct -union CommandData { +struct CommandData {  	uint32			_flags;  	Animation * 	_animation;  	Zone*			_zone; @@ -60,9 +60,18 @@ union CommandData {  	CommandData() {  		_flags = 0; +		_animation = 0; +		_zone = 0; +		_string = 0; +		_callable = 0; +		_object = 0; +		_move._x = 0; +		_move._y = 0;  	}  	~CommandData() { +		if (_string) +			free(_string);  	}  }; diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index 8d4e8f3e9d..93f2054c9e 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -179,11 +179,7 @@ char *Parallaction::parseDialogueString(Script &script) {  	vD0[strlen(vD0)-1] = '\0';	// deletes the trailing '0xA'  								// this is critical for Gfx::displayWrappedString to work properly - -	char *vCC = (char*)malloc(strlen(vD0)+1); -	strcpy(vCC, vD0); - -	return vCC; +	return strdup(vD0);  }  class DialogueManager { diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp index 4359b69e2a..177480927f 100644 --- a/engines/parallaction/location.cpp +++ b/engines/parallaction/location.cpp @@ -148,17 +148,46 @@ DECLARE_LOCATION_PARSER(music) {  		_soundMan->setMusicFile(_tokens[1]);  } - +DECLARE_LOCATION_PARSER(redundant) { +	warning("redundant '%s' line found in script '%s'", _tokens[0], _locParseCtxt.filename); +}  void Parallaction::parseLocation(const char *filename) {      debugC(1, kDebugLocation, "parseLocation('%s')", filename); -	_gfx->setFont(_labelFont); +	allocateLocationSlot(filename);  	Script *script = _disk->loadLocation(filename); + +	// TODO: the following two lines are specific to Nippon Safes +	// and should be moved into something like 'initializeParsing()' +	_gfx->setFont(_labelFont);  	_hasLocationSound = false; +	_locParseCtxt.end = false;; +	_locParseCtxt.script = script; +	_locParseCtxt.filename = filename; + + +	do { + +		fillBuffers(*script, true); + +		int index = _locationStmt->lookup(_tokens[0]); +		(this->*_locationParsers[index])(); + +	} while (!_locParseCtxt.end); + + +	delete script; + +	finalizeLocationParsing(); + +	return; +} + +void Parallaction::allocateLocationSlot(const char *name) {  	// WORKAROUND: the original code erroneously incremented  	// _currentLocationIndex, thus producing inconsistent  	// savegames. This workaround modified the following loop @@ -167,14 +196,17 @@ void Parallaction::parseLocation(const char *filename) {  	_currentLocationIndex = -1;  	uint16 _di = 0;  	while (_locationNames[_di][0] != '\0') { -		if (!scumm_stricmp(_locationNames[_di], filename)) { +		if (!scumm_stricmp(_locationNames[_di], name)) {  			_currentLocationIndex = _di;  		}  		_di++;  	} +	if (_di == 120) +		error("No more location slots available. Please report this immediately to ScummVM team."); +  	if (_currentLocationIndex  == -1) { -		strcpy(_locationNames[_numLocations], filename); +		strcpy(_locationNames[_numLocations], name);  		_currentLocationIndex = _numLocations;  		_numLocations++; @@ -183,41 +215,24 @@ void Parallaction::parseLocation(const char *filename) {  	} else {  		_localFlags[_currentLocationIndex] |= kFlagsVisited;	// 'visited'  	} - -	_locParseCtxt.end = false;; -	_locParseCtxt.script = script; -	_locParseCtxt.filename = filename; - -	fillBuffers(*script, true); - -	int index; -	while (true) { - -		index = _locationStmt->lookup(_tokens[0]); - -		(this->*_locationParsers[index])(); - -		if (_locParseCtxt.end) -			break; - -		fillBuffers(*script, true); -	} - -	resolveLocationForwards(); - -	delete script; - -	return;  } -void Parallaction::resolveLocationForwards() { +void Parallaction::finalizeLocationParsing() { +	// this resolves any forward references in the script  	for (uint16 _si = 0; _forwardedCommands[_si]; _si++) {  		_forwardedCommands[_si]->u._animation = findAnimation(_forwardedAnimationNames[_si]);  		_forwardedCommands[_si] = NULL;  	} -  	_numForwards = 0; + +	// this loads animation scripts +	AnimationList::iterator it = _animations.begin(); +	for ( ; it != _animations.end(); it++) { +		if ((*it)->_scriptName) +			loadProgram(*it, (*it)->_scriptName); +	} +  	return;  } diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 367b470a10..b2893ebfca 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -902,23 +902,25 @@ void Parallaction::initOpcodes() {  	_vm->_instructionOpcodes = op1;  	static const Opcode op2[] = { -		COMMAND_PARSER(Invalid), -		COMMAND_PARSER(Flags),			// set -		COMMAND_PARSER(Flags),			// clear -		COMMAND_PARSER(Animation),		// start -		COMMAND_PARSER(Zone),			// speak -		COMMAND_PARSER(Zone),			// get -		COMMAND_PARSER(Location),		// location -		COMMAND_PARSER(Zone),			// open -		COMMAND_PARSER(Zone),			// close -		COMMAND_PARSER(Zone),			// on -		COMMAND_PARSER(Zone),			// off -		COMMAND_PARSER(Call),			// call -		COMMAND_PARSER(Flags),			// toggle -		COMMAND_PARSER(Drop),			// drop -		COMMAND_PARSER(Null),			// quit -		COMMAND_PARSER(Move),			// move -		COMMAND_PARSER(Animation)		// stop +		COMMAND_PARSER(invalid), +		COMMAND_PARSER(flags),			// set +		COMMAND_PARSER(flags),			// clear +		COMMAND_PARSER(animation),		// start +		COMMAND_PARSER(zone),			// speak +		COMMAND_PARSER(zone),			// get +		COMMAND_PARSER(location),		// location +		COMMAND_PARSER(zone),			// open +		COMMAND_PARSER(zone),			// close +		COMMAND_PARSER(zone),			// on +		COMMAND_PARSER(zone),			// off +		COMMAND_PARSER(call),			// call +		COMMAND_PARSER(flags),			// toggle +		COMMAND_PARSER(drop),			// drop +		COMMAND_PARSER(null),			// quit +		COMMAND_PARSER(move),			// move +		COMMAND_PARSER(animation),		// stop +		COMMAND_PARSER(endcommands),	// endcommands +		COMMAND_PARSER(endcommands)		// endzone  	};  	_commandParsers = op2; @@ -961,12 +963,41 @@ void Parallaction::initOpcodes() {  		LOCATION_PARSER(comment),  		LOCATION_PARSER(endcomment),  		LOCATION_PARSER(sound), -		LOCATION_PARSER(music) +		LOCATION_PARSER(music), +		LOCATION_PARSER(redundant)	// for redundant endanimation  	};  	_locationParsers = op4; +	static const Opcode op5[] = { +		ZONE_PARSER(invalid), +		ZONE_PARSER(limits), +		ZONE_PARSER(moveto), +		ZONE_PARSER(type), +		ZONE_PARSER(commands), +		ZONE_PARSER(label), +		ZONE_PARSER(flags), +		ZONE_PARSER(endzone) +	}; + +	_locationZoneParsers = op5; + +	static const Opcode op6[] = { +		ANIM_PARSER(invalid), +		ANIM_PARSER(script), +		ANIM_PARSER(commands), +		ANIM_PARSER(type), +		ANIM_PARSER(label), +		ANIM_PARSER(flags), +		ANIM_PARSER(file), +		ANIM_PARSER(position), +		ANIM_PARSER(moveto), +		ANIM_PARSER(endanimation) +	}; + +	_locationAnimParsers = op6; +  }  } // namespace Parallaction diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index c7d6f5529b..43564b4743 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -296,6 +296,14 @@ struct BackgroundInfo {  }; +#define DECLARE_ZONE_PARSER(sig) void Parallaction::locZoneParse_##sig() +#define DECLARE_UNQUALIFIED_ZONE_PARSER(sig) void locZoneParse_##sig() +#define ZONE_PARSER(sig) &Parallaction::locZoneParse_##sig + +#define DECLARE_ANIM_PARSER(sig) void Parallaction::locAnimParse_##sig() +#define DECLARE_UNQUALIFIED_ANIM_PARSER(sig) void locAnimParse_##sig() +#define ANIM_PARSER(sig) &Parallaction::locAnimParse_##sig +  #define DECLARE_COMMAND_PARSER(sig) void Parallaction::cmdParse_##sig()  #define DECLARE_UNQUALIFIED_COMMAND_PARSER(sig) void cmdParse_##sig()  #define COMMAND_PARSER(sig) &Parallaction::cmdParse_##sig @@ -338,20 +346,25 @@ public:  	typedef void (Parallaction::*Opcode)();  	const Opcode	*_commandParsers; +	uint	_lookup; +  	struct {  		Command	*cmd;  		int		nextToken; +		CommandList *list; +		bool	end;  	} _cmdParseCtxt; -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Invalid); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Flags); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Animation); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Zone); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Location); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Drop); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Call); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Null); -	DECLARE_UNQUALIFIED_COMMAND_PARSER(Move); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(invalid); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(flags); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(animation); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(zone); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(location); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(drop); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(call); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(null); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(move); +	DECLARE_UNQUALIFIED_COMMAND_PARSER(endcommands);  	const Opcode	*_commandOpcodes; @@ -434,6 +447,7 @@ public:  		const char	*filename;  		bool	end;  		Script	*script; +		Zone *z;  	} _locParseCtxt;  	DECLARE_UNQUALIFIED_LOCATION_PARSER(invalid); @@ -451,6 +465,43 @@ public:  	DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment);  	DECLARE_UNQUALIFIED_LOCATION_PARSER(sound);  	DECLARE_UNQUALIFIED_LOCATION_PARSER(music); +	DECLARE_UNQUALIFIED_LOCATION_PARSER(redundant); + +	const Opcode  *_locationZoneParsers; + +	struct { +		bool	end; +		Script	*script; +		Zone *z; +	} _locZoneParseCtxt; + +	DECLARE_UNQUALIFIED_ZONE_PARSER(invalid); +	DECLARE_UNQUALIFIED_ZONE_PARSER(limits); +	DECLARE_UNQUALIFIED_ZONE_PARSER(moveto); +	DECLARE_UNQUALIFIED_ZONE_PARSER(type); +	DECLARE_UNQUALIFIED_ZONE_PARSER(commands); +	DECLARE_UNQUALIFIED_ZONE_PARSER(label); +	DECLARE_UNQUALIFIED_ZONE_PARSER(flags); +	DECLARE_UNQUALIFIED_ZONE_PARSER(endzone); + +	const Opcode  *_locationAnimParsers; + +	struct { +		bool	end; +		Script	*script; +		Animation *a; +	} _locAnimParseCtxt; + +	DECLARE_UNQUALIFIED_ANIM_PARSER(invalid); +	DECLARE_UNQUALIFIED_ANIM_PARSER(script); +	DECLARE_UNQUALIFIED_ANIM_PARSER(commands); +	DECLARE_UNQUALIFIED_ANIM_PARSER(type); +	DECLARE_UNQUALIFIED_ANIM_PARSER(label); +	DECLARE_UNQUALIFIED_ANIM_PARSER(flags); +	DECLARE_UNQUALIFIED_ANIM_PARSER(file); +	DECLARE_UNQUALIFIED_ANIM_PARSER(position); +	DECLARE_UNQUALIFIED_ANIM_PARSER(moveto); +	DECLARE_UNQUALIFIED_ANIM_PARSER(endanimation);  	void 		changeCursor(int32 index);  	void		showCursor(bool visible); @@ -496,8 +547,8 @@ public:  	Table		*_instructionNames;  	Table		*_localFlagNames;  	Table		*_locationStmt; - - +	Table		*_locationZoneStmt; +	Table		*_locationAnimStmt;  public: @@ -597,7 +648,8 @@ protected:		// members  	void		doLocationEnterTransition();  	void		changeLocation(char *location); -	void 		resolveLocationForwards(); +	void		allocateLocationSlot(const char *name); +	void 		finalizeLocationParsing();  	void 		switchBackground(const char* background, const char* mask);  	void 		freeLocation();  	void 		showLocationComment(const char *text, bool end); @@ -616,6 +668,9 @@ protected:		// members  	LValue		getLValue(Instruction *inst, char *str, LocalVariable *locals, Animation *a);  	void		parseCommands(Script &script, CommandList&); +	void		parseCommandFlags(); +	void		createCommand(uint id); +	void		addCommand();  	void 		freeCharacter(); diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp index d786cc6487..34b5e02f8e 100644 --- a/engines/parallaction/parser.cpp +++ b/engines/parallaction/parser.cpp @@ -103,8 +103,7 @@ char *Parallaction::parseComment(Script &script) {  		strcat(_tmp_comment, " ");  	} while (true); -	v194 = (char*)malloc(strlen(_tmp_comment)+1); -	strcpy(v194, _tmp_comment); +	v194 = strdup(_tmp_comment);  	_tmp_comment[0] = '\0';  	return v194; diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp index fe7c91160f..d8dbd35816 100644 --- a/engines/parallaction/staticres.cpp +++ b/engines/parallaction/staticres.cpp @@ -278,7 +278,9 @@ const char *_commandsNamesRes_ns[] = {  	"drop",  	"quit",  	"move", -	"stop" +	"stop", +	"endcommands", +	"endzone"  };  const char *_instructionNamesRes_ns[] = { @@ -344,7 +346,30 @@ const char *_locationStmtRes_ns[] = {  	"comment",  	"endcomment",  	"sound", -	"music" +	"music", +	"endanimation" +}; + +const char *_locationZoneStmtRes_ns[] = { +	"limits", +	"moveto", +	"type", +	"commands", +	"label", +	"flags", +	"endzone" +}; + +const char *_locationAnimStmtRes_ns[] = { +	"script", +	"commands", +	"type", +	"label", +	"flags", +	"file", +	"position", +	"moveto", +	"endanimation"  };  const char *_zoneTypeNamesRes_br[] = { @@ -582,6 +607,8 @@ void Parallaction_ns::initResources() {  	_zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_ns), _zoneTypeNamesRes_ns);  	_commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_ns), _commandsNamesRes_ns);  	_locationStmt = new Table(ARRAYSIZE(_locationStmtRes_ns), _locationStmtRes_ns); +	_locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_ns), _locationZoneStmtRes_ns); +	_locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_ns), _locationAnimStmtRes_ns);  	_localFlagNames = new Table(120);  	_localFlagNames->addData("visited"); diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp index 9cc5f28c8a..7179e7c67d 100644 --- a/engines/parallaction/zone.cpp +++ b/engines/parallaction/zone.cpp @@ -36,17 +36,72 @@ namespace Parallaction {  Zone *Parallaction::findZone(const char *name) { -	for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) +	for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) {  		if (!scumm_stricmp((*it)->_label._text, name)) return *it; +	}  	return findAnimation(name);  } +DECLARE_ZONE_PARSER(invalid) { +	error("unknown statement '%s' in zone %s", _tokens[0], _locZoneParseCtxt.z->_label._text); +} + +DECLARE_ZONE_PARSER(endzone) { +	_locZoneParseCtxt.end = true; +} + +DECLARE_ZONE_PARSER(limits) { +	_locZoneParseCtxt.z->_left = atoi(_tokens[1]); +	_locZoneParseCtxt.z->_top = atoi(_tokens[2]); +	_locZoneParseCtxt.z->_right = atoi(_tokens[3]); +	_locZoneParseCtxt.z->_bottom = atoi(_tokens[4]); +} + + +DECLARE_ZONE_PARSER(moveto) { +	_locZoneParseCtxt.z->_moveTo.x = atoi(_tokens[1]); +	_locZoneParseCtxt.z->_moveTo.y = atoi(_tokens[2]); +} + + +DECLARE_ZONE_PARSER(type) { +	if (_tokens[2][0] != '\0') { +		_locZoneParseCtxt.z->_type = (4 + _objectsNames->lookup(_tokens[2])) << 16; +	} +	int16 _si = _zoneTypeNames->lookup(_tokens[1]); +	if (_si != Table::notFound) { +		_locZoneParseCtxt.z->_type |= 1 << (_si - 1); +		parseZoneTypeBlock(*_locZoneParseCtxt.script, _locZoneParseCtxt.z); +	} + +	_locZoneParseCtxt.end = true; +} + + +DECLARE_ZONE_PARSER(commands) { +	 parseCommands(*_locZoneParseCtxt.script, _locZoneParseCtxt.z->_commands); +} + + +DECLARE_ZONE_PARSER(label) { +//			printf("label: %s", _tokens[1]); +	renderLabel(&_locZoneParseCtxt.z->_label._cnv, _tokens[1]); +} + +DECLARE_ZONE_PARSER(flags) { +	uint16 _si = 1; +	do { +		char _al = _zoneFlagNames->lookup(_tokens[_si]); +		_si++; +		_locZoneParseCtxt.z->_flags |= 1 << (_al - 1); +	} while (!scumm_stricmp(_tokens[_si++], "|")); +}  void Parallaction::parseZone(Script &script, ZoneList &list, char *name) { -//	printf("parseZone(%s)", name); +	printf("parseZone(%s)\n", name);  	if (findZone(name)) {  		while (scumm_stricmp(_tokens[0], "endzone")) { @@ -57,55 +112,22 @@ void Parallaction::parseZone(Script &script, ZoneList &list, char *name) {  	Zone *z = new Zone; -	z->_label._text = (char*)malloc(strlen(name)+1); -	strcpy(z->_label._text, name); +	z->_label._text = strdup(name); -	list.push_front(z); +	_locZoneParseCtxt.z = z; +	_locZoneParseCtxt.end = false; +	_locZoneParseCtxt.script = &script; -	fillBuffers(script, true); -	while (scumm_stricmp(_tokens[0], "endzone")) { -//		printf("token[0] = %s", _tokens[0]); +	list.push_front(z); -		if (!scumm_stricmp(_tokens[0], "limits")) { -			z->_left = atoi(_tokens[1]); -			z->_top = atoi(_tokens[2]); -			z->_right = atoi(_tokens[3]); -			z->_bottom = atoi(_tokens[4]); -		} -		if (!scumm_stricmp(_tokens[0], "moveto")) { -			z->_moveTo.x = atoi(_tokens[1]); -			z->_moveTo.y = atoi(_tokens[2]); -		} -		if (!scumm_stricmp(_tokens[0], "type")) { -			if (_tokens[2][0] != '\0') { -				z->_type = (4 + _objectsNames->lookup(_tokens[2])) << 16; -			} -			int16 _si = _zoneTypeNames->lookup(_tokens[1]); -			if (_si != Table::notFound) { -				z->_type |= 1 << (_si - 1); -				parseZoneTypeBlock(script, z); -				continue; -			} -		} -		if (!scumm_stricmp(_tokens[0], "commands")) { -			 parseCommands(script, z->_commands); -		} -		if (!scumm_stricmp(_tokens[0], "label")) { -//			printf("label: %s", _tokens[1]); -			renderLabel(&z->_label._cnv, _tokens[1]); -		} -		if (!scumm_stricmp(_tokens[0], "flags")) { -			uint16 _si = 1; - -			do { -				char _al = _zoneFlagNames->lookup(_tokens[_si]); -				_si++; -				z->_flags |= 1 << (_al - 1); -			} while (!scumm_stricmp(_tokens[_si++], "|")); -		} +	do {  		fillBuffers(script, true); -	} + +		int index = _locationZoneStmt->lookup(_tokens[0]); +		(this->*_locationZoneParsers[index])(); + +	} while (!_locZoneParseCtxt.end);  	return;  } @@ -191,8 +213,7 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {  		switch (z->_type & 0xFFFF) {  		case kZoneExamine: // examine Zone init  			if (!scumm_stricmp(_tokens[0], "file")) { -				u->examine->_filename = (char*)malloc(strlen(_tokens[1])+1); -				strcpy(u->examine->_filename, _tokens[1]); +				u->examine->_filename = strdup(_tokens[1]);  			}  			if (!scumm_stricmp(_tokens[0], "desc")) {  				u->examine->_description = parseComment(script); @@ -207,8 +228,7 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {  			}  			if (!scumm_stricmp(_tokens[0], "location")) { -				u->door->_location = (char*)malloc(strlen(_tokens[1])+1); -				strcpy(u->door->_location, _tokens[1]); +				u->door->_location = strdup(_tokens[1]);  			}  			if (!scumm_stricmp(_tokens[0], "file")) { diff --git a/engines/parallaction/zone.h b/engines/parallaction/zone.h index c6a1164eb4..38b8730c4b 100644 --- a/engines/parallaction/zone.h +++ b/engines/parallaction/zone.h @@ -297,6 +297,7 @@ struct Animation : public Zone  {  	Common::Point	_oldPos;  	Program 	*_program;  	Cnv 		*_cnv; +	char		*_scriptName;  	int16		_frame;  	uint16		field_50;		// unused  	int16		_z; | 
