ScummVM API documentation
vm.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21#ifndef GAMOS_VM_H
22#define GAMOS_VM_H
23
24#include "common/array.h"
25#include "common/hashmap.h"
26
27namespace Gamos {
28
29class VM {
30public:
31 static constexpr const uint THREADS_COUNT = 2;
32 static constexpr const uint STACK_SIZE = 0x100;
33 static constexpr const uint STACK_POS = 0x80;
34 static constexpr const uint MEMTYPE_SHIFT = 30;
35 static constexpr const uint ADDRESS_MASK = (1 << MEMTYPE_SHIFT) - 1;
36
37 enum OP {
38 OP_EXIT = 0,
39 OP_CMP_EQ = 1,
40 OP_CMP_NE = 2,
41 OP_CMP_LE = 3,
42 OP_CMP_LEQ = 4,
43 OP_CMP_GR = 5,
44 OP_CMP_GREQ = 6,
45 OP_CMP_NAE = 7,
46 OP_CMP_NA = 8,
47 OP_CMP_A = 9,
48 OP_CMP_AE = 10,
49 OP_BRANCH = 11,
50 OP_JMP = 12,
51 OP_SP_ADD = 13,
52 OP_MOV_EDI_ECX_AL = 14,
53 OP_MOV_EBX_ECX_AL = 15,
54 OP_MOV_EDI_ECX_EAX = 16,
55 OP_MOV_EBX_ECX_EAX = 17,
56 OP_RET = 18,
57 OP_RETX = 19,
58 OP_MOV_EDX_EAX = 20,
59 OP_ADD_EAX_EDX = 21,
60 OP_MUL = 22,
61 OP_OR = 23,
62 OP_XOR = 24,
63 OP_AND = 25,
64 OP_NEG = 26,
65 OP_SAR = 27,
66 OP_SHL = 28,
67 OP_LOAD = 29,
68 OP_INC = 30,
69 OP_DEC = 31,
70 OP_XCHG = 32,
71 OP_PUSH_EAX = 33,
72 OP_POP_EDX = 34,
73 OP_LOAD_OFFSET_EDI = 35,
74 OP_LOAD_OFFSET_EDI2 = 36,
75 OP_LOAD_OFFSET_EBX = 37,
76 OP_LOAD_OFFSET_ESP = 38,
77 OP_MOV_PTR_EDX_AL = 39,
78 OP_MOV_PTR_EDX_EAX = 40,
79 OP_SHL_2 = 41,
80 OP_ADD_4 = 42,
81 OP_SUB_4 = 43,
82 OP_XCHG_ESP = 44,
83 OP_NEG_ADD = 45,
84 OP_DIV = 46,
85 OP_MOV_EAX_BPTR_EDI = 47,
86 OP_MOV_EAX_BPTR_EBX = 48,
87 OP_MOV_EAX_DPTR_EDI = 49,
88 OP_MOV_EAX_DPTR_EBX = 50,
89 OP_MOV_EAX_BPTR_EAX = 51,
90 OP_MOV_EAX_DPTR_EAX = 52,
91 OP_PUSH_ESI_ADD_EDI = 53,
92 OP_CALL_FUNC = 54,
93 OP_PUSH_ESI_SET_EDX_EDI = 55,
94
95 OP_MAX
96 };
97
98 enum MEMREF {
99 REF_UNK = 0,
100 REF_STACK = 1,
101 REF_EBX = 2,
102 REF_EDI = 3
103 };
104
105 struct ValAddr {
106 uint32 value = 0;
107
108 inline uint32 getVal() const { return value; };
109 inline void setVal(uint32 v) { value = v; };
110
111 inline uint32 getOffset() const { return value & ADDRESS_MASK; };
112 inline uint getMemType() const { return (value >> MEMTYPE_SHIFT ) & 3; };
113
114 inline void setMemType(uint tp) { value = (value & ADDRESS_MASK) | ((tp & 3) << MEMTYPE_SHIFT); };
115 inline void setOffset(uint32 offset) { value = (value & (~ADDRESS_MASK)) | (offset & ADDRESS_MASK); };
116
117 inline void setAddress(uint tp, uint32 offset) { value = (offset & ADDRESS_MASK) | ((tp & 3) << MEMTYPE_SHIFT); };
118 };
119
120 struct MemoryBlock {
121 uint32 address = 0;
122 byte data[256];
123
124 MemoryBlock() {
125 address = 0;
126 memset(data, 0, sizeof(data));
127 }
128 };
129
130 struct OpLog {
131 uint32 addr;
132 OP op;
133 uint32 sp;
134 };
135
136 struct MemAccess {
137 MemAccess(VM &vm): _vm(vm) {};
138
139 VM &_vm;
140 MemoryBlock *_currentBlock = nullptr;
141
142 uint8 getU8(uint32 address);
143 uint32 getU32(uint32 address);
144
145 void setU8(uint32 address, uint8 val);
146 void setU32(uint32 address, uint32 val);
147
148 void reset() {
149 _currentBlock = nullptr;
150 }
151 };
152
153 class Context {
154 public:
155 Context(VM &vm): _vm(vm), _readAccess(vm), _writeAccess(vm) {
156 memset(_stack, 0, sizeof(_stack));
157 };
158
159 Common::String getString(int memtype, uint32 offset, uint32 maxLen = 256);
160 Common::String getString(const ValAddr &addr, uint32 maxLen = 256);
161
162 uint32 execute(uint32 scriptAddress, byte *storage = nullptr);
163
164 void push32(uint32 val);
165 uint32 pop32();
166
167 void pushReg(ValAddr reg);
168 ValAddr popReg();
169
170 uint32 getMem32(int memtype, uint32 offset);
171 uint32 getMem32(const ValAddr& addr);
172 uint8 getMem8(int memtype, uint32 offset);
173 uint8 getMem8(const ValAddr& addr);
174
175 void setMem32(int memtype, uint32 offset, uint32 val);
176 void setMem32(const ValAddr& addr, uint32 val);
177 void setMem8(int memtype, uint32 offset, uint8 val);
178 void setMem8(const ValAddr& addr, uint8 val);
179
180 public:
181 VM &_vm;
182 bool _inUse = false;
183
184 uint32 ESI = 0;
185 byte *EBX = nullptr;
186 ValAddr EAX;
187 ValAddr EDX;
188 ValAddr ECX;
189 uint32 SP = 0;
190 byte _stack[STACK_SIZE];
191
192 private:
193 MemAccess _readAccess;
194 MemAccess _writeAccess;
195 };
196
197 typedef void (* CallDispatcher)(void *object, Context *state, uint32 funcID);
198
199public:
200 friend class Context;
201
202public:
203 VM(void *obj, CallDispatcher dispatcher): _memAccess(*this), _threads{*this, *this}, _callFuncs(dispatcher), _callingObject(obj) {};
204
205 inline MemAccess &memory() {
206 return _memAccess;
207 };
208
209 void clearMemory();
210 void writeMemory(uint32 address, const byte* data, uint32 dataSize);
211
212 void zeroMemory(uint32 address, uint32 count);
213
214 MemoryBlock *findMemoryBlock(uint32 address);
215
216 MemoryBlock *createBlock(uint32 address);
217
218 Common::Array<byte> readMemBlocks(uint32 address, uint32 count);
219 void readMemBlocks(byte *dst, uint32 address, uint32 count);
220
221 Common::String readMemString(uint32 address, uint32 maxLen = 256);
222
223 uint32 doScript(uint32 scriptAddress, byte *storage = nullptr);
224
225 static int32 getS32(const void *);
226 static uint32 getU32(const void *);
227 static void setU32(void *, uint32 val);
228
229 Common::String decodeOp(uint32 address, int *size = nullptr);
230 Common::String disassembly(uint32 address);
231
232 Common::String opLog(const Common::Array<OpLog> &log);
233
234 void printDisassembly(uint32 address);
235
236protected:
238
239 MemAccess _memAccess;
240
241 Context _threads[THREADS_COUNT];
242
243 CallDispatcher const _callFuncs = nullptr;
244 void * const _callingObject = nullptr;
245
246public:
247
248 bool _interrupt = false;
249};
250
251
252}
253
254#endif
Definition: hashmap.h:85
Definition: str.h:59
Definition: vm.h:153
Definition: vm.h:29
Definition: vm.h:136
Definition: vm.h:120
Definition: vm.h:130
Definition: vm.h:105