1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
/* ScummVM - Kyrandia Interpreter
* Copyright (C) 2003-2005 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*
*/
#ifndef VM_H
#define VM_H
namespace Kyra {
// TODO:
// find out more script functions
enum ScriptFunc {
kSetupScene = 0,
kClickEvent = 1, // _registers[1] and _registers[2] are mouse x, y _registers[4] is action
kActorEvent = 2,
kEnterEvent = 4,
kExitEvent = 5,
kLoadResources = 7
};
enum ScriptState {
kScriptStopped = 0,
kScriptRunning = 1,
kScriptWaiting = 2,
kScriptError = 3
};
class VMContext {
public:
VMContext(KyraEngine* engine);
~VMContext() { delete [] _scriptFile; }
void loadScript(const char* file);
const char* stringAtIndex(int32 index);
// TODO: check for 'over'flow
void pushStack(int32 value) { _stack[_stackPos++] = value; }
void registerValue(int32 reg, int32 value) { _registers[reg] = value; }
int32 checkReg(int32 reg) { return _registers[reg]; }
uint32 state(void) { return _scriptState; }
bool startScript(int32 func);
uint32 contScript(void);
protected:
KyraEngine* _engine;
uint8* _scriptFile;
uint32 _scriptFileSize;
uint32 _scriptState;
uint32 _delay;
int32 _registers[32]; // registers of the interpreter
int32 _stack[64]; // our stack
// TODO: check for 'under'flow
int32 popStack(void) { return _stack[--_stackPos]; }
int32& topStack(void) { return _stack[_stackPos]; }
uint32 _returnValue;
int32 _nextScriptPos;
int32 _instructionPos;
int32 _stackPos;
int32 _tempPos;
// used by command & opcode procs
uint16 _argument;
uint8 _currentCommand;
uint32 _currentOpcode;
int32 param(int32 index);
const char* paramString(int32 index) { return stringAtIndex(param(index)); }
bool _error; // used by all command- and opcodefuncs
enum ScriptChunkTypes {
kForm = 0,
kEmc2Ordr = 1,
kText = 2,
kData = 3,
kCountChunkTypes
};
struct ScriptChunk {
uint32 _size;
uint8* _data; // by TEXT used for count of texts, by EMC2ODRD it is used for a count of somewhat
uint8* _additional; // currently only used for TEXT
};
ScriptChunk _chunks[kCountChunkTypes];
typedef void (VMContext::*CommandProc)();
struct CommandEntry {
CommandProc proc;
const char* desc;
};
typedef void (VMContext::*OpcodeProc)();
struct OpcodeEntry {
OpcodeProc proc;
const char* desc;
};
uint16 _numCommands;
const CommandEntry* _commands;
uint16 _numOpcodes;
const OpcodeEntry* _opcodes;
protected:
// the command procs
void c1_goToLine(void); // 0x00
void c1_setReturn(void); // 0x01
void c1_pushRetRec(void); // 0x02
void c1_push(void); // 0x03 & 0x04
void c1_pushVar(void); // 0x05
void c1_pushFrameNeg(void); // 0x06
void c1_pushFramePos(void); // 0x07
void c1_popRetRec(void); // 0x08
void c1_popVar(void); // 0x09
void c1_popFrameNeg(void); // 0x0A
void c1_popFramePos(void); // 0x0B
void c1_addToSP(void); // 0x0C
void c1_subFromSP(void); // 0x0D
void c1_execOpcode(void); // 0x0E
void c1_ifNotGoTo(void); // 0x0F
void c1_negate(void); // 0x10
void c1_evaluate(void); // 0x11
void c1_unknownCommand(void);
// the opcode procs
void o1_0x68(void); // 0x68
void o1_unknownOpcode(void);
};
} // end of namespace Kyra
#endif
|