Beispiel #1
0
static void D_Display(void)
{
	boolean forcerefresh = false;
	static boolean wipe = false;
	INT32 wipedefindex = 0;

	if (dedicated)
		return;

	if (nodrawers)
		return; // for comparative timing/profiling

	// check for change of screen size (video mode)
	if (setmodeneeded && !wipe)
		SCR_SetMode(); // change video mode

	if (vid.recalc)
		SCR_Recalc(); // NOTE! setsizeneeded is set by SCR_Recalc()

	// change the view size if needed
	if (setsizeneeded)
	{
		R_ExecuteSetViewSize();
		forcerefresh = true; // force background redraw
	}

	// draw buffered stuff to screen
	// Used only by linux GGI version
	I_UpdateNoBlit();

	// save the current screen if about to wipe
	wipe = (gamestate != wipegamestate);
	if (wipe)
	{
		// set for all later
		wipedefindex = gamestate; // wipe_xxx_toblack
		if (gamestate == GS_INTERMISSION)
		{
			if (intertype == int_spec) // Special Stage
				wipedefindex = wipe_specinter_toblack;
			else if (intertype != int_coop) // Multiplayer
				wipedefindex = wipe_multinter_toblack;
		}

		if (rendermode != render_none)
		{
			// Fade to black first
			if (gamestate != GS_LEVEL // fades to black on its own timing, always
			 && wipedefs[wipedefindex] != UINT8_MAX)
			{
				F_WipeStartScreen();
				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
				F_WipeEndScreen();
				F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
			}

			F_WipeStartScreen();
		}
	}

	// do buffered drawing
	switch (gamestate)
	{
		case GS_LEVEL:
			if (!gametic)
				break;
			HU_Erase();
			if (automapactive)
				AM_Drawer();
			break;

		case GS_INTERMISSION:
			Y_IntermissionDrawer();
			HU_Erase();
			HU_Drawer();
			break;

		case GS_TIMEATTACK:
			break;

		case GS_INTRO:
			F_IntroDrawer();
			if (wipegamestate == (gamestate_t)-1)
				wipe = true;
			break;

		case GS_CUTSCENE:
			F_CutsceneDrawer();
			HU_Erase();
			HU_Drawer();
			break;

		case GS_GAMEEND:
			F_GameEndDrawer();
			break;

		case GS_EVALUATION:
			F_GameEvaluationDrawer();
			HU_Drawer();
			break;

		case GS_CONTINUING:
			F_ContinueDrawer();
			break;

		case GS_CREDITS:
			F_CreditDrawer();
			HU_Erase();
			HU_Drawer();
			break;

		case GS_TITLESCREEN:
			F_TitleScreenDrawer();
			break;

		case GS_WAITINGPLAYERS:
			// The clientconnect drawer is independent...
		case GS_DEDICATEDSERVER:
		case GS_NULL:
			break;
	}

	// clean up border stuff
	// see if the border needs to be initially drawn
	if (gamestate == GS_LEVEL)
	{
		// draw the view directly
		if (!automapactive && !dedicated && cv_renderview.value)
		{
			if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
			{
				topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
				objectsdrawn = 0;
#ifdef HWRENDER
				if (rendermode != render_soft)
					HWR_RenderPlayerView(0, &players[displayplayer]);
				else
#endif
				if (rendermode != render_none)
					R_RenderPlayerView(&players[displayplayer]);
			}

			// render the second screen
			if (splitscreen && players[secondarydisplayplayer].mo)
			{
#ifdef HWRENDER
				if (rendermode != render_soft)
					HWR_RenderPlayerView(1, &players[secondarydisplayplayer]);
				else
#endif
				if (rendermode != render_none)
				{
					viewwindowy = vid.height / 2;
					M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));

					topleft = screens[0] + viewwindowy*vid.width + viewwindowx;

					R_RenderPlayerView(&players[secondarydisplayplayer]);

					viewwindowy = 0;
					M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
				}
			}

			// Image postprocessing effect
			if (postimgtype)
				V_DoPostProcessor(0, postimgtype, postimgparam);
			if (postimgtype2)
				V_DoPostProcessor(1, postimgtype2, postimgparam2);
		}

		if (lastdraw)
		{
			if (rendermode == render_soft)
			{
				VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
				usebuffer = true;
			}
			lastdraw = false;
		}

		ST_Drawer();

		HU_Drawer();
	}

	// change gamma if needed
	// (GS_LEVEL handles this already due to level-specific palettes)
	if (forcerefresh && gamestate != GS_LEVEL)
		V_SetPalette(0);

	wipegamestate = gamestate;

	// draw pause pic
	if (paused && cv_showhud.value && (!menuactive || netgame))
	{
		INT32 py;
		patch_t *patch;
		if (automapactive)
			py = 4;
		else
			py = viewwindowy + 4;
		patch = W_CachePatchName("M_PAUSE", PU_CACHE);
		V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - SHORT(patch->width))/2, py, 0, patch);
	}

	// vid size change is now finished if it was on...
	vid.recalc = 0;

	// FIXME: draw either console or menu, not the two
	if (gamestate != GS_TIMEATTACK)
		CON_Drawer();

	M_Drawer(); // menu is drawn even on top of everything
	// focus lost moved to M_Drawer

	//
	// wipe update
	//
	if (wipe)
	{
		// note: moved up here because NetUpdate does input changes
		// and input during wipe tends to mess things up
		wipedefindex += WIPEFINALSHIFT;

		if (rendermode != render_none)
		{
			F_WipeEndScreen();
			F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
		}
	}

	NetUpdate(); // send out any new accumulation

	// It's safe to end the game now.
	if (G_GetExitGameFlag())
	{
		Command_ExitGame_f();
		G_ClearExitGameFlag();
	}

	//
	// normal update
	//
	if (!wipe)
	{
		if (cv_netstat.value)
		{
			char s[50];
			Net_GetNetStat();

			s[sizeof s - 1] = '\0';

			snprintf(s, sizeof s - 1, "get %d b/s", getbps);
			V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-40, V_YELLOWMAP, s);
			snprintf(s, sizeof s - 1, "send %d b/s", sendbps);
			V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-30, V_YELLOWMAP, s);
			snprintf(s, sizeof s - 1, "GameMiss %.2f%%", gamelostpercent);
			V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-20, V_YELLOWMAP, s);
			snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent);
			V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
		}

		I_FinishUpdate(); // page flip or blit buffer
	}
}
Beispiel #2
0
/** Copies data to the end of a variable size buffer.
  *
  * \param buf    The buffer.
  * \param data   The data to copy.
  * \param length The length of the data.
  * \sa VS_Print
  */
