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  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 
199 public:
200  friend class Context;
201 
202 public:
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 
236 protected:
238 
239  MemAccess _memAccess;
240 
241  Context _threads[THREADS_COUNT];
242 
243  CallDispatcher const _callFuncs = nullptr;
244  void * const _callingObject = nullptr;
245 
246 public:
247 
248  bool _interrupt = false;
249 };
250 
251 
252 }
253 
254 #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