diff options
34 files changed, 802 insertions, 328 deletions
@@ -354,6 +354,7 @@ else # ifeq Linux ifeq ($(PLATFORM),darwin) HAVE_VM_COMPILED=true + LIBS = -framework Cocoa CLIENT_LIBS= OPTIMIZEVM= @@ -410,7 +411,7 @@ ifeq ($(PLATFORM),darwin) # the file has been modified by each build. LIBSDLMAIN=$(B)/libSDLmain.a LIBSDLMAINSRC=$(LIBSDIR)/macosx/libSDLmain.a - CLIENT_LIBS += -framework Cocoa -framework IOKit -framework OpenGL \ + CLIENT_LIBS += -framework IOKit -framework OpenGL \ $(LIBSDIR)/macosx/libSDL-1.2.0.dylib OPTIMIZEVM += -falign-loops=16 @@ -447,8 +448,6 @@ ifeq ($(PLATFORM),mingw32) WINDRES=windres endif - ARCH=x86 - BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ -DUSE_ICON CLIENT_CFLAGS = @@ -473,12 +472,20 @@ ifeq ($(PLATFORM),mingw32) CLIENT_CFLAGS += -DUSE_CODEC_VORBIS endif - OPTIMIZEVM = -O3 -march=i586 -fno-omit-frame-pointer \ - -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \ - -fstrength-reduce - OPTIMIZE = $(OPTIMIZEVM) -ffast-math - - HAVE_VM_COMPILED = true + ifeq ($(ARCH),x64) + OPTIMIZEVM = -O3 -fno-omit-frame-pointer \ + -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \ + -fstrength-reduce + OPTIMIZE = $(OPTIMIZEVM) --fast-math + HAVE_VM_COMPILED = true + endif + ifeq ($(ARCH),x86) + OPTIMIZEVM = -O3 -march=i586 -fno-omit-frame-pointer \ + -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \ + -fstrength-reduce + OPTIMIZE = $(OPTIMIZEVM) -ffast-math + HAVE_VM_COMPILED = true + endif SHLIBEXT=dll SHLIBCFLAGS= @@ -486,7 +493,7 @@ ifeq ($(PLATFORM),mingw32) BINEXT=.exe - LIBS= -lws2_32 -lwinmm + LIBS= -lws2_32 -lwinmm -lpsapi CLIENT_LDFLAGS = -mwindows CLIENT_LIBS = -lgdi32 -lole32 -lopengl32 @@ -496,7 +503,11 @@ ifeq ($(PLATFORM),mingw32) ifneq ($(USE_CURL_DLOPEN),1) ifeq ($(USE_LOCAL_HEADERS),1) CLIENT_CFLAGS += -DCURL_STATICLIB - CLIENT_LIBS += $(LIBSDIR)/win32/libcurl.a + ifeq ($(ARCH),x64) + CLIENT_LIBS += $(LIBSDIR)/win64/libcurl.a + else + CLIENT_LIBS += $(LIBSDIR)/win32/libcurl.a + endif else CLIENT_LIBS += $(CURL_LIBS) endif @@ -510,14 +521,22 @@ ifeq ($(PLATFORM),mingw32) ifeq ($(ARCH),x86) # build 32bit BASE_CFLAGS += -m32 + else + BASE_CFLAGS += -m64 endif # libmingw32 must be linked before libSDLmain CLIENT_LIBS += -lmingw32 ifeq ($(USE_LOCAL_HEADERS),1) CLIENT_CFLAGS += -I$(SDLHDIR)/include + ifeq ($(ARCH), x86) CLIENT_LIBS += $(LIBSDIR)/win32/libSDLmain.a \ $(LIBSDIR)/win32/libSDL.dll.a + else + CLIENT_LIBS += $(LIBSDIR)/win64/libSDLmain.a \ + $(LIBSDIR)/win64/libSDL.dll.a \ + $(LIBSDIR)/win64/libSDL.a + endif else CLIENT_CFLAGS += $(SDL_CFLAGS) CLIENT_LIBS += $(SDL_LIBS) @@ -533,45 +552,16 @@ else # ifeq mingw32 ifeq ($(PLATFORM),freebsd) - ifneq (,$(findstring alpha,$(shell uname -m))) - ARCH=axp - else #default to x86 - ARCH=x86 - endif #alpha test - - BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ - -DUSE_ICON + # flags + BASE_CFLAGS = $(shell env MACHINE_ARCH=$(ARCH) make -f /dev/null -VCFLAGS) \ + -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ + -DUSE_ICON -DMAP_ANONYMOUS=MAP_ANON CLIENT_CFLAGS = $(SDL_CFLAGS) SERVER_CFLAGS = + HAVE_VM_COMPILED = true - ifeq ($(USE_OPENAL),1) - CLIENT_CFLAGS += -DUSE_OPENAL - ifeq ($(USE_OPENAL_DLOPEN),1) - CLIENT_CFLAGS += -DUSE_OPENAL_DLOPEN - endif - endif - - ifeq ($(USE_CODEC_VORBIS),1) - CLIENT_CFLAGS += -DUSE_CODEC_VORBIS - endif - - OPTIMIZEVM = -O3 -funroll-loops -fomit-frame-pointer - - ifeq ($(ARCH),axp) - BASE_CFLAGS += -DNO_VM_COMPILED - OPTIMIZEVM += -fexpensive-optimizations - else - ifeq ($(ARCH),x86) - OPTIMIZEVM += -mtune=pentiumpro \ - -march=pentium -pipe -falign-loops=2 -falign-jumps=2 \ - -falign-functions=2 -funroll-loops -fstrength-reduce - HAVE_VM_COMPILED=true - else - BASE_CFLAGS += -DNO_VM_COMPILED - endif - endif - - OPTIMIZE = $(OPTIMIZEVM) -ffast-math + OPTIMIZEVM = -O3 -funroll-loops -fomit-frame-pointer -ffast-math + OPTIMIZE = $(OPTIMIZEVM) SHLIBEXT=so SHLIBCFLAGS=-fPIC @@ -585,16 +575,43 @@ ifeq ($(PLATFORM),freebsd) CLIENT_LIBS += $(SDL_LIBS) -lGL + # optional features/libraries ifeq ($(USE_OPENAL),1) - ifneq ($(USE_OPENAL_DLOPEN),1) + CLIENT_CFLAGS += -DUSE_OPENAL + ifeq ($(USE_OPENAL_DLOPEN),1) + CLIENT_CFLAGS += -DUSE_OPENAL_DLOPEN CLIENT_LIBS += $(THREAD_LIBS) -lopenal endif endif + ifeq ($(USE_CURL),1) + CLIENT_CFLAGS += -DUSE_CURL + ifeq ($(USE_CURL_DLOPEN),1) + CLIENT_CFLAGS += -DUSE_CURL_DLOPEN + CLIENT_LIBS += -lcurl + endif + endif + + ifeq ($(USE_CODEC_VORBIS),1) + CLIENT_CFLAGS += -DUSE_CODEC_VORBIS + endif + ifeq ($(USE_CODEC_VORBIS),1) CLIENT_LIBS += -lvorbisfile -lvorbis -logg endif + # cross-compiling tweaks + ifeq ($(ARCH),i386) + ifeq ($(CROSS_COMPILING),1) + BASE_CFLAGS += -m32 + endif + endif + ifeq ($(ARCH),amd64) + ifeq ($(CROSS_COMPILING),1) + BASE_CFLAGS += -m64 + endif + endif + else # ifeq freebsd ############################################################################# @@ -854,9 +871,7 @@ endif ifeq ($(USE_INTERNAL_ZLIB),1) BASE_CFLAGS += -DNO_GZIP - ifneq ($(USE_LOCAL_HEADERS),1) - BASE_CFLAGS += -I$(ZDIR) - endif + BASE_CFLAGS += -I$(ZDIR) else LIBS += -lz endif @@ -1057,7 +1072,7 @@ makedirs: # QVM BUILD TOOLS ############################################################################# -TOOLS_OPTIMIZE = -g -O2 -Wall -fno-strict-aliasing +TOOLS_OPTIMIZE = -g -Wall -fno-strict-aliasing TOOLS_CFLAGS += $(TOOLS_OPTIMIZE) \ -DTEMPDIR=\"$(TEMPDIR)\" -DSYSTEM=\"\" \ -I$(Q3LCCSRCDIR) \ @@ -1418,6 +1433,12 @@ ifeq ($(HAVE_VM_COMPILED),true) ifeq ($(ARCH),x86_64) Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o endif + ifeq ($(ARCH),amd64) + Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o + endif + ifeq ($(ARCH),x64) + Q3OBJ += $(B)/client/vm_x86_64.o $(B)/client/vm_x86_64_assembler.o + endif ifeq ($(ARCH),ppc) Q3OBJ += $(B)/client/vm_powerpc.o $(B)/client/vm_powerpc_asm.o endif @@ -1440,7 +1461,7 @@ endif ifeq ($(PLATFORM),darwin) Q3OBJ += \ - $(B)/client/sys_cocoa.o + $(B)/client/sys_osx.o endif ifeq ($(USE_MUMBLE),1) @@ -1545,6 +1566,12 @@ ifeq ($(HAVE_VM_COMPILED),true) ifeq ($(ARCH),x86_64) Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o endif + ifeq ($(ARCH),amd64) + Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o + endif + ifeq ($(ARCH),x64) + Q3DOBJ += $(B)/ded/vm_x86_64.o $(B)/ded/vm_x86_64_assembler.o + endif ifeq ($(ARCH),ppc) Q3DOBJ += $(B)/ded/vm_powerpc.o $(B)/ded/vm_powerpc_asm.o endif @@ -1567,6 +1594,11 @@ else $(B)/ded/con_tty.o endif +ifeq ($(PLATFORM),darwin) + Q3DOBJ += \ + $(B)/ded/sys_osx.o +endif + $(B)/tremded$(FULLBINEXT): $(Q3DOBJ) $(echo_cmd) "LD $@" $(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(Q3DOBJ) $(LIBS) diff --git a/cross-make-mingw.sh b/cross-make-mingw.sh index c6dbe377..604ced10 100755 --- a/cross-make-mingw.sh +++ b/cross-make-mingw.sh @@ -3,4 +3,8 @@ export CC=i586-mingw32msvc-gcc export WINDRES=i586-mingw32msvc-windres export PLATFORM=mingw32 +if [ !$ARCH ] +then +export ARCH=x86 +fi exec make $* diff --git a/src/client/cl_cin.c b/src/client/cl_cin.c index f1fde54b..6d03d40a 100644 --- a/src/client/cl_cin.c +++ b/src/client/cl_cin.c @@ -1653,6 +1653,9 @@ void CIN_UploadCinematic(int handle) { if (cl_inGameVideo->integer == 0 && cinTable[handle].playonwalls == 1) { cinTable[handle].playonwalls--; } + else if (cl_inGameVideo->integer != 0 && cinTable[handle].playonwalls != 1) { + cinTable[handle].playonwalls = 1; + } } } diff --git a/src/client/cl_keys.c b/src/client/cl_keys.c index 212ac8d5..c2cda2d6 100644 --- a/src/client/cl_keys.c +++ b/src/client/cl_keys.c @@ -532,12 +532,14 @@ void Field_CharEvent( field_t *edit, int ch ) { } if ( key_overstrikeMode ) { - if ( edit->cursor == MAX_EDIT_LINE - 1 ) + // - 2 to leave room for the leading slash and trailing \0 + if ( edit->cursor == MAX_EDIT_LINE - 2 ) return; edit->buffer[edit->cursor] = ch; edit->cursor++; } else { // insert mode - if ( len == MAX_EDIT_LINE - 1 ) { + // - 2 to leave room for the leading slash and trailing \0 + if ( len == MAX_EDIT_LINE - 2 ) { return; // all full } memmove( edit->buffer + edit->cursor + 1, @@ -581,8 +583,10 @@ void Console_Key (int key) { // enter finishes the line if ( key == K_ENTER || key == K_KP_ENTER ) { // if not in the game explicitly prepend a slash if needed - if ( cls.state != CA_ACTIVE && g_consoleField.buffer[0] != '\\' - && g_consoleField.buffer[0] != '/' ) { + if ( cls.state != CA_ACTIVE && + g_consoleField.buffer[0] && + g_consoleField.buffer[0] != '\\' && + g_consoleField.buffer[0] != '/' ) { char temp[MAX_EDIT_LINE-1]; Q_strncpyz( temp, g_consoleField.buffer, sizeof( temp ) ); diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 81cb98ac..a4c74c5a 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -3407,7 +3407,6 @@ void CL_Init( void ) { // userinfo Cvar_Get ("name", Sys_GetCurrentUser( ), CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("color1", "4", CVAR_USERINFO | CVAR_ARCHIVE ); @@ -3441,7 +3440,7 @@ void CL_Init( void ) { // just demand it. Who doesn't have at least a DSL line now, anyhow? If // you don't, you don't need VoIP. :) if ((cl_voip->integer) && (Cvar_VariableIntegerValue("rate") < 25000)) { - Com_Printf("Your network rate is too slow for VoIP.\n"); + Com_Printf(S_COLOR_YELLOW "Your network rate is too slow for VoIP.\n"); Com_Printf("Set 'Data Rate' to 'LAN/Cable/xDSL' in 'Setup/System/Network' and restart.\n"); Com_Printf("Until then, VoIP is disabled.\n"); Cvar_Set("cl_voip", "0"); @@ -3504,14 +3503,14 @@ CL_Shutdown =============== */ -void CL_Shutdown( void ) { +void CL_Shutdown( char *finalmsg ) { static qboolean recursive = qfalse; // check whether the client is running at all. if(!(com_cl_running && com_cl_running->integer)) return; - Com_Printf( "----- CL_Shutdown -----\n" ); + Com_Printf( "----- Client Shutdown (%s) -----\n", finalmsg ); if ( recursive ) { Com_Printf( "WARNING: Recursive shutdown\n" ); diff --git a/src/client/cl_scrn.c b/src/client/cl_scrn.c index a5769b0d..c8568472 100644 --- a/src/client/cl_scrn.c +++ b/src/client/cl_scrn.c @@ -549,8 +549,10 @@ void SCR_UpdateScreen( void ) { // that case. if( uivm || com_dedicated->integer ) { + // XXX + extern cvar_t* r_anaglyphMode; // if running in stereo, we need to draw the frame twice - if ( cls.glconfig.stereoEnabled || Cvar_VariableIntegerValue("r_anaglyphMode")) { + if ( cls.glconfig.stereoEnabled || r_anaglyphMode->integer) { SCR_DrawScreenField( STEREO_LEFT ); SCR_DrawScreenField( STEREO_RIGHT ); } else { diff --git a/src/client/libmumblelink.c b/src/client/libmumblelink.c index 1b1e521e..10e90011 100644 --- a/src/client/libmumblelink.c +++ b/src/client/libmumblelink.c @@ -112,6 +112,7 @@ int mumble_link(const char* name) } close(shmfd); #endif + memset(lm, 0, sizeof(LinkedMem)); mbstowcs(lm->name, name, sizeof(lm->name)); return 0; @@ -128,12 +129,12 @@ void mumble_update_coordinates2(float fAvatarPosition[3], float fAvatarFront[3], if (!lm) return; - memcpy(lm->fAvatarPosition, fAvatarPosition, sizeof(fAvatarPosition)); - memcpy(lm->fAvatarFront, fAvatarFront, sizeof(fAvatarFront)); - memcpy(lm->fAvatarTop, fAvatarTop, sizeof(fAvatarTop)); - memcpy(lm->fCameraPosition, fCameraPosition, sizeof(fCameraPosition)); - memcpy(lm->fCameraFront, fCameraFront, sizeof(fCameraFront)); - memcpy(lm->fCameraTop, fCameraTop, sizeof(fCameraTop)); + memcpy(lm->fAvatarPosition, fAvatarPosition, sizeof(lm->fAvatarPosition)); + memcpy(lm->fAvatarFront, fAvatarFront, sizeof(lm->fAvatarFront)); + memcpy(lm->fAvatarTop, fAvatarTop, sizeof(lm->fAvatarTop)); + memcpy(lm->fCameraPosition, fCameraPosition, sizeof(lm->fCameraPosition)); + memcpy(lm->fCameraFront, fCameraFront, sizeof(lm->fCameraFront)); + memcpy(lm->fCameraTop, fCameraTop, sizeof(lm->fCameraTop)); lm->uiVersion = 2; lm->uiTick = GetTickCount(); } @@ -152,6 +153,7 @@ void mumble_set_context(const unsigned char* context, size_t len) if (!lm) return; len = MIN(sizeof(lm->context), len); + lm->context_len = len; memcpy(lm->context, context, len); } diff --git a/src/client/snd_openal.c b/src/client/snd_openal.c index b0e7cae6..6f48713f 100644 --- a/src/client/snd_openal.c +++ b/src/client/snd_openal.c @@ -128,6 +128,7 @@ typedef struct alSfx_s snd_info_t info; // information for this sound like rate, sample count.. qboolean isDefault; // Couldn't be loaded - use default FX + qboolean isDefaultChecked; // Sound has been check if it isDefault qboolean inMemory; // Sound is stored in memory qboolean isLocked; // Sound is locked (can not be unloaded) int lastUsedTime; // Time last used @@ -294,7 +295,7 @@ static qboolean S_AL_BufferEvict( void ) S_AL_BufferLoad ================= */ -static void S_AL_BufferLoad(sfxHandle_t sfx) +static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache) { ALenum error; ALuint format; @@ -302,7 +303,6 @@ static void S_AL_BufferLoad(sfxHandle_t sfx) void *data; snd_info_t info; alSfx_t *curSfx = &knownSfx[sfx]; - int size_per_sec; // Nothing? if(curSfx->filename[0] == '\0') @@ -313,7 +313,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx) return; // Already done? - if((curSfx->inMemory) || (curSfx->isDefault)) + if((curSfx->inMemory) || (curSfx->isDefault) || (!cache && curSfx->isDefaultChecked)) return; // Try to load @@ -324,9 +324,14 @@ static void S_AL_BufferLoad(sfxHandle_t sfx) return; } - size_per_sec = info.rate * info.channels * info.width; - if( size_per_sec > 0 ) - curSfx->duration = (int)(1000.0f * ((double)info.size / size_per_sec)); + curSfx->isDefaultChecked = qtrue; + + if (!cache) + { + // Don't create AL cache + Z_Free(data); + return; + } format = S_AL_Format(info.width, info.channels); @@ -402,7 +407,7 @@ void S_AL_BufferUse(sfxHandle_t sfx) return; if((!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault)) - S_AL_BufferLoad(sfx); + S_AL_BufferLoad(sfx, qtrue); knownSfx[sfx].lastUsedTime = Sys_Milliseconds(); } @@ -468,10 +473,14 @@ sfxHandle_t S_AL_RegisterSound( const char *sample, qboolean compressed ) { sfxHandle_t sfx = S_AL_BufferFind(sample); - if( s_alPrecache->integer && (!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault)) - S_AL_BufferLoad(sfx); + if((!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault)) + S_AL_BufferLoad(sfx, s_alPrecache->integer); knownSfx[sfx].lastUsedTime = Com_Milliseconds(); + if (knownSfx[sfx].isDefault) { + return 0; + } + return sfx; } diff --git a/src/jpeg-6b/jinclude.h b/src/jpeg-6b/jinclude.h index 1c5515cd..33d2cd5b 100644 --- a/src/jpeg-6b/jinclude.h +++ b/src/jpeg-6b/jinclude.h @@ -14,6 +14,9 @@ * JPEG library. Most applications need only include jpeglib.h. */ +#ifdef __WIN64__ +#include "basetsd.h" +#endif #ifdef _MSC_VER diff --git a/src/jpeg-6b/jmorecfg.h b/src/jpeg-6b/jmorecfg.h index f8020071..d677127d 100644 --- a/src/jpeg-6b/jmorecfg.h +++ b/src/jpeg-6b/jmorecfg.h @@ -158,9 +158,11 @@ typedef short INT16; /* INT32 must hold at least signed 32-bit values. */ /* MinGW basetsd.h defines INT32 - don't redefine it */ -#if !(defined __MINGW32__ && defined _BASETSD_H) +#ifndef __WIN64 +#if !(defined __MINGW32__ && (defined _BASETSD_H || defined _BASETSD_H_)) typedef long INT32; #endif +#endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore diff --git a/src/null/null_client.c b/src/null/null_client.c index 5c96ccb0..aca14061 100644 --- a/src/null/null_client.c +++ b/src/null/null_client.c @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *cl_shownet; -void CL_Shutdown( void ) { +void CL_Shutdown( char *finalmsg ) { } void CL_Init( void ) { diff --git a/src/qcommon/common.c b/src/qcommon/common.c index d9fb4495..38902e92 100644 --- a/src/qcommon/common.c +++ b/src/qcommon/common.c @@ -82,6 +82,7 @@ cvar_t *com_unfocused; cvar_t *com_maxfpsUnfocused; cvar_t *com_minimized; cvar_t *com_maxfpsMinimized; +cvar_t *com_abnormalExit; // com_speeds times int time_game; @@ -238,7 +239,7 @@ void QDECL Com_DPrintf( const char *fmt, ...) { Com_Error Both client and server can use this, and it will -do the apropriate things. +do the appropriate thing. ============= */ void QDECL Com_Error( int code, const char *fmt, ... ) { @@ -323,7 +324,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) { com_errorEntered = qfalse; longjmp (abortframe, -1); } else { - CL_Shutdown (); + CL_Shutdown (va("Client fatal crashed: %s", com_errorMessage)); SV_Shutdown (va("Server fatal crashed: %s", com_errorMessage)); } @@ -347,7 +348,7 @@ void Com_Quit_f( void ) { char *p = Cmd_Args( ); if ( !com_errorEntered ) { SV_Shutdown (p[0] ? p : "Server quit"); - CL_Shutdown (); + CL_Shutdown (p[0] ? p : "Client quit"); Com_Shutdown (); FS_Shutdown(qtrue); } @@ -2616,12 +2617,25 @@ void Com_Init( char *commandLine ) { com_maxfpsUnfocused = Cvar_Get( "com_maxfpsUnfocused", "0", CVAR_ARCHIVE ); com_minimized = Cvar_Get( "com_minimized", "0", CVAR_ROM ); com_maxfpsMinimized = Cvar_Get( "com_maxfpsMinimized", "0", CVAR_ARCHIVE ); + com_abnormalExit = Cvar_Get( "com_abnormalExit", "0", CVAR_ROM ); s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ ); com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO ); Sys_Init(); + if( Sys_WritePIDFile( ) ) { +#ifndef DEDICATED + const char *message = "The last time " CLIENT_WINDOW_TITLE " ran, " + "it didn't exit properly. This may be due to inappropriate video " + "settings. Would you like to start with \"safe\" video settings?"; + + if( Sys_Dialog( DT_YES_NO, message, "Abnormal Exit" ) == DR_YES ) { + Cvar_Set( "com_abnormalExit", "1" ); + } +#endif + } + // Pick a random port value Com_RandomBytes( (byte*)&qport, sizeof(int) ); Netchan_Init( qport & 0xffff ); diff --git a/src/qcommon/msg.c b/src/qcommon/msg.c index c85360c4..ba956bc8 100644 --- a/src/qcommon/msg.c +++ b/src/qcommon/msg.c @@ -1033,6 +1033,10 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]); lc = MSG_ReadByte(msg); + if ( lc > numFields || lc < 0 ) { + Com_Error( ERR_DROP, "invalid entityState field count" ); + } + // shownet 2/3 will interleave with other printed info, -1 will // just print the delta records` if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 ) { @@ -1352,6 +1356,10 @@ void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *t numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] ); lc = MSG_ReadByte(msg); + if ( lc > numFields || lc < 0 ) { + Com_Error( ERR_DROP, "invalid playerState field count" ); + } + for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) { fromF = (int *)( (byte *)from + field->offset ); toF = (int *)( (byte *)to + field->offset ); diff --git a/src/qcommon/net_ip.c b/src/qcommon/net_ip.c index 2be40a86..c1e527c5 100644 --- a/src/qcommon/net_ip.c +++ b/src/qcommon/net_ip.c @@ -310,11 +310,11 @@ static qboolean Sys_StringToSockaddr(const char *s, struct sockaddr *sadr, int s if(search) { - if(res->ai_addrlen > sadr_len) - res->ai_addrlen = sadr_len; + if(search->ai_addrlen > sadr_len) + search->ai_addrlen = sadr_len; - memcpy(sadr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); + memcpy(sadr, search->ai_addr, search->ai_addrlen); + freeaddrinfo(search); return qtrue; } @@ -853,9 +853,6 @@ int NET_IPSocket( char *net_interface, int port, int *err ) { // make it broadcast capable if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i) ) == SOCKET_ERROR ) { Com_Printf( "WARNING: NET_IPSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString() ); - - // it is not that bad if this one fails. -// return newsocket; } if( !net_interface || !net_interface[0]) { @@ -1035,28 +1032,28 @@ void NET_JoinMulticast6(void) if(curgroup.ipv6mr_interface) { if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_MULTICAST_IF, - (char *) &curgroup.ipv6mr_interface, sizeof(curgroup.ipv6mr_interface)) < 0) + (char *) &curgroup.ipv6mr_interface, sizeof(curgroup.ipv6mr_interface)) < 0) { - Com_Printf("NET_JoinMulticast6: Couldn't set scope on multicast socket: %s\n", NET_ErrorString()); + Com_Printf("NET_JoinMulticast6: Couldn't set scope on multicast socket: %s\n", NET_ErrorString()); - if(multicast6_socket != ip6_socket) - { - closesocket(multicast6_socket); - multicast6_socket = INVALID_SOCKET; - return; + if(multicast6_socket != ip6_socket) + { + closesocket(multicast6_socket); + multicast6_socket = INVALID_SOCKET; + return; } } - } - - if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &curgroup, sizeof(curgroup))) - { - Com_Printf("NET_JoinMulticast6: Couldn't join multicast group: %s\n", NET_ErrorString()); - - if(multicast6_socket != ip6_socket) - { - closesocket(multicast6_socket); - multicast6_socket = INVALID_SOCKET; - return; + } + + if (setsockopt(multicast6_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *) &curgroup, sizeof(curgroup))) + { + Com_Printf("NET_JoinMulticast6: Couldn't join multicast group: %s\n", NET_ErrorString()); + + if(multicast6_socket != ip6_socket) + { + closesocket(multicast6_socket); + multicast6_socket = INVALID_SOCKET; + return; } } } @@ -1253,10 +1250,10 @@ void NET_OpenSocks( int port ) { /* ===================== -NET_GetLocalAddress +NET_AddLocalAddress ===================== */ -void NET_AddLocalAddress(char *ifname, struct sockaddr *addr, struct sockaddr *netmask) +static void NET_AddLocalAddress(char *ifname, struct sockaddr *addr, struct sockaddr *netmask) { int addrlen; sa_family_t family; @@ -1294,7 +1291,7 @@ void NET_AddLocalAddress(char *ifname, struct sockaddr *addr, struct sockaddr *n } #if defined(__linux__) || defined(MACOSX) || defined(__BSD__) -void NET_GetLocalAddress(void) +static void NET_GetLocalAddress(void) { struct ifaddrs *ifap, *search; @@ -1315,10 +1312,10 @@ void NET_GetLocalAddress(void) } } #else -void NET_GetLocalAddress( void ) { +static void NET_GetLocalAddress( void ) { char hostname[256]; - struct addrinfo hint; - struct addrinfo *res = NULL; + struct addrinfo hint; + struct addrinfo *res = NULL; if(gethostname( hostname, 256 ) == SOCKET_ERROR) return; @@ -1334,7 +1331,7 @@ void NET_GetLocalAddress( void ) { { struct sockaddr_in mask4; struct sockaddr_in6 mask6; - struct addrinfo *search; + struct addrinfo *search; /* On operating systems where it's more difficult to find out the configured interfaces, we'll just assume a * netmask with all bits set. */ @@ -1476,27 +1473,27 @@ static qboolean NET_GetCvars( void ) { #else net_mcast6iface = Cvar_Get( "net_mcast6iface", "", CVAR_LATCH | CVAR_ARCHIVE ); #endif - modified += net_mcast6iface->modified; + modified += net_mcast6iface->modified; net_mcast6iface->modified = qfalse; net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE ); - modified += net_socksEnabled->modified; + modified += net_socksEnabled->modified; net_socksEnabled->modified = qfalse; net_socksServer = Cvar_Get( "net_socksServer", "", CVAR_LATCH | CVAR_ARCHIVE ); - modified += net_socksServer->modified; + modified += net_socksServer->modified; net_socksServer->modified = qfalse; net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE ); - modified += net_socksPort->modified; + modified += net_socksPort->modified; net_socksPort->modified = qfalse; net_socksUsername = Cvar_Get( "net_socksUsername", "", CVAR_LATCH | CVAR_ARCHIVE ); - modified += net_socksUsername->modified; + modified += net_socksUsername->modified; net_socksUsername->modified = qfalse; net_socksPassword = Cvar_Get( "net_socksPassword", "", CVAR_LATCH | CVAR_ARCHIVE ); - modified += net_socksPassword->modified; + modified += net_socksPassword->modified; net_socksPassword->modified = qfalse; return modified ? qtrue : qfalse; diff --git a/src/qcommon/q_platform.h b/src/qcommon/q_platform.h index 9405e749..4d4d2856 100644 --- a/src/qcommon/q_platform.h +++ b/src/qcommon/q_platform.h @@ -73,9 +73,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // for windows fastcall option #define QDECL -//================================================================= WIN32 === +//================================================================= WIN64/32 === -#ifdef _WIN32 +#if defined(_WIN64) || defined(__WIN64__) + +#undef QDECL +#define QDECL __cdecl + +#if defined( _MSC_VER ) +#define OS_STRING "win_msvc64" +#elif defined __MINGW64__ +#define OS_STRING "win_mingw64" +#endif + +#define ID_INLINE inline +#define PATH_SEP '\\' + +#if defined( __WIN64__ ) +#define ARCH_STRING "x86_64" +#elif defined _M_ALPHA +#define ARCH_STRING "AXP" +#endif + +#define Q3_LITTLE_ENDIAN + +#define DLL_EXT ".dll" + +#elif defined(_WIN32) || defined(__WIN32__) #undef QDECL #define QDECL __cdecl @@ -120,6 +144,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #elif defined __i386__ #define ARCH_STRING "x86" #define Q3_LITTLE_ENDIAN +#elif defined __x86_64__ +#define ARCH_STRING "x86_64" +#define Q3_LITTLE_ENDIAN #endif #define DLL_EXT ".dylib" @@ -201,7 +228,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifdef __i386__ #define ARCH_STRING "x86" #elif defined __amd64__ -#define ARCH_STRING "x86_64" +#define ARCH_STRING "amd64" #elif defined __axp__ #define ARCH_STRING "alpha" #endif diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h index 44685582..3f2cb9d5 100644 --- a/src/qcommon/q_shared.h +++ b/src/qcommon/q_shared.h @@ -184,6 +184,8 @@ typedef int clipHandle_t; #define MAX_QINT 0x7fffffff #define MIN_QINT (-MAX_QINT-1) +#define ARRAY_LEN(x) (sizeof(x) / sizeof(*x)) + // angle indexes #define PITCH 0 // up / down diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h index 18f4c5e5..09132159 100644 --- a/src/qcommon/qcommon.h +++ b/src/qcommon/qcommon.h @@ -179,7 +179,7 @@ qboolean NET_CompareBaseAdrMask(netadr_t a, netadr_t b, int netmask); qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b); qboolean NET_IsLocalAddress (netadr_t adr); const char *NET_AdrToString (netadr_t a); -const char *NET_AdrToStringwPort (netadr_t a); +const char *NET_AdrToStringwPort (netadr_t a); int NET_StringToAdr ( const char *s, netadr_t *a, netadrtype_t family); qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, msg_t *net_message); void NET_JoinMulticast6(void); @@ -923,7 +923,7 @@ void CL_InitKeyCommands( void ); void CL_Init( void ); void CL_Disconnect( qboolean showMainMenu ); -void CL_Shutdown( void ); +void CL_Shutdown( char *finalmsg ); void CL_Frame( int msec ); qboolean CL_GameCommand( void ); void CL_KeyEvent (int key, qboolean down, unsigned time); @@ -1072,6 +1072,7 @@ char *Sys_DefaultAppPath(void); void Sys_SetDefaultHomePath(const char *path); char *Sys_DefaultHomePath(void); +const char *Sys_TempPath(void); const char *Sys_Dirname( char *path ); const char *Sys_Basename( char *path ); char *Sys_ConsoleInput(void); @@ -1084,6 +1085,27 @@ qboolean Sys_LowPhysicalMemory( void ); void Sys_SetEnv(const char *name, const char *value); +typedef enum +{ + DR_YES = 0, + DR_NO = 1, + DR_OK = 0, + DR_CANCEL = 1 +} dialogResult_t; + +typedef enum +{ + DT_INFO, + DT_WARNING, + DT_ERROR, + DT_YES_NO, + DT_OK_CANCEL +} dialogType_t; + +dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title ); + +qboolean Sys_WritePIDFile( void ); + /* This is based on the Adaptive Huffman algorithm described in Sayood's Data * Compression book. The ranks are not actually stored, but implicitly defined * by the location of a node within a doubly-linked list */ diff --git a/src/qcommon/vm_interpreted.c b/src/qcommon/vm_interpreted.c index 53357f5d..2b9ffea6 100644 --- a/src/qcommon/vm_interpreted.c +++ b/src/qcommon/vm_interpreted.c @@ -517,18 +517,20 @@ nextInstruction2: //VM_LogSyscalls( (int *)&image[ programStack + 4 ] ); { - intptr_t* argptr = (intptr_t *)&image[ programStack + 4 ]; - #if __WORDSIZE == 64 - // the vm has ints on the stack, we expect - // longs so we have to convert it - intptr_t argarr[16]; - int i; - for (i = 0; i < 16; ++i) { - argarr[i] = *(int*)&image[ programStack + 4 + 4*i ]; + // the vm has ints on the stack, we expect + // pointers so we might have to convert it + if (sizeof(intptr_t) != sizeof(int)) { + intptr_t argarr[16]; + int *imagePtr = (int *)&image[programStack]; + int i; + for (i = 0; i < 16; ++i) { + argarr[i] = *(++imagePtr); + } + r = vm->systemCall( argarr ); + } else { + intptr_t* argptr = (intptr_t *)&image[ programStack + 4 ]; + r = vm->systemCall( argptr ); } - argptr = argarr; - #endif - r = vm->systemCall( argptr ); } #ifdef DEBUG_VM diff --git a/src/qcommon/vm_x86.c b/src/qcommon/vm_x86.c index dc7f5a67..41806f2a 100644 --- a/src/qcommon/vm_x86.c +++ b/src/qcommon/vm_x86.c @@ -37,7 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* need this on NX enabled systems (i386 with PAE kernel or * noexec32=on x86_64) */ -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) #define VM_X86_MMAP #endif diff --git a/src/qcommon/vm_x86_64.c b/src/qcommon/vm_x86_64.c index 93e25f6d..13c39172 100644 --- a/src/qcommon/vm_x86_64.c +++ b/src/qcommon/vm_x86_64.c @@ -24,11 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // vm_x86_64.c -- load time compiler and execution environment for x86-64 #include "vm_local.h" - -#include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> -#include <sys/wait.h> #include <sys/time.h> #include <time.h> #include <fcntl.h> @@ -36,6 +33,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include <unistd.h> #include <stdarg.h> +#include <inttypes.h> + +#ifdef __WIN64__ + #include <windows.h> + #define CROSSCALL __attribute__ ((sysv_abi))//fool the vm we're SYSV ABI + //#define __USE_MINGW_ANSI_STDIO 1 //very slow - avoid if possible +#else + #include <sys/mman.h> + #include <sys/wait.h> + #define VM_X86_64_MMAP + #define CROSSCALL +#endif + //#define DEBUG_VM #ifdef DEBUG_VM @@ -45,8 +55,6 @@ static FILE* qdasmout; #define Dfprintf(args...) #endif -#define VM_X86_64_MMAP - void assembler_set_output(char* buf); size_t assembler_get_code_size(void); void assembler_init(int pass); @@ -72,11 +80,11 @@ static void VM_Destroy_Compiled(vm_t* self); */ -static long callAsmCall(long callProgramStack, long callSyscallNum) +static int64_t CROSSCALL callAsmCall(int64_t callProgramStack, int64_t callSyscallNum) { vm_t *savedVM; - long ret = 0x77; - long args[11]; + int64_t ret = 0x77; + int64_t args[11]; // int iargs[11]; int i; @@ -232,13 +240,13 @@ void emit(const char* fmt, ...) #define CHECK_INSTR_REG(reg) \ emit("cmpl $%u, %%"#reg, header->instructionCount); \ emit("jb jmp_ok_i_%08x", instruction); \ - emit("movq $%lu, %%rax", (unsigned long)jmpviolation); \ + emit("movq $%"PRIu64", %%rax", (uint64_t)jmpviolation); \ emit("callq *%%rax"); \ emit("jmp_ok_i_%08x:", instruction); #define PREPARE_JMP(reg) \ CHECK_INSTR_REG(reg) \ - emit("movq $%lu, %%rbx", (unsigned long)vm->instructionPointers); \ + emit("movq $%"PRIu64", %%rbx", (uint64_t)vm->instructionPointers); \ emit("movl (%%rbx, %%rax, 4), %%eax"); \ emit("addq %%r10, %%rax"); @@ -250,7 +258,7 @@ void emit(const char* fmt, ...) #define JMPIARG \ CHECK_INSTR(iarg); \ - emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \ + emit("movq $%"PRIu64", %%rax", vm->codeBase+vm->instructionPointers[iarg]); \ emit("jmpq *%%rax"); #define CONST_OPTIMIZE @@ -340,7 +348,7 @@ void emit(const char* fmt, ...) emit("andl $0x%x, %%ecx", vm->dataMask &~(bytes-1)); \ emit("cmpl %%" #reg ", %%ecx"); \ emit("jz rc_ok_i_%08x", instruction); \ - emit("movq $%lu, %%rax", (unsigned long)memviolation); \ + emit("movq $%"PRIu64", %%rax", (uint64_t)memviolation); \ emit("callq *%%rax"); \ emit("rc_ok_i_%08x:", instruction); #elif 1 @@ -364,7 +372,7 @@ static void* getentrypoint(vm_t* vm) return vm->codeBase; } -static void block_copy_vm(unsigned dest, unsigned src, unsigned count) +static void CROSSCALL block_copy_vm(unsigned dest, unsigned src, unsigned count) { unsigned dataMask = currentVM->dataMask; @@ -379,20 +387,20 @@ static void block_copy_vm(unsigned dest, unsigned src, unsigned count) memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count); } -static void eop(void) +static void CROSSCALL eop(void) { Com_Error(ERR_DROP, "end of program reached without return!\n"); exit(1); } -static void jmpviolation(void) +static void CROSSCALL jmpviolation(void) { Com_Error(ERR_DROP, "program tried to execute code outside VM\n"); exit(1); } #ifdef DEBUG_VM -static void memviolation(void) +static void CROSSCALL memviolation(void) { Com_Error(ERR_DROP, "program tried to access memory outside VM\n"); exit(1); @@ -431,9 +439,19 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { { compiledOfs = assembler_get_code_size(); vm->codeLength = compiledOfs; - vm->codeBase = mmap(NULL, compiledOfs, PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); - if(vm->codeBase == (void*)-1) - Com_Error(ERR_DROP, "VM_CompileX86: can't mmap memory"); + + #ifdef VM_X86_64_MMAP + vm->codeBase = mmap(NULL, compiledOfs, PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + if(vm->codeBase == (void*)-1) + Com_Error(ERR_DROP, "VM_CompileX86: can't mmap memory"); + #elif __WIN64__ + // allocate memory with write permissions under windows. + vm->codeBase = VirtualAlloc(NULL, compiledOfs, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if(!vm->codeBase) + Com_Error(ERR_DROP, "VM_CompileX86: VirtualAlloc failed"); + #else + vm->codeBase = malloc(compiledOfs); + #endif assembler_set_output((char*)vm->codeBase); } @@ -474,7 +492,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { else if(op_argsize[op] == 1) { barg = code[pc++]; - Dfprintf(qdasmout, "%s %8hhu\n", opnames[op], barg); + Dfprintf(qdasmout, "%s %8hu\n", opnames[op], barg); } else { @@ -518,7 +536,7 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { goto emit_do_syscall; CHECK_INSTR(const_value); - emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[const_value]); + emit("movq $%"PRIu64", %%rax", vm->codeBase+vm->instructionPointers[const_value]); emit("callq *%%rax"); got_const = 0; break; @@ -559,7 +577,7 @@ emit_do_syscall: // first argument already in rdi emit("movq %%rax, %%rsi"); // second argument in rsi } - emit("movq $%lu, %%rax", (unsigned long)callAsmCall); + emit("movq $%"PRIu64", %%rax", (uint64_t)callAsmCall); emit("callq *%%rax"); emit("pop %%rbx"); emit("addq %%rbx, %%rsp"); @@ -726,7 +744,7 @@ emit_do_syscall: MAYBE_EMIT_CONST(); emit("subq $4, %%rsi"); emit("movl 4(%%rsi), %%eax"); // get value from stack - emit("movl $0x%hhx, %%ebx", barg); + emit("movl $0x%hx, %%ebx", barg); emit("addl %%edi, %%ebx"); RANGECHECK(ebx, 4); emit("movl %%eax, 0(%%r8,%%rbx, 1)"); // store in args space @@ -740,11 +758,18 @@ emit_do_syscall: emit("push %%r8"); emit("push %%r9"); emit("push %%r10"); + emit("movq %%rsp, %%rbx"); // we need to align the stack pointer + emit("subq $8, %%rbx"); // | + emit("andq $127, %%rbx"); // | + emit("subq %%rbx, %%rsp"); // <-+ + emit("push %%rbx"); emit("movl 4(%%rsi), %%edi"); // 1st argument dest emit("movl 8(%%rsi), %%esi"); // 2nd argument src emit("movl $%d, %%edx", iarg); // 3rd argument count - emit("movq $%lu, %%rax", (unsigned long)block_copy_vm); + emit("movq $%"PRIu64", %%rax", (uint64_t)block_copy_vm); emit("callq *%%rax"); + emit("pop %%rbx"); + emit("addq %%rbx, %%rsp"); emit("pop %%r10"); emit("pop %%r9"); emit("pop %%r8"); @@ -910,15 +935,25 @@ emit_do_syscall: Com_Error(ERR_DROP, "leftover const\n"); } - emit("movq $%lu, %%rax", (unsigned long)eop); + emit("movq $%"PRIu64", %%rax", (uint64_t)eop); emit("callq *%%rax"); } // pass loop assembler_init(0); - if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC)) - Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed"); + #ifdef VM_X86_64_MMAP + if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC)) + Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed"); + #elif __WIN64__ + { + DWORD oldProtect = 0; + + // remove write permissions; give exec permision + if(!VirtualProtect(vm->codeBase, compiledOfs, PAGE_EXECUTE_READ, &oldProtect)) + Com_Error(ERR_DROP, "VM_CompileX86: VirtualProtect failed"); + } + #endif vm->destroy = VM_Destroy_Compiled; @@ -935,17 +970,19 @@ emit_do_syscall: fclose(qdasmout); #endif #endif - - if(vm->compiled) - { - struct timeval tvdone = {0, 0}; - struct timeval dur = {0, 0}; - Com_Printf( "VM file %s compiled to %i bytes of code (%p - %p)\n", vm->name, vm->codeLength, vm->codeBase, vm->codeBase+vm->codeLength ); - gettimeofday(&tvdone, NULL); - timersub(&tvdone, &tvstart, &dur); - Com_Printf( "compilation took %lu.%06lu seconds\n", dur.tv_sec, dur.tv_usec ); - } + #ifndef __WIN64__ //timersub and gettimeofday + if(vm->compiled) + { + struct timeval tvdone = {0, 0}; + struct timeval dur = {0, 0}; + Com_Printf( "VM file %s compiled to %i bytes of code (%p - %p)\n", vm->name, vm->codeLength, vm->codeBase, vm->codeBase+vm->codeLength ); + + gettimeofday(&tvdone, NULL); + timersub(&tvdone, &tvstart, &dur); + Com_Printf( "compilation took %"PRIu64".%06"PRIu64" seconds\n", dur.tv_sec, dur.tv_usec ); + } + #endif } @@ -1035,7 +1072,7 @@ int VM_CallCompiled( vm_t *vm, int *args ) { ); if ( opStack != &stack[1] ) { - Com_Error( ERR_DROP, "opStack corrupted in compiled code (offset %ld)\n", (long int) ((void *) &stack[1] - opStack)); + Com_Error( ERR_DROP, "opStack corrupted in compiled code (offset %"PRId64")\n", (int64_t) ((void *) &stack[1] - opStack)); } if ( programStack != stackOnEntry - 48 ) { Com_Error( ERR_DROP, "programStack corrupted in compiled code\n" ); diff --git a/src/qcommon/vm_x86_64_assembler.c b/src/qcommon/vm_x86_64_assembler.c index 46227e6d..99d2898e 100644 --- a/src/qcommon/vm_x86_64_assembler.c +++ b/src/qcommon/vm_x86_64_assembler.c @@ -27,10 +27,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include <string.h> #include <stdarg.h> -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long u64; +#include <inttypes.h> + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; static char* out; static unsigned compiledOfs; @@ -79,7 +81,7 @@ static void emit1(unsigned char v) if(fout) writecnt = fwrite(&v, 1, 1, fout); - debug("%02hhx ", v); + debug("%02hx ", v); } else { @@ -284,7 +286,7 @@ static void labelhash_free(void) min = MIN(min, n); max = MAX(max, n); } - printf("total %u, hsize %lu, zero %u, min %u, max %u\n", t, sizeof(labelhash)/sizeof(labelhash[0]), z, min, max); + printf("total %u, hsize %"PRIu64", zero %u, min %u, max %u\n", t, sizeof(labelhash)/sizeof(labelhash[0]), z, min, max); memset(labelhash, 0, sizeof(labelhash)); } @@ -310,7 +312,7 @@ static const char* argtype2str(argtype_t t) static inline int iss8(u64 v) { - return (labs(v) <= 0x80); + return (llabs(v) <= 0x80); //llabs instead of labs required for __WIN64 } static inline int isu8(u64 v) @@ -320,7 +322,7 @@ static inline int isu8(u64 v) static inline int iss16(u64 v) { - return (labs(v) <= 0x8000); + return (llabs(v) <= 0x8000); } static inline int isu16(u64 v) @@ -330,7 +332,7 @@ static inline int isu16(u64 v) static inline int iss32(u64 v) { - return (labs(v) <= 0x80000000); + return (llabs(v) <= 0x80000000); } static inline int isu32(u64 v) @@ -340,7 +342,7 @@ static inline int isu32(u64 v) static void emit_opsingle(const char* mnemonic, arg_t arg1, arg_t arg2, void* data) { - u8 op = (u8)((unsigned long) data); + u8 op = (u8)((uint64_t) data); if(arg1.type != T_NONE || arg2.type != T_NONE) CRAP_INVALID_ARGS; @@ -503,7 +505,7 @@ static void maybe_emit_displacement(arg_t* arg) /* one byte operator with register added to operator */ static void emit_opreg(const char* mnemonic, arg_t arg1, arg_t arg2, void* data) { - u8 op = (u8)((unsigned long) data); + u8 op = (u8)((uint64_t) data); if(arg1.type != T_REGISTER || arg2.type != T_NONE) CRAP_INVALID_ARGS; @@ -756,7 +758,7 @@ static void emit_condjump(const char* mnemonic, arg_t arg1, arg_t arg2, void* da { unsigned off; int disp; - unsigned char opcode = (unsigned char)(((unsigned long)data)&0xFF); + unsigned char opcode = (unsigned char)(((uint64_t)data)&0xFF); if(arg1.type != T_LABEL || arg2.type != T_NONE) crap("%s: argument must be label", mnemonic); @@ -1153,7 +1155,7 @@ static unsigned char nexttok(const char** str, char* label, u64* val) else if(*s >= '0' && *s <= '9') { char* endptr = NULL; - u64 v = strtol(s, &endptr, 0); + u64 v = strtoull(s, &endptr, 0); if(endptr && (endptr-s == 0)) crap("invalid integer %s", s); if(val) *val = v; @@ -1274,7 +1276,7 @@ tok_memory: } break; default: - crap("invalid token %hhu in %s", *(unsigned char*)s, *str); + crap("invalid token %hu in %s", *(unsigned char*)s, *str); break; } diff --git a/src/renderer/tr_model.c b/src/renderer/tr_model.c index 70660583..b02d52a4 100644 --- a/src/renderer/tr_model.c +++ b/src/renderer/tr_model.c @@ -563,8 +563,8 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char ((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] ); } - curframe++; - frame++; + curframe = (mdrFrame_t *) &curframe->bones[mdr->numBones]; + frame = (mdrFrame_t *) &frame->bones[mdr->numBones]; } } diff --git a/src/renderer/tr_shade_calc.c b/src/renderer/tr_shade_calc.c index c3de88cc..ba61a6df 100644 --- a/src/renderer/tr_shade_calc.c +++ b/src/renderer/tr_shade_calc.c @@ -360,10 +360,10 @@ static void AutospriteDeform( void ) { vec3_t leftDir, upDir; if ( tess.numVertexes & 3 ) { - ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd vertex count", tess.shader->name ); + ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd vertex count\n", tess.shader->name ); } if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) { - ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count", tess.shader->name ); + ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count\n", tess.shader->name ); } oldVerts = tess.numVertexes; diff --git a/src/renderer/tr_shader.c b/src/renderer/tr_shader.c index 8e86a73f..bfcd47d3 100644 --- a/src/renderer/tr_shader.c +++ b/src/renderer/tr_shader.c @@ -2328,11 +2328,15 @@ static char *FindShaderInShaderText( const char *shadername ) { hash = generateHashValue(shadername, MAX_SHADERTEXT_HASH); - for (i = 0; shaderTextHashTable[hash][i]; i++) { - p = shaderTextHashTable[hash][i]; - token = COM_ParseExt(&p, qtrue); - if ( !Q_stricmp( token, shadername ) ) { - return p; + if(shaderTextHashTable[hash]) + { + for (i = 0; shaderTextHashTable[hash][i]; i++) + { + p = shaderTextHashTable[hash][i]; + token = COM_ParseExt(&p, qtrue); + + if(!Q_stricmp(token, shadername)) + return p; } } @@ -2867,7 +2871,6 @@ void R_ShaderList_f (void) { ri.Printf (PRINT_ALL, "------------------\n"); } - /* ==================== ScanAndLoadShaderFiles @@ -2884,7 +2887,7 @@ static void ScanAndLoadShaderFiles( void ) char *p; int numShaderFiles; int i; - char *oldp, *token, *hashMem; + char *oldp, *token, *hashMem, *textEnd; int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size; long sum = 0, summand; @@ -2945,20 +2948,22 @@ static void ScanAndLoadShaderFiles( void ) // build single large buffer s_shaderText = ri.Hunk_Alloc( sum + numShaderFiles*2, h_low ); s_shaderText[ 0 ] = '\0'; - + textEnd = s_shaderText; + // free in reverse order, so the temp files are all dumped for ( i = numShaderFiles - 1; i >= 0 ; i-- ) { - if(buffers[i]) - { - p = &s_shaderText[strlen(s_shaderText)]; - strcat( s_shaderText, buffers[i] ); - ri.FS_FreeFile( buffers[i] ); - COM_Compress(p); - strcat( s_shaderText, "\n" ); - } + if ( !buffers[i] ) + continue; + + strcat( textEnd, buffers[i] ); + strcat( textEnd, "\n" ); + textEnd += strlen( textEnd ); + ri.FS_FreeFile( buffers[i] ); } + COM_Compress( s_shaderText ); + // free up memory ri.FS_FreeFileList( shaderFiles ); diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index cfc10153..f065eb2d 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -691,6 +691,15 @@ void GLimp_Init( void ) r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE ); r_centerWindow = ri.Cvar_Get( "r_centerWindow", "0", CVAR_ARCHIVE ); + if( Cvar_VariableIntegerValue( "com_abnormalExit" ) ) + { + ri.Cvar_Set( "r_width", va( "%d", R_FAILSAFE_WIDTH ) ); + ri.Cvar_Set( "r_height", va( "%d", R_FAILSAFE_HEIGHT ) ); + ri.Cvar_Set( "r_fullscreen", "0" ); + ri.Cvar_Set( "r_centerWindow", "0" ); + ri.Cvar_Set( "com_abnormalExit", "0" ); + } + Sys_SetEnv( "SDL_VIDEO_CENTERED", r_centerWindow->integer ? "1" : "" ); Sys_GLimpInit( ); diff --git a/src/sdl/sdl_input.c b/src/sdl/sdl_input.c index ec96b086..0d1164fb 100644 --- a/src/sdl/sdl_input.c +++ b/src/sdl/sdl_input.c @@ -949,7 +949,7 @@ static void IN_ProcessEvents( void ) break; case SDL_QUIT: - Sys_Quit( ); + Cbuf_ExecuteText(EXEC_NOW, "quit Closed window\n"); break; case SDL_VIDEORESIZE: @@ -965,6 +965,14 @@ static void IN_ProcessEvents( void ) vidRestartTime = Sys_Milliseconds() + 1000; } break; + case SDL_ACTIVEEVENT: + if (e.active.state & SDL_APPINPUTFOCUS) { + Cvar_SetValue( "com_unfocused", !e.active.gain); + } + if (e.active.state & SDL_APPACTIVE) { + Cvar_SetValue( "com_minimized", !e.active.gain); + } + break; default: break; @@ -1034,6 +1042,8 @@ IN_Init */ void IN_Init( void ) { + int appState; + if( !SDL_WasInit( SDL_INIT_VIDEO ) ) { Com_Error( ERR_FATAL, "IN_Init called before SDL_Init( SDL_INIT_VIDEO )\n" ); @@ -1071,6 +1081,10 @@ void IN_Init( void ) mouseAvailable = qfalse; } + appState = SDL_GetAppState( ); + Cvar_SetValue( "com_unfocused", !( appState & SDL_APPINPUTFOCUS ) ); + Cvar_SetValue( "com_minimized", !( appState & SDL_APPACTIVE ) ); + IN_InitJoystick( ); Com_DPrintf( "------------------------------------\n" ); } diff --git a/src/server/sv_client.c b/src/server/sv_client.c index 1448822c..815bf4db 100644 --- a/src/server/sv_client.c +++ b/src/server/sv_client.c @@ -1272,7 +1272,7 @@ void SV_ExecuteClientCommand( client_t *cl, const char *s, qboolean clientOK ) { if (clientOK) { // pass unknown strings to the game - if (!u->name && sv.state == SS_GAME) { + if (!u->name && sv.state == SS_GAME && cl->state == CS_ACTIVE) { VM_Call( gvm, GAME_CLIENT_COMMAND, cl - svs.clients ); } } diff --git a/src/server/sv_main.c b/src/server/sv_main.c index 4363e532..fa009b62 100644 --- a/src/server/sv_main.c +++ b/src/server/sv_main.c @@ -701,7 +701,7 @@ static void SVC_RemoteCommand( netadr_t from, msg_t *msg ) { // Prevent using rcon as an amplifier and make dictionary attacks impractical if ( SVC_RateLimitAddress( from, 10, 1000 ) ) { - Com_DPrintf( "SVC_Status: rate limit from %s exceeded, dropping request\n", + Com_DPrintf( "SVC_RemoteCommand: rate limit from %s exceeded, dropping request\n", NET_AdrToString( from ) ); return; } @@ -712,7 +712,7 @@ static void SVC_RemoteCommand( netadr_t from, msg_t *msg ) { // Make DoS via rcon impractical if ( SVC_RateLimit( &bucket, 10, 1000 ) ) { - Com_DPrintf( "SVC_Status: rate limit exceeded, dropping request\n" ); + Com_DPrintf( "SVC_RemoteCommand: rate limit exceeded, dropping request\n" ); return; } diff --git a/src/sys/sys_cocoa.m b/src/sys/sys_cocoa.m deleted file mode 100644 index cfc754dd..00000000 --- a/src/sys/sys_cocoa.m +++ /dev/null @@ -1,40 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#ifndef MACOS_X -#error This file is for Mac OS X only. You probably should not compile it. -#endif - -// Please note that this file is just some Mac-specific bits. Most of the -// Mac OS X code is shared with other Unix platforms in sys_unix.c ... - -#import <Cocoa/Cocoa.h> - -void Cocoa_MsgBox( const char *text ) -{ - NSRunInformationalAlertPanel(@"ioquake3", - [NSString stringWithUTF8String:text], - @"OK", nil, nil); -} - -// end of sys_cocoa.m ... - diff --git a/src/sys/sys_local.h b/src/sys/sys_local.h index 6017150a..9f4de9cf 100644 --- a/src/sys/sys_local.h +++ b/src/sys/sys_local.h @@ -55,3 +55,6 @@ void Sys_PlatformInit( void ); void Sys_SigHandler( int signal ); void Sys_ErrorDialog( const char *error ); void Sys_AnsiColorPrint( const char *msg ); + +int Sys_PID( void ); +qboolean Sys_PIDIsRunning( int pid ); diff --git a/src/sys/sys_main.c b/src/sys/sys_main.c index 460e8a22..53fc57fb 100644 --- a/src/sys/sys_main.c +++ b/src/sys/sys_main.c @@ -128,6 +128,65 @@ char *Sys_ConsoleInput(void) return CON_Input( ); } +#ifdef DEDICATED +# define PID_FILENAME PRODUCT_NAME "_server.pid" +#else +# define PID_FILENAME PRODUCT_NAME ".pid" +#endif + +/* +================= +Sys_PIDFileName +================= +*/ +static char *Sys_PIDFileName( void ) +{ + return va( "%s/%s", Sys_TempPath( ), PID_FILENAME ); +} + +/* +================= +Sys_WritePIDFile + +Return qtrue if there is an existing stale PID file +================= +*/ +qboolean Sys_WritePIDFile( void ) +{ + char *pidFile = Sys_PIDFileName( ); + FILE *f; + qboolean stale = qfalse; + + // First, check if the pid file is already there + if( ( f = fopen( pidFile, "r" ) ) != NULL ) + { + char pidBuffer[ 64 ] = { 0 }; + int pid; + + pid = fread( pidBuffer, sizeof( char ), sizeof( pidBuffer ) - 1, f ); + fclose( f ); + + if(pid > 0) + { + pid = atoi( pidBuffer ); + if( !Sys_PIDIsRunning( pid ) ) + stale = qtrue; + } + else + stale = qtrue; + } + + if( ( f = fopen( pidFile, "w" ) ) != NULL ) + { + fprintf( f, "%d", Sys_PID( ) ); + fclose( f ); + } + else + Com_Printf( S_COLOR_YELLOW "Couldn't write %s.\n", pidFile ); + + return stale; +} + /* ================= Sys_Exit @@ -135,7 +194,7 @@ Sys_Exit Single exit point (regular exit or in case of error) ================= */ -void Sys_Exit( int ex ) +static void Sys_Exit( int exitCode ) { CON_Shutdown( ); @@ -143,13 +202,13 @@ void Sys_Exit( int ex ) SDL_Quit( ); #endif -#ifdef NDEBUG - exit( ex ); -#else - // Cause a backtrace on error exits - assert( ex == 0 ); - exit( ex ); -#endif + if( exitCode < 2 ) + { + // Normal exit + remove( Sys_PIDFileName( ) ); + } + + exit( exitCode ); } /* @@ -159,7 +218,6 @@ Sys_Quit */ void Sys_Quit( void ) { - CL_Shutdown( ); Sys_Exit( 0 ); } @@ -288,15 +346,14 @@ void Sys_Error( const char *error, ... ) va_list argptr; char string[1024]; - CL_Shutdown (); - va_start (argptr,error); Q_vsnprintf (string, sizeof(string), error, argptr); va_end (argptr); + CL_Shutdown( string ); Sys_ErrorDialog( string ); - Sys_Exit( 1 ); + Sys_Exit( 3 ); } /* @@ -451,7 +508,7 @@ void Sys_ParseArgs( int argc, char **argv ) #else fprintf( stdout, Q3_VERSION " client (%s)\n", date ); #endif - Sys_Exit(0); + Sys_Exit( 0 ); } } } @@ -481,14 +538,16 @@ void Sys_SigHandler( int signal ) else { signalcaught = qtrue; - fprintf( stderr, "Received signal %d, exiting...\n", signal ); #ifndef DEDICATED - CL_Shutdown(); + CL_Shutdown( va( "Received signal %d", signal ) ); #endif - SV_Shutdown( "Signal caught" ); + SV_Shutdown( va( "Received signal %d", signal ) ); } - Sys_Exit( 0 ); // Exit with 0 to avoid recursive signals + if( signal == SIGTERM || signal == SIGINT ) + Sys_Exit( 1 ); + else + Sys_Exit( 2 ); } /* @@ -520,7 +579,10 @@ int main( int argc, char **argv ) if( SDL_VERSIONNUM( ver->major, ver->minor, ver->patch ) < SDL_VERSIONNUM( MINSDL_MAJOR, MINSDL_MINOR, MINSDL_PATCH ) ) { - Sys_Print( "SDL version " MINSDL_VERSION " or greater required\n" ); + Sys_Dialog( DT_ERROR, va( "SDL version " MINSDL_VERSION " or greater is required, " + "but only version %d.%d.%d was found. You may be able to obtain a more recent copy " + "from http://www.libsdl.org/.", ver->major, ver->minor, ver->patch ), "SDL Library Too Old" ); + Sys_Exit( 1 ); } #endif @@ -562,13 +624,6 @@ int main( int argc, char **argv ) while( 1 ) { -#ifndef DEDICATED - int appState = SDL_GetAppState( ); - - Cvar_SetValue( "com_unfocused", !( appState & SDL_APPINPUTFOCUS ) ); - Cvar_SetValue( "com_minimized", !( appState & SDL_APPACTIVE ) ); -#endif - IN_Frame( ); Com_Frame( ); } diff --git a/src/sys/sys_unix.c b/src/sys/sys_unix.c index ccff6312..5ab0f8c7 100644 --- a/src/sys/sys_unix.c +++ b/src/sys/sys_unix.c @@ -69,6 +69,23 @@ char *Sys_DefaultHomePath(void) return homePath; } +#ifndef MACOS_X +/* +================ +Sys_TempPath +================ +*/ +const char *Sys_TempPath( void ) +{ + const char *TMPDIR = getenv( "TMPDIR" ); + + if( TMPDIR == NULL || TMPDIR[ 0 ] == '\0' ) + return "/tmp"; + else + return TMPDIR; +} +#endif + /* ================ Sys_Milliseconds @@ -76,8 +93,7 @@ Sys_Milliseconds */ /* base time in seconds, that's our origin timeval:tv_sec is an int: - assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038 - using unsigned long data type to work right with Sys_XTimeToSysTime */ + assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038 */ unsigned long sys_timeBase = 0; /* current time in ms, using sys_timeBase as origin NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch @@ -429,35 +445,6 @@ void Sys_FreeFileList( char **list ) Z_Free( list ); } -#ifdef MACOS_X -/* -================= -Sys_StripAppBundle - -Discovers if passed dir is suffixed with the directory structure of a Mac OS X -.app bundle. If it is, the .app directory structure is stripped off the end and -the result is returned. If not, dir is returned untouched. -================= -*/ -char *Sys_StripAppBundle( char *dir ) -{ - static char cwd[MAX_OSPATH]; - - Q_strncpyz(cwd, dir, sizeof(cwd)); - if(strcmp(Sys_Basename(cwd), "MacOS")) - return dir; - Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd)); - if(strcmp(Sys_Basename(cwd), "Contents")) - return dir; - Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd)); - if(!strstr(Sys_Basename(cwd), ".app")) - return dir; - Q_strncpyz(cwd, Sys_Dirname(cwd), sizeof(cwd)); - return cwd; -} -#endif // MACOS_X - - /* ================== Sys_Sleep @@ -518,39 +505,195 @@ void Sys_ErrorDialog( const char *error ) Sys_Print( va( "%s\n", error ) ); -#if defined(MACOS_X) && !DEDICATED - /* This function has to be in a separate file, compiled as Objective-C. */ - extern void Cocoa_MsgBox( const char *text ); - if (!com_dedicated || !com_dedicated->integer) - Cocoa_MsgBox(error); +#ifndef DEDICATED + Sys_Dialog( DT_ERROR, va( "%s. See \"%s\" for details.", error, ospath ), "Error" ); #endif - /* make sure the write path for the crashlog exists... */ + // Make sure the write path for the crashlog exists... if( FS_CreatePath( ospath ) ) { Com_Printf( "ERROR: couldn't create path '%s' for crash log.\n", ospath ); return; } - /* we might be crashing because we maxed out the Quake MAX_FILE_HANDLES, - which will come through here, so we don't want to recurse forever by - calling FS_FOpenFileWrite()...use the Unix system APIs instead. */ - f = open(ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640); + // We might be crashing because we maxed out the Quake MAX_FILE_HANDLES, + // which will come through here, so we don't want to recurse forever by + // calling FS_FOpenFileWrite()...use the Unix system APIs instead. + f = open( ospath, O_CREAT | O_TRUNC | O_WRONLY, 0640 ); if( f == -1 ) { Com_Printf( "ERROR: couldn't open %s\n", fileName ); return; } - /* We're crashing, so we don't care much if write() or close() fails. */ + // We're crashing, so we don't care much if write() or close() fails. while( ( size = CON_LogRead( buffer, sizeof( buffer ) ) ) > 0 ) { - if (write( f, buffer, size ) != size) { + if( write( f, buffer, size ) != size ) { Com_Printf( "ERROR: couldn't fully write to %s\n", fileName ); break; } } - close(f); + close( f ); +} + +#ifndef MACOS_X +/* +============== +Sys_ZenityCommand +============== +*/ +static int Sys_ZenityCommand( dialogType_t type, const char *message, const char *title ) +{ + const char *options = ""; + char command[ 1024 ]; + + switch( type ) + { + default: + case DT_INFO: options = "--info"; break; + case DT_WARNING: options = "--warning"; break; + case DT_ERROR: options = "--error"; break; + case DT_YES_NO: options = "--question --ok-label=\"Yes\" --cancel-label=\"No\""; break; + case DT_OK_CANCEL: options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\""; break; + } + + Com_sprintf( command, sizeof( command ), "zenity %s --text=\"%s\" --title=\"%s\"", + options, message, title ); + + return system( command ); +} + +/* +============== +Sys_KdialogCommand +============== +*/ +static int Sys_KdialogCommand( dialogType_t type, const char *message, const char *title ) +{ + const char *options = ""; + char command[ 1024 ]; + + switch( type ) + { + default: + case DT_INFO: options = "--msgbox"; break; + case DT_WARNING: options = "--sorry"; break; + case DT_ERROR: options = "--error"; break; + case DT_YES_NO: options = "--warningyesno"; break; + case DT_OK_CANCEL: options = "--warningcontinuecancel"; break; + } + + Com_sprintf( command, sizeof( command ), "kdialog %s \"%s\" --title \"%s\"", + options, message, title ); + + return system( command ); +} + +/* +============== +Sys_XmessageCommand +============== +*/ +static int Sys_XmessageCommand( dialogType_t type, const char *message, const char *title ) +{ + const char *options = ""; + char command[ 1024 ]; + + switch( type ) + { + default: options = "-buttons OK"; break; + case DT_YES_NO: options = "-buttons Yes:0,No:1"; break; + case DT_OK_CANCEL: options = "-buttons OK:0,Cancel:1"; break; + } + + Com_sprintf( command, sizeof( command ), "xmessage -center %s \"%s\"", + options, message ); + + return system( command ); +} + +/* +============== +Sys_Dialog + +Display a *nix dialog box +============== +*/ +dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title ) +{ + typedef enum + { + NONE = 0, + ZENITY, + KDIALOG, + XMESSAGE, + NUM_DIALOG_PROGRAMS + } dialogCommandType_t; + typedef int (*dialogCommandBuilder_t)( dialogType_t, const char *, const char * ); + + const char *session = getenv( "DESKTOP_SESSION" ); + qboolean tried[ NUM_DIALOG_PROGRAMS ] = { qfalse }; + dialogCommandBuilder_t commands[ NUM_DIALOG_PROGRAMS ] = { NULL }; + dialogCommandType_t preferredCommandType = NONE; + + commands[ ZENITY ] = &Sys_ZenityCommand; + commands[ KDIALOG ] = &Sys_KdialogCommand; + commands[ XMESSAGE ] = &Sys_XmessageCommand; + + // This may not be the best way + if( !Q_stricmp( session, "gnome" ) ) + preferredCommandType = ZENITY; + else if( !Q_stricmp( session, "kde" ) ) + preferredCommandType = KDIALOG; + + while( 1 ) + { + int i; + int exitCode; + + for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ ) + { + if( preferredCommandType != NONE && preferredCommandType != i ) + continue; + + if( !tried[ i ] ) + { + exitCode = commands[ i ]( type, message, title ); + + if( exitCode >= 0 ) + { + switch( type ) + { + case DT_YES_NO: return exitCode ? DR_NO : DR_YES; + case DT_OK_CANCEL: return exitCode ? DR_CANCEL : DR_OK; + default: return DR_OK; + } + } + + tried[ i ] = qtrue; + + // The preference failed, so start again in order + if( preferredCommandType != NONE ) + { + preferredCommandType = NONE; + break; + } + } + } + + for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ ) + { + if( !tried[ i ] ) + continue; + } + + break; + } + + Com_DPrintf( S_COLOR_YELLOW "WARNING: failed to show a dialog\n" ); + return DR_OK; } +#endif /* ============== @@ -612,3 +755,23 @@ void Sys_SetEnv(const char *name, const char *value) else unsetenv(name); } + +/* +============== +Sys_PID +============== +*/ +int Sys_PID( void ) +{ + return getpid( ); +} + +/* +============== +Sys_PIDIsRunning +============== +*/ +qboolean Sys_PIDIsRunning( int pid ) +{ + return kill( pid, 0 ) == 0; +} diff --git a/src/sys/sys_win32.c b/src/sys/sys_win32.c index ead428eb..ad6f18eb 100644 --- a/src/sys/sys_win32.c +++ b/src/sys/sys_win32.c @@ -38,10 +38,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include <conio.h> #include <wincrypt.h> #include <shlobj.h> +#include <psapi.h> // Used to determine where to store user-specific files static char homePath[ MAX_OSPATH ] = { 0 }; +#ifdef __WIN64__ +void Sys_SnapVector( float *v ) +{ + v[0] = rint(v[0]); + v[1] = rint(v[1]); + v[2] = rint(v[2]); +} +#endif + /* ================ Sys_DefaultHomePath @@ -86,6 +96,24 @@ char *Sys_DefaultHomePath( void ) /* ================ +Sys_TempPath +================ +*/ +const char *Sys_TempPath( void ) +{ + static TCHAR path[ MAX_PATH ]; + DWORD length; + + length = GetTempPath( sizeof( path ), path ); + + if( length > sizeof( path ) || length == 0 ) + return Sys_DefaultHomePath( ); + else + return path; +} + +/* +================ Sys_Milliseconds ================ */ @@ -317,7 +345,7 @@ void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, ch { char search[MAX_OSPATH], newsubdirs[MAX_OSPATH]; char filename[MAX_OSPATH]; - int findhandle; + intptr_t findhandle; struct _finddata_t findinfo; if ( *numfiles >= MAX_FOUND_FILES - 1 ) { @@ -400,7 +428,7 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter char **listCopy; char *list[MAX_FOUND_FILES]; struct _finddata_t findinfo; - int findhandle; + intptr_t findhandle; int flag; int i; @@ -545,8 +573,8 @@ 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 ) + if( Sys_Dialog( DT_YES_NO, va( "%s. Copy console log to clipboard?", error ), + "Error" ) == DR_YES ) { HGLOBAL memoryHandle; char *clipMemory; @@ -577,6 +605,37 @@ void Sys_ErrorDialog( const char *error ) } } +/* +============== +Sys_Dialog + +Display a win32 dialog box +============== +*/ +dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *title ) +{ + UINT uType; + + switch( type ) + { + default: + case DT_INFO: uType = MB_ICONINFORMATION|MB_OK; break; + case DT_WARNING: uType = MB_ICONWARNING|MB_OK; break; + case DT_ERROR: uType = MB_ICONERROR|MB_OK; break; + case DT_YES_NO: uType = MB_ICONQUESTION|MB_YESNO; break; + case DT_OK_CANCEL: uType = MB_ICONWARNING|MB_OKCANCEL; break; + } + + switch( MessageBox( NULL, message, title, uType ) ) + { + default: + case IDOK: return DR_OK; + case IDCANCEL: return DR_CANCEL; + case IDYES: return DR_YES; + case IDNO: return DR_NO; + } +} + #ifndef DEDICATED static qboolean SDL_VIDEODRIVER_externallySet = qfalse; #endif @@ -660,8 +719,43 @@ Sys_SetEnv set/unset environment variables (empty value removes it) ============== */ - void Sys_SetEnv(const char *name, const char *value) { _putenv(va("%s=%s", name, value)); } + +/* +============== +Sys_PID +============== +*/ +int Sys_PID( void ) +{ + return GetCurrentProcessId( ); +} + +/* +============== +Sys_PIDIsRunning +============== +*/ +qboolean Sys_PIDIsRunning( int pid ) +{ + DWORD processes[ 1024 ]; + DWORD numBytes, numProcesses; + int i; + + if( !EnumProcesses( processes, sizeof( processes ), &numBytes ) ) + return qfalse; // Assume it's not running + + numProcesses = numBytes / sizeof( DWORD ); + + // Search for the pid + for( i = 0; i < numProcesses; i++ ) + { + if( processes[ i ] == pid ) + return qtrue; + } + + return qfalse; +} diff --git a/src/tools/asm/cmdlib.c b/src/tools/asm/cmdlib.c index 95fbb8c1..bf503464 100644 --- a/src/tools/asm/cmdlib.c +++ b/src/tools/asm/cmdlib.c @@ -64,7 +64,7 @@ char *ex_argv[MAX_EX_ARGC]; void ExpandWildcards( int *argc, char ***argv ) { struct _finddata_t fileinfo; - int handle; + intptr_t handle; int i; char filename[1024]; char filebase[1024]; |