Esempio n. 1
0
FLARM::FrameHeader
FLARM::PrepareFrameHeader(unsigned sequence_number, MessageType message_type,
                          const void *data, size_t length)
{
  assert((data != NULL && length > 0) || (data == NULL && length == 0));

  FrameHeader header;
  header.SetLength(8 + length);
  header.version = 0;
  header.SetSequenceNumber(sequence_number++);
  header.type = (uint8_t)message_type;
  header.SetCRC(CalculateCRC(header, data, length));
  return header;
}
Esempio n. 2
0
void FontRenderer::copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
	FrameHeader frame;

	frame.read(charPtr);

	byte *source = charPtr + FrameHeader::size();
	byte *rowPtr = spritePtr;

	for (uint i = 0; i < frame.height; i++) {
		byte *dest = rowPtr;

		if (pen) {
			// Use the specified colors
			for (uint j = 0; j < frame.width; j++) {
				switch (*source++) {
				case 0:
					// Do nothing if source pixel is zero,
					// ie. transparent
					break;
				case LETTER_COL_PSX1: // Values for colored zone
				case LETTER_COL_PSX2:
				case LETTER_COL:
					*dest = pen;
					break;
				case BORDER_COL:
				default:
					// Don't do a border pixel if there's
					// already a bit of another character
					// underneath (for overlapping!)
					if (!*dest)
						*dest = _borderPen;
					break;
				}
				dest++;
			}
		} else {
			// Pen is zero, so just copy character sprites
			// directly into text sprite without remapping colors.
			// Apparently overlapping is never considered here?
			memcpy(dest, source, frame.width);
			source += frame.width;
		}
		rowPtr += spriteWidth;
	}
}
Esempio n. 3
0
void MoviePlayer::openTextObject(uint32 index) {
	MovieText *text = &_movieTexts[index];

	// Pull out the text line to get the official text number (for WAV id)

	uint32 res = text->_textNumber / SIZE;
	uint32 localText = text->_textNumber & 0xffff;

	// Open text resource and get the line

	byte *textData = _vm->fetchTextLine(_vm->_resman->openResource(res), localText);

	text->_speechId = READ_LE_UINT16(textData);

	// Is it speech or subtitles, or both?

	// If we want subtitles, or there was no sound

	if (_vm->getSubtitles() || !text->_speechId) {
		text->_textMem = _vm->_fontRenderer->makeTextSprite(textData + 2, 600, 255, _vm->_speechFontId, 1);
	}

	_vm->_resman->closeResource(res);

	if (text->_textMem) {
		FrameHeader frame;

		frame.read(text->_textMem);

		text->_textSprite.x = 320 - frame.width / 2;
		text->_textSprite.y = 440 - frame.height;
		text->_textSprite.w = frame.width;
		text->_textSprite.h = frame.height;
		text->_textSprite.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION;
		text->_textSprite.data = text->_textMem + FrameHeader::size();
		text->_textSprite.isText = true;
		_vm->_screen->createSurface(&text->_textSprite, &_textSurface);

		_textX = 320 - text->_textSprite.w / 2;
		_textY = 420 - text->_textSprite.h;
	}
}
	bool readFrameHeader(FrameHeader &h,PxFileBuffer &fph)
	{
		bool ret = false;

		h.init();
		h.mItemCount = fph.readDword();
		h.mItemSize  = fph.readDword();
		h.mSeekLocation = fph.tellRead();
		if ( h.mItemCount > 0 && h.mItemSize > 0 )
		{
			fph.seekRead(h.mSeekLocation+h.mItemSize);
			ret = true;
		}
		return ret;
	}