void VS_Write(vsbuf_t *buf, const void *data, size_t length)
{
	M_Memcpy(VS_GetSpace(buf, length), data, length);
}
Beispiel #3
0
vector_t *FV_Copy(vector_t *a_o, const vector_t *a_i)
{
	return M_Memcpy(a_o, a_i, sizeof(vector_t));
}
Beispiel #4
0
static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
{
	char *texturesToken;
	size_t texturesTokenLength;
	char *endPos;
	char *patchName = NULL;
	INT16 patchXPos;
	INT16 patchYPos;
	texpatch_t *resultPatch = NULL;
	lumpnum_t patchLumpNum;

	// Patch identifier
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch name should be");
	}
	texturesTokenLength = strlen(texturesToken);
	if (texturesTokenLength>8)
	{
		I_Error("Error parsing TEXTURES lump: Patch name \"%s\" exceeds 8 characters",texturesToken);
	}
	else
	{
		if (patchName != NULL)
		{
			Z_Free(patchName);
		}
		patchName = (char *)Z_Malloc((texturesTokenLength+1)*sizeof(char),PU_STATIC,NULL);
		M_Memcpy(patchName,texturesToken,texturesTokenLength*sizeof(char));
		patchName[texturesTokenLength] = '\0';
	}

	// Comma 1
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName);
	}
	if (strcmp(texturesToken,",")!=0)
	{
		I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken);
	}

	// XPos
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s x coordinate should be",patchName);
	}
	endPos = NULL;
#ifndef AVOID_ERRNO
	errno = 0;
#endif
	patchXPos = strtol(texturesToken,&endPos,10);
	(void)patchXPos; //unused for now
	if (endPos == texturesToken // Empty string
		|| *endPos != '\0' // Not end of string
#ifndef AVOID_ERRNO
		|| errno == ERANGE // Number out-of-range
#endif
		)
	{
		I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken);
	}

	// Comma 2
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName);
	}
	if (strcmp(texturesToken,",")!=0)
	{
		I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken);
	}

	// YPos
	Z_Free(texturesToken);
	texturesToken = M_GetToken(NULL);
	if (texturesToken == NULL)
	{
		I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s y coordinate should be",patchName);
	}
	endPos = NULL;
