2010-10-08 22:30:39 +00:00
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef TOON_SCRIPT_H
|
|
|
|
#define TOON_SCRIPT_H
|
|
|
|
|
|
|
|
#include "common/stream.h"
|
|
|
|
#include "common/array.h"
|
|
|
|
#include "common/func.h"
|
|
|
|
#include "common/iff_container.h"
|
|
|
|
|
|
|
|
// Based on Kyra script interpretor
|
|
|
|
namespace Toon {
|
|
|
|
|
|
|
|
struct EMCState;
|
2010-10-13 07:14:38 +00:00
|
|
|
class ScriptFunc;
|
|
|
|
typedef Common::Functor1Mem<EMCState *, int32, ScriptFunc> OpcodeV2;
|
2010-10-08 22:30:39 +00:00
|
|
|
|
|
|
|
struct EMCData {
|
|
|
|
char filename[13];
|
|
|
|
|
|
|
|
byte *text;
|
|
|
|
uint16 *data;
|
|
|
|
uint16 *ordr;
|
|
|
|
uint16 dataSize;
|
|
|
|
|
2010-10-13 07:14:38 +00:00
|
|
|
const Common::Array<const OpcodeV2 *> *sysFuncs;
|
2010-10-08 22:30:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
|
bool running;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define stackPos(x) (state->stack[state->sp+x])
|
|
|
|
#define stackPosString(x) ((const char *)&state->dataPtr->text[READ_BE_UINT16(&state->dataPtr->text[stackPos(x)<<1])])
|
|
|
|
|
|
|
|
class Resource;
|
|
|
|
class ToonEngine;
|
|
|
|
|
|
|
|
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 accidently 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.
|
2011-04-12 14:53:15 +00:00
|
|
|
if (_formType == MKTAG('E','M','C','2'))
|
2010-10-08 22:30:39 +00:00
|
|
|
_formChunk.size -= 8;
|
2011-04-12 14:53:15 +00:00
|
|
|
else if (_formType == MKTAG('A','V','F','S'))
|
2010-10-08 22:30:39 +00:00
|
|
|
_formChunk.size += 4;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class EMCInterpreter {
|
|
|
|
public:
|
|
|
|
EMCInterpreter(ToonEngine *vm);
|
2010-11-08 03:14:32 +00:00
|
|
|
~EMCInterpreter();
|
2010-10-08 22:30:39 +00:00
|
|
|
|
2010-10-13 07:14:38 +00:00
|
|
|
bool load(const char *filename, EMCData *data, const Common::Array<const OpcodeV2 *> *opcodes);
|
2010-10-08 22:30:39 +00:00
|
|
|
void unload(EMCData *data);
|
|
|
|
|
|
|
|
void init(EMCState *scriptState, const EMCData *data);
|
|
|
|
bool start(EMCState *script, int function);
|
|
|
|
|
2010-10-09 11:11:26 +00:00
|
|
|
void saveState(EMCState *script, Common::WriteStream *stream);
|
|
|
|
void loadState(EMCState *script, Common::ReadStream *stream);
|
2010-10-08 22:30:39 +00:00
|
|
|
|
|
|
|
bool isValid(EMCState *script);
|
|
|
|
|
|
|
|
bool run(EMCState *script);
|
|
|
|
protected:
|
|
|
|
ToonEngine *_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 *);
|
|
|
|
};
|
2010-11-08 03:14:32 +00:00
|
|
|
|
2010-10-08 22:30:39 +00:00
|
|
|
} // End of namespace Toon
|
|
|
|
|
|
|
|
#endif
|