Пример #1
0
SciVersion GameFeatures::detectMessageFunctionType() {
	if (_messageFunctionType != SCI_VERSION_NONE)
		return _messageFunctionType;

	if (getSciVersion() > SCI_VERSION_1_1) {
		_messageFunctionType = SCI_VERSION_1_1;
		return _messageFunctionType;
	} else if (getSciVersion() < SCI_VERSION_1_1) {
		_messageFunctionType = SCI_VERSION_1_LATE;
		return _messageFunctionType;
	}

	Common::List<ResourceId> resources = g_sci->getResMan()->listResources(kResourceTypeMessage, -1);

	if (resources.empty()) {
		// No messages found, so this doesn't really matter anyway...
		_messageFunctionType = SCI_VERSION_1_1;
		return _messageFunctionType;
	}

	Resource *res = g_sci->getResMan()->findResource(*resources.begin(), false);
	assert(res);

	// Only v2 Message resources use the kGetMessage kernel function.
	// v3-v5 use the kMessage kernel function.

	if (READ_SCI11ENDIAN_UINT32(res->data) / 1000 == 2)
		_messageFunctionType = SCI_VERSION_1_LATE;
	else
		_messageFunctionType = SCI_VERSION_1_1;

	debugC(1, kDebugLevelVM, "Detected message function type: %s", getSciVersionDesc(_messageFunctionType));
	return _messageFunctionType;
}
Пример #2
0
SciVersion GameFeatures::detectDoSoundType() {
	if (_doSoundType == SCI_VERSION_NONE) {
		if (getSciVersion() == SCI_VERSION_0_EARLY) {
			// Almost all of the SCI0EARLY games use different sound resources than
			//  SCI0LATE. Although the last SCI0EARLY game (lsl2) uses SCI0LATE resources
			_doSoundType = g_sci->getResMan()->detectEarlySound() ? SCI_VERSION_0_EARLY : SCI_VERSION_0_LATE;
#ifdef ENABLE_SCI32
		} else if (getSciVersion() >= SCI_VERSION_2_1_EARLY) {
			_doSoundType = SCI_VERSION_2_1_EARLY;
#endif
		} else if (SELECTOR(nodePtr) == -1) {
			// No nodePtr selector, so this game is definitely using newer
			// SCI0 sound code (i.e. SCI_VERSION_0_LATE)
			_doSoundType = SCI_VERSION_0_LATE;
		} else if (getSciVersion() >= SCI_VERSION_1_LATE) {
			// All SCI1 late games use the newer doSound semantics
			_doSoundType = SCI_VERSION_1_LATE;
		} else {
			if (!autoDetectSoundType()) {
				warning("DoSound detection failed, taking an educated guess");

				if (getSciVersion() >= SCI_VERSION_1_MIDDLE)
					_doSoundType = SCI_VERSION_1_LATE;
				else if (getSciVersion() > SCI_VERSION_01)
					_doSoundType = SCI_VERSION_1_EARLY;
			}
		}

		debugC(1, kDebugLevelSound, "Detected DoSound type: %s", getSciVersionDesc(_doSoundType));
	}

	return _doSoundType;
}
Пример #3
0
reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) {
	debugC(kDebugLevelFile, "kFileIO(close): %d", argv[0].toUint16());

	if (argv[0] == SIGNAL_REG)
		return s->r_acc;
	
	uint16 handle = argv[0].toUint16();

#ifdef ENABLE_SCI32
	if (handle == VIRTUALFILE_HANDLE) {
		s->_virtualIndexFile->close();
		return SIGNAL_REG;
	}
#endif

	FileHandle *f = getFileFromHandle(s, handle);
	if (f) {
		f->close();
		if (getSciVersion() <= SCI_VERSION_0_LATE)
			return s->r_acc;	// SCI0 semantics: no value returned
		return SIGNAL_REG;
	}

	if (getSciVersion() <= SCI_VERSION_0_LATE)
		return s->r_acc;	// SCI0 semantics: no value returned
	return NULL_REG;
}
Пример #4
0
reg_t kFileIOWriteString(EngineState *s, int argc, reg_t *argv) {
	int handle = argv[0].toUint16();
	Common::String str = s->_segMan->getString(argv[1]);
	debugC(kDebugLevelFile, "kFileIO(writeString): %d", handle);

#ifdef ENABLE_SCI32
	if (handle == VIRTUALFILE_HANDLE) {
		s->_virtualIndexFile->write(str.c_str(), str.size());
		return NULL_REG;
	}
#endif

	FileHandle *f = getFileFromHandle(s, handle);

	if (f) {
		f->_out->write(str.c_str(), str.size());
		if (getSciVersion() <= SCI_VERSION_0_LATE)
			return s->r_acc;	// SCI0 semantics: no value returned
		return NULL_REG;
	}

	if (getSciVersion() <= SCI_VERSION_0_LATE)
		return s->r_acc;	// SCI0 semantics: no value returned
	return make_reg(0, 6); // DOS - invalid handle
}
Пример #5
0
void SciEngine::updateScummVMAudioOptions() {
	// Update ScummVM's speech/subtitles settings for SCI1.1 CD games,
	// depending on the in-game settings
	if ((isCD() && getSciVersion() == SCI_VERSION_1_1) ||
		getSciVersion() >= SCI_VERSION_2) {

		uint16 ingameSetting = _gamestate->variables[VAR_GLOBAL][kGlobalVarMessageType].getOffset();

		switch (ingameSetting) {
		case 1:
			// subtitles
			ConfMan.setBool("subtitles", true);
			ConfMan.setBool("speech_mute", true);
			break;
		case 2:
			// speech
			ConfMan.setBool("subtitles", false);
			ConfMan.setBool("speech_mute", false);
			break;
		case 3:
			// speech + subtitles
			ConfMan.setBool("subtitles", true);
			ConfMan.setBool("speech_mute", false);
			break;
		default:
			break;
		}
	}
}
Пример #6
0
// TODO: script_adjust_opcode_formats should probably be part of the
// constructor (?) of a VirtualMachine or a ScriptManager class.
void script_adjust_opcode_formats() {

	g_sci->_opcode_formats = new opcode_format[128][4];
	memcpy(g_sci->_opcode_formats, g_base_opcode_formats, 128*4*sizeof(opcode_format));

	if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) {
		g_sci->_opcode_formats[op_lofsa][0] = Script_Offset;
		g_sci->_opcode_formats[op_lofss][0] = Script_Offset;
	}

