ScummVM API documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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  kGlobalVarCast = 5,
149  kGlobalVarSounds = 8,
150  kGlobalVarPlanes = 10, // SCI32
151  kGlobalVarCurrentRoomNo = 11,
152  kGlobalVarPreviousRoomNo = 12,
153  kGlobalVarNewRoomNo = 13,
154  kGlobalVarScore = 15,
155  kGlobalVarVersionNew = 27, // version string or object in later games
156  kGlobalVarVersionOld = 28, // version string in earlier games
157  kGlobalVarGK2MusicVolume = 76, // 0 to 127
158  kGlobalVarPhant2SecondaryVolume = 76, // 0 to 127
159  kGlobalVarUser = 80,
160  kGlobalVarFastCast = 84, // SCI16
161  kGlobalVarMessageType = 90,
162  kGlobalVarTextSpeed = 94, // SCI32; 0 is fastest, 8 is slowest
163  kGlobalVarGK1Music1 = 102, // 0 to 127
164  kGlobalVarGK1Music2 = 103, // 0 to 127
165  kGlobalVarRamaCatalogFile = 130,
166  kGlobalVarLSL6HiresGameFlags = 137,
167  kGlobalVarKQ7UpscaleVideos = 160,
168  kGlobalVarGK1NarratorMode = 166, // 0 for text, 1 for speech
169  kGlobalVarRamaMusicVolume = 176, // 0 to 16
170  kGlobalVarPhant1MusicVolume = 187, // 0 to 15
171  kGlobalVarPhant1DACVolume = 188, // 0 to 127
172  kGlobalVarLSL6MusicVolume = 194, // 0 to 13
173  kGlobalVarGK1DAC1 = 207, // 0 to 127
174  kGlobalVarPhant2CensorshipFlag = 207,
175  kGlobalVarGK1DAC2 = 208, // 0 to 127
176  kGlobalVarLSL6HiresRestoreTextWindow = 210,
177  kGlobalVarGK1DAC3 = 211, // 0 to 127
178  kGlobalVarShiversFlags = 211,
179  kGlobalVarTorinMusicVolume = 227, // 0 to 100
180  kGlobalVarTorinSFXVolume = 228, // 0 to 100
181  kGlobalVarTorinSpeechVolume = 229, // 0 to 100
182  // Phant2 labels its volume slider as "music volume" but it is actually
183  // a master volume that affects both music *and* sound effects
184  kGlobalVarPhant2MasterVolume = 236, // 0 to 127
185  kGlobalVarPhant2ControlPanel = 250,
186  kGlobalVarShivers1Score = 349,
187  kGlobalVarQFG4Flags = 500,
188  kGlobalVarHoyle5MusicVolume = 897
189 };
190 
192 enum {
193  GC_INTERVAL = 0x8000
194 };
195 
196 enum SciOpcodes {
197  op_bnot = 0x00, // 000
198  op_add = 0x01, // 001
199  op_sub = 0x02, // 002
200  op_mul = 0x03, // 003
201  op_div = 0x04, // 004
202  op_mod = 0x05, // 005
203  op_shr = 0x06, // 006
204  op_shl = 0x07, // 007
205  op_xor = 0x08, // 008
206  op_and = 0x09, // 009
207  op_or = 0x0a, // 010
208  op_neg = 0x0b, // 011
209  op_not = 0x0c, // 012
210  op_eq_ = 0x0d, // 013
211  op_ne_ = 0x0e, // 014
212  op_gt_ = 0x0f, // 015
213  op_ge_ = 0x10, // 016
214  op_lt_ = 0x11, // 017
215  op_le_ = 0x12, // 018
216  op_ugt_ = 0x13, // 019
217  op_uge_ = 0x14, // 020
218  op_ult_ = 0x15, // 021
219  op_ule_ = 0x16, // 022
220  op_bt = 0x17, // 023
221  op_bnt = 0x18, // 024
222  op_jmp = 0x19, // 025
223  op_ldi = 0x1a, // 026
224  op_push = 0x1b, // 027
225  op_pushi = 0x1c, // 028
226  op_toss = 0x1d, // 029
227  op_dup = 0x1e, // 030
228  op_link = 0x1f, // 031
229  op_call = 0x20, // 032
230  op_callk = 0x21, // 033
231  op_callb = 0x22, // 034
232  op_calle = 0x23, // 035
233  op_ret = 0x24, // 036
234  op_send = 0x25, // 037
235  op_info = 0x26, // 038
236  op_superP = 0x27, // 039
237  op_class = 0x28, // 040
238  // dummy 0x29, // 041
239  op_self = 0x2a, // 042
240  op_super = 0x2b, // 043
241  op_rest = 0x2c, // 044
242  op_lea = 0x2d, // 045
243  op_selfID = 0x2e, // 046
244  // dummy 0x2f // 047
245  op_pprev = 0x30, // 048
246  op_pToa = 0x31, // 049
247  op_aTop = 0x32, // 050
248  op_pTos = 0x33, // 051
249  op_sTop = 0x34, // 052
250  op_ipToa = 0x35, // 053
251  op_dpToa = 0x36, // 054
252  op_ipTos = 0x37, // 055
253  op_dpTos = 0x38, // 056
254  op_lofsa = 0x39, // 057
255  op_lofss = 0x3a, // 058
256  op_push0 = 0x3b, // 059
257  op_push1 = 0x3c, // 060
258  op_push2 = 0x3d, // 061
259  op_pushSelf = 0x3e, // 062
260  op_line = 0x3f, // 063
261  //
262  op_lag = 0x40, // 064
263  op_lal = 0x41, // 065
264  op_lat = 0x42, // 066
265  op_lap = 0x43, // 067
266  op_lsg = 0x44, // 068
267  op_lsl = 0x45, // 069
268  op_lst = 0x46, // 070
269  op_lsp = 0x47, // 071
270  op_lagi = 0x48, // 072
271  op_lali = 0x49, // 073
272  op_lati = 0x4a, // 074
273  op_lapi = 0x4b, // 075
274  op_lsgi = 0x4c, // 076
275  op_lsli = 0x4d, // 077
276  op_lsti = 0x4e, // 078
277  op_lspi = 0x4f, // 079
278  //
279  op_sag = 0x50, // 080
280  op_sal = 0x51, // 081
281  op_sat = 0x52, // 082
282  op_sap = 0x53, // 083
283  op_ssg = 0x54, // 084
284  op_ssl = 0x55, // 085
285  op_sst = 0x56, // 086
286  op_ssp = 0x57, // 087
287  op_sagi = 0x58, // 088
288  op_sali = 0x59, // 089
289  op_sati = 0x5a, // 090
290  op_sapi = 0x5b, // 091
291  op_ssgi = 0x5c, // 092
292  op_ssli = 0x5d, // 093
293  op_ssti = 0x5e, // 094
294  op_sspi = 0x5f, // 095
295  //
296  op_plusag = 0x60, // 096
297  op_plusal = 0x61, // 097
298  op_plusat = 0x62, // 098
299  op_plusap = 0x63, // 099
300  op_plussg = 0x64, // 100
301  op_plussl = 0x65, // 101
302  op_plusst = 0x66, // 102
303  op_plussp = 0x67, // 103
304  op_plusagi = 0x68, // 104
305  op_plusali = 0x69, // 105
306  op_plusati = 0x6a, // 106
307  op_plusapi = 0x6b, // 107
308  op_plussgi = 0x6c, // 108
309  op_plussli = 0x6d, // 109
310  op_plussti = 0x6e, // 110
311  op_plusspi = 0x6f, // 111
312  //
313  op_minusag = 0x70, // 112
314  op_minusal = 0x71, // 113
315  op_minusat = 0x72, // 114
316  op_minusap = 0x73, // 115
317  op_minussg = 0x74, // 116
318  op_minussl = 0x75, // 117
319  op_minusst = 0x76, // 118
320  op_minussp = 0x77, // 119
321  op_minusagi = 0x78, // 120
322  op_minusali = 0x79, // 121
323  op_minusati = 0x7a, // 122
324  op_minusapi = 0x7b, // 123
325  op_minussgi = 0x7c, // 124
326  op_minussli = 0x7d, // 125
327  op_minussti = 0x7e, // 126
328  op_minusspi = 0x7f // 127
329 };
330 
331 void script_adjust_opcode_formats();
332 
346 ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct,
347  StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp);
348 
349 
366 ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj,
367  StackPtr sp, int framesize, StackPtr argp);
368 
369 
376 void run_vm(EngineState *s);
377 
398 SelectorType lookupSelector(SegManager *segMan, reg_t obj, Selector selectorid,
399  ObjVarRef *varp, reg_t *fptr);
400 
417 int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]);
418 
427 uint32 findOffset(const int16 relOffset, const Script *scr, const uint32 pcOffset);
428 
429 } // End of namespace Sci
430 
431 #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