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
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "sci/sci.h"
24 #include "sci/engine/features.h"
25 #include "sci/engine/kernel.h"
26 #include "sci/engine/state.h"
27 #include "sci/engine/selector.h"
28
29 namespace Sci {
30
31 #if 1
32
33 #define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_)
34 #define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_)
35
36 #else
37
38 // The defines below can be used to construct static selector tables for games which don't have
39 // a vocab.997 resource, by dumping the selector table from other similar versions or games
40 #define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_); \
41 debugN("\t{ \"%s\", %d },\n", #_slc_, _selectorCache._slc_)
42
43 #define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_); \
44 debugN("\t{ \"%s\", %d },\n", _slcstr_, _selectorCache._slc_)
45
46 #endif
47
mapSelectors()48 void Kernel::mapSelectors() {
49 // species
50 // superClass
51 FIND_SELECTOR2(_info_, "-info-");
52 FIND_SELECTOR(y);
53 FIND_SELECTOR(x);
54 FIND_SELECTOR(view);
55 FIND_SELECTOR(loop);
56 FIND_SELECTOR(cel);
57 FIND_SELECTOR(underBits);
58 FIND_SELECTOR(nsTop);
59 FIND_SELECTOR(nsLeft);
60 FIND_SELECTOR(nsBottom);
61 FIND_SELECTOR(nsRight);
62 FIND_SELECTOR(lsTop);
63 FIND_SELECTOR(lsLeft);
64 FIND_SELECTOR(lsBottom);
65 FIND_SELECTOR(lsRight);
66 FIND_SELECTOR(signal);
67 FIND_SELECTOR(illegalBits);
68 FIND_SELECTOR(brTop);
69 FIND_SELECTOR(brLeft);
70 FIND_SELECTOR(brBottom);
71 FIND_SELECTOR(brRight);
72 // name
73 // key
74 // time
75 FIND_SELECTOR(text);
76 FIND_SELECTOR(elements);
77 // color
78 // back
79 FIND_SELECTOR(mode);
80 // style
81 FIND_SELECTOR(state);
82 FIND_SELECTOR(font);
83 FIND_SELECTOR(type);
84 // window
85 FIND_SELECTOR(cursor);
86 FIND_SELECTOR(max);
87 FIND_SELECTOR(mark);
88 FIND_SELECTOR(sort);
89 // who
90 FIND_SELECTOR(message);
91 // edit
92 FIND_SELECTOR(play);
93 FIND_SELECTOR(restore);
94 FIND_SELECTOR(number);
95 FIND_SELECTOR(handle); // nodePtr
96 FIND_SELECTOR(client);
97 FIND_SELECTOR(dx);
98 FIND_SELECTOR(dy);
99 FIND_SELECTOR2(b_movCnt, "b-moveCnt");
100 FIND_SELECTOR2(b_i1, "b-i1");
101 FIND_SELECTOR2(b_i2, "b-i2");
102 FIND_SELECTOR2(b_di, "b-di");
103 FIND_SELECTOR2(b_xAxis, "b-xAxis");
104 FIND_SELECTOR2(b_incr, "b-incr");
105 FIND_SELECTOR(xStep);
106 FIND_SELECTOR(yStep);
107 FIND_SELECTOR(xLast);
108 FIND_SELECTOR(yLast);
109 FIND_SELECTOR(moveSpeed);
110 FIND_SELECTOR(canBeHere); // cantBeHere
111 FIND_SELECTOR(heading);
112 FIND_SELECTOR(mover);
113 FIND_SELECTOR(doit);
114 FIND_SELECTOR(isBlocked);
115 FIND_SELECTOR(looper);
116 FIND_SELECTOR(priority);
117 FIND_SELECTOR(modifiers);
118 FIND_SELECTOR(replay);
119 // setPri
120 // at
121 // next
122 // done
123 // width
124 FIND_SELECTOR(wordFail);
125 FIND_SELECTOR(syntaxFail);
126 // semanticFail
127 // pragmaFail
128 // said
129 FIND_SELECTOR(claimed);
130 // value
131 // save
132 // restore
133 // title
134 // button
135 // icon
136 // draw
137 FIND_SELECTOR2(delete_, "delete");
138 FIND_SELECTOR(z);
139 // -----------------------------
140 FIND_SELECTOR(size);
141 FIND_SELECTOR(moveDone);
142 FIND_SELECTOR(vol);
143 FIND_SELECTOR(pri);
144 FIND_SELECTOR(min);
145 FIND_SELECTOR(sec);
146 FIND_SELECTOR(frame);
147 FIND_SELECTOR(dataInc);
148 FIND_SELECTOR(palette);
149 FIND_SELECTOR(cantBeHere);
150 FIND_SELECTOR(nodePtr);
151 FIND_SELECTOR(flags);
152 FIND_SELECTOR(points);
153 FIND_SELECTOR(syncCue);
154 FIND_SELECTOR(syncTime);
155 FIND_SELECTOR(printLang);
156 FIND_SELECTOR(subtitleLang);
157 FIND_SELECTOR(parseLang);
158 FIND_SELECTOR(overlay);
159 FIND_SELECTOR(topString);
160 FIND_SELECTOR(scaleSignal);
161 FIND_SELECTOR(scaleX);
162 FIND_SELECTOR(scaleY);
163 FIND_SELECTOR(maxScale);
164 FIND_SELECTOR(vanishingX);
165 FIND_SELECTOR(vanishingY);
166 FIND_SELECTOR(iconIndex);
167 FIND_SELECTOR(select);
168 FIND_SELECTOR(handsOff);
169 FIND_SELECTOR(setStep);
170 FIND_SELECTOR(setMotion);
171 FIND_SELECTOR(cycleSpeed);
172 FIND_SELECTOR(owner);
173
174 #ifdef ENABLE_SCI32
175 FIND_SELECTOR(data);
176 FIND_SELECTOR(picture);
177 FIND_SELECTOR(bitmap);
178 FIND_SELECTOR(plane);
179 FIND_SELECTOR(top);
180 FIND_SELECTOR(left);
181 FIND_SELECTOR(bottom);
182 FIND_SELECTOR(right);
183 FIND_SELECTOR(seenRect);
184 FIND_SELECTOR(resY);
185 FIND_SELECTOR(resX);
186 FIND_SELECTOR(dimmed);
187 FIND_SELECTOR(fore);
188 FIND_SELECTOR(back);
189 FIND_SELECTOR(skip);
190 FIND_SELECTOR(borderColor);
191 FIND_SELECTOR(width);
192 FIND_SELECTOR(fixPriority);
193 FIND_SELECTOR(mirrored);
194 FIND_SELECTOR(visible);
195 FIND_SELECTOR(useInsetRect);
196 FIND_SELECTOR(inTop);
197 FIND_SELECTOR(inLeft);
198 FIND_SELECTOR(inBottom);
199 FIND_SELECTOR(inRight);
200 FIND_SELECTOR(textTop);
201 FIND_SELECTOR(textLeft);
202 FIND_SELECTOR(textBottom);
203 FIND_SELECTOR(textRight);
204 FIND_SELECTOR(title);
205 FIND_SELECTOR(titleFont);
206 FIND_SELECTOR(titleFore);
207 FIND_SELECTOR(titleBack);
208 FIND_SELECTOR(magnifier);
209 FIND_SELECTOR(frameOut);
210 FIND_SELECTOR(casts);
211 FIND_SELECTOR(setVol);
212 FIND_SELECTOR(reSyncVol);
213 FIND_SELECTOR(set);
214 FIND_SELECTOR(clear);
215 FIND_SELECTOR(curPos);
216 FIND_SELECTOR(update);
217 FIND_SELECTOR(show);
218 FIND_SELECTOR(position);
219 FIND_SELECTOR(musicVolume);
220 FIND_SELECTOR(soundVolume);
221 FIND_SELECTOR(initialOff);
222 FIND_SELECTOR(setPos);
223 FIND_SELECTOR(setSize);
224 FIND_SELECTOR(displayValue);
225 FIND_SELECTOR2(new_, "new");
226 FIND_SELECTOR(mainCel);
227 FIND_SELECTOR(move);
228 FIND_SELECTOR(eachElementDo);
229 FIND_SELECTOR(physicalBar);
230 FIND_SELECTOR(init);
231 FIND_SELECTOR(scratch);
232 FIND_SELECTOR(num);
233 FIND_SELECTOR(reallyRestore);
234 FIND_SELECTOR(bookMark);
235 FIND_SELECTOR(fileNumber);
236 FIND_SELECTOR(description);
237 FIND_SELECTOR(dispose);
238 FIND_SELECTOR(masterVolume);
239 FIND_SELECTOR(setCel);
240 FIND_SELECTOR(value);
241 #endif
242 }
243
readSelector(SegManager * segMan,reg_t object,Selector selectorId)244 reg_t readSelector(SegManager *segMan, reg_t object, Selector selectorId) {
245 ObjVarRef address;
246
247 if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
248 return NULL_REG;
249 else
250 return *address.getPointer(segMan);
251 }
252
253 #ifdef ENABLE_SCI32
updateInfoFlagViewVisible(Object * obj,int index,bool fromPropertyOp)254 void updateInfoFlagViewVisible(Object *obj, int index, bool fromPropertyOp) {
255 if (getSciVersion() >= SCI_VERSION_2 && obj->mustSetViewVisible(index, fromPropertyOp)) {
256 obj->setInfoSelectorFlag(kInfoFlagViewVisible);
257 }
258 }
259 #endif
260
writeSelector(SegManager * segMan,reg_t object,Selector selectorId,reg_t value)261 void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t value) {
262 ObjVarRef address;
263
264 if ((selectorId < 0) || (selectorId > (int)g_sci->getKernel()->getSelectorNamesSize())) {
265 const SciCallOrigin origin = g_sci->getEngineState()->getCurrentCallOrigin();
266 error("Attempt to write to invalid selector %d. Address %04x:%04x, %s", selectorId, PRINT_REG(object), origin.toString().c_str());
267 }
268
269 if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable) {
270 const SciCallOrigin origin = g_sci->getEngineState()->getCurrentCallOrigin();
271 error("Selector '%s' of object could not be written to. Address %04x:%04x, %s", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object), origin.toString().c_str());
272 }
273
274 *address.getPointer(segMan) = value;
275 #ifdef ENABLE_SCI32
276 updateInfoFlagViewVisible(segMan->getObject(object), address.varindex);
277 #endif
278 }
279
invokeSelector(EngineState * s,reg_t object,int selectorId,int k_argc,StackPtr k_argp,int argc,const reg_t * argv)280 void invokeSelector(EngineState *s, reg_t object, int selectorId,
281 int k_argc, StackPtr k_argp, int argc, const reg_t *argv) {
282 int i;
283 int framesize = 2 + 1 * argc;
284 int slc_type;
285 StackPtr stackframe = k_argp + k_argc;
286
287 stackframe[0] = make_reg(0, selectorId); // The selector we want to call
288 stackframe[1] = make_reg(0, argc); // Argument count
289
290 slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, NULL);
291
292 if (slc_type == kSelectorNone) {
293 const SciCallOrigin origin = g_sci->getEngineState()->getCurrentCallOrigin();
294 error("invokeSelector: Selector '%s' could not be invoked. Address %04x:%04x, %s", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object), origin.toString().c_str());
295 }
296 if (slc_type == kSelectorVariable) {
297 const SciCallOrigin origin = g_sci->getEngineState()->getCurrentCallOrigin();
298 error("invokeSelector: Attempting to invoke variable selector %s. Address %04x:%04x, %s", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object), origin.toString().c_str());
299 }
300
301 for (i = 0; i < argc; i++)
302 stackframe[2 + i] = argv[i]; // Write each argument
303
304 ExecStack *xstack;
305
306 // Now commit the actual function:
307 xstack = send_selector(s, object, object, stackframe, framesize, stackframe);
308
309 xstack->sp += argc + 2;
310 xstack->fp += argc + 2;
311
312 run_vm(s); // Start a new vm
313 }
314
lookupSelector(SegManager * segMan,reg_t obj_location,Selector selectorId,ObjVarRef * varp,reg_t * fptr)315 SelectorType lookupSelector(SegManager *segMan, reg_t obj_location, Selector selectorId, ObjVarRef *varp, reg_t *fptr) {
316 const Object *obj = segMan->getObject(obj_location);
317 int index;
318 bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
319
320 // Early SCI versions used the LSB in the selector ID as a read/write
321 // toggle, meaning that we must remove it for selector lookup.
322 if (oldScriptHeader)
323 selectorId &= ~1;
324
325 if (!obj) {
326 const SciCallOrigin origin = g_sci->getEngineState()->getCurrentCallOrigin();
327 error("lookupSelector: Attempt to send to non-object or invalid script. Address %04x:%04x, %s", PRINT_REG(obj_location), origin.toString().c_str());
328 }
329
330 index = obj->locateVarSelector(segMan, selectorId);
331
332 if (index >= 0) {
333 // Found it as a variable
334 if (varp) {
335 varp->obj = obj_location;
336 varp->varindex = index;
337 }
338 return kSelectorVariable;
339 } else {
340 // Check if it's a method, with recursive lookup in superclasses
341 while (obj) {
342 index = obj->funcSelectorPosition(selectorId);
343 if (index >= 0) {
344 if (fptr)
345 *fptr = obj->getFunction(index);
346
347 return kSelectorMethod;
348 } else {
349 obj = segMan->getObject(obj->getSuperClassSelector());
350 }
351 }
352
353 return kSelectorNone;
354 }
355
356
357 // return _lookupSelector_function(segMan, obj, selectorId, fptr);
358 }
359
360 } // End of namespace Sci
361