#ifdef ENABLE_SCI32
	// In SCI32, some arguments are now words instead of bytes
	if (getSciVersion() >= SCI_VERSION_2) {
		g_sci->_opcode_formats[op_calle][2] = Script_Word;
		g_sci->_opcode_formats[op_callk][1] = Script_Word;
		g_sci->_opcode_formats[op_super][1] = Script_Word;
		g_sci->_opcode_formats[op_send][0] = Script_Word;
		g_sci->_opcode_formats[op_self][0] = Script_Word;
		g_sci->_opcode_formats[op_call][1] = Script_Word;
		g_sci->_opcode_formats[op_callb][1] = Script_Word;
	}

	if (getSciVersion() >= SCI_VERSION_3) {
		// TODO: There are also opcodes in
		// here to get the superclass, and possibly the species too.
		g_sci->_opcode_formats[0x4d/2][0] = Script_None;
		g_sci->_opcode_formats[0x4e/2][0] = Script_None;
	}
#endif
}
Пример #7
0
void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv) {
	byte old_picNotValid = _screen->_picNotValid;

	if (getSciVersion() >= SCI_VERSION_1_1)
		_palette->palVaryUpdate();

	if (listReference.isNull()) {
		disposeLastCast();
		if (_screen->_picNotValid)
			animateShowPic();
		return;
	}

	List *list = _s->_segMan->lookupList(listReference);
	if (!list)
		error("kAnimate called with non-list as parameter");

	if (cycle) {
		if (!invoke(list, argc, argv))
			return;

		// Look up the list again, as it may have been modified
		list = _s->_segMan->lookupList(listReference);
	}

	Port *oldPort = _ports->setPort((Port *)_ports->_picWind);
	disposeLastCast();

	makeSortedList(list);
	fill(old_picNotValid);

	if (old_picNotValid) {
		// beginUpdate()/endUpdate() were introduced SCI1.
		// Calling those for SCI0 will work most of the time but breaks minor
		// stuff like percentage bar of qfg1ega at the character skill screen.
		if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
			_ports->beginUpdate(_ports->_picWind);
		update();
		if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY)
			_ports->endUpdate(_ports->_picWind);
	}

	drawCels();

	if (_screen->_picNotValid)
		animateShowPic();

	updateScreen(old_picNotValid);
	restoreAndDelete(argc, argv);

	// We update the screen here as well, some scenes like EQ1 credits run w/o calling kGetEvent thus we wouldn't update
	//  screen at all
	g_sci->getEventManager()->updateScreen();

	_ports->setPort(oldPort);

	// Now trigger speed throttler
	throttleSpeed();
}
Пример #8
0
void Script::init(int script_nr, ResourceManager *resMan) {
	Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);

	if (!script)
		error("Script %d not found", script_nr);

	_localsOffset = 0;
	_localsBlock = NULL;
	_localsCount = 0;

	_markedAsDeleted = false;

	_nr = script_nr;
	_buf = 0;
	_heapStart = 0;

	_scriptSize = script->size;
	_bufSize = script->size;
	_heapSize = 0;

	_lockers = 1;

	if (getSciVersion() == SCI_VERSION_0_EARLY) {
		_bufSize += READ_LE_UINT16(script->data) * 2;
	} else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
		// In SCI1.1 - SCI2.1, the heap was in a separate space from the script. We append
		// it to the end of the script, and adjust addressing accordingly.
		// However, since we address the heap with a 16-bit pointer, the
		// combined size of the stack and the heap must be 64KB. So far this has
		// worked for SCI11, SCI2 and SCI21 games. SCI3 games use a different
		// script format, and theoretically they can exceed the 64KB boundary
		// using relocation.
		Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
		_bufSize += heap->size;
		_heapSize = heap->size;

		// Ensure that the start of the heap resource can be word-aligned.
		if (script->size & 2) {
			_bufSize++;
			_scriptSize++;
		}

		// As mentioned above, the script and the heap together should not exceed 64KB
		if (script->size + heap->size > 65535)
			error("Script and heap sizes combined exceed 64K. This means a fundamental "
					"design bug was made regarding SCI1.1 and newer games.\n"
					"Please report this error to the ScummVM team");
	} else if (getSciVersion() == SCI_VERSION_3) {
		// Check for scripts over 64KB. These won't work with the current 16-bit address
		// scheme. We need an overlaying mechanism, or a mechanism to split script parts
		// in different segments to handle these. For now, simply stop when such a script
		// is found.
		// TODO: Remove this once such a mechanism is in place
		if (script->size > 65535)
			error("TODO: SCI script %d is over 64KB - it's %d bytes long. This can't "
			      "be handled at the moment, thus stopping", script_nr, script->size);
	}
}
Пример #9
0
void Script::load(ResourceManager *resMan) {
	Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0);
	assert(script != 0);

	uint extraLocalsWorkaround = 0;
	if (g_sci->getGameId() == GID_FANMADE && _nr == 1 && script->size == 11140) {
		// WORKAROUND: Script 1 in Ocean Battle doesn't have enough locals to
		// fit the string showing how many shots are left (a nasty script bug,
		// corrupting heap memory). We add 10 more locals so that it has enough
		// space to use as the target for its kFormat operation. Fixes bug
		// #3059871.
		extraLocalsWorkaround = 10;
	}
	_bufSize += extraLocalsWorkaround * 2;

	_buf = (byte *)malloc(_bufSize);
	assert(_buf);

	assert(_bufSize >= script->size);
	memcpy(_buf, script->data, script->size);

	// Check scripts for matching signatures and patch those, if found
	matchSignatureAndPatch(_nr, _buf, script->size);

	if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
		Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0);
		assert(heap != 0);

		_heapStart = _buf + _scriptSize;

		assert(_bufSize - _scriptSize <= heap->size);
		memcpy(_heapStart, heap->data, heap->size);
	}

	_exportTable = 0;
	_numExports = 0;
	_synonyms = 0;
	_numSynonyms = 0;
	
	if (getSciVersion() <= SCI_VERSION_1_LATE) {
		_exportTable = (const uint16 *)findBlockSCI0(SCI_OBJ_EXPORTS);
		if (_exportTable) {
			_numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1);
			_exportTable += 3;	// skip header plus 2 bytes (_exportTable is a uint16 pointer)
		}
		_synonyms = findBlockSCI0(SCI_OBJ_SYNONYMS);
		if (_synonyms) {
			_numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4;
			_synonyms += 4;	// skip header
		}
		const byte* localsBlock = findBlockSCI0(SCI_OBJ_LOCALVARS);
		if (localsBlock) {
			_localsOffset = localsBlock - _buf + 4;
			_localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1;	// half block size
		}
	} else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
