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/kernel.h"
25 #include "sci/event.h"
26 #include "sci/resource/resource.h"
27 #include "sci/engine/features.h"
28 #include "sci/engine/kernel_tables.h"
29 #include "sci/engine/state.h"
30 #include "sci/engine/workarounds.h"
31 
32 #include "common/system.h"
33 
34 namespace Sci {
35 
Kernel(ResourceManager * resMan,SegManager * segMan)36 Kernel::Kernel(ResourceManager *resMan, SegManager *segMan)	:
37 	_resMan(resMan),
38 	_segMan(segMan),
39 	_invalid("<invalid>") {
40 	loadSelectorNames();
41 	mapSelectors();
42 }
43 
~Kernel()44 Kernel::~Kernel() {
45 	for (KernelFunctionArray::iterator it = _kernelFuncs.begin(); it != _kernelFuncs.end(); ++it) {
46 		if (it->subFunctionCount) {
47 			uint16 subFunctionNr = 0;
48 			while (subFunctionNr < it->subFunctionCount) {
49 				delete[] it->subFunctions[subFunctionNr].signature;
50 				subFunctionNr++;
51 			}
52 			delete[] it->subFunctions;
53 		}
54 		delete[] it->signature;
55 	}
56 }
57 
getSelectorNamesSize() const58 uint Kernel::getSelectorNamesSize() const {
59 	return _selectorNames.size();
60 }
61 
getSelectorName(uint selector)62 const Common::String &Kernel::getSelectorName(uint selector) {
63 	if (selector >= _selectorNames.size()) {
64 		// This should only occur in games w/o a selector-table
65 		//  We need this for proper workaround tables
66 		// TODO: maybe check, if there is a fixed selector-table and error() out in that case
67 		for (uint loopSelector = _selectorNames.size(); loopSelector <= selector; ++loopSelector)
68 			_selectorNames.push_back(Common::String::format("<noname%d>", loopSelector));
69 	}
70 
71 	// Ensure that the selector has a name
72 	if (_selectorNames[selector].empty())
73 		_selectorNames[selector] = Common::String::format("<noname%d>", selector);
74 
75 	return _selectorNames[selector];
76 }
77 
getKernelNamesSize() const78 uint Kernel::getKernelNamesSize() const {
79 	return _kernelNames.size();
80 }
81 
getKernelName(uint number) const82 const Common::String &Kernel::getKernelName(uint number) const {
83 	assert(number < _kernelFuncs.size());
84 	return _kernelNames[number];
85 }
86 
getKernelName(uint number,uint subFunction) const87 Common::String Kernel::getKernelName(uint number, uint subFunction) const {
88 	assert(number < _kernelFuncs.size());
89 	const KernelFunction &kernelCall = _kernelFuncs[number];
90 
91 	assert(subFunction < kernelCall.subFunctionCount);
92 	return kernelCall.subFunctions[subFunction].name;
93 }
94 
95 
findKernelFuncPos(Common::String kernelFuncName)96 int Kernel::findKernelFuncPos(Common::String kernelFuncName) {
97 	for (uint32 i = 0; i < _kernelNames.size(); i++)
98 		if (_kernelNames[i] == kernelFuncName)
99 			return i;
100 
101 	return -1;
102 }
103 
findSelector(const char * selectorName) const104 int Kernel::findSelector(const char *selectorName) const {
105 	for (uint pos = 0; pos < _selectorNames.size(); ++pos) {
106 		if (_selectorNames[pos] == selectorName)
107 			return pos;
108 	}
109 
110 	debugC(kDebugLevelVM, "Could not map '%s' to any selector", selectorName);
111 
112 	return -1;
113 }
114 
loadSelectorNames()115 void Kernel::loadSelectorNames() {
116 	Resource *r = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS), 0);
117 	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
118 
119 #ifdef ENABLE_SCI32
120 	// Starting with KQ7, Mac versions have a BE name table. GK1 Mac and earlier (and all
121 	// other platforms) always use LE.
122 	const bool isBE = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1_EARLY
123 			&& g_sci->getGameId() != GID_GK1);
124 #else
125 	const bool isBE = false;
126 #endif
127 
128 	if (!r) { // No such resource?
129 		// Check if we have a table for this game
130 		// Some demos do not have a selector table
131 		Common::StringArray staticSelectorTable = checkStaticSelectorNames();
132 
133 		if (staticSelectorTable.empty())
134 			error("Kernel: Could not retrieve selector names");
135 		else
136 			warning("No selector vocabulary found, using a static one");
137 
138 		for (uint32 i = 0; i < staticSelectorTable.size(); i++) {
139 			_selectorNames.push_back(staticSelectorTable[i]);
140 			if (oldScriptHeader)
141 				_selectorNames.push_back(staticSelectorTable[i]);
142 		}
143 
144 		return;
145 	}
146 
147 	int count = (isBE ? r->getUint16BEAt(0) : r->getUint16LEAt(0)) + 1; // Counter is slightly off
148 
149 	for (int i = 0; i < count; i++) {
150 		int offset = isBE ? r->getUint16BEAt(2 + i * 2) : r->getUint16LEAt(2 + i * 2);
151 		int len = isBE ? r->getUint16BEAt(offset) : r->getUint16LEAt(offset);
152 
153 		Common::String tmp = r->getStringAt(offset + 2, len);
154 		_selectorNames.push_back(tmp);
155 		//debug("%s", tmp.c_str());
156 
157 		// Early SCI versions used the LSB in the selector ID as a read/write
158 		// toggle. To compensate for that, we add every selector name twice.
159 		if (oldScriptHeader)
160 			_selectorNames.push_back(tmp);
161 	}
162 }
163 
164 // this parses a written kernel signature into an internal memory format
165 // [io] -> either integer or object
166 // (io) -> optionally integer AND an object
167 // (i) -> optional integer
168 // . -> any type
169 // i* -> at least one integer, more integers may follow after that
170 // (i*) -> optional multiple integers
171 // .* -> at least one parameter of any type and more parameters of any type may follow
172 // (.*) -> any parameters afterwards (or none)
173 // * -> means "more of the last parameter may follow (or none at all)", must be at the end of a signature. Is not valid anywhere else.
parseKernelSignature(const char * kernelName,const char * writtenSig)174 static uint16 *parseKernelSignature(const char *kernelName, const char *writtenSig) {
175 	const char *curPos;
176 	char curChar;
177 	uint16 *result = NULL;
178 	uint16 *writePos = NULL;
179 	int size = 0;
180 	bool validType = false;
181 	bool optionalType = false;
182 	bool eitherOr = false;
183 	bool optional = false;
184 	bool hadOptional = false;
185 
186 	// No signature given? no signature out
187 	if (!writtenSig)
188 		return NULL;
189 
190 	// First, we check how many bytes the result will be
191 	//  we also check, if the written signature makes any sense
192 	curPos = writtenSig;
193 	while (*curPos) {
194 		curChar = *curPos;
195 		switch (curChar) {
196 		case '[': // either or
197 			if (eitherOr)
198 				error("signature for k%s: '[' used within '[]'", kernelName);
199 			eitherOr = true;
200 			validType = false;
201 			break;
202 		case ']': // either or end
203 			if (!eitherOr)
204 				error("signature for k%s: ']' used without leading '['", kernelName);
205 			if (!validType)
206 				error("signature for k%s: '[]' does not surround valid type(s)", kernelName);
207 			eitherOr = false;
208 			validType = false;
209 			size++;
210 			break;
211 		case '(': // optional
212 			if (optional)
213 				error("signature for k%s: '(' used within '()' brackets", kernelName);
214 			if (eitherOr)
215 				error("signature for k%s: '(' used within '[]' brackets", kernelName);
216 			optional = true;
217 			validType = false;
218 			optionalType = false;
219 			break;
220 		case ')': // optional end
221 			if (!optional)
222 				error("signature for k%s: ')' used without leading '('", kernelName);
223 			if (!optionalType)
224 				error("signature for k%s: '()' does not to surround valid type(s)", kernelName);
225 			optional = false;
226 			validType = false;
227 			hadOptional = true;
228 			break;
229 		case '0': // allowed types
230 		case 'i':
231 		case 'o':
232 		case 'r':
233 		case 'l':
234 		case 'n':
235 		case '.':
236 		case '!':
237 			if ((hadOptional) & (!optional))
238 				error("signature for k%s: non-optional type may not follow optional type", kernelName);
239 			validType = true;
240 			if (optional)
241 				optionalType = true;
242 			if (!eitherOr)
243 				size++;
244 			break;
245 		case '*': // accepts more of the same parameter (must be last char)
246 			if (!validType) {
247 				if ((writtenSig == curPos) || (*(curPos - 1) != ']'))
248 					error("signature for k%s: a valid type must be in front of '*'", kernelName);
249 			}
250 			if (eitherOr)
251 				error("signature for k%s: '*' may not be inside '[]'", kernelName);
252 			if (optional) {
253 				if ((*(curPos + 1) != ')') || (*(curPos + 2) != 0))
254 					error("signature for k%s: '*' may only be used for last type", kernelName);
255 			} else {
256 				if (*(curPos + 1) != 0)
257 					error("signature for k%s: '*' may only be used for last type", kernelName);
258 			}
259 			break;
260 		default:
261 			error("signature for k%s: '%c' unknown", kernelName, *curPos);
262 		}
263 		curPos++;
264 	}
265 
266 	uint16 signature = 0;
267 
268 	// Now we allocate buffer with required size and fill it
269 	result = new uint16[size + 1];
270 	writePos = result;
271 	curPos = writtenSig;
272 	do {
273 		curChar = *curPos;
274 		if (!eitherOr) {
275 			// not within either-or, check if next character forces output
276 			switch (curChar) {
277 			case 0:
278 			case '[':
279 			case '(':
280 			case ')':
281 			case 'i':
282 			case 'o':
283 			case 'r':
284 			case 'l':
285 			case 'n':
286 			case '.':
287 			case '!':
288 				// and we also got some signature pending?
289 				if (signature) {
290 					if (!(signature & SIG_MAYBE_ANY))
291 						error("signature for k%s: invalid ('!') may only get used in combination with a real type", kernelName);
292 					if ((signature & SIG_IS_INVALID) && ((signature & SIG_MAYBE_ANY) == (SIG_TYPE_NULL | SIG_TYPE_INTEGER)))
293 						error("signature for k%s: invalid ('!') should not be used on exclusive null/integer type", kernelName);
294 					if (optional) {
295 						signature |= SIG_IS_OPTIONAL;
296 						if (curChar != ')')
297 							signature |= SIG_NEEDS_MORE;
298 					}
299 					*writePos = signature;
300 					writePos++;
301 					signature = 0;
302 				}
303 				break;
304 			default:
305 				break;
306 			}
307 		}
308 		switch (curChar) {
309 		case '[': // either or
310 			eitherOr = true;
311 			break;
312 		case ']': // either or end
313 			eitherOr = false;
314 			break;
315 		case '(': // optional
316 			optional = true;
317 			break;
318 		case ')': // optional end
319 			optional = false;
320 			break;
321 		case '0':
322 			if (signature & SIG_TYPE_NULL)
323 				error("signature for k%s: NULL ('0') specified more than once", kernelName);
324 			signature |= SIG_TYPE_NULL;
325 			break;
326 		case 'i':
327 			if (signature & SIG_TYPE_INTEGER)
328 				error("signature for k%s: integer ('i') specified more than once", kernelName);
329 			signature |= SIG_TYPE_INTEGER | SIG_TYPE_NULL;
330 			break;
331 		case 'o':
332 			if (signature & SIG_TYPE_OBJECT)
333 				error("signature for k%s: object ('o') specified more than once", kernelName);
334 			signature |= SIG_TYPE_OBJECT;
335 			break;
336 		case 'r':
337 			if (signature & SIG_TYPE_REFERENCE)
338 				error("signature for k%s: reference ('r') specified more than once", kernelName);
339 			signature |= SIG_TYPE_REFERENCE;
340 			break;
341 		case 'l':
342 			if (signature & SIG_TYPE_LIST)
343 				error("signature for k%s: list ('l') specified more than once", kernelName);
344 			signature |= SIG_TYPE_LIST;
345 			break;
346 		case 'n':
347 			if (signature & SIG_TYPE_NODE)
348 				error("signature for k%s: node ('n') specified more than once", kernelName);
349 			signature |= SIG_TYPE_NODE;
350 			break;
351 		case '.':
352 			if (signature & SIG_MAYBE_ANY)
353 				error("signature for k%s: maybe-any ('.') shouldn't get specified with other types in front of it", kernelName);
354 			signature |= SIG_MAYBE_ANY;
355 			break;
356 		case '!':
357 			if (signature & SIG_IS_INVALID)
358 				error("signature for k%s: invalid ('!') specified more than once", kernelName);
359 			signature |= SIG_IS_INVALID;
360 			break;
361 		case '*': // accepts more of the same parameter
362 			signature |= SIG_MORE_MAY_FOLLOW;
363 			break;
364 		default:
365 			break;
366 		}
367 		curPos++;
368 	} while (curChar);
369 
370 	// Write terminator
371 	*writePos = 0;
372 
373 	return result;
374 }
375 
findRegType(reg_t reg)376 uint16 Kernel::findRegType(reg_t reg) {
377 	// No segment? Must be integer
378 	if (!reg.getSegment())
379 		return SIG_TYPE_INTEGER | (reg.getOffset() ? 0 : SIG_TYPE_NULL);
380 
381 	if (reg.getSegment() == kUninitializedSegment)
382 		return SIG_TYPE_UNINITIALIZED;
383 
384 	// Otherwise it's an object
385 	SegmentObj *mobj = _segMan->getSegmentObj(reg.getSegment());
386 	if (!mobj)
387 		return SIG_TYPE_ERROR;
388 
389 	uint16 result = 0;
390 	if (!mobj->isValidOffset(reg.getOffset()))
391 		result |= SIG_IS_INVALID;
392 
393 	switch (mobj->getType()) {
394 	case SEG_TYPE_SCRIPT:
395 		if (reg.getOffset() <= (*(Script *)mobj).getBufSize() &&
396 			reg.getOffset() >= (uint)-SCRIPT_OBJECT_MAGIC_OFFSET &&
397 			(*(Script *)mobj).offsetIsObject(reg.getOffset())) {
398 			result |= ((Script *)mobj)->getObject(reg.getOffset()) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE;
399 		} else
400 			result |= SIG_TYPE_REFERENCE;
401 		break;
402 	case SEG_TYPE_CLONES:
403 		result |= SIG_TYPE_OBJECT;
404 		break;
405 	case SEG_TYPE_LOCALS:
406 	case SEG_TYPE_STACK:
407 	case SEG_TYPE_DYNMEM:
408 	case SEG_TYPE_HUNK:
409 #ifdef ENABLE_SCI32
410 	case SEG_TYPE_ARRAY:
411 	case SEG_TYPE_BITMAP:
412 #endif
413 		result |= SIG_TYPE_REFERENCE;
414 		break;
415 	case SEG_TYPE_LISTS:
416 		result |= SIG_TYPE_LIST;
417 		break;
418 	case SEG_TYPE_NODES:
419 		result |= SIG_TYPE_NODE;
420 		break;
421 	default:
422 		return SIG_TYPE_ERROR;
423 	}
424 	return result;
425 }
426 
427 struct SignatureDebugType {
428 	uint16 typeCheck;
429 	const char *text;
430 };
431 
432 static const SignatureDebugType signatureDebugTypeList[] = {
433 	{ SIG_TYPE_NULL,          "null" },
434 	{ SIG_TYPE_INTEGER,       "integer" },
435 	{ SIG_TYPE_UNINITIALIZED, "uninitialized" },
436 	{ SIG_TYPE_OBJECT,        "object" },
437 	{ SIG_TYPE_REFERENCE,     "reference" },
438 	{ SIG_TYPE_LIST,          "list" },
439 	{ SIG_TYPE_NODE,          "node" },
440 	{ SIG_TYPE_ERROR,         "error" },
441 	{ SIG_IS_INVALID,         "invalid" },
442 	{ 0,                      NULL }
443 };
444 
kernelSignatureDebugType(Common::String & signatureDetailsStr,const uint16 type)445 static void kernelSignatureDebugType(Common::String &signatureDetailsStr, const uint16 type) {
446 	bool firstPrint = true;
447 
448 	const SignatureDebugType *list = signatureDebugTypeList;
449 	while (list->typeCheck) {
450 		if (type & list->typeCheck) {
451 			if (!firstPrint)
452 //				debugN(", ");
453 				signatureDetailsStr += ", ";
454 //			debugN("%s", list->text);
455 //			signatureDetailsStr += signatureDetailsStr.format("%s", list->text);
456 			signatureDetailsStr += list->text;
457 			firstPrint = false;
458 		}
459 		list++;
460 	}
461 }
462 
463 // Create string, that holds the details of a kernel call signature and current arguments
464 //  For debugging purposes
signatureDebug(Common::String & signatureDetailsStr,const uint16 * sig,int argc,const reg_t * argv)465 void Kernel::signatureDebug(Common::String &signatureDetailsStr, const uint16 *sig, int argc, const reg_t *argv) {
466 	int argnr = 0;
467 
468 	// add ERROR: to debug output
469 	debugN("ERROR:");
470 
471 	while (*sig || argc) {
472 		// add leading spaces for additional parameters
473 		signatureDetailsStr += signatureDetailsStr.format("parameter %d: ", argnr++);
474 		if (argc) {
475 			reg_t parameter = *argv;
476 			signatureDetailsStr += signatureDetailsStr.format("%04x:%04x (", PRINT_REG(parameter));
477 			int regType = findRegType(parameter);
478 			if (regType)
479 				kernelSignatureDebugType(signatureDetailsStr, regType);
480 			else
481 				signatureDetailsStr += signatureDetailsStr.format("unknown type of %04x:%04x", PRINT_REG(parameter));
482 			signatureDetailsStr += ")";
483 			argv++;
484 			argc--;
485 		} else {
486 			signatureDetailsStr += "not passed";
487 		}
488 		if (*sig) {
489 			const uint16 signature = *sig;
490 			if ((signature & SIG_MAYBE_ANY) == SIG_MAYBE_ANY) {
491 				signatureDetailsStr += ", may be any";
492 			} else {
493 				signatureDetailsStr += ", should be ";
494 				kernelSignatureDebugType(signatureDetailsStr, signature);
495 			}
496 			if (signature & SIG_IS_OPTIONAL)
497 				signatureDetailsStr += " (optional)";
498 			if (signature & SIG_NEEDS_MORE)
499 				signatureDetailsStr += " (needs more)";
500 			if (signature & SIG_MORE_MAY_FOLLOW)
501 				signatureDetailsStr += " (more may follow)";
502 			sig++;
503 		}
504 		signatureDetailsStr += "\n";
505 	}
506 }
507 
signatureMatch(const uint16 * sig,int argc,const reg_t * argv)508 bool Kernel::signatureMatch(const uint16 *sig, int argc, const reg_t *argv) {
509 	uint16 nextSig = *sig;
510 	uint16 curSig = nextSig;
511 	while (nextSig && argc) {
512 		curSig = nextSig;
513 		int type = findRegType(*argv);
514 
515 		if ((type & SIG_IS_INVALID) && (!(curSig & SIG_IS_INVALID)))
516 			return false; // pointer is invalid and signature doesn't allow that?
517 
518 		if (!((type & ~SIG_IS_INVALID) & curSig)) {
519 			if ((type & ~SIG_IS_INVALID) == SIG_TYPE_ERROR && (curSig & SIG_IS_INVALID)) {
520 				// Type is unknown (error - usually because of a deallocated object or
521 				// stale pointer) and the signature allows invalid pointers. In this case,
522 				// ignore the invalid pointer.
523 			} else {
524 				return false; // type mismatch
525 			}
526 		}
527 
528 		if (!(curSig & SIG_MORE_MAY_FOLLOW)) {
529 			sig++;
530 			nextSig = *sig;
531 		} else {
532 			nextSig |= SIG_IS_OPTIONAL; // more may follow -> assumes followers are optional
533 		}
534 		argv++;
535 		argc--;
536 	}
537 
538 	// Too many arguments?
539 	if (argc)
540 		return false;
541 	// Signature end reached?
542 	if (nextSig == 0)
543 		return true;
544 	// current parameter is optional?
545 	if (curSig & SIG_IS_OPTIONAL) {
546 		// yes, check if nothing more is required
547 		if (!(curSig & SIG_NEEDS_MORE))
548 			return true;
549 	} else {
550 		// no, check if next parameter is optional
551 		if (nextSig & SIG_IS_OPTIONAL)
552 			return true;
553 	}
554 	// Too few arguments or more optional arguments required
555 	return false;
556 }
557 
mapFunctions(GameFeatures * features)558 void Kernel::mapFunctions(GameFeatures *features) {
559 	int mapped = 0;
560 	int ignored = 0;
561 	uint functionCount = _kernelNames.size();
562 	byte platformMask = 0;
563 	SciVersion myVersion = getSciVersion();
564 
565 	switch (g_sci->getPlatform()) {
566 	case Common::kPlatformDOS:
567 	case Common::kPlatformFMTowns:
568 		platformMask = SIGFOR_DOS;
569 		break;
570 	case Common::kPlatformPC98:
571 		platformMask = SIGFOR_PC98;
572 		break;
573 	case Common::kPlatformWindows:
574 		platformMask = SIGFOR_WIN;
575 		break;
576 	case Common::kPlatformMacintosh:
577 		platformMask = SIGFOR_MAC;
578 		break;
579 	case Common::kPlatformAmiga:
580 		platformMask = SIGFOR_AMIGA;
581 		break;
582 	case Common::kPlatformAtariST:
583 		platformMask = SIGFOR_ATARI;
584 		break;
585 	default:
586 		break;
587 	}
588 
589 	_kernelFuncs.resize(functionCount);
590 
591 	for (uint id = 0; id < functionCount; id++) {
592 		// First, get the name, if known, of the kernel function with number functnr
593 		Common::String kernelName = _kernelNames[id];
594 
595 		// Reset the table entry
596 		_kernelFuncs[id].function = NULL;
597 		_kernelFuncs[id].signature = NULL;
598 		_kernelFuncs[id].name = NULL;
599 		_kernelFuncs[id].workarounds = NULL;
600 		_kernelFuncs[id].subFunctions = NULL;
601 		_kernelFuncs[id].subFunctionCount = 0;
602 		if (kernelName.empty()) {
603 			// No name was given -> must be an unknown opcode
604 			warning("Kernel function %x unknown", id);
605 			continue;
606 		}
607 
608 		// Don't map dummy functions - they will never be called
609 		if (kernelName == "Dummy") {
610 			_kernelFuncs[id].function = kDummy;
611 			continue;
612 		}
613 
614 #ifdef ENABLE_SCI32
615 		// Several SCI 2.1 Middle Mac games use a modified kDoSound
616 		//  with different subop numbers.
617 		if (features->useDoSoundMac32() && kernelName == "DoSound") {
618 			_kernelFuncs[id].function = kDoSoundMac32;
619 			_kernelFuncs[id].signature = parseKernelSignature("DoSoundMac32", "i(.*)");
620 			_kernelFuncs[id].name = "DoSoundMac32";
621 			continue;
622 		}
623 #endif
624 
625 		// If the name is known, look it up in s_kernelMap. This table
626 		// maps kernel func names to actual function (pointers).
627 		SciKernelMapEntry *kernelMap = s_kernelMap;
628 		bool nameMatch = false;
629 		while (kernelMap->name) {
630 			if (kernelName == kernelMap->name) {
631 				if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion <= myVersion))
632 					if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion >= myVersion))
633 						if (platformMask & kernelMap->forPlatform)
634 							break;
635 				nameMatch = true;
636 			}
637 			kernelMap++;
638 		}
639 
640 		if (kernelMap->name) {
641 			// A match was found
642 			_kernelFuncs[id].function = kernelMap->function;
643 			_kernelFuncs[id].name = kernelMap->name;
644 			_kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature);
645 			_kernelFuncs[id].workarounds = kernelMap->workarounds;
646 			if (kernelMap->subFunctions) {
647 				// Get version for subfunction identification
648 				SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).getOffset();
649 				// Now check whats the highest subfunction-id for this version
650 				const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions;
651 				uint16 subFunctionCount = 0;
652 				while (kernelSubMap->function) {
653 					if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion))
654 						if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion))
655 							if (subFunctionCount <= kernelSubMap->id)
656 								subFunctionCount = kernelSubMap->id + 1;
657 					kernelSubMap++;
658 				}
659 				if (!subFunctionCount)
660 					error("k%s[%x]: no subfunctions found for requested version %s", kernelName.c_str(), id, getSciVersionDesc(mySubVersion));
661 				// Now allocate required memory and go through it again
662 				_kernelFuncs[id].subFunctionCount = subFunctionCount;
663 				KernelSubFunction *subFunctions = new KernelSubFunction[subFunctionCount];
664 				_kernelFuncs[id].subFunctions = subFunctions;
665 				memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount);
666 				// And fill this info out
667 				kernelSubMap = kernelMap->subFunctions;
668 				uint kernelSubNr = 0;
669 				while (kernelSubMap->function) {
670 					if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion))
671 						if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) {
672 							uint subId = kernelSubMap->id;
673 							if (!subFunctions[subId].function) {
674 								subFunctions[subId].function = kernelSubMap->function;
675 								subFunctions[subId].name = kernelSubMap->name;
676 								subFunctions[subId].workarounds = kernelSubMap->workarounds;
677 								if (kernelSubMap->signature) {
678 									subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature);
679 								} else {
680 									// we go back the submap to find the previous signature for that kernel call
681 									const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap;
682 									uint kernelSubLeft = kernelSubNr;
683 									while (kernelSubLeft) {
684 										kernelSubLeft--;
685 										kernelSubMapBack--;
686 										if (kernelSubMapBack->name == kernelSubMap->name) {
687 											if (kernelSubMapBack->signature) {
688 												subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature);
689 												break;
690 											}
691 										}
692 									}
693 									if (!subFunctions[subId].signature)
694 										error("k%s: no previous signatures", kernelSubMap->name);
695 								}
696 							}
697 						}
698 					kernelSubMap++;
699 					kernelSubNr++;
700 				}
701 			}
702 			++mapped;
703 		} else {
704 			if (nameMatch)
705 				error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id);
706 			// No match but a name was given -> stub
707 			warning("k%s[%x]: unmapped", kernelName.c_str(), id);
708 			_kernelFuncs[id].function = kStub;
709 		}
710 	} // for all functions requesting to be mapped
711 
712 	debugC(kDebugLevelVM, "Handled %d/%d kernel functions, mapping %d and ignoring %d.",
713 				mapped + ignored, _kernelNames.size(), mapped, ignored);
714 
715 	return;
716 }
717 
718 #ifdef ENABLE_SCI32
719 enum {
720 	kKernelEntriesSci2 = 0x8b,
721 	kKernelEntriesGk2Demo = 0xa0,
722 	kKernelEntriesSci21 = 0x9d,
723 	kKernelEntriesSci3 = 0xa2
724 };
725 #endif
726 
loadKernelNames(GameFeatures * features)727 void Kernel::loadKernelNames(GameFeatures *features) {
728 	_kernelNames.clear();
729 
730 	if (getSciVersion() <= SCI_VERSION_1_1) {
731 		_kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames));
732 
733 		// Some (later) SCI versions replaced CanBeHere by CantBeHere
734 		// If vocab.999 exists, the kernel function is still named CanBeHere
735 		if (_selectorCache.cantBeHere != -1)
736 			_kernelNames[0x4d] = "CantBeHere";
737 	}
738 
739 	switch (getSciVersion()) {
740 	case SCI_VERSION_0_EARLY:
741 	case SCI_VERSION_0_LATE:
742 		// Insert SCI0 file functions after SetCursor (0x28)
743 		_kernelNames.insert_at(0x29, "FOpen");
744 		_kernelNames.insert_at(0x2A, "FPuts");
745 		_kernelNames.insert_at(0x2B, "FGets");
746 		_kernelNames.insert_at(0x2C, "FClose");
747 
748 		// Function 0x55 is DoAvoider
749 		_kernelNames[0x55] = "DoAvoider";
750 
751 		// Cut off unused functions
752 		_kernelNames.resize(0x72);
753 		break;
754 
755 	case SCI_VERSION_01:
756 		// Multilingual SCI01 games have StrSplit as function 0x78
757 		_kernelNames[0x78] = "StrSplit";
758 
759 		// Cut off unused functions
760 		_kernelNames.resize(0x79);
761 		break;
762 
763 	case SCI_VERSION_1_LATE:
764 		_kernelNames[0x71] = "MoveCursor";
765 		break;
766 
767 	case SCI_VERSION_1_1:
768 		// In SCI1.1, kSetSynonyms is an empty function
769 		_kernelNames[0x26] = "Empty";
770 
771 		if (g_sci->getGameId() == GID_KQ6) {
772 			// In the Windows version of KQ6 CD, the empty kSetSynonyms
773 			// function has been replaced with kPortrait. In KQ6 Mac,
774 			// kPlayBack has been replaced by kShowMovie.
775 			if ((g_sci->getPlatform() == Common::kPlatformWindows) || (g_sci->forceHiresGraphics()))
776 				_kernelNames[0x26] = "Portrait";
777 			else if (g_sci->getPlatform() == Common::kPlatformMacintosh)
778 				_kernelNames[0x84] = "ShowMovie";
779 		} else if (g_sci->getGameId() == GID_QFG4DEMO) {
780 			_kernelNames[0x7b] = "RemapColors"; // QFG4 Demo has this SCI2 function instead of StrSplit
781 		} else if (_resMan->testResource(ResourceId(kResourceTypeVocab, 184))) {
782 			_kernelNames[0x7b] = "RemapColorsKawa";
783 			_kernelNames[0x88] = "KawaDbugStr";
784 			_kernelNames[0x89] = "KawaHacks";
785 		}
786 
787 		_kernelNames[0x71] = "PalVary";
788 
789 		// At least EcoQuest 1 demo uses kGetMessage instead of kMessage.
790 		// Detect which function to use.
791 		if (features->detectMessageFunctionType() == SCI_VERSION_1_1)
792 			_kernelNames[0x7c] = "Message";
793 		break;
794 
795 #ifdef ENABLE_SCI32
796 	case SCI_VERSION_2:
797 		_kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2);
798 		break;
799 
800 	case SCI_VERSION_2_1_EARLY:
801 	case SCI_VERSION_2_1_MIDDLE:
802 	case SCI_VERSION_2_1_LATE:
803 		if (features->detectSci21KernelType() == SCI_VERSION_2) {
804 			// Some early SCI2.1 games use a modified SCI2 kernel table instead of
805 			// the SCI2.1 kernel table. We detect which version to use based on
806 			// how kDoSound is called from Sound::play().
807 			// Known games that use this:
808 			// GK2 demo
809 			// KQ7 1.4/1.51
810 			// PQ:SWAT demo
811 			// LSL6
812 			// PQ4CD
813 			// QFG4CD
814 
815 			// This is interesting because they all have the same interpreter
816 			// version (2.100.002), yet they would not be compatible with other
817 			// games of the same interpreter.
818 
819 			_kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo);
820 			// OnMe is IsOnMe here, but they should be compatible
821 			_kernelNames[0x23] = g_sci->getGameId() == GID_LSL6HIRES ? "Empty" : "Robot"; // Graph in SCI2
822 			_kernelNames[0x2e] = "Priority"; // DisposeTextBitmap in SCI2
823 		} else {
824 			// Normal SCI2.1 kernel table
825 			_kernelNames = Common::StringArray(sci21_default_knames, kKernelEntriesSci21);
826 		}
827 		break;
828 
829 	case SCI_VERSION_3:
830 		_kernelNames = Common::StringArray(sci21_default_knames, kKernelEntriesSci3);
831 
832 		// In SCI3, some kernel functions have been removed, and others have been added
833 		_kernelNames[0x18] = "Dummy";	// AddMagnify in SCI2.1
834 		_kernelNames[0x19] = "Dummy";	// DeleteMagnify in SCI2.1
835 		_kernelNames[0x30] = "Dummy";	// SetScroll in SCI2.1
836 		_kernelNames[0x39] = "Dummy";	// ShowMovie in SCI2.1
837 		_kernelNames[0x4c] = "Dummy";	// ScrollWindow in SCI2.1
838 		_kernelNames[0x56] = "Dummy";	// VibrateMouse in SCI2.1 (only used in QFG4 floppy)
839 		_kernelNames[0x66] = "Dummy";	// MergePoly in SCI2.1
840 		_kernelNames[0x8d] = "MessageBox";	// Dummy in SCI2.1
841 		_kernelNames[0x9b] = "Minimize";	// Dummy in SCI2.1
842 
843 		break;
844 #endif
845 
846 	default:
847 		// Use default table for the other versions
848 		break;
849 	}
850 
851 #ifdef ENABLE_SCI32
852 	// Reserve a high range of kernel call IDs (0xe0 to 0xef) that can be used
853 	// by ScummVM to improve integration and fix bugs in games that require
854 	// more help than can be provided by a simple script patch (e.g. spinloops
855 	// in Hoyle5).
856 	// Using a new high range instead of just replacing dummied kernel calls in
857 	// the normal kernel range is intended to avoid any conflicts with fangames
858 	// that might try to add their own kernel calls in the same manner. It also
859 	// helps to separate ScummVM interpreter's kernel calls from SSCI's standard
860 	// kernel calls.
861 	if (getSciVersion() >= SCI_VERSION_2) {
862 		const uint kernelListSize = _kernelNames.size();
863 		_kernelNames.resize(0xe2);
864 		for (uint id = kernelListSize; id < 0xe0; ++id) {
865 			_kernelNames[id] = "Dummy";
866 		}
867 
868 		// Used by SCI32 script patches to remove CPU spinning on kGetTime
869 		_kernelNames[kScummVMSleepId] = "ScummVMSleep";
870 
871 		// Used by GuestAdditions to support integrated save/load dialogue
872 		_kernelNames[kScummVMSaveLoadId] = "ScummVMSaveLoad";
873 	}
874 #endif
875 
876 	mapFunctions(features);
877 }
878 
lookupText(reg_t address,int index)879 Common::String Kernel::lookupText(reg_t address, int index) {
880 	if (address.getSegment())
881 		return _segMan->getString(address);
882 
883 	ResourceId resourceId = ResourceId(kResourceTypeText, address.getOffset());
884 	if (g_sci->getGameId() == GID_HOYLE3 && g_sci->getPlatform() == Common::kPlatformAmiga) {
885 		// WORKAROUND: In the Amiga version of Hoyle 3, texts are stored as
886 		// either text, font or palette types. Seems like the resource type
887 		// bits are used as part of the resource numbers. This is the same
888 		// as the workaround used in GfxFontFromResource()
889 		resourceId = ResourceId(kResourceTypeText, address.getOffset() & 0x7FF);
890 		if (!_resMan->testResource(resourceId))
891 			resourceId = ResourceId(kResourceTypeFont, address.getOffset() & 0x7FF);
892 		if (!_resMan->testResource(resourceId))
893 			resourceId = ResourceId(kResourceTypePalette, address.getOffset() & 0x7FF);
894 	}
895 
896 	Resource *textres = _resMan->findResource(resourceId, false);
897 
898 	if (!textres) {
899 		error("text.%03d not found", address.getOffset());
900 	}
901 
902 	int textlen = textres->size();
903 	const char *seeker = (const char *)textres->getUnsafeDataAt(0);
904 
905 	if (g_sci->getGameId() == GID_LONGBOW && address.getOffset() == 1535 && textlen == 2662) {
906 		// WORKAROUND: Longbow 1.0's text resource 1535 is missing 8 texts for
907 		//  the pub. It appears that only the 5.25 floppy release was affected.
908 		//  This was fixed by Sierra's 1.0 patch.
909 		if (index >= 41) {
910 			// texts 41+ exist but with incorrect offsets
911 			index -= 8;
912 		} else if (index >= 33) {
913 			// texts 33 through 40 are missing. they comprise two sequences of
914 			//  four messages. only one of the two can play, and only once in
915 			//  the specific circumstance that the player enters the pub as a
916 			//  merchant, changes beards, and re-enters.
917 			return "** MISSING MESSAGE **";
918 		}
919 	}
920 
921 	int _index = index;
922 	while (index-- && textlen)
923 		while (textlen-- && *seeker++)
924 			;
925 
926 	if (textlen)
927 		return seeker;
928 
929 	error("Index %d out of bounds in text.%03d", _index, address.getOffset());
930 }
931 
932 // TODO: script_adjust_opcode_formats should probably be part of the
933 // constructor (?) of a VirtualMachine or a ScriptManager class.
script_adjust_opcode_formats()934 void script_adjust_opcode_formats() {
935 
936 	g_sci->_opcode_formats = new opcode_format[128][4];
937 	memcpy(g_sci->_opcode_formats, g_base_opcode_formats, 128*4*sizeof(opcode_format));
938 
939 	if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) {
940 		g_sci->_opcode_formats[op_lofsa][0] = Script_Offset;
941 		g_sci->_opcode_formats[op_lofss][0] = Script_Offset;
942 	}
943 
944 #ifdef ENABLE_SCI32
945 	// In SCI32, some arguments are now words instead of bytes
946 	if (getSciVersion() >= SCI_VERSION_2) {
947 		g_sci->_opcode_formats[op_calle][2] = Script_Word;
948 		g_sci->_opcode_formats[op_callk][1] = Script_Word;
949 		g_sci->_opcode_formats[op_super][1] = Script_Word;
950 		g_sci->_opcode_formats[op_send][0] = Script_Word;
951 		g_sci->_opcode_formats[op_self][0] = Script_Word;
952 		g_sci->_opcode_formats[op_call][1] = Script_Word;
953 		g_sci->_opcode_formats[op_callb][1] = Script_Word;
954 	}
955 
956 	if (getSciVersion() >= SCI_VERSION_3) {
957 		g_sci->_opcode_formats[op_info][0] = Script_None;
958 		g_sci->_opcode_formats[op_superP][0] = Script_None;
959 	}
960 #endif
961 }
962 
963 } // End of namespace Sci
964