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