Пример #10
0
SciVersion GameFeatures::detectLofsType() {
	if (_lofsType == SCI_VERSION_NONE) {
		// This detection only works (and is only needed) for SCI 1
		if (getSciVersion() <= SCI_VERSION_01) {
			_lofsType = SCI_VERSION_0_EARLY;
			return _lofsType;
		}

		if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
			// SCI1.1 type, i.e. we compensate for the fact that the heap is attached
			// to the end of the script
			_lofsType = SCI_VERSION_1_1;
			return _lofsType;
		}

		if (getSciVersion() == SCI_VERSION_3) {
			// SCI3 type, same as pre-SCI1.1, really, as there is no separate heap
			// resource
			_lofsType = SCI_VERSION_3;
			return _lofsType;
		}

		// Find a function of the "Game" object (which is the game super class) which invokes lofsa/lofss
		reg_t gameSuperClass = g_sci->getGameSuperClassAddress();
		bool found = false;
		if (!gameSuperClass.isNull()) {
			Common::String gameSuperClassName = _segMan->getObjectName(gameSuperClass);
			const Object *gameSuperObject = _segMan->getObject(gameSuperClass);

			if (gameSuperObject) {
				for (uint m = 0; m < gameSuperObject->getMethodCount(); m++) {
					found = autoDetectLofsType(gameSuperClassName, m);
					if (found)
						break;
				}
			} else {
				warning("detectLofsType(): Could not get superclass object");
			}
		} else {
			warning("detectLofsType(): Could not find superclass of game object");
		}

		if (!found) {
			warning("detectLofsType(): failed, taking an educated guess");

			if (getSciVersion() >= SCI_VERSION_1_MIDDLE)
				_lofsType = SCI_VERSION_1_MIDDLE;
			else
				_lofsType = SCI_VERSION_0_EARLY;
		}

		debugC(1, kDebugLevelVM, "Detected Lofs type: %s", getSciVersionDesc(_lofsType));
	}

	return _lofsType;
}
Пример #11
0
void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) {
	int16 sci0EarlyPen = 0, sci0EarlyBack = 0;
	if (!hilite) {
		if (getSciVersion() == SCI_VERSION_0_EARLY) {
			// SCI0early actually used hardcoded green/black buttons instead of using the port colors
			sci0EarlyPen = _ports->_curPort->penClr;
			sci0EarlyBack = _ports->_curPort->backClr;
			_ports->penColor(0);
			_ports->backColor(2);
		}
		rect.grow(1);
		_paint16->eraseRect(rect);
		_paint16->frameRect(rect);
		rect.grow(-2);
		_ports->textGreyedOutput(!(style & SCI_CONTROLS_STYLE_ENABLED));

	//20140521
		//_text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId);

		std::map<std::string, std::string>::iterator iter;
		if(g_sci->_ScriptData)
		{		
			_ShouterInfo* pInfo = g_sci->_ScriptData->GetShouterInfo();
			iter = pInfo->SentenceList.find(text);
			if(iter == pInfo->SentenceList.end())
				_text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId, true);
			else
				_text16->Box(iter->second.c_str(), false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId, true);
		}
		else
		{
			_text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId);
		}
