예제 #1
0
void GuestAdditions::syncLSL6HiresUI(const int16 musicVolume) const {
	const reg_t musicDialId = _segMan->findObjectByName("volumeDial");
	if (!musicDialId.isNull()) {
		writeSelectorValue(_segMan, musicDialId, SELECTOR(curPos), musicVolume);
		writeSelectorValue(_segMan, musicDialId, SELECTOR(cel), musicVolume);
		reg_t params[] = { make_reg(0, musicVolume) };
		invokeSelector(musicDialId, SELECTOR(update), 1, params);
		if (_segMan->getObject(musicDialId)->isInserted()) {
			g_sci->_gfxFrameout->kernelUpdateScreenItem(musicDialId);
		}
	}
}
예제 #2
0
void SciEngine::setLauncherLanguage() {
	if (_gameDescription->flags & ADGF_ADDENGLISH) {
		// If game is multilingual
		if (Common::parseLanguage(ConfMan.get("language")) == Common::EN_ANY) {
			// and English was selected as language
			if (SELECTOR(printLang) != -1) // set text language to English
				writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(printLang), K_LANG_ENGLISH);
			if (SELECTOR(parseLang) != -1) // and set parser language to English as well
				writeSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(parseLang), K_LANG_ENGLISH);
		}
	}
}
예제 #3
0
void SoundCommandParser::processPlaySound(reg_t obj) {
	MusicEntry *musicSlot = _music->getSlot(obj);
	if (!musicSlot) {
		warning("kDoSound(play): Slot not found (%04x:%04x), initializing it manually", PRINT_REG(obj));
		// The sound hasn't been initialized for some reason, so initialize it
		// here. Happens in KQ6, room 460, when giving the creature (child) to
		// the bookworm. Fixes bugs #3413301 and #3421098.
		processInitSound(obj);
		musicSlot = _music->getSlot(obj);
		if (!musicSlot)
			error("Failed to initialize uninitialized sound slot");
	}

	int resourceId = getSoundResourceId(obj);

	if (musicSlot->resourceId != resourceId) { // another sound loaded into struct
		processDisposeSound(obj);
		processInitSound(obj);
		// Find slot again :)
		musicSlot = _music->getSlot(obj);
	}

	writeSelector(_segMan, obj, SELECTOR(handle), obj);

	if (_soundVersion >= SCI_VERSION_1_EARLY) {
		writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
		writeSelectorValue(_segMan, obj, SELECTOR(min), 0);
		writeSelectorValue(_segMan, obj, SELECTOR(sec), 0);
		writeSelectorValue(_segMan, obj, SELECTOR(frame), 0);
		writeSelectorValue(_segMan, obj, SELECTOR(signal), 0);
	} else {
		writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundPlaying);
	}

	musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
	musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority));
	// Reset hold when starting a new song. kDoSoundSetHold is always called after
	// kDoSoundPlay to set it properly, if needed. Fixes bug #3413589.
	musicSlot->hold = -1;
	if (_soundVersion >= SCI_VERSION_1_EARLY)
		musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol));

	debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x number %d, loop %d, prio %d, vol %d", PRINT_REG(obj),
			resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume);

	_music->soundPlay(musicSlot);

	// Reset any left-over signals
	musicSlot->signal = 0;
	musicSlot->fadeStep = 0;
}
예제 #4
0
void GuestAdditions::syncQFG4UI(const int16 musicVolume) const {
	const reg_t sliderId = _segMan->findObjectByName("volumeSlider");
	if (!sliderId.isNull()) {
		const int16 yPosition = 84 - musicVolume * 34 / 10;
		writeSelectorValue(_segMan, sliderId, SELECTOR(y), yPosition);

		// There does not seem to be any good way to learn whether the
		// volume slider is visible (and thus eligible for
		// kUpdateScreenItem)
		const reg_t planeId = readSelector(_segMan, sliderId, SELECTOR(plane));
		if (g_sci->_gfxFrameout->getPlanes().findByObject(planeId) != nullptr) {
			g_sci->_gfxFrameout->kernelUpdateScreenItem(sliderId);
		}
	}
}
예제 #5
0
void GfxAnimate::fill(byte &old_picNotValid) {
	GfxView *view = NULL;
	AnimateList::iterator it;
	const AnimateList::iterator end = _list.end();

	for (it = _list.begin(); it != end; ++it) {
		// Get the corresponding view
		view = _cache->getView(it->viewId);

		adjustInvalidCels(view, it);
		processViewScaling(view, it);
		setNsRect(view, it);

		//warning("%s view %d, loop %d, cel %d, signal %x", _s->_segMan->getObjectName(curObject), it->viewId, it->loopNo, it->celNo, it->signal);

		// Calculate current priority according to y-coordinate
		if (!(it->signal & kSignalFixedPriority)) {
			it->priority = _ports->kernelCoordinateToPriority(it->y);
			writeSelectorValue(_s->_segMan, it->object, SELECTOR(priority), it->priority);
		}

		if (it->signal & kSignalNoUpdate) {
			if ((it->signal & (kSignalForceUpdate | kSignalViewUpdated))
				||   (it->signal & kSignalHidden  && !(it->signal & kSignalRemoveView))
				|| (!(it->signal & kSignalHidden) &&   it->signal & kSignalRemoveView)
				||   (it->signal & kSignalAlwaysUpdate))
				old_picNotValid++;
			it->signal &= ~kSignalStopUpdate;
		} else {
			if ((it->signal & kSignalStopUpdate) || (it->signal & kSignalAlwaysUpdate))
				old_picNotValid++;
			it->signal &= ~kSignalForceUpdate;
		}
	}
}
예제 #6
0
reg_t SoundCommandParser::kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc) {
	reg_t obj = argv[0];
	int16 value = argv[1].toSint16();

	MusicEntry *musicSlot = _music->getSlot(obj);
	if (!musicSlot) {
		// Do not throw a warning if the sound can't be found, as in some games
		// this is called before the actual sound is loaded (e.g. SQ4CD, with
		// the drum sounds of the energizer bunny at the beginning), so this is
		// normal behavior.
		//warning("cmdSetSoundVolume: Slot not found (%04x:%04x)", PRINT_REG(obj));
		return acc;
	}

	debugC(kDebugLevelSound, "kDoSound(setVolume): %d", value);

	value = CLIP<int>(value, 0, MUSIC_VOLUME_MAX);

	if (musicSlot->volume != value) {
		musicSlot->volume = value;
		_music->soundSetVolume(musicSlot, value);
		writeSelectorValue(_segMan, obj, SELECTOR(vol), value);
	}
	return acc;
}
예제 #7
0
reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) {
	reg_t obj = argv[0];
	int16 value = argv[1].toSint16();

	debugC(kDebugLevelSound, "kDoSound(setLoop): %04x:%04x, %d", PRINT_REG(obj), value);

	MusicEntry *musicSlot = _music->getSlot(obj);
	if (!musicSlot) {
		// Apparently, it's perfectly normal for a game to call cmdSetSoundLoop
		// before actually initializing the sound and adding it to the playlist
		// with cmdInitSound. Usually, it doesn't matter if the game doesn't
		// request to loop the sound, so in this case, don't throw any warning,
		// otherwise do, because the sound won't be looped.
		if (value == -1) {
			warning("kDoSound(setLoop): Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj));
		} else {
			// Doesn't really matter
		}
		return acc;
	}
	if (value == -1) {
		musicSlot->loop = 0xFFFF;
	} else {
		musicSlot->loop = 1; // actually plays the music once
	}

	writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop);
	return acc;
}
예제 #8
0
void SoundCommandParser::processDisposeSound(reg_t obj) {
	MusicEntry *musicSlot = _music->getSlot(obj);
	if (!musicSlot) {
		warning("kDoSound(dispose): Slot not found (%04x:%04x)", PRINT_REG(obj));
		return;
	}

	processStopSound(obj, false);

	_music->soundKill(musicSlot);
	writeSelectorValue(_segMan, obj, SELECTOR(handle), 0);
	if (_soundVersion >= SCI_VERSION_1_EARLY)
		writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
	else
		writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped);
}
예제 #9
0
파일: klists.cpp 프로젝트: OmerMor/scummvm
reg_t kArrayGetData(EngineState *s, int argc, reg_t *argv) {
	if (s->_segMan->isObject(argv[0])) {
		return readSelector(s->_segMan, argv[0], SELECTOR(data));
	}

	return argv[0];
}
예제 #10
0
bool GameFeatures::autoDetectSci21StringFunctionType() {
	// Look up the script address
	reg_t addr = getDetectionAddr("Str", SELECTOR(size));

	if (!addr.segment)
		return false;

	uint16 offset = addr.offset;
	Script *script = _segMan->getScript(addr.segment);

	while (true) {
		int16 opparams[4];
		byte extOpcode;
		byte opcode;
		offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
		opcode = extOpcode >> 1;

		// Check for end of script
		if (opcode == op_ret || offset >= script->getBufSize())
			break;

		if (opcode == op_callk) {
			uint16 kFuncNum = opparams[0];

			// SCI2.1 games which use the new kString functions call kString(8).
			// Earlier ones call the callKernel script function, but not kString
			// directly
			if (_kernel->getKernelName(kFuncNum) == "String")
				return true;
		}
	}

	return false;	// not found a call to kString
}
예제 #11
0
파일: features.cpp 프로젝트: 86400/scummvm
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;
}
예제 #12
0
파일: kparse.cpp 프로젝트: Cruel/scummvm
reg_t kSaid(EngineState *s, int argc, reg_t *argv) {
	reg_t heap_said_block = argv[0];
	byte *said_block;
	int new_lastmatch;
	Vocabulary *voc = g_sci->getVocabulary();
#ifdef DEBUG_PARSER
	const int debug_parser = 1;
#else
	const int debug_parser = 0;
#endif

	if (!heap_said_block.getSegment())
		return NULL_REG;

	said_block = (byte *)s->_segMan->derefBulkPtr(heap_said_block, 0);

	if (!said_block) {
		warning("Said on non-string, pointer %04x:%04x", PRINT_REG(heap_said_block));
		return NULL_REG;
	}

#ifdef DEBUG_PARSER
		debugN("Said block: ");
		g_sci->getVocabulary()->debugDecipherSaidBlock(said_block);
#endif

	if (voc->parser_event.isNull() || (readSelectorValue(s->_segMan, voc->parser_event, SELECTOR(claimed)))) {
		return NULL_REG;
	}

	new_lastmatch = said(said_block, debug_parser);
	if (new_lastmatch  != SAID_NO_MATCH) { /* Build and possibly display a parse tree */

#ifdef DEBUG_PARSER
		debugN("kSaid: Match.\n");
#endif

		s->r_acc = make_reg(0, 1);

		if (new_lastmatch != SAID_PARTIAL_MATCH)
			writeSelectorValue(s->_segMan, voc->parser_event, SELECTOR(claimed), 1);

	} else {
		return NULL_REG;
	}
	return s->r_acc;
}
예제 #13
0
void SciEngine::runGame() {
	setTotalPlayTime(0);

	initStackBaseWithSelector(SELECTOR(play)); // Call the play selector

	// Attach the debug console on game startup, if requested
	if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup))
		_console->attach();

	_gamestate->_syncedAudioOptions = false;

	do {
		_gamestate->_executionStackPosChanged = false;
		run_vm(_gamestate);
		exitGame();

		_gamestate->_syncedAudioOptions = true;

		if (_gamestate->abortScriptProcessing == kAbortRestartGame) {
			_gamestate->_segMan->resetSegMan();
			initGame();
			initStackBaseWithSelector(SELECTOR(play));
			patchGameSaveRestore();
			setLauncherLanguage();
			_gamestate->gameIsRestarting = GAMEISRESTARTING_RESTART;
			_gamestate->_throttleLastTime = 0;
			if (_gfxMenu)
				_gfxMenu->reset();
			_gamestate->abortScriptProcessing = kAbortNone;
			_gamestate->_syncedAudioOptions = false;
		} else if (_gamestate->abortScriptProcessing == kAbortLoadGame) {
			_gamestate->abortScriptProcessing = kAbortNone;
			_gamestate->_executionStack.clear();
			initStackBaseWithSelector(SELECTOR(replay));
			patchGameSaveRestore();
			setLauncherLanguage();
			_gamestate->shrinkStackToBase();
			_gamestate->abortScriptProcessing = kAbortNone;

			syncSoundSettings();
			syncIngameAudioOptions();
			// Games do not set their audio settings when loading
		} else {
			break;	// exit loop
		}
	} while (true);
}
예제 #14
0
파일: compare.cpp 프로젝트: Fyre91/scummvm
Common::Rect GfxCompare::getNSRect(reg_t object, bool fixRect) {
	Common::Rect nsRect;
	nsRect.top = readSelectorValue(_segMan, object, SELECTOR(nsTop));
	nsRect.left = readSelectorValue(_segMan, object, SELECTOR(nsLeft));
	nsRect.bottom = readSelectorValue(_segMan, object, SELECTOR(nsBottom));
	nsRect.right = readSelectorValue(_segMan, object, SELECTOR(nsRight));

	if (fixRect) {
		// nsRect top/left may be negative, adjust accordingly
		if (nsRect.top < 0)
			nsRect.top = 0;
		if (nsRect.left < 0)
			nsRect.left = 0;
	}

	return nsRect;
}
예제 #15
0
reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv) {
	reg_t obj = argv[0];
	reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32
	SegManager *segMan = s->_segMan;

	if (obj.getSegment()) {
		int16 x = readSelectorValue(segMan, obj, SELECTOR(x));
		int16 y = readSelectorValue(segMan, obj, SELECTOR(y));

		g_sci->_gfxCoordAdjuster->kernelLocalToGlobal(x, y, planeObject);

		writeSelectorValue(segMan, obj, SELECTOR(x), x);
		writeSelectorValue(segMan, obj, SELECTOR(y), y);
	}

	return s->r_acc;
}
예제 #16
0
reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) {
	if (argc == 1)
		debugC(kDebugLevelSound, "kDoSound(pause): %04x:%04x", PRINT_REG(argv[0]));
	else
		debugC(kDebugLevelSound, "kDoSound(pause): %04x:%04x, %04x:%04x", PRINT_REG(argv[0]), PRINT_REG(argv[1]));

	if (_soundVersion <= SCI_VERSION_0_LATE) {
		// SCI0 games give us 0/1 for either resuming or pausing the current music
		//  this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume
		uint16 value = argv[0].toUint16();
		MusicEntry *musicSlot = _music->getActiveSci0MusicSlot();
		switch (value) {
		case 1:
			if ((musicSlot) && (musicSlot->status == kSoundPlaying)) {
				_music->soundPause(musicSlot);
				writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused);
			}
			return make_reg(0, 0);
		case 0:
			if ((musicSlot) && (musicSlot->status == kSoundPaused)) {
				_music->soundResume(musicSlot);
				writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying);
				return make_reg(0, 1);
			}
			return make_reg(0, 0);
		default:
			error("kDoSound(pause): parameter 0 is invalid for sound-sci0");
		}
	}

	reg_t obj = argv[0];
	uint16 value = argc > 1 ? argv[1].toUint16() : 0;
	if (!obj.segment) {		// pause the whole playlist
		_music->pauseAll(value);
	} else {	// pause a playlist slot
		MusicEntry *musicSlot = _music->getSlot(obj);
		if (!musicSlot) {
			// This happens quite frequently
			debugC(kDebugLevelSound, "kDoSound(pause): Slot not found (%04x:%04x)", PRINT_REG(obj));
			return acc;
		}

		_music->soundToggle(musicSlot, value);
	}
	return acc;
}
예제 #17
0
void GuestAdditions::syncGK2VolumeFromScummVM(const int16 musicVolume) const {
	_state->variables[VAR_GLOBAL][kGlobalVarGK2MusicVolume] = make_reg(0, musicVolume);

	// Calling `setVol` on all sounds is necessary to propagate the volume
	// change to existing sounds, and matches how game scripts propagate
	// volume changes when the in-game music slider is moved
	const reg_t soundsId = _state->variables[VAR_GLOBAL][kGlobalVarSounds];
	if (!soundsId.isNull()) {
		List *sounds = _segMan->lookupList(readSelector(_segMan, soundsId, SELECTOR(elements)));
		reg_t soundId = sounds->first;
		while (!soundId.isNull()) {
			Node *sound = _segMan->lookupNode(soundId);
			reg_t params[] = { make_reg(0, musicVolume) };
			invokeSelector(sound->value, SELECTOR(setVol), 1, params);
			soundId = sound->succ;
		}
	}
}
예제 #18
0
파일: animate.cpp 프로젝트: Cruel/scummvm
bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
	reg_t curAddress = list->first;
	Node *curNode = _s->_segMan->lookupNode(curAddress);
	reg_t curObject;
	uint16 signal;

	while (curNode) {
		curObject = curNode->value;

		if (_fastCastEnabled) {
			// Check if the game has a fastCast object set
			//  if we don't abort kAnimate processing, at least in kq5 there will be animation cels drawn into speech boxes.
			if (!_s->variables[VAR_GLOBAL][84].isNull()) {
				// This normally points to an object called "fastCast",
				// but for example in Eco Quest 1 it may also point to an object called "EventHandler" (see bug #5170)
				// Original SCI only checked, if this global was not 0.
				return false;
			}
		}

		signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
		if (!(signal & kSignalFrozen)) {
			// Call .doit method of that object
			invokeSelector(_s, curObject, SELECTOR(doit), argc, argv, 0);

			// If a game is being loaded, stop processing
			if (_s->abortScriptProcessing != kAbortNone)
				return true; // Stop processing

			// Lookup node again, since the nodetable it was in may have been reallocated.
			// The node might have been deallocated at this point (e.g. LSL2, room 42),
			// in which case the node reference will be null and the loop will stop below.
			// If the node is deleted from kDeleteKey, it won't have a successor node, thus
			// list processing will stop here (which is what SSCI does).
			curNode = _s->_segMan->lookupNode(curAddress, false);
		}

		if (curNode) {
			curAddress = curNode->succ;
			curNode = _s->_segMan->lookupNode(curAddress);
		}
	}
	return true;
}
예제 #19
0
reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
	int16 subop = argv[0].toUint16();

	switch (subop) {
	case 0: { // init
		int id = argv[1].toUint16();
		reg_t obj = argv[2];
		int16 flag = argv[3].toSint16();
		int16 x = argv[4].toUint16();
		int16 y = argv[5].toUint16();
		warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y);
		g_sci->_robotDecoder->load(id);
		g_sci->_robotDecoder->start();
		g_sci->_robotDecoder->setPos(x, y);
		}
		break;
	case 1:	// LSL6 hires (startup)
		// TODO
		return NULL_REG;	// an integer is expected
	case 4: {	// start - we don't really have a use for this one
			//int id = argv[1].toUint16();
			//warning("kRobot(start), id %d", id);
		}
		break;
	case 7:	// unknown, called e.g. by Phantasmagoria
		warning("kRobot(%d)", subop);
		break;
	case 8: // sync
		//if (true) {	// debug: automatically skip all robot videos
		if (g_sci->_robotDecoder->endOfVideo()) {
			g_sci->_robotDecoder->close();
			// Signal the engine scripts that the video is done
			writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG);
		} else {
			writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG);
		}
		break;
	default:
		warning("kRobot(%d)", subop);
		break;
	}

	return s->r_acc;
}
예제 #20
0
void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject) {
	reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap));
	uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back));
	// Sanity check: Check if the hunk is set. If not, either the game scripts
	// didn't set it, or an old saved game has been loaded, where it wasn't set.
	if (hunkId.isNull())
		return;

	// Negative coordinates indicate that text shouldn't be displayed
	if (x < 0 || y < 0)
		return;

	byte *memoryPtr = _segMan->getHunkPointer(hunkId);

	if (!memoryPtr) {
		// Happens when restoring in some SCI32 games
		warning("Attempt to draw an invalid text bitmap");
		return;
	}

	byte *surface = memoryPtr + BITMAP_HEADER_SIZE;

	int curByte = 0;
	uint16 skipColor = readSelectorValue(_segMan, textObject, SELECTOR(skip));
	uint16 textX = planeRect.left + x;
	uint16 textY = planeRect.top + y;
	// Get totalWidth, totalHeight
	uint16 width = READ_LE_UINT16(memoryPtr);
	uint16 height = READ_LE_UINT16(memoryPtr + 2);

	// Upscale the coordinates/width if the fonts are already upscaled
	if (_screen->fontIsUpscaled()) {
		textX = textX * _screen->getDisplayWidth() / _screen->getWidth();
		textY = textY * _screen->getDisplayHeight() / _screen->getHeight();
	}

	for (int curY = 0; curY < height; curY++) {
		for (int curX = 0; curX < width; curX++) {
			byte pixel = surface[curByte++];
			if (pixel != skipColor && pixel != backColor)
				_screen->putFontPixel(textY, curX + textX, curY, pixel);
		}
	}
}
예제 #21
0
void GfxFrameout::kernelAddPlane(reg_t object) {
	PlaneEntry newPlane;

	if (_planes.empty()) {
		// There has to be another way for sierra sci to do this or maybe script resolution is compiled into
		//  interpreter (TODO)
		uint16 scriptWidth = readSelectorValue(_segMan, object, SELECTOR(resX));
		uint16 scriptHeight = readSelectorValue(_segMan, object, SELECTOR(resY));

		// Phantasmagoria 2 doesn't specify a script width/height
		if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {
			scriptWidth = 640;
			scriptHeight = 480;
		}

		assert(scriptWidth > 0 && scriptHeight > 0);
		_coordAdjuster->setScriptsResolution(scriptWidth, scriptHeight);
	}

	// Import of QfG character files dialog is shown in QFG4.
	// Display additional popup information before letting user use it.
	// For the SCI0-SCI1.1 version of this, check kDrawControl().
	if (g_sci->inQfGImportRoom() && !strcmp(_segMan->getObjectName(object), "DSPlane")) {
		showScummVMDialog("Characters saved inside ScummVM are shown "
				"automatically. Character files saved in the original "
				"interpreter need to be put inside ScummVM's saved games "
				"directory and a prefix needs to be added depending on which "
				"game it was saved in: 'qfg1-' for Quest for Glory 1, 'qfg2-' "
				"for Quest for Glory 2, 'qfg3-' for Quest for Glory 3. "
				"Example: 'qfg2-thief.sav'.");
	}

	newPlane.object = object;
	newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority));
	newPlane.lastPriority = -1; // hidden
	newPlane.planeOffsetX = 0;
	newPlane.planeOffsetY = 0;
	newPlane.pictureId = kPlanePlainColored;
	newPlane.planePictureMirrored = false;
	newPlane.planeBack = 0;
	_planes.push_back(newPlane);

	kernelUpdatePlane(object);
}
예제 #22
0
void GuestAdditions::syncPQ4UI(const int16 musicVolume) const {
	const SegmentId segment = _segMan->getScriptSegment(9, SCRIPT_GET_DONT_LOAD);
	if (segment != 0 && _segMan->getScript(segment)->getLocalsCount() > 2) {
		const reg_t barId = _segMan->getScript(segment)->getLocalsBegin()[2];
		if (!barId.isNull()) {
			reg_t params[] = { make_reg(0, musicVolume) };
			invokeSelector(barId, SELECTOR(setSize), 1, params);
		}
	}
}
예제 #23
0
void GuestAdditions::syncShivers1UI(const int16 dacVolume) const {
	const reg_t sliderId = _segMan->findObjectByName("spVolume");
	if (!sliderId.isNull()) {
		const int16 xPosition = dacVolume * 78 / Audio32::kMaxVolume + 32;
		writeSelectorValue(_segMan, sliderId, SELECTOR(x), xPosition);
		if (_segMan->getObject(sliderId)->isInserted()) {
			g_sci->_gfxFrameout->kernelUpdateScreenItem(sliderId);
		}
	}
}
예제 #24
0
void GuestAdditions::syncSQ6UI() const {
	const reg_t bars[] = { _segMan->findObjectByName("musicBar"),
						   _segMan->findObjectByName("soundBar") };
	for (int i = 0; i < ARRAYSIZE(bars); ++i) {
		const reg_t barId = bars[i];
		if (!barId.isNull()) {
			invokeSelector(barId, SELECTOR(show));
		}
	}
}
예제 #25
0
void GuestAdditions::syncMessageTypeToScummVMUsingLSL6HiresStrategy(const reg_t sendObj, Selector &selector, reg_t *argp) {
	if (_state->variables[VAR_GLOBAL][kGlobalVarLSL6HiresGameFlags] == sendObj &&
		(selector == SELECTOR(clear) || selector == SELECTOR(set))) {

		if (argp[1].toUint16() == kLSL6HiresSubtitleFlag) {
			if (_messageTypeSynced) {
				ConfMan.setBool("subtitles", selector == SELECTOR(clear));
			} else if (ConfMan.getBool("subtitles")) {
				selector = SELECTOR(clear);
				argp[-1].setOffset(selector);
				_messageTypeSynced = true;
			} else {
				selector = SELECTOR(set);
				argp[-1].setOffset(selector);
				_messageTypeSynced = true;
			}
		}
	}
}
예제 #26
0
reg_t SoundCommandParser::kDoSoundUpdate(EngineState *s, int argc, reg_t *argv) {
	reg_t obj = argv[0];

	debugC(kDebugLevelSound, "kDoSound(update): %04x:%04x", PRINT_REG(argv[0]));

	MusicEntry *musicSlot = _music->getSlot(obj);
	if (!musicSlot) {
		warning("kDoSound(update): Slot not found (%04x:%04x)", PRINT_REG(obj));
		return s->r_acc;
	}

	musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
	int16 objVol = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, 255);
	if (objVol != musicSlot->volume)
		_music->soundSetVolume(musicSlot, objVol);
	int16 objPrio = readSelectorValue(_segMan, obj, SELECTOR(priority));
	if (objPrio != musicSlot->priority)
		_music->soundSetPriority(musicSlot, objPrio);
	return s->r_acc;
}
예제 #27
0
void SoundCommandParser::startNewSound(int number) {
	Common::StackLock lock(_music->_mutex);

	// Overwrite the first sound in the playlist
	MusicEntry *song = *_music->getPlayListStart();
	reg_t soundObj = song->soundObj;
	processDisposeSound(soundObj);
	writeSelectorValue(_segMan, soundObj, SELECTOR(number), number);
	processInitSound(soundObj);
	processPlaySound(soundObj);
}
예제 #28
0
bool GameFeatures::autoDetectSci21KernelType() {
	// First, check if the Sound object is loaded
	reg_t soundObjAddr = _segMan->findObjectByName("Sound");
	if (soundObjAddr.isNull()) {
		// Usually, this means that the Sound object isn't loaded yet.
		// This case doesn't occur in early SCI2.1 games, and we've only
		// seen it happen in the RAMA demo, thus we can assume that the
		// game is using a SCI2.1 table
		warning("autoDetectSci21KernelType(): Sound object not loaded, assuming a SCI2.1 table");
		_sci21KernelType = SCI_VERSION_2_1;
		return true;
	}

	// Look up the script address
	reg_t addr = getDetectionAddr("Sound", SELECTOR(play));

	if (!addr.segment)
		return false;

	uint16 offset = addr.offset;
	Script *script = _segMan->getScript(addr.segment);

	while (true) {
		int16 opparams[4];
		byte extOpcode;
		byte opcode;
		offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams);
		opcode = extOpcode >> 1;

		// Check for end of script
		if (opcode == op_ret || offset >= script->getBufSize())
			break;

		if (opcode == op_callk) {
			uint16 kFuncNum = opparams[0];

			// Here we check for the kDoSound opcode that's used in SCI2.1.
			// Finding 0x40 as kDoSound in the Sound::play() function means the
			// game is using the modified SCI2 kernel table found in some older
			// SCI2.1 games (GK2 demo, KQ7 v1.4).
			// Finding 0x75 as kDoSound means the game is using the regular
			// SCI2.1 kernel table.
			if (kFuncNum == 0x40) {
				_sci21KernelType = SCI_VERSION_2;
				return true;
			} else if (kFuncNum == 0x75) {
				_sci21KernelType = SCI_VERSION_2_1;
				return true;
			}
		}
	}

	return false;	// not found
}
예제 #29
0
reg_t kScrollWindowCreate(EngineState *s, int argc, reg_t *argv) {
	const reg_t object = argv[0];
	const uint16 maxNumEntries = argv[1].toUint16();

	SegManager *segMan = s->_segMan;
	const int16 borderColor = readSelectorValue(segMan, object, SELECTOR(borderColor));
	const TextAlign alignment = (TextAlign)readSelectorValue(segMan, object, SELECTOR(mode));
	const GuiResourceId fontId = (GuiResourceId)readSelectorValue(segMan, object, SELECTOR(font));
	const int16 backColor = readSelectorValue(segMan, object, SELECTOR(back));
	const int16 foreColor = readSelectorValue(segMan, object, SELECTOR(fore));
	const reg_t plane = readSelector(segMan, object, SELECTOR(plane));

	Common::Rect rect;
	rect.left = readSelectorValue(segMan, object, SELECTOR(nsLeft));
	rect.top = readSelectorValue(segMan, object, SELECTOR(nsTop));
	rect.right = readSelectorValue(segMan, object, SELECTOR(nsRight)) + 1;
	rect.bottom = readSelectorValue(segMan, object, SELECTOR(nsBottom)) + 1;
	const Common::Point position(rect.left, rect.top);

	return g_sci->_gfxControls32->makeScrollWindow(rect, position, plane, foreColor, backColor, fontId, alignment, borderColor, maxNumEntries);
}
예제 #30
0
void GuestAdditions::syncGK1UI() const {
	const reg_t bars[] = { _segMan->findObjectByName("musicBar"),
						   _segMan->findObjectByName("soundBar") };

	for (int i = 0; i < ARRAYSIZE(bars); ++i) {
		const reg_t barId = bars[i];
		if (!barId.isNull()) {
			// Resetting the position to 0 causes the bar to refresh its
			// position when it next draws
			writeSelectorValue(_segMan, barId, SELECTOR(position), 0);

			// The `signal` property indicates bar visibility (for some
			// reason, the normal `-info-` flag is not used)
			if (readSelectorValue(_segMan, barId, SELECTOR(signal)) & 0x20) {
				// `show` pulls a new value from the underlying sound object
				// and refreshes the bar rendering
				invokeSelector(barId, SELECTOR(show));
			}
		}
	}
}