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 
27 namespace Gamos {
28 
29 class VM {
30 public:
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 
157  Common::String getString(int memtype, uint32 offset, uint32 maxLen = 256);
158  Common::String getString(const ValAddr &addr, uint32 maxLen = 256);
159 
160  uint32 execute(uint32 scriptAddress, byte *storage = nullptr);
161 
162  void push32(uint32 val);
163  uint32 pop32();
164 
165  void pushReg(ValAddr reg);
166  ValAddr popReg();
167 
168  uint32 getMem32(int memtype, uint32 offset);
169  uint32 getMem32(const ValAddr& addr);
170  uint8 getMem8(int memtype, uint32 offset);
171  uint8 getMem8(const ValAddr& addr);
172 
173  void setMem32(int memtype, uint32 offset, uint32 val);
174  void setMem32(const ValAddr& addr, uint32 val);
175  void setMem8(int memtype, uint32 offset, uint8 val);
176  void setMem8(const ValAddr& addr, uint8 val);
177 
178  public:
179  VM &_vm;
180  bool _inUse = false;
181 
182  uint32 ESI = 0;
183  byte *EBX = nullptr;
184  ValAddr EAX;
185  ValAddr EDX;
186  ValAddr ECX;
187  uint32 SP = 0;
188  byte _stack[STACK_SIZE];
189 
190  private:
191  MemAccess _readAccess;
192  MemAccess _writeAccess;
193  };
194 
195  typedef void (* CallDispatcher)(void *object, Context *state, uint32 funcID);
196 
197 public:
198  friend class Context;
199 
200 public:
201  VM(void *obj, CallDispatcher dispatcher): _memAccess(*this), _threads{*this, *this}, _callFuncs(dispatcher), _callingObject(obj) {};
202 
203  inline MemAccess &memory() {
204  return _memAccess;
205  };
206 
207  void clearMemory();
208  void writeMemory(uint32 address, const byte* data, uint32 dataSize);
209 
210  void zeroMemory(uint32 address, uint32 count);
211 
212  MemoryBlock *findMemoryBlock(uint32 address);
213 
214  MemoryBlock *createBlock(uint32 address);
215 
216  Common::Array<byte> readMemBlocks(uint32 address, uint32 count);
217  void readMemBlocks(byte *dst, uint32 address, uint32 count);
218 
219  Common::String readMemString(uint32 address, uint32 maxLen = 256);
220 
221  uint32 doScript(uint32 scriptAddress, byte *storage = nullptr);
222 
223  static int32 getS32(const void *);
224  static uint32 getU32(const void *);
225  static void setU32(void *, uint32 val);
226 
227  Common::String decodeOp(uint32 address, int *size = nullptr);
228  Common::String disassembly(uint32 address);
229 
230  Common::String opLog(const Common::Array<OpLog> &log);
231 
232  void printDisassembly(uint32 address);
233 
234 protected:
236 
237  MemAccess _memAccess;
238 
239  Context _threads[THREADS_COUNT];
240 
241  CallDispatcher const _callFuncs = nullptr;
242  void * const _callingObject = nullptr;
243 
244 public:
245 
246  bool _interrupt = false;
247 };
248 
249 
250 }
251 
252 #endif
Definition: vm.h:130
Definition: str.h:59
Definition: vm.h:105
Definition: blit.h:28
Definition: vm.h:153
Definition: vm.h:136
Definition: hashmap.h:85
Definition: vm.h:29
Definition: vm.h:120