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