diff options
-rw-r--r-- | engines/parallaction/exec_br.cpp | 484 | ||||
-rw-r--r-- | engines/parallaction/module.mk | 2 | ||||
-rw-r--r-- | engines/parallaction/parallaction.h | 4 | ||||
-rw-r--r-- | engines/parallaction/parser_br.cpp | 764 |
4 files changed, 1252 insertions, 2 deletions
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp new file mode 100644 index 0000000000..9c174dd036 --- /dev/null +++ b/engines/parallaction/exec_br.cpp @@ -0,0 +1,484 @@ + +#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_PROCESS 17 +#define INST_MOVE 18 +#define INST_COLOR 19 +#define INST_SOUND 20 +#define INST_MASK 21 +#define INST_PRINT 22 +#define INST_TEXT 23 +#define INST_MUL 24 +#define INST_DIV 25 +#define INST_IF 26 +#define INST_IFEQ 27 +#define INST_IFLT 28 +#define INST_IFGT 29 +#define INST_ENDIF 30 +#define INST_STOP 31 + + +typedef OpcodeImpl<Parallaction_br> OpcodeV2; +#define COMMAND_OPCODE(op) OpcodeV2(this, &Parallaction_br::cmdOp_##op) +#define DECLARE_COMMAND_OPCODE(op) void Parallaction_br::cmdOp_##op() + +#define INSTRUCTION_OPCODE(op) OpcodeV2(this, &Parallaction_br::instOp_##op) +#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_br::instOp_##op() + + +DECLARE_COMMAND_OPCODE(location) { + warning("Parallaction_br::cmdOp_location command not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(open) { + warning("Parallaction_br::cmdOp_open command not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(close) { + warning("Parallaction_br::cmdOp_close not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(on) { + warning("Parallaction_br::cmdOp_on not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(off) { + warning("Parallaction_br::cmdOp_off not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(call) { + callFunction(_cmdRunCtxt.cmd->u._callable, _cmdRunCtxt.z); +} + + +DECLARE_COMMAND_OPCODE(drop) { + warning("Parallaction_br::cmdOp_drop not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(move) { + warning("Parallaction_br::cmdOp_move not yet implemented"); +} + +DECLARE_COMMAND_OPCODE(start) { + warning("Parallaction_br::cmdOp_start not yet implemented"); +} + +DECLARE_COMMAND_OPCODE(stop) { + warning("Parallaction_br::cmdOp_stop not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(character) { + warning("Parallaction_br::cmdOp_character not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(followme) { + warning("Parallaction_br::cmdOp_followme not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(onmouse) { + showCursor(true); +} + + +DECLARE_COMMAND_OPCODE(offmouse) { + showCursor(false); +} + + +DECLARE_COMMAND_OPCODE(add) { + warning("Parallaction_br::cmdOp_add not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(leave) { + warning("Parallaction_br::cmdOp_leave not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(inc) { + _counters[_cmdRunCtxt.cmd->u._lvalue] += _cmdRunCtxt.cmd->u._rvalue; +} + + +DECLARE_COMMAND_OPCODE(dec) { + _counters[_cmdRunCtxt.cmd->u._lvalue] -= _cmdRunCtxt.cmd->u._rvalue; +} + + +DECLARE_COMMAND_OPCODE(ifeq) { + if (_counters[_cmdRunCtxt.cmd->u._lvalue] == _cmdRunCtxt.cmd->u._rvalue) { + _localFlags[_currentLocationIndex] |= kFlagsTestTrue; + } else { + _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue; + } +} + +DECLARE_COMMAND_OPCODE(iflt) { + if (_counters[_cmdRunCtxt.cmd->u._lvalue] < _cmdRunCtxt.cmd->u._rvalue) { + _localFlags[_currentLocationIndex] |= kFlagsTestTrue; + } else { + _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue; + } +} + +DECLARE_COMMAND_OPCODE(ifgt) { + if (_counters[_cmdRunCtxt.cmd->u._lvalue] > _cmdRunCtxt.cmd->u._rvalue) { + _localFlags[_currentLocationIndex] |= kFlagsTestTrue; + } else { + _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue; + } +} + + +DECLARE_COMMAND_OPCODE(let) { + _counters[_cmdRunCtxt.cmd->u._lvalue] = _cmdRunCtxt.cmd->u._rvalue; +} + + +DECLARE_COMMAND_OPCODE(music) { + warning("Parallaction_br::cmdOp_music not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(fix) { + _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsFixed; +} + + +DECLARE_COMMAND_OPCODE(unfix) { + _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed; +} + + +DECLARE_COMMAND_OPCODE(zeta) { + _zeta0 = _cmdRunCtxt.cmd->u._zeta0; + _zeta1 = _cmdRunCtxt.cmd->u._zeta1; + _zeta2 = _cmdRunCtxt.cmd->u._zeta2; +} + + +DECLARE_COMMAND_OPCODE(scroll) { + warning("Parallaction_br::cmdOp_scroll not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(swap) { + warning("Parallaction_br::cmdOp_swap not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(give) { + warning("Parallaction_br::cmdOp_give not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(text) { + warning("Parallaction_br::cmdOp_text not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(part) { + warning("Parallaction_br::cmdOp_part not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(testsfx) { + warning("Parallaction_br::cmdOp_testsfx not completely implemented"); + _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue; // should test if sfx are enabled +} + + +DECLARE_COMMAND_OPCODE(ret) { + warning("Parallaction_br::cmdOp_ret not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(onsave) { + warning("Parallaction_br::cmdOp_onsave not yet implemented"); +} + + +DECLARE_COMMAND_OPCODE(offsave) { + warning("Parallaction_br::cmdOp_offsave not yet implemented"); +} + + + + +DECLARE_INSTRUCTION_OPCODE(on) { + warning("Parallaction_br::instOp_on not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(off) { + warning("Parallaction_br::instOp_off not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(set) { + Instruction *inst = *_instRunCtxt.inst; + + int16 rvalue = inst->_opB.getRValue(); + int16* lvalue = inst->_opA.getLValue(); + + *lvalue = rvalue; + +} + + +DECLARE_INSTRUCTION_OPCODE(loop) { + Instruction *inst = *_instRunCtxt.inst; + + _instRunCtxt.a->_program->_loopCounter = inst->_opB.getRValue(); + _instRunCtxt.a->_program->_loopStart = _instRunCtxt.inst; +} + + +DECLARE_INSTRUCTION_OPCODE(inc) { + Instruction *inst = *_instRunCtxt.inst; + + int16 rvalue = inst->_opB.getRValue(); + + if (inst->_flags & kInstMod) { // mod + int16 _bx = (rvalue > 0 ? rvalue : -rvalue); + if (_instRunCtxt.modCounter % _bx != 0) return; + + rvalue = (rvalue > 0 ? 1 : -1); + } + + int16 *lvalue = inst->_opA.getLValue(); + + switch (inst->_index) { + case INST_INC: + *lvalue += rvalue; + break; + + case INST_DEC: + *lvalue -= rvalue; + break; + + case INST_MUL: + *lvalue *= rvalue; + break; + + case INST_DIV: + *lvalue /= rvalue; + break; + + default: + error("This should never happen. Report immediately");; + } + + if (inst->_opA._flags & kParaLocal) { + wrapLocalVar(inst->_opA._local); + } + +} + + +DECLARE_INSTRUCTION_OPCODE(put) { + warning("Parallaction_br::instOp_put not yet implemented"); +} + + + +DECLARE_INSTRUCTION_OPCODE(wait) { + warning("Parallaction_br::instOp_wait not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(start) { + (*_instRunCtxt.inst)->_z->_flags |= kFlagsActing; +} + + +DECLARE_INSTRUCTION_OPCODE(process) { + _activeZone2 = (*_instRunCtxt.inst)->_z; +} + + +DECLARE_INSTRUCTION_OPCODE(move) { + warning("Parallaction_br::instOp_move not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(color) { + Instruction *inst = *_instRunCtxt.inst; + + int16 entry = inst->_opB.getRValue(); + + _gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]); + +} + + +DECLARE_INSTRUCTION_OPCODE(mask) { + Instruction *inst = *_instRunCtxt.inst; + + _gfx->_bgLayers[0] = inst->_opA.getRValue(); + _gfx->_bgLayers[1] = inst->_opB.getRValue(); + _gfx->_bgLayers[2] = inst->_opC.getRValue(); +} + + +DECLARE_INSTRUCTION_OPCODE(print) { + warning("Parallaction_br::instOp_print not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(text) { + warning("Parallaction_br::instOp_text not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(ifeq) { + warning("Parallaction_br::instOp_ifeq not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(iflt) { + warning("Parallaction_br::instOp_iflt not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(ifgt) { + warning("Parallaction_br::instOp_ifgt not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(endif) { + warning("Parallaction_br::instOp_endif not yet implemented"); +} + + +DECLARE_INSTRUCTION_OPCODE(stop) { + warning("Parallaction_br::instOp_stop not yet implemented"); +} + +DECLARE_INSTRUCTION_OPCODE(endscript) { + warning("Parallaction_br::instOp_endscript not yet implemented"); +} + +void Parallaction_br::initOpcodes() { + + static const OpcodeV2 op1[] = { + 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), + COMMAND_OPCODE(character), + COMMAND_OPCODE(followme), + COMMAND_OPCODE(onmouse), + COMMAND_OPCODE(offmouse), + COMMAND_OPCODE(add), + COMMAND_OPCODE(leave), + COMMAND_OPCODE(inc), + COMMAND_OPCODE(dec), + COMMAND_OPCODE(ifeq), + COMMAND_OPCODE(iflt), + COMMAND_OPCODE(ifgt), + COMMAND_OPCODE(let), + COMMAND_OPCODE(music), + COMMAND_OPCODE(fix), + COMMAND_OPCODE(unfix), + COMMAND_OPCODE(zeta), + COMMAND_OPCODE(scroll), + COMMAND_OPCODE(swap), + COMMAND_OPCODE(give), + COMMAND_OPCODE(text), + COMMAND_OPCODE(part), + COMMAND_OPCODE(testsfx), + COMMAND_OPCODE(ret), + COMMAND_OPCODE(onsave), + COMMAND_OPCODE(offsave) + }; + + uint i; + for (i = 0; i < ARRAYSIZE(op1); i++) + _commandOpcodes.push_back(&op1[i]); + + + static const OpcodeV2 op2[] = { + 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), // show + INSTRUCTION_OPCODE(inc), + INSTRUCTION_OPCODE(inc), // dec + INSTRUCTION_OPCODE(set), + INSTRUCTION_OPCODE(put), + INSTRUCTION_OPCODE(call), + INSTRUCTION_OPCODE(wait), + INSTRUCTION_OPCODE(start), + INSTRUCTION_OPCODE(process), + INSTRUCTION_OPCODE(move), + INSTRUCTION_OPCODE(color), + INSTRUCTION_OPCODE(process), // sound + INSTRUCTION_OPCODE(mask), + INSTRUCTION_OPCODE(print), + INSTRUCTION_OPCODE(text), + INSTRUCTION_OPCODE(inc), // mul + INSTRUCTION_OPCODE(inc), // div + INSTRUCTION_OPCODE(ifeq), + INSTRUCTION_OPCODE(iflt), + INSTRUCTION_OPCODE(ifgt), + INSTRUCTION_OPCODE(endif), + INSTRUCTION_OPCODE(stop), + INSTRUCTION_OPCODE(endscript) + }; + + for (i = 0; i < ARRAYSIZE(op2); i++) + _instructionOpcodes.push_back(&op2[i]); + + +} + + +} // namespace Parallaction diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index 61e293ed5b..56eaddac95 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -8,6 +8,7 @@ MODULE_OBJS := \ dialogue.o \ disk_br.o \ disk_ns.o \ + exec_br.o \ exec_ns.o \ font.o \ graphics.o \ @@ -18,6 +19,7 @@ MODULE_OBJS := \ parallaction_br.o \ parallaction_ns.o \ parser.o \ + parser_br.o \ parser_ns.o \ saveload.o \ sound.o \ diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 4fc9f64537..cc91d4bdf7 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -871,7 +871,7 @@ private: void _c_password(void*); const Callable *_callables; -/* + DECLARE_UNQUALIFIED_LOCATION_PARSER(location); DECLARE_UNQUALIFIED_LOCATION_PARSER(zone); DECLARE_UNQUALIFIED_LOCATION_PARSER(animation); @@ -976,7 +976,7 @@ private: DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif); DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop); DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript); -*/ + }; // FIXME: remove global diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp new file mode 100644 index 0000000000..2e51c99851 --- /dev/null +++ b/engines/parallaction/parser_br.cpp @@ -0,0 +1,764 @@ +#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 CMD_CHARACTER 17 +#define CMD_FOLLOWME 18 +#define CMD_ONMOUSE 19 +#define CMD_OFFMOUSE 20 +#define CMD_ADD 21 +#define CMD_LEAVE 22 +#define CMD_INC 23 +#define CMD_DEC 24 +#define CMD_TEST 25 +#define CMD_TEST_GT 26 +#define CMD_TEST_LT 27 +#define CMD_LET 28 +#define CMD_MUSIC 29 +#define CMD_FIX 30 +#define CMD_UNFIX 31 +#define CMD_ZETA 32 +#define CMD_SCROLL 33 +#define CMD_SWAP 34 +#define CMD_GIVE 35 +#define CMD_TEXT 36 +#define CMD_PART 37 +#define CMD_TEST_SFX 38 +#define CMD_RETURN 39 +#define CMD_ONSAVE 40 +#define CMD_OFFSAVE 41 + + +#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_PROCESS 17 +#define INST_MOVE 18 +#define INST_COLOR 19 +#define INST_SOUND 20 +#define INST_MASK 21 +#define INST_PRINT 22 +#define INST_TEXT 23 +#define INST_MUL 24 +#define INST_DIV 25 +#define INST_IF 26 +#define INST_IFEQ 27 +#define INST_IFLT 28 +#define INST_IFGT 29 +#define INST_ENDIF 30 +#define INST_STOP 31 + +#define DECLARE_ZONE_PARSER(sig) void Parallaction_br::locZoneParse_##sig() +#define DECLARE_ANIM_PARSER(sig) void Parallaction_br::locAnimParse_##sig() +#define DECLARE_COMMAND_PARSER(sig) void Parallaction_br::cmdParse_##sig() +#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction_br::instParse_##sig() +#define DECLARE_LOCATION_PARSER(sig) void Parallaction_br::locParse_##sig() + + +DECLARE_LOCATION_PARSER(location) { + strcpy(_location._name, _tokens[1]); + + bool flip = false; + int nextToken; + + if (!scumm_stricmp("flip", _tokens[2])) { + flip = true; + nextToken = 3; + } else { + nextToken = 2; + } + + _disk->loadScenery(*_backgroundInfo, _location._name, NULL, NULL); + +// if (flip) { +// flip(); +// } + + _gfx->setBackground(&_backgroundInfo->bg); + _gfx->_palette.clone(_backgroundInfo->palette); + _gfx->setPalette(_backgroundInfo->palette); + + + 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]); + } +} + + + +DECLARE_LOCATION_PARSER(zone) { + parseZone(*_locParseCtxt.script, _zones, _tokens[1]); + + _locParseCtxt.z->_index = _locParseCtxt.numZones++; + + if (_localFlags[_currentLocationIndex] & kFlagsVisited) { + _locParseCtxt.z->_flags = _zoneFlags[_currentLocationIndex][_locParseCtxt.z->_index]; + } else { + _zoneFlags[_currentLocationIndex][_locParseCtxt.z->_index] = _locParseCtxt.z->_flags; + } + +} + + +DECLARE_LOCATION_PARSER(animation) { + parseAnimation(*_locParseCtxt.script, _animations, _tokens[1]); + + _locParseCtxt.a->_index = _locParseCtxt.numZones++; + + if (_localFlags[_currentLocationIndex] & kFlagsVisited) { + _locParseCtxt.a->_flags = _zoneFlags[_currentLocationIndex][_locParseCtxt.a->_index]; + } else { + _zoneFlags[_currentLocationIndex][_locParseCtxt.a->_index] = _locParseCtxt.a->_flags; + } + +} + + +DECLARE_LOCATION_PARSER(localflags) { + int _si = 1; // _localFlagNames[0] = 'visited' + while (_tokens[_si][0] != '\0') { + _localFlagNames->addData(_tokens[_si]); + _si++; + } +} + + +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) { +// _soundMan->loadSound(_tokens[1]); +} + + +DECLARE_LOCATION_PARSER(music) { +// _soundMan->loadMusic(_tokens[1]); +} + +DECLARE_LOCATION_PARSER(redundant) { + warning("redundant '%s' line found in script '%s'", _tokens[0], _locParseCtxt.filename); +} + + +DECLARE_LOCATION_PARSER(character) { +// changeCharacter(character); +} + + +DECLARE_LOCATION_PARSER(ifchar) { + skip(_locParseCtxt.script, "ENDIF"); +} + + +DECLARE_LOCATION_PARSER(null) { + +} + + +DECLARE_LOCATION_PARSER(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]); +} + + +DECLARE_LOCATION_PARSER(path) { + _disk->loadScenery(*_backgroundInfo, NULL, NULL, _tokens[1]); + _pathBuffer = &_backgroundInfo->path; +} + + +DECLARE_LOCATION_PARSER(escape) { + parseCommands(*_locParseCtxt.script, _location._escapeCommands); +} + + +DECLARE_LOCATION_PARSER(zeta) { + _zeta0 = atoi(_tokens[1]); + _zeta1 = atoi(_tokens[2]); + + if (_tokens[3][0] != '\0') { + _zeta2 = atoi(_tokens[1]); + } else { + _zeta2 = 50; + } +} + +DECLARE_COMMAND_PARSER(ifchar) { + if (!scumm_stricmp(_characterName, _tokens[1])) + skip(_locParseCtxt.script, "endif"); +} + + +DECLARE_COMMAND_PARSER(endif) { + +} + + +DECLARE_COMMAND_PARSER(location) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._string = strdup(_tokens[1]); + _locParseCtxt.nextToken++; + + if (_tokens[_locParseCtxt.nextToken][0] != '\0') { + _locParseCtxt.cmd->u._startPos.x = atoi(_tokens[_locParseCtxt.nextToken]); + _locParseCtxt.nextToken++; + _locParseCtxt.cmd->u._startPos.y = atoi(_tokens[_locParseCtxt.nextToken]); + _locParseCtxt.nextToken++; + } + + if (_tokens[_locParseCtxt.nextToken][0] != '\0') { + _locParseCtxt.cmd->u._startPos2.x = atoi(_tokens[_locParseCtxt.nextToken]); + _locParseCtxt.nextToken++; + _locParseCtxt.cmd->u._startPos2.y = atoi(_tokens[_locParseCtxt.nextToken]); + _locParseCtxt.nextToken++; + } + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(string) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._string = strdup(_tokens[1]); + _locParseCtxt.nextToken++; + + parseCommandFlags(); + addCommand(); +} + +DECLARE_COMMAND_PARSER(math) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._lvalue = _countersNames->lookup(_tokens[1]); + _locParseCtxt.nextToken++; + _locParseCtxt.cmd->u._rvalue = atoi(_tokens[2]); + _locParseCtxt.nextToken++; + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(test) { + createCommand(_lookup); + + uint counter = _countersNames->lookup(_tokens[1]); + _locParseCtxt.nextToken++; + + if (counter == Table::notFound) { + if (!scumm_stricmp("SFX", _tokens[1])) { + _locParseCtxt.cmd->_id = CMD_TEST_SFX; + } else { + error("unknown counter '%s' in test opcode", _tokens[1]); + } + } else { + _locParseCtxt.cmd->u._lvalue = counter; + _locParseCtxt.cmd->u._rvalue = atoi(_tokens[3]); + _locParseCtxt.nextToken++; + + if (_tokens[2][0] == '>') { + _locParseCtxt.cmd->_id = CMD_TEST_GT; + } else + if (_tokens[2][0] == '<') { + _locParseCtxt.cmd->_id = CMD_TEST_LT; + } + _locParseCtxt.nextToken++; + } + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(music) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._musicCommand = _audioCommandsNames->lookup(_tokens[1]); + _locParseCtxt.nextToken++; + + if (_tokens[2][0] != '\0' && scumm_stricmp("flags", _tokens[2]) && scumm_stricmp("gflags", _tokens[2])) { + _locParseCtxt.cmd->u._musicParm = atoi(_tokens[2]); + _locParseCtxt.nextToken++; + } + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(zone) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._zone = findZone(_tokens[_locParseCtxt.nextToken]); + _locParseCtxt.nextToken++; + + if (_locParseCtxt.cmd->u._zone == NULL) { + strcpy(_forwardedAnimationNames[_numForwards], _tokens[_locParseCtxt.nextToken-1]); + _forwardedCommands[_numForwards] = _locParseCtxt.cmd; + _numForwards++; + } + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(zeta) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._zeta0 = atoi(_tokens[1]); + _locParseCtxt.nextToken++; + _locParseCtxt.cmd->u._zeta1 = atoi(_tokens[2]); + _locParseCtxt.nextToken++; + + if (_tokens[3][0] != '\0') { + _locParseCtxt.cmd->u._zeta2 = atoi(_tokens[3]); + _locParseCtxt.nextToken++; + } else { + _locParseCtxt.cmd->u._zeta2 = 50; + } + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(give) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._object = 4 + atoi(_tokens[1]); + _locParseCtxt.nextToken++; + + if (!scumm_stricmp("dino", _tokens[2])) { + _locParseCtxt.cmd->u._characterId = 1; + } else + if (!scumm_stricmp("doug", _tokens[2])) { + _locParseCtxt.cmd->u._characterId = 2; + } else + if (!scumm_stricmp("donna", _tokens[2])) { + _locParseCtxt.cmd->u._characterId = 3; + } else + error("unknown recipient '%s' in give command", _tokens[2]); + + _locParseCtxt.nextToken++; + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(text) { + createCommand(_lookup); + + if (isdigit(_tokens[1][1])) { + _locParseCtxt.cmd->u._zeta0 = atoi(_tokens[1]); + _locParseCtxt.nextToken++; + } else { + _locParseCtxt.cmd->u._zeta0 = 0; + } + + _locParseCtxt.cmd->u._string = strdup(_tokens[_locParseCtxt.nextToken]); + _locParseCtxt.nextToken++; + + if (_tokens[_locParseCtxt.nextToken][0] != '\0' && scumm_stricmp("flags", _tokens[_locParseCtxt.nextToken])) { + _locParseCtxt.cmd->u._string2 = strdup(_tokens[_locParseCtxt.nextToken]); + _locParseCtxt.nextToken++; + } + + + parseCommandFlags(); + addCommand(); +} + + +DECLARE_COMMAND_PARSER(unary) { + createCommand(_lookup); + + _locParseCtxt.cmd->u._rvalue = atoi(_tokens[1]); + _locParseCtxt.nextToken++; + + parseCommandFlags(); + addCommand(); +} + + + +DECLARE_INSTRUCTION_PARSER(zone) { + _instParseCtxt.inst->_z = findZone(_tokens[1]); +} + + + +DECLARE_INSTRUCTION_PARSER(color) { + + parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); + + _instParseCtxt.inst->_colors[0] = atoi(_tokens[2]); + _instParseCtxt.inst->_colors[1] = atoi(_tokens[3]); + _instParseCtxt.inst->_colors[2] = atoi(_tokens[4]); + +} + + +DECLARE_INSTRUCTION_PARSER(mask) { + + parseRValue(_instParseCtxt.inst->_opA, _tokens[1]); + parseRValue(_instParseCtxt.inst->_opB, _tokens[2]); + parseRValue(_instParseCtxt.inst->_opC, _tokens[3]); + +} + + +DECLARE_INSTRUCTION_PARSER(print) { + parseRValue(_instParseCtxt.inst->_opB, _tokens[1]); +} + + +DECLARE_INSTRUCTION_PARSER(text) { + + int _si = 1; + + if (isdigit(_tokens[1][1])) { + _instParseCtxt.inst->_y = atoi(_tokens[1]); + _si = 2; + } else { + _instParseCtxt.inst->_y = -1; + } + + _instParseCtxt.inst->_text = strdup(_tokens[_si]); + _si++; + + if (_tokens[_si][0] != '\0' && scumm_stricmp("flags", _tokens[_si])) { + _instParseCtxt.inst->_text2 = strdup(_tokens[_si]); + } + +} + + +DECLARE_INSTRUCTION_PARSER(if_op) { + + if (_instParseCtxt.openIf) + error("cannot nest 'if' blocks"); + + parseLValue(_instParseCtxt.inst->_opA, _tokens[1]); + parseRValue(_instParseCtxt.inst->_opB, _tokens[3]); + + if (_tokens[2][0] == '=') { + _instParseCtxt.inst->_index = INST_IFEQ; + } else + if (_tokens[2][0] == '>') { + _instParseCtxt.inst->_index = INST_IFGT; + } else + if (_tokens[2][0] == '<') { + _instParseCtxt.inst->_index = INST_IFLT; + } else + error("unknown test operator '%s' in if-clause", _tokens[2]); + + _instParseCtxt.openIf = _instParseCtxt.inst; + +} + + +DECLARE_INSTRUCTION_PARSER(endif) { + if (_instParseCtxt.openIf == 0) + error("unexpected 'endif'"); + +// _instParseCtxt.openIf->_endif = _instParseCtxt.inst; + _instParseCtxt.openIf = NULL; +} + + +void Parallaction_br::parseRValue(ScriptVar &v, const char *str) { + + if (isdigit(str[0]) || str[0] == '-') { + v.setImmediate(atoi(str)); + return; + } + + int index = _instParseCtxt.program->findLocal(str); + if (index != -1) { + v.setLocal(&_instParseCtxt.locals[index]); + return; + } + + Animation *a; + if (str[1] == '.') { + a = findAnimation(&str[2]); + if (!a) { + error("unknown animation '%s' in script", &str[2]); + } + } else + a = _instParseCtxt.a; + + if (str[0] == 'X') { + v.setField(&a->_left); + } else + if (str[0] == 'Y') { + v.setField(&a->_top); + } else + if (str[0] == 'Z') { + v.setField(&a->_z); + } else + if (str[0] == 'F') { + v.setField(&a->_frame); + } else + if (str[0] == 'N') { + v.setImmediate(a->getFrameNum()); + } else + if (str[0] == 'R') { + v.setRandom(atoi(&str[1])); + } else + if (str[0] == 'L') { + v.setField(&_lipSyncVal); + } + +} + +typedef OpcodeImpl<Parallaction_br> OpcodeV2; +#define INSTRUCTION_PARSER(sig) OpcodeV2(this, &Parallaction_br::instParse_##sig) +#define ZONE_PARSER(sig) OpcodeV2(this, &Parallaction_br::locZoneParse_##sig) +#define ANIM_PARSER(sig) OpcodeV2(this, &Parallaction_br::locAnimParse_##sig) +#define LOCATION_PARSER(sig) OpcodeV2(this, &Parallaction_br::locParse_##sig) +#define COMMAND_PARSER(sig) OpcodeV2(this, &Parallaction_br::cmdParse_##sig) + +void Parallaction_br::initParsers() { + + static const OpcodeV2 op0[] = { + INSTRUCTION_PARSER(defLocal), // invalid opcode -> local definition + INSTRUCTION_PARSER(zone), // on + INSTRUCTION_PARSER(zone), // 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(zone), // start + INSTRUCTION_PARSER(zone), // process + INSTRUCTION_PARSER(move), + INSTRUCTION_PARSER(color), + INSTRUCTION_PARSER(zone), // sound + INSTRUCTION_PARSER(mask), + INSTRUCTION_PARSER(print), + INSTRUCTION_PARSER(text), + INSTRUCTION_PARSER(inc), // mul + INSTRUCTION_PARSER(inc), // div + INSTRUCTION_PARSER(if_op), + INSTRUCTION_PARSER(endif), + INSTRUCTION_PARSER(zone) // stop + }; + + uint i; + for (i = 0; i < ARRAYSIZE(op0); i++) + _instructionParsers.push_back(&op0[i]); + + + static const OpcodeV2 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), + COMMAND_PARSER(zone), // open + COMMAND_PARSER(zone), // close + COMMAND_PARSER(zone), // on + COMMAND_PARSER(zone), // off + COMMAND_PARSER(call), + COMMAND_PARSER(flags), // toggle + COMMAND_PARSER(drop), + COMMAND_PARSER(simple), // quit + COMMAND_PARSER(move), + COMMAND_PARSER(animation), // stop + COMMAND_PARSER(string), // character + COMMAND_PARSER(string), // followme + COMMAND_PARSER(simple), // onmouse + COMMAND_PARSER(simple), // offmouse + COMMAND_PARSER(drop), // add + COMMAND_PARSER(zone), // leave + COMMAND_PARSER(math), // inc + COMMAND_PARSER(math), // dec + COMMAND_PARSER(math), // test + COMMAND_PARSER(invalid), + COMMAND_PARSER(invalid), + COMMAND_PARSER(math), // let + COMMAND_PARSER(music), + COMMAND_PARSER(zone), // fix + COMMAND_PARSER(zone), // unfix + COMMAND_PARSER(zeta), + COMMAND_PARSER(unary), // scroll + COMMAND_PARSER(string), // swap + COMMAND_PARSER(give), + COMMAND_PARSER(text), + COMMAND_PARSER(unary), // part + COMMAND_PARSER(invalid), + COMMAND_PARSER(simple), // return + COMMAND_PARSER(simple), // onsave + COMMAND_PARSER(simple), // offsave + COMMAND_PARSER(endcommands), // endcommands + COMMAND_PARSER(ifchar), + COMMAND_PARSER(endif) + }; + + for (i = 0; i < ARRAYSIZE(op2); i++) + _commandParsers.push_back(&op2[i]); + + static const OpcodeV2 op4[] = { + LOCATION_PARSER(invalid), + LOCATION_PARSER(character), + LOCATION_PARSER(endlocation), + LOCATION_PARSER(ifchar), + LOCATION_PARSER(null), // endif + LOCATION_PARSER(location), + LOCATION_PARSER(mask), + LOCATION_PARSER(path), + LOCATION_PARSER(null), // disk + LOCATION_PARSER(localflags), + LOCATION_PARSER(commands), + LOCATION_PARSER(escape), + LOCATION_PARSER(acommands), + LOCATION_PARSER(flags), + LOCATION_PARSER(comment), + LOCATION_PARSER(endcomment), + LOCATION_PARSER(zone), + LOCATION_PARSER(animation), + LOCATION_PARSER(zeta), + LOCATION_PARSER(music), + LOCATION_PARSER(sound) +// LOCATION_PARSER(redundant) // for redundant endanimation + }; + + for (i = 0; i < ARRAYSIZE(op4); i++) + _locationParsers.push_back(&op4[i]); + + static const OpcodeV2 op5[] = { + ZONE_PARSER(invalid), + ZONE_PARSER(endzone), + ZONE_PARSER(limits), + ZONE_PARSER(moveto), + ZONE_PARSER(type), + ZONE_PARSER(commands), + ZONE_PARSER(label), + ZONE_PARSER(flags) + }; + + for (i = 0; i < ARRAYSIZE(op5); i++) + _locationZoneParsers.push_back(&op5[i]); + + static const OpcodeV2 op6[] = { + ANIM_PARSER(invalid), + ANIM_PARSER(endanimation), + ANIM_PARSER(endanimation), // endzone + ANIM_PARSER(script), + ANIM_PARSER(commands), + ANIM_PARSER(type), + ANIM_PARSER(label), + ANIM_PARSER(flags), + ANIM_PARSER(file), + ANIM_PARSER(position), + ANIM_PARSER(moveto) + }; + + for (i = 0; i < ARRAYSIZE(op6); i++) + _locationAnimParsers.push_back(&op6[i]); + + _currentOpcodes = 0; + _currentStatements = 0; + +} + +void Parallaction_br::parseLocation(const char* filename) { + + _locParseCtxt.numZones = 0; + + Super::parseLocation(filename); + +// drawZones(); + + return; +} + + + + + +} // namespace Parallaction |