aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction
diff options
context:
space:
mode:
authorNicola Mettifogo2007-08-16 17:28:18 +0000
committerNicola Mettifogo2007-08-16 17:28:18 +0000
commitf0f46113ee103e922ecde5f32652a482899c7e61 (patch)
treef64d178e1ac84dc135fef556c4ba53b944a24fdf /engines/parallaction
parentc987d6aaf0744e088c3119d7270e8a02ad47044a (diff)
downloadscummvm-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
Diffstat (limited to 'engines/parallaction')
-rw-r--r--engines/parallaction/animation.cpp155
-rw-r--r--engines/parallaction/commands.cpp193
-rw-r--r--engines/parallaction/commands.h11
-rw-r--r--engines/parallaction/dialogue.cpp6
-rw-r--r--engines/parallaction/location.cpp77
-rw-r--r--engines/parallaction/parallaction.cpp67
-rw-r--r--engines/parallaction/parallaction.h79
-rw-r--r--engines/parallaction/parser.cpp3
-rw-r--r--engines/parallaction/staticres.cpp31
-rw-r--r--engines/parallaction/zone.cpp120
-rw-r--r--engines/parallaction/zone.h1
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;