#ifndef AVOID_ERRNO
	errno = 0;
#endif
	patchYPos = strtol(texturesToken,&endPos,10);
	(void)patchYPos; //unused for now
	if (endPos == texturesToken // Empty string
		|| *endPos != '\0' // Not end of string
#ifndef AVOID_ERRNO
		|| errno == ERANGE // Number out-of-range
#endif
		)
	{
		I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s y coordinate, got \"%s\"",patchName,texturesToken);
	}
	Z_Free(texturesToken);

	if (actuallyLoadPatch == true)
	{
		// Check lump exists
		patchLumpNum = W_GetNumForName(patchName);
		// If so, allocate memory for texpatch_t and fill 'er up
		resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL);
		resultPatch->originx = patchXPos;
		resultPatch->originy = patchYPos;
		resultPatch->lump = patchLumpNum & 65535;
		resultPatch->wad = patchLumpNum>>16;
		// Clean up a little after ourselves
		Z_Free(patchName);
		// Then return it
		return resultPatch;
	}
Beispiel #5
0
/** Flushes (executes) console commands in the buffer.
  */
void COM_BufExecute(void)
{
	size_t i;
	char *ptext;
	char line[1024] = "";
	INT32 quotes;

	if (com_wait)
	{
		com_wait--;
		return;
	}

	while (com_text.cursize)
	{
		// find a '\n' or; line break
		ptext = (char *)com_text.data;

		quotes = 0;
		for (i = 0; i < com_text.cursize; i++)
		{
			if (ptext[i] == '\"' && !quotes && i > 0 && ptext[i-1] != ' ') // Malformed command
				break;
			if (ptext[i] == '\"')
				quotes++;
			if (!(quotes & 1) && ptext[i] == ';')
				break; // don't break if inside a quoted string
			if (ptext[i] == '\n' || ptext[i] == '\r')
				break;
		}

		M_Memcpy(line, ptext, i);
		line[i] = 0;

		// flush the command text from the command buffer, _BEFORE_
		// executing, to avoid that 'recursive' aliases overflow the
		// command text buffer, in that case, new commands are inserted
		// at the beginning, in place of the actual, so it doesn't
		// overflow
		if (i == com_text.cursize)
			// the last command was just flushed
			com_text.cursize = 0;
		else
		{
			i++;
			com_text.cursize -= i;
			//memcpy(ptext, ptext+i, com_text.cursize); // Use memmove if the memory areas do overlap.
			memmove(ptext, ptext+i, com_text.cursize);
		}

		// execute the command line
		COM_ExecuteString(line);

		// delay following commands if a wait was encountered
		if (com_wait)
		{
			com_wait--;
			break;
		}
	}
}
Beispiel #6
0
//
// R_GenerateTexture
//
// Allocate space for full size texture, either single patch or 'composite'
// Build the full textures from patches.
// The texture caching system is a little more hungry of memory, but has
// been simplified for the sake of highcolor, dynamic ligthing, & speed.
//
// This is not optimised, but it's supposed to be executed only once
// per level, when enough memory is available.
//
static UINT8 *R_GenerateTexture(size_t texnum)
{
	UINT8 *block;
	UINT8 *blocktex;
	texture_t *texture;
	texpatch_t *patch;
	patch_t *realpatch;
	int x, x1, x2, i;
	size_t blocksize;
	column_t *patchcol;
	UINT32 *colofs;

	I_Assert(texnum <= (size_t)numtextures);
	texture = textures[texnum];
	I_Assert(texture != NULL);

	// allocate texture column offset lookup

	// single-patch textures can have holes in them and may be used on
	// 2sided lines so they need to be kept in 'packed' format
	// BUT this is wrong for skies and walls with over 255 pixels,
	// so check if there's holes and if not strip the posts.
	if (texture->patchcount == 1)
	{
		boolean holey = false;
		patch = texture->patches;
		realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);

		// Check the patch for holes.
		if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
			holey = true;
		colofs = (UINT32 *)realpatch->columnofs;
		for (x = 0; x < texture->width && !holey; x++)
		{
			column_t *col = (column_t *)((UINT8 *)realpatch + LONG(colofs[x]));
			INT32 topdelta, prevdelta = -1, y = 0;
			while (col->topdelta != 0xff)
			{
				topdelta = col->topdelta;
				if (topdelta <= prevdelta)
					topdelta += prevdelta;
				prevdelta = topdelta;
				if (topdelta > y)
					break;
				y = topdelta + col->length + 1;
				col = (column_t *)((UINT8 *)col + col->length + 4);
			}
			if (y < texture->height)
				holey = true; // this texture is HOLEy! D:
		}

		// If the patch uses transparency, we have to save it this way.
		if (holey)
		{
			texture->holes = true;
			blocksize = W_LumpLengthPwad(patch->wad, patch->lump);
			block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function
				&texturecache[texnum]);
			M_Memcpy(block, realpatch, blocksize);
			texturememory += blocksize;

			// use the patch's column lookup
			colofs = (UINT32 *)(void *)(block + 8);
			texturecolumnofs[texnum] = colofs;
			blocktex = block;
			for (x = 0; x < texture->width; x++)
				colofs[x] = LONG(LONG(colofs[x]) + 3);
			goto done;
		}

		// Otherwise, do multipatch format.
	}

	// multi-patch textures (or 'composite')
	texture->holes = false;
	blocksize = (texture->width * 4) + (texture->width * texture->height);
	texturememory += blocksize;
	block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]);

	memset(block, 0xF7, blocksize+1); // Transparency hack

	// columns lookup table
	colofs = (UINT32 *)(void *)block;
	texturecolumnofs[texnum] = colofs;

	// texture data after the lookup table
	blocktex = block + (texture->width*4);

	// Composite the columns together.
	for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
	{
		realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
		x1 = patch->originx;
		x2 = x1 + SHORT(realpatch->width);

		if (x1 < 0)
			x = 0;
		else
			x = x1;

		if (x2 > texture->width)
			x2 = texture->width;

		for (; x < x2; x++)
		{
			patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1]));

			// generate column ofset lookup
			colofs[x] = LONG((x * texture->height) + (texture->width*4));
			R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height);
		}
	}

