diff options
| author | Eugene Sandulenko | 2008-06-07 19:40:43 +0000 | 
|---|---|---|
| committer | Eugene Sandulenko | 2008-06-07 19:40:43 +0000 | 
| commit | e14f81391c8210ea7cef8f798871ff0f57c76cbb (patch) | |
| tree | 641aa28ae40e35dae82934cfe6788317897c6e43 /engines/drascula/graphics.cpp | |
| parent | 3723afc268afc8aedc83f9353eb44be6566050bf (diff) | |
| download | scummvm-rg350-e14f81391c8210ea7cef8f798871ff0f57c76cbb.tar.gz scummvm-rg350-e14f81391c8210ea7cef8f798871ff0f57c76cbb.tar.bz2 scummvm-rg350-e14f81391c8210ea7cef8f798871ff0f57c76cbb.zip | |
Shuffled around more code. Now the files look more manageable.
svn-id: r32599
Diffstat (limited to 'engines/drascula/graphics.cpp')
| -rw-r--r-- | engines/drascula/graphics.cpp | 736 | 
1 files changed, 736 insertions, 0 deletions
| diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp new file mode 100644 index 0000000000..803b26f96d --- /dev/null +++ b/engines/drascula/graphics.cpp @@ -0,0 +1,736 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "drascula/drascula.h" + +namespace Drascula { + +void DrasculaEngine::allocMemory() { +	screenSurface = (byte *)malloc(64000); +	assert(screenSurface); +	frontSurface = (byte *)malloc(64000); +	assert(frontSurface); +	backSurface = (byte *)malloc(64000); +	assert(backSurface); +	drawSurface1 = (byte *)malloc(64000); +	assert(drawSurface1); +	drawSurface2 = (byte *)malloc(64000); +	assert(drawSurface2); +	drawSurface3 = (byte *)malloc(64000); +	assert(drawSurface3); +	tableSurface = (byte *)malloc(64000); +	assert(tableSurface); +	extraSurface = (byte *)malloc(64000); +	assert(extraSurface); +} + +void DrasculaEngine::freeMemory() { +	free(screenSurface); +	free(drawSurface1); +	free(backSurface); +	free(drawSurface2); +	free(tableSurface); +	free(drawSurface3); +	free(extraSurface); +	free(frontSurface); +} + +void DrasculaEngine::moveCursor() { +	int cursorPos[8]; + +	copyBackground(0, 0, 0, 0, 320, 200, drawSurface1, screenSurface); + +	updateRefresh_pre(); +	moveCharacters(); +	updateRefresh(); + +	if (!strcmp(textName, "hacker") && hasName == 1) { +		if (_color != kColorRed && menuScreen == 0) +			color_abc(kColorRed); +	} else if (menuScreen == 0 && _color != kColorLightGreen) +		color_abc(kColorLightGreen); +	if (hasName == 1 && menuScreen == 0) +		centerText(textName, mouseX, mouseY); +	if (menuScreen == 1) +		showMenu(); +	else if (menuBar == 1) +		clearMenu(); + +	cursorPos[0] = 0; +	cursorPos[1] = 0; +	cursorPos[2] = mouseX - 20; +	cursorPos[3] = mouseY - 17; +	cursorPos[4] = OBJWIDTH; +	cursorPos[5] = OBJHEIGHT; +	copyRectClip(cursorPos, drawSurface3, screenSurface); +} + +void DrasculaEngine::setCursorTable() { +	int cursorPos[8]; + +	cursorPos[0] = 225; +	cursorPos[1] = 56; +	cursorPos[2] = mouseX - 20; +	cursorPos[3] = mouseY - 12; +	cursorPos[4] = 40; +	cursorPos[5] = 25; + +	copyRectClip(cursorPos, tableSurface, screenSurface); +} + +void DrasculaEngine::loadPic(const char *NamePcc, byte *targetSurface, int colorCount) { +	unsigned int con, x = 0; +	unsigned int fExit = 0; +	byte ch, rep; +	byte *auxPun; + +	_arj.open(NamePcc); +	if (!_arj.isOpen()) +		error("missing game data %s %c", NamePcc, 7); + +	pcxBuffer = (byte *)malloc(65000); +	auxPun = pcxBuffer; +	_arj.seek(128); +	while (!fExit) { +		ch = _arj.readByte(); +		rep = 1; +		if ((ch & 192) == 192) { +			rep = (ch & 63); +			ch = _arj.readByte(); +		} +		for (con = 0; con < rep; con++) { +			*auxPun++ = ch; +			x++; +			if (x > 64000) +				fExit = 1; +		} +	} + +	_arj.read(cPal, 768); +	_arj.close(); + +	memcpy(targetSurface, pcxBuffer, 64000); +	free(pcxBuffer); +	setRGB((byte *)cPal, colorCount); +} + +byte *DrasculaEngine::loadPCX(byte *NamePcc) { +	signed int con = 0; +	unsigned int X = 0; +	unsigned int fExit = 0; +	char ch, rep; +	byte *AuxPun = AuxBuffDes; + +	while (!fExit) { +		ch = *NamePcc++; +		rep = 1; +		if ((ch & 192) == 192) { +			rep = (ch & 63); +			ch = *NamePcc++; +		} +		for (con = 0; con< rep; con++) { +			*AuxPun++ = ch; +			X++; +			if (X > 64000) +				fExit = 1; +		} +	} +	return AuxBuffDes; +} + +void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width, +								  int height, byte *src, byte *dest) { +	dest += xdes + ydes * 320; +	src += xorg + yorg * 320; +	for (int x = 0; x < height; x++) { +		memcpy(dest, src, width); +		dest += 320; +		src += 320; +	} +} + +void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width, +								   int height, byte *src, byte *dest) { +	int y, x; + +	dest += xdes + ydes * 320; +	src += xorg + yorg * 320; + +	for (y = 0; y < height; y++) +		for (x = 0; x < width; x++) +			if (src[x + y * 320] != 255) +				dest[x + y * 320] = src[x + y * 320]; +} + +void DrasculaEngine::copyRectClip(int *Array, byte *src, byte *dest) { +	int y, x; +	int xorg = Array[0]; +	int yorg = Array[1]; +	int xdes = Array[2]; +	int ydes = Array[3]; +	int width = Array[4]; +	int height = Array[5]; + +	if (ydes < 0) { +		yorg += -ydes; +		height += ydes; +		ydes = 0; +	} +	if (xdes < 0) { +		xorg += -xdes; +		width += xdes; +		xdes = 0; +	} +	if ((xdes + width) > 319) +		width -= (xdes + width) - 320; +	if ((ydes + height) > 199) +		height -= (ydes + height) - 200; + +	dest += xdes + ydes * 320; +	src += xorg + yorg * 320; + +	for (y = 0; y < height; y++) +		for (x = 0; x < width; x++) +			if (src[x + y * 320] != 255) +				dest[x + y * 320] = src[x + y * 320]; +} + +void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer) { +	byte *ptr = VGA; + +	ptr += xdes + ydes * 320; +	buffer += xorg + yorg * 320; +	for (int x = 0; x < height; x++) { +		memcpy(ptr, buffer, width); +		ptr += 320; +		buffer += 320; +	} + +	_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +	_system->updateScreen(); +} + +void DrasculaEngine::print_abc(const char *said, int screenX, int screenY) { +	int textPos[8]; +	int letterY = 0, letterX = 0, c, i; +	uint len = strlen(said); + +	for (uint h = 0; h < len; h++) { +		c = toupper(said[h]); + +		for (i = 0; i < CHARMAP_SIZE; i++) { +			if (c == charMap[i].inChar) { +				letterX = charMap[i].mappedChar; + +				switch (charMap[i].charType) { +					case 0:		// letters +						letterY = (_lang == kSpanish) ? 149 : 158; +						break; +					case 1:		// signs +						letterY = (_lang == kSpanish) ? 160 : 169; +						break; +					case 2:		// accented +						letterY = 180; +						break; +				}	// switch +				break; +			}	// if +		}	// for + +		textPos[0] = letterX; +		textPos[1] = letterY; +		textPos[2] = screenX; +		textPos[3] = screenY; +		textPos[4] = CHAR_WIDTH; +		textPos[5] = CHAR_HEIGHT; + +		copyRectClip(textPos, textSurface, screenSurface); + +		screenX = screenX + CHAR_WIDTH; +		if (screenX > 317) { +			screenX = 0; +			screenY = screenY + CHAR_HEIGHT + 2; +		} +	}	// for +} + +void DrasculaEngine::print_abc_opc(const char *said, int screenX, int screenY, int game) { +	int textPos[6]; +	int signY, letterY, letterX = 0; +	uint len = strlen(said); + +	for (uint h = 0; h < len; h++) { +		if (game == 1) { +			letterY = 6; +			signY = 15; +		} else if (game == 3) { +			letterY = 56; +			signY = 65; +		} else { +			letterY = 31; +			signY = 40; +		} + +		int c = toupper(said[h]); + +		// WORKAROUND: Even original did not process it correctly +		// Fixes apostrophe rendering +		if (_lang != kSpanish) +			if (c == '\'') +				c = '\244'; + +		for (int i = 0; i < CHARMAP_SIZE; i++) { +			if (c == charMap[i].inChar) { +				// Convert the mapped char of the normal font to the +				// mapped char of the dialogue font + +				int multiplier = (charMap[i].mappedChar - 6) / 9; + +				letterX = multiplier * 7 + 10; + +				if (charMap[i].charType > 0) +					letterY = signY; +				break; +			}	// if +		}	// for + +		textPos[0] = letterX; +		textPos[1] = letterY; +		textPos[2] = screenX; +		textPos[3] = screenY; +		textPos[4] = CHAR_WIDTH_OPC; +		textPos[5] = CHAR_HEIGHT_OPC; + +		copyRectClip(textPos, backSurface, screenSurface); + +		screenX = screenX + CHAR_WIDTH_OPC; +	} +} + +void DrasculaEngine::centerText(const char *message, int textX, int textY) { +	char bb[200], m2[200], m1[200], mb[10][50]; +	char m3[200]; +	int h, fil, textX3, textX2, textX1, conta_f = 0, ya = 0; + +	strcpy(m1, " "); +	strcpy(m2, " "); +	strcpy(m3, " "); +	strcpy(bb, " "); + +	for (h = 0; h < 10; h++) +		strcpy(mb[h], " "); + +	if (textX > 160) +		ya = 1; + +	strcpy(m1, message); +	textX = CLIP<int>(textX, 60, 255); + +	textX1 = textX; + +	if (ya == 1) +		textX1 = 315 - textX; + +	textX2 = (strlen(m1) / 2) * CHAR_WIDTH; + +	while (true) { +		strcpy(bb, m1); +		scumm_strrev(bb); + +		if (textX1 < textX2) { +			strcpy(m3, strrchr(m1, ' ')); +			strcpy(m1, strstr(bb, " ")); +			scumm_strrev(m1); +			m1[strlen(m1) - 1] = '\0'; +			strcat(m3, m2); +			strcpy(m2, m3); +		}; + +		textX2 = (strlen(m1) / 2) * CHAR_WIDTH; + +		if (textX1 < textX2) +			continue; + +		strcpy(mb[conta_f], m1); + +		if (!strcmp(m2, "")) +			break; + +		scumm_strrev(m2); +		m2[strlen(m2) - 1] = '\0'; +		scumm_strrev(m2); +		strcpy(m1, m2); +		strcpy(m2, ""); +		conta_f++; +	} + +	fil = textY - (((conta_f + 3) * CHAR_HEIGHT)); + +	for (h = 0; h < conta_f + 1; h++) { +		textX3 = strlen(mb[h]) / 2; +		print_abc(mb[h], ((textX) - textX3 * CHAR_WIDTH) - 1, fil); +		fil = fil + CHAR_HEIGHT + 2; +	} +} + +void DrasculaEngine::screenSaver() { +	int xr, yr; +	byte *copia, *ghost; +	float coeff = 0, coeff2 = 0; +	int count = 0; +	int count2 = 0; +	int tempLine[320]; +	int tempRow[200]; + +	clearRoom(); + +	loadPic("sv.alg", drawSurface1, HALF_PAL); + +	// inicio_ghost(); +	copia = (byte *)malloc(64000); +	ghost = (byte *)malloc(65536); + +	// carga_ghost(); +	_arj.open("ghost.drv"); +	if (!_arj.isOpen()) +		error("Cannot open file ghost.drv"); + +	_arj.read(ghost, 65536); +	_arj.close(); + +	updateEvents(); +	xr = mouseX; +	yr = mouseY; + +	for (;;) { +		// efecto(drawSurface1); + +		memcpy(copia, drawSurface1, 64000); +		coeff += 0.1f; +		coeff2 = coeff; + +		if (++count > 319) +			count = 0; + +		for (int i = 0; i < 320; i++) { +			tempLine[i] = (int)(sin(coeff2) * 16); +			coeff2 += 0.02f; +			tempLine[i] = checkWrapY(tempLine[i]); +		} + +		coeff2 = coeff; +		for (int i = 0; i < 200; i++) { +			tempRow[i] = (int)(sin(coeff2) * 16); +			coeff2 += 0.02f; +			tempRow[i] = checkWrapX(tempRow[i]); +		} + +		if (++count2 > 199) +			count2 = 0; + +		int x1_, y1_, off1, off2; + +		for (int i = 0; i < 200; i++) { +			for (int j = 0; j < 320; j++) { +				x1_ = j + tempRow[i]; +				x1_ = checkWrapX(x1_); + +				y1_ = i + count2; +				y1_ = checkWrapY(y1_); + +				off1 = 320 * y1_ + x1_; + +				x1_ = j + count; +				x1_ = checkWrapX(x1_); + +				y1_ = i + tempLine[j]; +				y1_ = checkWrapY(y1_); +				off2 = 320 * y1_ + x1_; + +				VGA[320 * i + j] = ghost[drawSurface1[off2] + (copia[off1] << 8)]; +			} +		} +		_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +		_system->updateScreen(); + +		_system->delayMillis(20); + +		// end of efecto() + +		updateEvents(); +		if (rightMouseButton == 1 || leftMouseButton == 1) +			break; +		if (mouseX != xr) +			break; +		if (mouseY != yr) +			break; +	} +	// fin_ghost(); +	free(copia); +	free(ghost); + +	loadPic(roomNumber, drawSurface1, HALF_PAL); +} + +void DrasculaEngine::playFLI(const char *filefli, int vel) { +	// Open file +	MiVideoSSN = (byte *)malloc(64256); +	globalSpeed = 1000 / vel; +	FrameSSN = 0; +	UsingMem = 0; +	if (MiVideoSSN == NULL) +		return; +	_arj.open(filefli); +	mSession = TryInMem(); +	LastFrame = _system->getMillis(); + +	while (playFrameSSN() && (!term_int)) { +		if (getScan() == Common::KEYCODE_ESCAPE) +			term_int = 1; +	} + +	free(MiVideoSSN); +	if (UsingMem) +		free(pointer); +	else +		_arj.close(); +} + +int DrasculaEngine::playFrameSSN() { +	int Exit = 0; +	uint32 Lengt; +	byte *BufferSSN; + +	if (!UsingMem) +		_arj.read(&CHUNK, 1); +	else { +		memcpy(&CHUNK, mSession, 1); +		mSession += 1; +	} + +	switch (CHUNK) { +	case kFrameSetPal: +		if (!UsingMem) +			_arj.read(dacSSN, 768); +		else { +			memcpy(dacSSN, mSession, 768); +			mSession += 768; +		} +		setPalette(dacSSN); +		break; +	case kFrameEmptyFrame: +		WaitFrameSSN(); +		break; +	case kFrameInit: +		if (!UsingMem) { +			CMP = _arj.readByte(); +			Lengt = _arj.readUint32LE(); +		} else { +			memcpy(&CMP, mSession, 1); +			mSession += 1; +			Lengt = READ_LE_UINT32(mSession); +			mSession += 4; +		} +		if (CMP == kFrameCmpRle) { +			if (!UsingMem) { +				BufferSSN = (byte *)malloc(Lengt); +				_arj.read(BufferSSN, Lengt); +			} else { +				BufferSSN = (byte *)malloc(Lengt); +				memcpy(BufferSSN, mSession, Lengt); +				mSession += Lengt; +			} +			Des_RLE(BufferSSN, MiVideoSSN); +			free(BufferSSN); +			if (FrameSSN) { +				WaitFrameSSN(); +				MixVideo(VGA, MiVideoSSN); +				_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +			} else { +				WaitFrameSSN(); +				memcpy(VGA, MiVideoSSN, 64000); +				_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +			} +			_system->updateScreen(); +			FrameSSN++; +		} else { +			if (CMP == kFrameCmpOff) { +				if (!UsingMem) { +					BufferSSN = (byte *)malloc(Lengt); +					_arj.read(BufferSSN, Lengt); +				} else { +					BufferSSN = (byte *)malloc(Lengt); +					memcpy(BufferSSN, mSession, Lengt); +					mSession += Lengt; +				} +				Des_OFF(BufferSSN, MiVideoSSN, Lengt); +				free(BufferSSN); +				if (FrameSSN) { +					WaitFrameSSN(); +					MixVideo(VGA, MiVideoSSN); +					_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +				} else { +					WaitFrameSSN(); +					memcpy(VGA, MiVideoSSN, 64000); +					_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +				} +				_system->updateScreen(); +				FrameSSN++; +			} +		} +		break; +	case kFrameEndAnim: +		Exit = 1; +		break; +	default: +		Exit = 1; +		break; +	} + +	return (!Exit); +} + +byte *DrasculaEngine::TryInMem() { +	int Lengt; + +	_arj.seek(0, SEEK_END); +	Lengt = _arj.pos(); +	_arj.seek(0, SEEK_SET); +	pointer = (byte *)malloc(Lengt); +	if (pointer == NULL) +		return NULL; +	_arj.read(pointer, Lengt); +	UsingMem = 1; +	_arj.close(); + +	return pointer; +} + +void DrasculaEngine::Des_OFF(byte *BufferOFF, byte *MiVideoOFF, int Lenght) { +	int x = 0; +	unsigned char Reps; +	int Offset; + +	memset(MiVideoSSN, 0, 64000); +	while (x < Lenght) { +		Offset = BufferOFF[x] + BufferOFF[x + 1] * 256; +		Reps = BufferOFF[x + 2]; +		memcpy(MiVideoOFF + Offset, &BufferOFF[x + 3], Reps); +		x += 3 + Reps; +	} +} + +void DrasculaEngine::Des_RLE(byte *BufferRLE, byte *MiVideoRLE) { +	signed int con = 0; +	unsigned int X = 0; +	unsigned int fExit = 0; +	char ch, rep; +	while (!fExit) { +		ch = *BufferRLE++; +		rep = 1; +		if ((ch & 192) == 192) { +			rep = (ch & 63); +			ch =* BufferRLE++; +		} +		for (con = 0; con < rep; con++) { +			*MiVideoRLE++ = ch; +			X++; +			if (X > 64000) +				fExit = 1; +		} +	} +} + +void DrasculaEngine::MixVideo(byte *OldScreen, byte *NewScreen) { +	for (int x = 0; x < 64000; x++) +		OldScreen[x] ^= NewScreen[x]; +} + +void DrasculaEngine::WaitFrameSSN() { +	uint32 now; +	while ((now = _system->getMillis()) - LastFrame < ((uint32) globalSpeed)) +		_system->delayMillis(globalSpeed - (now - LastFrame)); +	LastFrame = LastFrame + globalSpeed; +} + +void DrasculaEngine::WaitForNext(int FPS) { +	_system->delayMillis(1000 / FPS); +} + +bool DrasculaEngine::animate(const char *animationFile, int FPS) { +	unsigned j; +	int NFrames = 1; +	int cnt = 2; +	int dataSize = 0; + +	AuxBuffDes = (byte *)malloc(65000); + +	_arj.open(animationFile); + +	if (!_arj.isOpen()) { +		error("Animation file %s not found", animationFile); +	} + +	NFrames = _arj.readSint32LE(); +	dataSize = _arj.readSint32LE(); +	AuxBuffOrg = (byte *)malloc(dataSize); +	_arj.read(AuxBuffOrg, dataSize); +	_arj.read(cPal, 768); +	loadPCX(AuxBuffOrg); +	free(AuxBuffOrg); +	memcpy(VGA, AuxBuffDes, 64000); +	_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +	_system->updateScreen(); +	setPalette(cPal); +	WaitForNext(FPS); +	while (cnt < NFrames) { +		dataSize = _arj.readSint32LE(); +		AuxBuffOrg = (byte *)malloc(dataSize); +		_arj.read(AuxBuffOrg, dataSize); +		_arj.read(cPal, 768); +		loadPCX(AuxBuffOrg); +		free(AuxBuffOrg); +		for (j = 0;j < 64000; j++) { +			VGA[j] = AuxBuffDes[j] ^ VGA[j]; +		} +		_system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200); +		_system->updateScreen(); +		WaitForNext(FPS); +		cnt++; +		byte key = getScan(); +		if (key == Common::KEYCODE_ESCAPE) +			term_int = 1; +		if (key != 0) +			break; +	} +	free(AuxBuffDes); +	_arj.close(); + +	return ((term_int == 1) || (getScan() == Common::KEYCODE_ESCAPE)); +} + + + +} // End of namespace Drascula | 
