Example #1
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 tmpRunningWidth = readSelectorValue(_segMan, object, SELECTOR(resX));
		uint16 tmpRunningHeight = readSelectorValue(_segMan, object, SELECTOR(resY));

		// The above can be 0 in SCI3 (e.g. Phantasmagoria 2)
		if (tmpRunningWidth > 0 && tmpRunningHeight > 0) {
			scriptsRunningWidth = tmpRunningWidth;
			scriptsRunningHeight = tmpRunningHeight;
		}

		_coordAdjuster->setScriptsResolution(scriptsRunningWidth, scriptsRunningHeight);
	}

	newPlane.object = object;
	newPlane.pictureId = 0xFFFF;
	newPlane.priority = readSelectorValue(_segMan, object, SELECTOR(priority));
	newPlane.lastPriority = 0xFFFF; // hidden
	newPlane.planeOffsetX = 0;
	_planes.push_back(newPlane);

	kernelUpdatePlane(object);
}
Example #2
0
reg_t GfxCompare::canBeHereCheckRectList(const reg_t checkObject, const Common::Rect &checkRect, const List *list, const uint16 signalFlags) const {
	reg_t curAddress = list->first;
	Node *curNode = _segMan->lookupNode(curAddress);
	reg_t curObject;
	uint16 signal;
	Common::Rect curRect;

	while (curNode) {
		curObject = curNode->value;
		if (curObject != checkObject) {
			signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
			if (!(signal & signalFlags)) {
				curRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
				curRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
				curRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
				curRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
				// Check if curRect is within checkRect
				// This behavior is slightly odd, but it's how the original SCI
				// engine did it: a rect cannot be contained within itself
				// (there is no equality). Do NOT change this to contains(), as
				// it breaks KQ4 early (bug #3315639).
				if (curRect.right > checkRect.left &&
					curRect.left < checkRect.right &&
					curRect.bottom > checkRect.top &&
					curRect.top < checkRect.bottom)
					return curObject;
			}
		}
		curAddress = curNode->succ;
		curNode = _segMan->lookupNode(curAddress);
	}
	return NULL_REG;
}
Example #3
0
reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) {
	reg_t obj = argv[0];
	int16 value = argv[1].toSint16();

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

	MusicEntry *musicSlot = _music->getSlot(obj);
	if (!musicSlot) {
		debugC(kDebugLevelSound, "kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj));
		return acc;
	}

	if (value == -1) {
		uint16 resourceId = musicSlot->resourceId;

		// Set priority from the song data
		Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceId), 0);
		if (song->data[0] == 0xf0)
			_music->soundSetPriority(musicSlot, song->data[1]);
		else
			warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value");

		//pSnd->prio=0;field_15B=0
		writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD);
	} else {
		// Scripted priority

		//pSnd->field_15B=1;
		writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2);
		//DoSOund(0xF,hobj,w)
	}
	return acc;
}
Example #4
0
void SoundCommandParser::processInitSound(reg_t obj) {
	int resourceId = getSoundResourceId(obj);

	// Check if a track with the same sound object is already playing
	MusicEntry *oldSound = _music->getSlot(obj);
	if (oldSound)
		processDisposeSound(obj);

	MusicEntry *newSound = new MusicEntry();
	newSound->resourceId = resourceId;
	newSound->soundObj = obj;
	newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
	newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(pri)) & 0xFF;
	if (_soundVersion >= SCI_VERSION_1_EARLY)
		newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX);
	newSound->reverb = -1;	// initialize to SCI invalid, it'll be set correctly in soundInitSnd() below

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

	initSoundResource(newSound);

	_music->pushBackSlot(newSound);

	if (newSound->soundRes || newSound->pStreamAud) {
		// Notify the engine
		if (_soundVersion <= SCI_VERSION_0_LATE)
			writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized);
		else
			writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
	}
}
Example #5
0
// Adapted from GfxAnimate::applyGlobalScaling()
void GfxFrameout::applyGlobalScaling(FrameoutEntry *itemEntry, Common::Rect planeRect, int16 celHeight) {
	// Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
	int16 maxScale = readSelectorValue(_segMan, itemEntry->object, SELECTOR(maxScale));
	int16 maxCelHeight = (maxScale * celHeight) >> 7;
	reg_t globalVar2 = g_sci->getEngineState()->variables[VAR_GLOBAL][2]; // current room object
	int16 vanishingY = readSelectorValue(_segMan, globalVar2, SELECTOR(vanishingY));

	int16 fixedPortY = planeRect.bottom - vanishingY;
	int16 fixedEntryY = itemEntry->y - vanishingY;
	if (!fixedEntryY)
		fixedEntryY = 1;

	if ((celHeight == 0) || (fixedPortY == 0))
		error("global scaling panic");

	itemEntry->scaleY = (maxCelHeight * fixedEntryY) / fixedPortY;
	itemEntry->scaleY = (itemEntry->scaleY * maxScale) / celHeight;

	// Make sure that the calculated value is sane
	if (itemEntry->scaleY < 1 /*|| itemEntry->scaleY > 128*/)
		itemEntry->scaleY = 128;

	itemEntry->scaleX = itemEntry->scaleY;

	// and set objects scale selectors
	//writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleX), itemEntry->scaleX);
	//writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleY), itemEntry->scaleY);
}
Example #6
0
void GfxAnimate::applyGlobalScaling(AnimateList::iterator entry, GfxView *view) {
	// Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
	int16 maxScale = readSelectorValue(_s->_segMan, entry->object, SELECTOR(maxScale));
	int16 celHeight = view->getHeight(entry->loopNo, entry->celNo);
	int16 maxCelHeight = (maxScale * celHeight) >> 7;
	reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object
	int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY));

	int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY;
	int16 fixedEntryY = entry->y - vanishingY;
	if (!fixedEntryY)
		fixedEntryY = 1;

	if ((celHeight == 0) || (fixedPortY == 0))
		error("global scaling panic");

	entry->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY;
	entry->scaleY = (entry->scaleY * 128) / celHeight;

	entry->scaleX = entry->scaleY;

	// and set objects scale selectors
	writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleX), entry->scaleX);
	writeSelectorValue(_s->_segMan, entry->object, SELECTOR(scaleY), entry->scaleY);
}
Example #7
0
reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) {
	reg_t obj = argv[0];
	SegManager *segMan = s->_segMan;

	if (readSelectorValue(segMan, obj, SELECTOR(type)) == SCI_EVENT_KEYBOARD) { // Keyboard
		uint16 message = readSelectorValue(segMan, obj, SELECTOR(message));
		uint16 eventType = SCI_EVENT_DIRECTION;
		// Check if the game is using cursor views. These games allowed control
		// of the mouse cursor via the keyboard controls (the so called
		// "PseudoMouse" functionality in script 933).
		if (g_sci->_features->detectSetCursorType() == SCI_VERSION_1_1)
			eventType |= SCI_EVENT_KEYBOARD;

		for (int i = 0; i < 9; i++) {
			if (keyToDirMap[i].key == message) {
				writeSelectorValue(segMan, obj, SELECTOR(type), eventType);
				writeSelectorValue(segMan, obj, SELECTOR(message), keyToDirMap[i].direction);
				return TRUE_REG;	// direction mapped
			}
		}

		return NULL_REG;	// unknown direction
	}

	return s->r_acc;	// no keyboard event to map, leave accumulator unchanged
}
Example #8
0
reg_t GfxCompare::kernelCantBeHere32(const reg_t curObject, const reg_t listReference) const {
	// Most of SCI32 graphics code converts rects from the VM to exclusive
	// rects before operating on them, but this call leverages SCI16 engine
	// code that operates on inclusive rects, so the rect's bottom-right
	// point is not modified like in other SCI32 kernel calls
	Common::Rect checkRect;

	// At least LSL6 hires passes invalid rectangles which trigger the
	// isValidRect assertion in the Rect constructor; this is avoided by
	// assigning the properties after construction and then testing the
	// rect for validity ourselves here. SSCI does not care about whether
	// or not the rects are valid
	checkRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
	checkRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
	checkRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
	checkRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
	if (!checkRect.isValidRect()) {
		return make_reg(0, 0);
	}

	uint16 result = 0;
	uint16 signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));
	const uint16 signalFlags = kSignalIgnoreActor | kSignalHidden;

	if ((signal & signalFlags) == 0) {
		List *list = _segMan->lookupList(listReference);
		if (!list) {
			error("kCantBeHere called with non-list as parameter");
		}
		result = !canBeHereCheckRectList(curObject, checkRect, list, signalFlags).isNull();
	}

	return make_reg(0, result);
}
Example #9
0
void GfxCoordAdjuster32::kernelGlobalToLocal(int16 &x, int16 &y, reg_t planeObject) {
	uint16 planeTop = readSelectorValue(_segMan, planeObject, SELECTOR(top));
	uint16 planeLeft = readSelectorValue(_segMan, planeObject, SELECTOR(left));

	y -= planeTop;
	x -= planeLeft;
}
Example #10
0
Common::Rect GfxCompare::getNSRect(reg_t object) {
	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));

	return nsRect;
}
Example #11
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;
}
Example #12
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);
	}
}
Example #13
0
void GuestAdditions::syncGK1StartupVolumeFromScummVM(const int index, const reg_t value) const {
	if (index == kGlobalVarGK1Music1 || index == kGlobalVarGK1Music2 ||
		index == kGlobalVarGK1DAC1 || index == kGlobalVarGK1DAC2 ||
		index == kGlobalVarGK1DAC3) {

		int16 volume;
		Selector selector;

		switch (readSelectorValue(_segMan, value, SELECTOR(type))) {
		case kSoundsMusicType: {
			volume = (ConfMan.getInt("music_volume") + 1) * MUSIC_VOLUME_MAX / Audio::Mixer::kMaxMixerVolume;
			selector = SELECTOR(musicVolume);
			break;
		}

		case kSoundsSoundType: {
			volume = (ConfMan.getInt("sound_volume") + 1) * MUSIC_VOLUME_MAX / Audio::Mixer::kMaxMixerVolume;
			selector = SELECTOR(soundVolume);
			break;
		}

		default:
			error("Unknown sound type");
		}

		writeSelectorValue(_segMan, value, selector, volume);
		writeSelectorValue(_segMan, value, selector, volume);
	}
}
Example #14
0
void GuestAdditions::syncGK1VolumeFromScummVM(const int16 musicVolume, const int16 dacVolume) const {
	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);
			const int16 type = readSelectorValue(_segMan, sound->value, SELECTOR(type));
			int16 volume;

			if (type == kSoundsMusicType) {
				volume = ConfMan.getBool("mute") ? 0 : musicVolume;
				writeSelectorValue(_segMan, sound->value, SELECTOR(musicVolume), musicVolume);
			} else if (type == kSoundsSoundType) {
				volume = dacVolume;
				writeSelectorValue(_segMan, sound->value, SELECTOR(soundVolume), dacVolume);
			} else {
				error("Unknown sound type %d", type);
			}

			// `setVolume` will set the `vol` property on the sound object;
			// if it did not do this, an invocation of the `setVol` selector
			// would need to be here (though doing so would result in
			// recursion, so don't)
			g_sci->_soundCmd->setVolume(sound->value, volume);
			soundId = sound->succ;
		}
	}
}
Example #15
0
void GfxMacIconBar::drawIcons() {
	// Draw the icons to the bottom of the screen

	byte *pal = new byte[256 * 4];
	Graphics::PictDecoder *pict = new Graphics::PictDecoder(Graphics::PixelFormat::createFormatCLUT8());
	uint32 lastX = 0;

	for (uint32 i = 0; i < _iconBarObjects.size(); i++) {
		uint32 iconIndex = readSelectorValue(g_sci->getEngineState()->_segMan, _iconBarObjects[i], SELECTOR(iconIndex));
		Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMacIconBarPictN, iconIndex + 1), false);
		if (!res)
			continue;

		Common::SeekableReadStream *stream = new Common::MemoryReadStream(res->data, res->size);
		Graphics::Surface *surf = pict->decodeImage(stream, pal);
		remapColors(surf, pal);

		g_system->copyRectToScreen((byte *)surf->pixels, surf->pitch, lastX, 200, MIN<uint32>(surf->w, 320 - lastX), surf->h);

		lastX += surf->w;
		surf->free();
		delete surf;
		delete stream;
	}

	delete pict;
	delete[] pal;
}
Example #16
0
void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) {
	AnimateList::iterator it;
	const AnimateList::iterator end = _list.end();

	// This has to be done in a separate loop. At least in sq1 some .dispose
	// modifies FIXEDLOOP flag in signal for another object. In that case we
	// would overwrite the new signal with our version of the old signal.
	for (it = _list.begin(); it != end; ++it) {
		// Finally update signal
		writeSelectorValue(_s->_segMan, it->object, SELECTOR(signal), it->signal);
	}

	for (it = _list.legacy_reverse_begin(); it != end; --it) {
		// We read out signal here again, this is not by accident but to ensure
		// that we got an up-to-date signal
		it->signal = readSelectorValue(_s->_segMan, it->object, SELECTOR(signal));

		if ((it->signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) {
			_paint16->bitsRestore(readSelector(_s->_segMan, it->object, SELECTOR(underBits)));
			writeSelectorValue(_s->_segMan, it->object, SELECTOR(underBits), 0);
		}

		if (it->signal & kSignalDisposeMe) {
			// Call .delete_ method of that object
			invokeSelector(_s, it->object, SELECTOR(delete_), argc, argv, 0);
		}
	}
}
Example #17
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;
}
Example #18
0
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;
}
Example #19
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;
}
Example #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);
		}
	}
}
Example #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);
}
Example #22
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;
}
Example #23
0
reg_t GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) {
	Common::Rect checkRect;
	uint16 result;

	checkRect.left = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
	checkRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
	checkRect.right = readSelectorValue(_segMan, curObject, SELECTOR(brRight));
	checkRect.bottom = readSelectorValue(_segMan, curObject, SELECTOR(brBottom));
	uint16 signal = readSelectorValue(_segMan, curObject, SELECTOR(signal));

	if (!checkRect.isValidRect()) {	// can occur in Iceman and Mother Goose - HACK? TODO: is this really occuring in sierra sci? check this
		warning("kCan(t)BeHere - invalid rect %d, %d -> %d, %d", checkRect.left, checkRect.top, checkRect.right, checkRect.bottom);
		return NULL_REG; // this means "can be here"
	}

	Common::Rect adjustedRect = _coordAdjuster->onControl(checkRect);
	uint16 controlMask = readSelectorValue(_segMan, curObject, SELECTOR(illegalBits));
	result = isOnControl(GFX_SCREEN_MASK_CONTROL, adjustedRect) & controlMask;
	if ((!result) && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) {
		List *list = _segMan->lookupList(listReference);
		if (!list)
			error("kCanBeHere called with non-list as parameter");

		return canBeHereCheckRectList(curObject, checkRect, list, kSignalIgnoreActor | kSignalRemoveView | kSignalNoUpdate);
	}

	return make_reg(0, result);
}
Example #24
0
int SoundCommandParser::getSoundResourceId(reg_t obj) {
	int resourceId = obj.getSegment() ? (int)readSelectorValue(_segMan, obj, SELECTOR(number)) : -1;
	// Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did.
	if (g_sci && g_sci->_features->useAltWinGMSound()) {
		// Check if the alternate MIDI song actually exists...
		// There are cases where it just doesn't exist (e.g. SQ4, room 530 -
		// bug #3392767). In these cases, use the DOS tracks instead.
		if (resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, resourceId + 1000)))
			resourceId += 1000;
	}

	return resourceId;
}
Example #25
0
void GfxAnimate::updateScreen(byte oldPicNotValid) {
	AnimateList::iterator it;
	const AnimateList::iterator end = _list.end();
	Common::Rect lsRect;
	Common::Rect workerRect;

	for (it = _list.begin(); it != end; ++it) {
		if (it->showBitsFlag || !(it->signal & (kSignalRemoveView | kSignalNoUpdate) ||
										(!(it->signal & kSignalRemoveView) && (it->signal & kSignalNoUpdate) && oldPicNotValid))) {
			lsRect.left = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft));
			lsRect.top = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop));
			lsRect.right = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight));
			lsRect.bottom = readSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom));

			workerRect = lsRect;
			workerRect.clip(it->celRect);

			if (!workerRect.isEmpty()) {
				workerRect = lsRect;
				workerRect.extend(it->celRect);
			} else {
				_paint16->bitsShow(lsRect);
				workerRect = it->celRect;
			}
			writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsLeft), it->celRect.left);
			writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsTop), it->celRect.top);
			writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsRight), it->celRect.right);
			writeSelectorValue(_s->_segMan, it->object, SELECTOR(lsBottom), it->celRect.bottom);
			// may get used for debugging
			//_paint16->frameRect(workerRect);
			_paint16->bitsShow(workerRect);

			if (it->signal & kSignalHidden)
				it->signal |= kSignalRemoveView;
		}
	}
	// use this for debug purposes
	// _screen->copyToScreen();
}
Example #26
0
void GfxFrameout::kernelDeletePlane(reg_t object) {
	deletePlaneItems(object);
	deletePlanePictures(object);

	for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
		if (it->object == object) {
			_planes.erase(it);
			Common::Rect planeRect;
			planeRect.top = readSelectorValue(_segMan, object, SELECTOR(top));
			planeRect.left = readSelectorValue(_segMan, object, SELECTOR(left));
			planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom));
			planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right));

			_coordAdjuster->fromScriptToDisplay(planeRect.top, planeRect.left);
			_coordAdjuster->fromScriptToDisplay(planeRect.bottom, planeRect.right);

			// Blackout removed plane rect
			_paint32->fillRect(planeRect, 0);
			return;
		}
	}
}
Example #27
0
reg_t kSort(EngineState *s, int argc, reg_t *argv) {
	SegManager *segMan = s->_segMan;
	reg_t source = argv[0];
	reg_t dest = argv[1];
	reg_t order_func = argv[2];

	int input_size = (int16)readSelectorValue(segMan, source, SELECTOR(size));
	reg_t input_data = readSelector(segMan, source, SELECTOR(elements));
	reg_t output_data = readSelector(segMan, dest, SELECTOR(elements));

	List *list;
	Node *node;

	if (!input_size)
		return s->r_acc;

	if (output_data.isNull()) {
		list = s->_segMan->allocateList(&output_data);
		list->first = list->last = NULL_REG;
		writeSelector(segMan, dest, SELECTOR(elements), output_data);
	}

	writeSelectorValue(segMan, dest, SELECTOR(size), input_size);

	list = s->_segMan->lookupList(input_data);
	node = s->_segMan->lookupNode(list->first);

	sort_temp_t *temp_array = (sort_temp_t *)malloc(sizeof(sort_temp_t) * input_size);

	int i = 0;
	while (node) {
		reg_t params[1] = { node->value };
		invokeSelector(s, order_func, SELECTOR(doit), argc, argv, 1, params);
		temp_array[i].key = node->key;
		temp_array[i].value = node->value;
		temp_array[i].order = s->r_acc;
		i++;
		node = s->_segMan->lookupNode(node->succ);
	}

	qsort(temp_array, input_size, sizeof(sort_temp_t), sort_temp_cmp);

	for (i = 0;i < input_size;i++) {
		reg_t lNode = s->_segMan->newNode(temp_array[i].value, temp_array[i].key);
		addToEnd(s, output_data, lNode);
	}

	free(temp_array);

	return s->r_acc;
}
Example #28
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));

		// HACK: Ignore invalid views for now (perhaps unimplemented text views?)
		if (viewId == 0xFFFF)	// invalid view
			return;

		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 {
			if (tmpView->isSci2Hires())
				tmpView->adjustToUpscaledCoordinates(y, x);

			tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);

			if (tmpView->isSci2Hires()) {
				tmpView->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
				tmpView->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
			}
		}

		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);
	}
}
Example #29
0
void ScreenItem::update(const reg_t object) {
	SegManager *segMan = g_sci->getEngineState()->_segMan;

	const GuiResourceId view = readSelectorValue(segMan, object, SELECTOR(view));
	const int16 loopNo = readSelectorValue(segMan, object, SELECTOR(loop));
	const int16 celNo = readSelectorValue(segMan, object, SELECTOR(cel));

	const bool updateCel = (
		_celInfo.resourceId != view ||
		_celInfo.loopNo != loopNo ||
		_celInfo.celNo != celNo
	);

	const bool updateBitmap = !readSelector(segMan, object, SELECTOR(bitmap)).isNull();

	setFromObject(segMan, object, updateCel, updateBitmap);

	if (!_created) {
		_updated = g_sci->_gfxFrameout->getScreenCount();
	}

	_deleted = 0;
}
Example #30
0
void GfxFrameout::kernelDeletePlane(reg_t object) {
	deletePlanePictures(object);
	for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
		if (it->object == object) {
			_planes.erase(it);
			Common::Rect planeRect;
			planeRect.top = readSelectorValue(_segMan, object, SELECTOR(top));
			planeRect.left = readSelectorValue(_segMan, object, SELECTOR(left));
			planeRect.bottom = readSelectorValue(_segMan, object, SELECTOR(bottom)) + 1;
			planeRect.right = readSelectorValue(_segMan, object, SELECTOR(right)) + 1;

			Common::Rect screenRect(_screen->getWidth(), _screen->getHeight());
			planeRect.top = (planeRect.top * screenRect.height()) / scriptsRunningHeight;
			planeRect.left = (planeRect.left * screenRect.width()) / scriptsRunningWidth;
			planeRect.bottom = (planeRect.bottom * screenRect.height()) / scriptsRunningHeight;
			planeRect.right = (planeRect.right * screenRect.width()) / scriptsRunningWidth;
			planeRect.clip(screenRect); // we need to do this, at least in gk1 on cemetary we get bottom right -> 201, 321
			// Blackout removed plane rect
			_paint32->fillRect(planeRect, 0);
			return;
		}
	}
}