Esempio n. 5
0
byte *FontRenderer::findChar(byte ch, byte *charSet) {

	// PSX version doesn't use an animation table to keep all letters,
	// instead a big sprite (char atlas) is used, and the single char
	// must be extracted from that.

	if (Sword2Engine::isPsx()) {
		byte *buffer;
		PSXFontEntry header;
		FrameHeader bogusHeader;

		charSet += ResHeader::size() + 2;

		if (ch < FIRST_CHAR)
			ch = DUD;

		// Read font entry of the corresponding char.
		header.read(charSet + PSXFontEntry::size() * (ch - 32));

		// We have no such character, generate an empty one
		// on the fly, size 6x12.
		if (header.charWidth == 0) {

			// Prepare a "bogus" FrameHeader to be returned with
			// "empty" character data.
			bogusHeader.compSize = 0;
			bogusHeader.width = 6;
			bogusHeader.height = 12;

			buffer = (byte *)malloc(24 * 3 + FrameHeader::size());
			memset(buffer, 0, 24 * 3 + FrameHeader::size());
			bogusHeader.write(buffer);

			return buffer;
		}

		buffer = (byte *)malloc(FrameHeader::size() + header.charWidth * header.charHeight * 4);
		byte *tempchar = (byte *)malloc(header.charWidth * header.charHeight);

		// Prepare the "bogus" header to be returned with character
		bogusHeader.compSize = 0;
		bogusHeader.width = header.charWidth * 2;
		bogusHeader.height = header.charHeight;

		// Go to the beginning of char atlas
		charSet += 2062;

		memset(buffer, 0, FrameHeader::size() + header.charWidth * header.charHeight * 4);

		bogusHeader.write(buffer);

		// Copy and stretch the char into destination buffer
		for (int idx = 0; idx < header.charHeight; idx++) {
			memcpy(tempchar + header.charWidth * idx, charSet + header.offset + 128 * (header.skipLines + idx), header.charWidth);
		}

		for (int line = 0; line < header.charHeight; line++) {
			for (int col = 0; col < header.charWidth; col++) {
				*(buffer + FrameHeader::size() + line * bogusHeader.width + col * 2) = *(tempchar + line * header.charWidth + col);
				*(buffer + FrameHeader::size() + line * bogusHeader.width + col * 2 + 1) = *(tempchar + line * header.charWidth + col);
			}
		}

		free(tempchar);

		return buffer;

	} else {
		if (ch < FIRST_CHAR)
			ch = DUD;
		return _vm->fetchFrameHeader(charSet, ch - FIRST_CHAR);
	}
}
Esempio n. 6
0
void Screen::rollCredits() {
	uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();

	// Prepare for the credits by fading down, stoping the music, etc.

	_vm->_mouse->setMouse(0);

	_vm->_sound->muteFx(true);
	_vm->_sound->muteSpeech(true);

	waitForFade();
	fadeDown();
	waitForFade();

	_vm->_mouse->closeMenuImmediately();

	// There are three files which I believe are involved in showing the
	// credits:
	//
	// credits.bmp  - The "Smacker" logo, stored as follows:
	//
	//     width     2 bytes, little endian
	//     height    2 bytes, little endian
	//     palette   3 * 256 bytes
	//     data      width * height bytes
	//
	//     Note that the maximum colour component in the palette is 0x3F.
	//     This is the same resolution as the _paletteMatch table. I doubt
	//     that this is a coincidence, but let's use the image palette
	//     directly anyway, just to be safe.
	//
	// credits.clu  - The credits text (credits.txt in PSX version)
	//
	//     This is simply a text file with CRLF line endings.
	//     '^' is not shown, but used to mark the center of the line.
	//     '@' is used as a placeholder for the "Smacker" logo. At least
	//     when it appears alone.
	//     Remaining lines are centered.
	//     The German version also contains character code 9 for no
	//     apparent reason. We ignore them.
	//
	// fonts.clu    - The credits font?
	//
	//     FIXME: At this time I don't know how to interpret fonts.clu. For
	//     now, let's just the standard speech font instead.

	SpriteInfo spriteInfo;
	Common::File f;
	int i;

	spriteInfo.isText = false;

	// Read the "Smacker" logo

	uint16 logoWidth = 0;
	uint16 logoHeight = 0;
	byte *logoData = NULL;
	byte palette[256 * 3];

	if (f.open("credits.bmp")) {
		logoWidth = f.readUint16LE();
		logoHeight = f.readUint16LE();

		for (i = 0; i < 256; i++) {
			palette[i * 3 + 0] = f.readByte() << 2;
			palette[i * 3 + 1] = f.readByte() << 2;
			palette[i * 3 + 2] = f.readByte() << 2;
		}

		logoData = (byte *)malloc(logoWidth * logoHeight);

		f.read(logoData, logoWidth * logoHeight);
		f.close();
	} else {
		warning("Can't find credits.bmp");
		memset(palette, 0, sizeof(palette));
		palette[14 * 3 + 0] = 252;
		palette[14 * 3 + 1] = 252;
		palette[14 * 3 + 2] = 252;
	}

	setPalette(0, 256, palette, RDPAL_INSTANT);

	// Read the credits text

	Common::Array<CreditsLine *> creditsLines;

	int lineCount = 0;
	int lineTop = 400;
	int paragraphStart = 0;
	bool hasCenterMark = false;

	if (Sword2Engine::isPsx()) {
		if (!f.open("credits.txt")) {
			warning("Can't find credits.txt");

			free(logoData);
			return;
		}
	} else {
		if (!f.open("credits.clu")) {
			warning("Can't find credits.clu");

			free(logoData);
			return;
		}
	}

	while (1) {
		char buffer[80];
		char *line = f.readLine(buffer, sizeof(buffer));

		if (line) {
			// Replace invalid character codes prevent the 'dud'
			// symbol from showing up in the credits.

			for (byte *ptr = (byte *)line; *ptr; ptr++) {
				switch (*ptr) {
				case 9:
					// The German credits contain these.
					// Convert them to spaces.
					*ptr = 32;
					break;
				case 10:
					// LF is treated as end of line.
					*ptr = 0;
					break;
				case 170:
					// The Spanish credits contain these.
					// Convert them to periods.
					*ptr = '.';
				default:
					break;
				}
			}
		}

		if (!line || *line == 0) {
			if (!hasCenterMark) {
				for (i = paragraphStart; i < lineCount; i++)
					creditsLines[i]->type = LINE_CENTER;
			}
			paragraphStart = lineCount;
			hasCenterMark = false;
			if (paragraphStart == lineCount)
				lineTop += CREDITS_LINE_SPACING;

			if (!line)
				break;

			continue;
		}

		char *center_mark = strchr(line, '^');

		if (center_mark) {
			// The current paragraph has at least one center mark.
			hasCenterMark = true;

			if (center_mark != line) {
				creditsLines.push_back(new CreditsLine);

				// The center mark is somewhere inside the
				// line. Split it into left and right side.
				*center_mark = 0;

				creditsLines[lineCount]->top = lineTop;
				creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
				creditsLines[lineCount]->type = LINE_LEFT;
				creditsLines[lineCount]->str = strdup(line);

				lineCount++;
				*center_mark = '^';
			}

			line = center_mark;
		}

		creditsLines.push_back(new CreditsLine);

		creditsLines[lineCount]->top = lineTop;

		if (*line == '^') {
			creditsLines[lineCount]->type = LINE_RIGHT;
			line++;
		} else
			creditsLines[lineCount]->type = LINE_LEFT;

		if (strcmp(line, "@") == 0) {
			creditsLines[lineCount]->height = logoHeight;
			lineTop += logoHeight;
		} else {
			creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
			lineTop += CREDITS_LINE_SPACING;
		}

		creditsLines[lineCount]->str = strdup(line);
		lineCount++;
	}

	f.close();

	// We could easily add some ScummVM stuff to the credits, if we wanted
	// to. On the other hand, anyone with the attention span to actually
	// read all the credits probably already knows. :-)

	// Start the music and roll the credits

	// The credits music (which can also be heard briefly in the "carib"
	// cutscene) is played once.

	_vm->_sound->streamCompMusic(309, false);

	clearScene();
	fadeUp(0);

	spriteInfo.scale = 0;
	spriteInfo.scaledWidth = 0;
	spriteInfo.scaledHeight = 0;
	spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
	spriteInfo.blend = 0;

	int startLine = 0;
	int scrollPos = 0;

	bool abortCredits = false;

	int scrollSteps = lineTop + CREDITS_FONT_HEIGHT;
	uint32 musicStart = getTick();

	// Ideally the music should last just a tiny bit longer than the
	// credits. Note that musicTimeRemaining() will return 0 if the music
	// is muted, so we need a sensible fallback for that case.

	uint32 musicLength = MAX((int32)(1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32)scrollSteps);

	while (scrollPos < scrollSteps && !_vm->shouldQuit()) {
		clearScene();

		for (i = startLine; i < lineCount; i++) {
			if (!creditsLines[i])
				continue;

			// Free any sprites that have scrolled off the screen

			if (creditsLines[i]->top + creditsLines[i]->height < scrollPos) {
				debug(2, "Freeing line %d: '%s'", i, creditsLines[i]->str);

				delete creditsLines[i];
				creditsLines[i] = NULL;

				startLine = i + 1;
			} else if (creditsLines[i]->top < scrollPos + 400) {
				if (!creditsLines[i]->sprite) {
					debug(2, "Creating line %d: '%s'", i, creditsLines[i]->str);
					creditsLines[i]->sprite = _vm->_fontRenderer->makeTextSprite((byte *)creditsLines[i]->str, 600, 14, _vm->_speechFontId, 0);
				}

				FrameHeader frame;

				frame.read(creditsLines[i]->sprite);

				spriteInfo.y = creditsLines[i]->top - scrollPos;
				spriteInfo.w = frame.width;
				spriteInfo.h = frame.height;
				spriteInfo.data = creditsLines[i]->sprite + FrameHeader::size();
				spriteInfo.isText = true;

				switch (creditsLines[i]->type) {
				case LINE_LEFT:
					spriteInfo.x = RENDERWIDE / 2 - 5 - frame.width;
					break;
				case LINE_RIGHT:
					spriteInfo.x = RENDERWIDE / 2 + 5;
					break;
				case LINE_CENTER:
					if (strcmp(creditsLines[i]->str, "@") == 0) {
						spriteInfo.data = logoData;
						spriteInfo.x = (RENDERWIDE - logoWidth) / 2;
						spriteInfo.w = logoWidth;
						spriteInfo.h = logoHeight;
					} else
						spriteInfo.x = (RENDERWIDE - frame.width) / 2;
					break;
				}

				if (spriteInfo.data)
					drawSprite(&spriteInfo);
			} else
				break;
		}

		updateDisplay();

		KeyboardEvent *ke = _vm->keyboardEvent();

		if (ke && ke->kbd.keycode == Common::KEYCODE_ESCAPE) {
			if (!abortCredits) {
				abortCredits = true;
				fadeDown();
			}
		}

		if (abortCredits && getFadeStatus() == RDFADE_BLACK)
			break;

		_vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps + _pauseTicks);
		scrollPos++;
	}

	// We're done. Clean up and try to put everything back where it was
	// before the credits.

	for (i = 0; i < lineCount; i++) {
		delete creditsLines[i];
	}

	free(logoData);

	if (!abortCredits) {
		fadeDown();

		// The music should either have stopped or be about to stop, so
		// wait for it to really happen.

		while (_vm->_sound->musicTimeRemaining() && !_vm->shouldQuit()) {
			updateDisplay(false);
			_vm->_system->delayMillis(100);
		}
	}

	if (_vm->shouldQuit())
		return;

	waitForFade();

	_vm->_sound->muteFx(false);
	_vm->_sound->muteSpeech(false);

	if (loopingMusicId)
		_vm->_sound->streamCompMusic(loopingMusicId, true);
	else
		_vm->_sound->stopMusic(false);

	if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing())
		_vm->_mouse->setMouse(NORMAL_MOUSE_ID);

	if (_vm->_logic->readVar(DEAD))
		_vm->_mouse->buildSystemMenu();
}
Esempio n. 7
0
void Screen::displayMsg(byte *text, int time) {
	byte pal[256 * 3];
	byte oldPal[256 * 3];

	debug(2, "DisplayMsg: %s", text);

	if (getFadeStatus() != RDFADE_BLACK) {
		fadeDown();
		waitForFade();
	}

	_vm->_mouse->setMouse(0);
	_vm->_mouse->setLuggage(0);
	_vm->_mouse->closeMenuImmediately();

	clearScene();

	byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId);

	FrameHeader frame;

	frame.read(text_spr);

	SpriteInfo spriteInfo;

	spriteInfo.x = _screenWide / 2 - frame.width / 2;
	if (!time)
		spriteInfo.y = _screenDeep / 2 - frame.height / 2 - MENUDEEP;
	else
		spriteInfo.y = 400 - frame.height;
	spriteInfo.w = frame.width;
	spriteInfo.h = frame.height;
	spriteInfo.scale = 0;
	spriteInfo.scaledWidth = 0;
	spriteInfo.scaledHeight	= 0;
	spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
	spriteInfo.blend = 0;
	spriteInfo.data = text_spr + FrameHeader::size();
	spriteInfo.colourTable = 0;
	spriteInfo.isText = true;

	uint32 rv = drawSprite(&spriteInfo);
	if (rv)
		error("Driver Error %.8x (in DisplayMsg)", rv);

	memcpy(oldPal, _palette, sizeof(oldPal));
	memset(pal, 0, sizeof(pal));

	pal[187 * 3 + 0] = 255;
	pal[187 * 3 + 1] = 255;
	pal[187 * 3 + 2] = 255;

	setPalette(0, 256, pal, RDPAL_FADE);
	fadeUp();
	free(text_spr);
	waitForFade();

	if (time > 0) {
		uint32 targetTime = _vm->_system->getMillis() + (time * 1000);
		_vm->sleepUntil(targetTime);
	} else {
		while (!_vm->shouldQuit()) {
			MouseEvent *me = _vm->mouseEvent();
			if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)))
				break;

			if (_vm->keyboardEvent())
				break;

			updateDisplay();
			_vm->_system->delayMillis(50);
		}
	}

	fadeDown();
	waitForFade();
	clearScene();
	setPalette(0, 256, oldPal, RDPAL_FADE);
	fadeUp();
}
Esempio n. 8
0
bool NoiseSockets::InitNoiseDataFromFile(char *filename)
{
	int i;

	if(p_noise_data_buf!=NULL)
	{
		delete [] p_noise_data_buf;
		p_noise_data_buf=NULL;
	}

	// Seed the rand() with 12 a.m. today
	CTime now=CTime::GetCurrentTime();
	CTime today(now.GetYear(),now.GetMonth(),now.GetDay(),0,0,0);	// 12 a.m. today
	srand((unsigned int)today.GetTime());

	p_noise_data_buf=new unsigned char[NOISE_DATA_LEN+NOISE_BUFFER_LEN];
	memset(p_noise_data_buf,0,NOISE_DATA_LEN+NOISE_BUFFER_LEN);
	
	CFile file;
	if(file.Open(filename,CFile::modeRead|CFile::typeBinary|CFile::shareDenyWrite)==NULL)
	{
		return false;
	}

	// Seek past the zeros to find the first frame
	unsigned int first_frame_index=0;
	while(1)
	{
		char c;
		file.Read(&c,1);
		if(c==0)
		{
			first_frame_index++;
		}
		else
		{
			break;
		}
	}

	// Position the file pointer at the first frame
	file.Seek(first_frame_index,CFile::begin);

	FrameHeader hdr;

	unsigned int offset=0;
	unsigned int num_read=0;

	while(1)
	{
		// Check to see if a frame header will go beyond the buffer
		if((NOISE_DATA_LEN-offset)<sizeof(FrameHeader))
		{
			break;
		}

		num_read=file.Read(&hdr,sizeof(FrameHeader));

		// if EOF, reset file
		if(num_read!=sizeof(FrameHeader))
		{
			file.Seek(first_frame_index,CFile::begin);
			file.Read(&hdr,sizeof(FrameHeader));
		}

		if(hdr.IsValid()==false)
		{
			return false;
		}

		unsigned int frame_len=hdr.ReturnFrameSize();

		// Check to see if this frame will go beyond the buffer
		if((NOISE_DATA_LEN-offset)<frame_len)
		{
			break;
		}

		memcpy(&p_noise_data_buf[offset],&hdr,sizeof(FrameHeader));
		offset+=sizeof(FrameHeader);

		num_read=file.Read(&p_noise_data_buf[offset],frame_len-sizeof(FrameHeader));
		
		// Make sure that all of the frame data is there
		if(num_read!=(frame_len-sizeof(FrameHeader)))
		{
			return false;
		}

		offset+=frame_len-sizeof(FrameHeader);
	}

	// Init remainder of dookie
	for(i=offset;i<NOISE_DATA_LEN;i++)
	{
		p_noise_data_buf[i]=rand()%256;
	}

	// Copy out the buffer padding
	memcpy(&p_noise_data_buf[NOISE_DATA_LEN],&p_noise_data_buf[0],NOISE_BUFFER_LEN);

	return true;
}