Initial commit
This commit is contained in:
455
engines/kyra/script/script.cpp
Normal file
455
engines/kyra/script/script.cpp
Normal file
@@ -0,0 +1,455 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/script/script.h"
|
||||
#include "kyra/kyra_v1.h"
|
||||
#include "kyra/resource/resource.h"
|
||||
|
||||
#include "common/endian.h"
|
||||
|
||||
namespace Kyra {
|
||||
EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm), _scriptData(nullptr), _filename(nullptr), _parameter(0) {
|
||||
#define OPCODE(x) { &EMCInterpreter::x, #x }
|
||||
static const OpcodeEntry opcodes[] = {
|
||||
// 0x00
|
||||
OPCODE(op_jmp),
|
||||
OPCODE(op_setRetValue),
|
||||
OPCODE(op_pushRetOrPos),
|
||||
OPCODE(op_push),
|
||||
// 0x04
|
||||
OPCODE(op_push),
|
||||
OPCODE(op_pushReg),
|
||||
OPCODE(op_pushBPNeg),
|
||||
OPCODE(op_pushBPAdd),
|
||||
// 0x08
|
||||
OPCODE(op_popRetOrPos),
|
||||
OPCODE(op_popReg),
|
||||
OPCODE(op_popBPNeg),
|
||||
OPCODE(op_popBPAdd),
|
||||
// 0x0C
|
||||
OPCODE(op_addSP),
|
||||
OPCODE(op_subSP),
|
||||
OPCODE(op_sysCall),
|
||||
OPCODE(op_ifNotJmp),
|
||||
// 0x10
|
||||
OPCODE(op_negate),
|
||||
OPCODE(op_eval),
|
||||
OPCODE(op_setRetAndJmp)
|
||||
};
|
||||
_opcodes = opcodes;
|
||||
#undef OPCODE
|
||||
}
|
||||
|
||||
bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
|
||||
switch (chunk._type) {
|
||||
case MKTAG('T','E','X','T'):
|
||||
_scriptData->text = new byte[chunk._size];
|
||||
assert(_scriptData->text);
|
||||
if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size)
|
||||
error("Couldn't read TEXT chunk from file '%s'", _filename);
|
||||
break;
|
||||
|
||||
case MKTAG('O','R','D','R'):
|
||||
_scriptData->ordr = new uint16[chunk._size >> 1];
|
||||
_scriptData->ordrSize = chunk._size;
|
||||
assert(_scriptData->ordr);
|
||||
if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size)
|
||||
error("Couldn't read ORDR chunk from file '%s'", _filename);
|
||||
|
||||
for (int i = (chunk._size >> 1) - 1; i >= 0; --i)
|
||||
_scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
|
||||
break;
|
||||
|
||||
case MKTAG('D','A','T','A'):
|
||||
_scriptData->data = new uint16[chunk._size >> 1];
|
||||
_scriptData->dataSize = chunk._size;
|
||||
assert(_scriptData->data);
|
||||
if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size)
|
||||
error("Couldn't read DATA chunk from file '%s'", _filename);
|
||||
|
||||
for (int i = (chunk._size >> 1) - 1; i >= 0; --i)
|
||||
_scriptData->data[i] = READ_BE_UINT16(&_scriptData->data[i]);
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("Unexpected chunk '%s' of size %d found in file '%s'", tag2str(chunk._type), chunk._size, _filename);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode *> *opcodes) {
|
||||
Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
|
||||
if (!stream) {
|
||||
error("Couldn't open script file '%s'", filename);
|
||||
return false; // for compilers that don't support NORETURN
|
||||
}
|
||||
|
||||
memset(scriptData, 0, sizeof(EMCData));
|
||||
|
||||
_scriptData = scriptData;
|
||||
_filename = filename;
|
||||
|
||||
IFFParser iff(*stream);
|
||||
Common::Functor1Mem< Common::IFFChunk &, bool, EMCInterpreter > c(this, &EMCInterpreter::callback);
|
||||
iff.parse(c);
|
||||
|
||||
if (!_scriptData->ordr)
|
||||
error("No ORDR chunk found in file: '%s'", filename);
|
||||
|
||||
if (!_scriptData->data)
|
||||
error("No DATA chunk found in file: '%s'", filename);
|
||||
|
||||
if (stream->err())
|
||||
error("Read error while parsing file '%s'", filename);
|
||||
|
||||
delete stream;
|
||||
|
||||
_scriptData->sysFuncs = opcodes;
|
||||
|
||||
Common::strlcpy(_scriptData->filename, filename, 13);
|
||||
|
||||
_scriptData = nullptr;
|
||||
_filename = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EMCInterpreter::unload(EMCData *data) {
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
delete[] data->text;
|
||||
delete[] data->ordr;
|
||||
delete[] data->data;
|
||||
|
||||
data->text = nullptr;
|
||||
data->ordr = data->data = nullptr;
|
||||
}
|
||||
|
||||
void EMCInterpreter::init(EMCState *scriptStat, const EMCData *data) {
|
||||
scriptStat->dataPtr = data;
|
||||
scriptStat->ip = nullptr;
|
||||
scriptStat->stack[EMCState::kStackLastEntry] = 0;
|
||||
scriptStat->bp = EMCState::kStackSize+1;
|
||||
scriptStat->sp = EMCState::kStackLastEntry;
|
||||
}
|
||||
|
||||
bool EMCInterpreter::start(EMCState *script, int function) {
|
||||
if (!script->dataPtr)
|
||||
return false;
|
||||
|
||||
if (function >= (int) script->dataPtr->ordrSize / 2 || function < 0)
|
||||
return false;
|
||||
|
||||
uint16 functionOffset = script->dataPtr->ordr[function];
|
||||
if (functionOffset == 0xFFFF)
|
||||
return false;
|
||||
|
||||
if (_vm->game() == GI_KYRA1) {
|
||||
if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98 || _vm->gameFlags().lang == Common::KO_KOR)
|
||||
script->ip = &script->dataPtr->data[functionOffset+1];
|
||||
else
|
||||
script->ip = &script->dataPtr->data[functionOffset];
|
||||
} else {
|
||||
if (functionOffset+1 >= (int) script->dataPtr->dataSize / 2)
|
||||
return false;
|
||||
script->ip = &script->dataPtr->data[functionOffset+1];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EMCInterpreter::isValid(EMCState *script) {
|
||||
if (!script->ip || !script->dataPtr || _vm->shouldQuit())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EMCInterpreter::run(EMCState *script) {
|
||||
_parameter = 0;
|
||||
|
||||
if (!script->ip)
|
||||
return false;
|
||||
|
||||
// Should be no Problem at all to cast to uint32 here, since that's the biggest ptrdiff the original
|
||||
// would allow, of course that's not realistic to happen to be somewhere near the limit of uint32 anyway.
|
||||
const uint32 instOffset = (uint32)((const byte *)script->ip - (const byte *)script->dataPtr->data);
|
||||
if ((int32)instOffset < 0 || instOffset >= script->dataPtr->dataSize) {
|
||||
error("Attempt to execute out of bounds: 0x%.08X out of 0x%.08X",
|
||||
instOffset, script->dataPtr->dataSize);
|
||||
}
|
||||
int16 code = *script->ip++;
|
||||
int16 opcode = (code >> 8) & 0x1F;
|
||||
|
||||
if (code & 0x8000) {
|
||||
opcode = 0;
|
||||
_parameter = code & 0x7FFF;
|
||||
} else if (code & 0x4000) {
|
||||
_parameter = (int8)(code);
|
||||
} else if (code & 0x2000) {
|
||||
_parameter = *script->ip++;
|
||||
} else {
|
||||
_parameter = 0;
|
||||
}
|
||||
|
||||
if (opcode > 18) {
|
||||
error("Unknown script opcode: %d in file '%s' at offset 0x%.08X", opcode, script->dataPtr->filename, instOffset);
|
||||
} else {
|
||||
debugC(5, kDebugLevelScript, "[0x%.08X] EMCInterpreter::%s([%d/%u])", instOffset, _opcodes[opcode].desc, _parameter, (uint)_parameter);
|
||||
(this->*(_opcodes[opcode].proc))(script);
|
||||
}
|
||||
|
||||
return (script->ip != nullptr);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark - Command implementations
|
||||
#pragma mark -
|
||||
|
||||
void EMCInterpreter::op_jmp(EMCState *script) {
|
||||
script->ip = script->dataPtr->data + _parameter;
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_setRetValue(EMCState *script) {
|
||||
script->retValue = _parameter;
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_pushRetOrPos(EMCState *script) {
|
||||
switch (_parameter) {
|
||||
case 0:
|
||||
script->stack[--script->sp] = script->retValue;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
script->stack[--script->sp] = script->ip - script->dataPtr->data + 1;
|
||||
script->stack[--script->sp] = script->bp;
|
||||
script->bp = script->sp + 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
script->ip = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_push(EMCState *script) {
|
||||
script->stack[--script->sp] = _parameter;
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_pushReg(EMCState *script) {
|
||||
script->stack[--script->sp] = script->regs[_parameter];
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_pushBPNeg(EMCState *script) {
|
||||
script->stack[--script->sp] = script->stack[(-(int32)(_parameter + 2)) + script->bp];
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_pushBPAdd(EMCState *script) {
|
||||
script->stack[--script->sp] = script->stack[(_parameter - 1) + script->bp];
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_popRetOrPos(EMCState *script) {
|
||||
switch (_parameter) {
|
||||
case 0:
|
||||
script->retValue = script->stack[script->sp++];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (script->sp >= EMCState::kStackLastEntry) {
|
||||
script->ip = nullptr;
|
||||
} else {
|
||||
script->bp = script->stack[script->sp++];
|
||||
script->ip = script->dataPtr->data + script->stack[script->sp++];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
script->ip = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_popReg(EMCState *script) {
|
||||
script->regs[_parameter] = script->stack[script->sp++];
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_popBPNeg(EMCState *script) {
|
||||
script->stack[(-(int32)(_parameter + 2)) + script->bp] = script->stack[script->sp++];
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_popBPAdd(EMCState *script) {
|
||||
script->stack[(_parameter - 1) + script->bp] = script->stack[script->sp++];
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_addSP(EMCState *script) {
|
||||
script->sp += _parameter;
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_subSP(EMCState *script) {
|
||||
script->sp -= _parameter;
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_sysCall(EMCState *script) {
|
||||
const uint8 id = _parameter;
|
||||
|
||||
assert(script->dataPtr->sysFuncs);
|
||||
assert(id < script->dataPtr->sysFuncs->size());
|
||||
|
||||
if ((*script->dataPtr->sysFuncs)[id] && ((*script->dataPtr->sysFuncs)[id])->isValid()) {
|
||||
script->retValue = (*(*script->dataPtr->sysFuncs)[id])(script);
|
||||
} else {
|
||||
script->retValue = 0;
|
||||
warning("Unimplemented system call 0x%.02X/%d used in file '%s'", id, id, script->dataPtr->filename);
|
||||
}
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_ifNotJmp(EMCState *script) {
|
||||
if (!script->stack[script->sp++]) {
|
||||
_parameter &= 0x7FFF;
|
||||
script->ip = script->dataPtr->data + _parameter;
|
||||
}
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_negate(EMCState *script) {
|
||||
int16 value = script->stack[script->sp];
|
||||
switch (_parameter) {
|
||||
case 0:
|
||||
if (!value)
|
||||
script->stack[script->sp] = 1;
|
||||
else
|
||||
script->stack[script->sp] = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
script->stack[script->sp] = -value;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
script->stack[script->sp] = ~value;
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("Unknown negation func: %d", _parameter);
|
||||
script->ip = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_eval(EMCState *script) {
|
||||
int16 ret = 0;
|
||||
bool error = false;
|
||||
|
||||
int16 val1 = script->stack[script->sp++];
|
||||
int16 val2 = script->stack[script->sp++];
|
||||
|
||||
switch (_parameter) {
|
||||
case 0:
|
||||
ret = (val2 && val1) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ret = (val2 || val1) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ret = (val1 == val2) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ret = (val1 != val2) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ret = (val1 > val2) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ret = (val1 >= val2) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
ret = (val1 < val2) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
ret = (val1 <= val2) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ret = val1 + val2;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
ret = val2 - val1;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
ret = val1 * val2;
|
||||
break;
|
||||
|
||||
case 11:
|
||||
ret = val2 / val1;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
ret = val2 >> val1;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
ret = val2 << val1;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
ret = val1 & val2;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
ret = val1 | val2;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
ret = val2 % val1;
|
||||
break;
|
||||
|
||||
case 17:
|
||||
ret = val1 ^ val2;
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("Unknown evaluate func: %d", _parameter);
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (error)
|
||||
script->ip = nullptr;
|
||||
else
|
||||
script->stack[--script->sp] = ret;
|
||||
}
|
||||
|
||||
void EMCInterpreter::op_setRetAndJmp(EMCState *script) {
|
||||
if (script->sp >= EMCState::kStackLastEntry) {
|
||||
script->ip = nullptr;
|
||||
} else {
|
||||
script->retValue = script->stack[script->sp++];
|
||||
uint16 temp = script->stack[script->sp++];
|
||||
script->stack[EMCState::kStackLastEntry] = 0;
|
||||
script->ip = &script->dataPtr->data[temp];
|
||||
}
|
||||
}
|
||||
} // End of namespace Kyra
|
||||
164
engines/kyra/script/script.h
Normal file
164
engines/kyra/script/script.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_SCRIPT_H
|
||||
#define KYRA_SCRIPT_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/array.h"
|
||||
#include "common/func.h"
|
||||
#include "common/formats/iff_container.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
struct EMCState;
|
||||
typedef Common::Functor1<EMCState *, int> Opcode;
|
||||
|
||||
struct EMCData {
|
||||
char filename[13];
|
||||
|
||||
byte *text;
|
||||
uint16 *data;
|
||||
uint32 ordrSize;
|
||||
uint16 *ordr;
|
||||
uint32 dataSize;
|
||||
|
||||
const Common::Array<const Opcode *> *sysFuncs;
|
||||
};
|
||||
|
||||
struct EMCState {
|
||||
enum {
|
||||
kStackSize = 100,
|
||||
kStackLastEntry = kStackSize - 1
|
||||
};
|
||||
|
||||
const uint16 *ip;
|
||||
const EMCData *dataPtr;
|
||||
int16 retValue;
|
||||
uint16 bp;
|
||||
uint16 sp;
|
||||
int16 regs[30]; // VM registers
|
||||
int16 stack[kStackSize]; // VM stack
|
||||
};
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
#define stackPos(x) (script->stack[script->sp+x])
|
||||
#else
|
||||
#define stackPos(x) emcSafeReadStack(script, x, __LINE__, __FILE__)
|
||||
#endif
|
||||
#define safeStackPos(x) (script->sp+x < EMCState::kStackSize ? stackPos(x) : 0)
|
||||
#define stackPosString(x) ((const char *)&script->dataPtr->text[READ_BE_UINT16(&script->dataPtr->text[stackPos(x)<<1])])
|
||||
|
||||
class Resource;
|
||||
class KyraEngine_v1;
|
||||
|
||||
class IFFParser : public Common::IFFParser {
|
||||
public:
|
||||
IFFParser(Common::ReadStream &input) : Common::IFFParser(&input) {
|
||||
// It seems Westwood missunderstood the 'size' field of the FORM chunk.
|
||||
//
|
||||
// For EMC scripts (type EMC2) it's filesize instead of filesize - 8,
|
||||
// means accidentally including the 8 bytes used by the chunk header for the FORM
|
||||
// chunk.
|
||||
//
|
||||
// For TIM scripts (type AVFS) it's filesize - 12 instead of filesize - 8,
|
||||
// means it will not include the size of the 'type' field in the FORM chunk,
|
||||
// instead of only not including the chunk header size.
|
||||
//
|
||||
// Both lead to some problems in our IFF parser, either reading after the end
|
||||
// of file or producing a "Chunk overread" error message. To work around this
|
||||
// we need to adjust the size field properly.
|
||||
|
||||
// Fix for certain Russian fan translations:
|
||||
// Westwood's original code completely ignores the FORM chunk and its size
|
||||
// setting. After opening a TIM or EMC file they just check whether the FORM
|
||||
// chunk exists (as a kind of file type verification) and then immediately seek
|
||||
// behind the FORM chunk.
|
||||
// This means that their parser is immune to weird fan translation scripts
|
||||
// where the file size doesn't match the form chunk size. In our implemetation
|
||||
// this would produce "Chunk overread" errors.
|
||||
// Westwood also always pads all chunk sizes to 2 byte alignment after reading
|
||||
// them from the file (not with FORM though, since they completely ignore it).
|
||||
// This seems to do the trick for our FORM chunk size issue with the Russian
|
||||
// fan translations. Another method which I have tried and which seems to work
|
||||
// well would be simply setting _formChunk.size to the file size (-12 for TIM).
|
||||
|
||||
_formChunk.size = (_formChunk.size + 1) & ~1;
|
||||
|
||||
if (_formType == MKTAG('E','M','C','2'))
|
||||
_formChunk.size -= 8;
|
||||
else if (_formType == MKTAG('A','V','F','S'))
|
||||
_formChunk.size += 4;
|
||||
}
|
||||
};
|
||||
|
||||
class EMCInterpreter {
|
||||
public:
|
||||
EMCInterpreter(KyraEngine_v1 *vm);
|
||||
|
||||
bool load(const char *filename, EMCData *data, const Common::Array<const Opcode *> *opcodes);
|
||||
void unload(EMCData *data);
|
||||
|
||||
void init(EMCState *scriptState, const EMCData *data);
|
||||
bool start(EMCState *script, int function);
|
||||
|
||||
bool isValid(EMCState *script);
|
||||
|
||||
bool run(EMCState *script);
|
||||
protected:
|
||||
KyraEngine_v1 *_vm;
|
||||
int16 _parameter;
|
||||
|
||||
const char *_filename;
|
||||
EMCData *_scriptData;
|
||||
|
||||
bool callback(Common::IFFChunk &chunk);
|
||||
|
||||
typedef void (EMCInterpreter::*OpcodeProc)(EMCState *);
|
||||
struct OpcodeEntry {
|
||||
OpcodeProc proc;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
const OpcodeEntry *_opcodes;
|
||||
private:
|
||||
void op_jmp(EMCState *);
|
||||
void op_setRetValue(EMCState *);
|
||||
void op_pushRetOrPos(EMCState *);
|
||||
void op_push(EMCState *);
|
||||
void op_pushReg(EMCState *);
|
||||
void op_pushBPNeg(EMCState *);
|
||||
void op_pushBPAdd(EMCState *);
|
||||
void op_popRetOrPos(EMCState *);
|
||||
void op_popReg(EMCState *);
|
||||
void op_popBPNeg(EMCState *);
|
||||
void op_popBPAdd(EMCState *);
|
||||
void op_addSP(EMCState *);
|
||||
void op_subSP(EMCState *);
|
||||
void op_sysCall(EMCState *);
|
||||
void op_ifNotJmp(EMCState *);
|
||||
void op_negate(EMCState *);
|
||||
void op_eval(EMCState *);
|
||||
void op_setRetAndJmp(EMCState *);
|
||||
};
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
1658
engines/kyra/script/script_eob.cpp
Normal file
1658
engines/kyra/script/script_eob.cpp
Normal file
File diff suppressed because it is too large
Load Diff
132
engines/kyra/script/script_eob.h
Normal file
132
engines/kyra/script/script_eob.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_EOB
|
||||
|
||||
#ifndef KYRA_SCRIPT_EOB_H
|
||||
#define KYRA_SCRIPT_EOB_H
|
||||
|
||||
#include "common/func.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/savefile.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
class KyraRpgEngine;
|
||||
|
||||
class EoBInfProcessor {
|
||||
public:
|
||||
EoBInfProcessor(EoBCoreEngine *engine, Screen_EoB *_screen);
|
||||
~EoBInfProcessor();
|
||||
|
||||
void loadData(const uint8 *data, uint32 dataSize);
|
||||
void run(int func, int flags);
|
||||
|
||||
void setFlags(uint32 flags);
|
||||
void clearFlags(uint32 flags);
|
||||
bool checkFlags(uint32 flags) const;
|
||||
bool preventRest() const;
|
||||
|
||||
void loadState(Common::SeekableReadStreamEndian &in, bool origFile = false);
|
||||
void saveState(Common::OutSaveFile *out, bool origFile = false);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
const char *getString(uint16 index);
|
||||
|
||||
int oeob_setWallType(int8 *data);
|
||||
int oeob_toggleWallState(int8 *data);
|
||||
int oeob_openDoor(int8 *data);
|
||||
int oeob_closeDoor(int8 *data);
|
||||
int oeob_replaceMonster(int8 *data);
|
||||
int oeob_movePartyOrObject(int8 *data);
|
||||
int oeob_moveInventoryItemToBlock(int8 *data);
|
||||
int oeob_printMessage_v1(int8 *data);
|
||||
int oeob_printMessage_v2(int8 *data);
|
||||
int oeob_setFlags(int8 *data);
|
||||
int oeob_playSoundEffect(int8 *data);
|
||||
int oeob_removeFlags(int8 *data);
|
||||
int oeob_modifyCharacterHitPoints(int8 *data);
|
||||
int oeob_calcAndInflictCharacterDamage(int8 *data);
|
||||
int oeob_jump(int8 *data);
|
||||
int oeob_end(int8 *data);
|
||||
int oeob_returnFromSubroutine(int8 *data);
|
||||
int oeob_callSubroutine(int8 *data);
|
||||
int oeob_eval_v1(int8 *data);
|
||||
int oeob_eval_v2(int8 *data);
|
||||
int oeob_deleteItem(int8 *data);
|
||||
int oeob_loadNewLevelOrMonsters(int8 *data);
|
||||
int oeob_increasePartyExperience(int8 *data);
|
||||
int oeob_createItem_v1(int8 *data);
|
||||
int oeob_createItem_v2(int8 *data);
|
||||
int oeob_launchObject(int8 *data);
|
||||
int oeob_changeDirection(int8 *data);
|
||||
int oeob_identifyItems(int8 *data);
|
||||
int oeob_sequence(int8 *data);
|
||||
int oeob_delay(int8 *data);
|
||||
int oeob_drawScene(int8 *data);
|
||||
int oeob_dialogue(int8 *data);
|
||||
int oeob_specialEvent(int8 *data);
|
||||
|
||||
EoBCoreEngine *_vm;
|
||||
Screen_EoB *_screen;
|
||||
|
||||
typedef Common::Functor1Mem<int8 *, int, EoBInfProcessor> InfProc;
|
||||
struct InfOpcode : private Common::NonCopyable {
|
||||
InfOpcode(InfProc *p, const char *d) : proc(p), desc(d) {}
|
||||
~InfOpcode() { delete proc; }
|
||||
|
||||
InfProc *proc;
|
||||
Common::String desc;
|
||||
};
|
||||
Common::Array<const InfOpcode *> _opcodes;
|
||||
|
||||
int8 *_scriptData;
|
||||
uint16 _scriptSize;
|
||||
|
||||
uint8 _abortScript;
|
||||
uint16 _abortAfterSubroutine;
|
||||
int _dlgResult;
|
||||
uint8 _preventRest;
|
||||
|
||||
uint16 _lastScriptFunc;
|
||||
uint16 _lastScriptFlags;
|
||||
|
||||
int8 **_subroutineStack;
|
||||
int _subroutineStackPos;
|
||||
|
||||
uint32 *_flagTable;
|
||||
|
||||
int16 *_stack;
|
||||
int _stackIndex;
|
||||
|
||||
int8 _activeCharacter;
|
||||
|
||||
static const uint8 _segaCDColorMap[16];
|
||||
|
||||
const int _commandMin;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ENABLE_EOB
|
||||
1749
engines/kyra/script/script_hof.cpp
Normal file
1749
engines/kyra/script/script_hof.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1998
engines/kyra/script/script_lok.cpp
Normal file
1998
engines/kyra/script/script_lok.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3053
engines/kyra/script/script_lol.cpp
Normal file
3053
engines/kyra/script/script_lol.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1401
engines/kyra/script/script_mr.cpp
Normal file
1401
engines/kyra/script/script_mr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1108
engines/kyra/script/script_tim.cpp
Normal file
1108
engines/kyra/script/script_tim.cpp
Normal file
File diff suppressed because it is too large
Load Diff
305
engines/kyra/script/script_tim.h
Normal file
305
engines/kyra/script/script_tim.h
Normal file
@@ -0,0 +1,305 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef KYRA_SCRIPT_TIM_H
|
||||
#define KYRA_SCRIPT_TIM_H
|
||||
|
||||
#include "kyra/kyra_v1.h"
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/func.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
class WSAMovie_v2;
|
||||
class Screen_v2;
|
||||
class Movie;
|
||||
class LoLEngine;
|
||||
|
||||
class TimAnimator {
|
||||
public:
|
||||
struct AnimPart {
|
||||
uint16 firstFrame;
|
||||
uint16 lastFrame;
|
||||
uint16 cycles;
|
||||
int16 nextPart;
|
||||
int16 partDelay;
|
||||
uint16 field_A;
|
||||
int16 sfxIndex;
|
||||
uint16 sfxFrame;
|
||||
};
|
||||
|
||||
struct Animation {
|
||||
Movie *wsa;
|
||||
int16 x, y;
|
||||
uint32 nextFrame;
|
||||
uint8 enable;
|
||||
uint8 field_D;
|
||||
uint8 frameDelay;
|
||||
int8 curPart;
|
||||
uint8 curFrame;
|
||||
uint8 cyclesCompleted;
|
||||
uint16 wsaCopyParams;
|
||||
int8 lastPart;
|
||||
AnimPart *parts;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_LOL
|
||||
TimAnimator(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts);
|
||||
#else
|
||||
TimAnimator(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts);
|
||||
#endif
|
||||
~TimAnimator();
|
||||
|
||||
void init(int animIndex, Movie *wsa, int x, int y, int wsaCopyParams, int frameDelay);
|
||||
void reset(int animIndex, bool clearStruct);
|
||||
|
||||
void displayFrame(int animIndex, int page, int frame, int flags = -1);
|
||||
|
||||
const Movie *getWsaCPtr(int animIndex) { return (animIndex >= 0 && animIndex < 6) ? _animations[animIndex].wsa : 0; }
|
||||
int getAnimX(int animIndex) { return (animIndex >= 0 && animIndex < 6) ? _animations[animIndex].x : 0; }
|
||||
int getAnimY(int animIndex) { return (animIndex >= 0 && animIndex < 6) ? _animations[animIndex].y : 0; }
|
||||
|
||||
#ifdef ENABLE_LOL
|
||||
void setupPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
|
||||
void start(int animIndex, int part);
|
||||
void stop(int animIndex);
|
||||
void update(int animIndex);
|
||||
void playPart(int animIndex, int firstFrame, int lastFrame, int delay);
|
||||
int resetLastPart(int animIndex);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef ENABLE_LOL
|
||||
LoLEngine *_vm;
|
||||
#else
|
||||
KyraEngine_v1 *_vm;
|
||||
#endif
|
||||
Screen_v2 *_screen;
|
||||
OSystem *_system;
|
||||
|
||||
Animation *_animations;
|
||||
|
||||
const bool _useParts;
|
||||
};
|
||||
|
||||
struct TIM;
|
||||
typedef Common::Functor2<const TIM *, const uint16 *, int> TIMOpcode;
|
||||
|
||||
struct TIM {
|
||||
char filename[13];
|
||||
|
||||
uint16 clickedButton;
|
||||
int16 dlgFunc;
|
||||
|
||||
int16 procFunc;
|
||||
uint16 procParam;
|
||||
|
||||
enum {
|
||||
kCountFuncs = 10
|
||||
};
|
||||
|
||||
struct Function {
|
||||
uint16 *ip;
|
||||
|
||||
uint32 lastTime;
|
||||
uint32 nextTime;
|
||||
|
||||
uint16 *loopIp;
|
||||
|
||||
uint16 *avtl;
|
||||
} func[kCountFuncs];
|
||||
|
||||
enum {
|
||||
kWSASlots = 6,
|
||||
kAnimParts = 10
|
||||
};
|
||||
|
||||
struct WSASlot {
|
||||
int anim;
|
||||
|
||||
int16 x, y;
|
||||
uint16 wsaFlags;
|
||||
uint16 offscreen;
|
||||
} wsa[kWSASlots];
|
||||
|
||||
uint16 *avtl;
|
||||
uint8 *text;
|
||||
|
||||
const Common::Array<const TIMOpcode *> *opcodes;
|
||||
|
||||
// TODO: Get rid of this ugly HACK to allow the
|
||||
// Lands of Lore outro to be working properly.
|
||||
bool isLoLOutro;
|
||||
uint8 lolCharacter;
|
||||
};
|
||||
|
||||
class TIMInterpreter {
|
||||
public:
|
||||
TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system);
|
||||
virtual ~TIMInterpreter();
|
||||
|
||||
TIM *load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes);
|
||||
void unload(TIM *&tim) const;
|
||||
|
||||
bool callback(Common::IFFChunk &chunk);
|
||||
|
||||
virtual int initAnimStruct(int index, const char *filename, int x, int y, int, int offscreenBuffer, uint16 wsaFlags);
|
||||
virtual int freeAnimStruct(int index);
|
||||
TimAnimator *animator() { return _animator; }
|
||||
|
||||
void setLangData(const char *filename);
|
||||
void clearLangData() { delete[] _langData; _langData = 0; }
|
||||
|
||||
const char *getCTableEntry(uint idx) const;
|
||||
|
||||
void resetFinishedFlag() { _finished = false; }
|
||||
bool finished() const { return _finished; }
|
||||
|
||||
int exec(TIM *tim, bool loop);
|
||||
void stopCurFunc() { if (_currentTim) cmd_stopCurFunc(0); }
|
||||
void stopAllFuncs(TIM *tim);
|
||||
|
||||
void refreshTimersAfterPause(uint32 elapsedTime);
|
||||
|
||||
void displayText(uint16 textId, int16 flags);
|
||||
void displayText(uint16 textId, int16 flags, uint8 color);
|
||||
void setupTextPalette(uint index, int fadePalette);
|
||||
|
||||
virtual void resetDialogueState(TIM *tim) {}
|
||||
|
||||
int _drawPage2;
|
||||
|
||||
int _palDelayInc, _palDiff, _palDelayAcc;
|
||||
int _abortFlag;
|
||||
|
||||
protected:
|
||||
KyraEngine_v1 *_vm;
|
||||
Screen_v2 *_screen;
|
||||
OSystem *_system;
|
||||
|
||||
TIM *_currentTim;
|
||||
int _currentFunc;
|
||||
|
||||
TimAnimator *_animator;
|
||||
|
||||
bool _finished;
|
||||
|
||||
// used when loading
|
||||
int _avtlChunkSize;
|
||||
const char *_filename;
|
||||
TIM *_tim;
|
||||
|
||||
Common::String _vocFiles[120];
|
||||
|
||||
virtual void update() {}
|
||||
virtual void checkSpeechProgress() {}
|
||||
|
||||
char _audioFilename[32];
|
||||
|
||||
uint8 *_langData;
|
||||
char *getTableEntry(uint idx);
|
||||
bool _textDisplayed;
|
||||
uint8 *_textAreaBuffer;
|
||||
|
||||
virtual int execCommand(int cmd, const uint16 *param);
|
||||
|
||||
typedef int (TIMInterpreter::*CommandProc)(const uint16 *);
|
||||
struct CommandEntry {
|
||||
CommandProc proc;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
const CommandEntry *_commands;
|
||||
int _commandsSize;
|
||||
|
||||
int cmd_initFunc0(const uint16 *param);
|
||||
int cmd_stopCurFunc(const uint16 *param);
|
||||
int cmd_initWSA(const uint16 *param);
|
||||
int cmd_uninitWSA(const uint16 *param);
|
||||
int cmd_initFunc(const uint16 *param);
|
||||
int cmd_stopFunc(const uint16 *param);
|
||||
int cmd_wsaDisplayFrame(const uint16 *param);
|
||||
int cmd_displayText(const uint16 *param);
|
||||
int cmd_loadVocFile(const uint16 *param);
|
||||
int cmd_unloadVocFile(const uint16 *param);
|
||||
int cmd_playVocFile(const uint16 *param);
|
||||
int cmd_loadSoundFile(const uint16 *param);
|
||||
int cmd_playMusicTrack(const uint16 *param);
|
||||
virtual int cmd_setLoopIp(const uint16 *param);
|
||||
virtual int cmd_continueLoop(const uint16 *param);
|
||||
int cmd_resetLoopIp(const uint16 *param);
|
||||
int cmd_resetAllRuntimes(const uint16 *param);
|
||||
int cmd_execOpcode(const uint16 *param);
|
||||
int cmd_initFuncNow(const uint16 *param);
|
||||
int cmd_stopFuncNow(const uint16 *param);
|
||||
#define cmd_return(n, v) \
|
||||
int cmd_return_##n(const uint16 *){ return v; }
|
||||
cmd_return( 1, 1)
|
||||
cmd_return(n1, -1)
|
||||
#undef cmd_return
|
||||
};
|
||||
|
||||
#ifdef ENABLE_LOL
|
||||
class LoLEngine;
|
||||
class Screen_LoL;
|
||||
class TIMInterpreter_LoL : public TIMInterpreter {
|
||||
public:
|
||||
TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system);
|
||||
|
||||
int initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams) override;
|
||||
int freeAnimStruct(int index) override;
|
||||
|
||||
void resetDialogueState(TIM *tim) override;
|
||||
|
||||
private:
|
||||
void update() override;
|
||||
void checkSpeechProgress() override;
|
||||
|
||||
const char *getTableString(int id);
|
||||
void advanceToOpcode(int opcode);
|
||||
|
||||
LoLEngine *_vm;
|
||||
Screen_LoL *_screen;
|
||||
|
||||
int execCommand(int cmd, const uint16 *param) override;
|
||||
|
||||
typedef int (TIMInterpreter_LoL::*CommandProc)(const uint16 *);
|
||||
struct CommandEntry {
|
||||
CommandProc proc;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
const CommandEntry *_commands;
|
||||
int _commandsSize;
|
||||
|
||||
int cmd_stopAllFuncs(const uint16 *param);
|
||||
int cmd_setLoopIp(const uint16 *param) override;
|
||||
int cmd_continueLoop(const uint16 *param) override;
|
||||
int cmd_processDialogue(const uint16 *param);
|
||||
int cmd_dialogueBox(const uint16 *param);
|
||||
};
|
||||
#endif // ENABLE_LOL
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
||||
#endif
|
||||
125
engines/kyra/script/script_v1.cpp
Normal file
125
engines/kyra/script/script_v1.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/kyra_v1.h"
|
||||
#include "kyra/graphics/screen.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
int KyraEngine_v1::o1_queryGameFlag(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_queryGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
|
||||
return queryGameFlag(stackPos(0));
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_setGameFlag(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
|
||||
return setGameFlag(stackPos(0));
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_resetGameFlag(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_resetGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
|
||||
return resetGameFlag(stackPos(0));
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_getRand(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getRand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
int min = stackPos(0);
|
||||
int max = stackPos(1);
|
||||
if (max < min)
|
||||
SWAP(min, max);
|
||||
return _rnd.getRandomNumberRng(min, max);
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_hideMouse(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_hideMouse(%p) ()", (const void *)script);
|
||||
screen()->hideMouse();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_showMouse(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_showMouse(%p) ()", (const void *)script);
|
||||
screen()->showMouse();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_setMousePos(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setMousePos(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
setMousePos(stackPos(0), stackPos(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_setHandItem(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setHandItem(%p) (%d)", (const void *)script, stackPos(0));
|
||||
setHandItem(stackPos(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_removeHandItem(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_removeHandItem(%p) ()", (const void *)script);
|
||||
removeHandItem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_getMouseState(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_getMouseState(%p) ()", (const void *)script);
|
||||
return _mouseState;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_setDeathHandler(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_setDeathHandler(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_deathHandler = stackPos(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_playWanderScoreViaMap(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playWanderScoreViaMap(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
snd_playWanderScoreViaMap(stackPos(0), stackPos(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_fillRect(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_fillRect(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
|
||||
screen()->fillRect(stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_blockInWalkableRegion(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_blockInWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
|
||||
screen()->blockInRegion(stackPos(0), stackPos(1), stackPos(2) - stackPos(0) + 1, stackPos(3) - stackPos(1) + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_blockOutWalkableRegion(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
|
||||
screen()->blockOutRegion(stackPos(0), stackPos(1), stackPos(2) - stackPos(0) + 1, stackPos(3) - stackPos(1) + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v1::o1_playSoundEffect(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1_playSoundEffect(%p) (%d)", (const void *)script, stackPos(0));
|
||||
if (!_preventScriptSfx)
|
||||
snd_playSoundEffect(stackPos(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
341
engines/kyra/script/script_v2.cpp
Normal file
341
engines/kyra/script/script_v2.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kyra/engine/kyra_v2.h"
|
||||
#include "kyra/graphics/screen_v2.h"
|
||||
#include "kyra/engine/timer.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Kyra {
|
||||
|
||||
int KyraEngine_v2::o2_getCharacterX(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getCharacterX(%p) ()", (const void *)script);
|
||||
return _mainCharacter.x1;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_getCharacterY(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getCharacterY(%p) ()", (const void *)script);
|
||||
return _mainCharacter.y1;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_getCharacterFacing(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getCharacterFacing(%p) ()", (const void *)script);
|
||||
return _mainCharacter.facing;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_getCharacterScene(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getCharacterScene(%p) ()", (const void *)script);
|
||||
return _mainCharacter.sceneId;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_setCharacterFacingOverwrite(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setCharacterFacingOverwrite(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_mainCharacter.facing = stackPos(0);
|
||||
_overwriteSceneFacing = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_trySceneChange(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_trySceneChange(%p) (%d, %d, %d, %d)", (const void *)script,
|
||||
stackPos(0), stackPos(1), stackPos(2), stackPos(3));
|
||||
|
||||
_unkHandleSceneChangeFlag = 1;
|
||||
int success = inputSceneChange(stackPos(0), stackPos(1), stackPos(2), stackPos(3));
|
||||
_unkHandleSceneChangeFlag = 0;
|
||||
|
||||
if (success) {
|
||||
_emc->init(script, script->dataPtr);
|
||||
_unk4 = 0;
|
||||
_savedMouseState = -1;
|
||||
_unk5 = 1;
|
||||
return 0;
|
||||
} else {
|
||||
return (_unk4 != 0) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_moveCharacter(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_moveCharacter(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
|
||||
moveCharacter(stackPos(0), stackPos(1), stackPos(2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_checkForItem(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_checkForItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
return findItem(stackPos(0), stackPos(1)) == -1 ? 0 : 1;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_defineItem(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_defineItem(%p) (%d, %d, %d, %d)", (const void *)script,
|
||||
stackPos(0), stackPos(1), stackPos(2), stackPos(3));
|
||||
int freeItem = findFreeItem();
|
||||
|
||||
if (freeItem >= 0) {
|
||||
_itemList[freeItem].id = stackPos(0);
|
||||
_itemList[freeItem].x = stackPos(1);
|
||||
_itemList[freeItem].y = stackPos(2);
|
||||
_itemList[freeItem].sceneId = stackPos(3);
|
||||
}
|
||||
|
||||
return freeItem;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_addSpecialExit(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_addSpecialExit(%p) (%d, %d, %d, %d, %d)", (const void *)script,
|
||||
stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
|
||||
if (_specialExitCount < 5) {
|
||||
_specialExitTable[_specialExitCount + 0] = stackPos(0);
|
||||
_specialExitTable[_specialExitCount + 5] = stackPos(1);
|
||||
_specialExitTable[_specialExitCount + 10] = stackPos(2) + stackPos(0) - 1;
|
||||
_specialExitTable[_specialExitCount + 15] = stackPos(3) + stackPos(1) - 1;
|
||||
_specialExitTable[_specialExitCount + 20] = stackPos(4);
|
||||
++_specialExitCount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_delay(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_delay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
if (stackPos(1)) {
|
||||
uint32 maxWaitTime = _system->getMillis() + stackPos(0) * _tickLength;
|
||||
while (_system->getMillis() < maxWaitTime) {
|
||||
int inputFlag = checkInput(nullptr);
|
||||
removeInputTop();
|
||||
|
||||
if (inputFlag == 198 || inputFlag == 199)
|
||||
return 1;
|
||||
|
||||
if (!_chatText.empty())
|
||||
updateWithText();
|
||||
else
|
||||
update();
|
||||
_system->delayMillis(10);
|
||||
}
|
||||
} else {
|
||||
delay(stackPos(0) * _tickLength, true);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_update(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_update(%p) (%d)", (const void *)script, stackPos(0));
|
||||
for (int times = stackPos(0); times != 0; --times) {
|
||||
if (!_chatText.empty())
|
||||
updateWithText();
|
||||
else
|
||||
update();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_getShapeFlag1(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getShapeFlag1(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
return screen()->getShapeFlag1(stackPos(0), stackPos(1));
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_waitForConfirmationClick(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_waitForConfirmationClick(%p) (%d)", (const void *)script, stackPos(0));
|
||||
resetSkipFlag();
|
||||
uint32 maxWaitTime = _system->getMillis() + stackPos(0) * _tickLength;
|
||||
|
||||
while (_system->getMillis() < maxWaitTime) {
|
||||
int inputFlag = checkInput(nullptr);
|
||||
removeInputTop();
|
||||
|
||||
if (inputFlag == 198 || inputFlag == 199) {
|
||||
_sceneScriptState.regs[1] = _mouseX;
|
||||
_sceneScriptState.regs[2] = _mouseY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
update();
|
||||
_system->delayMillis(10);
|
||||
}
|
||||
|
||||
_sceneScriptState.regs[1] = _mouseX;
|
||||
_sceneScriptState.regs[2] = _mouseY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_randomSceneChat(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_randomSceneChat(%p)", (const void *)script);
|
||||
randomSceneChat();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_setDlgIndex(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setDlgIndex(%p) (%d)", (const void *)script, stackPos(0));
|
||||
setDlgIndex(stackPos(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_getDlgIndex(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getDlgIndex(%p) ()", (const void *)script);
|
||||
return _mainCharacter.dlgIndex;
|
||||
}
|
||||
|
||||
|
||||
int KyraEngine_v2::o2_defineRoomEntrance(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_defineRoomEntrance(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
|
||||
switch (stackPos(0)) {
|
||||
case 0:
|
||||
_sceneEnterX1 = stackPos(1);
|
||||
_sceneEnterY1 = stackPos(2);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_sceneEnterX2 = stackPos(1);
|
||||
_sceneEnterY2 = stackPos(2);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_sceneEnterX3 = stackPos(1);
|
||||
_sceneEnterY3 = stackPos(2);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_sceneEnterX4 = stackPos(1);
|
||||
_sceneEnterY4 = stackPos(2);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_runAnimationScript(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_runAnimationScript(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1),
|
||||
stackPos(2), stackPos(3));
|
||||
|
||||
runAnimationScript(stackPosString(0), stackPos(3), stackPos(2) ? 1 : 0, stackPos(1), stackPos(2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_setSpecialSceneScriptRunTime(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setSpecialSceneScriptRunTime(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
assert(stackPos(0) >= 0 && stackPos(0) < 10);
|
||||
_sceneSpecialScriptsTimer[stackPos(0)] = _system->getMillis() + stackPos(1) * _tickLength;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_defineScene(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_defineScene(%p) (%d, '%s', %d, %d, %d, %d, %d, %d)",
|
||||
(const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
|
||||
const int scene = stackPos(0);
|
||||
Common::strlcpy(_sceneList[scene].filename1, stackPosString(1), sizeof(_sceneList[scene].filename1));
|
||||
Common::strlcpy(_sceneList[scene].filename2, stackPosString(1), sizeof(_sceneList[scene].filename2));
|
||||
|
||||
_sceneList[scene].exit1 = stackPos(2);
|
||||
_sceneList[scene].exit2 = stackPos(3);
|
||||
_sceneList[scene].exit3 = stackPos(4);
|
||||
_sceneList[scene].exit4 = stackPos(5);
|
||||
_sceneList[scene].flags = stackPos(6);
|
||||
_sceneList[scene].sound = stackPos(7);
|
||||
|
||||
if (_mainCharacter.sceneId == scene) {
|
||||
_sceneExit1 = _sceneList[scene].exit1;
|
||||
_sceneExit2 = _sceneList[scene].exit2;
|
||||
_sceneExit3 = _sceneList[scene].exit3;
|
||||
_sceneExit4 = _sceneList[scene].exit4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_setSpecialSceneScriptState(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setSpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_specialSceneScriptState[stackPos(0)] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_clearSpecialSceneScriptState(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_clearSpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_specialSceneScriptState[stackPos(0)] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_querySpecialSceneScriptState(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_querySpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0));
|
||||
return _specialSceneScriptState[stackPos(0)];
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_setHiddenItemsEntry(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setHiddenItemsEntry(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
return (_hiddenItems[stackPos(0)] = stackPos(1));
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_getHiddenItemsEntry(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getHiddenItemsEntry(%p) (%d)", (const void *)script, stackPos(0));
|
||||
return (int16)_hiddenItems[stackPos(0)];
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_disableTimer(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_disableTimer(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_timer->disable(stackPos(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_enableTimer(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_enableTimer(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_timer->enable(stackPos(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_setTimerCountdown(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setTimerCountdown(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
|
||||
_timer->setCountdown(stackPos(0), stackPos(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_setVocHigh(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setVocHigh(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_vocHigh = stackPos(0);
|
||||
return _vocHigh;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2_getVocHigh(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_getVocHigh(%p) ()", (const void *)script);
|
||||
return _vocHigh;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
int KyraEngine_v2::o2a_setAnimationShapes(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2a_setAnimationShapes(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script,
|
||||
stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
|
||||
Common::strlcpy(_animShapeFilename, stackPosString(0), sizeof(_animShapeFilename));
|
||||
_animShapeLastEntry = stackPos(1);
|
||||
_animShapeWidth = stackPos(2);
|
||||
_animShapeHeight = stackPos(3);
|
||||
_animShapeXAdd = stackPos(4);
|
||||
_animShapeYAdd = stackPos(5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KyraEngine_v2::o2a_setResetFrame(EMCState *script) {
|
||||
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3t_setResetFrame(%p) (%d)", (const void *)script, stackPos(0));
|
||||
_animResetFrame = stackPos(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
Reference in New Issue
Block a user