aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/parallaction/animation.cpp769
-rw-r--r--engines/parallaction/commands.cpp421
-rw-r--r--engines/parallaction/commands.h92
-rw-r--r--engines/parallaction/dialogue.cpp155
-rw-r--r--engines/parallaction/disk_br.cpp12
-rw-r--r--engines/parallaction/exec_ns.cpp857
-rw-r--r--engines/parallaction/font.cpp2
-rw-r--r--engines/parallaction/inventory.cpp2
-rw-r--r--engines/parallaction/location.cpp567
-rw-r--r--engines/parallaction/module.mk11
-rw-r--r--engines/parallaction/objects.cpp215
-rw-r--r--engines/parallaction/objects.h (renamed from engines/parallaction/zone.h)118
-rw-r--r--engines/parallaction/parallaction.cpp584
-rw-r--r--engines/parallaction/parallaction.h548
-rw-r--r--engines/parallaction/parallaction_br.cpp86
-rw-r--r--engines/parallaction/parallaction_ns.cpp9
-rw-r--r--engines/parallaction/parser.cpp35
-rw-r--r--engines/parallaction/parser.h3
-rw-r--r--engines/parallaction/parser_ns.cpp1355
-rw-r--r--engines/parallaction/staticres.cpp59
-rw-r--r--engines/parallaction/zone.cpp697
21 files changed, 3392 insertions, 3205 deletions
diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp
deleted file mode 100644
index 47c5454be1..0000000000
--- a/engines/parallaction/animation.cpp
+++ /dev/null
@@ -1,769 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-
-#include "parallaction/parallaction.h"
-
-
-namespace Parallaction {
-
-
-#define INST_ON 1
-#define INST_OFF 2
-#define INST_X 3
-#define INST_Y 4
-#define INST_Z 5
-#define INST_F 6
-#define INST_LOOP 7
-#define INST_ENDLOOP 8
-#define INST_SHOW 9
-#define INST_INC 10
-#define INST_DEC 11
-#define INST_SET 12
-#define INST_PUT 13
-#define INST_CALL 14
-#define INST_WAIT 15
-#define INST_START 16
-#define INST_SOUND 17
-#define INST_MOVE 18
-#define INST_END 19
-
-
-void wrapLocalVar(LocalVariable *local);
-
-
-#define NUM_LOCALS 10
-
-uint16 _numLocals = 0;
-char _localNames[NUM_LOCALS][10];
-
-Animation *Parallaction::findAnimation(const char *name) {
-
- for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++)
- if (!scumm_stricmp((*it)->_label._text, name)) return *it;
-
- return NULL;
-}
-
-DECLARE_ANIM_PARSER(invalid) {
- error("unknown statement '%s' in animation %s", _tokens[0], _locAnimParseCtxt.a->_label._text);
-}
-
-
-DECLARE_ANIM_PARSER(script) {
- _locAnimParseCtxt.a->_scriptName = strdup(_tokens[1]);
-}
-
-
-DECLARE_ANIM_PARSER(commands) {
- parseCommands(*_locAnimParseCtxt.script, _locAnimParseCtxt.a->_commands);
-}
-
-
-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);
- }
- }
-
- _locAnimParseCtxt.a->_oldPos.x = -1000;
- _locAnimParseCtxt.a->_oldPos.y = -1000;
-
- _locAnimParseCtxt.a->_flags |= 0x1000000;
-
- popParserTables();
-}
-
-
-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.a->_oldPos.x = -1000;
- _locAnimParseCtxt.a->_oldPos.y = -1000;
-
- _locAnimParseCtxt.a->_flags |= 0x1000000;
-
- popParserTables();
-}
-
-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;
-
- pushParserTables(_locationAnimParsers, _locationAnimStmt);
-
- return a;
-}
-
-
-void Parallaction::freeAnimations() {
- _animations.clear();
- return;
-}
-
-
-
-void jobDisplayAnimations(void *parm, Job *j) {
-// printf("jobDisplayAnimations()...\n");
-
- Graphics::Surface v14;
-
- uint16 _si = 0;
-
- for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
-
- Animation *v18 = *it;
-
- if ((v18->_flags & kFlagsActive) && ((v18->_flags & kFlagsRemove) == 0)) {
- v14.w = v18->width();
- v14.h = v18->height();
-
- int16 frame = CLIP((int)v18->_frame, 0, v18->getFrameNum()-1);
-
- v14.pixels = v18->getFrameData(frame);
-
- if (v18->_flags & kFlagsNoMasked)
- _si = 3;
- else
- _si = _vm->_gfx->queryMask(v18->_top + v18->height());
-
- debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, f:%i/%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14.w, v14.h,
- frame, v18->getFrameNum(), v14.pixels);
- _vm->_gfx->blitCnv(&v14, v18->_left, v18->_top, _si, Gfx::kBitBack);
-
- }
-
- if (((v18->_flags & kFlagsActive) == 0) && (v18->_flags & kFlagsRemove)) {
- v18->_flags &= ~kFlagsRemove;
- v18->_oldPos.x = -1000;
- }
-
- if ((v18->_flags & kFlagsActive) && (v18->_flags & kFlagsRemove)) {
- v18->_flags &= ~kFlagsActive;
- v18->_flags |= kFlagsRemove;
- }
-
- }
-
-// printf("done\n");
-
- return;
-}
-
-
-void jobEraseAnimations(void *arg_0, Job *j) {
- debugC(3, kDebugJobs, "jobEraseAnimations");
-
- for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
-
- Animation *a = *it;
-
- if (((a->_flags & kFlagsActive) == 0) && ((a->_flags & kFlagsRemove) == 0)) continue;
-
- Common::Rect r(a->width(), a->height());
- r.moveTo(a->_oldPos);
- _vm->_gfx->restoreBackground(r);
-
- if (arg_0) {
- a->_oldPos.x = a->_left;
- a->_oldPos.y = a->_top;
- }
-
- }
-
-// printf("done\n");
-
- return;
-}
-
-
-void Parallaction::loadProgram(Animation *a, char *filename) {
-// printf("loadProgram(%s)\n", filename);
-
- Script *script = _disk->loadScript(filename);
-
- _numLocals = 0;
-
- fillBuffers(*script);
-
- a->_program = new Program;
-
- Instruction *vCC = new Instruction;
-
- while (scumm_stricmp(_tokens[0], "endscript")) {
- parseScriptLine(vCC, a, a->_program->_locals);
- a->_program->_instructions.push_back(vCC);
- vCC = new Instruction;
- fillBuffers(*script);
- }
-
- // TODO: use List<>::end() to detect the end of the program
- vCC->_index = INST_END;
- a->_program->_instructions.push_back(vCC);
- a->_program->_ip = a->_program->_instructions.begin();
-
- delete script;
-
- return;
-}
-
-int16 findLocal(const char* name, LocalVariable *locals) {
- for (uint16 _si = 0; _si < NUM_LOCALS; _si++) {
- if (!scumm_stricmp(name, _localNames[_si]))
- return _si;
- }
-
- return -1;
-}
-
-int16 addLocal(const char *name, LocalVariable *locals, int16 value = 0, int16 min = -10000, int16 max = 10000) {
- assert(_numLocals < NUM_LOCALS);
-
- strcpy(_localNames[_numLocals], name);
- locals[_numLocals]._value = value;
-
- locals[_numLocals]._min = min;
- locals[_numLocals]._max = max;
-
- return _numLocals++;
-}
-
-
-DECLARE_INSTRUCTION_PARSER(animation) {
- if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
- _instParseCtxt.inst->_opBase._a = _instParseCtxt.a;
- } else {
- _instParseCtxt.inst->_opBase._a = findAnimation(_tokens[1]);
- }
-}
-
-
-DECLARE_INSTRUCTION_PARSER(loop) {
- _instParseCtxt.inst->_opBase._loopCounter = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(x) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_left;
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(y) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_top;
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(z) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_z;
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(f) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_frame;
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(inc) {
- if (!scumm_stricmp(_tokens[1], "X")) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_left;
- } else
- if (!scumm_stricmp(_tokens[1], "Y")) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_top;
- } else
- if (!scumm_stricmp(_tokens[1], "Z")) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_z;
- } else
- if (!scumm_stricmp(_tokens[1], "F")) {
- _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_frame;
- } else {
- _instParseCtxt.inst->_flags |= kInstUsesLocal;
- _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
- }
-
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
-
- if (!scumm_stricmp(_tokens[3], "mod")) {
- _instParseCtxt.inst->_flags |= kInstMod;
- }
-}
-
-
-DECLARE_INSTRUCTION_PARSER(set) {
- // WORKAROUND: At least one script (balzo.script) in Amiga versions didn't declare
- // local variables before using them, thus leading to crashes. The line launching the
- // script was commented out on Dos version. This workaround enables the engine
- // to dynamically add a local variable when it is encountered the first time in
- // the script, so should fix any other occurrence as well.
- if (findLocal(_tokens[1], _instParseCtxt.locals) == -1) {
- addLocal(_tokens[1], _instParseCtxt.locals);
- }
-
- _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
- _instParseCtxt.inst->_flags |= kInstUsesLocal;
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(move) {
- _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(put) {
- if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
- _instParseCtxt.inst->_opBase._a = _instParseCtxt.a;
- } else {
- _instParseCtxt.inst->_opBase._a = findAnimation(_tokens[1]);
- }
-
- _instParseCtxt.inst->_opA = getLValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
- _instParseCtxt.inst->_opB = getLValue(_instParseCtxt.inst, _tokens[3], _instParseCtxt.locals, _instParseCtxt.a);
- if (!scumm_stricmp(_tokens[4], "masked")) {
- _instParseCtxt.inst->_flags |= kInstMaskedPut;
- }
-}
-
-
-DECLARE_INSTRUCTION_PARSER(call) {
- int index = _callableNames->lookup(_tokens[1]);
- if (index == Table::notFound)
- error("unknown callable '%s'", _tokens[1]);
- _instParseCtxt.inst->_opBase._index = index - 1;
-}
-
-
-DECLARE_INSTRUCTION_PARSER(sound) {
- _instParseCtxt.inst->_opBase._z = findZone(_tokens[1]);
-}
-
-
-DECLARE_INSTRUCTION_PARSER(null) {
-
-}
-
-
-DECLARE_INSTRUCTION_PARSER(defLocal) {
- int16 val = atoi(_tokens[2]);
- int16 index;
-
- if (_tokens[3][0] != '\0') {
- index = addLocal(_tokens[0], _instParseCtxt.locals, val, atoi(_tokens[3]), atoi(_tokens[4]));
- } else {
- index = addLocal(_tokens[0], _instParseCtxt.locals, val);
- }
-
- _instParseCtxt.inst->_opA._local = &_instParseCtxt.locals[index];
- _instParseCtxt.inst->_opB._value = _instParseCtxt.locals[index]._value;
-
- _instParseCtxt.inst->_flags = kInstUsesLiteral | kInstUsesLocal;
- _instParseCtxt.inst->_index = INST_SET;
-}
-
-
-
-
-void Parallaction::parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals) {
-// printf("parseScriptLine()\n");
-
- if (_tokens[0][1] == '.') {
- _tokens[0][1] = '\0';
- a = findAnimation(&_tokens[0][2]);
- }
-
- if (_tokens[1][1] == '.') {
- _tokens[1][1] = '\0';
- a = findAnimation(&_tokens[1][2]);
- }
-
- int16 _si = _instructionNames->lookup(_tokens[0]);
- inst->_index = _si;
-
- _instParseCtxt.a = a;
- _instParseCtxt.inst = inst;
- _instParseCtxt.locals = locals;
-
- (this->*_instructionParsers[inst->_index])();
-
- return;
-}
-
-LValue Parallaction::getLValue(Instruction *inst, char *str, LocalVariable *locals, Animation *a) {
-
- LValue v;
-
- v._pvalue = 0; // should stop compiler from complaining
-
- if (isdigit(str[0]) || str[0] == '-') {
- inst->_flags |= kInstUsesLiteral;
- v._value = atoi(str);
- return v;
- }
-
- int index = findLocal(str, locals);
- if (index != -1) {
- v._local = &locals[index];
- return v;
- }
-
- if (str[1] == '.') {
- a = findAnimation(&str[2]);
- }
-
- if (str[0] == 'X') {
- v._pvalue = &a->_left;
- } else
- if (str[0] == 'Y') {
- v._pvalue = &a->_top;
- } else
- if (str[0] == 'Z') {
- v._pvalue = &a->_z;
- } else
- if (str[0] == 'F') {
- v._pvalue = &a->_frame;
- }
-
- return v;
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(on) {
- (*_instRunCtxt.inst)->_opBase._a->_flags |= kFlagsActive;
- (*_instRunCtxt.inst)->_opBase._a->_flags &= ~kFlagsRemove;
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(off) {
- (*_instRunCtxt.inst)->_opBase._a->_flags |= kFlagsRemove;
-// v1C = (*_instRunCtxt.inst)->_opBase;
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(loop) {
- if ((*_instRunCtxt.inst)->_flags & kInstUsesLiteral) {
- _instRunCtxt.a->_program->_loopCounter = (*_instRunCtxt.inst)->_opBase._loopCounter._value;
- } else {
- _instRunCtxt.a->_program->_loopCounter = *(*_instRunCtxt.inst)->_opBase._loopCounter._pvalue;
- }
- _instRunCtxt.a->_program->_loopStart = _instRunCtxt.inst;
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(endloop) {
- if (--_instRunCtxt.a->_program->_loopCounter > 0) {
- _instRunCtxt.inst = _instRunCtxt.a->_program->_loopStart;
- }
-}
-
-DECLARE_INSTRUCTION_OPCODE(inc) {
- int16 _si = 0;
- int16 _ax = 0, _bx = 0;
- if ((*_instRunCtxt.inst)->_flags & kInstUsesLiteral) {
- _si = (*_instRunCtxt.inst)->_opB._value;
- } else {
- _si = *(*_instRunCtxt.inst)->_opB._pvalue;
- }
- if ((*_instRunCtxt.inst)->_flags & kInstMod) { // mod
- _bx = (_si > 0 ? _si : -_si);
- if (_instRunCtxt.modCounter % _bx != 0) return;
-
- _si = (_si > 0 ? 1 : -1);
- }
- if ((*_instRunCtxt.inst)->_flags & kInstUsesLocal) { // local
- if ((*_instRunCtxt.inst)->_index == INST_INC) _ax = _si;
- else _ax = -_si;
-
- (*_instRunCtxt.inst)->_opA._local->_value += _ax;
- wrapLocalVar((*_instRunCtxt.inst)->_opA._local);
- return;
- }
-
- // built-in variable (x, y, z, f)
- if ((*_instRunCtxt.inst)->_index == INST_INC) _ax = _si;
- else _ax = -_si;
- *(*_instRunCtxt.inst)->_opA._pvalue += _ax;
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(set) {
- int16 _si;
- if ((*_instRunCtxt.inst)->_flags & kInstUsesLiteral) {
- _si = (*_instRunCtxt.inst)->_opB._value;
- } else {
- _si = *(*_instRunCtxt.inst)->_opB._pvalue;
- }
-
- if ((*_instRunCtxt.inst)->_flags & kInstUsesLocal) {
- (*_instRunCtxt.inst)->_opA._local->_value = _si;
- } else {
- *(*_instRunCtxt.inst)->_opA._pvalue = _si;
- }
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(put) {
- Graphics::Surface v18;
- v18.w = (*_instRunCtxt.inst)->_opBase._a->width();
- v18.h = (*_instRunCtxt.inst)->_opBase._a->height();
- v18.pixels = (*_instRunCtxt.inst)->_opBase._a->getFrameData((*_instRunCtxt.inst)->_opBase._a->_frame);
-
- if ((*_instRunCtxt.inst)->_flags & kInstMaskedPut) {
- uint16 _si = _gfx->queryMask((*_instRunCtxt.inst)->_opB._value);
- _gfx->blitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, _si, Gfx::kBitBack);
- _gfx->blitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, _si, Gfx::kBit2);
- } else {
- _gfx->flatBlitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, Gfx::kBitBack);
- _gfx->flatBlitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, Gfx::kBit2);
- }
-}
-
-DECLARE_INSTRUCTION_OPCODE(null) {
-
-}
-
-DECLARE_INSTRUCTION_OPCODE(invalid) {
- error("Can't execute invalid opcode %i", (*_instRunCtxt.inst)->_index);
-}
-
-DECLARE_INSTRUCTION_OPCODE(call) {
- callFunction((*_instRunCtxt.inst)->_opBase._index, 0);
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(wait) {
- if (_engineFlags & kEngineWalking)
- _instRunCtxt.suspend = true;
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(start) {
-// v1C = (*_instRunCtxt.inst)->_opBase;
- (*_instRunCtxt.inst)->_opBase._a->_flags |= (kFlagsActing | kFlagsActive);
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(sound) {
- _activeZone = (*_instRunCtxt.inst)->_opBase._z;
-}
-
-
-DECLARE_INSTRUCTION_OPCODE(move) {
- WalkNodeList *v4 = _char._builder.buildPath(*(*_instRunCtxt.inst)->_opA._pvalue, *(*_instRunCtxt.inst)->_opB._pvalue);
- addJob(&jobWalk, v4, kPriority19 );
- _engineFlags |= kEngineWalking;
-}
-
-DECLARE_INSTRUCTION_OPCODE(end) {
- if ((_instRunCtxt.a->_flags & kFlagsLooping) == 0) {
- _instRunCtxt.a->_flags &= ~kFlagsActing;
- runCommands(_instRunCtxt.a->_commands, _instRunCtxt.a);
- }
- _instRunCtxt.a->_program->_ip = _instRunCtxt.a->_program->_instructions.begin();
-
- _instRunCtxt.suspend = true;
-}
-
-
-
-void jobRunScripts(void *parm, Job *j) {
- debugC(3, kDebugJobs, "jobRunScripts");
-
- static uint16 modCounter = 0;
-
- for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
-
- Animation *a = *it;
-
- if (a->_flags & kFlagsCharacter) a->_z = a->_top + a->height();
-
- if ((a->_flags & kFlagsActing) == 0) continue;
- InstructionList::iterator inst = a->_program->_ip;
-
- while (((*inst)->_index != INST_SHOW) && (a->_flags & kFlagsActing)) {
-
- debugC(9, kDebugJobs, "Animation: %s, instruction: %s", a->_label._text, (*inst)->_index == INST_END ? "end" : _vm->_instructionNamesRes[(*inst)->_index - 1]);
-
- _vm->_instRunCtxt.inst = inst;
- _vm->_instRunCtxt.a = a;
- _vm->_instRunCtxt.modCounter = modCounter;
- _vm->_instRunCtxt.suspend = false;
-
- (_vm->*(_vm->_instructionOpcodes)[(*inst)->_index])();
-
- inst = _vm->_instRunCtxt.inst; // handles endloop correctly
-
- if (_vm->_instRunCtxt.suspend)
- goto label1;
-
- inst++;
- }
-
- a->_program->_ip = ++inst;
-
-label1:
- if (a->_flags & kFlagsCharacter)
- a->_z = a->_top + a->height();
- }
-
- _vm->sortAnimations();
- modCounter++;
-
- return;
-}
-
-void wrapLocalVar(LocalVariable *local) {
-// printf("wrapLocalVar(v: %i, min: %i, max: %i)\n", local->_value, local->_min, local->_max);
-
- if (local->_value >= local->_max)
- local->_value = local->_min;
- if (local->_value < local->_min)
- local->_value = local->_max - 1;
-
- return;
-}
-
-int compareAnimationZ(const AnimationPointer &a1, const AnimationPointer &a2) {
- if (a1->_z == a2->_z) return 0;
- return (a1->_z < a2->_z ? -1 : 1);
-}
-
-
-void Parallaction::sortAnimations() {
- _char._ani._z = _char._ani.height() + _char._ani._top;
- _animations.sort(compareAnimationZ);
- return;
-}
-
-Animation::Animation() {
- _cnv = NULL;
- _program = NULL;
- _scriptName = 0;
- _frame = 0;
- _z = 0;
-}
-
-Animation::~Animation() {
- if (_program)
- delete _program;
-
- if (_scriptName)
- free(_scriptName);
-
- if (_cnv)
- delete _cnv;
-}
-
-uint16 Animation::width() const {
- if (!_cnv) return 0;
- return _cnv->_width;
-}
-
-uint16 Animation::height() const {
- if (!_cnv) return 0;
- return _cnv->_height;
-}
-
-uint16 Animation::getFrameNum() const {
- if (!_cnv) return 0;
- return _cnv->_count;
-}
-
-byte* Animation::getFrameData(uint32 index) const {
- if (!_cnv) return NULL;
- return _cnv->getFramePtr(index);
-}
-
-
-Program::Program() {
- _loopCounter = 0;
- _locals = new LocalVariable[10];
-}
-
-Program::~Program() {
- delete[] _locals;
-}
-
-
-} // namespace Parallaction
diff --git a/engines/parallaction/commands.cpp b/engines/parallaction/commands.cpp
deleted file mode 100644
index 41deaf49a0..0000000000
--- a/engines/parallaction/commands.cpp
+++ /dev/null
@@ -1,421 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-
-#include "parallaction/parallaction.h"
-
-
-namespace Parallaction {
-
-#define CMD_SET 1
-#define CMD_CLEAR 2
-#define CMD_START 3
-#define CMD_SPEAK 4
-#define CMD_GET 5
-#define CMD_LOCATION 6
-#define CMD_OPEN 7
-#define CMD_CLOSE 8
-#define CMD_ON 9
-#define CMD_OFF 10
-#define CMD_CALL 11
-#define CMD_TOGGLE 12
-#define CMD_DROP 13
-#define CMD_QUIT 14
-#define CMD_MOVE 15
-#define CMD_STOP 16
-
-DECLARE_COMMAND_PARSER(flags) {
- createCommand(_lookup);
-
- if (_globalTable->lookup(_tokens[1]) == Table::notFound) {
- do {
- char _al = _localFlagNames->lookup(_tokens[_cmdParseCtxt.nextToken]);
- _cmdParseCtxt.nextToken++;
- _cmdParseCtxt.cmd->u._flags |= 1 << (_al - 1);
- } while (!scumm_stricmp(_tokens[_cmdParseCtxt.nextToken++], "|"));
- _cmdParseCtxt.nextToken--;
- } else {
- _cmdParseCtxt.cmd->u._flags |= kFlagsGlobal;
- do {
- char _al = _globalTable->lookup(_tokens[1]);
- _cmdParseCtxt.nextToken++;
- _cmdParseCtxt.cmd->u._flags |= 1 << (_al - 1);
- } while (!scumm_stricmp(_tokens[_cmdParseCtxt.nextToken++], "|"));
- _cmdParseCtxt.nextToken--;
- }
-
- parseCommandFlags();
- addCommand();
-}
-
-
-DECLARE_COMMAND_PARSER(animation) {
- createCommand(_lookup);
-
- _cmdParseCtxt.cmd->u._animation = findAnimation(_tokens[_cmdParseCtxt.nextToken]);
- _cmdParseCtxt.nextToken++;
- if (_cmdParseCtxt.cmd->u._animation == NULL) {
- strcpy(_forwardedAnimationNames[_numForwards], _tokens[_cmdParseCtxt.nextToken-1]);
- _forwardedCommands[_numForwards] = _cmdParseCtxt.cmd;
- _numForwards++;
- }
-
- parseCommandFlags();
- addCommand();
-}
-
-
-DECLARE_COMMAND_PARSER(zone) {
- createCommand(_lookup);
-
- _cmdParseCtxt.cmd->u._zone = findZone(_tokens[_cmdParseCtxt.nextToken]);
- _cmdParseCtxt.nextToken++;
-
- parseCommandFlags();
- addCommand();
-}
-
-
-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) {
- createCommand(_lookup);
-
- _cmdParseCtxt.cmd->u._object = _objectsNames->lookup(_tokens[_cmdParseCtxt.nextToken]);
- _cmdParseCtxt.nextToken++;
-
- parseCommandFlags();
- addCommand();
-}
-
-
-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(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) {
- error("Can't parse unknown command '%s'", _tokens[0]);
-}
-
-DECLARE_COMMAND_PARSER(endcommands) {
- popParserTables();
-}
-
-void Parallaction::parseCommandFlags() {
-
- int _si = _cmdParseCtxt.nextToken;
- Command *cmd = _cmdParseCtxt.cmd;
-
- 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++], "|"));
-
- }
-
- 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
-
-}
-
-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;
-
- pushParserTables(_commandParsers, _commandsNames);
-
-}
-
-DECLARE_COMMAND_OPCODE(invalid) {
- error("Can't execute invalid command '%i'", _cmdRunCtxt.cmd->_id);
-}
-
-DECLARE_COMMAND_OPCODE(set) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags |= _cmdRunCtxt.cmd->u._flags;
- } else {
- _localFlags[_currentLocationIndex] |= _cmdRunCtxt.cmd->u._flags;
- }
-}
-
-
-DECLARE_COMMAND_OPCODE(clear) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags &= ~_cmdRunCtxt.cmd->u._flags;
- } else {
- _localFlags[_currentLocationIndex] &= ~_cmdRunCtxt.cmd->u._flags;
- }
-}
-
-
-DECLARE_COMMAND_OPCODE(start) {
- _cmdRunCtxt.cmd->u._animation->_flags |= kFlagsActing;
-}
-
-
-DECLARE_COMMAND_OPCODE(speak) {
- _activeZone = _cmdRunCtxt.cmd->u._zone;
-}
-
-
-DECLARE_COMMAND_OPCODE(get) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
- if (!runZone(_cmdRunCtxt.cmd->u._zone)) {
- runCommands(_cmdRunCtxt.cmd->u._zone->_commands);
- }
-}
-
-
-DECLARE_COMMAND_OPCODE(location) {
- strcpy(_location._name, _cmdRunCtxt.cmd->u._string);
- _engineFlags |= kEngineChangeLocation;
-}
-
-
-DECLARE_COMMAND_OPCODE(open) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsClosed;
- if (_cmdRunCtxt.cmd->u._zone->u.door->_cnv) {
- addJob(&jobToggleDoor, (void*)_cmdRunCtxt.cmd->u._zone, kPriority18 );
- }
-}
-
-
-DECLARE_COMMAND_OPCODE(close) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsClosed;
- if (_cmdRunCtxt.cmd->u._zone->u.door->_cnv) {
- addJob(&jobToggleDoor, (void*)_cmdRunCtxt.cmd->u._zone, kPriority18 );
- }
-}
-
-
-DECLARE_COMMAND_OPCODE(on) {
- // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing
- // the pointer to get structure members, thus leading to crashes in systems with memory
- // protection.
- // As a side note, the overwritten address is the 5th entry in the DOS interrupt table
- // (print screen handler): this suggests that a system would hang when the print screen
- // key is pressed after playing Nippon Safes, provided that this code path is taken.
- if (_cmdRunCtxt.cmd->u._zone != NULL) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsRemove;
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActive;
- if ((_cmdRunCtxt.cmd->u._zone->_type & 0xFFFF) == kZoneGet) {
- addJob(&jobDisplayDroppedItem, _cmdRunCtxt.cmd->u._zone, kPriority17 );
- }
- }
-}
-
-
-DECLARE_COMMAND_OPCODE(off) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsRemove;
-}
-
-
-DECLARE_COMMAND_OPCODE(call) {
- callFunction(_cmdRunCtxt.cmd->u._callable, _cmdRunCtxt.z);
-}
-
-
-DECLARE_COMMAND_OPCODE(toggle) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags ^= _cmdRunCtxt.cmd->u._flags;
- } else {
- _localFlags[_currentLocationIndex] ^= _cmdRunCtxt.cmd->u._flags;
- }
-}
-
-
-DECLARE_COMMAND_OPCODE(drop){
- dropItem( _cmdRunCtxt.cmd->u._object );
-}
-
-
-DECLARE_COMMAND_OPCODE(quit) {
- _engineFlags |= kEngineQuit;
-}
-
-
-DECLARE_COMMAND_OPCODE(move) {
- if ((_char._ani._flags & kFlagsRemove) || (_char._ani._flags & kFlagsActive) == 0) {
- return;
- }
-
- WalkNodeList *vC = _char._builder.buildPath(_cmdRunCtxt.cmd->u._move._x, _cmdRunCtxt.cmd->u._move._y);
-
- addJob(&jobWalk, vC, kPriority19 );
- _engineFlags |= kEngineWalking;
-}
-
-
-DECLARE_COMMAND_OPCODE(stop) {
- _cmdRunCtxt.cmd->u._animation->_flags &= ~kFlagsActing;
-}
-
-
-
-
-void Parallaction::runCommands(CommandList& list, Zone *z) {
- debugC(1, kDebugLocation, "runCommands");
-
- CommandList::iterator it = list.begin();
- for ( ; it != list.end(); it++) {
-
- Command *cmd = *it;
- uint32 v8 = _localFlags[_currentLocationIndex];
-
- if (_engineFlags & kEngineQuit)
- break;
-
- if (cmd->_flagsOn & kFlagsGlobal) {
- v8 = _commandFlags | kFlagsGlobal;
- }
-
- if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue;
- if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue;
-
- debugC(1, kDebugLocation, "runCommands: %s (on: %x, off: %x)", _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff);
-
- _cmdRunCtxt.z = z;
- _cmdRunCtxt.cmd = cmd;
-
- (this->*_commandOpcodes[cmd->_id])();
- }
-
- debugC(1, kDebugLocation, "runCommands completed");
-
- return;
-
-}
-
-Command::Command() {
- _id = 0;
- _flagsOn = 0;
- _flagsOff = 0;
-}
-
-Command::~Command() {
-
-}
-
-} // namespace Parallaction
-
-
-
diff --git a/engines/parallaction/commands.h b/engines/parallaction/commands.h
deleted file mode 100644
index 6db194d8c7..0000000000
--- a/engines/parallaction/commands.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef PARALLACTION_COMMANDS_H
-#define PARALLACTION_COMMANDS_H
-
-
-#include "common/stdafx.h"
-#include "common/scummsys.h"
-
-#include "parallaction/defs.h"
-
-namespace Parallaction {
-
-enum CommandFlags {
- kFlagsVisited = 1,
- kFlagsExit = 0x10000000,
- kFlagsEnter = 0x20000000,
- kFlagsGlobal = 0x40000000
-};
-
-struct Zone;
-struct Animation;
-
-
-// TODO: turn this into a struct
-struct CommandData {
- uint32 _flags;
- Animation * _animation;
- Zone* _zone;
- char* _string;
- uint16 _callable;
- uint16 _object;
- struct {
- int16 _x;
- int16 _y;
- } _move;
-
- CommandData() {
- _flags = 0;
- _animation = 0;
- _zone = 0;
- _string = 0;
- _callable = 0;
- _object = 0;
- _move._x = 0;
- _move._y = 0;
- }
-
- ~CommandData() {
- if (_string)
- free(_string);
- }
-};
-
-struct Command {
- uint16 _id;
- CommandData u;
- uint32 _flagsOn;
- uint32 _flagsOff;
-
- Command();
- ~Command();
-};
-
-typedef ManagedList<Command*> CommandList;
-
-} // namespace Parallaction
-
-#endif
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index 93f2054c9e..33d109842d 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -56,132 +56,6 @@ int16 _answerBalloonH[10] = { 0 };
-Dialogue *Parallaction::parseDialogue(Script &script) {
-// printf("parseDialogue()\n");
- uint16 numQuestions = 0;
-
- Dialogue *dialogue = new Dialogue;
-
- Table forwards(20);
-
- fillBuffers(script, true);
-
- while (scumm_stricmp(_tokens[0], "enddialogue")) {
- if (scumm_stricmp(_tokens[0], "Question")) continue;
-
- Question *question = new Question;
- dialogue->_questions[numQuestions] = question;
-
- forwards.addData(_tokens[1]);
-
- question->_text = parseDialogueString(script);
-
- fillBuffers(script, true);
- question->_mood = atoi(_tokens[0]);
-
- uint16 numAnswers = 0;
-
- fillBuffers(script, true);
- while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers
-
- Answer *answer = new Answer;
- question->_answers[numAnswers] = answer;
-
- if (_tokens[1][0]) {
-
- Table* flagNames;
- uint16 token;
-
- if (!scumm_stricmp(_tokens[1], "global")) {
- token = 2;
- flagNames = _globalTable;
- answer->_yesFlags |= kFlagsGlobal;
- } else {
- token = 1;
- flagNames = _localFlagNames;
- }
-
- do {
-
- if (!scumm_strnicmp(_tokens[token], "no", 2)) {
- byte _al = flagNames->lookup(_tokens[token]+2);
- answer->_noFlags |= 1 << (_al - 1);
- } else {
- byte _al = flagNames->lookup(_tokens[token]);
- answer->_yesFlags |= 1 << (_al - 1);
- }
-
- token++;
-
- } while (!scumm_stricmp(_tokens[token++], "|"));
-
- }
-
- answer->_text = parseDialogueString(script);
-
- fillBuffers(script, true);
- answer->_mood = atoi(_tokens[0]);
- answer->_following._name = parseDialogueString(script);
-
- fillBuffers(script, true);
- if (!scumm_stricmp(_tokens[0], "commands")) {
- parseCommands(script, answer->_commands);
- fillBuffers(script, true);
- }
-
- numAnswers++;
- }
-
- fillBuffers(script, true);
- numQuestions++;
-
- }
-
- // link questions
- byte v50[20];
- memset(v50, 0, 20);
-
- for (uint16 i = 0; i < numQuestions; i++) {
- Question *question = dialogue->_questions[i];
-
- for (uint16 j = 0; j < NUM_ANSWERS; j++) {
- Answer *answer = question->_answers[j];
- if (answer == 0) continue;
-
- int16 index = forwards.lookup(answer->_following._name);
- free(answer->_following._name);
-
- if (index == Table::notFound)
- answer->_following._question = 0;
- else
- answer->_following._question = dialogue->_questions[index - 1];
-
-
- }
- }
-
- return dialogue;
-}
-
-
-char *Parallaction::parseDialogueString(Script &script) {
-
- char vC8[200];
- char *vD0 = NULL;
- do {
-
- vD0 = script.readLine(vC8, 200);
- if (vD0 == 0) return NULL;
-
- vD0 = Common::ltrim(vD0);
-
- } while (strlen(vD0) == 0);
-
- vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA'
- // this is critical for Gfx::displayWrappedString to work properly
- return strdup(vD0);
-}
-
class DialogueManager {
Parallaction *_vm;
@@ -502,34 +376,5 @@ void Parallaction::runDialogue(SpeakData *data) {
return;
}
-Answer::Answer() {
- _text = NULL;
- _mood = 0;
- _following._question = NULL;
- _noFlags = 0;
- _yesFlags = 0;
-}
-
-Answer::~Answer() {
- if (_text)
- free(_text);
-}
-
-Question::Question() {
- _text = NULL;
- _mood = 0;
-
- for (uint32 i = 0; i < NUM_ANSWERS; i++)
- _answers[i] = NULL;
-
-}
-
-Question::~Question() {
-
- for (uint32 i = 0; i < NUM_ANSWERS; i++)
- if (_answers[i]) delete _answers[i];
-
- free(_text);
-}
} // namespace Parallaction
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 9e301a66c3..4853a9fb1a 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -102,7 +102,15 @@ Script* DosDisk_br::loadLocation(const char *name) {
Script* DosDisk_br::loadScript(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadScript");
- return 0;
+
+ Common::File *stream = new Common::File;
+
+ char path[PATH_LEN];
+ sprintf(path, "%s/scripts/%s.scr", _partPath, name);
+ if (!stream->open(path))
+ errorFileNotFound(path);
+
+ return new Script(stream, true);
}
// there are no Head resources in Big Red Adventure
@@ -275,7 +283,7 @@ Table* DosDisk_br::loadTable(const char* name) {
stream.close();
- return 0;
+ return t;
}
Common::SeekableReadStream* DosDisk_br::loadMusic(const char* name) {
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
new file mode 100644
index 0000000000..b3f90cc09b
--- /dev/null
+++ b/engines/parallaction/exec_ns.cpp
@@ -0,0 +1,857 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "parallaction/parallaction.h"
+#include "parallaction/sound.h"
+
+
+namespace Parallaction {
+
+#define INST_ON 1
+#define INST_OFF 2
+#define INST_X 3
+#define INST_Y 4
+#define INST_Z 5
+#define INST_F 6
+#define INST_LOOP 7
+#define INST_ENDLOOP 8
+#define INST_SHOW 9
+#define INST_INC 10
+#define INST_DEC 11
+#define INST_SET 12
+#define INST_PUT 13
+#define INST_CALL 14
+#define INST_WAIT 15
+#define INST_START 16
+#define INST_SOUND 17
+#define INST_MOVE 18
+#define INST_END 19
+
+
+typedef OpcodeImpl<Parallaction_ns> OpcodeV1;
+#define COMMAND_OPCODE(op) OpcodeV1(this, &Parallaction_ns::cmdOp_##op)
+#define DECLARE_COMMAND_OPCODE(op) void Parallaction_ns::cmdOp_##op()
+
+#define INSTRUCTION_OPCODE(op) OpcodeV1(this, &Parallaction_ns::instOp_##op)
+#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_ns::instOp_##op()
+
+
+
+
+DECLARE_INSTRUCTION_OPCODE(on) {
+ (*_instRunCtxt.inst)->_opBase._a->_flags |= kFlagsActive;
+ (*_instRunCtxt.inst)->_opBase._a->_flags &= ~kFlagsRemove;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(off) {
+ (*_instRunCtxt.inst)->_opBase._a->_flags |= kFlagsRemove;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(loop) {
+ if ((*_instRunCtxt.inst)->_flags & kInstUsesLiteral) {
+ _instRunCtxt.a->_program->_loopCounter = (*_instRunCtxt.inst)->_opBase._loopCounter._value;
+ } else {
+ _instRunCtxt.a->_program->_loopCounter = *(*_instRunCtxt.inst)->_opBase._loopCounter._pvalue;
+ }
+ _instRunCtxt.a->_program->_loopStart = _instRunCtxt.inst;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(endloop) {
+ if (--_instRunCtxt.a->_program->_loopCounter > 0) {
+ _instRunCtxt.inst = _instRunCtxt.a->_program->_loopStart;
+ }
+}
+
+DECLARE_INSTRUCTION_OPCODE(inc) {
+ int16 _si = 0;
+ int16 _ax = 0, _bx = 0;
+ if ((*_instRunCtxt.inst)->_flags & kInstUsesLiteral) {
+ _si = (*_instRunCtxt.inst)->_opB._value;
+ } else {
+ _si = *(*_instRunCtxt.inst)->_opB._pvalue;
+ }
+ if ((*_instRunCtxt.inst)->_flags & kInstMod) { // mod
+ _bx = (_si > 0 ? _si : -_si);
+ if (_instRunCtxt.modCounter % _bx != 0) return;
+
+ _si = (_si > 0 ? 1 : -1);
+ }
+ if ((*_instRunCtxt.inst)->_flags & kInstUsesLocal) { // local
+ if ((*_instRunCtxt.inst)->_index == INST_INC) _ax = _si;
+ else _ax = -_si;
+
+ (*_instRunCtxt.inst)->_opA._local->_value += _ax;
+ wrapLocalVar((*_instRunCtxt.inst)->_opA._local);
+ return;
+ }
+
+ // built-in variable (x, y, z, f)
+ if ((*_instRunCtxt.inst)->_index == INST_INC) _ax = _si;
+ else _ax = -_si;
+ *(*_instRunCtxt.inst)->_opA._pvalue += _ax;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(set) {
+ int16 _si;
+ if ((*_instRunCtxt.inst)->_flags & kInstUsesLiteral) {
+ _si = (*_instRunCtxt.inst)->_opB._value;
+ } else {
+ _si = *(*_instRunCtxt.inst)->_opB._pvalue;
+ }
+
+ if ((*_instRunCtxt.inst)->_flags & kInstUsesLocal) {
+ (*_instRunCtxt.inst)->_opA._local->_value = _si;
+ } else {
+ *(*_instRunCtxt.inst)->_opA._pvalue = _si;
+ }
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(put) {
+ Graphics::Surface v18;
+ v18.w = (*_instRunCtxt.inst)->_opBase._a->width();
+ v18.h = (*_instRunCtxt.inst)->_opBase._a->height();
+ v18.pixels = (*_instRunCtxt.inst)->_opBase._a->getFrameData((*_instRunCtxt.inst)->_opBase._a->_frame);
+
+ if ((*_instRunCtxt.inst)->_flags & kInstMaskedPut) {
+ uint16 _si = _gfx->queryMask((*_instRunCtxt.inst)->_opB._value);
+ _gfx->blitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, _si, Gfx::kBitBack);
+ _gfx->blitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, _si, Gfx::kBit2);
+ } else {
+ _gfx->flatBlitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, Gfx::kBitBack);
+ _gfx->flatBlitCnv(&v18, (*_instRunCtxt.inst)->_opA._value, (*_instRunCtxt.inst)->_opB._value, Gfx::kBit2);
+ }
+}
+
+DECLARE_INSTRUCTION_OPCODE(null) {
+
+}
+
+DECLARE_INSTRUCTION_OPCODE(invalid) {
+ error("Can't execute invalid opcode %i", (*_instRunCtxt.inst)->_index);
+}
+
+DECLARE_INSTRUCTION_OPCODE(call) {
+ callFunction((*_instRunCtxt.inst)->_opBase._index, 0);
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(wait) {
+ if (_engineFlags & kEngineWalking)
+ _instRunCtxt.suspend = true;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(start) {
+ (*_instRunCtxt.inst)->_opBase._a->_flags |= (kFlagsActing | kFlagsActive);
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(sound) {
+ _activeZone = (*_instRunCtxt.inst)->_opBase._z;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(move) {
+ WalkNodeList *v4 = _char._builder.buildPath(*(*_instRunCtxt.inst)->_opA._pvalue, *(*_instRunCtxt.inst)->_opB._pvalue);
+ addJob(&jobWalk, v4, kPriority19 );
+ _engineFlags |= kEngineWalking;
+}
+
+DECLARE_INSTRUCTION_OPCODE(end) {
+ if ((_instRunCtxt.a->_flags & kFlagsLooping) == 0) {
+ _instRunCtxt.a->_flags &= ~kFlagsActing;
+ runCommands(_instRunCtxt.a->_commands, _instRunCtxt.a);
+ }
+ _instRunCtxt.a->_program->_ip = _instRunCtxt.a->_program->_instructions.begin();
+
+ _instRunCtxt.suspend = true;
+}
+
+
+
+void Parallaction_ns::wrapLocalVar(LocalVariable *local) {
+
+ if (local->_value >= local->_max)
+ local->_value = local->_min;
+ if (local->_value < local->_min)
+ local->_value = local->_max - 1;
+
+ return;
+}
+
+
+DECLARE_COMMAND_OPCODE(invalid) {
+ error("Can't execute invalid command '%i'", _cmdRunCtxt.cmd->_id);
+}
+
+DECLARE_COMMAND_OPCODE(set) {
+ if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
+ _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags |= _cmdRunCtxt.cmd->u._flags;
+ } else {
+ _localFlags[_currentLocationIndex] |= _cmdRunCtxt.cmd->u._flags;
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(clear) {
+ if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
+ _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags &= ~_cmdRunCtxt.cmd->u._flags;
+ } else {
+ _localFlags[_currentLocationIndex] &= ~_cmdRunCtxt.cmd->u._flags;
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(start) {
+ _cmdRunCtxt.cmd->u._animation->_flags |= kFlagsActing;
+}
+
+
+DECLARE_COMMAND_OPCODE(speak) {
+ _activeZone = _cmdRunCtxt.cmd->u._zone;
+}
+
+
+DECLARE_COMMAND_OPCODE(get) {
+ _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
+ if (!runZone(_cmdRunCtxt.cmd->u._zone)) {
+ runCommands(_cmdRunCtxt.cmd->u._zone->_commands);
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(location) {
+ strcpy(_location._name, _cmdRunCtxt.cmd->u._string);
+ _engineFlags |= kEngineChangeLocation;
+}
+
+
+DECLARE_COMMAND_OPCODE(open) {
+ _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsClosed;
+ if (_cmdRunCtxt.cmd->u._zone->u.door->_cnv) {
+ addJob(&jobToggleDoor, (void*)_cmdRunCtxt.cmd->u._zone, kPriority18 );
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(close) {
+ _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsClosed;
+ if (_cmdRunCtxt.cmd->u._zone->u.door->_cnv) {
+ addJob(&jobToggleDoor, (void*)_cmdRunCtxt.cmd->u._zone, kPriority18 );
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(on) {
+ // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing
+ // the pointer to get structure members, thus leading to crashes in systems with memory
+ // protection.
+ // As a side note, the overwritten address is the 5th entry in the DOS interrupt table
+ // (print screen handler): this suggests that a system would hang when the print screen
+ // key is pressed after playing Nippon Safes, provided that this code path is taken.
+ if (_cmdRunCtxt.cmd->u._zone != NULL) {
+ _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsRemove;
+ _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActive;
+ if ((_cmdRunCtxt.cmd->u._zone->_type & 0xFFFF) == kZoneGet) {
+ addJob(&jobDisplayDroppedItem, _cmdRunCtxt.cmd->u._zone, kPriority17 );
+ }
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(off) {
+ _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsRemove;
+}
+
+
+DECLARE_COMMAND_OPCODE(call) {
+ callFunction(_cmdRunCtxt.cmd->u._callable, _cmdRunCtxt.z);
+}
+
+
+DECLARE_COMMAND_OPCODE(toggle) {
+ if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
+ _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags ^= _cmdRunCtxt.cmd->u._flags;
+ } else {
+ _localFlags[_currentLocationIndex] ^= _cmdRunCtxt.cmd->u._flags;
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(drop){
+ dropItem( _cmdRunCtxt.cmd->u._object );
+}
+
+
+DECLARE_COMMAND_OPCODE(quit) {
+ _engineFlags |= kEngineQuit;
+}
+
+
+DECLARE_COMMAND_OPCODE(move) {
+ if ((_char._ani._flags & kFlagsRemove) || (_char._ani._flags & kFlagsActive) == 0) {
+ return;
+ }
+
+ WalkNodeList *vC = _char._builder.buildPath(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y);
+
+ addJob(&jobWalk, vC, kPriority19 );
+ _engineFlags |= kEngineWalking;
+}
+
+
+DECLARE_COMMAND_OPCODE(stop) {
+ _cmdRunCtxt.cmd->u._animation->_flags &= ~kFlagsActing;
+}
+
+
+void jobDisplayAnimations(void *parm, Job *j) {
+
+ Graphics::Surface v14;
+
+ uint16 _si = 0;
+
+ for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
+
+ Animation *v18 = *it;
+
+ if ((v18->_flags & kFlagsActive) && ((v18->_flags & kFlagsRemove) == 0)) {
+ v14.w = v18->width();
+ v14.h = v18->height();
+
+ int16 frame = CLIP((int)v18->_frame, 0, v18->getFrameNum()-1);
+
+ v14.pixels = v18->getFrameData(frame);
+
+ if (v18->_flags & kFlagsNoMasked)
+ _si = 3;
+ else
+ _si = _vm->_gfx->queryMask(v18->_top + v18->height());
+
+ debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, f:%i/%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14.w, v14.h,
+ frame, v18->getFrameNum(), v14.pixels);
+ _vm->_gfx->blitCnv(&v14, v18->_left, v18->_top, _si, Gfx::kBitBack);
+
+ }
+
+ if (((v18->_flags & kFlagsActive) == 0) && (v18->_flags & kFlagsRemove)) {
+ v18->_flags &= ~kFlagsRemove;
+ v18->_oldPos.x = -1000;
+ }
+
+ if ((v18->_flags & kFlagsActive) && (v18->_flags & kFlagsRemove)) {
+ v18->_flags &= ~kFlagsActive;
+ v18->_flags |= kFlagsRemove;
+ }
+
+ }
+
+// printf("done\n");
+
+ return;
+}
+
+
+void jobEraseAnimations(void *arg_0, Job *j) {
+ debugC(3, kDebugJobs, "jobEraseAnimations");
+
+ for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
+
+ Animation *a = *it;
+
+ if (((a->_flags & kFlagsActive) == 0) && ((a->_flags & kFlagsRemove) == 0)) continue;
+
+ Common::Rect r(a->width(), a->height());
+ r.moveTo(a->_oldPos);
+ _vm->_gfx->restoreBackground(r);
+
+ if (arg_0) {
+ a->_oldPos.x = a->_left;
+ a->_oldPos.y = a->_top;
+ }
+
+ }
+
+ return;
+}
+
+
+void jobRunScripts(void *parm, Job *j) {
+ debugC(3, kDebugJobs, "jobRunScripts");
+
+ static uint16 modCounter = 0;
+
+ for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
+
+ Animation *a = *it;
+
+ if (a->_flags & kFlagsCharacter)
+ a->_z = a->_top + a->height();
+
+ if ((a->_flags & kFlagsActing) == 0)
+ continue;
+
+ InstructionList::iterator inst = a->_program->_ip;
+ while (((*inst)->_index != INST_SHOW) && (a->_flags & kFlagsActing)) {
+
+ debugC(9, kDebugJobs, "Animation: %s, instruction: %s", a->_label._text, (*inst)->_index == INST_END ? "end" : _vm->_instructionNamesRes[(*inst)->_index - 1]);
+
+ _vm->_instRunCtxt.inst = inst;
+ _vm->_instRunCtxt.a = a;
+ _vm->_instRunCtxt.modCounter = modCounter;
+ _vm->_instRunCtxt.suspend = false;
+
+ (*_vm->_instructionOpcodes[(*inst)->_index])();
+
+ inst = _vm->_instRunCtxt.inst; // handles endloop correctly
+
+ if (_vm->_instRunCtxt.suspend)
+ goto label1;
+
+ inst++;
+ }
+
+ a->_program->_ip = ++inst;
+
+label1:
+ if (a->_flags & kFlagsCharacter)
+ a->_z = a->_top + a->height();
+ }
+
+ _vm->sortAnimations();
+ modCounter++;
+
+ return;
+}
+
+
+void Parallaction::runCommands(CommandList& list, Zone *z) {
+ debugC(1, kDebugLocation, "runCommands");
+
+ CommandList::iterator it = list.begin();
+ for ( ; it != list.end(); it++) {
+
+ Command *cmd = *it;
+ uint32 v8 = _localFlags[_currentLocationIndex];
+
+ if (_engineFlags & kEngineQuit)
+ break;
+
+ if (cmd->_flagsOn & kFlagsGlobal) {
+ v8 = _commandFlags | kFlagsGlobal;
+ }
+
+ if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue;
+ if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue;
+
+ debugC(1, kDebugLocation, "runCommands[%i]: %s (on: %x, off: %x)", cmd->_id, _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff);
+
+ _cmdRunCtxt.z = z;
+ _cmdRunCtxt.cmd = cmd;
+
+ (*_commandOpcodes[cmd->_id])();
+ }
+
+ debugC(1, kDebugLocation, "runCommands completed");
+
+ return;
+
+}
+
+
+
+
+// displays character head commenting an examined object
+//
+// works on the frontbuffer
+//
+void Parallaction::displayCharacterComment(ExamineData *data) {
+ if (data->_description == NULL) return;
+
+ // NOTE: saving visible screen before displaying comment allows
+ // to restore the exact situation after the comment is deleted.
+ // This means animations are restored in the exact position as
+ // they were, thus avoiding clipping effect as signalled in
+ // BUG item #1762614.
+ _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
+
+ _gfx->setFont(_dialogueFont);
+ _gfx->flatBlitCnv(_char._talk, 0, 190, 80, Gfx::kBitFront);
+
+ int16 v26, v28;
+ _gfx->getStringExtent(data->_description, 130, &v28, &v26);
+ Common::Rect r(v28, v26);
+ r.moveTo(140, 10);
+ _gfx->drawBalloon(r, 0);
+ _gfx->displayWrappedString(data->_description, 140, 10, 0, 130);
+
+ waitUntilLeftClick();
+
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->updateScreen();
+
+ return;
+}
+
+//
+// ZONE TYPE: EXAMINE
+//
+
+// display detail view of an item (and eventually comments)
+//
+// works on the frontbuffer
+//
+
+void Parallaction::displayItemComment(ExamineData *data) {
+
+ if (data->_description == NULL) return;
+
+ _gfx->setHalfbriteMode(true);
+
+ char v68[PATH_LEN];
+ strcpy(v68, data->_filename);
+ data->_cnv = _disk->loadStatic(v68);
+ _gfx->flatBlitCnv(data->_cnv, 140, (_screenHeight - data->_cnv->h)/2, Gfx::kBitFront);
+ delete data->_cnv;
+
+ int16 v6A = 0, v6C = 0;
+
+ _gfx->setFont(_dialogueFont);
+ _gfx->getStringExtent(data->_description, 130, &v6C, &v6A);
+ Common::Rect r(v6C, v6A);
+ r.moveTo(0, 90);
+ _gfx->drawBalloon(r, 0);
+ _gfx->flatBlitCnv(_char._head, 100, 152, Gfx::kBitFront);
+ _gfx->displayWrappedString(data->_description, 0, 90, 0, 130);
+
+ jobEraseAnimations((void*)1, NULL);
+ _gfx->updateScreen();
+
+ waitUntilLeftClick();
+
+ _gfx->setHalfbriteMode(false);
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->updateScreen();
+
+ return;
+}
+
+
+
+uint16 Parallaction::runZone(Zone *z) {
+ debugC(3, kDebugLocation, "runZone (%s)", z->_label._text);
+
+ uint16 subtype = z->_type & 0xFFFF;
+
+ debugC(3, kDebugLocation, "type = %x, object = %x", subtype, (z->_type & 0xFFFF0000) >> 16);
+ switch(subtype) {
+
+ case kZoneExamine:
+ if (z->u.examine->_filename) {
+ displayItemComment(z->u.examine);
+ } else {
+ displayCharacterComment(z->u.examine);
+ }
+ break;
+
+ case kZoneGet:
+ if (z->_flags & kFlagsFixed) break;
+ if (pickupItem(z) != 0) {
+ return 1;
+ }
+ z->_flags |= kFlagsRemove;
+ break;
+
+ case kZoneDoor:
+ if (z->_flags & kFlagsLocked) break;
+ z->_flags ^= kFlagsClosed;
+ if (z->u.door->_cnv == NULL) break;
+ addJob(&jobToggleDoor, z, kPriority18 );
+ break;
+
+ case kZoneHear:
+ _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
+ break;
+
+ case kZoneSpeak:
+ runDialogue(z->u.speak);
+ break;
+
+ }
+
+ debugC(3, kDebugLocation, "runZone completed");
+
+ return 0;
+}
+
+//
+// ZONE TYPE: DOOR
+//
+void jobToggleDoor(void *parm, Job *j) {
+
+ static byte count = 0;
+
+ Zone *z = (Zone*)parm;
+
+ if (z->u.door->_cnv) {
+ Common::Rect r(z->_left, z->_top, z->_left+z->u.door->_cnv->_width, z->_top+z->u.door->_cnv->_height);
+
+ uint16 _ax = (z->_flags & kFlagsClosed ? 1 : 0);
+ _vm->_gfx->restoreDoorBackground(r, z->u.door->_cnv->getFramePtr(_ax), z->u.door->_background);
+
+ _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+ _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
+ _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBit2);
+ }
+
+ count++;
+ if (count == 2) {
+ j->_finished = 1;
+ count = 0;
+ }
+
+ return;
+}
+
+
+
+//
+// ZONE TYPE: GET
+//
+
+int16 Parallaction::pickupItem(Zone *z) {
+ int r = addInventoryItem(z->u.get->_icon);
+ if (r == 0)
+ addJob(&jobRemovePickedItem, z, kPriority17 );
+
+ return r;
+}
+
+void jobRemovePickedItem(void *parm, Job *j) {
+
+ Zone *z = (Zone*)parm;
+
+ static uint16 count = 0;
+
+ if (z->u.get->_cnv) {
+ Common::Rect r(z->_left, z->_top, z->_left + z->u.get->_cnv->w, z->_top + z->u.get->_cnv->h);
+
+ _vm->_gfx->restoreGetBackground(r, z->u.get->_backup);
+ }
+
+ count++;
+ if (count == 2) {
+ count = 0;
+ j->_finished = 1;
+ }
+
+ return;
+}
+
+void jobDisplayDroppedItem(void *parm, Job *j) {
+// printf("jobDisplayDroppedItem...");
+
+ Zone *z = (Zone*)parm;
+
+ if (z->u.get->_cnv) {
+ if (j->_count == 0) {
+ _vm->_gfx->backupGetBackground(z->u.get, z->_left, z->_top);
+ }
+
+ _vm->_gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBitBack);
+ _vm->_gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBit2);
+ }
+
+ j->_count++;
+ if (j->_count == 2) {
+ j->_count = 0;
+ j->_finished = 1;
+ }
+
+// printf("done");
+
+ return;
+}
+
+
+
+
+Zone *Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
+// printf("hitZone(%i, %i, %i)", type, x, y);
+
+ uint16 _di = y;
+ uint16 _si = x;
+
+ for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) {
+// printf("Zone name: %s", z->_name);
+
+ Zone *z = *it;
+
+ if (z->_flags & kFlagsRemove) continue;
+
+ Common::Rect r;
+ z->getRect(r);
+ r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
+ r.bottom++;
+
+ r.grow(-1); // allows some tolerance for mouse click
+
+ if (!r.contains(_si, _di)) {
+
+ // out of Zone, so look for special values
+ if ((z->_left == -2) || (z->_left == -3)) {
+
+ // WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
+ // instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
+ // but we need to check it separately here. The same workaround is applied in freeZones.
+ if ((((z->_type & 0xFFFF) == kZoneMerge) && (((_si == z->u.merge->_obj1) && (_di == z->u.merge->_obj2)) || ((_si == z->u.merge->_obj2) && (_di == z->u.merge->_obj1)))) ||
+ (((z->_type & 0xFFFF) == kZoneGet) && ((_si == z->u.get->_icon) || (_di == z->u.get->_icon)))) {
+
+ // special Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return z;
+ if (z->_type == type)
+ return z;
+ if ((z->_type & 0xFFFF0000) == type)
+ return z;
+
+ }
+ }
+
+ if (z->_left != -1)
+ continue;
+ if (_si < _char._ani._left)
+ continue;
+ if (_si > (_char._ani._left + _char._ani.width()))
+ continue;
+ if (_di < _char._ani._top)
+ continue;
+ if (_di > (_char._ani._top + _char._ani.height()))
+ continue;
+
+ }
+
+ // normal Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return z;
+ if (z->_type == type)
+ return z;
+ if ((z->_type & 0xFFFF0000) == type)
+ return z;
+
+ }
+
+
+ int16 _a, _b, _c, _d, _e, _f;
+ for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++) {
+
+ Animation *a = *it;
+
+ _a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
+ _e = ((_si >= a->_left + a->width()) || (_si <= a->_left)) ? 0 : 1; // _e: horizontal range
+ _f = ((_di >= a->_top + a->height()) || (_di <= a->_top)) ? 0 : 1; // _f: vertical range
+
+ _b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
+ _c = (a->_type & 0xFFFF0000) ? 0 : 1; // _c: Animation is not an object
+ _d = ((a->_type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
+
+ if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) {
+
+ return a;
+
+ }
+
+ }
+
+ return NULL;
+}
+
+
+void Parallaction_ns::initOpcodes() {
+
+ static const OpcodeV1 op1[] = {
+ INSTRUCTION_OPCODE(invalid),
+ INSTRUCTION_OPCODE(on),
+ INSTRUCTION_OPCODE(off),
+ INSTRUCTION_OPCODE(set), // x
+ INSTRUCTION_OPCODE(set), // y
+ INSTRUCTION_OPCODE(set), // z
+ INSTRUCTION_OPCODE(set), // f
+ INSTRUCTION_OPCODE(loop),
+ INSTRUCTION_OPCODE(endloop),
+ INSTRUCTION_OPCODE(null),
+ INSTRUCTION_OPCODE(inc),
+ INSTRUCTION_OPCODE(inc), // dec
+ INSTRUCTION_OPCODE(set),
+ INSTRUCTION_OPCODE(put),
+ INSTRUCTION_OPCODE(call),
+ INSTRUCTION_OPCODE(wait),
+ INSTRUCTION_OPCODE(start),
+ INSTRUCTION_OPCODE(sound),
+ INSTRUCTION_OPCODE(move),
+ INSTRUCTION_OPCODE(end)
+ };
+
+ uint i;
+ for (i = 0; i < ARRAYSIZE(op1); i++)
+ _instructionOpcodes.push_back(&op1[i]);
+
+ static const OpcodeV1 op3[] = {
+ COMMAND_OPCODE(invalid),
+ COMMAND_OPCODE(set),
+ COMMAND_OPCODE(clear),
+ COMMAND_OPCODE(start),
+ COMMAND_OPCODE(speak),
+ COMMAND_OPCODE(get),
+ COMMAND_OPCODE(location),
+ COMMAND_OPCODE(open),
+ COMMAND_OPCODE(close),
+ COMMAND_OPCODE(on),
+ COMMAND_OPCODE(off),
+ COMMAND_OPCODE(call),
+ COMMAND_OPCODE(toggle),
+ COMMAND_OPCODE(drop),
+ COMMAND_OPCODE(quit),
+ COMMAND_OPCODE(move),
+ COMMAND_OPCODE(stop)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op3); i++)
+ _commandOpcodes.push_back(&op3[i]);
+
+}
+
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp
index d0973c27e7..afa00f81af 100644
--- a/engines/parallaction/font.cpp
+++ b/engines/parallaction/font.cpp
@@ -571,7 +571,7 @@ Font *AmigaDisk_ns::createFont(const char *name, Common::SeekableReadStream &str
}
Font *DosDisk_br::createFont(const char *name, Common::ReadStream &stream) {
- printf("DosDisk_br::createFont(%s)\n", name);
+// printf("DosDisk_br::createFont(%s)\n", name);
return new BraFont(stream);
}
diff --git a/engines/parallaction/inventory.cpp b/engines/parallaction/inventory.cpp
index c9e74b2074..2804578c84 100644
--- a/engines/parallaction/inventory.cpp
+++ b/engines/parallaction/inventory.cpp
@@ -157,7 +157,7 @@ void Parallaction::dropItem(uint16 v) {
bool found = false;
for (uint16 slot = 0; slot < INVENTORY_MAX_ITEMS - 1; slot++) {
- if (v + INVENTORY_FIRST_ITEM == _inventory[slot]._index) {
+ if (v == _inventory[slot]._index) {
found = true;
}
diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp
deleted file mode 100644
index 0bac727f88..0000000000
--- a/engines/parallaction/location.cpp
+++ /dev/null
@@ -1,567 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-
-#include "common/system.h"
-
-#include "parallaction/parallaction.h"
-#include "parallaction/sound.h"
-
-namespace Parallaction {
-
-
-DECLARE_LOCATION_PARSER(invalid) {
- error("unknown keyword '%s' in location '%s'", _tokens[0], _locParseCtxt.filename);
-}
-
-DECLARE_LOCATION_PARSER(endlocation) {
- _locParseCtxt.end = true;
-}
-
-
-DECLARE_LOCATION_PARSER(location) {
- // The parameter for location is 'location.mask'.
- // If mask is not present, then it is assumed
- // that path & mask are encoded in the background
- // bitmap, otherwise a separate .msk file exists.
-
- char *mask = strchr(_tokens[1], '.');
- if (mask) {
- mask[0] = '\0';
- mask++;
- }
-
- strcpy(_location._name, _tokens[1]);
- switchBackground(_location._name, mask);
-
- if (_tokens[2][0] != '\0') {
- _char._ani._left = atoi(_tokens[2]);
- _char._ani._top = atoi(_tokens[3]);
- }
-
- if (_tokens[4][0] != '\0') {
- _char._ani._frame = atoi(_tokens[4]);
- }
-}
-
-
-DECLARE_LOCATION_PARSER(disk) {
- _disk->selectArchive(_tokens[1]);
-}
-
-
-DECLARE_LOCATION_PARSER(nodes) {
- parseWalkNodes(*_locParseCtxt.script, _location._walkNodes);
-}
-
-
-DECLARE_LOCATION_PARSER(zone) {
- parseZone(*_locParseCtxt.script, _zones, _tokens[1]);
-}
-
-
-DECLARE_LOCATION_PARSER(animation) {
- parseAnimation(*_locParseCtxt.script, _animations, _tokens[1]);
-}
-
-
-DECLARE_LOCATION_PARSER(localflags) {
- int _si = 1; // _localFlagNames[0] = 'visited'
- while (_tokens[_si][0] != '\0') {
- _localFlagNames->addData(_tokens[_si]);
- _si++;
- }
-}
-
-
-DECLARE_LOCATION_PARSER(commands) {
- parseCommands(*_locParseCtxt.script, _location._commands);
-}
-
-
-DECLARE_LOCATION_PARSER(acommands) {
- parseCommands(*_locParseCtxt.script, _location._aCommands);
-}
-
-
-DECLARE_LOCATION_PARSER(flags) {
- if ((_localFlags[_currentLocationIndex] & kFlagsVisited) == 0) {
- // only for 1st visit
- _localFlags[_currentLocationIndex] = 0;
- int _si = 1;
-
- do {
- byte _al = _localFlagNames->lookup(_tokens[_si]);
- _localFlags[_currentLocationIndex] |= 1 << (_al - 1);
-
- _si++;
- if (scumm_stricmp(_tokens[_si], "|")) break;
- _si++;
- } while (true);
- }
-}
-
-
-DECLARE_LOCATION_PARSER(comment) {
- _location._comment = parseComment(*_locParseCtxt.script);
-}
-
-
-DECLARE_LOCATION_PARSER(endcomment) {
- _location._endComment = parseComment(*_locParseCtxt.script);
-}
-
-
-DECLARE_LOCATION_PARSER(sound) {
- if (getPlatform() == Common::kPlatformAmiga) {
- strcpy(_locationSound, _tokens[1]);
- _hasLocationSound = true;
- }
-}
-
-
-DECLARE_LOCATION_PARSER(music) {
- if (getPlatform() == Common::kPlatformAmiga)
- _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);
-
- 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;
-
- pushParserTables(_locationParsers, _locationStmt);
-
- do {
-
- fillBuffers(*script, true);
-
- parseStatement();
-
- } while (!_locParseCtxt.end);
-
- popParserTables();
-
- 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
- // and if-statement, so the code exactly matches the one
- // in Big Red Adventure.
- _currentLocationIndex = -1;
- uint16 _di = 0;
- while (_locationNames[_di][0] != '\0') {
- 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], name);
- _currentLocationIndex = _numLocations;
-
- _numLocations++;
- _locationNames[_numLocations][0] = '\0';
- _localFlags[_numLocations] = 0;
- } else {
- _localFlags[_currentLocationIndex] |= kFlagsVisited; // 'visited'
- }
-}
-
-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;
-}
-
-
-void Parallaction::freeLocation() {
- debugC(7, kDebugLocation, "freeLocation");
-
- _soundMan->stopSfx(0);
- _soundMan->stopSfx(1);
- _soundMan->stopSfx(2);
- _soundMan->stopSfx(3);
-
- if (_localFlagNames)
- delete _localFlagNames;
-
- // HACK: prevents leakage. A routine like this
- // should allocate memory at all, though.
- if ((_engineFlags & kEngineQuit) == 0) {
- _localFlagNames = new Table(120);
- _localFlagNames->addData("visited");
- }
-
- _location._walkNodes.clear();
-
- freeZones();
- freeAnimations();
-
- if (_location._comment) {
- free(_location._comment);
- }
- _location._comment = NULL;
-
- _location._commands.clear();
- _location._aCommands.clear();
-
- return;
-}
-
-
-
-void Parallaction::parseWalkNodes(Script& script, WalkNodeList &list) {
-
- fillBuffers(script, true);
- while (scumm_stricmp(_tokens[0], "ENDNODES")) {
-
- if (!scumm_stricmp(_tokens[0], "COORD")) {
-
- WalkNode *v4 = new WalkNode(
- atoi(_tokens[1]) - _char._ani.width()/2,
- atoi(_tokens[2]) - _char._ani.height()
- );
-
- list.push_front(v4);
- }
-
- fillBuffers(script, true);
- }
-
- return;
-
-}
-
-void Parallaction::freeBackground() {
-
- if (!_backgroundInfo)
- return;
-
- _backgroundInfo->bg.free();
- _backgroundInfo->mask.free();
- _backgroundInfo->path.free();
-
- _pathBuffer = 0;
-
-}
-
-void Parallaction::setBackground(const char* name, const char* mask, const char* path) {
-
- _disk->loadScenery(*_backgroundInfo, name, mask, path);
-
- _gfx->setPalette(_backgroundInfo->palette);
- _gfx->_palette.clone(_backgroundInfo->palette);
- _gfx->setBackground(&_backgroundInfo->bg);
-
- if (_backgroundInfo->mask.data)
- _gfx->setMask(&_backgroundInfo->mask);
-
- if (_backgroundInfo->path.data)
- _pathBuffer = &_backgroundInfo->path;
-
- return;
-}
-
-void Parallaction::showLocationComment(const char *text, bool end) {
-
- _gfx->setFont(_dialogueFont);
-
- int16 w, h;
- _gfx->getStringExtent(const_cast<char*>(text), 130, &w, &h);
-
- Common::Rect r(w + (end ? 5 : 10), h + 5);
- r.moveTo(5, 5);
-
- _gfx->floodFill(Gfx::kBitFront, r, 0);
- r.grow(-2);
- _gfx->floodFill(Gfx::kBitFront, r, 1);
- _gfx->displayWrappedString(const_cast<char*>(text), 3, 5, 0, 130);
-
- _gfx->updateScreen();
-
- return;
-}
-
-void Parallaction::switchBackground(const char* background, const char* mask) {
-// printf("switchBackground(%s)", name);
-
- Palette pal;
-
- uint16 v2 = 0;
- if (!scumm_stricmp(background, "final")) {
- _gfx->clearScreen(Gfx::kBitBack);
- for (uint16 _si = 0; _si <= 32; _si++) {
- pal.setEntry(_si, v2, v2, v2);
- v2 += 4;
- }
-
- g_system->delayMillis(20);
- _gfx->setPalette(pal);
- _gfx->updateScreen();
- }
-
- setBackground(background, mask, mask);
-
- return;
-}
-
-extern Zone *_hoverZone;
-extern Job *_jDrawLabel;
-extern Job *_jEraseLabel;
-
-void Parallaction::showSlide(const char *name) {
-
- BackgroundInfo info;
-
- _disk->loadSlide(info, name);
-
- // TODO: avoid using screen buffers for displaying slides. Using a generic buffer
- // allows for positioning of graphics as needed by Big Red Adventure.
- // The main problem lies with menu, which relies on multiple buffers, mainly because
- // it is crappy code.
- _gfx->setBackground(&info.bg);
- _gfx->setPalette(info.palette);
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
-
- info.bg.free();
- info.mask.free();
- info.path.free();
-
- return;
-}
-
-/*
- changeLocation handles transitions between locations, and is able to display slides
- between one and the other. The input parameter 'location' exists in some flavours:
-
- 1 - [S].slide.[L]{.[C]}
- 2 - [L]{.[C]}
-
- where:
-
- [S] is the slide to be shown
- [L] is the location to switch to (immediately in case 2, or right after slide [S] in case 1)
- [C] is the character to be selected, and is optional
-
- The routine tells one form from the other by searching for the '.slide.'
-
- NOTE: there exists one script in which [L] is not used in the case 1, but its use
- is commented out, and would definitely crash the current implementation.
-*/
-void Parallaction::changeLocation(char *location) {
- debugC(1, kDebugLocation, "changeLocation(%s)", location);
-
- _soundMan->playLocationMusic(location);
-
- // WORKAROUND: this if-statement has been added to avoid crashes caused by
- // execution of label jobs after a location switch. The other workaround in
- // Parallaction::runGame should have been rendered useless by this one.
- if (_jDrawLabel != NULL) {
- removeJob(_jDrawLabel);
- removeJob(_jEraseLabel);
- _jDrawLabel = NULL;
- _jEraseLabel = NULL;
- }
-
-
- _hoverZone = NULL;
- if (_engineFlags & kEngineBlockInput) {
- changeCursor( kCursorArrow );
- }
-
- _animations.remove(&_char._ani);
-
- freeLocation();
- char buf[100];
- strcpy(buf, location);
-
- Common::StringList list;
- char *tok = strtok(location, ".");
- while (tok) {
- list.push_back(tok);
- tok = strtok(NULL, ".");
- }
-
- if (list.size() < 1 || list.size() > 4)
- error("changeLocation: ill-formed location string '%s'", location);
-
- if (list.size() > 1) {
- if (list[1] == "slide") {
- showSlide(list[0].c_str());
- _gfx->setFont(_menuFont);
- _gfx->displayCenteredString(14, _slideText[0]); // displays text on screen
- _gfx->updateScreen();
- waitUntilLeftClick();
-
- list.remove_at(0); // removes slide name
- list.remove_at(0); // removes 'slide'
- }
-
- // list is now only [L].{[C]} (see above comment)
- if (list.size() == 2) {
- changeCharacter(list[1].c_str());
- strcpy(_characterName, list[1].c_str());
- }
- }
-
- _animations.push_front(&_char._ani);
-
- strcpy(_saveData1, list[0].c_str());
- parseLocation(list[0].c_str());
-
- _char._ani._oldPos.x = -1000;
- _char._ani._oldPos.y = -1000;
-
- _char._ani.field_50 = 0;
- if (_location._startPosition.x != -1000) {
- _char._ani._left = _location._startPosition.x;
- _char._ani._top = _location._startPosition.y;
- _char._ani._frame = _location._startFrame;
- _location._startPosition.y = -1000;
- _location._startPosition.x = -1000;
- }
-
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
- _gfx->setBlackPalette();
- _gfx->updateScreen();
-
- if (_location._commands.size() > 0) {
- runCommands(_location._commands);
- runJobs();
- _gfx->swapBuffers();
- runJobs();
- _gfx->swapBuffers();
- }
-
- if (_location._comment) {
- doLocationEnterTransition();
- }
-
- runJobs();
- _gfx->swapBuffers();
-
- _gfx->setPalette(_gfx->_palette);
- if (_location._aCommands.size() > 0) {
- runCommands(_location._aCommands);
- }
-
- if (_hasLocationSound)
- _soundMan->playSfx(_locationSound, 0, true);
-
- debugC(1, kDebugLocation, "changeLocation() done");
-
- return;
-
-}
-
-// displays transition before a new location
-//
-// clears screen (in white??)
-// shows location comment (if any)
-// waits for mouse click
-// fades towards game palette
-//
-void Parallaction::doLocationEnterTransition() {
- debugC(1, kDebugLocation, "doLocationEnterTransition");
-
- if (_localFlags[_currentLocationIndex] & kFlagsVisited) {
- debugC(3, kDebugLocation, "skipping location transition");
- return; // visited
- }
-
- Palette pal(_gfx->_palette);
- pal.makeGrayscale();
- _gfx->setPalette(pal);
-
- jobRunScripts(NULL, NULL);
- jobEraseAnimations(NULL, NULL);
- jobDisplayAnimations(NULL, NULL);
-
- _gfx->swapBuffers();
- _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
-
- showLocationComment(_location._comment, false);
- waitUntilLeftClick();
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront );
-
- // fades maximum intensity palette towards approximation of main palette
- for (uint16 _si = 0; _si<6; _si++) {
- pal.fadeTo(_gfx->_palette, 4);
- _gfx->setPalette(pal);
- waitTime( 1 );
- _gfx->updateScreen();
- }
-
- debugC(1, kDebugLocation, "doLocationEnterTransition completed");
-
- return;
-}
-
-} // namespace Parallaction
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index b7f60eeb32..61e293ed5b 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -1,29 +1,28 @@
MODULE := engines/parallaction
MODULE_OBJS := \
- animation.o \
callables_br.o \
callables_ns.o \
- commands.o \
debug.o \
detection.o \
dialogue.o \
disk_br.o \
disk_ns.o \
+ exec_ns.o \
font.o \
graphics.o \
inventory.o \
- location.o \
menu.o \
- parser.o \
+ objects.o \
parallaction.o \
parallaction_br.o \
parallaction_ns.o \
+ parser.o \
+ parser_ns.o \
saveload.o \
sound.o \
staticres.o \
- walk.o \
- zone.o
+ walk.o
# This module can be built as a plugin
ifdef BUILD_PLUGINS
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
new file mode 100644
index 0000000000..d4eba330bb
--- /dev/null
+++ b/engines/parallaction/objects.cpp
@@ -0,0 +1,215 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "parallaction/objects.h"
+
+namespace Parallaction {
+
+
+
+Command::Command() {
+ _id = 0;
+ _flagsOn = 0;
+ _flagsOff = 0;
+}
+
+Command::~Command() {
+
+}
+
+
+Animation::Animation() {
+ _cnv = NULL;
+ _program = NULL;
+ _scriptName = 0;
+ _frame = 0;
+ _z = 0;
+}
+
+Animation::~Animation() {
+ if (_program)
+ delete _program;
+
+ if (_scriptName)
+ free(_scriptName);
+
+ if (_cnv)
+ delete _cnv;
+}
+
+uint16 Animation::width() const {
+ if (!_cnv) return 0;
+ return _cnv->_width;
+}
+
+uint16 Animation::height() const {
+ if (!_cnv) return 0;
+ return _cnv->_height;
+}
+
+uint16 Animation::getFrameNum() const {
+ if (!_cnv) return 0;
+ return _cnv->_count;
+}
+
+byte* Animation::getFrameData(uint32 index) const {
+ if (!_cnv) return NULL;
+ return _cnv->getFramePtr(index);
+}
+
+
+Program::Program() {
+ _loopCounter = 0;
+ _locals = new LocalVariable[10];
+}
+
+Program::~Program() {
+ delete[] _locals;
+}
+
+
+Zone::Zone() {
+ _left = _top = _right = _bottom = 0;
+
+ _type = 0;
+ _flags = 0;
+}
+
+Zone::~Zone() {
+// printf("~Zone(%s)\n", _label._text);
+
+ _label._cnv.free();
+
+ switch (_type & 0xFFFF) {
+ case kZoneExamine:
+ free(u.examine->_filename);
+ free(u.examine->_description);
+ delete u.examine;
+ break;
+
+ case kZoneDoor:
+ free(u.door->_location);
+ free(u.door->_background);
+ if (u.door->_cnv)
+ delete u.door->_cnv;
+ delete u.door;
+ break;
+
+ case kZoneSpeak:
+ delete u.speak->_dialogue;
+ delete u.speak;
+ break;
+
+ case kZoneGet:
+ free(u.get->_backup);
+ if (u.get->_cnv) {
+ u.get->_cnv->free();
+ delete u.get->_cnv;
+ }
+ delete u.get;
+ break;
+
+ case kZoneHear:
+ delete u.hear;
+ break;
+
+ case kZoneMerge:
+ delete u.merge;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Zone::getRect(Common::Rect& r) const {
+ r.left = _left;
+ r.right = _right;
+ r.top = _top;
+ r.bottom = _bottom;
+}
+
+void Zone::translate(int16 x, int16 y) {
+ _left += x;
+ _right += x;
+ _top += y;
+ _bottom += y;
+}
+
+uint16 Zone::width() const {
+ return _right - _left;
+}
+
+uint16 Zone::height() const {
+ return _bottom - _top;
+}
+
+Label::Label() {
+ _text = NULL;
+}
+
+Label::~Label() {
+ _cnv.free();
+ if (_text)
+ free(_text);
+}
+
+
+Answer::Answer() {
+ _text = NULL;
+ _mood = 0;
+ _following._question = NULL;
+ _noFlags = 0;
+ _yesFlags = 0;
+}
+
+Answer::~Answer() {
+ if (_text)
+ free(_text);
+}
+
+Question::Question() {
+ _text = NULL;
+ _mood = 0;
+
+ for (uint32 i = 0; i < NUM_ANSWERS; i++)
+ _answers[i] = NULL;
+
+}
+
+Question::~Question() {
+
+ for (uint32 i = 0; i < NUM_ANSWERS; i++)
+ if (_answers[i]) delete _answers[i];
+
+ free(_text);
+}
+
+
+
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/zone.h b/engines/parallaction/objects.h
index 38b8730c4b..3f8635eb0d 100644
--- a/engines/parallaction/zone.h
+++ b/engines/parallaction/objects.h
@@ -30,12 +30,19 @@
#include "parallaction/defs.h"
-#include "parallaction/commands.h"
#include "parallaction/graphics.h"
namespace Parallaction {
+struct Zone;
+struct Animation;
+struct Command;
+struct Question;
+struct Answer;
+struct Instruction;
+struct Program;
+
enum ZoneTypes {
kZoneExamine = 1, // zone displays comment if activated
kZoneDoor = 2, // zone activated on click (after some walk if needed)
@@ -68,12 +75,67 @@ enum ZoneFlags {
};
+enum CommandFlags {
+ kFlagsVisited = 1,
+ kFlagsExit = 0x10000000,
+ kFlagsEnter = 0x20000000,
+ kFlagsGlobal = 0x40000000,
+
+ // BRA specific
+ kFlagsTestTrue = 2
+};
+
+struct CommandData {
+ uint32 _flags;
+ Animation * _animation;
+ Zone* _zone;
+ char* _string;
+ uint16 _callable;
+ uint16 _object;
+ Common::Point _move;
+
+ // BRA specific
+ Common::Point _startPos;
+ Common::Point _startPos2;
+ uint _lvalue;
+ int _rvalue;
+ int _zeta0;
+ int _zeta1;
+ int _zeta2;
+ int _characterId;
+ char* _string2;
+ int _musicCommand;
+ int _musicParm;
+
+
+ CommandData() {
+ memset(this, 0, sizeof(CommandData));
+ }
+
+ ~CommandData() {
+ if (_string)
+ free(_string);
+ if (_string2)
+ free(_string2);
+ }
+};
+
+struct Command {
+ uint16 _id;
+ CommandData u;
+ uint32 _flagsOn;
+ uint32 _flagsOff;
+
+ Command();
+ ~Command();
+};
+
+typedef ManagedList<Command*> CommandList;
+
+
#define NUM_QUESTIONS 20
#define NUM_ANSWERS 5
-struct Command;
-struct Question;
-
struct Answer {
char* _text;
uint16 _mood;
@@ -192,8 +254,8 @@ struct TypeData {
};
struct Label {
- char* _text;
- Graphics::Surface _cnv;
+ char* _text;
+ Graphics::Surface _cnv;
Label();
~Label();
@@ -237,12 +299,12 @@ struct LocalVariable {
}
};
-union LValue {
+union ScriptVar {
int16 _value;
int16* _pvalue;
LocalVariable* _local;
- LValue() {
+ ScriptVar() {
_local = NULL;
}
};
@@ -251,10 +313,18 @@ enum InstructionFlags {
kInstUsesLiteral = 1,
kInstUsesLocal = 2,
kInstMod = 4,
- kInstMaskedPut = 8
+ kInstMaskedPut = 8,
+
+ kInstUsesField = 0x10, // this value wasn't originally in NS, but it has been added for completeness
+
+ // BRA specific
+ kInstUnk20 = 0x20,
+ kInstUsesLLocal = 0x40,
+ kInstUsesLField = 0x80,
+ kInstRandom = 0x100
};
-struct Animation;
+typedef ManagedList<Instruction*> InstructionList;
struct Instruction {
uint32 _index;
@@ -263,20 +333,30 @@ struct Instruction {
Animation *_a;
Zone *_z;
uint32 _index;
- LValue _loopCounter;
+ ScriptVar _loopCounter;
} _opBase;
- LValue _opA;
- LValue _opB;
+ ScriptVar _opA;
+ ScriptVar _opB;
+
+ // BRA specific
+ byte _colors[3];
+ ScriptVar _opC;
+ char *_text;
+ char *_text2;
+ int _y;
+ InstructionList::iterator _endif;
Instruction() {
- _index = 0;
- _flags = 0;
- _opBase._a = NULL;
+ memset(this, 0, sizeof(Instruction));
}
-};
-//typedef Common::List<Instruction*> InstructionList;
-typedef ManagedList<Instruction*> InstructionList;
+ ~Instruction() {
+ if (_text)
+ free(_text);
+ if (_text2)
+ free(_text2);
+ }
+};
struct Program {
LocalVariable *_locals;
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index af0a34e409..dedcddb8c7 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -53,7 +53,6 @@ char _saveData1[30] = { '\0' };
uint16 _language = 0;
char _slideText[2][40];
uint32 _engineFlags = 0;
-Zone *_activeZone = NULL;
uint16 _score = 1;
@@ -128,11 +127,9 @@ Parallaction::~Parallaction() {
delete _globalTable;
delete _callableNames;
- delete _commandsNames;
- delete _instructionNames;
+
delete _zoneTypeNames;
delete _zoneFlagNames;
- delete _locationStmt;
_animations.remove(&_char._ani);
@@ -168,6 +165,7 @@ int Parallaction::init() {
_backgroundInfo = 0;
_pathBuffer = 0;
+ _activeZone = 0;
_screenSize = _screenWidth * _screenHeight;
@@ -178,8 +176,6 @@ int Parallaction::init() {
memset(_locationNames, 0, 120*32);
- initOpcodes();
-
initInventory(); // needs to be pushed into subclass
_animations.push_front(&_char._ani);
@@ -840,7 +836,7 @@ void Table::addData(const char* s) {
}
-int Table::lookup(const char* s) {
+uint16 Table::lookup(const char* s) {
for (uint16 i = 0; i < _used; i++) {
if (!scumm_stricmp(_data[i], s)) return i + 1;
@@ -849,14 +845,12 @@ int Table::lookup(const char* s) {
return notFound;
}
-void Parallaction::pushParserTables(const Opcode* opcodes, Table *statements) {
-
+void Parallaction::pushParserTables(OpcodeSet *opcodes, Table *statements) {
_opcodes.push(_currentOpcodes);
_statements.push(_currentStatements);
_currentOpcodes = opcodes;
_currentStatements = statements;
-
}
void Parallaction::popParserTables() {
@@ -870,161 +864,427 @@ void Parallaction::parseStatement() {
assert(_currentOpcodes != 0);
_lookup = _currentStatements->lookup(_tokens[0]);
- (this->*(_currentOpcodes[_lookup]))();
+ (*(*_currentOpcodes)[_lookup])();
+}
+
+
+
+
+Animation *Parallaction::findAnimation(const char *name) {
+
+ for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++)
+ if (!scumm_stricmp((*it)->_label._text, name)) return *it;
+
+ return NULL;
+}
+
+void Parallaction::freeAnimations() {
+ _animations.clear();
+ return;
+}
+
+int compareAnimationZ(const AnimationPointer &a1, const AnimationPointer &a2) {
+ if (a1->_z == a2->_z) return 0;
+ return (a1->_z < a2->_z ? -1 : 1);
+}
+
+void Parallaction::sortAnimations() {
+ _char._ani._z = _char._ani.height() + _char._ani._top;
+ _animations.sort(compareAnimationZ);
+ return;
+}
+
+
+void Parallaction::allocateLocationSlot(const char *name) {
+ // WORKAROUND: the original code erroneously incremented
+ // _currentLocationIndex, thus producing inconsistent
+ // savegames. This workaround modified the following loop
+ // and if-statement, so the code exactly matches the one
+ // in Big Red Adventure.
+ _currentLocationIndex = -1;
+ uint16 _di = 0;
+ while (_locationNames[_di][0] != '\0') {
+ 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], name);
+ _currentLocationIndex = _numLocations;
+
+ _numLocations++;
+ _locationNames[_numLocations][0] = '\0';
+ _localFlags[_numLocations] = 0;
+ } else {
+ _localFlags[_currentLocationIndex] |= kFlagsVisited; // 'visited'
+ }
+}
+
+
+
+void Parallaction::freeLocation() {
+ debugC(7, kDebugLocation, "freeLocation");
+
+ _soundMan->stopSfx(0);
+ _soundMan->stopSfx(1);
+ _soundMan->stopSfx(2);
+ _soundMan->stopSfx(3);
+
+ if (_localFlagNames)
+ delete _localFlagNames;
+
+ // HACK: prevents leakage. A routine like this
+ // should allocate memory at all, though.
+ if ((_engineFlags & kEngineQuit) == 0) {
+ _localFlagNames = new Table(120);
+ _localFlagNames->addData("visited");
+ }
+
+ _location._walkNodes.clear();
+
+ freeZones();
+ freeAnimations();
+
+ if (_location._comment) {
+ free(_location._comment);
+ }
+ _location._comment = NULL;
+
+ _location._commands.clear();
+ _location._aCommands.clear();
+
+ return;
+}
+
+
+
+
+void Parallaction::freeBackground() {
+
+ if (!_backgroundInfo)
+ return;
+
+ _backgroundInfo->bg.free();
+ _backgroundInfo->mask.free();
+ _backgroundInfo->path.free();
+
+ _pathBuffer = 0;
+
+}
+
+void Parallaction::setBackground(const char* name, const char* mask, const char* path) {
+
+ _disk->loadScenery(*_backgroundInfo, name, mask, path);
+
+ _gfx->setPalette(_backgroundInfo->palette);
+ _gfx->_palette.clone(_backgroundInfo->palette);
+ _gfx->setBackground(&_backgroundInfo->bg);
+
+ if (_backgroundInfo->mask.data)
+ _gfx->setMask(&_backgroundInfo->mask);
+
+ if (_backgroundInfo->path.data)
+ _pathBuffer = &_backgroundInfo->path;
+
+ return;
+}
+
+void Parallaction::showLocationComment(const char *text, bool end) {
+
+ _gfx->setFont(_dialogueFont);
+
+ int16 w, h;
+ _gfx->getStringExtent(const_cast<char*>(text), 130, &w, &h);
+
+ Common::Rect r(w + (end ? 5 : 10), h + 5);
+ r.moveTo(5, 5);
+
+ _gfx->floodFill(Gfx::kBitFront, r, 0);
+ r.grow(-2);
+ _gfx->floodFill(Gfx::kBitFront, r, 1);
+ _gfx->displayWrappedString(const_cast<char*>(text), 3, 5, 0, 130);
+
+ _gfx->updateScreen();
+
+ return;
+}
+
+void Parallaction::switchBackground(const char* background, const char* mask) {
+// printf("switchBackground(%s)", name);
+
+ Palette pal;
+
+ uint16 v2 = 0;
+ if (!scumm_stricmp(background, "final")) {
+ _gfx->clearScreen(Gfx::kBitBack);
+ for (uint16 _si = 0; _si <= 32; _si++) {
+ pal.setEntry(_si, v2, v2, v2);
+ v2 += 4;
+ }
+
+ g_system->delayMillis(20);
+ _gfx->setPalette(pal);
+ _gfx->updateScreen();
+ }
+
+ setBackground(background, mask, mask);
+
+ return;
+}
+
+extern Zone *_hoverZone;
+extern Job *_jDrawLabel;
+extern Job *_jEraseLabel;
+
+void Parallaction::showSlide(const char *name) {
+
+ BackgroundInfo info;
+
+ _disk->loadSlide(info, name);
+
+ // TODO: avoid using screen buffers for displaying slides. Using a generic buffer
+ // allows for positioning of graphics as needed by Big Red Adventure.
+ // The main problem lies with menu, which relies on multiple buffers, mainly because
+ // it is crappy code.
+ _gfx->setBackground(&info.bg);
+ _gfx->setPalette(info.palette);
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+
+ info.bg.free();
+ info.mask.free();
+ info.path.free();
+
+ return;
+}
+
+/*
+ changeLocation handles transitions between locations, and is able to display slides
+ between one and the other. The input parameter 'location' exists in some flavours:
+
+ 1 - [S].slide.[L]{.[C]}
+ 2 - [L]{.[C]}
+
+ where:
+
+ [S] is the slide to be shown
+ [L] is the location to switch to (immediately in case 2, or right after slide [S] in case 1)
+ [C] is the character to be selected, and is optional
+
+ The routine tells one form from the other by searching for the '.slide.'
+
+ NOTE: there exists one script in which [L] is not used in the case 1, but its use
+ is commented out, and would definitely crash the current implementation.
+*/
+void Parallaction::changeLocation(char *location) {
+ debugC(1, kDebugLocation, "changeLocation(%s)", location);
+
+ _soundMan->playLocationMusic(location);
+
+ // WORKAROUND: this if-statement has been added to avoid crashes caused by
+ // execution of label jobs after a location switch. The other workaround in
+ // Parallaction::runGame should have been rendered useless by this one.
+ if (_jDrawLabel != NULL) {
+ removeJob(_jDrawLabel);
+ removeJob(_jEraseLabel);
+ _jDrawLabel = NULL;
+ _jEraseLabel = NULL;
+ }
+
+
+ _hoverZone = NULL;
+ if (_engineFlags & kEngineBlockInput) {
+ changeCursor( kCursorArrow );
+ }
+
+ _animations.remove(&_char._ani);
+
+ freeLocation();
+ char buf[100];
+ strcpy(buf, location);
+
+ Common::StringList list;
+ char *tok = strtok(location, ".");
+ while (tok) {
+ list.push_back(tok);
+ tok = strtok(NULL, ".");
+ }
+
+ if (list.size() < 1 || list.size() > 4)
+ error("changeLocation: ill-formed location string '%s'", location);
+
+ if (list.size() > 1) {
+ if (list[1] == "slide") {
+ showSlide(list[0].c_str());
+ _gfx->setFont(_menuFont);
+ _gfx->displayCenteredString(14, _slideText[0]); // displays text on screen
+ _gfx->updateScreen();
+ waitUntilLeftClick();
+
+ list.remove_at(0); // removes slide name
+ list.remove_at(0); // removes 'slide'
+ }
+
+ // list is now only [L].{[C]} (see above comment)
+ if (list.size() == 2) {
+ changeCharacter(list[1].c_str());
+ strcpy(_characterName, list[1].c_str());
+ }
+ }
+
+ _animations.push_front(&_char._ani);
+
+ strcpy(_saveData1, list[0].c_str());
+ parseLocation(list[0].c_str());
+
+ _char._ani._oldPos.x = -1000;
+ _char._ani._oldPos.y = -1000;
+
+ _char._ani.field_50 = 0;
+ if (_location._startPosition.x != -1000) {
+ _char._ani._left = _location._startPosition.x;
+ _char._ani._top = _location._startPosition.y;
+ _char._ani._frame = _location._startFrame;
+ _location._startPosition.y = -1000;
+ _location._startPosition.x = -1000;
+ }
+
+
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
+ _gfx->setBlackPalette();
+ _gfx->updateScreen();
+
+ if (_location._commands.size() > 0) {
+ runCommands(_location._commands);
+ runJobs();
+ _gfx->swapBuffers();
+ runJobs();
+ _gfx->swapBuffers();
+ }
+
+ if (_location._comment) {
+ doLocationEnterTransition();
+ }
+
+ runJobs();
+ _gfx->swapBuffers();
+
+ _gfx->setPalette(_gfx->_palette);
+ if (_location._aCommands.size() > 0) {
+ runCommands(_location._aCommands);
+ }
+
+ if (_hasLocationSound)
+ _soundMan->playSfx(_locationSound, 0, true);
+
+ debugC(1, kDebugLocation, "changeLocation() done");
+
+ return;
+
}
-void Parallaction::initOpcodes() {
-
- static const Opcode op0[] = {
- INSTRUCTION_PARSER(defLocal), // invalid opcode -> local definition
- INSTRUCTION_PARSER(animation), // on
- INSTRUCTION_PARSER(animation), // off
- INSTRUCTION_PARSER(x),
- INSTRUCTION_PARSER(y),
- INSTRUCTION_PARSER(z),
- INSTRUCTION_PARSER(f),
- INSTRUCTION_PARSER(loop),
- INSTRUCTION_PARSER(null), // endloop
- INSTRUCTION_PARSER(null), // show
- INSTRUCTION_PARSER(inc),
- INSTRUCTION_PARSER(inc), // dec
- INSTRUCTION_PARSER(set),
- INSTRUCTION_PARSER(put),
- INSTRUCTION_PARSER(call),
- INSTRUCTION_PARSER(null), // wait
- INSTRUCTION_PARSER(animation), // start
- INSTRUCTION_PARSER(sound),
- INSTRUCTION_PARSER(move)
- };
-
- _instructionParsers = op0;
-
-
- static const Opcode op1[] = {
- INSTRUCTION_OPCODE(invalid),
- INSTRUCTION_OPCODE(on),
- INSTRUCTION_OPCODE(off),
- INSTRUCTION_OPCODE(set), // x
- INSTRUCTION_OPCODE(set), // y
- INSTRUCTION_OPCODE(set), // z
- INSTRUCTION_OPCODE(set), // f
- INSTRUCTION_OPCODE(loop),
- INSTRUCTION_OPCODE(endloop),
- INSTRUCTION_OPCODE(null),
- INSTRUCTION_OPCODE(inc),
- INSTRUCTION_OPCODE(inc), // dec
- INSTRUCTION_OPCODE(set),
- INSTRUCTION_OPCODE(put),
- INSTRUCTION_OPCODE(call),
- INSTRUCTION_OPCODE(wait),
- INSTRUCTION_OPCODE(start),
- INSTRUCTION_OPCODE(sound),
- INSTRUCTION_OPCODE(move),
- INSTRUCTION_OPCODE(end)
- };
-
- _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(endcommands), // endcommands
- COMMAND_PARSER(endcommands) // endzone
- };
-
- _commandParsers = op2;
-
- static const Opcode op3[] = {
- COMMAND_OPCODE(invalid),
- COMMAND_OPCODE(set),
- COMMAND_OPCODE(clear),
- COMMAND_OPCODE(start),
- COMMAND_OPCODE(speak),
- COMMAND_OPCODE(get),
- COMMAND_OPCODE(location),
- COMMAND_OPCODE(open),
- COMMAND_OPCODE(close),
- COMMAND_OPCODE(on),
- COMMAND_OPCODE(off),
- COMMAND_OPCODE(call),
- COMMAND_OPCODE(toggle),
- COMMAND_OPCODE(drop),
- COMMAND_OPCODE(quit),
- COMMAND_OPCODE(move),
- COMMAND_OPCODE(stop)
- };
-
- _commandOpcodes = op3;
-
-
- static const Opcode op4[] = {
- LOCATION_PARSER(invalid),
- LOCATION_PARSER(endlocation),
- LOCATION_PARSER(location),
- LOCATION_PARSER(disk),
- LOCATION_PARSER(nodes),
- LOCATION_PARSER(zone),
- LOCATION_PARSER(animation),
- LOCATION_PARSER(localflags),
- LOCATION_PARSER(commands),
- LOCATION_PARSER(acommands),
- LOCATION_PARSER(flags),
- LOCATION_PARSER(comment),
- LOCATION_PARSER(endcomment),
- LOCATION_PARSER(sound),
- 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;
-
- _currentOpcodes = 0;
- _currentStatements = 0;
+// displays transition before a new location
+//
+// clears screen (in white??)
+// shows location comment (if any)
+// waits for mouse click
+// fades towards game palette
+//
+void Parallaction::doLocationEnterTransition() {
+ debugC(1, kDebugLocation, "doLocationEnterTransition");
+
+ if (_localFlags[_currentLocationIndex] & kFlagsVisited) {
+ debugC(3, kDebugLocation, "skipping location transition");
+ return; // visited
+ }
+
+ Palette pal(_gfx->_palette);
+ pal.makeGrayscale();
+ _gfx->setPalette(pal);
+
+ jobRunScripts(NULL, NULL);
+ jobEraseAnimations(NULL, NULL);
+ jobDisplayAnimations(NULL, NULL);
+
+ _gfx->swapBuffers();
+ _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
+
+ showLocationComment(_location._comment, false);
+ waitUntilLeftClick();
+
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront );
+
+ // fades maximum intensity palette towards approximation of main palette
+ for (uint16 _si = 0; _si<6; _si++) {
+ pal.fadeTo(_gfx->_palette, 4);
+ _gfx->setPalette(pal);
+ waitTime( 1 );
+ _gfx->updateScreen();
+ }
+ debugC(1, kDebugLocation, "doLocationEnterTransition completed");
+
+ return;
+}
+
+
+
+Zone *Parallaction::findZone(const char *name) {
+
+ for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) {
+ if (!scumm_stricmp((*it)->_label._text, name)) return *it;
+ }
+
+ return findAnimation(name);
}
+
+void Parallaction::freeZones() {
+ debugC(1, kDebugLocation, "freeZones: kEngineQuit = %i", _engineFlags & kEngineQuit);
+
+ ZoneList::iterator it = _zones.begin();
+
+ while ( it != _zones.end() ) {
+
+ Zone* z = *it;
+
+ // WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
+ // instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
+ // but we need to check it separately here. The same workaround is applied in hitZone.
+ if (((z->_top == -1) ||
+ ((z->_left == -2) && (
+ (((z->_type & 0xFFFF) == kZoneMerge) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj1)) != 0) || (isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj2)) != 0))) ||
+ (((z->_type & 0xFFFF) == kZoneGet) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.get->_icon)) != 0)))
+ ))) &&
+ ((_engineFlags & kEngineQuit) == 0)) {
+
+ debugC(1, kDebugLocation, "freeZones preserving zone '%s'", z->_label._text);
+
+ it++;
+
+ } else
+
+ it = _zones.erase(it);
+
+ }
+
+ return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 28551341df..eac10e9b55 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -28,15 +28,16 @@
#include "common/str.h"
#include "common/stack.h"
+#include "common/array.h"
#include "engines/engine.h"
#include "parallaction/defs.h"
#include "parallaction/inventory.h"
#include "parallaction/parser.h"
+#include "parallaction/objects.h"
#include "parallaction/disk.h"
#include "parallaction/walk.h"
-#include "parallaction/zone.h"
namespace GUI {
class ListWidget;
@@ -165,7 +166,6 @@ typedef void (*callable)(void*);
extern uint16 _mouseButtons;
extern uint16 _score;
extern uint16 _language;
-extern Zone *_activeZone;
extern uint32 _engineFlags;
extern callable _callables[];
extern uint32 _localFlags[];
@@ -225,7 +225,6 @@ struct Location {
Common::Point _startPosition;
uint16 _startFrame;
- WalkNodeList _walkNodes;
char _name[100];
CommandList _aCommands;
@@ -233,6 +232,11 @@ struct Location {
char *_comment;
char *_endComment;
+ // NS specific
+ WalkNodeList _walkNodes;
+
+ // BRA specific
+ CommandList _escapeCommands;
};
struct Character {
@@ -281,7 +285,7 @@ public:
void addData(const char* s);
- int lookup(const char* s);
+ uint16 lookup(const char* s);
};
struct BackgroundInfo {
@@ -295,34 +299,46 @@ struct BackgroundInfo {
Palette palette;
};
+class Opcode {
-#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
+public:
+ virtual void operator()() const = 0;
+ virtual ~Opcode() { }
+};
-#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
+template <class T>
+class OpcodeImpl : public Opcode {
-#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
+ typedef void (T::*Fn)();
+
+ T* _instance;
+ Fn _fn;
+
+public:
+ OpcodeImpl(T* instance, const Fn &fn) : _instance(instance), _fn(fn) { }
+
+ void operator()() const {
+ (_instance->*_fn)();
+ }
+
+};
+
+
+typedef Common::Array<const Opcode*> OpcodeSet;
-#define DECLARE_COMMAND_OPCODE(op) void Parallaction::cmdOp_##op()
-#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op()
-#define COMMAND_OPCODE(op) &Parallaction::cmdOp_##op
-#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction::instParse_##sig()
+
+#define DECLARE_UNQUALIFIED_ZONE_PARSER(sig) void locZoneParse_##sig()
+#define DECLARE_UNQUALIFIED_ANIM_PARSER(sig) void locAnimParse_##sig()
+#define DECLARE_UNQUALIFIED_COMMAND_PARSER(sig) void cmdParse_##sig()
+#define DECLARE_UNQUALIFIED_LOCATION_PARSER(sig) void locParse_##sig()
#define DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sig) void instParse_##sig()
-#define INSTRUCTION_PARSER(sig) &Parallaction::instParse_##sig
-#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction::instOp_##op()
+#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op()
#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op()
-#define INSTRUCTION_OPCODE(op) &Parallaction::instOp_##op
-#define DECLARE_LOCATION_PARSER(sig) void Parallaction::locParse_##sig()
-#define DECLARE_UNQUALIFIED_LOCATION_PARSER(sig) void locParse_##sig()
-#define LOCATION_PARSER(sig) &Parallaction::locParse_##sig
+
+
class Parallaction : public Engine {
friend class Debugger;
@@ -341,90 +357,23 @@ public:
void waitTime(uint32 t);
- void initOpcodes();
-
- typedef void (Parallaction::*Opcode)();
- const Opcode *_commandParsers;
-
uint _lookup;
-
- Common::Stack<const Opcode*> _opcodes;
- Common::Stack<Table*> _statements;
-
- const Opcode *_currentOpcodes;
- Table *_currentStatements;
-
- void pushParserTables(const Opcode* opcodes, Table* statements);
+ Common::Stack<OpcodeSet*> _opcodes;
+ Common::Stack<Table*> _statements;
+ OpcodeSet *_currentOpcodes;
+ Table *_currentStatements;
+ void pushParserTables(OpcodeSet *opcodes, Table* statements);
void popParserTables();
void parseStatement();
- 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(endcommands);
-
- const Opcode *_commandOpcodes;
+ OpcodeSet _commandOpcodes;
struct {
Command *cmd;
Zone *z;
} _cmdRunCtxt;
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(get);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
-
- const Opcode *_instructionParsers;
-
- struct {
- Animation *a;
- Instruction *inst;
- LocalVariable *locals;
- } _instParseCtxt;
-
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(defLocal);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(animation);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(loop);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(x);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(y);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(z);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(f);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(inc);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(set);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(move);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(put);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(call);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sound);
- DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(null);
-
- const Opcode *_instructionOpcodes;
+ OpcodeSet _instructionOpcodes;
struct {
Animation *a;
@@ -433,93 +382,11 @@ public:
bool suspend;
} _instRunCtxt;
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(end);
-
- void parseLocation(const char *filename);
-
- const Opcode *_locationParsers;
-
- struct {
- const char *filename;
- bool end;
- Script *script;
- Zone *z;
- } _locParseCtxt;
-
- DECLARE_UNQUALIFIED_LOCATION_PARSER(invalid);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(endlocation);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(location);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(disk);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(nodes);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(zone);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(animation);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(commands);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(acommands);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(flags);
- DECLARE_UNQUALIFIED_LOCATION_PARSER(comment);
- 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);
void changeCharacter(const char *name);
- char *parseComment(Script &script);
- char *parseDialogueString(Script &script);
- Dialogue *parseDialogue(Script &script);
Job *addJob(JobFn fn, void *parm, uint16 tag);
void removeJob(Job *j);
@@ -552,13 +419,8 @@ public:
Table *_objectsNames;
Table *_zoneTypeNames;
Table *_zoneFlagNames;
- Table *_commandsNames;
Table *_callableNames;
- Table *_instructionNames;
Table *_localFlagNames;
- Table *_locationStmt;
- Table *_locationZoneStmt;
- Table *_locationAnimStmt;
public:
@@ -595,6 +457,8 @@ public:
Common::Point _mousePos;
+ Zone *_activeZone;
+
ZoneList _zones;
AnimationList _animations;
@@ -664,24 +528,11 @@ protected: // members
void freeLocation();
void showLocationComment(const char *text, bool end);
- void parseZone(Script &script, ZoneList &list, char *name);
- void parseZoneTypeBlock(Script &script, Zone *z);
void displayCharacterComment(ExamineData *data);
void displayItemComment(ExamineData *data);
- void parseWalkNodes(Script& script, WalkNodeList &list);
uint16 checkDoor();
- Animation * parseAnimation(Script &script, AnimationList &list, char *name);
- void parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals);
- void loadProgram(Animation *a, char *filename);
- 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();
int addInventoryItem(uint16 item);
@@ -696,6 +547,8 @@ public:
virtual void setMousePointer(int16 index) = 0;
+ virtual void parseLocation(const char* name) = 0;
+
public:
const char **_zoneFlagNamesRes;
const char **_zoneTypeNamesRes;
@@ -722,15 +575,14 @@ public:
void renderLabel(Graphics::Surface *cnv, char *text);
void setMousePointer(int16 index);
-public:
+private:
Menu* _menu;
-private:
void initFonts();
void freeFonts();
private:
- void initResources();
+ void initResources();
void initCursors();
static byte _mouseArrow[256];
@@ -773,12 +625,184 @@ private:
void _c_HBOn(void*);
const Callable *_callables;
+
+protected:
+ // location parser
+ OpcodeSet _locationParsers;
+ OpcodeSet _locationZoneParsers;
+ OpcodeSet _locationAnimParsers;
+ OpcodeSet _commandParsers;
+ Table *_commandsNames;
+ Table *_locationStmt;
+ Table *_locationZoneStmt;
+ Table *_locationAnimStmt;
+
+ struct {
+ const char *filename;
+ bool end;
+ Script *script;
+ } _locParseCtxt;
+ struct {
+ bool end;
+ Script *script;
+ Zone *z;
+ } _locZoneParseCtxt;
+ struct {
+ bool end;
+ Script *script;
+ Animation *a;
+ } _locAnimParseCtxt;
+ struct {
+ Command *cmd;
+ int nextToken;
+ CommandList *list;
+ bool end;
+ Script *script;
+ } _cmdParseCtxt;
+
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(invalid);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(endlocation);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(location);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(disk);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(nodes);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(zone);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(animation);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(commands);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(acommands);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(flags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(comment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(sound);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(music);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(redundant);
+ 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);
+ 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);
+ 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(simple);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(move);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(endcommands);
+
+ void parseLocation(const char *filename);
+ char *parseComment(Script &script);
+ char *parseDialogueString(Script &script);
+ Dialogue *parseDialogue(Script &script);
+ void parseZone(Script &script, ZoneList &list, char *name);
+ void parseZoneTypeBlock(Script &script, Zone *z);
+ void parseWalkNodes(Script& script, WalkNodeList &list);
+ Animation *parseAnimation(Script &script, AnimationList &list, char *name);
+ void parseCommands(Script &script, CommandList&);
+ void parseCommandFlags();
+ void createCommand(uint id);
+ void addCommand();
+ void initOpcodes();
+ void initParsers();
+
+
+ // program parser
+ OpcodeSet _instructionParsers;
+ Table *_instructionNames;
+
+ struct {
+ Animation *a;
+ Instruction *inst;
+ LocalVariable *locals;
+
+ // BRA specific
+ Instruction *openIf;
+ } _instParseCtxt;
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(defLocal);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(animation);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(x);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(y);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(z);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(f);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(call);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sound);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(null);
+
+ void parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals);
+ void loadProgram(Animation *a, const char *filename);
+ ScriptVar parseLValue(Instruction *inst, const char *str, LocalVariable *locals, Animation *a);
+ virtual ScriptVar parseRValue(Instruction *inst, const char *str, LocalVariable *locals, Animation *a);
+ int16 findLocal(const char* name, LocalVariable *locals);
+ int16 addLocal(const char *name, LocalVariable *locals, int16 value = 0, int16 min = -10000, int16 max = 10000);
+ void wrapLocalVar(LocalVariable *local);
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(get);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(end);
+
};
-class Parallaction_br : public Parallaction {
+
+
+
+
+class Parallaction_br : public Parallaction_ns {
+
+ typedef Parallaction_ns Super;
public:
- Parallaction_br(OSystem* syst) : Parallaction(syst) { }
+ Parallaction_br(OSystem* syst) : Parallaction_ns(syst) { }
~Parallaction_br();
int init();
@@ -797,10 +821,23 @@ public:
int _part;
int _progress;
+ int _zeta0;
+ int _zeta1;
+ int _zeta2;
+
+ int16 _lipSyncVal;
+
+ Zone *_activeZone2;
+
+ int32 _counters[32];
+
private:
void initResources();
void initFonts();
void freeFonts();
+ void initOpcodes();
+ void initParsers();
+
void initPart();
void freePart();
@@ -831,6 +868,113 @@ private:
void _c_password(void*);
const Callable *_callables;
+/*
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(location);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(zone);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(animation);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(flags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(comment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(sound);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(music);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(redundant);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(ifchar);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(character);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(mask);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(path);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(escape);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(zeta);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(null);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(ifchar);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(endif);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(zone);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(location);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(toggle);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(string);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(math);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(test);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(music);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(zeta);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(swap);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(give);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(text);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(unary);
+
+ void parseLocation(const char* name);
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(zone);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(color);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(mask);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(print);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(text);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(if_op);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(endif);
+
+ virtual ScriptVar parseRValue(Instruction *inst, const char *str, LocalVariable *locals, Animation *a);
+
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(character);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(add);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(let);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(music);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(give);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(text);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(part);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave);
+
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
+*/
};
// FIXME: remove global
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 955994a307..3fd56b80aa 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -79,10 +79,14 @@ int Parallaction_br::init() {
_soundMan = new DummySoundMan(this);
+ _activeZone2 = 0;
+
initResources();
initFonts();
initCursors();
-
+/* initOpcodes();
+ initParsers();
+*/
_part = -1;
Parallaction::init();
@@ -316,6 +320,8 @@ void Parallaction_br::setMousePointer(int16 index) {
void Parallaction_br::initPart() {
+ memset(_counters, 0, ARRAYSIZE(_counters));
+
_globalTable = _disk->loadTable("global");
_objectsNames = _disk->loadTable("objects");
_countersNames = _disk->loadTable("counters");
@@ -343,83 +349,5 @@ void Parallaction_br::startPart() {
}
-void skip(Script* script, const char* endToken) {
-
- while (scumm_stricmp(_tokens[0], endToken)) {
- fillBuffers(*script, true);
- }
-
-}
-#if 0
-bool Parallaction_br::parseLocationLine(const char *filename, Script *script) {
-
- bool parsed = true;
- bool flip = false;
- int nextToken = 0;
-
- if (!scumm_stricmp(_tokens[0], "LOCATION")) {
-
- strcpy(_location._name, _tokens[1]);
- _disk->loadScenery(*_backgroundInfo, _location._name, NULL, NULL);
- _gfx->setBackground(&_backgroundInfo->bg);
- _gfx->_palette.clone(_backgroundInfo->palette);
- _gfx->setPalette(_backgroundInfo->palette);
-
- if (!scumm_stricmp("flip", _tokens[2])) {
- flip = true;
- nextToken = 3;
- } else {
- nextToken = 2;
- }
-
- if (_tokens[nextToken][0] != '\0') {
- _char._ani._left = atoi(_tokens[nextToken]);
- nextToken++;
- _char._ani._top = atoi(_tokens[nextToken]);
- nextToken++;
- }
-
- if (_tokens[nextToken][0] != '\0') {
- _char._ani._frame = atoi(_tokens[nextToken]);
- }
- } else
- if (!scumm_stricmp(_tokens[0], "IFCHAR")) {
- skip(script, "ENDIF");
- } else
- if (!scumm_stricmp(_tokens[0], "CHARACTER")) {
-
- } else
- if (!scumm_stricmp(_tokens[0], "MASK")) {
- _disk->loadScenery(*_backgroundInfo, NULL, _tokens[1], NULL);
- _gfx->setMask(&_backgroundInfo->mask);
-
- _gfx->_bgLayers[0] = atoi(_tokens[2]);
- _gfx->_bgLayers[1] = atoi(_tokens[3]);
- _gfx->_bgLayers[2] = atoi(_tokens[4]);
- } else
- if (!scumm_stricmp(_tokens[0], "PATH")) {
- _disk->loadScenery(*_backgroundInfo, NULL, NULL, _tokens[1]);
- _pathBuffer = &_backgroundInfo->path;
- } else
- if (!scumm_stricmp(_tokens[0], "DISK")) {
- //
- } else
- if (!scumm_stricmp(_tokens[0], "ESCAPE")) {
- skip(script, "endcommands");
- } else
- if (!scumm_stricmp(_tokens[0], "ZETA")) {
- //
- } else
- if (!scumm_stricmp(_tokens[0], "ZONE")) {
- skip(script, "endzone");
- } else
- if (!scumm_stricmp(_tokens[0], "ANIMATION")) {
- skip(script, "endanimation");
- } else
- parsed = false;
-
- return parsed;
-}
-#endif
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index e98ef3847c..2a82002f24 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -74,6 +74,8 @@ int Parallaction_ns::init() {
initResources();
initFonts();
initCursors();
+ initOpcodes();
+ initParsers();
Parallaction::init();
@@ -85,6 +87,12 @@ Parallaction_ns::~Parallaction_ns() {
_mouseComposedArrow->free();
delete _mouseComposedArrow;
+
+
+ delete _commandsNames;
+ delete _instructionNames;
+ delete _locationStmt;
+
}
@@ -200,4 +208,5 @@ int Parallaction_ns::go() {
}
+
} // namespace Parallaction
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index 34b5e02f8e..dfda083392 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -82,33 +82,6 @@ void Script::seek(int32 offset, int whence) {
error("seek not supported on Script streams");
}
-//
-// a comment can appear both at location and Zone levels
-// comments are displayed into rectangles on the screen
-//
-char *Parallaction::parseComment(Script &script) {
-
- char _tmp_comment[1000] = "\0";
- char *v194;
-
- do {
- char v190[400];
- v194 = script.readLine(v190, 400);
-
- v194[strlen(v194)-1] = '\0';
- if (!scumm_stricmp(v194, "endtext"))
- break;
-
- strcat(_tmp_comment, v194);
- strcat(_tmp_comment, " ");
- } while (true);
-
- v194 = strdup(_tmp_comment);
- _tmp_comment[0] = '\0';
-
- return v194;
-}
-
void clearTokens() {
for (uint16 i = 0; i < 20; i++)
@@ -118,6 +91,14 @@ void clearTokens() {
}
+void skip(Script* script, const char* endToken) {
+
+ while (scumm_stricmp(_tokens[0], endToken)) {
+ fillBuffers(*script, true);
+ }
+
+}
+
//
// Scans 's' until one of the stop-chars in 'brk' is found, building a token.
// If the routine encounters quotes, it will extract the contained text and
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index aa3929a52c..3d1b32ec3a 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -57,6 +57,9 @@ public:
void seek(int32 offset, int whence = SEEK_SET);
};
+void skip(Script* script, const char* endToken);
+
+
} // namespace Parallaction
#endif
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
new file mode 100644
index 0000000000..093e95e5f4
--- /dev/null
+++ b/engines/parallaction/parser_ns.cpp
@@ -0,0 +1,1355 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "parallaction/parallaction.h"
+#include "parallaction/sound.h"
+
+namespace Parallaction {
+
+#define CMD_SET 1
+#define CMD_CLEAR 2
+#define CMD_START 3
+#define CMD_SPEAK 4
+#define CMD_GET 5
+#define CMD_LOCATION 6
+#define CMD_OPEN 7
+#define CMD_CLOSE 8
+#define CMD_ON 9
+#define CMD_OFF 10
+#define CMD_CALL 11
+#define CMD_TOGGLE 12
+#define CMD_DROP 13
+#define CMD_QUIT 14
+#define CMD_MOVE 15
+#define CMD_STOP 16
+
+#define INST_ON 1
+#define INST_OFF 2
+#define INST_X 3
+#define INST_Y 4
+#define INST_Z 5
+#define INST_F 6
+#define INST_LOOP 7
+#define INST_ENDLOOP 8
+#define INST_SHOW 9
+#define INST_INC 10
+#define INST_DEC 11
+#define INST_SET 12
+#define INST_PUT 13
+#define INST_CALL 14
+#define INST_WAIT 15
+#define INST_START 16
+#define INST_SOUND 17
+#define INST_MOVE 18
+#define INST_END 19
+
+
+#define DECLARE_ZONE_PARSER(sig) void Parallaction_ns::locZoneParse_##sig()
+#define DECLARE_ANIM_PARSER(sig) void Parallaction_ns::locAnimParse_##sig()
+#define DECLARE_COMMAND_PARSER(sig) void Parallaction_ns::cmdParse_##sig()
+#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction_ns::instParse_##sig()
+#define DECLARE_LOCATION_PARSER(sig) void Parallaction_ns::locParse_##sig()
+
+
+#define NUM_LOCALS 10
+
+uint16 _numLocals = 0;
+char _localNames[NUM_LOCALS][10];
+
+
+DECLARE_ANIM_PARSER(invalid) {
+ error("unknown statement '%s' in animation %s", _tokens[0], _locAnimParseCtxt.a->_label._text);
+}
+
+
+DECLARE_ANIM_PARSER(script) {
+ _locAnimParseCtxt.a->_scriptName = strdup(_tokens[1]);
+}
+
+
+DECLARE_ANIM_PARSER(commands) {
+ parseCommands(*_locAnimParseCtxt.script, _locAnimParseCtxt.a->_commands);
+}
+
+
+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);
+ }
+ }
+
+ _locAnimParseCtxt.a->_oldPos.x = -1000;
+ _locAnimParseCtxt.a->_oldPos.y = -1000;
+
+ _locAnimParseCtxt.a->_flags |= 0x1000000;
+
+ popParserTables();
+}
+
+
+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.a->_oldPos.x = -1000;
+ _locAnimParseCtxt.a->_oldPos.y = -1000;
+
+ _locAnimParseCtxt.a->_flags |= 0x1000000;
+
+ popParserTables();
+}
+
+Animation *Parallaction_ns::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;
+
+ pushParserTables(&_locationAnimParsers, _locationAnimStmt);
+
+ return a;
+}
+
+void Parallaction_ns::loadProgram(Animation *a, const char *filename) {
+// printf("loadProgram(%s)\n", filename);
+
+ Script *script = _disk->loadScript(filename);
+
+ _numLocals = 0;
+
+ fillBuffers(*script);
+
+ a->_program = new Program;
+
+ Instruction *vCC = new Instruction;
+
+ _instParseCtxt.openIf = NULL;
+
+ while (scumm_stricmp(_tokens[0], "endscript")) {
+ parseScriptLine(vCC, a, a->_program->_locals);
+ a->_program->_instructions.push_back(vCC);
+ vCC = new Instruction;
+ fillBuffers(*script);
+ }
+
+ // TODO: use List<>::end() to detect the end of the program
+ vCC->_index = INST_END;
+ a->_program->_instructions.push_back(vCC);
+ a->_program->_ip = a->_program->_instructions.begin();
+
+ delete script;
+
+ return;
+}
+
+int16 Parallaction_ns::findLocal(const char* name, LocalVariable *locals) {
+ for (uint16 _si = 0; _si < NUM_LOCALS; _si++) {
+ if (!scumm_stricmp(name, _localNames[_si]))
+ return _si;
+ }
+
+ return -1;
+}
+
+int16 Parallaction_ns::addLocal(const char *name, LocalVariable *locals, int16 value, int16 min, int16 max) {
+ assert(_numLocals < NUM_LOCALS);
+
+ strcpy(_localNames[_numLocals], name);
+ locals[_numLocals]._value = value;
+
+ locals[_numLocals]._min = min;
+ locals[_numLocals]._max = max;
+
+ return _numLocals++;
+}
+
+
+DECLARE_INSTRUCTION_PARSER(animation) {
+ if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
+ _instParseCtxt.inst->_opBase._a = _instParseCtxt.a;
+ } else {
+ _instParseCtxt.inst->_opBase._a = findAnimation(_tokens[1]);
+ }
+}
+
+
+DECLARE_INSTRUCTION_PARSER(loop) {
+ _instParseCtxt.inst->_opBase._loopCounter = parseRValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(x) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_left;
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(y) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_top;
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(z) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_z;
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(f) {
+ _instParseCtxt.inst->_opA._pvalue = &_instParseCtxt.a->_frame;
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(inc) {
+ _instParseCtxt.inst->_opA = parseLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+
+ if (!scumm_stricmp(_tokens[3], "mod")) {
+ _instParseCtxt.inst->_flags |= kInstMod;
+ }
+}
+
+
+DECLARE_INSTRUCTION_PARSER(set) {
+ // WORKAROUND: At least one script (balzo.script) in Amiga versions didn't declare
+ // local variables before using them, thus leading to crashes. The line launching the
+ // script was commented out on Dos version. This workaround enables the engine
+ // to dynamically add a local variable when it is encountered the first time in
+ // the script, so should fix any other occurrence as well.
+ if (findLocal(_tokens[1], _instParseCtxt.locals) == -1) {
+ addLocal(_tokens[1], _instParseCtxt.locals);
+ }
+
+ _instParseCtxt.inst->_opA = parseLValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(move) {
+ _instParseCtxt.inst->_opA = parseRValue(_instParseCtxt.inst, _tokens[1], _instParseCtxt.locals, _instParseCtxt.a);
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(put) {
+ if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
+ _instParseCtxt.inst->_opBase._a = _instParseCtxt.a;
+ } else {
+ _instParseCtxt.inst->_opBase._a = findAnimation(_tokens[1]);
+ }
+
+ _instParseCtxt.inst->_opA = parseRValue(_instParseCtxt.inst, _tokens[2], _instParseCtxt.locals, _instParseCtxt.a);
+ _instParseCtxt.inst->_opB = parseRValue(_instParseCtxt.inst, _tokens[3], _instParseCtxt.locals, _instParseCtxt.a);
+ if (!scumm_stricmp(_tokens[4], "masked")) {
+ _instParseCtxt.inst->_flags |= kInstMaskedPut;
+ }
+}
+
+
+DECLARE_INSTRUCTION_PARSER(call) {
+ int index = _callableNames->lookup(_tokens[1]);
+ if (index == Table::notFound)
+ error("unknown callable '%s'", _tokens[1]);
+ _instParseCtxt.inst->_opBase._index = index - 1;
+}
+
+
+DECLARE_INSTRUCTION_PARSER(sound) {
+ _instParseCtxt.inst->_opBase._z = findZone(_tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(null) {
+
+}
+
+
+DECLARE_INSTRUCTION_PARSER(defLocal) {
+ int16 val = atoi(_tokens[2]);
+ int16 index;
+
+ if (_tokens[3][0] != '\0') {
+ index = addLocal(_tokens[0], _instParseCtxt.locals, val, atoi(_tokens[3]), atoi(_tokens[4]));
+ } else {
+ index = addLocal(_tokens[0], _instParseCtxt.locals, val);
+ }
+
+ _instParseCtxt.inst->_opA._local = &_instParseCtxt.locals[index];
+ _instParseCtxt.inst->_opB._value = _instParseCtxt.locals[index]._value;
+
+ _instParseCtxt.inst->_flags = kInstUsesLiteral | kInstUsesLocal;
+ _instParseCtxt.inst->_index = INST_SET;
+}
+
+
+
+
+void Parallaction_ns::parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals) {
+// printf("parseScriptLine()\n");
+
+ if (_tokens[0][1] == '.') {
+ _tokens[0][1] = '\0';
+ a = findAnimation(&_tokens[0][2]);
+ }
+
+ if (_tokens[1][1] == '.') {
+ _tokens[1][1] = '\0';
+ a = findAnimation(&_tokens[1][2]);
+ }
+
+ int16 _si = _instructionNames->lookup(_tokens[0]);
+ inst->_index = _si;
+
+ _instParseCtxt.a = a;
+ _instParseCtxt.inst = inst;
+ _instParseCtxt.locals = locals;
+
+ (*(_instructionParsers[inst->_index]))();
+
+ return;
+}
+
+ScriptVar Parallaction_ns::parseRValue(Instruction *inst, const char *str, LocalVariable *locals, Animation *a) {
+
+ ScriptVar v;
+
+ v._pvalue = 0; // should stop compiler from complaining
+
+ if (isdigit(str[0]) || str[0] == '-') {
+ inst->_flags |= kInstUsesLiteral;
+ v._value = atoi(str);
+ return v;
+ }
+
+ int index = findLocal(str, locals);
+ if (index != -1) {
+ v._local = &locals[index];
+ inst->_flags |= kInstUsesLocal;
+ return v;
+ }
+
+ if (str[1] == '.') {
+ a = findAnimation(&str[2]);
+ }
+
+ if (str[0] == 'X') {
+ v._pvalue = &a->_left;
+ inst->_flags |= kInstUsesField;
+ } else
+ if (str[0] == 'Y') {
+ v._pvalue = &a->_top;
+ inst->_flags |= kInstUsesField;
+ } else
+ if (str[0] == 'Z') {
+ v._pvalue = &a->_z;
+ inst->_flags |= kInstUsesField;
+ } else
+ if (str[0] == 'F') {
+ v._pvalue = &a->_frame;
+ inst->_flags |= kInstUsesField;
+ }
+
+ return v;
+}
+
+ScriptVar Parallaction_ns::parseLValue(Instruction *inst, const char *str, LocalVariable *locals, Animation *a) {
+
+ ScriptVar v;
+
+ v._pvalue = 0; // should stop compiler from complaining
+
+ int index = findLocal(str, locals);
+ if (index != -1) {
+ v._local = &locals[index];
+ inst->_flags |= kInstUsesLocal;
+ return v;
+ }
+
+ if (str[1] == '.') {
+ a = findAnimation(&str[2]);
+ }
+
+ if (str[0] == 'X') {
+ v._pvalue = &a->_left;
+ inst->_flags |= kInstUsesField;
+ } else
+ if (str[0] == 'Y') {
+ v._pvalue = &a->_top;
+ inst->_flags |= kInstUsesField;
+ } else
+ if (str[0] == 'Z') {
+ v._pvalue = &a->_z;
+ inst->_flags |= kInstUsesField;
+ } else
+ if (str[0] == 'F') {
+ v._pvalue = &a->_frame;
+ inst->_flags |= kInstUsesField;
+ }
+
+ return v;
+}
+
+
+DECLARE_COMMAND_PARSER(flags) {
+ createCommand(_lookup);
+
+ if (_globalTable->lookup(_tokens[1]) == Table::notFound) {
+ do {
+ char _al = _localFlagNames->lookup(_tokens[_cmdParseCtxt.nextToken]);
+ _cmdParseCtxt.nextToken++;
+ _cmdParseCtxt.cmd->u._flags |= 1 << (_al - 1);
+ } while (!scumm_stricmp(_tokens[_cmdParseCtxt.nextToken++], "|"));
+ _cmdParseCtxt.nextToken--;
+ } else {
+ _cmdParseCtxt.cmd->u._flags |= kFlagsGlobal;
+ do {
+ char _al = _globalTable->lookup(_tokens[1]);
+ _cmdParseCtxt.nextToken++;
+ _cmdParseCtxt.cmd->u._flags |= 1 << (_al - 1);
+ } while (!scumm_stricmp(_tokens[_cmdParseCtxt.nextToken++], "|"));
+ _cmdParseCtxt.nextToken--;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(animation) {
+ createCommand(_lookup);
+
+ _cmdParseCtxt.cmd->u._animation = findAnimation(_tokens[_cmdParseCtxt.nextToken]);
+ _cmdParseCtxt.nextToken++;
+ if (_cmdParseCtxt.cmd->u._animation == NULL) {
+ strcpy(_forwardedAnimationNames[_numForwards], _tokens[_cmdParseCtxt.nextToken-1]);
+ _forwardedCommands[_numForwards] = _cmdParseCtxt.cmd;
+ _numForwards++;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(zone) {
+ createCommand(_lookup);
+
+ _cmdParseCtxt.cmd->u._zone = findZone(_tokens[_cmdParseCtxt.nextToken]);
+ _cmdParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+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) {
+ createCommand(_lookup);
+
+ _cmdParseCtxt.cmd->u._object = 4 + _objectsNames->lookup(_tokens[_cmdParseCtxt.nextToken]);
+ _cmdParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(call) {
+ createCommand(_lookup);
+
+ _cmdParseCtxt.cmd->u._callable = _callableNames->lookup(_tokens[_cmdParseCtxt.nextToken]) - 1;
+ _cmdParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(simple) {
+ createCommand(_lookup);
+ addCommand();
+}
+
+
+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) {
+ error("Can't parse unknown command '%s'", _tokens[0]);
+}
+
+DECLARE_COMMAND_PARSER(endcommands) {
+ popParserTables();
+
+ // temporary trick to handle dialogue commands
+ _cmdParseCtxt.end = true;
+}
+
+void Parallaction_ns::parseCommandFlags() {
+
+ int _si = _cmdParseCtxt.nextToken;
+ Command *cmd = _cmdParseCtxt.cmd;
+
+ 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++], "|"));
+
+ }
+
+ 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_ns::addCommand() {
+ _cmdParseCtxt.list->push_front(_cmdParseCtxt.cmd); // NOTE: command lists are written backwards in scripts
+}
+
+void Parallaction_ns::createCommand(uint id) {
+
+ _cmdParseCtxt.nextToken = 1;
+ _cmdParseCtxt.cmd = new Command;
+ _cmdParseCtxt.cmd->_id = id;
+
+}
+
+void Parallaction_ns::parseCommands(Script &script, CommandList& list) {
+ _cmdParseCtxt.list = &list;
+ _cmdParseCtxt.end = false;
+ _cmdParseCtxt.script = &script;
+
+ pushParserTables(&_commandParsers, _commandsNames);
+
+}
+
+Dialogue *Parallaction_ns::parseDialogue(Script &script) {
+// printf("parseDialogue()\n");
+ uint16 numQuestions = 0;
+
+ Dialogue *dialogue = new Dialogue;
+
+ Table forwards(20);
+
+ fillBuffers(script, true);
+
+ while (scumm_stricmp(_tokens[0], "enddialogue")) {
+ if (scumm_stricmp(_tokens[0], "Question")) continue;
+
+ Question *question = new Question;
+ dialogue->_questions[numQuestions] = question;
+
+ forwards.addData(_tokens[1]);
+
+ question->_text = parseDialogueString(script);
+
+ fillBuffers(script, true);
+ question->_mood = atoi(_tokens[0]);
+
+ uint16 numAnswers = 0;
+
+ fillBuffers(script, true);
+ while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers
+
+ Answer *answer = new Answer;
+ question->_answers[numAnswers] = answer;
+
+ if (_tokens[1][0]) {
+
+ Table* flagNames;
+ uint16 token;
+
+ if (!scumm_stricmp(_tokens[1], "global")) {
+ token = 2;
+ flagNames = _globalTable;
+ answer->_yesFlags |= kFlagsGlobal;
+ } else {
+ token = 1;
+ flagNames = _localFlagNames;
+ }
+
+ do {
+
+ if (!scumm_strnicmp(_tokens[token], "no", 2)) {
+ byte _al = flagNames->lookup(_tokens[token]+2);
+ answer->_noFlags |= 1 << (_al - 1);
+ } else {
+ byte _al = flagNames->lookup(_tokens[token]);
+ answer->_yesFlags |= 1 << (_al - 1);
+ }
+
+ token++;
+
+ } while (!scumm_stricmp(_tokens[token++], "|"));
+
+ }
+
+ answer->_text = parseDialogueString(script);
+
+ fillBuffers(script, true);
+ answer->_mood = atoi(_tokens[0]);
+ answer->_following._name = parseDialogueString(script);
+
+ fillBuffers(script, true);
+ if (!scumm_stricmp(_tokens[0], "commands")) {
+
+ parseCommands(script, answer->_commands);
+ _cmdParseCtxt.end = false;
+ do {
+ fillBuffers(script, true);
+ parseStatement();
+ } while (!_cmdParseCtxt.end);
+
+ fillBuffers(script, true);
+ }
+
+ numAnswers++;
+ }
+
+ fillBuffers(script, true);
+ numQuestions++;
+
+ }
+
+ // link questions
+ byte v50[20];
+ memset(v50, 0, 20);
+
+ for (uint16 i = 0; i < numQuestions; i++) {
+ Question *question = dialogue->_questions[i];
+
+ for (uint16 j = 0; j < NUM_ANSWERS; j++) {
+ Answer *answer = question->_answers[j];
+ if (answer == 0) continue;
+
+ int16 index = forwards.lookup(answer->_following._name);
+ free(answer->_following._name);
+
+ if (index == Table::notFound)
+ answer->_following._question = 0;
+ else
+ answer->_following._question = dialogue->_questions[index - 1];
+
+
+ }
+ }
+
+ return dialogue;
+}
+
+
+char *Parallaction_ns::parseDialogueString(Script &script) {
+
+ char vC8[200];
+ char *vD0 = NULL;
+ do {
+
+ vD0 = script.readLine(vC8, 200);
+ if (vD0 == 0) return NULL;
+
+ vD0 = Common::ltrim(vD0);
+
+ } while (strlen(vD0) == 0);
+
+ vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA'
+ // this is critical for Gfx::displayWrappedString to work properly
+ return strdup(vD0);
+}
+
+
+DECLARE_LOCATION_PARSER(invalid) {
+ error("unknown keyword '%s' in location '%s'", _tokens[0], _locParseCtxt.filename);
+}
+
+DECLARE_LOCATION_PARSER(endlocation) {
+ _locParseCtxt.end = true;
+}
+
+
+DECLARE_LOCATION_PARSER(location) {
+ // The parameter for location is 'location.mask'.
+ // If mask is not present, then it is assumed
+ // that path & mask are encoded in the background
+ // bitmap, otherwise a separate .msk file exists.
+
+ char *mask = strchr(_tokens[1], '.');
+ if (mask) {
+ mask[0] = '\0';
+ mask++;
+ }
+
+ strcpy(_location._name, _tokens[1]);
+ switchBackground(_location._name, mask);
+
+ if (_tokens[2][0] != '\0') {
+ _char._ani._left = atoi(_tokens[2]);
+ _char._ani._top = atoi(_tokens[3]);
+ }
+
+ if (_tokens[4][0] != '\0') {
+ _char._ani._frame = atoi(_tokens[4]);
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(disk) {
+ _disk->selectArchive(_tokens[1]);
+}
+
+
+DECLARE_LOCATION_PARSER(nodes) {
+ parseWalkNodes(*_locParseCtxt.script, _location._walkNodes);
+}
+
+
+DECLARE_LOCATION_PARSER(zone) {
+ parseZone(*_locParseCtxt.script, _zones, _tokens[1]);
+}
+
+
+DECLARE_LOCATION_PARSER(animation) {
+ parseAnimation(*_locParseCtxt.script, _animations, _tokens[1]);
+}
+
+
+DECLARE_LOCATION_PARSER(localflags) {
+ int _si = 1; // _localFlagNames[0] = 'visited'
+ while (_tokens[_si][0] != '\0') {
+ _localFlagNames->addData(_tokens[_si]);
+ _si++;
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(commands) {
+ parseCommands(*_locParseCtxt.script, _location._commands);
+}
+
+
+DECLARE_LOCATION_PARSER(acommands) {
+ parseCommands(*_locParseCtxt.script, _location._aCommands);
+}
+
+
+DECLARE_LOCATION_PARSER(flags) {
+ if ((_localFlags[_currentLocationIndex] & kFlagsVisited) == 0) {
+ // only for 1st visit
+ _localFlags[_currentLocationIndex] = 0;
+ int _si = 1;
+
+ do {
+ byte _al = _localFlagNames->lookup(_tokens[_si]);
+ _localFlags[_currentLocationIndex] |= 1 << (_al - 1);
+
+ _si++;
+ if (scumm_stricmp(_tokens[_si], "|")) break;
+ _si++;
+ } while (true);
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(comment) {
+ _location._comment = parseComment(*_locParseCtxt.script);
+}
+
+
+DECLARE_LOCATION_PARSER(endcomment) {
+ _location._endComment = parseComment(*_locParseCtxt.script);
+}
+
+
+DECLARE_LOCATION_PARSER(sound) {
+ if (getPlatform() == Common::kPlatformAmiga) {
+ strcpy(_locationSound, _tokens[1]);
+ _hasLocationSound = true;
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(music) {
+ if (getPlatform() == Common::kPlatformAmiga)
+ _soundMan->setMusicFile(_tokens[1]);
+}
+
+DECLARE_LOCATION_PARSER(redundant) {
+ warning("redundant '%s' line found in script '%s'", _tokens[0], _locParseCtxt.filename);
+}
+
+
+void Parallaction_ns::parseLocation(const char *filename) {
+ debugC(1, kDebugLocation, "parseLocation('%s')", filename);
+
+ 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;
+
+ pushParserTables(&_locationParsers, _locationStmt);
+
+ do {
+
+ fillBuffers(*script, true);
+
+ parseStatement();
+
+ } while (!_locParseCtxt.end);
+
+ popParserTables();
+
+ delete script;
+
+ // 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;
+}
+
+
+void Parallaction_ns::parseWalkNodes(Script& script, WalkNodeList &list) {
+
+ fillBuffers(script, true);
+ while (scumm_stricmp(_tokens[0], "ENDNODES")) {
+
+ if (!scumm_stricmp(_tokens[0], "COORD")) {
+
+ WalkNode *v4 = new WalkNode(
+ atoi(_tokens[1]) - _char._ani.width()/2,
+ atoi(_tokens[2]) - _char._ani.height()
+ );
+
+ list.push_front(v4);
+ }
+
+ fillBuffers(script, true);
+ }
+
+ return;
+
+}
+
+typedef OpcodeImpl<Parallaction_ns> OpcodeV1;
+#define INSTRUCTION_PARSER(sig) OpcodeV1(this, &Parallaction_ns::instParse_##sig)
+#define ZONE_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locZoneParse_##sig)
+#define ANIM_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locAnimParse_##sig)
+#define LOCATION_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locParse_##sig)
+#define COMMAND_PARSER(sig) OpcodeV1(this, &Parallaction_ns::cmdParse_##sig)
+
+void Parallaction_ns::initParsers() {
+
+ static const OpcodeV1 op0[] = {
+ INSTRUCTION_PARSER(defLocal), // invalid opcode -> local definition
+ INSTRUCTION_PARSER(animation), // on
+ INSTRUCTION_PARSER(animation), // off
+ INSTRUCTION_PARSER(x),
+ INSTRUCTION_PARSER(y),
+ INSTRUCTION_PARSER(z),
+ INSTRUCTION_PARSER(f),
+ INSTRUCTION_PARSER(loop),
+ INSTRUCTION_PARSER(null), // endloop
+ INSTRUCTION_PARSER(null), // show
+ INSTRUCTION_PARSER(inc),
+ INSTRUCTION_PARSER(inc), // dec
+ INSTRUCTION_PARSER(set),
+ INSTRUCTION_PARSER(put),
+ INSTRUCTION_PARSER(call),
+ INSTRUCTION_PARSER(null), // wait
+ INSTRUCTION_PARSER(animation), // start
+ INSTRUCTION_PARSER(sound),
+ INSTRUCTION_PARSER(move)
+ };
+
+ uint i;
+ for (i = 0; i < ARRAYSIZE(op0); i++)
+ _instructionParsers.push_back(&op0[i]);
+
+
+ static const OpcodeV1 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(simple), // quit
+ COMMAND_PARSER(move), // move
+ COMMAND_PARSER(animation), // stop
+ COMMAND_PARSER(endcommands), // endcommands
+ COMMAND_PARSER(endcommands) // endzone
+ };
+
+ for (i = 0; i < ARRAYSIZE(op2); i++)
+ _commandParsers.push_back(&op2[i]);
+
+
+ static const OpcodeV1 op4[] = {
+ LOCATION_PARSER(invalid),
+ LOCATION_PARSER(endlocation),
+ LOCATION_PARSER(location),
+ LOCATION_PARSER(disk),
+ LOCATION_PARSER(nodes),
+ LOCATION_PARSER(zone),
+ LOCATION_PARSER(animation),
+ LOCATION_PARSER(localflags),
+ LOCATION_PARSER(commands),
+ LOCATION_PARSER(acommands),
+ LOCATION_PARSER(flags),
+ LOCATION_PARSER(comment),
+ LOCATION_PARSER(endcomment),
+ LOCATION_PARSER(sound),
+ LOCATION_PARSER(music),
+ LOCATION_PARSER(redundant) // for redundant endanimation
+ };
+
+ for (i = 0; i < ARRAYSIZE(op4); i++)
+ _locationParsers.push_back(&op4[i]);
+
+ static const OpcodeV1 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)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op5); i++)
+ _locationZoneParsers.push_back(&op5[i]);
+
+ static const OpcodeV1 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)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op6); i++)
+ _locationAnimParsers.push_back(&op6[i]);
+
+ _currentOpcodes = 0;
+ _currentStatements = 0;
+
+}
+
+//
+// a comment can appear both at location and Zone levels
+// comments are displayed into rectangles on the screen
+//
+char *Parallaction_ns::parseComment(Script &script) {
+
+ char _tmp_comment[1000] = "\0";
+ char *v194;
+
+ do {
+ char v190[400];
+ v194 = script.readLine(v190, 400);
+
+ v194[strlen(v194)-1] = '\0';
+ if (!scumm_stricmp(v194, "endtext"))
+ break;
+
+ strcat(_tmp_comment, v194);
+ strcat(_tmp_comment, " ");
+ } while (true);
+
+ v194 = strdup(_tmp_comment);
+ _tmp_comment[0] = '\0';
+
+ return v194;
+}
+
+
+DECLARE_ZONE_PARSER(invalid) {
+ error("unknown statement '%s' in zone %s", _tokens[0], _locZoneParseCtxt.z->_label._text);
+}
+
+DECLARE_ZONE_PARSER(endzone) {
+ popParserTables();
+}
+
+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);
+ }
+
+ popParserTables();
+}
+
+
+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_ns::parseZone(Script &script, ZoneList &list, char *name) {
+
+ if (findZone(name)) {
+ while (scumm_stricmp(_tokens[0], "endzone")) {
+ fillBuffers(script, true);
+ }
+ return;
+ }
+
+ Zone *z = new Zone;
+
+ z->_label._text = strdup(name);
+
+ _locZoneParseCtxt.z = z;
+ _locZoneParseCtxt.end = false;
+ _locZoneParseCtxt.script = &script;
+
+ list.push_front(z);
+
+ pushParserTables(&_locationZoneParsers, _locationZoneStmt);
+
+ return;
+}
+
+
+void Parallaction_ns::parseZoneTypeBlock(Script &script, Zone *z) {
+// printf("parseZoneTypeBlock()");
+
+ TypeData *u = &z->u;
+
+ switch (z->_type & 0xFFFF) {
+ case kZoneExamine: // examine Zone alloc
+ u->examine = new ExamineData;
+ break;
+
+ case kZoneDoor: // door Zone alloc
+ u->door = new DoorData;
+ break;
+
+ case kZoneGet: // get Zone alloc
+ u->get = new GetData;
+ break;
+
+ case kZoneMerge: // merge Zone alloc
+ u->merge = new MergeData;
+ break;
+
+ case kZoneHear: // hear Zone alloc
+ u->hear = new HearData;
+ break;
+
+ case kZoneSpeak: // speak Zone alloc
+ u->speak = new SpeakData;
+ break;
+
+ }
+
+ char vC8[PATH_LEN];
+
+// printf("type = %x", z->_type);
+
+ do {
+
+ switch (z->_type & 0xFFFF) {
+ case kZoneExamine: // examine Zone init
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ u->examine->_filename = strdup(_tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "desc")) {
+ u->examine->_description = parseComment(script);
+ }
+ break;
+
+ case kZoneDoor: // door Zone init
+ if (!scumm_stricmp(_tokens[0], "slidetext")) {
+ strcpy(_slideText[0], _tokens[1]);
+// printf("%s\t", _slideText[0]);
+ strcpy(_slideText[1], _tokens[2]);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "location")) {
+ u->door->_location = strdup(_tokens[1]);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+// printf("file: '%s'", _tokens[0]);
+
+ strcpy(vC8, _tokens[1]);
+
+ u->door->_cnv = _disk->loadFrames(vC8);
+ uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+
+ u->door->_background = (byte*)malloc(u->door->_cnv->_width * u->door->_cnv->_height);
+ _gfx->backupDoorBackground(u->door, z->_left, z->_top);
+
+ _gfx->flatBlitCnv(u->door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "startpos")) {
+ u->door->_startPos.x = atoi(_tokens[1]);
+ u->door->_startPos.y = atoi(_tokens[2]);
+ u->door->_startFrame = atoi(_tokens[3]);
+ }
+ break;
+
+ case kZoneGet: // get Zone init
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ strcpy(vC8, _tokens[1]);
+ u->get->_cnv = _disk->loadStatic(vC8);
+ u->get->_backup = (byte*)malloc(u->get->_cnv->w*u->get->_cnv->h);
+
+ if ((z->_flags & kFlagsRemove) == 0) {
+ _gfx->backupGetBackground(u->get, z->_left, z->_top);
+ _gfx->flatBlitCnv(u->get->_cnv, z->_left, z->_top, Gfx::kBitBack);
+ }
+ }
+
+ if (!scumm_stricmp(_tokens[0], "icon")) {
+ u->get->_icon = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+ break;
+
+ case kZoneMerge: // merge Zone init
+ if (!scumm_stricmp(_tokens[0], "obj1")) {
+ u->merge->_obj1 = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "obj2")) {
+ u->merge->_obj2 = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "newobj")) {
+ u->merge->_obj3 = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+ break;
+
+ case kZoneHear: // hear Zone init
+ if (!scumm_stricmp(_tokens[0], "sound")) {
+ strcpy(u->hear->_name, _tokens[1]);
+ z->u.hear->_channel = atoi(_tokens[2]);
+ }
+ if (!scumm_stricmp(_tokens[0], "freq")) {
+ z->u.hear->_freq = atoi(_tokens[1]);
+ }
+ break;
+
+ case kZoneSpeak: // speak Zone init
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ strcpy(u->speak->_name, _tokens[1]);
+// printf("speak file name: %s", u.speak._name);
+ }
+ if (!scumm_stricmp(_tokens[0], "Dialogue")) {
+ u->speak->_dialogue = parseDialogue(script);
+ }
+ break;
+ }
+
+ fillBuffers(script, true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ return;
+}
+
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp
index d8dbd35816..bd583155db 100644
--- a/engines/parallaction/staticres.cpp
+++ b/engines/parallaction/staticres.cpp
@@ -434,9 +434,6 @@ const char *_instructionNamesRes_br[] = {
"mul",
"div",
"if",
- "ifeq",
- "iflt",
- "ifgt",
"endif",
"stop"
};
@@ -446,7 +443,7 @@ const char *_commandsNamesRes_br[] = {
"clear",
"start",
"speak",
- "get"
+ "get",
"location",
"open",
"close",
@@ -482,7 +479,10 @@ const char *_commandsNamesRes_br[] = {
"dummy",
"return",
"onsave",
- "offsave"
+ "offsave",
+ "endcommands",
+ "ifchar",
+ "endif"
};
const char *_callableNamesRes_br[] = {
@@ -514,6 +514,52 @@ const char *_audioCommandsNamesRes_br[] = {
"loop"
};
+const char *_locationStmtRes_br[] = {
+ "character",
+ "endlocation",
+ "ifchar",
+ "endif",
+ "location",
+ "mask",
+ "path",
+ "disk",
+ "localflags",
+ "commands",
+ "escape",
+ "acommands",
+ "flags",
+ "comment",
+ "endcomment",
+ "zone",
+ "animation",
+ "zeta",
+ "music",
+ "sound"
+};
+
+const char *_locationZoneStmtRes_br[] = {
+ "endzone",
+ "limits",
+ "moveto",
+ "type",
+ "commands",
+ "label",
+ "flags"
+};
+
+const char *_locationAnimStmtRes_br[] = {
+ "endanimation",
+ "endzone",
+ "script",
+ "commands",
+ "type",
+ "label",
+ "flags",
+ "file",
+ "position",
+ "moveto"
+};
+
const char *_dinoName = "dino";
const char *_donnaName = "donna";
const char *_doughName = "dough";
@@ -636,6 +682,9 @@ void Parallaction_br::initResources() {
_zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_br), _zoneTypeNamesRes_br);
_commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_br), _commandsNamesRes_br);
_audioCommandsNames = new Table(ARRAYSIZE(_audioCommandsNamesRes_br), _audioCommandsNamesRes_br);
+ _locationStmt = new Table(ARRAYSIZE(_locationStmtRes_br), _locationStmtRes_br);
+ _locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_br), _locationZoneStmtRes_br);
+ _locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_br), _locationAnimStmtRes_br);
// TODO: make sure there are 120 max locations in Big Red Adventure
_localFlagNames = new Table(120);
diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp
deleted file mode 100644
index 64ef933167..0000000000
--- a/engines/parallaction/zone.cpp
+++ /dev/null
@@ -1,697 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-
-#include "common/stdafx.h"
-
-#include "parallaction/parallaction.h"
-#include "parallaction/sound.h"
-
-namespace Parallaction {
-
-
-
-
-Zone *Parallaction::findZone(const char *name) {
-
- 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) {
- popParserTables();
-}
-
-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);
- }
-
- popParserTables();
-}
-
-
-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)\n", name);
-
- if (findZone(name)) {
- while (scumm_stricmp(_tokens[0], "endzone")) {
- fillBuffers(script, true);
- }
- return;
- }
-
- Zone *z = new Zone;
-
- z->_label._text = strdup(name);
-
- _locZoneParseCtxt.z = z;
- _locZoneParseCtxt.end = false;
- _locZoneParseCtxt.script = &script;
-
- list.push_front(z);
-
- pushParserTables(_locationZoneParsers, _locationZoneStmt);
-
- return;
-}
-
-void Parallaction::freeZones() {
- debugC(1, kDebugLocation, "freeZones: kEngineQuit = %i", _engineFlags & kEngineQuit);
-
- ZoneList::iterator it = _zones.begin();
-
- while ( it != _zones.end() ) {
-
- Zone* z = *it;
-
- // WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
- // instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
- // but we need to check it separately here. The same workaround is applied in hitZone.
- if (((z->_top == -1) ||
- ((z->_left == -2) && (
- (((z->_type & 0xFFFF) == kZoneMerge) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj1)) != 0) || (isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj2)) != 0))) ||
- (((z->_type & 0xFFFF) == kZoneGet) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.get->_icon)) != 0)))
- ))) &&
- ((_engineFlags & kEngineQuit) == 0)) {
-
- debugC(1, kDebugLocation, "freeZones preserving zone '%s'", z->_label._text);
-
- it++;
-
- } else
-
- it = _zones.erase(it);
-
- }
-
- return;
-}
-
-
-
-
-
-
-
-
-
-void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
-// printf("parseZoneTypeBlock()");
-
- TypeData *u = &z->u;
-
- switch (z->_type & 0xFFFF) {
- case kZoneExamine: // examine Zone alloc
- u->examine = new ExamineData;
- break;
-
- case kZoneDoor: // door Zone alloc
- u->door = new DoorData;
- break;
-
- case kZoneGet: // get Zone alloc
- u->get = new GetData;
- break;
-
- case kZoneMerge: // merge Zone alloc
- u->merge = new MergeData;
- break;
-
- case kZoneHear: // hear Zone alloc
- u->hear = new HearData;
- break;
-
- case kZoneSpeak: // speak Zone alloc
- u->speak = new SpeakData;
- break;
-
- }
-
- char vC8[PATH_LEN];
-
-// printf("type = %x", z->_type);
-
- do {
-
- switch (z->_type & 0xFFFF) {
- case kZoneExamine: // examine Zone init
- if (!scumm_stricmp(_tokens[0], "file")) {
- u->examine->_filename = strdup(_tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "desc")) {
- u->examine->_description = parseComment(script);
- }
- break;
-
- case kZoneDoor: // door Zone init
- if (!scumm_stricmp(_tokens[0], "slidetext")) {
- strcpy(_slideText[0], _tokens[1]);
-// printf("%s\t", _slideText[0]);
- strcpy(_slideText[1], _tokens[2]);
- }
-
- if (!scumm_stricmp(_tokens[0], "location")) {
- u->door->_location = strdup(_tokens[1]);
- }
-
- if (!scumm_stricmp(_tokens[0], "file")) {
-// printf("file: '%s'", _tokens[0]);
-
- strcpy(vC8, _tokens[1]);
-
- u->door->_cnv = _disk->loadFrames(vC8);
- uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
-
- u->door->_background = (byte*)malloc(u->door->_cnv->_width * u->door->_cnv->_height);
- _gfx->backupDoorBackground(u->door, z->_left, z->_top);
-
- _gfx->flatBlitCnv(u->door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
- }
-
- if (!scumm_stricmp(_tokens[0], "startpos")) {
- u->door->_startPos.x = atoi(_tokens[1]);
- u->door->_startPos.y = atoi(_tokens[2]);
- u->door->_startFrame = atoi(_tokens[3]);
- }
- break;
-
- case kZoneGet: // get Zone init
- if (!scumm_stricmp(_tokens[0], "file")) {
- strcpy(vC8, _tokens[1]);
- u->get->_cnv = _disk->loadStatic(vC8);
- u->get->_backup = (byte*)malloc(u->get->_cnv->w*u->get->_cnv->h);
-
- if ((z->_flags & kFlagsRemove) == 0) {
- _gfx->backupGetBackground(u->get, z->_left, z->_top);
- _gfx->flatBlitCnv(u->get->_cnv, z->_left, z->_top, Gfx::kBitBack);
- }
- }
-
- if (!scumm_stricmp(_tokens[0], "icon")) {
- u->get->_icon = 4 + _objectsNames->lookup(_tokens[1]);
- }
- break;
-
- case kZoneMerge: // merge Zone init
- if (!scumm_stricmp(_tokens[0], "obj1")) {
- u->merge->_obj1 = 4 + _objectsNames->lookup(_tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "obj2")) {
- u->merge->_obj2 = 4 + _objectsNames->lookup(_tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "newobj")) {
- u->merge->_obj3 = 4 + _objectsNames->lookup(_tokens[1]);
- }
- break;
-
- case kZoneHear: // hear Zone init
- if (!scumm_stricmp(_tokens[0], "sound")) {
- strcpy(u->hear->_name, _tokens[1]);
- z->u.hear->_channel = atoi(_tokens[2]);
- }
- if (!scumm_stricmp(_tokens[0], "freq")) {
- z->u.hear->_freq = atoi(_tokens[1]);
- }
- break;
-
- case kZoneSpeak: // speak Zone init
- if (!scumm_stricmp(_tokens[0], "file")) {
- strcpy(u->speak->_name, _tokens[1]);
-// printf("speak file name: %s", u.speak._name);
- }
- if (!scumm_stricmp(_tokens[0], "Dialogue")) {
- u->speak->_dialogue = parseDialogue(script);
- }
- break;
- }
-
- fillBuffers(script, true);
- } while (scumm_stricmp(_tokens[0], "endzone"));
-
- return;
-}
-
-// displays character head commenting an examined object
-//
-// works on the frontbuffer
-//
-void Parallaction::displayCharacterComment(ExamineData *data) {
- if (data->_description == NULL) return;
-
- // NOTE: saving visible screen before displaying comment allows
- // to restore the exact situation after the comment is deleted.
- // This means animations are restored in the exact position as
- // they were, thus avoiding clipping effect as signalled in
- // BUG item #1762614.
- _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
-
- _gfx->setFont(_dialogueFont);
- _gfx->flatBlitCnv(_char._talk, 0, 190, 80, Gfx::kBitFront);
-
- int16 v26, v28;
- _gfx->getStringExtent(data->_description, 130, &v28, &v26);
- Common::Rect r(v28, v26);
- r.moveTo(140, 10);
- _gfx->drawBalloon(r, 0);
- _gfx->displayWrappedString(data->_description, 140, 10, 0, 130);
-
- waitUntilLeftClick();
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _gfx->updateScreen();
-
- return;
-}
-
-//
-// ZONE TYPE: EXAMINE
-//
-
-// display detail view of an item (and eventually comments)
-//
-// works on the frontbuffer
-//
-
-void Parallaction::displayItemComment(ExamineData *data) {
-
- if (data->_description == NULL) return;
-
- _gfx->setHalfbriteMode(true);
-
- char v68[PATH_LEN];
- strcpy(v68, data->_filename);
- data->_cnv = _disk->loadStatic(v68);
- _gfx->flatBlitCnv(data->_cnv, 140, (_screenHeight - data->_cnv->h)/2, Gfx::kBitFront);
- delete data->_cnv;
-
- int16 v6A = 0, v6C = 0;
-
- _gfx->setFont(_dialogueFont);
- _gfx->getStringExtent(data->_description, 130, &v6C, &v6A);
- Common::Rect r(v6C, v6A);
- r.moveTo(0, 90);
- _gfx->drawBalloon(r, 0);
- _gfx->flatBlitCnv(_char._head, 100, 152, Gfx::kBitFront);
- _gfx->displayWrappedString(data->_description, 0, 90, 0, 130);
-
- jobEraseAnimations((void*)1, NULL);
- _gfx->updateScreen();
-
- waitUntilLeftClick();
-
- _gfx->setHalfbriteMode(false);
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _gfx->updateScreen();
-
- return;
-}
-
-
-
-uint16 Parallaction::runZone(Zone *z) {
- debugC(3, kDebugLocation, "runZone (%s)", z->_label._text);
-
- uint16 subtype = z->_type & 0xFFFF;
-
- debugC(3, kDebugLocation, "type = %x, object = %x", subtype, (z->_type & 0xFFFF0000) >> 16);
- switch(subtype) {
-
- case kZoneExamine:
- if (z->u.examine->_filename) {
- displayItemComment(z->u.examine);
- } else {
- displayCharacterComment(z->u.examine);
- }
- break;
-
- case kZoneGet:
- if (z->_flags & kFlagsFixed) break;
- if (pickupItem(z) != 0) {
- return 1;
- }
- z->_flags |= kFlagsRemove;
- break;
-
- case kZoneDoor:
- if (z->_flags & kFlagsLocked) break;
- z->_flags ^= kFlagsClosed;
- if (z->u.door->_cnv == NULL) break;
- addJob(&jobToggleDoor, z, kPriority18 );
- break;
-
- case kZoneHear:
- _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
- break;
-
- case kZoneSpeak:
- runDialogue(z->u.speak);
- break;
-
- }
-
- debugC(3, kDebugLocation, "runZone completed");
-
- return 0;
-}
-
-//
-// ZONE TYPE: DOOR
-//
-void jobToggleDoor(void *parm, Job *j) {
-
- static byte count = 0;
-
- Zone *z = (Zone*)parm;
-
- if (z->u.door->_cnv) {
- Common::Rect r(z->_left, z->_top, z->_left+z->u.door->_cnv->_width, z->_top+z->u.door->_cnv->_height);
-
- uint16 _ax = (z->_flags & kFlagsClosed ? 1 : 0);
- _vm->_gfx->restoreDoorBackground(r, z->u.door->_cnv->getFramePtr(_ax), z->u.door->_background);
-
- _ax = (z->_flags & kFlagsClosed ? 0 : 1);
- _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
- _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBit2);
- }
-
- count++;
- if (count == 2) {
- j->_finished = 1;
- count = 0;
- }
-
- return;
-}
-
-
-
-//
-// ZONE TYPE: GET
-//
-
-int16 Parallaction::pickupItem(Zone *z) {
- int r = addInventoryItem(z->u.get->_icon);
- if (r == 0)
- addJob(&jobRemovePickedItem, z, kPriority17 );
-
- return r;
-}
-
-void jobRemovePickedItem(void *parm, Job *j) {
-
- Zone *z = (Zone*)parm;
-
- static uint16 count = 0;
-
- if (z->u.get->_cnv) {
- Common::Rect r(z->_left, z->_top, z->_left + z->u.get->_cnv->w, z->_top + z->u.get->_cnv->h);
-
- _vm->_gfx->restoreGetBackground(r, z->u.get->_backup);
- }
-
- count++;
- if (count == 2) {
- count = 0;
- j->_finished = 1;
- }
-
- return;
-}
-
-void jobDisplayDroppedItem(void *parm, Job *j) {
-// printf("jobDisplayDroppedItem...");
-
- Zone *z = (Zone*)parm;
-
- if (z->u.get->_cnv) {
- if (j->_count == 0) {
- _vm->_gfx->backupGetBackground(z->u.get, z->_left, z->_top);
- }
-
- _vm->_gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBitBack);
- _vm->_gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBit2);
- }
-
- j->_count++;
- if (j->_count == 2) {
- j->_count = 0;
- j->_finished = 1;
- }
-
-// printf("done");
-
- return;
-}
-
-
-
-
-Zone *Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
-// printf("hitZone(%i, %i, %i)", type, x, y);
-
- uint16 _di = y;
- uint16 _si = x;
-
- for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) {
-// printf("Zone name: %s", z->_name);
-
- Zone *z = *it;
-
- if (z->_flags & kFlagsRemove) continue;
-
- Common::Rect r;
- z->getRect(r);
- r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
- r.bottom++;
-
- r.grow(-1); // allows some tolerance for mouse click
-
- if (!r.contains(_si, _di)) {
-
- // out of Zone, so look for special values
- if ((z->_left == -2) || (z->_left == -3)) {
-
- // WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
- // instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
- // but we need to check it separately here. The same workaround is applied in freeZones.
- if ((((z->_type & 0xFFFF) == kZoneMerge) && (((_si == z->u.merge->_obj1) && (_di == z->u.merge->_obj2)) || ((_si == z->u.merge->_obj2) && (_di == z->u.merge->_obj1)))) ||
- (((z->_type & 0xFFFF) == kZoneGet) && ((_si == z->u.get->_icon) || (_di == z->u.get->_icon)))) {
-
- // special Zone
- if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
- return z;
- if (z->_type == type)
- return z;
- if ((z->_type & 0xFFFF0000) == type)
- return z;
-
- }
- }
-
- if (z->_left != -1)
- continue;
- if (_si < _char._ani._left)
- continue;
- if (_si > (_char._ani._left + _char._ani.width()))
- continue;
- if (_di < _char._ani._top)
- continue;
- if (_di > (_char._ani._top + _char._ani.height()))
- continue;
-
- }
-
- // normal Zone
- if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
- return z;
- if (z->_type == type)
- return z;
- if ((z->_type & 0xFFFF0000) == type)
- return z;
-
- }
-
-
- int16 _a, _b, _c, _d, _e, _f;
- for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++) {
-
- Animation *a = *it;
-
- _a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
- _e = ((_si >= a->_left + a->width()) || (_si <= a->_left)) ? 0 : 1; // _e: horizontal range
- _f = ((_di >= a->_top + a->height()) || (_di <= a->_top)) ? 0 : 1; // _f: vertical range
-
- _b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
- _c = (a->_type & 0xFFFF0000) ? 0 : 1; // _c: Animation is not an object
- _d = ((a->_type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
-
- if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) {
-
- return a;
-
- }
-
- }
-
- return NULL;
-}
-
-
-Zone::Zone() {
- _left = _top = _right = _bottom = 0;
-
- _type = 0;
- _flags = 0;
-}
-
-Zone::~Zone() {
-// printf("~Zone(%s)\n", _label._text);
-
- _label._cnv.free();
-
- switch (_type & 0xFFFF) {
- case kZoneExamine:
- free(u.examine->_filename);
- free(u.examine->_description);
- delete u.examine;
- break;
-
- case kZoneDoor:
- free(u.door->_location);
- free(u.door->_background);
- if (u.door->_cnv)
- delete u.door->_cnv;
- delete u.door;
- break;
-
- case kZoneSpeak:
- delete u.speak->_dialogue;
- delete u.speak;
- break;
-
- case kZoneGet:
- free(u.get->_backup);
- if (u.get->_cnv) {
- u.get->_cnv->free();
- delete u.get->_cnv;
- }
- delete u.get;
- break;
-
- case kZoneHear:
- delete u.hear;
- break;
-
- case kZoneMerge:
- delete u.merge;
- break;
-
- default:
- break;
- }
-}
-
-void Zone::getRect(Common::Rect& r) const {
- r.left = _left;
- r.right = _right;
- r.top = _top;
- r.bottom = _bottom;
-}
-
-void Zone::translate(int16 x, int16 y) {
- _left += x;
- _right += x;
- _top += y;
- _bottom += y;
-}
-
-uint16 Zone::width() const {
- return _right - _left;
-}
-
-uint16 Zone::height() const {
- return _bottom - _top;
-}
-
-Label::Label() {
- _text = NULL;
-}
-
-Label::~Label() {
- _cnv.free();
- if (_text)
- free(_text);
-}
-
-
-} // namespace Parallaction