2014-07-21 01:34:28 +02:00
|
|
|
#pragma once
|
|
|
|
#ifndef _SCRIPTMACHINE_HPP_
|
|
|
|
#define _SCRIPTMACHINE_HPP_
|
2014-07-24 00:57:21 +02:00
|
|
|
#include <script/ScriptTypes.hpp>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iomanip>
|
2014-07-21 01:34:28 +02:00
|
|
|
#include <string>
|
2014-07-24 00:57:21 +02:00
|
|
|
#include <vector>
|
2014-07-21 01:34:28 +02:00
|
|
|
|
|
|
|
#define SCM_CONDITIONAL_MASK 0xF000
|
2014-07-24 00:57:21 +02:00
|
|
|
#define SCM_THREAD_LOCAL_SIZE 256
|
|
|
|
|
|
|
|
class SCMFile;
|
2014-07-21 01:34:28 +02:00
|
|
|
|
|
|
|
struct SCMException
|
|
|
|
{
|
|
|
|
virtual ~SCMException() { }
|
|
|
|
virtual std::string what() const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IllegalInstruction : SCMException
|
|
|
|
{
|
|
|
|
SCMOpcode opcode;
|
|
|
|
unsigned int offset;
|
2014-07-24 00:57:21 +02:00
|
|
|
std::string thread;
|
2014-07-21 01:34:28 +02:00
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
IllegalInstruction(SCMOpcode opcode, unsigned int offset, const std::string& thread)
|
|
|
|
: opcode(opcode), offset(offset), thread(thread) { }
|
2014-07-21 01:34:28 +02:00
|
|
|
|
|
|
|
std::string what() const {
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "Illegal Instruction " <<
|
|
|
|
std::setfill('0') << std::setw(4) << std::hex << opcode <<
|
|
|
|
" encountered at offset " <<
|
2014-07-24 00:57:21 +02:00
|
|
|
std::setfill('0') << std::setw(4) << std::hex << offset <<
|
|
|
|
" on thread " << thread;
|
2014-07-21 01:34:28 +02:00
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UnknownType : SCMException
|
|
|
|
{
|
|
|
|
SCMByte type;
|
|
|
|
unsigned int offset;
|
2014-07-24 00:57:21 +02:00
|
|
|
std::string thread;
|
2014-07-21 01:34:28 +02:00
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
UnknownType(SCMByte type, unsigned int offset, const std::string& thread)
|
|
|
|
: type(type), offset(offset), thread(thread) {}
|
2014-07-21 01:34:28 +02:00
|
|
|
|
|
|
|
std::string what() const {
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "Unkown data type " <<
|
|
|
|
std::setfill('0') << std::hex << static_cast<unsigned int>(type) <<
|
|
|
|
" encountered at offset " <<
|
2014-07-24 00:57:21 +02:00
|
|
|
std::setfill('0') << std::hex << offset <<
|
|
|
|
" on thread " << thread;
|
2014-07-21 01:34:28 +02:00
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
static SCMMicrocodeTable knownOps;
|
|
|
|
|
|
|
|
struct SCMThread
|
|
|
|
{
|
|
|
|
typedef unsigned int pc_t;
|
|
|
|
|
2014-07-21 01:34:28 +02:00
|
|
|
std::string name;
|
2014-07-24 00:57:21 +02:00
|
|
|
pc_t programCounter;
|
|
|
|
/** Number of MS until the thread should be waked (-1 = yeilded) */
|
|
|
|
int wakeCounter;
|
|
|
|
SCMByte locals[SCM_THREAD_LOCAL_SIZE];
|
2014-07-21 01:34:28 +02:00
|
|
|
};
|
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
class ScriptMachine
|
|
|
|
{
|
|
|
|
SCMFile* _file;
|
|
|
|
SCMOpcodes* _ops;
|
2014-07-21 01:34:28 +02:00
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
std::vector<SCMThread> _activeThreads;
|
2014-07-21 01:34:28 +02:00
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
void executeThread(SCMThread& t, int msPassed);
|
2014-07-21 01:34:28 +02:00
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
public:
|
|
|
|
ScriptMachine(SCMFile* file, SCMOpcodes* ops);
|
|
|
|
~ScriptMachine();
|
|
|
|
|
|
|
|
void startThread(SCMThread::pc_t start);
|
2014-07-21 01:34:28 +02:00
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
SCMByte* getGlobals();
|
2014-07-21 01:34:28 +02:00
|
|
|
|
2014-07-24 00:57:21 +02:00
|
|
|
/**
|
|
|
|
* @brief executes threads until they are all in waiting state.
|
|
|
|
*/
|
|
|
|
void execute(float dt);
|
2014-07-21 01:34:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|