done:
	// Now that the texture has been built in column cache, it is purgable from zone memory.
	Z_ChangeTag(block, PU_CACHE);
	return blocktex;
}
Beispiel #7
0
void R_LoadTextures(void)
{
	INT32 i, k, w;
	UINT16 j;
	UINT16 texstart, texend, texturesLumpPos;
	patch_t *patchlump;
	texpatch_t *patch;
	texture_t *texture;

	// Free previous memory before numtextures change.
	if (numtextures)
	{
		for (i = 0; i < numtextures; i++)
		{
			Z_Free(textures[i]);
			Z_Free(texturecache[i]);
		}
		Z_Free(texturetranslation);
		Z_Free(textures);
	}

	// Load patches and textures.

	// Get the number of textures to check.
	// NOTE: Make SURE the system does not process
	// the markers.
	// This system will allocate memory for all duplicate/patched textures even if it never uses them,
	// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
	for (w = 0, numtextures = 0; w < numwadfiles; w++)
	{
		texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
		texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
		texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);

		if (texturesLumpPos != INT16_MAX)
		{
			numtextures += R_CountTexturesInTEXTURESLump((UINT16)w);
		}

		// Add all the textures between TX_START and TX_END
		if (texstart != INT16_MAX && texend != INT16_MAX)
		{
			numtextures += (UINT32)(texend - texstart);
		}

		// If no textures found by this point, bomb out
		if (!numtextures && w == (numwadfiles - 1))
		{
			I_Error("No textures detected in any WADs!\n");
		}
	}

	// Allocate memory and initialize to 0 for all the textures we are initialising.
	// There are actually 5 buffers allocated in one for convenience.
	textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);

	// Allocate texture column offset table.
	texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
	// Allocate texture referencing cache.
	texturecache     = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
	// Allocate texture width mask table.
	texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
	// Allocate texture height mask table.
	textureheight    = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
	// Create translation table for global animation.
	texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);

	for (i = 0; i < numtextures; i++)
		texturetranslation[i] = i;

	for (i = 0, w = 0; w < numwadfiles; w++)
	{
		// Get the lump numbers for the markers in the WAD, if they exist.
		texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
		texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
		texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);

		if (texturesLumpPos != INT16_MAX)
			R_ParseTEXTURESLump(w,&i);

		if (texstart == INT16_MAX || texend == INT16_MAX)
			continue;

		// Work through each lump between the markers in the WAD.
		for (j = 0; j < (texend - texstart); i++, j++)
		{
			patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);

			// Then, check the lump directly to see if it's a texture SOC,
			// and if it is, load it using dehacked instead.
			if (strstr((const char *)patchlump, "TEXTURE"))
			{
				CONS_Alert(CONS_WARNING, "%s is a Texture SOC.\n", W_CheckNameForNumPwad((UINT16)w,texstart+j));
				Z_Unlock(patchlump);
				DEH_LoadDehackedLumpPwad((UINT16)w, texstart + j);
			}
			else
			{
				UINT16 patchcount = 1;
				//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
				if (SHORT(patchlump->width) == 64
				&& SHORT(patchlump->height) == 64)
				{ // 64x64 patch
					const column_t *column;
					for (k = 0; k < SHORT(patchlump->width); k++)
					{ // Find use of transparency.
						column = (const column_t *)((const UINT8 *)patchlump + LONG(patchlump->columnofs[k]));
						if (column->length != SHORT(patchlump->height))
							break;
					}
					if (k == SHORT(patchlump->width))
						patchcount = 2; // No transparency? 64x128 texture.
				}
				texture = textures[i] = Z_Calloc(sizeof(texture_t) + (sizeof(texpatch_t) * patchcount), PU_STATIC, NULL);

				// Set texture properties.
				M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
				texture->width = SHORT(patchlump->width);
				texture->height = SHORT(patchlump->height)*patchcount;
				texture->patchcount = patchcount;
				texture->holes = false;

				// Allocate information for the texture's patches.
				for (k = 0; k < patchcount; k++)
				{
					patch = &texture->patches[k];

					patch->originx = 0;
					patch->originy = (INT16)(k*patchlump->height);
					patch->wad = (UINT16)w;
					patch->lump = texstart + j;
				}

				Z_Unlock(patchlump);

				k = 1;
				while (k << 1 <= texture->width)
					k <<= 1;

				texturewidthmask[i] = k - 1;
				textureheight[i] = texture->height << FRACBITS;
			}
		}
	}
}
Beispiel #8
0
size_t
lzf_decompress (const void *const in_data,  size_t in_len,
                void             *out_data, size_t out_len)
{
	u8 const *ip = (const u8 *)in_data;
	u8       *op = (u8 *)out_data;
	u8 const *const in_end  = ip + in_len;
	u8       *const out_end = op + out_len;

	do
	{
		unsigned int ctrl = *ip++;

		if (ctrl < (1 << 5)) /* literal run */
		{
			ctrl++;

			if (op + ctrl > out_end)
			{
				SET_ERRNO (E2BIG);
				return 0;
			}

#if CHECK_INPUT
			if (ip + ctrl > in_end)
			{
				SET_ERRNO (EINVAL);
				return 0;
			}
#endif

#if USE_MEMCPY
			M_Memcpy (op, ip, ctrl);
			op += ctrl;
			ip += ctrl;
#else
			do
				*op++ = *ip++;
			while (--ctrl);
#endif
		}
		else /* back reference */
		{
			unsigned int len = ctrl >> 5;

			u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;

#if CHECK_INPUT
			if (ip >= in_end)
			{
				SET_ERRNO (EINVAL);
				return 0;
			}
#endif
			if (len == 7)
			{
				len += *ip++;
#if CHECK_INPUT
				if (ip >= in_end)
				{
					SET_ERRNO (EINVAL);
					return 0;
				}
#endif
			}

			ref -= *ip++;

			if (op + len + 2 > out_end)
			{
				SET_ERRNO (E2BIG);
				return 0;
			}

			if (ref < (u8 *)out_data)
			{
				SET_ERRNO (EINVAL);
				return 0;
			}

			*op++ = *ref++;
			*op++ = *ref++;

			do
				*op++ = *ref++;
			while (--len);
		}
	}
	while (ip < in_end);

	return op - (u8 *)out_data;
}
Beispiel #9
0
//
// HGetPacket
// Returns false if no packet is waiting
// Check Datalength and checksum
//
boolean HGetPacket(void)
{
	// get a packet from self
	if (rebound_tail != rebound_head)
	{
		M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]);
		doomcom->datalength = reboundsize[rebound_tail];
		if (netbuffer->packettype == PT_NODETIMEOUT)
			doomcom->remotenode = netbuffer->u.textcmd[0];
		else
			doomcom->remotenode = 0;

		rebound_tail = (rebound_tail+1) % MAXREBOUND;