//End

		_ports->textGreyedOutput(false);
		rect.grow(1);
		if (style & SCI_CONTROLS_STYLE_SELECTED)
			_paint16->frameRect(rect);
		if (!getPicNotValid()) {
			rect.grow(1);
			_paint16->bitsShow(rect);
		}
		if (getSciVersion() == SCI_VERSION_0_EARLY) {
			_ports->penColor(sci0EarlyPen);
			_ports->backColor(sci0EarlyBack);
		}
	} else {
		// SCI0early used xor to invert button rectangles resulting in pink/white buttons
		if (getSciVersion() == SCI_VERSION_0_EARLY)
			_paint16->invertRectViaXOR(rect);
		else
			_paint16->invertRect(rect);
		_paint16->bitsShow(rect);
	}
}
Пример #12
0
void Script::initializeObjects(SegManager *segMan, SegmentId segmentId) {
	if (getSciVersion() <= SCI_VERSION_1_LATE)
		initializeObjectsSci0(segMan, segmentId);
	else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE)
		initializeObjectsSci11(segMan, segmentId);
#ifdef ENABLE_SCI32
	else if (getSciVersion() == SCI_VERSION_3)
		initializeObjectsSci3(segMan, segmentId);
#endif
}
Пример #13
0
/**
 * Causes an immediate plane transition with an optional transition
 * effect
 */
reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
	ShowStyleType type = (ShowStyleType)argv[0].toUint16();
	reg_t planeObj = argv[1];
	int16 seconds = argv[2].toSint16();
	// NOTE: This value seems to indicate whether the transition is an
	// “exit” transition (0) or an “enter” transition (-1) for fade
	// transitions. For other types of transitions, it indicates a palette
	// index value to use when filling the screen.
	int16 back = argv[3].toSint16();
	int16 priority = argv[4].toSint16();
	int16 animate = argv[5].toSint16();
	// TODO: Rename to frameOutNow?
	int16 refFrame = argv[6].toSint16();
	int16 blackScreen;
	reg_t pFadeArray;
	int16 divisions;

	// SCI 2–2.1early
	if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
		blackScreen = 0;
		pFadeArray = NULL_REG;
		divisions = argc > 7 ? argv[7].toSint16() : -1;
	}
	// SCI 2.1mid–2.1late
	else if (getSciVersion() < SCI_VERSION_3) {
		blackScreen = 0;
		pFadeArray = argc > 7 ? argv[7] : NULL_REG;
		divisions = argc > 8 ? argv[8].toSint16() : -1;
	}
	// SCI 3
	else {
		blackScreen = argv[7].toSint16();
		pFadeArray = argc > 8 ? argv[8] : NULL_REG;
		divisions = argc > 9 ? argv[9].toSint16() : -1;
	}

