summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2009-10-03 11:12:39 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:14:44 +0000
commit593953c7deabb08cc77c22c08f5c8859bafbcb79 (patch)
tree8a22c17d66e749656a5665e1379d29ca715e219e
parent3ffe4805cfebd93a60bf59b582303540b2ec0d80 (diff)
* Merge ioq3-r1233
-rw-r--r--Makefile14
-rw-r--r--src/client/cl_avi.c23
-rw-r--r--src/qcommon/common.c9
-rw-r--r--src/qcommon/unzip.c2
-rw-r--r--src/renderer/tr_init.c5
-rw-r--r--src/renderer/tr_local.h1
-rw-r--r--src/renderer/tr_types.h1
-rw-r--r--src/sdl/sdl_glimp.c102
-rw-r--r--src/sys/con_tty.c26
-rw-r--r--src/sys/con_win32.c29
-rw-r--r--src/sys/sys_local.h17
-rw-r--r--src/sys/sys_main.c83
-rw-r--r--src/sys/sys_unix.c38
-rw-r--r--src/sys/sys_win32.c40
14 files changed, 277 insertions, 113 deletions
diff --git a/Makefile b/Makefile
index 63526571..df02c7d0 100644
--- a/Makefile
+++ b/Makefile
@@ -6,11 +6,15 @@
COMPILE_PLATFORM=$(shell uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]')
+COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/)
+
ifeq ($(COMPILE_PLATFORM),sunos)
# Solaris uname and GNU uname differ
COMPILE_ARCH=$(shell uname -p | sed -e s/i.86/x86/)
-else
- COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/)
+endif
+ifeq ($(COMPILE_PLATFORM),darwin)
+ # Apple does some things a little differently...
+ COMPILE_ARCH=$(shell uname -p | sed -e s/i.86/x86/)
endif
BUILD_CLIENT =
@@ -698,6 +702,7 @@ ifeq ($(PLATFORM),sunos)
BASE_CFLAGS += -m32
LDFLAGS += -m32
BASE_CFLAGS += -I/usr/X11/include/NVIDIA
+ CLIENT_LDFLAGS += -L/usr/X11/lib/NVIDIA -R/usr/X11/lib/NVIDIA
endif
endif
@@ -718,7 +723,7 @@ ifeq ($(PLATFORM),sunos)
BOTCFLAGS=-O0
- CLIENT_LDFLAGS=$(shell sdl-config --libs) -lGL
+ CLIENT_LDFLAGS +=$(shell sdl-config --libs) -lGL
else # ifeq sunos
@@ -1170,6 +1175,8 @@ Q3OBJ = \
$(B)/client/sdl_input.o \
$(B)/client/sdl_snd.o \
\
+ $(B)/client/con_passive.o \
+ $(B)/client/con_log.o \
$(B)/client/sys_main.o
ifeq ($(ARCH),x86)
@@ -1268,6 +1275,7 @@ Q3DOBJ = \
$(B)/ded/null_input.o \
$(B)/ded/null_snddma.o \
\
+ $(B)/ded/con_log.o \
$(B)/ded/sys_main.o
ifeq ($(ARCH),x86)
diff --git a/src/client/cl_avi.c b/src/client/cl_avi.c
index c54e7054..df7bc7b9 100644
--- a/src/client/cl_avi.c
+++ b/src/client/cl_avi.c
@@ -250,14 +250,17 @@ void CL_WriteAVIHeader( void )
WRITE_2BYTES( 1 ); //biPlanes
WRITE_2BYTES( 24 ); //biBitCount
- if( afd.motionJpeg ) { //biCompression
+ if( afd.motionJpeg ) //biCompression
+ {
WRITE_STRING( "MJPG" );
WRITE_4BYTES( afd.width *
- afd.height ); //biSizeImage
- } else {
+ afd.height ); //biSizeImage
+ }
+ else
+ {
WRITE_4BYTES( 0 ); // BI_RGB
WRITE_4BYTES( afd.width *
- afd.height*3 ); //biSizeImage
+ afd.height * 3 ); //biSizeImage
}
WRITE_4BYTES( 0 ); //biXPelsPetMeter
@@ -391,10 +394,14 @@ qboolean CL_OpenAVIForWriting( const char *fileName )
}
else if( Q_stricmp( Cvar_VariableString( "s_backend" ), "OpenAL" ) )
{
- if( afd.a.bits == 16 && afd.a.channels == 2 )
- afd.audio = qtrue;
+ if( afd.a.bits != 16 || afd.a.channels != 2 )
+ {
+ Com_Printf( S_COLOR_YELLOW "WARNING: Audio format of %d bit/%d channels not supported",
+ afd.a.bits, afd.a.channels );
+ afd.audio = qfalse;
+ }
else
- afd.audio = qfalse; //FIXME: audio not implemented for this case
+ afd.audio = qtrue;
}
else
{
@@ -542,7 +549,7 @@ void CL_WriteAVIAudioFrame( const byte *pcmBuffer, int size )
WRITE_4BYTES( bytesInBuffer );
SafeFS_Write( buffer, 8, afd.f );
- SafeFS_Write( pcmBuffer, bytesInBuffer, afd.f );
+ SafeFS_Write( pcmCaptureBuffer, bytesInBuffer, afd.f );
SafeFS_Write( padding, paddingSize, afd.f );
afd.fileSize += ( chunkSize + paddingSize );
diff --git a/src/qcommon/common.c b/src/qcommon/common.c
index ff742803..e2aa156c 100644
--- a/src/qcommon/common.c
+++ b/src/qcommon/common.c
@@ -3154,6 +3154,8 @@ static void Field_CompleteCommand( char *cmd,
}
else
{
+ int completionOffset;
+
if( completionString[0] == '\\' || completionString[0] == '/' )
completionString++;
@@ -3172,9 +3174,10 @@ static void Field_CompleteCommand( char *cmd,
if( matchCount == 0 )
return; // no matches
- Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
- strlen( completionString ) ], shortestMatch,
- sizeof( completionField->buffer ) );
+ completionOffset = strlen( completionField->buffer ) - strlen( completionString );
+
+ Q_strncpyz( &completionField->buffer[ completionOffset ], shortestMatch,
+ sizeof( completionField->buffer ) - completionOffset );
completionField->cursor = strlen( completionField->buffer );
diff --git a/src/qcommon/unzip.c b/src/qcommon/unzip.c
index ac956091..7daf271b 100644
--- a/src/qcommon/unzip.c
+++ b/src/qcommon/unzip.c
@@ -4048,7 +4048,7 @@ int inflateInit2_(z_streamp z, int w, const char *version, int stream_size)
/* create inflate_blocks state */
if ((z->state->blocks =
- inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+ inflate_blocks_new(z, z->state->nowrap ? ((check_func)0) : adler32, (uInt)1 << w))
== Z_NULL)
{
inflateEnd(z);
diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c
index 534dec3a..fd230bd2 100644
--- a/src/renderer/tr_init.c
+++ b/src/renderer/tr_init.c
@@ -24,10 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_local.h"
-glconfig_t glConfig;
-qboolean textureFilterAnisotropic = qfalse;
-int maxAnisotropy = 0;
-
+glconfig_t glConfig;
glstate_t glState;
static void GfxInfo_f( void );
diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h
index a507e8a7..1bbe12fc 100644
--- a/src/renderer/tr_local.h
+++ b/src/renderer/tr_local.h
@@ -971,6 +971,7 @@ extern trGlobals_t tr;
extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared during ref re-init
extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init
+
//
// cvars
//
diff --git a/src/renderer/tr_types.h b/src/renderer/tr_types.h
index 2d7c66d3..a1c338b1 100644
--- a/src/renderer/tr_types.h
+++ b/src/renderer/tr_types.h
@@ -192,6 +192,7 @@ typedef struct {
// than scrWidth / scrHeight if the pixels are non-square
// normal screens should be 4/3, but wide aspect monitors may be 16/9
float windowAspect;
+ float displayAspect;
int displayFrequency;
diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c
index 347505b8..fac67a54 100644
--- a/src/sdl/sdl_glimp.c
+++ b/src/sdl/sdl_glimp.c
@@ -44,6 +44,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <math.h>
#include "../renderer/tr_local.h"
#include "../client/client.h"
@@ -92,12 +93,15 @@ GLimp_Shutdown
*/
void GLimp_Shutdown( void )
{
+ float oldDisplayAspect = glConfig.displayAspect;
+
IN_Shutdown();
SDL_QuitSubSystem( SDL_INIT_VIDEO );
screen = NULL;
Com_Memset( &glConfig, 0, sizeof( glConfig ) );
+ glConfig.displayAspect = oldDisplayAspect;
Com_Memset( &glState, 0, sizeof( glState ) );
}
@@ -112,6 +116,81 @@ void GLimp_LogComment( char *comment )
/*
===============
+GLimp_CompareModes
+===============
+*/
+static int GLimp_CompareModes( const void *a, const void *b )
+{
+ const float ASPECT_EPSILON = 0.001f;
+ SDL_Rect *modeA = *(SDL_Rect **)a;
+ SDL_Rect *modeB = *(SDL_Rect **)b;
+ float aspectDiffA = fabs( ( (float)modeA->w / (float)modeA->h ) - glConfig.displayAspect );
+ float aspectDiffB = fabs( ( (float)modeB->w / (float)modeB->h ) - glConfig.displayAspect );
+ float aspectDiffsDiff = aspectDiffA - aspectDiffB;
+
+ if( aspectDiffsDiff > ASPECT_EPSILON )
+ return 1;
+ else if( aspectDiffsDiff < -ASPECT_EPSILON )
+ return -1;
+ else
+ {
+ if( modeA->w == modeB->w )
+ return modeA->h - modeB->h;
+ else
+ return modeA->w - modeB->w;
+ }
+}
+
+/*
+===============
+GLimp_DetectAvailableModes
+===============
+*/
+static void GLimp_DetectAvailableModes(void)
+{
+ char buf[ MAX_STRING_CHARS ] = { 0 };
+ SDL_Rect **modes;
+ int numModes;
+ int i;
+
+ modes = SDL_ListModes( NULL, SDL_OPENGL | SDL_FULLSCREEN );
+
+ if( !modes )
+ {
+ ri.Printf( PRINT_WARNING, "Can't get list of available modes\n" );
+ return;
+ }
+
+ if( modes == (SDL_Rect **)-1 )
+ {
+ ri.Printf( PRINT_ALL, "Display supports any resolution\n" );
+ return; // can set any resolution
+ }
+
+ for( numModes = 0; modes[ numModes ]; numModes++ );
+
+ qsort( modes, numModes, sizeof( SDL_Rect* ), GLimp_CompareModes );
+
+ for( i = 0; i < numModes; i++ )
+ {
+ const char *newModeString = va( "%ux%u ", modes[ i ]->w, modes[ i ]->h );
+
+ if( strlen( newModeString ) < (int)sizeof( buf ) - strlen( buf ) )
+ Q_strcat( buf, sizeof( buf ), newModeString );
+ else
+ ri.Printf( PRINT_WARNING, "Skipping mode %ux%x, buffer too small\n", modes[i]->w, modes[i]->h );
+ }
+
+ if( *buf )
+ {
+ buf[ strlen( buf ) - 1 ] = 0;
+ ri.Printf( PRINT_ALL, "Available modes: '%s'\n", buf );
+ ri.Cvar_Set( "r_availableModes", buf );
+ }
+}
+
+/*
+===============
GLimp_SetMode
===============
*/
@@ -124,9 +203,28 @@ static int GLimp_SetMode( int mode, qboolean fullscreen )
int i = 0;
SDL_Surface *vidscreen = NULL;
Uint32 flags = SDL_OPENGL;
+ const SDL_VideoInfo *videoInfo;
ri.Printf( PRINT_ALL, "Initializing OpenGL display\n");
+ if( glConfig.displayAspect == 0.0f )
+ {
+#if !SDL_VERSION_ATLEAST(1, 2, 10)
+ // 1.2.10 is needed to get the desktop resolution
+ glConfig.displayAspect = 4.0f / 3.0f;
+#elif MINSDL_PATCH >= 10
+# error Ifdeffery no longer necessary, please remove
+#else
+ // Guess the display aspect ratio through the desktop resolution
+ // by assuming (relatively safely) that it is set at or close to
+ // the display's native aspect ratio
+ videoInfo = SDL_GetVideoInfo( );
+ glConfig.displayAspect = (float)videoInfo->current_w / (float)videoInfo->current_h;
+#endif
+
+ ri.Printf( PRINT_ALL, "Estimated display aspect: %.3f\n", glConfig.displayAspect );
+ }
+
ri.Printf (PRINT_ALL, "...setting mode %d:", mode );
if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) )
@@ -275,6 +373,8 @@ static int GLimp_SetMode( int mode, qboolean fullscreen )
break;
}
+ GLimp_DetectAvailableModes();
+
if (!vidscreen)
{
ri.Printf( PRINT_ALL, "Couldn't get a visual\n" );
@@ -526,6 +626,8 @@ void GLimp_Init( void )
// initialize extensions
GLimp_InitExtensions( );
+ ri.Cvar_Get( "r_availableModes", "", CVAR_ROM );
+
// This depends on SDL_INIT_VIDEO, hence having it here
IN_Init( );
diff --git a/src/sys/con_tty.c b/src/sys/con_tty.c
index f128b0d7..687d1dd4 100644
--- a/src/sys/con_tty.c
+++ b/src/sys/con_tty.c
@@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
+#include "sys_local.h"
#include <unistd.h>
#include <signal.h>
@@ -102,7 +103,7 @@ Clear the display of the line currently edited
bring cursor back to beginning of line
==================
*/
-void CON_Hide( void )
+static void CON_Hide( void )
{
if( ttycon_on )
{
@@ -132,7 +133,7 @@ Show the current line
FIXME need to position the cursor if needed?
==================
*/
-void CON_Show( void )
+static void CON_Show( void )
{
if( ttycon_on )
{
@@ -297,10 +298,10 @@ void CON_Init( void )
/*
==================
-CON_ConsoleInput
+CON_Input
==================
*/
-char *CON_ConsoleInput( void )
+char *CON_Input( void )
{
// we use this when sending back commands
static char text[256];
@@ -440,3 +441,20 @@ char *CON_ConsoleInput( void )
return text;
}
}
+
+/*
+==================
+CON_Print
+==================
+*/
+void CON_Print( const char *msg )
+{
+ CON_Hide( );
+
+ if( com_ansiColor && com_ansiColor->integer )
+ Sys_AnsiColorPrint( msg );
+ else
+ fputs( msg, stderr );
+
+ CON_Show( );
+}
diff --git a/src/sys/con_win32.c b/src/sys/con_win32.c
index 71549b7d..a27c9cca 100644
--- a/src/sys/con_win32.c
+++ b/src/sys/con_win32.c
@@ -132,19 +132,10 @@ static void CON_HistNext( void )
/*
==================
-CON_Hide
-==================
-*/
-void CON_Hide( void )
-{
-}
-
-/*
-==================
CON_Show
==================
*/
-void CON_Show( void )
+static void CON_Show( void )
{
CONSOLE_SCREEN_BUFFER_INFO binfo;
COORD writeSize = { MAX_EDIT_LINE, 1 };
@@ -155,7 +146,7 @@ void CON_Show( void )
GetConsoleScreenBufferInfo( qconsole_hout, &binfo );
- // if we' re in the middle of printf, don't bother writing the buffer
+ // if we're in the middle of printf, don't bother writing the buffer
if( binfo.dwCursorPosition.X != 0 )
return;
@@ -249,10 +240,10 @@ void CON_Init( void )
/*
==================
-CON_ConsoleInput
+CON_Input
==================
*/
-char *CON_ConsoleInput( void )
+char *CON_Input( void )
{
INPUT_RECORD buff[ MAX_EDIT_LINE ];
DWORD count = 0, events = 0;
@@ -353,3 +344,15 @@ char *CON_ConsoleInput( void )
return qconsole_line;
}
+
+/*
+==================
+CON_Print
+==================
+*/
+void CON_Print( const char *msg )
+{
+ fputs( msg, stderr );
+
+ CON_Show( );
+}
diff --git a/src/sys/sys_local.h b/src/sys/sys_local.h
index 60c7e63a..40336e3a 100644
--- a/src/sys/sys_local.h
+++ b/src/sys/sys_local.h
@@ -29,19 +29,24 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MINSDL_PATCH 7
// Input subsystem
-void IN_Init (void);
-void IN_Frame (void);
-void IN_Shutdown (void);
+void IN_Init( void );
+void IN_Frame( void );
+void IN_Shutdown( void );
// Console
-void CON_Hide( void );
-void CON_Show( void );
void CON_Shutdown( void );
void CON_Init( void );
-char *CON_ConsoleInput(void);
+char *CON_Input( void );
+void CON_Print( const char *message );
+
+unsigned int CON_LogSize( void );
+unsigned int CON_LogWrite( const char *in );
+unsigned int CON_LogRead( char *out, unsigned int outSize );
#ifdef MACOS_X
char *Sys_StripAppBundle( char *pwd );
#endif
void Sys_SigHandler( int signal );
+void Sys_ErrorDialog( const char *error );
+void Sys_AnsiColorPrint( const char *msg );
diff --git a/src/sys/sys_main.c b/src/sys/sys_main.c
index 512c43b8..284a1194 100644
--- a/src/sys/sys_main.c
+++ b/src/sys/sys_main.c
@@ -108,34 +108,6 @@ void Sys_In_Restart_f( void )
/*
=================
-Sys_ConsoleInputInit
-
-Start the console input subsystem
-=================
-*/
-void Sys_ConsoleInputInit( void )
-{
-#ifdef DEDICATED
- CON_Init( );
-#endif
-}
-
-/*
-=================
-Sys_ConsoleInputShutdown
-
-Shutdown the console input subsystem
-=================
-*/
-void Sys_ConsoleInputShutdown( void )
-{
-#ifdef DEDICATED
- CON_Shutdown( );
-#endif
-}
-
-/*
-=================
Sys_ConsoleInput
Handle new console input
@@ -143,11 +115,7 @@ Handle new console input
*/
char *Sys_ConsoleInput(void)
{
-#ifdef DEDICATED
- return CON_ConsoleInput( );
-#endif
-
- return NULL;
+ return CON_Input( );
}
/*
@@ -159,18 +127,18 @@ Single exit point (regular exit or in case of error)
*/
void Sys_Exit( int ex )
{
- Sys_ConsoleInputShutdown();
+ CON_Shutdown( );
#ifndef DEDICATED
SDL_Quit( );
#endif
#ifdef NDEBUG
- exit(ex);
+ exit( ex );
#else
// Cause a backtrace on error exits
assert( ex == 0 );
- exit(ex);
+ exit( ex );
#endif
}
@@ -179,10 +147,10 @@ void Sys_Exit( int ex )
Sys_Quit
=================
*/
-void Sys_Quit (void)
+void Sys_Quit( void )
{
- CL_Shutdown ();
- Sys_Exit(0);
+ CL_Shutdown( );
+ Sys_Exit( 0 );
}
/*
@@ -227,7 +195,7 @@ Sys_AnsiColorPrint
Transform Q3 colour codes to ANSI escape sequences
=================
*/
-static void Sys_AnsiColorPrint( const char *msg )
+void Sys_AnsiColorPrint( const char *msg )
{
static char buffer[ MAXPRINTMSG ];
int length = 0;
@@ -296,18 +264,8 @@ Sys_Print
*/
void Sys_Print( const char *msg )
{
-#ifdef DEDICATED
- CON_Hide();
-#endif
-
- if( com_ansiColor && com_ansiColor->integer )
- Sys_AnsiColorPrint( msg );
- else
- fputs(msg, stderr);
-
-#ifdef DEDICATED
- CON_Show();
-#endif
+ CON_LogWrite( msg );
+ CON_Print( msg );
}
/*
@@ -320,16 +278,13 @@ void Sys_Error( const char *error, ... )
va_list argptr;
char string[1024];
-#ifdef DEDICATED
- CON_Hide();
-#endif
-
CL_Shutdown ();
va_start (argptr,error);
Q_vsnprintf (string, sizeof(string), error, argptr);
va_end (argptr);
- fprintf(stderr, "Sys_Error: %s\n", string);
+
+ Sys_ErrorDialog( string );
Sys_Exit( 1 );
}
@@ -348,15 +303,7 @@ void Sys_Warn( char *warning, ... )
Q_vsnprintf (string, sizeof(string), warning, argptr);
va_end (argptr);
-#ifdef DEDICATED
- CON_Hide();
-#endif
-
- fprintf(stderr, "Warning: %s", string);
-
-#ifdef DEDICATED
- CON_Show();
-#endif
+ CON_Print( va( "Warning: %s", string ) );
}
/*
@@ -624,9 +571,9 @@ int main( int argc, char **argv )
}
Com_Init( commandLine );
- NET_Init();
+ NET_Init( );
- Sys_ConsoleInputInit();
+ CON_Init( );
#ifndef _WIN32
// Windows doesn't have these signals
diff --git a/src/sys/sys_unix.c b/src/sys/sys_unix.c
index 230d8c44..090e9e43 100644
--- a/src/sys/sys_unix.c
+++ b/src/sys/sys_unix.c
@@ -19,6 +19,11 @@ along with Tremulous; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
+
+#include "../qcommon/q_shared.h"
+#include "../qcommon/qcommon.h"
+#include "sys_local.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
@@ -30,9 +35,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <pwd.h>
#include <libgen.h>
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qcommon.h"
-
// Used to determine where to store user-specific files
static char homePath[ MAX_OSPATH ] = { 0 };
@@ -476,3 +478,33 @@ void Sys_Sleep( int msec )
select((fileno(stdin) + 1), &fdset, NULL, NULL, &timeout);
}
}
+
+/*
+==============
+Sys_ErrorDialog
+
+Display an error message
+==============
+*/
+void Sys_ErrorDialog( const char *error )
+{
+ char buffer[ 1024 ];
+ unsigned int size;
+ fileHandle_t f;
+ const char *fileName = "crashlog.txt";
+
+ Sys_Print( va( "%s\n", error ) );
+
+ // Write console log to file
+ f = FS_FOpenFileWrite( fileName );
+ if( !f )
+ {
+ Com_Printf( "ERROR: couldn't open %s\n", fileName );
+ return;
+ }
+
+ while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 )
+ FS_Write( buffer, size, f );
+
+ FS_FCloseFile( f );
+}
diff --git a/src/sys/sys_win32.c b/src/sys/sys_win32.c
index 36d81a77..df8861d3 100644
--- a/src/sys/sys_win32.c
+++ b/src/sys/sys_win32.c
@@ -525,3 +525,43 @@ void Sys_Sleep( int msec )
WaitForSingleObject( GetStdHandle( STD_INPUT_HANDLE ), msec );
}
+/*
+==============
+Sys_ErrorDialog
+
+Display an error message
+==============
+*/
+void Sys_ErrorDialog( const char *error )
+{
+ if( MessageBox( NULL, va( "%s. Copy console log to clipboard?", error ),
+ NULL, MB_YESNO|MB_ICONERROR ) == IDYES )
+ {
+ HGLOBAL memoryHandle;
+ char *clipMemory;
+
+ memoryHandle = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, CON_LogSize( ) + 1 );
+ clipMemory = (char *)GlobalLock( memoryHandle );
+
+ if( clipMemory )
+ {
+ char *p = clipMemory;
+ char buffer[ 1024 ];
+ unsigned int size;
+
+ while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 )
+ {
+ Com_Memcpy( p, buffer, size );
+ p += size;
+ }
+
+ *p = '\0';
+
+ if( OpenClipboard( NULL ) && EmptyClipboard( ) )
+ SetClipboardData( CF_TEXT, memoryHandle );
+
+ GlobalUnlock( clipMemory );
+ CloseClipboard( );
+ }
+ }
+}