#ifdef DEBUGFILE
		if (debugfile)
			DebugPrintpacket("GETLOCAL");
#endif
		return true;
	}

	if (!netgame)
		return false;

	while(true)
	{
		I_NetGet();

		if (doomcom->remotenode == -1)
			return false;

		getbytes += packetheaderlength + doomcom->datalength; // for stat

		if (doomcom->remotenode >= MAXNETNODES)
		{
			DEBFILE(va("receive packet from node %d !\n", doomcom->remotenode));
			continue;
		}

		nodes[doomcom->remotenode].lasttimepacketreceived = I_GetTime();

		if (netbuffer->checksum != NetbufferChecksum())
		{
			DEBFILE("Bad packet checksum\n");
			if (I_Shun)
				I_Shun(doomcom->remotenode);
			Net_CloseConnection(doomcom->remotenode);
			continue;
		}

#ifdef DEBUGFILE
		if (debugfile)
			DebugPrintpacket("GET");
#endif

		// proceed the ack and ackreturn field
		if (!Processackpak())
			continue; // discarded (duplicated)

		// a packet with just ackreturn
		if (netbuffer->packettype == PT_NOTHING)
		{
			GotAcks();
			continue;
		}
	break;
	}

	return true;
}
Beispiel #10
0
//
// HSendPacket
//
boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength)
{
	doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE);
	if (node == 0) // packet is to go back to us
	{
		if ((rebound_head+1) % MAXREBOUND == rebound_tail)
		{
#ifdef PARANOIA
			CONS_Printf("No more rebound buf\n");
#endif
			return false;
		}
		M_Memcpy(&reboundstore[rebound_head], netbuffer,
			doomcom->datalength);
		reboundsize[rebound_head] = doomcom->datalength;
		rebound_head = (rebound_head+1) % MAXREBOUND;
#ifdef DEBUGFILE
		if (debugfile)
		{
			doomcom->remotenode = (INT16)node;
			DebugPrintpacket("SENDLOCAL");
		}
#endif
		return true;
	}

	if (!netgame)
		I_Error("Tried to transmit to another node");

	// do this before GetFreeAcknum because this function backup
	// the current packet
	doomcom->remotenode = (INT16)node;
	if (doomcom->datalength <= 0)
	{
		DEBFILE("HSendPacket: nothing to send\n");
#ifdef DEBUGFILE
		if (debugfile)
			DebugPrintpacket("TRISEND");
#endif
		return false;
	}

	if (node < MAXNETNODES) // can be a broadcast
		netbuffer->ackreturn = GetAcktosend(node);
	else
		netbuffer->ackreturn = 0;
	if (reliable)
	{
		if (I_NetCanSend && !I_NetCanSend())
		{
			if (netbuffer->packettype < PT_CANFAIL)
				GetFreeAcknum(&netbuffer->ack, true);

			DEBFILE("HSendPacket: Out of bandwidth\n");
			return false;
		}
		else if (!GetFreeAcknum(&netbuffer->ack, false))
			return false;
	}
	else
		netbuffer->ack = acknum;

	netbuffer->checksum = NetbufferChecksum();
	sendbytes += packetheaderlength + doomcom->datalength; // for stat

	// simulate internet :)
	if (true || rand()<(INT32)RAND_MAX/5)
	{
#ifdef DEBUGFILE
		if (debugfile)
			DebugPrintpacket("SEND");
#endif
		I_NetSend();
	}
#ifdef DEBUGFILE
	else if (debugfile)
		DebugPrintpacket("NOTSEND");
#endif
	return true;
}
Beispiel #11
0
// send special packet with only ack on it
void Net_SendAcks(INT32 node)
{
	netbuffer->packettype = PT_NOTHING;
	M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND);
	HSendPacket(node, false, 0, MAXACKTOSEND);
}
Beispiel #12
0
// poly : the convex polygon that encloses all child subsectors
static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *bbox)
{
	node_t *bsp;
	poly_t *backpoly, *frontpoly;
	fdivline_t fdivline;
	polyvertex_t *pt;
	INT32 i;

	// Found a subsector?
	if (bspnum & NF_SUBSECTOR)
	{
		if (bspnum == -1)
		{
			// BP: i think this code is useless and wrong because
			// - bspnum==-1 happens only when numsubsectors == 0
			// - it can't happens in bsp recursive call since bspnum is a INT32 and children is UINT16
			// - the BSP is complet !! (there just can have subsector without segs) (i am not sure of this point)

			// do we have a valid polygon ?
			if (poly && poly->numpts > 2)
			{
				DEBPRINT("Adding a new subsector\n");
				if (addsubsector == numsubsectors + NEWSUBSECTORS)
					I_Error("WalkBSPNode: not enough addsubsectors\n");
				else if (addsubsector > 0x7fff)
					I_Error("WalkBSPNode: addsubsector > 0x7fff\n");
				*leafnode = (UINT16)((UINT16)addsubsector | NF_SUBSECTOR);
				extrasubsectors[addsubsector].planepoly = poly;
				addsubsector++;
			}

			//add subsectors without segs here?
			//HWR_SubsecPoly(0, NULL);
		}
		else
		{
			HWR_SubsecPoly(bspnum&(~NF_SUBSECTOR), poly);
			//Hurdler: implement a loading status

			if (ls_count-- <= 0)
			{
				char s[16];
				int x, y;

				I_OsPolling();
				ls_count = numsubsectors/50;
				CON_Drawer();
				sprintf(s, "%d%%", (++ls_percent)<<1);
				x = BASEVIDWIDTH/2;
				y = BASEVIDHEIGHT/2;
				V_DrawFill(0, 0, vid.width, vid.height, 31); // Black background to match fade in effect
				//V_DrawPatchFill(W_CachePatchName("SRB2BACK",PU_CACHE)); // SRB2 background, ehhh too bright.
				M_DrawTextBox(x-58, y-8, 13, 1);
				V_DrawString(x-50, y, V_YELLOWMAP, "Loading...");
				V_DrawString(x+50-V_StringWidth(s), y, V_YELLOWMAP, s);

				// Is this really necessary at this point..?
				V_DrawCenteredString(BASEVIDWIDTH/2, 40, V_YELLOWMAP, "OPENGL MODE IS INCOMPLETE AND MAY");
				V_DrawCenteredString(BASEVIDWIDTH/2, 50, V_YELLOWMAP, "NOT DISPLAY SOME SURFACES.");
				V_DrawCenteredString(BASEVIDWIDTH/2, 70, V_YELLOWMAP, "USE AT SONIC'S RISK.");

				I_UpdateNoVsync();
			}
		}
		M_ClearBox(bbox);
		poly = extrasubsectors[bspnum&~NF_SUBSECTOR].planepoly;

		for (i = 0, pt = poly->pts; i < poly->numpts; i++,pt++)
			M_AddToBox(bbox, FLOAT_TO_FIXED(pt->x), FLOAT_TO_FIXED(pt->y));

		return;
	}

	bsp = &nodes[bspnum];
	SearchDivline(bsp, &fdivline);
	SplitPoly(&fdivline, poly, &frontpoly, &backpoly);
	poly = NULL;

	//debug
	if (!backpoly)
		nobackpoly++;

	// Recursively divide front space.
	if (frontpoly)
	{
		WalkBSPNode(bsp->children[0], frontpoly, &bsp->children[0],bsp->bbox[0]);

		// copy child bbox
		M_Memcpy(bbox, bsp->bbox[0], 4*sizeof (fixed_t));
	}
	else
		I_Error("WalkBSPNode: no front poly?");

	// Recursively divide back space.
	if (backpoly)
	{
		// Correct back bbox to include floor/ceiling convex polygon
		WalkBSPNode(bsp->children[1], backpoly, &bsp->children[1],
			bsp->bbox[1]);

		// enlarge bbox with seconde child
		M_AddToBox(bbox, bsp->bbox[1][BOXLEFT  ],
			bsp->bbox[1][BOXTOP   ]);
		M_AddToBox(bbox, bsp->bbox[1][BOXRIGHT ],
			bsp->bbox[1][BOXBOTTOM]);
	}
}