// TODO: Reuse later for SCI2 and SCI3 implementation and then discard
//	warning("kSetShowStyle: effect %d, plane: %04x:%04x (%s), sec: %d, "
//			"dir: %d, prio: %d, animate: %d, ref frame: %d, black screen: %d, "
//			"pFadeArray: %04x:%04x (%s), divisions: %d",
//			type, PRINT_REG(planeObj), s->_segMan->getObjectName(planeObj), seconds,
//			back, priority, animate, refFrame, blackScreen,
//			PRINT_REG(pFadeArray), s->_segMan->getObjectName(pFadeArray), divisions);

	// NOTE: The order of planeObj and showStyle are reversed
	// because this is how SCI3 called the corresponding method
	// on the KernelMgr
	g_sci->_gfxTransitions32->kernelSetShowStyle(argc, planeObj, type, seconds, back, priority, animate, refFrame, pFadeArray, divisions, blackScreen);

	return s->r_acc;
}
Пример #14
0
void GfxAnimate::init() {
	_lastCastData.clear();

	_ignoreFastCast = false;
	// fastCast object is not found in any SCI games prior SCI1
	if (getSciVersion() <= SCI_VERSION_01)
		_ignoreFastCast = true;
	// Also if fastCast object exists at gamestartup, we can assume that the interpreter doesnt do kAnimate aborts
	//  (found in Larry 1)
	if (getSciVersion() > SCI_VERSION_0_EARLY) {
		if (!_s->_segMan->findObjectByName("fastCast").isNull())
			_ignoreFastCast = true;
	}
}
Пример #15
0
Common::StringArray Kernel::checkStaticSelectorNames() {
	Common::StringArray names;
	const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0;

#ifdef ENABLE_SCI32
	const int count = (getSciVersion() <= SCI_VERSION_1_1) ? ARRAYSIZE(sci0Selectors) + offset : ARRAYSIZE(sci2Selectors);
#else
	const int count = ARRAYSIZE(sci0Selectors) + offset;
#endif
	int countSci1 = ARRAYSIZE(sci1Selectors);
	int countSci11 = ARRAYSIZE(sci11Selectors);

	// Resize the list of selector names and fill in the SCI 0 names.
	names.resize(count);
	if (getSciVersion() <= SCI_VERSION_1_LATE) {
		// Fill selectors 0 - 2 for SCI0 - SCI1 late
		names[0] = "species";
		names[1] = "superClass";
		names[2] = "-info-";
	}

	if (getSciVersion() <= SCI_VERSION_1_1) {
		// SCI0 - SCI11
		for (int i = offset; i < count; i++)
			names[i] = sci0Selectors[i - offset];

		if (getSciVersion() > SCI_VERSION_01) {
			// Several new selectors were added in SCI 1 and later.
			names.resize(count + countSci1);
			for (int i = count; i < count + countSci1; i++)
				names[i] = sci1Selectors[i - count];
		}

		if (getSciVersion() >= SCI_VERSION_1_1) {
			// Several new selectors were added in SCI 1.1
			names.resize(count + countSci1 + countSci11);
			for (int i = count + countSci1; i < count + countSci1 + countSci11; i++)
				names[i] = sci11Selectors[i - count - countSci1];
		}
#ifdef ENABLE_SCI32
	} else {
		// SCI2+
		for (int i = 0; i < count; i++)
			names[i] = sci2Selectors[i];
#endif
	}

	findSpecificSelectors(names);

	for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
		if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
			const uint32 slot = selectorRemap->slot;
			if (slot >= names.size())
				names.resize(slot + 1);
			names[slot] = selectorRemap->name;
		}
	}

	return names;
}
Пример #16
0
void GfxAnimate::init() {
	_lastCastData.clear();

	_fastCastEnabled = false;
	if (getSciVersion() == SCI_VERSION_1_1) {
		// Seems to have been available for all SCI1.1 games
		_fastCastEnabled = true;
	} else if (getSciVersion() >= SCI_VERSION_1_EARLY) {
		// fastCast only exists for some games between SCI1 early and SCI1 late
		// Try to detect it by code signature
		// It's extremely important, that we only enable it for games that actually need it
		if (detectFastCast()) {
			_fastCastEnabled = true;
		}
	}
}
Пример #17
0
// Note: don't do too many steps in here, otherwise cpu will crap out because of
// the load
void GfxTransitions::fadeOut() {
	byte oldPalette[3 * 256], workPalette[3 * 256];
	int16 stepNr, colorNr;
	// Sierra did not fade in/out color 255 for sci1.1, but they used it in
	//  several pictures (e.g. qfg3 demo/intro), so the fading looked weird
	int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254;

	g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256);

	for (stepNr = 100; stepNr >= 0; stepNr -= 10) {
		for (colorNr = 1; colorNr <= tillColorNr; colorNr++) {
			if (_palette->colorIsFromMacClut(colorNr)) {
				workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3];
				workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1];
				workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2];
			} else {
				workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100;
				workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100;
				workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100;
			}
		}
		g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr);
		g_sci->getEngineState()->wait(2);
	}
}
Пример #18
0
void SoundCommandParser::initSoundResource(MusicEntry *newSound) {
	if (newSound->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, newSound->resourceId)))
		newSound->soundRes = new SoundResource(newSound->resourceId, _resMan, _soundVersion);
	else
		newSound->soundRes = 0;

	// In SCI1.1 games, sound effects are started from here. If we can find
	// a relevant audio resource, play it, otherwise switch to synthesized
	// effects. If the resource exists, play it using map 65535 (sound
	// effects map)
	bool checkAudioResource = getSciVersion() >= SCI_VERSION_1_1;
	// Hoyle 4 has garbled audio resources in place of the sound resources.
	// The demo of GK1 has no alternate sound effects.
	if ((g_sci->getGameId() == GID_HOYLE4) || 
		(g_sci->getGameId() == GID_GK1 && g_sci->isDemo()))
		checkAudioResource = false;

	if (checkAudioResource && _resMan->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId))) {
		// Found a relevant audio resource, create an audio stream if there is
		// no associated sound resource, or if both resources exist and the
		// user wants the digital version.
		if (_bMultiMidi || !newSound->soundRes) {
			int sampleLen;
			newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen);
			newSound->soundType = Audio::Mixer::kSpeechSoundType;
		}
	}

	if (!newSound->pStreamAud && newSound->soundRes)
		_music->soundInitSnd(newSound);
}
Пример #19
0
void SciEngine::syncIngameAudioOptions() {
	// Sync the in-game speech/subtitles settings for SCI1.1 CD games
	if (isCD() && getSciVersion() == SCI_VERSION_1_1) {
		bool subtitlesOn = ConfMan.getBool("subtitles");
		bool speechOn = !ConfMan.getBool("speech_mute");

		if (subtitlesOn && !speechOn) {
			_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 1);	// subtitles
		} else if (!subtitlesOn && speechOn) {
			_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2);	// speech
		} else if (subtitlesOn && speechOn) {
			// Is it a game that supports simultaneous speech and subtitles?
			switch (_gameId) {
			case GID_SQ4:
			case GID_FREDDYPHARKAS:
			case GID_ECOQUEST:
			case GID_LSL6:
			case GID_LAURABOW2:
			case GID_KQ6:
				_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 3);	// speech + subtitles
				break;
			default:
				// Game does not support speech and subtitles, set it to speech
				_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2);	// speech
			}
		}
	}
}
Пример #20
0
void GuestAdditions::instantiateScriptHook(Script &script, const bool ignoreDelayedRestore) const {
	if (getSciVersion() < SCI_VERSION_2) {
		return;
	}

	// If there is a delayed restore, we still want to patch the script so
	// that the automatic return of the game ID works, but we do not want to
	// patch the scripts that get restored
	if (ConfMan.getBool("originalsaveload") &&
		(ignoreDelayedRestore || _state->_delayedRestoreGameId == -1)) {
		return;
	}

	if (g_sci->getGameId() == GID_TORIN && script.getScriptNumber() == 64866) {
		patchGameSaveRestoreTorin(script);
	} else if (script.getScriptNumber() == 64990) {
		// 64990 is the system script containing SRDialog. This script is used
		// by the main Game object, but it is not loaded immediately, so we wait
		// for it to be loaded before patching it. Attempting to preload this
		// script early for patching will cause the order of entries in the
		// segment table to change (versus save games that are not patched),
		// breaking persistent objects (like the control panel in SQ6) which
		// require reg_ts created during game startup to always be the same
		patchGameSaveRestoreSCI32(script);
	}
}
Пример #21
0
SciSpan<const byte> Script::findBlockSCI0(ScriptObjectTypes type, bool findLastBlock) const {
	SciSpan<const byte> foundBlock;

	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);

	SciSpan<const byte> buf = *_buf;
	if (oldScriptHeader)
		buf += 2;

	for (;;) {
		const int blockType = buf.getUint16LEAt(0);

		if (blockType == 0)
			break;

		// the size in the block header includes the size of the header itself
		const int blockSize = buf.getUint16LEAt(2);
		assert(blockSize > 0);

		if (blockType == type) {
			foundBlock = buf.subspan(0, blockSize, Common::String::format("%s, %s block", _buf->name().c_str(), sciObjectTypeNames[type]));

			if (!findLastBlock) {
				break;
			}
		}

		buf += blockSize;
	}

	return foundBlock;
}
Пример #22
0
void GfxCompare::kernelBaseSetter(reg_t object) {
	if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) {
		int16 x = readSelectorValue(_segMan, object, SELECTOR(x));
		int16 y = readSelectorValue(_segMan, object, SELECTOR(y));
		int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0;
		int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep));
		GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view));
		int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop));
		int16 celNo = readSelectorValue(_segMan, object, SELECTOR(cel));
		uint16 scaleSignal = 0;
		if (getSciVersion() >= SCI_VERSION_1_1)
			scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal));

		Common::Rect celRect;

		GfxView *tmpView = _cache->getView(viewId);
		if (!tmpView->isScaleable())
			scaleSignal = 0;

		if (scaleSignal & kScaleSignalDoScaling) {
			celRect = getNSRect(object);
		} else {
			tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);
		}

		celRect.bottom = y + 1;
		celRect.top = celRect.bottom - yStep;

		writeSelectorValue(_segMan, object, SELECTOR(brLeft), celRect.left);
		writeSelectorValue(_segMan, object, SELECTOR(brRight), celRect.right);
		writeSelectorValue(_segMan, object, SELECTOR(brTop), celRect.top);
		writeSelectorValue(_segMan, object, SELECTOR(brBottom), celRect.bottom);
	}
}
Пример #23
0
static void patchGameSaveRestoreCodeSci2(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) {
	Script *script = segMan->getScript(methodAddress.getSegment());
	byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset()));
	int kcallOffset;

	if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
		if (doRestore) {
			memcpy(patchPtr, patchGameRestoreSci2, sizeof(patchGameRestoreSci2));
			kcallOffset = 9;
		} else {
			memcpy(patchPtr, patchGameSaveSci2, sizeof(patchGameSaveSci2));
			kcallOffset = 10;
		}
	} else {
		if (doRestore) {
			memcpy(patchPtr, patchGameRestoreSci21, sizeof(patchGameRestoreSci21));
			kcallOffset = 10;
		} else {
			memcpy(patchPtr, patchGameSaveSci21, sizeof(patchGameSaveSci21));
			kcallOffset = 11;
		}
	}

	patchPtr[kcallOffset] = id;
	if (g_sci->isBE()) {
		SWAP(patchPtr[kcallOffset + 1], patchPtr[kcallOffset + 2]);
	}
}
Пример #24
0
void SciEngine::loadMacExecutable() {
	if (getPlatform() != Common::kPlatformMacintosh || getSciVersion() < SCI_VERSION_1_EARLY || getSciVersion() > SCI_VERSION_1_1)
		return;

	Common::String filename;

	switch (getGameId()) {
	case GID_KQ6:
		filename = "King's Quest VI";
		break;
	case GID_FREDDYPHARKAS:
		filename = "Freddy Pharkas";
		break;
	default:
		break;
	}

	if (filename.empty())
		return;

	if (!_macExecutable.open(filename) || !_macExecutable.hasResFork()) {
		// KQ6/Freddy require the executable to load their icon bar palettes
		if (hasMacIconBar())
			error("Could not load Mac resource fork '%s'", filename.c_str());

		// TODO: Show some sort of warning dialog saying they can't get any
		// high-res Mac fonts, when we get to that point ;)
	}
}
Пример #25
0
void SciEngine::syncIngameAudioOptions() {
	// Now, sync the in-game speech/subtitles settings for SCI1.1 CD games
	if (isCD() && getSciVersion() == SCI_VERSION_1_1) {
		bool subtitlesOn = ConfMan.getBool("subtitles");
		bool speechOn = !ConfMan.getBool("speech_mute");

		if (subtitlesOn && !speechOn) {
			_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 1);	// subtitles
		} else if (!subtitlesOn && speechOn) {
			_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2);	// speech
		} else if (subtitlesOn && speechOn) {
			// Is it a game that supports simultaneous speech and subtitles?
			if (getGameId() == GID_SQ4 
				|| getGameId() == GID_FREDDYPHARKAS
				// TODO: The following need script patches for simultaneous speech and subtitles
				//|| getGameId() == GID_KQ6
				//|| getGameId() == GID_LAURABOW2
				) {
				_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 3);	// speech + subtitles
			} else {
				// Game does not support speech and subtitles, set it to speech
				_gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 2);	// speech
			}
		}
	}
}
Пример #26
0
reg_t kSetSynonyms(EngineState *s, int argc, reg_t *argv) {
	SegManager *segMan = s->_segMan;
	reg_t object = argv[0];
	List *list;
	Node *node;
	int script;
	int numSynonyms = 0;
	Vocabulary *voc = g_sci->getVocabulary();

	// Only SCI0-SCI1 EGA games had a parser. In newer versions, this is a stub
	if (getSciVersion() > SCI_VERSION_1_EGA_ONLY)
		return s->r_acc;

	voc->clearSynonyms();

	list = s->_segMan->lookupList(readSelector(segMan, object, SELECTOR(elements)));
	node = s->_segMan->lookupNode(list->first);

	while (node) {
		reg_t objpos = node->value;
		int seg;

		script = readSelectorValue(segMan, objpos, SELECTOR(number));
		seg = s->_segMan->getScriptSegment(script);

		if (seg > 0)
			numSynonyms = s->_segMan->getScript(seg)->getSynonymsNr();

		if (numSynonyms) {
			const byte *synonyms = s->_segMan->getScript(seg)->getSynonyms();

			if (synonyms) {
				debugC(kDebugLevelParser, "Setting %d synonyms for script.%d",
				          numSynonyms, script);

				if (numSynonyms > 16384) {
					error("Segtable corruption: script.%03d has %d synonyms",
					         script, numSynonyms);
					/* We used to reset the corrupted value here. I really don't think it's appropriate.
					 * Lars */
				} else
					for (int i = 0; i < numSynonyms; i++) {
						synonym_t tmp;
						tmp.replaceant = READ_LE_UINT16(synonyms + i * 4);
						tmp.replacement = READ_LE_UINT16(synonyms + i * 4 + 2);
						voc->addSynonym(tmp);
					}
			} else
				warning("Synonyms of script.%03d were requested, but script is not available", script);

		}

		node = s->_segMan->lookupNode(node->succ);
	}

	debugC(kDebugLevelParser, "A total of %d synonyms are active now.", numSynonyms);

	return s->r_acc;
}
Пример #27
0
SciVersion GameFeatures::detectSetCursorType() {
	if (_setCursorType == SCI_VERSION_NONE) {
		if (getSciVersion() <= SCI_VERSION_1_MIDDLE) {
			// SCI1 middle and older games never use cursor views
			_setCursorType = SCI_VERSION_0_EARLY;
		} else if (getSciVersion() >= SCI_VERSION_1_1) {
			// SCI1.1 games always use cursor views
			_setCursorType = SCI_VERSION_1_1;
		} else {	// SCI1 late game, detect cursor semantics
			// If the Cursor object doesn't exist, we're using the SCI0 early
			// kSetCursor semantics.
			if (_segMan->findObjectByName("Cursor") == NULL_REG) {
				_setCursorType = SCI_VERSION_0_EARLY;
				debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", getSciVersionDesc(_setCursorType));
				return _setCursorType;
			}

			// Check for the existence of the handCursor object (first found).
			// This is based on KQ5.
			reg_t objAddr = _segMan->findObjectByName("handCursor", 0);

			// If that doesn't exist, we assume it uses SCI1.1 kSetCursor semantics
			if (objAddr == NULL_REG) {
				_setCursorType = SCI_VERSION_1_1;
				debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", getSciVersionDesc(_setCursorType));
				return _setCursorType;
			}

			// Now we check what the number variable holds in the handCursor
			// object.
			uint16 number = readSelectorValue(_segMan, objAddr, SELECTOR(number));

			// If the number is 0, it uses views and therefore the SCI1.1
			// kSetCursor semantics, otherwise it uses the SCI0 early kSetCursor
			// semantics.
			if (number == 0)
				_setCursorType = SCI_VERSION_1_1;
			else
				_setCursorType = SCI_VERSION_0_EARLY;
		}

		debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", getSciVersionDesc(_setCursorType));
	}

	return _setCursorType;
}
Пример #28
0
reg_t kArrayGetElement(EngineState *s, int argc, reg_t *argv) {
	if (getSciVersion() == SCI_VERSION_2_1_LATE) {
		return kStringGetChar(s, argc, argv);
	}

	SciArray &array = *s->_segMan->lookupArray(argv[0]);
	return array.getAsID(argv[1].toUint16());
}
Пример #29
0
reg_t kArrayFree(EngineState *s, int argc, reg_t *argv) {
	if (getSciVersion() == SCI_VERSION_2_1_LATE && !s->_segMan->isValidAddr(argv[0], SEG_TYPE_ARRAY)) {
		return s->r_acc;
	}

	s->_segMan->freeArray(argv[0]);
	return s->r_acc;
}
Пример #30
0
void Script::load(ResourceManager *resMan) {
	Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0);
	assert(script != 0);

	_buf = (byte *)malloc(_bufSize);
	assert(_buf);

	assert(_bufSize >= script->size);
	memcpy(_buf, script->data, script->size);

	// Check scripts for matching signatures and patch those, if found
	matchSignatureAndPatch(_nr, _buf, script->size);

	if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
		Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0);
		assert(heap != 0);

		_heapStart = _buf + _scriptSize;

		assert(_bufSize - _scriptSize <= heap->size);
		memcpy(_heapStart, heap->data, heap->size);
	}

	_exportTable = 0;
	_numExports = 0;
	_synonyms = 0;
	_numSynonyms = 0;
	
	if (getSciVersion() <= SCI_VERSION_1_LATE) {
		_exportTable = (const uint16 *)findBlockSCI0(SCI_OBJ_EXPORTS);
		if (_exportTable) {
			_numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1);
			_exportTable += 3;	// skip header plus 2 bytes (_exportTable is a uint16 pointer)
		}
		_synonyms = findBlockSCI0(SCI_OBJ_SYNONYMS);
		if (_synonyms) {
			_numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4;
			_synonyms += 4;	// skip header
		}
		const byte* localsBlock = findBlockSCI0(SCI_OBJ_LOCALVARS);
		if (localsBlock) {
			_localsOffset = localsBlock - _buf + 4;
			_localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1;	// half block size
		}
	} else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {