Пример #1
0
static long ovc_tell (void *datasource)
{
	bgTrack_t	*track = (bgTrack_t *)datasource;

#ifdef OGG_DIRECT_FILE
	return ftell(track->file);
#else
	Com_Printf("Calling FS_Tell\n");
	return FS_Tell(track->file);
#endif
}
Пример #2
0
/*
* SCR_PlayCinematic
*/
static void SCR_PlayCinematic( char *arg )
{
	int len;
	size_t name_size;
	static cinematics_t clientCin;
	cinematics_t *cin = cl.cin = &clientCin;
	roq_chunk_t *chunk = &cin->chunk;

	name_size = strlen( "video/" ) + strlen( arg ) + strlen( ".roq" ) + 1;
	cin->name = Mem_ZoneMalloc( name_size );
	Q_snprintfz( cin->name, name_size, "video/%s", arg );
	COM_DefaultExtension( cin->name, ".roq", name_size );

	// nasty hack
	cin->s_rate = 22050;
	cin->s_width = 2;
	cin->width = cin->height = 0;

	cin->frame = 0;
	len = FS_FOpenFile( cin->name, &cin->file, FS_READ );
	if( !cin->file || len < 1 )
	{
		Com_Printf( "Couldn't find %s\n", cin->name );
		SCR_StopCinematic();
		return;
	}

	// read header
	RoQ_ReadChunk( cin );

	if( chunk->id != RoQ_HEADER1 || chunk->size != RoQ_HEADER2 || chunk->argument != RoQ_HEADER3 )
	{
		Com_Printf( "Invalid video file %s\n", cin->name );
		SCR_StopCinematic();
		return;
	}

	SCR_EndLoadingPlaque();

	cin->headerlen = FS_Tell( cin->file );
	cin->frame = 0;
	cin->pic = cin->pic_pending = SCR_ReadNextCinematicFrame();
	cin->time = cls.realtime + 1; // add 1 msec so SCR_GetCinematicTime is also valid for early commands

	CL_SetClientState( CA_ACTIVE );

	CL_SoundModule_StopAllSounds();
}
Пример #3
0
/*
=================
CL_DrawDemoRecording
=================
*/
void CL_DrawDemoRecording( void )
{
	char		string[64];
	rgba_t		color = { 255, 255, 255, 255 };
	fs_offset_t	pos;
	int		len;

	if(!( host.developer && cls.demorecording ))
		return;

	pos = FS_Tell( cls.demofile );
	Q_snprintf( string, sizeof( string ), "RECORDING %s: %ik", cls.demoname, (int)(pos / 1024) );

	Con_DrawStringLen( string, &len, NULL );
	Con_DrawString(( scr_width->integer - len) >> 1, scr_height->integer >> 2, string, color );
}
Пример #4
0
/*
=================
CL_StopRecord

finish recording demo
=================
*/
void CL_StopRecord( void )
{
	int	i, curpos;
	float	stoptime;

	if( !cls.demorecording ) return;

	// demo playback should read this as an incoming message.
	CL_WriteDemoCmdHeader( dem_stop, cls.demofile );

	stoptime = CL_GetDemoRecordClock();

	// close down the hud for now.
	// g-cont. is this need???
	if( clgame.hInstance ) clgame.dllFuncs.pfnReset();

	curpos = FS_Tell( cls.demofile );
	demo.entry->length = curpos - demo.entry->offset;
	demo.entry->playback_time = stoptime - demo.realstarttime;
	demo.entry->playback_frames = demo.framecount;

	//  Now write out the directory and free it and touch up the demo header.
	FS_Write( cls.demofile, &demo.directory.numentries, sizeof( int ));

	for( i = 0; i < demo.directory.numentries; i++ )
	{
		FS_Write( cls.demofile, &demo.directory.entries[i], sizeof( demoentry_t ));
	}

	Mem_Free( demo.directory.entries );
	demo.directory.numentries = 0;

	demo.header.directory_offset = curpos;
	FS_Seek( cls.demofile, 0, SEEK_SET );
	FS_Write( cls.demofile, &demo.header, sizeof( demo.header ));
	
	FS_Close( cls.demofile );
	cls.demofile = NULL;
	cls.demorecording = false;
	cls.demoname[0] = '\0';
	menu.globals->demoname[0] = '\0';

	Msg( "Completed demo\n" );
	MsgDev( D_INFO, "Recording time %.2f\n", cls.demotime );
	cls.demotime = 0.0;
}
Пример #5
0
/*
====================
CheckPendingDownloads

checks if there are free download slots to start new downloads in.
To not start too many downloads at once, only one download is added at a time,
up to a maximum number of cl_curl_maxdownloads are running.
====================
*/
static void CheckPendingDownloads(void)
{
	const char *h;
	if(!curl_dll)
		return;
	if(numdownloads < cl_curl_maxdownloads.integer)
	{
		downloadinfo *di;
		for(di = downloads; di; di = di->next)
		{
			if(!di->started)
			{
				if(!di->buffer)
				{
					Con_Printf("Downloading %s -> %s", CleanURL(di->url), di->filename);

					di->stream = FS_OpenRealFile(di->filename, "ab", false);
					if(!di->stream)
					{
						Con_Printf("\nFAILED: Could not open output file %s\n", di->filename);
						Curl_EndDownload(di, CURL_DOWNLOAD_FAILED, CURLE_OK);
						return;
					}
					FS_Seek(di->stream, 0, SEEK_END);
					di->startpos = FS_Tell(di->stream);

					if(di->startpos > 0)
						Con_Printf(", resuming from position %ld", (long) di->startpos);
					Con_Print("...\n");
				}
				else
				{
					Con_DPrintf("Downloading %s -> memory\n", CleanURL(di->url));
					di->startpos = 0;
				}

				di->curle = qcurl_easy_init();
				di->slist = NULL;
				qcurl_easy_setopt(di->curle, CURLOPT_URL, di->url);
				qcurl_easy_setopt(di->curle, CURLOPT_USERAGENT, engineversion);
				qcurl_easy_setopt(di->curle, CURLOPT_REFERER, di->referer);
				qcurl_easy_setopt(di->curle, CURLOPT_RESUME_FROM, (long) di->startpos);
				qcurl_easy_setopt(di->curle, CURLOPT_FOLLOWLOCATION, 1);
				qcurl_easy_setopt(di->curle, CURLOPT_WRITEFUNCTION, CURL_fwrite);
				qcurl_easy_setopt(di->curle, CURLOPT_LOW_SPEED_LIMIT, (long) 256);
				qcurl_easy_setopt(di->curle, CURLOPT_LOW_SPEED_TIME, (long) 45);
				qcurl_easy_setopt(di->curle, CURLOPT_WRITEDATA, (void *) di);
				qcurl_easy_setopt(di->curle, CURLOPT_PRIVATE, (void *) di);
				qcurl_easy_setopt(di->curle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP);
				if(qcurl_easy_setopt(di->curle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP) != CURLE_OK)
				{
					Con_Printf("^1WARNING:^7 for security reasons, please upgrade to libcurl 7.19.4 or above. In a later version of DarkPlaces, HTTP redirect support will be disabled for this libcurl version.\n");
					//qcurl_easy_setopt(di->curle, CURLOPT_FOLLOWLOCATION, 0);
				}
				if(di->post_content_type)
				{
					qcurl_easy_setopt(di->curle, CURLOPT_POST, 1);
					qcurl_easy_setopt(di->curle, CURLOPT_POSTFIELDS, di->postbuf);
					qcurl_easy_setopt(di->curle, CURLOPT_POSTFIELDSIZE, di->postbufsize);
					di->slist = qcurl_slist_append(di->slist, va("Content-Type: %s", di->post_content_type));
				}

				// parse extra headers into slist
				// \n separated list!
				h = di->extraheaders;
				while(h)
				{
					const char *hh = strchr(h, '\n');
					if(hh)
					{
						char *buf = (char *) Mem_Alloc(tempmempool, hh - h + 1);
						memcpy(buf, h, hh - h);
						buf[hh - h] = 0;
						di->slist = qcurl_slist_append(di->slist, buf);
						h = hh + 1;
					}
					else
					{
						di->slist = qcurl_slist_append(di->slist, h);
						h = NULL;
					}
				}

				qcurl_easy_setopt(di->curle, CURLOPT_HTTPHEADER, di->slist);

				
				qcurl_multi_add_handle(curlm, di->curle);
				di->started = true;
				++numdownloads;
				if(numdownloads >= cl_curl_maxdownloads.integer)
					break;
			}
		}
	}
}
Пример #6
0
/* <2a121> ../engine/hashpak.c:1060 */
void HPAK_CreatePak(char *pakname, struct resource_s *pResource, void *pData, FileHandle_t fpSource)
{
	char name[MAX_PATH];
	int32 curpos;
	FileHandle_t fp;
	hash_pack_entry_t *pCurrentEntry;

	byte md5[16];
	MD5Context_t ctx;
	byte *pDiskData;

	if ((!fpSource && !pData) || (fpSource && pData))
	{
		Con_Printf("HPAK_CreatePak, must specify one of pData or fpSource\n");
		return;
	}

	Q_snprintf(name, ARRAYSIZE(name), "%s", pakname);
#ifdef REHLDS_FIXES
	name[ARRAYSIZE(name) - 1] = 0;
#endif // REHLDS_FIXES

	COM_DefaultExtension(name, HASHPAK_EXTENSION);
	Con_Printf("Creating HPAK %s.\n", name);

	fp = FS_Open(name, "wb");
	if (!fp)
	{
		Con_Printf("ERROR: couldn't open new .hpk, check access rights to %s.\n", name);
		return;
	}

	Q_memset(&ctx, 0, sizeof(MD5Context_t));
	MD5Init(&ctx);

	if (pData)
		MD5Update(&ctx, (byte *)pData, pResource->nDownloadSize);
	else
	{
		curpos = FS_Tell(fpSource);
		pDiskData = (byte *)Mem_Malloc(pResource->nDownloadSize + 1);
		Q_memset(pDiskData, 0, pResource->nDownloadSize);
		FS_Read(pDiskData, pResource->nDownloadSize, 1, fp);
		FS_Seek(fpSource, curpos, FILESYSTEM_SEEK_HEAD);
		MD5Update(&ctx, pDiskData, pResource->nDownloadSize);
		Mem_Free(pDiskData);
	}

	MD5Final(md5, &ctx);
	if (Q_memcmp(pResource->rgucMD5_hash, md5, sizeof(md5)) != 0)
	{
		Con_Printf("HPAK_CreatePak called with bogus lump, md5 mismatch\n");
		Con_Printf("Purported:  %s\n", MD5_Print(pResource->rgucMD5_hash));
		Con_Printf("Actual   :  %s\n", MD5_Print(md5));
		Con_Printf("Ignoring lump addition\n");
		return;
	}

	Q_memset(&hash_pack_header, 0, sizeof(hash_pack_header_t));
	Q_memcpy(hash_pack_header.szFileStamp, "HPAK", sizeof(hash_pack_header.szFileStamp));

	hash_pack_header.version = HASHPAK_VERSION;
	hash_pack_header.nDirectoryOffset = 0;

	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, fp);
	Q_memset(&hash_pack_dir, 0, sizeof(hash_pack_directory_t));

	hash_pack_dir.nEntries = 1;
	hash_pack_dir.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t));
	Q_memset(hash_pack_dir.p_rgEntries, 0, sizeof(hash_pack_entry_t) * hash_pack_dir.nEntries);

	pCurrentEntry = &hash_pack_dir.p_rgEntries[0];
	Q_memcpy(&pCurrentEntry->resource, pResource, sizeof(resource_t));

	pCurrentEntry->nOffset = FS_Tell(fp);
	pCurrentEntry->nFileLength = pResource->nDownloadSize;

	if (pData)
		FS_Write(pData, pResource->nDownloadSize, 1, fp);

	else COM_CopyFileChunk(fp, fpSource, pResource->nDownloadSize);

	curpos = FS_Tell(fp);
	FS_Write(&hash_pack_dir.nEntries, 4, 1, fp);
	FS_Write(hash_pack_dir.p_rgEntries, sizeof(hash_pack_entry_t), 1, fp);

	if (hash_pack_dir.p_rgEntries)
	{
		Mem_Free(hash_pack_dir.p_rgEntries);
		hash_pack_dir.p_rgEntries = NULL;
	}

	hash_pack_dir.nEntries = 0;
	hash_pack_header.nDirectoryOffset = curpos;

	FS_Seek(fp, 0, FILESYSTEM_SEEK_HEAD);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, fp);
	FS_Close(fp);
}
Пример #7
0
/* <2a974> ../engine/hashpak.c:598 */
void HPAK_RemoveLump(char *pakname, resource_t *pResource)
{
	FileHandle_t fp;
	FileHandle_t tmp;
	char szTempName[MAX_PATH];
	char szOriginalName[MAX_PATH];
	hash_pack_directory_t olddir;
	hash_pack_directory_t newdir;
	hash_pack_entry_t *oldentry;
	hash_pack_entry_t *newentry;
	int n;
	int i;

	if (pakname == NULL || *pakname == '\0' || pResource == NULL)
	{
		Con_Printf(__FUNCTION__ ":  Invalid arguments\n");
		return;
	}
	HPAK_FlushHostQueue();

#ifdef REHLDS_FIXES
	Q_strncpy(szOriginalName, pakname, ARRAYSIZE(szOriginalName) - 1);
	szOriginalName[ARRAYSIZE(szOriginalName) - 1] = 0;
	COM_DefaultExtension(szOriginalName, HASHPAK_EXTENSION);
#else

	//TODO: Not sure why Cmd_Argv(1) is used since function receives pakname parameter
	char name[MAX_PATH];
	Q_snprintf(name, ARRAYSIZE(name), "%s", Cmd_Argv(1));
	COM_DefaultExtension(name, HASHPAK_EXTENSION);
	Q_strncpy(szOriginalName, name, ARRAYSIZE(szOriginalName) - 1);
	szOriginalName[ARRAYSIZE(szOriginalName) - 1] = 0;

#endif // REHLDS_FIXES

	fp = FS_Open(szOriginalName, "rb");
	if (!fp)
	{
		Con_Printf("Error:  couldn't open HPAK file %s for removal.\n", szOriginalName);
		return;
	}
	COM_StripExtension(szOriginalName, szTempName);
	COM_DefaultExtension(szTempName, ".hp2");

	tmp = FS_Open(szTempName, "w+b");
	if (!tmp)
	{
		FS_Close(fp);
		Con_Printf("ERROR: couldn't create %s.\n", szTempName);
		return;
	}	
	FS_Seek(fp, 0, FILESYSTEM_SEEK_HEAD);
	FS_Seek(tmp, 0, FILESYSTEM_SEEK_HEAD);
	FS_Read(&hash_pack_header, sizeof(hash_pack_header_t), 1, fp);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, tmp);
	if (Q_strncmp(hash_pack_header.szFileStamp, "HPAK", sizeof(hash_pack_header.szFileStamp)))
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Con_Printf("%s is not an HPAK file\n", szOriginalName);
		return;
	}
	if (hash_pack_header.version != HASHPAK_VERSION)
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Con_Printf("ERROR: HPAK version outdated\n");
		return;
	}
	FS_Seek(fp, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);
	FS_Read(&olddir.nEntries, 4, 1, fp);
	if (olddir.nEntries < 1 || (unsigned int)olddir.nEntries > MAX_FILE_ENTRIES)
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Con_Printf("ERROR: HPAK had bogus # of directory entries:  %i\n", olddir.nEntries);
		return;
	}
	if (olddir.nEntries == 1)
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szOriginalName);
		FS_Unlink(szTempName);
		Con_Printf("Removing final lump from HPAK, deleting HPAK:\n  %s\n", szOriginalName);
		return;
	}
	olddir.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * olddir.nEntries);
	FS_Read(olddir.p_rgEntries, sizeof(hash_pack_entry_t) * olddir.nEntries, 1, fp);

	newdir.nEntries = olddir.nEntries - 1;
	newdir.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * newdir.nEntries);
	if (!HPAK_FindResource(&olddir, pResource->rgucMD5_hash, NULL))
	{
		FS_Close(fp);
		FS_Close(tmp);
		FS_Unlink(szTempName);
		Mem_Free(olddir.p_rgEntries);
		Mem_Free(newdir.p_rgEntries);

		Con_Printf("ERROR: HPAK doesn't contain specified lump:  %s\n", pResource->szFileName);
		return;
	}
	Con_Printf("Removing %s from HPAK %s.\n", pResource->szFileName, szOriginalName);
	for (i = 0, n = 0; i < olddir.nEntries; i++)
	{
		oldentry = &olddir.p_rgEntries[i];

		if (Q_memcmp(olddir.p_rgEntries[i].resource.rgucMD5_hash, pResource->rgucMD5_hash, 16))
		{
			newentry = &newdir.p_rgEntries[n++];
			Q_memcpy(newentry, oldentry, sizeof(hash_pack_entry_t));
			newentry->nOffset = FS_Tell(tmp);

			FS_Seek(fp, oldentry->nOffset, FILESYSTEM_SEEK_HEAD);
			COM_CopyFileChunk(tmp, fp, newentry->nFileLength);
		}
	}
	hash_pack_header.nDirectoryOffset = FS_Tell(tmp);
	FS_Write(&newdir.nEntries, 4, 1, tmp);
	for (i = 0; i < newdir.nEntries; i++)
		FS_Write(&newdir.p_rgEntries[i], sizeof(hash_pack_entry_t), 1, tmp);

	FS_Seek(tmp, 0, FILESYSTEM_SEEK_HEAD);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, tmp);
	FS_Close(fp);
	FS_Close(tmp);
	FS_Unlink(szOriginalName);
	FS_Rename(szTempName, szOriginalName);
	Mem_Free(olddir.p_rgEntries);
	Mem_Free(newdir.p_rgEntries);
}
Пример #8
0
/* <2a494> ../engine/hashpak.c:322 */
void HPAK_AddLump(qboolean bUseQueue, char *pakname, struct resource_s *pResource, void *pData, FileHandle_t fpSource)
{
	FileHandle_t iRead;
	FileHandle_t iWrite;
	char name[MAX_PATH];
	char szTempName[MAX_PATH];
	char szOriginalName[MAX_PATH];
	hash_pack_directory_t olddirectory;
	hash_pack_directory_t newdirectory;
	hash_pack_entry_t *pNewEntry;

	byte md5[16];
	MD5Context_t ctx;
	byte *pDiskData;

	if (pakname == NULL)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no .pak filename\n");
		return;
	}
	if (!pResource)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no lump to add\n");
		return;
	}
	if (!pData && !fpSource)
	{
		Con_Printf("HPAK_AddLump called with invalid arguments:  no file handle\n");
		return;
	}
	if (pResource->nDownloadSize < 1024 || (unsigned int)pResource->nDownloadSize > MAX_FILE_SIZE)
	{
		Con_Printf("HPAK_AddLump called with bogus lump, size:  %i\n", pResource->nDownloadSize);
		return;
	}
	Q_memset(&ctx, 0, sizeof(MD5Context_t));
	MD5Init(&ctx);
	if (pData)
		MD5Update(&ctx, (byte *)pData, pResource->nDownloadSize);
	else
	{
		pDiskData = (byte *)Mem_Malloc(pResource->nDownloadSize + 1);
		Q_memset(pDiskData, 0, pResource->nDownloadSize);

		FS_Read(pDiskData, pResource->nDownloadSize, 1, fpSource);
		FS_Seek(fpSource, FS_Tell(fpSource), FILESYSTEM_SEEK_HEAD);

		MD5Update(&ctx, pDiskData, pResource->nDownloadSize);
		Mem_Free(pDiskData);
	}
	MD5Final(md5, &ctx);
	if (Q_memcmp(pResource->rgucMD5_hash, md5, sizeof(md5)) != 0)
	{
		Con_Printf("HPAK_AddLump called with bogus lump, md5 mismatch\n");
		Con_Printf("Purported:  %s\n", MD5_Print(pResource->rgucMD5_hash));
		Con_Printf("Actual   :  %s\n", MD5_Print(md5));
		Con_Printf("Ignoring lump addition\n");
		return;
	}
	if (bUseQueue)
	{
		HPAK_AddToQueue(pakname, pResource, pData, fpSource);
		return;
	}

	Q_snprintf(name, ARRAYSIZE(name), "%s", pakname);
#ifdef REHLDS_FIXES
	name[ARRAYSIZE(name) - 1] = 0;
#endif // REHLDS_FIXES

	COM_DefaultExtension(name, HASHPAK_EXTENSION);
	COM_FixSlashes(name);

	Q_strncpy(szOriginalName, name, ARRAYSIZE(szOriginalName) - 1);
	szOriginalName[ARRAYSIZE(szOriginalName) - 1] = 0;


	iRead = FS_Open(name, "rb");

	if (!iRead)
	{
		HPAK_CreatePak(pakname, pResource, pData, fpSource);
		return;
	}

	COM_StripExtension(name, szTempName);
	COM_DefaultExtension(szTempName, ".hp2");

	iWrite = FS_Open(szTempName, "w+b");
	if (!iWrite)
	{
		FS_Close(iRead);
		Con_Printf("ERROR: couldn't open %s.\n", szTempName);
		return;
	}
	FS_Read(&hash_pack_header, sizeof(hash_pack_header_t), 1, iRead);
	if (hash_pack_header.version != HASHPAK_VERSION)
	{
		FS_Close(iRead);
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Con_Printf("Invalid .hpk version in HPAK_AddLump\n");
		return;
	}

	FS_Seek(iRead, 0, FILESYSTEM_SEEK_HEAD);
	COM_CopyFileChunk(iWrite, iRead, FS_Size(iRead));
	FS_Seek(iRead, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);
	FS_Read(&olddirectory.nEntries, 4, 1, iRead);

	if (olddirectory.nEntries < 1 || (unsigned int)olddirectory.nEntries > MAX_FILE_ENTRIES)
	{
		FS_Close(iRead);
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Con_Printf("ERROR: .hpk had bogus # of directory entries:  %i\n", olddirectory.nEntries);
		return;
	}

	olddirectory.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * olddirectory.nEntries);

	FS_Read(olddirectory.p_rgEntries, sizeof(hash_pack_entry_t) * olddirectory.nEntries, 1, iRead);
	FS_Close(iRead);

	if (HPAK_FindResource(&olddirectory, pResource->rgucMD5_hash, NULL) != FALSE)
	{
		FS_Close(iWrite);
		FS_Unlink(szTempName);
		Mem_Free(olddirectory.p_rgEntries);
		return;
	}

	newdirectory.nEntries = olddirectory.nEntries + 1;
	newdirectory.p_rgEntries = (hash_pack_entry_t *)Mem_Malloc(sizeof(hash_pack_entry_t) * newdirectory.nEntries);

	Q_memset(newdirectory.p_rgEntries, 0, sizeof(hash_pack_entry_t) * newdirectory.nEntries);
	Q_memcpy(newdirectory.p_rgEntries, olddirectory.p_rgEntries, sizeof(hash_pack_entry_t) * olddirectory.nEntries);

	pNewEntry = NULL;

	for (int i = 0; i < olddirectory.nEntries; i++)
	{
		if (Q_memcmp(pResource->rgucMD5_hash, olddirectory.p_rgEntries[i].resource.rgucMD5_hash, 16) >= 0)
		{
			pNewEntry = &newdirectory.p_rgEntries[i];
#ifndef REHLDS_FIXES
			while (i < olddirectory.nEntries)
			{
				Q_memcpy(&newdirectory.p_rgEntries[i + 1], &olddirectory.p_rgEntries[i], sizeof(hash_pack_entry_t));
				i++;
			}
#else
			Q_memcpy(&newdirectory.p_rgEntries[i + 1], &olddirectory.p_rgEntries[i], (olddirectory.nEntries - i) * sizeof(hash_pack_entry_t));
#endif
			break;
		}
	}

	if (pNewEntry == NULL)
	{
		pNewEntry = &newdirectory.p_rgEntries[newdirectory.nEntries - 1];
	}

	Q_memset(pNewEntry, 0, sizeof(hash_pack_entry_t));
	FS_Seek(iWrite, hash_pack_header.nDirectoryOffset, FILESYSTEM_SEEK_HEAD);

	Q_memcpy(&pNewEntry->resource, pResource, sizeof(resource_t));

	pNewEntry->nOffset = FS_Tell(iWrite);
	pNewEntry->nFileLength = pResource->nDownloadSize;

	if (pData)
		FS_Write(pData, pResource->nDownloadSize, 1, iWrite);

	else COM_CopyFileChunk(iWrite, fpSource, pResource->nDownloadSize);

	hash_pack_header.nDirectoryOffset = FS_Tell(iWrite);

	FS_Write(&newdirectory.nEntries, 4, 1, iWrite);

	for (int j = 0; j < newdirectory.nEntries; j++)
		FS_Write(&newdirectory.p_rgEntries[j], sizeof(hash_pack_entry_t), 1, iWrite);

	if (newdirectory.p_rgEntries)
		Mem_Free(newdirectory.p_rgEntries);

	if (olddirectory.p_rgEntries)
		Mem_Free(olddirectory.p_rgEntries);

	FS_Seek(iWrite, 0, FILESYSTEM_SEEK_HEAD);
	FS_Write(&hash_pack_header, sizeof(hash_pack_header_t), 1, iWrite);
	FS_Close(iWrite);
	FS_Unlink(szOriginalName);
	FS_Rename(szTempName, szOriginalName);
}
Пример #9
0
/*
=================
CL_DemoReadMessage

reads demo data and write it to client
=================
*/
qboolean CL_DemoReadMessage( byte *buffer, size_t *length )
{
	float	f = 0.0f;
	int	curpos = 0;
	float	fElapsedTime = 0.0f;
	qboolean	swallowmessages = true;
	byte	*userbuf = NULL;
	size_t	size;
	byte	cmd;

	if( !cls.demofile )
	{
		MsgDev( D_ERROR, "tried to read a demo message with no demo file\n" );
		CL_DemoCompleted();
		return false;
	}

	// HACKHACK: changedemo issues
	if( !cls.netchan.remote_address.type )
		cls.netchan.remote_address.type = NA_LOOPBACK;

	if(( !cl.background && ( cl.refdef.paused || cls.key_dest != key_game )) || cls.key_dest == key_console )
	{
		demo.starttime += host.frametime;
		return false; // paused
	}

	do
	{
		qboolean	bSkipMessage = false;

		if( !cls.demofile ) break;
		curpos = FS_Tell( cls.demofile );

		CL_ReadDemoCmdHeader( &cmd, &f );

		fElapsedTime = CL_GetDemoPlaybackClock() - demo.starttime;
		bSkipMessage = (f >= fElapsedTime) ? true : false;

		if( cls.changelevel )
			demo.framecount = 1;

		// HACKHACK: changelevel issues
		if( demo.framecount <= 10 && ( fElapsedTime - f ) > host.frametime )
			demo.starttime = CL_GetDemoPlaybackClock();

		// not ready for a message yet, put it back on the file.
		if( cmd != dem_norewind && cmd != dem_stop && bSkipMessage )
		{
			// never skip first message
			if( demo.framecount != 0 )
			{
				FS_Seek( cls.demofile, curpos, SEEK_SET );
				return false; // not time yet.
			}
		}

		// COMMAND HANDLERS
		switch( cmd )
		{
		case dem_jumptime:
			demo.starttime = CL_GetDemoPlaybackClock();
			break;
		case dem_stop:
			CL_DemoMoveToNextSection();
			break;
		case dem_userdata:
			FS_Read( cls.demofile, &size, sizeof( int ));
			userbuf = Mem_Alloc( cls.mempool, size );
			FS_Read( cls.demofile, userbuf, size );

			if( clgame.hInstance )
				clgame.dllFuncs.pfnDemo_ReadBuffer( size, userbuf );
			Mem_Free( userbuf );
			userbuf = NULL;
			break;
		case dem_usercmd:
			CL_ReadDemoUserCmd( false );
			break;
		default:
			swallowmessages = false;
			break;
		}
	} while( swallowmessages );

	if( !cls.demofile )
		return false;

	// if not on "LOADING" section, check a few things
	if( demo.entryIndex )
	{
		// We are now on the second frame of a new section,
		// if so, reset start time (unless in a timedemo)
		if( demo.framecount == 1 )
		{
			// cheat by moving the relative start time forward.
			demo.starttime = CL_GetDemoPlaybackClock();
		}	
	}

	demo.framecount++;
	CL_ReadDemoSequence( false );

	return CL_ReadRawNetworkData( buffer, length );
}
Пример #10
0
/*
====================
CL_WriteDemoHeader

Write demo header
====================
*/
void CL_WriteDemoHeader( const char *name )
{
	fs_offset_t	copysize;
	fs_offset_t	savepos;
	fs_offset_t	curpos;
	
	MsgDev( D_INFO, "recording to %s.\n", name );
	cls.demofile = FS_Open( name, "wb", false );
	cls.demotime = 0.0;

	if( !cls.demofile )
	{
		MsgDev( D_ERROR, "couldn't open %s.\n", name );
		return;
	}

	cls.demorecording = true;
	cls.demowaiting = true;	// don't start saving messages until a non-delta compressed message is received

	Q_memset( &demo.header, 0, sizeof( demo.header ));

	demo.header.id = IDEMOHEADER;
	demo.header.dem_protocol = DEMO_PROTOCOL;
	demo.header.net_protocol = PROTOCOL_VERSION;
	Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname ));
	Q_strncpy( demo.header.gamedir, FS_Gamedir(), sizeof( demo.header.gamedir ));

	// write header
	FS_Write( cls.demofile, &demo.header, sizeof( demo.header ));

	demo.directory.numentries = 2;
	demo.directory.entries = Mem_Alloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );

	// DIRECTORY ENTRY # 0
	demo.entry = &demo.directory.entries[0];	// only one here.
	demo.entry->entrytype = DEMO_STARTUP;
	demo.entry->playback_time = 0.0f;		// startup takes 0 time.
	demo.entry->offset = FS_Tell( cls.demofile );	// position for this chunk.

	// finish off the startup info.
	CL_WriteDemoCmdHeader( dem_stop, cls.demoheader );

	// now copy the stuff we cached from the server.
	copysize = savepos = FS_Tell( cls.demoheader );

	FS_Seek( cls.demoheader, 0, SEEK_SET );

	FS_FileCopy( cls.demofile, cls.demoheader, copysize );

	// jump back to end, in case we record another demo for this session.
	FS_Seek( cls.demoheader, savepos, SEEK_SET );

	demo.starttime = CL_GetDemoRecordClock();	// setup the demo starttime
	demo.realstarttime = demo.starttime;
	demo.framecount = 0;

	// now move on to entry # 1, the first data chunk.
	curpos = FS_Tell( cls.demofile );
	demo.entry->length = curpos - demo.entry->offset;

	// now we are writing the first real lump.
	demo.entry = &demo.directory.entries[1]; // first real data lump
	demo.entry->entrytype = DEMO_NORMAL;
	demo.entry->playback_time = 0.0f; // startup takes 0 time.

	demo.entry->offset = FS_Tell( cls.demofile );

	// demo playback should read this as an incoming message.
	// write the client's realtime value out so we can synchronize the reads.
	CL_WriteDemoCmdHeader( dem_jumptime, cls.demofile );

	if( clgame.hInstance ) clgame.dllFuncs.pfnReset();

	Cbuf_InsertText( "fullupdate\n" );
	Cbuf_Execute();
}
Пример #11
0
void HPAK_CreatePak( const char *filename, resource_t *DirEnt, byte *data, file_t *f )
{
	int		filelocation;
	string		pakname;
	char		md5[16];
	char		*temp;
	MD5Context_t	MD5_Hash;
	file_t		*fout;

	if( !filename || !filename[0] )
	{
		MsgDev( D_ERROR, "HPAK_CreatePak: NULL name\n" );
		return;
	}

	if(( f != NULL && data != NULL ) || ( f == NULL && data == NULL ))
	{
		MsgDev( D_ERROR, "HPAK_CreatePak: too many sources, please leave one.\n" );
		return;
	}

	Q_strncpy( pakname, filename, sizeof( pakname ));
	FS_StripExtension( pakname );
	FS_DefaultExtension( pakname, ".hpk" );

	MsgDev( D_INFO, "creating HPAK %s.\n", pakname );
	fout = FS_Open( pakname, "wb", false );
	if( !fout )
	{
		MsgDev( D_ERROR, "HPAK_CreatePak: can't write %s.\n", pakname );
		return;
	}

	// let's hash it.
	Q_memset( &MD5_Hash, 0, sizeof( MD5Context_t ));
	MD5Init( &MD5_Hash );

	if( data == NULL )
	{
		// there are better ways
		filelocation = FS_Tell( f );
		temp = Z_Malloc( DirEnt->nDownloadSize );
		FS_Read( f, temp, DirEnt->nDownloadSize );
		FS_Seek( f, filelocation, SEEK_SET );

		MD5Update( &MD5_Hash, temp, DirEnt->nDownloadSize );
		Mem_Free( temp );
	}
	else
	{
		MD5Update( &MD5_Hash, data, DirEnt->nDownloadSize );
	}

	MD5Final( md5, &MD5_Hash );

	if( Q_memcmp( md5, DirEnt->rgucMD5_hash, 16 ))
	{
		MsgDev( D_ERROR, "HPAK_CreatePak: bad checksum for %s. Ignored\n", pakname );
		return;
	}

	hash_pack_header.ident = IDCUSTOMHEADER;
	hash_pack_header.version = IDCUSTOM_VERSION;
	hash_pack_header.seek = 0;

	FS_Write( fout, &hash_pack_header, sizeof( hash_pack_header ));

	hash_pack_dir.count = 1;
	hash_pack_dir.dirs = Z_Malloc( sizeof( hpak_dir_t ));
	hash_pack_dir.dirs[0].DirectoryResource = *DirEnt;
	hash_pack_dir.dirs[0].seek = FS_Tell( fout );
	hash_pack_dir.dirs[0].size = DirEnt->nDownloadSize;

	if( data == NULL )
	{
		HPAK_FileCopy( fout, f, hash_pack_dir.dirs[0].size );
	}
	else
	{
		FS_Write( fout, data, hash_pack_dir.dirs[0].size );
	}

	filelocation = FS_Tell( fout );
	FS_Write( fout, &hash_pack_dir.count, sizeof( hash_pack_dir.count ));
	FS_Write( fout, &hash_pack_dir.dirs[0], sizeof( hpak_dir_t ));

	Mem_Free( hash_pack_dir.dirs );
	Q_memset( &hash_pack_dir, 0, sizeof( hpak_container_t ));

	hash_pack_header.seek = filelocation;
	FS_Seek( fout, 0, SEEK_SET );
	FS_Write( fout, &hash_pack_header, sizeof( hpak_header_t ));
	FS_Close( fout );
}
Пример #12
0
void HPAK_RemoveLump( const char *name, resource_t *resource )
{
	string		read_path;
	string		save_path;
	file_t		*f1, *f2;
	hpak_container_t	hpak_read;
	hpak_container_t	hpak_save;
	int		i, j;

	if( !name || !name[0] || !resource )
		return;

	HPAK_FlushHostQueue();

	Q_strncpy( read_path, name, sizeof( read_path ));
	FS_StripExtension( read_path );
	FS_DefaultExtension( read_path, ".hpk" );

	f1 = FS_Open( read_path, "rb", false );
	if( !f1 )
	{
		MsgDev( D_ERROR, "HPAK_RemoveLump: %s couldn't open.\n", read_path );
		return;
	}

	Q_strncpy( save_path, read_path, sizeof( save_path ));
	FS_StripExtension( save_path );
	FS_DefaultExtension( save_path, ".hp2" );
	f2 = FS_Open( save_path, "w+b", false );
	if( !f2 )
	{
		MsgDev( D_ERROR, "HPAK_RemoveLump: %s couldn't open.\n", save_path );
		FS_Close( f1 );
		return;
	}

	FS_Seek( f1, 0, SEEK_SET );
	FS_Seek( f2, 0, SEEK_SET );

	// header copy
	FS_Read( f1, &hash_pack_header, sizeof( hpak_header_t ));
	FS_Write( f2, &hash_pack_header, sizeof( hpak_header_t ));

	if( hash_pack_header.ident != IDCUSTOMHEADER || hash_pack_header.version != IDCUSTOM_VERSION )
	{
		MsgDev( D_ERROR, "HPAK_RemoveLump: %s has invalid header.\n", read_path );
		FS_Close( f1 );
		FS_Close( f2 );
		FS_Delete( save_path ); // delete temp file
		return;
	}

	FS_Seek( f1, hash_pack_header.seek, SEEK_SET );
	FS_Read( f1, &hpak_read.count, sizeof( hpak_read.count ));

	if( hpak_read.count < 1 || hpak_read.count > MAX_FILES_IN_WAD )
	{
		MsgDev( D_ERROR, "HPAK_RemoveLump: %s has invalid number of lumps.\n", read_path );
		FS_Close( f1 );
		FS_Close( f2 );
		FS_Delete( save_path ); // delete temp file
		return;
	}

	if( hpak_read.count == 1 )
	{
		MsgDev( D_ERROR, "HPAK_RemoveLump: %s only has one element, so it's not deleted.\n", read_path );
		FS_Close( f1 );
		FS_Close( f2 );
		FS_Delete( read_path );
		FS_Delete( save_path );
		return;
	}

	hpak_save.count = hpak_read.count - 1;
	hpak_read.dirs = Z_Malloc( sizeof( hpak_dir_t ) * hpak_read.count );
	hpak_save.dirs = Z_Malloc( sizeof( hpak_dir_t ) * hpak_save.count );

	FS_Read( f1, hpak_read.dirs, sizeof( hpak_dir_t ) * hpak_read.count );

	if( !HPAK_FindResource( &hpak_read, resource->rgucMD5_hash, NULL ))
	{
		MsgDev( D_ERROR, "HPAK_RemoveLump: Couldn't find the lump %s in hpak %s.n", resource->szFileName, read_path );
		Mem_Free( hpak_read.dirs );
		Mem_Free( hpak_save.dirs );
		FS_Close( f1 );
		FS_Close( f2 );
		FS_Delete( save_path );
		return;
	}

	MsgDev( D_INFO, "Removing lump %s from %s.\n", resource->szFileName, read_path );

	// If there's a collision, we've just corrupted this hpak.
	for( i = 0, j = 0; i < hpak_read.count; i++ )
	{
		if( !Q_memcmp( hpak_read.dirs[i].DirectoryResource.rgucMD5_hash, resource->rgucMD5_hash, 16 ))
			continue;

		hpak_save.dirs[j] = hpak_read.dirs[i];
		hpak_save.dirs[j].seek = FS_Tell( f2 );
		FS_Seek( f1, hpak_read.dirs[j].seek, SEEK_SET );
		HPAK_FileCopy( f2, f1, hpak_save.dirs[j].size );
		j++;
	}

	hash_pack_header.seek = FS_Tell( f2 );
	FS_Write( f2, &hpak_save.count, ( hpak_save.count ));

	for( i = 0; i < hpak_save.count; i++ )
	{
		FS_Write( f2, &hpak_save.dirs[i], sizeof( hpak_dir_t ));
	}

	FS_Seek( f2, 0, SEEK_SET );
	FS_Write( f2, &hash_pack_header, sizeof( hpak_header_t ));

	Mem_Free( hpak_read.dirs );
	Mem_Free( hpak_save.dirs );
	FS_Close( f1 );
	FS_Close( f2 );

	FS_Delete( read_path );
	FS_Rename( save_path, read_path );
}
Пример #13
0
void HPAK_AddLump( qboolean add_to_queue, const char *name, resource_t *DirEnt, byte *data, file_t *f )
{
	int		i, position, length;
	string		pakname1, pakname2;
	char		md5[16];
	MD5Context_t	MD5_Hash;
	hpak_container_t	hpak1, hpak2;
	file_t		*f1, *f2;
	hpak_dir_t	*dirs;
	byte		*temp;

	if( !name || !name[0] )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: NULL name\n" );
		return;
	}

	if( !DirEnt )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: invalid lump\n" );
		return;
	}

	if( data == NULL && f == NULL )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: missing lump data\n" );
		return;
	}

	if( DirEnt->nDownloadSize < 1024 || DirEnt->nDownloadSize > 131072 )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: invalid size %s\n", Q_pretifymem( DirEnt->nDownloadSize, 2 ));
		return;
	}

	// hash it
	Q_memset( &MD5_Hash, 0, sizeof( MD5Context_t ));
	MD5Init( &MD5_Hash );

	if( data == NULL )
	{
		// there are better ways
		position = FS_Tell( f );
		temp = Z_Malloc( DirEnt->nDownloadSize );
		FS_Read( f, temp, DirEnt->nDownloadSize );
		FS_Seek( f, position, SEEK_SET );

		MD5Update( &MD5_Hash, temp, DirEnt->nDownloadSize );
		Mem_Free( temp );
	}
	else
	{
		MD5Update( &MD5_Hash, data, DirEnt->nDownloadSize );
	}

	MD5Final( md5, &MD5_Hash );

	if( Q_memcmp( md5, DirEnt->rgucMD5_hash, 0x10 ))
	{
		MsgDev( D_ERROR, "HPAK_AddLump: bad checksum for %s. Ignored\n", DirEnt->szFileName );
		return;
	}

	if( add_to_queue )
	{
		HPAK_AddToQueue( name, DirEnt, data, f );
		return;
	}

	Q_strncpy( pakname1, name, sizeof( pakname1 ));
	FS_StripExtension( pakname1 );
	FS_DefaultExtension( pakname1, ".hpk" );

	f1 = FS_Open( pakname1, "rb", false );

	if( !f1 )
	{
		// create new pack
		HPAK_CreatePak( name, DirEnt, data, f );
		return;
	}

	Q_strncpy( pakname2, pakname1, sizeof( pakname2 ));
	FS_StripExtension( pakname2 );
	FS_DefaultExtension( pakname2, ".hp2" );

	f2 = FS_Open( pakname2, "w+b", false );

	if( !f2 )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: couldn't open %s.\n", pakname2 );
		FS_Close( f1 );
		return;
	}

	// load headers
	FS_Read( f1, &hash_pack_header, sizeof( hpak_header_t ));

	if( hash_pack_header.version != IDCUSTOM_VERSION )
	{
		// we don't check the HPAK bit for some reason.
		MsgDev( D_ERROR, "HPAK_AddLump: %s does not have a valid header.\n", pakname2 );
		FS_Close( f1 );
		FS_Close( f2 );
	}

	length = FS_FileLength( f1 );
	HPAK_FileCopy( f2, f1, length );

	FS_Seek( f1, hash_pack_header.seek, SEEK_SET );
	FS_Read( f1, &hpak1.count, sizeof( hpak1.count ));

	if( hpak1.count < 1 || hpak1.count > MAX_FILES_IN_WAD )
	{
		MsgDev( D_ERROR, "HPAK_AddLump: %s contain too many lumps.\n", pakname1 );
		FS_Close( f1 );
		FS_Close( f2 );
		return;
	}

	// load the data
	hpak1.dirs = Z_Malloc( sizeof( hpak_dir_t ) * hpak1.count );
	FS_Read( f1, hpak1.dirs, sizeof( hpak_dir_t ) * hpak1.count );
	FS_Close( f1 );

	if( HPAK_FindResource( &hpak1, DirEnt->rgucMD5_hash, NULL ))
	{
		Mem_Free( hpak1.dirs );
		FS_Close( f2 );
	}

	// make a new container
	hpak2.count = hpak1.count;
	hpak2.dirs = Z_Malloc( sizeof( hpak_dir_t ) * hpak2.count );
	Q_memcpy( hpak2.dirs, hpak1.dirs, hpak1.count );

	for( i = 0, dirs = NULL; i < hpak1.count; i++ )
	{
		if( Q_memcmp( hpak1.dirs[i].DirectoryResource.rgucMD5_hash, DirEnt->rgucMD5_hash, 16 ) < 0 )
		{
			dirs = &hpak1.dirs[i];
			while( i < hpak1.count )
			{
				hpak2.dirs[i+1] = hpak1.dirs[i];
				i++;
			}
			break;
		}
	}

	if( dirs == NULL ) dirs = &hpak2.dirs[hpak2.count-1];

	Q_memset( dirs, 0, sizeof( hpak_dir_t ));
	FS_Seek( f2, hash_pack_header.seek, SEEK_SET );
	dirs->DirectoryResource = *DirEnt;
	dirs->seek = FS_Tell( f2 );
	dirs->size = DirEnt->nDownloadSize;

	if( !data ) HPAK_FileCopy( f2, f, dirs->size );
	else FS_Write( f2, data, dirs->size );

	hash_pack_header.seek = FS_Tell( f2 );
	FS_Write( f2, &hpak2.count, sizeof( hpak2.count ));

	for( i = 0; i < hpak2.count; i++ )
	{
		FS_Write( f2, &hpak2.dirs[i], sizeof( hpak_dir_t ));
	}

	// finalize
	Mem_Free( hpak1.dirs );
	Mem_Free( hpak2.dirs );

	FS_Seek( f2, 0, SEEK_SET );
	FS_Write( f2, &hash_pack_header, sizeof( hpak_header_t ));
	FS_Close( f2 );

	FS_Delete( pakname1 );
	FS_Rename( pakname2, pakname1 );
}