From f0f46113ee103e922ecde5f32652a482899c7e61 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Thu, 16 Aug 2007 17:28:18 +0000 Subject: Changed more parsing routines to use tables instead of switch statements. svn-id: r28637 --- engines/parallaction/animation.cpp | 155 ++++++++++++++++----------- engines/parallaction/commands.cpp | 193 +++++++++++++++++++++------------- engines/parallaction/commands.h | 11 +- engines/parallaction/dialogue.cpp | 6 +- engines/parallaction/location.cpp | 77 ++++++++------ engines/parallaction/parallaction.cpp | 67 ++++++++---- engines/parallaction/parallaction.h | 79 +++++++++++--- engines/parallaction/parser.cpp | 3 +- engines/parallaction/staticres.cpp | 31 +++++- engines/parallaction/zone.cpp | 120 ++++++++++++--------- engines/parallaction/zone.h | 1 + 11 files changed, 490 insertions(+), 253 deletions(-) (limited to 'engines/parallaction') 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; -- cgit v1.2.3