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 
22 #ifndef SCI_ENGINE_VM_H
23 #define SCI_ENGINE_VM_H
24 
25 /* VM and kernel declarations */
26 
27 #include "sci/engine/vm_types.h" // for reg_t
28 #include "sci/resource/resource.h" // for SciVersion
29 
30 #include "common/util.h"
31 
32 namespace Sci {
33 
34 class SegManager;
35 struct EngineState;
36 class Object;
37 class ResourceManager;
38 class Script;
39 
41 #define VM_STACK_SIZE 0x1000
42 
44 #define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234
45 
47 #define SCRIPT_OBJECT_MAGIC_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? -8 : 0)
48 
50 #define CALL_SP_CARRY NULL
51 
54  kSelectorNone = 0,
55  kSelectorVariable,
56  kSelectorMethod
57 };
58 
59 struct Class {
60  int script;
62 };
63 
64 // A reference to an object's variable.
65 // The object is stored as a reg_t, the variable as an index into _variables
66 struct ObjVarRef {
67  reg_t obj;
68  int varindex;
69 
70  reg_t* getPointer(SegManager *segMan) const;
71 };
72 
73 enum ExecStackType {
74  EXEC_STACK_TYPE_CALL = 0,
75  EXEC_STACK_TYPE_KERNEL = 1,
76  EXEC_STACK_TYPE_VARSELECTOR = 2
77 };
78 
79 struct ExecStack {
82 
83  union {
84  ObjVarRef varp; // Variable pointer for r/w access
85  reg_t pc; // Pointer to the initial program counter. Not accurate for the TOS element
86  } addr;
87 
88  StackPtr fp; // Frame pointer
89  StackPtr sp; // Stack pointer
90 
91  int argc;
92  StackPtr variables_argp; // Argument pointer
93 
94  int tempCount; // Number of temp variables allocated by link opcode
95 
96  SegmentId local_segment; // local variables etc
97 
98  Selector debugSelector; // The selector which was used to call or -1 if not applicable
99  int debugExportId; // The exportId which was called or -1 if not applicable
100  int debugLocalCallOffset; // Local call offset or -1 if not applicable
101  int debugOrigin; // The stack frame position the call was made from, or -1 if it was the initial call
102  int debugKernelFunction; // The kernel function called, or -1 if not applicable
103  int debugKernelSubFunction; // The kernel subfunction called, or -1 if not applicable
104  ExecStackType type;
105 
106  reg_t* getVarPointer(SegManager *segMan) const;
107 
108  ExecStack(reg_t objp_, reg_t sendp_, StackPtr sp_, int argc_, StackPtr argp_,
109  SegmentId localsSegment_, reg_t pc_, Selector debugSelector_,
110  int debugKernelFunction_, int debugKernelSubFunction_,
111  int debugExportId_, int debugLocalCallOffset_, int debugOrigin_,
112  ExecStackType type_) {
113  objp = objp_;
114  sendp = sendp_;
115  // varp is set separately for varselector calls
116  addr.pc = pc_;
117  fp = sp = sp_;
118  argc = argc_;
119  variables_argp = argp_;
120  tempCount = 0;
121  if (localsSegment_ != kUninitializedSegment)
122  local_segment = localsSegment_;
123  else
124  local_segment = pc_.getSegment();
125  debugSelector = debugSelector_;
126  debugKernelFunction = debugKernelFunction_;
127  debugKernelSubFunction = debugKernelSubFunction_;
128  debugExportId = debugExportId_;
129  debugLocalCallOffset = debugLocalCallOffset_;
130  debugOrigin = debugOrigin_;
131  type = type_;
132  }
133 };
134 
135 enum {
136  VAR_GLOBAL = 0,
137  VAR_LOCAL = 1,
138  VAR_TEMP = 2,
139  VAR_PARAM = 3
140 };
141 
142 enum GlobalVar {
143  kGlobalVarEgo = 0,
144  kGlobalVarGame = 1,
145  kGlobalVarCurrentRoom = 2,
146  kGlobalVarSpeed = 3, // SCI16
147  kGlobalVarQuit = 4,
148  kGlobalVarSounds = 8,
149  kGlobalVarPlanes = 10, // SCI32
150  kGlobalVarCurrentRoomNo = 11,
151  kGlobalVarPreviousRoomNo = 12,
152  kGlobalVarNewRoomNo = 13,
153  kGlobalVarScore = 15,
154  kGlobalVarVersionNew = 27, // version string or object in later games
155  kGlobalVarVersionOld = 28, // version string in earlier games
156  kGlobalVarGK2MusicVolume = 76, // 0 to 127
157  kGlobalVarPhant2SecondaryVolume = 76, // 0 to 127
158  kGlobalVarUser = 80,
159  kGlobalVarFastCast = 84, // SCI16
160  kGlobalVarMessageType = 90,
161  kGlobalVarTextSpeed = 94, // SCI32; 0 is fastest, 8 is slowest
162  kGlobalVarGK1Music1 = 102, // 0 to 127
163  kGlobalVarGK1Music2 = 103, // 0 to 127
164  kGlobalVarRamaCatalogFile = 130,
165  kGlobalVarLSL6HiresGameFlags = 137,
166  kGlobalVarKQ7UpscaleVideos = 160,
167  kGlobalVarGK1NarratorMode = 166, // 0 for text, 1 for speech
168  kGlobalVarRamaMusicVolume = 176, // 0 to 16
169  kGlobalVarPhant1MusicVolume = 187, // 0 to 15
170  kGlobalVarPhant1DACVolume = 188, // 0 to 127
171  kGlobalVarLSL6MusicVolume = 194, // 0 to 13
172  kGlobalVarGK1DAC1 = 207, // 0 to 127
173  kGlobalVarPhant2CensorshipFlag = 207,
174  kGlobalVarGK1DAC2 = 208, // 0 to 127
175  kGlobalVarLSL6HiresRestoreTextWindow = 210,
176  kGlobalVarGK1DAC3 = 211, // 0 to 127
177  kGlobalVarShiversFlags = 211,
178  kGlobalVarTorinMusicVolume = 227, // 0 to 100
179  kGlobalVarTorinSFXVolume = 228, // 0 to 100
180  kGlobalVarTorinSpeechVolume = 229, // 0 to 100
181  // Phant2 labels its volume slider as "music volume" but it is actually
182  // a master volume that affects both music *and* sound effects
183  kGlobalVarPhant2MasterVolume = 236, // 0 to 127
184  kGlobalVarPhant2ControlPanel = 250,
185  kGlobalVarShivers1Score = 349,
186  kGlobalVarQFG4Flags = 500,
187  kGlobalVarHoyle5MusicVolume = 897
188 };
189 
191 enum {
192  GC_INTERVAL = 0x8000
193 };
194 
195 enum SciOpcodes {
196  op_bnot = 0x00, // 000
197  op_add = 0x01, // 001
198  op_sub = 0x02, // 002
199  op_mul = 0x03, // 003
200  op_div = 0x04, // 004
201  op_mod = 0x05, // 005
202  op_shr = 0x06, // 006
203  op_shl = 0x07, // 007
204  op_xor = 0x08, // 008
205  op_and = 0x09, // 009
206  op_or = 0x0a, // 010
207  op_neg = 0x0b, // 011
208  op_not = 0x0c, // 012
209  op_eq_ = 0x0d, // 013
210  op_ne_ = 0x0e, // 014
211  op_gt_ = 0x0f, // 015
212  op_ge_ = 0x10, // 016
213  op_lt_ = 0x11, // 017
214  op_le_ = 0x12, // 018
215  op_ugt_ = 0x13, // 019
216  op_uge_ = 0x14, // 020
217  op_ult_ = 0x15, // 021
218  op_ule_ = 0x16, // 022
219  op_bt = 0x17, // 023
220  op_bnt = 0x18, // 024
221  op_jmp = 0x19, // 025
222  op_ldi = 0x1a, // 026
223  op_push = 0x1b, // 027
224  op_pushi = 0x1c, // 028
225  op_toss = 0x1d, // 029
226  op_dup = 0x1e, // 030
227  op_link = 0x1f, // 031
228  op_call = 0x20, // 032
229  op_callk = 0x21, // 033
230  op_callb = 0x22, // 034
231  op_calle = 0x23, // 035
232  op_ret = 0x24, // 036
233  op_send = 0x25, // 037
234  op_info = 0x26, // 038
235  op_superP = 0x27, // 039
236  op_class = 0x28, // 040
237  // dummy 0x29, // 041
238  op_self = 0x2a, // 042
239  op_super = 0x2b, // 043
240  op_rest = 0x2c, // 044
241  op_lea = 0x2d, // 045
242  op_selfID = 0x2e, // 046
243  // dummy 0x2f // 047
244  op_pprev = 0x30, // 048
245  op_pToa = 0x31, // 049
246  op_aTop = 0x32, // 050
247  op_pTos = 0x33, // 051
248  op_sTop = 0x34, // 052
249  op_ipToa = 0x35, // 053
250  op_dpToa = 0x36, // 054
251  op_ipTos = 0x37, // 055
252  op_dpTos = 0x38, // 056
253  op_lofsa = 0x39, // 057
254  op_lofss = 0x3a, // 058
255  op_push0 = 0x3b, // 059
256  op_push1 = 0x3c, // 060
257  op_push2 = 0x3d, // 061
258  op_pushSelf = 0x3e, // 062
259  op_line = 0x3f, // 063
260  //
261  op_lag = 0x40, // 064
262  op_lal = 0x41, // 065
263  op_lat = 0x42, // 066
264  op_lap = 0x43, // 067
265  op_lsg = 0x44, // 068
266  op_lsl = 0x45, // 069
267  op_lst = 0x46, // 070
268  op_lsp = 0x47, // 071
269  op_lagi = 0x48, // 072
270  op_lali = 0x49, // 073
271  op_lati = 0x4a, // 074
272  op_lapi = 0x4b, // 075
273  op_lsgi = 0x4c, // 076
274  op_lsli = 0x4d, // 077
275  op_lsti = 0x4e, // 078
276  op_lspi = 0x4f, // 079
277  //
278  op_sag = 0x50, // 080
279  op_sal = 0x51, // 081
280  op_sat = 0x52, // 082
281  op_sap = 0x53, // 083
282  op_ssg = 0x54, // 084
283  op_ssl = 0x55, // 085
284  op_sst = 0x56, // 086
285  op_ssp = 0x57, // 087
286  op_sagi = 0x58, // 088
287  op_sali = 0x59, // 089
288  op_sati = 0x5a, // 090
289  op_sapi = 0x5b, // 091
290  op_ssgi = 0x5c, // 092
291  op_ssli = 0x5d, // 093
292  op_ssti = 0x5e, // 094
293  op_sspi = 0x5f, // 095
294  //
295  op_plusag = 0x60, // 096
296  op_plusal = 0x61, // 097
297  op_plusat = 0x62, // 098
298  op_plusap = 0x63, // 099
299  op_plussg = 0x64, // 100
300  op_plussl = 0x65, // 101
301  op_plusst = 0x66, // 102
302  op_plussp = 0x67, // 103
303  op_plusagi = 0x68, // 104
304  op_plusali = 0x69, // 105
305  op_plusati = 0x6a, // 106
306  op_plusapi = 0x6b, // 107
307  op_plussgi = 0x6c, // 108
308  op_plussli = 0x6d, // 109
309  op_plussti = 0x6e, // 110
310  op_plusspi = 0x6f, // 111
311  //
312  op_minusag = 0x70, // 112
313  op_minusal = 0x71, // 113
314  op_minusat = 0x72, // 114
315  op_minusap = 0x73, // 115
316  op_minussg = 0x74, // 116
317  op_minussl = 0x75, // 117
318  op_minusst = 0x76, // 118
319  op_minussp = 0x77, // 119
320  op_minusagi = 0x78, // 120
321  op_minusali = 0x79, // 121
322  op_minusati = 0x7a, // 122
323  op_minusapi = 0x7b, // 123
324  op_minussgi = 0x7c, // 124
325  op_minussli = 0x7d, // 125
326  op_minussti = 0x7e, // 126
327  op_minusspi = 0x7f // 127
328 };
329 
330 void script_adjust_opcode_formats();
331 
345 ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct,
346  StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp);
347 
348 
365 ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj,
366  StackPtr sp, int framesize, StackPtr argp);
367 
368 
375 void run_vm(EngineState *s);
376 
397 SelectorType lookupSelector(SegManager *segMan, reg_t obj, Selector selectorid,
398  ObjVarRef *varp, reg_t *fptr);
399 
416 int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]);
417 
426 uint32 findOffset(const int16 relOffset, const Script *scr, const uint32 pcOffset);
427 
428 } // End of namespace Sci
429 
430 #endif // SCI_ENGINE_VM_H
Definition: state.h:100
reg_t reg
offset; script-relative offset, segment: 0 if not instantiated
Definition: vm.h:61
ExecStack * send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp)
int script
number of the script the class is in, -1 for non-existing
Definition: vm.h:60
reg_t sendp
Pointer to the object containing the invoked method.
Definition: vm.h:81
Definition: vm.h:66
Definition: script.h:71
reg_t objp
Pointer to the beginning of the current object.
Definition: vm.h:80
Definition: console.h:28
Definition: seg_manager.h:48
ExecStack * execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp)
SelectorType lookupSelector(SegManager *segMan, reg_t obj, Selector selectorid, ObjVarRef *varp, reg_t *fptr)
Definition: vm.h:79
void run_vm(EngineState *s)
int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4])
Definition: vm_types.h:39
uint32 findOffset(const int16 relOffset, const Script *scr, const uint32 pcOffset)
SelectorType
Definition: vm.h:53
Definition: vm.h:59