diff --git a/CMakeLists.txt b/CMakeLists.txt index 08fb03f6..65a05115 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,7 @@ endif() # We need to pass some options to minizip / unzip. add_definitions(-DNOUNCRYPT) -if(NOT CMAKE_SYSTEM_NAME MATCHES "Linux" OR NOT CMAKE_SYSTEM_NAME MATCHES "Windows") +if(NOT (CMAKE_SYSTEM_NAME MATCHES "Linux") AND NOT (CMAKE_SYSTEM_NAME MATCHES "Windows")) add_definitions(-DIOAPI_NO_64) endif() @@ -589,19 +589,18 @@ endif() # Main Quake 2 executable if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - add_executable(yquake2 ${Client-Source} ${Client-Header} ${Platform-Specific-Source} + add_executable(yquake2 WIN32 ${Client-Source} ${Client-Header} ${Platform-Specific-Source} ${Backends-Generic-Source}) set_target_properties(yquake2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release + C_STANDARD 11 ) target_link_libraries(yquake2 ${yquake2LinkerFlags} ${yquake2ClientLinkerFlags} ${yquake2SDLLinkerFlags} ${yquake2ZLibLinkerFlags} ws2_32 winmm) # Wrapper for the Windows binary - add_executable(quake2 ${Wrapper-Source}) - set_target_properties(quake2 PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release - ) + add_executable(quake2 WIN32 ${Wrapper-Source}) + set_target_properties(quake2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release) else() add_executable(quake2 ${Client-Source} ${Client-Header} ${Platform-Specific-Source} ${Backends-Generic-Source}) @@ -618,6 +617,7 @@ add_executable(q2ded ${Server-Source} ${Server-Header} ${Platform-Specific-Sourc set_target_properties(q2ded PROPERTIES COMPILE_DEFINITIONS "DEDICATED_ONLY" RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release + C_STANDARD 11 ) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(q2ded ${yquake2LinkerFlags} ${yquake2SDLLinkerFlags} ${yquake2ZLibLinkerFlags} ws2_32 winmm) @@ -632,6 +632,7 @@ set_target_properties(game PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release/baseq2 RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release/baseq2 SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX} + C_STANDARD 11 ) target_link_libraries(game ${yquake2LinkerFlags}) @@ -642,6 +643,7 @@ set_target_properties(ref_gl1 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX} + C_STANDARD 11 ) target_link_libraries(ref_gl1 ${yquake2LinkerFlags} ${yquake2OpenGLLinkerFlags} ${yquake2SDLLinkerFlags}) @@ -652,6 +654,7 @@ set_target_properties(ref_gl3 PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX} + C_STANDARD 11 ) target_link_libraries(ref_gl3 ${yquake2LinkerFlags} ${yquake2SDLLinkerFlags}) @@ -662,5 +665,6 @@ set_target_properties(ref_soft PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX} + C_STANDARD 11 ) target_link_libraries(ref_soft ${yquake2LinkerFlags} ${yquake2SDLLinkerFlags}) diff --git a/src/client/refresh/gl1/gl1_main.c b/src/client/refresh/gl1/gl1_main.c index acd76a1f..83ebed0e 100644 --- a/src/client/refresh/gl1/gl1_main.c +++ b/src/client/refresh/gl1/gl1_main.c @@ -427,9 +427,10 @@ R_DrawParticles2(int num_particles, const particle_t particles[], float scale; YQ2_ALIGNAS_TYPE(unsigned) byte color[4]; - GLfloat vtx[3*num_particles*3]; - GLfloat tex[2*num_particles*3]; - GLfloat clr[4*num_particles*3]; + YQ2_VLA(GLfloat, vtx, 3 * num_particles * 3); + YQ2_VLA(GLfloat, tex, 2 * num_particles * 3); + YQ2_VLA(GLfloat, clr, 4 * num_particles * 3); + unsigned int index_vtx = 0; unsigned int index_tex = 0; unsigned int index_clr = 0; @@ -511,6 +512,10 @@ R_DrawParticles2(int num_particles, const particle_t particles[], glColor4f(1, 1, 1, 1); glDepthMask(1); /* back to normal Z buffering */ R_TexEnv(GL_REPLACE); + + YQ2_VLAFREE(vtx); + YQ2_VLAFREE(tex); + YQ2_VLAFREE(clr); } void @@ -524,9 +529,10 @@ R_DrawParticles(void) int i; YQ2_ALIGNAS_TYPE(unsigned) byte color[4]; const particle_t *p; + + YQ2_VLA(GLfloat, vtx, 3 * r_newrefdef.num_particles); + YQ2_VLA(GLfloat, clr, 4*r_newrefdef.num_particles); - GLfloat vtx[3*r_newrefdef.num_particles]; - GLfloat clr[4*r_newrefdef.num_particles]; unsigned int index_vtx = 0; unsigned int index_clr = 0; @@ -564,6 +570,9 @@ R_DrawParticles(void) glColor4f( 1, 1, 1, 1 ); glDepthMask(GL_TRUE); glEnable(GL_TEXTURE_2D); + + YQ2_VLAFREE(vtx); + YQ2_VLAFREE(clr); } else { diff --git a/src/client/refresh/gl1/gl1_mesh.c b/src/client/refresh/gl1/gl1_mesh.c index 69e06dbd..8bc3b512 100644 --- a/src/client/refresh/gl1/gl1_mesh.c +++ b/src/client/refresh/gl1/gl1_mesh.c @@ -176,9 +176,9 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp) } total = count; - GLfloat vtx[3*total]; - GLfloat tex[2*total]; - GLfloat clr[4 * total]; + YQ2_VLA(GLfloat, vtx, 3*total); // FIXME: alloca in loop is bad! + YQ2_VLA(GLfloat, tex, 2*total); + YQ2_VLA(GLfloat, clr, 4*total); unsigned int index_vtx = 0; unsigned int index_tex = 0; unsigned int index_clr = 0; @@ -240,6 +240,10 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp) glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); + + YQ2_VLAFREE(vtx); + YQ2_VLAFREE(tex); + YQ2_VLAFREE(clr) } if (currententity->flags & @@ -294,7 +298,8 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum) } total = count; - GLfloat vtx[3*total]; + + YQ2_VLA(GLfloat, vtx, 3*total); // FIXME: alloca in loop is bad! unsigned int index_vtx = 0; do @@ -320,6 +325,7 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum) glDrawArrays( type, 0, total ); glDisableClientState( GL_VERTEX_ARRAY ); + YQ2_VLAFREE(vtx); } /* stencilbuffer shadows */ diff --git a/src/client/refresh/gl1/gl1_misc.c b/src/client/refresh/gl1/gl1_misc.c index 05690378..4c4cf732 100644 --- a/src/client/refresh/gl1/gl1_misc.c +++ b/src/client/refresh/gl1/gl1_misc.c @@ -137,7 +137,7 @@ R_ScreenShot(void) // so swap bottom rows with top rows { size_t bytesPerRow = 3*w; - byte rowBuffer[bytesPerRow]; + YQ2_VLA(byte, rowBuffer, bytesPerRow); byte *curRowL = buffer; // first byte of first row byte *curRowH = buffer + bytesPerRow*(h-1); // first byte of last row while(curRowL < curRowH) @@ -149,6 +149,7 @@ R_ScreenShot(void) curRowL += bytesPerRow; curRowH -= bytesPerRow; } + YQ2_VLAFREE(rowBuffer); } ri.Vid_WriteScreenshot(w, h, 3, buffer); diff --git a/src/client/refresh/gl1/gl1_surf.c b/src/client/refresh/gl1/gl1_surf.c index 541693f3..4a1b4b42 100644 --- a/src/client/refresh/gl1/gl1_surf.c +++ b/src/client/refresh/gl1/gl1_surf.c @@ -101,7 +101,7 @@ R_DrawGLFlowingPoly(msurface_t *fa) scroll = -64.0; } - GLfloat tex[2*p->numverts]; + YQ2_VLA(GLfloat, tex, 2*p->numverts); unsigned int index_tex = 0; v = p->verts [ 0 ]; @@ -122,6 +122,8 @@ R_DrawGLFlowingPoly(msurface_t *fa) glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + + YQ2_VLAFREE(tex); } static void @@ -210,7 +212,7 @@ R_DrawGLPolyChain(glpoly_t *p, float soffset, float toffset) v = p->verts[0]; - GLfloat tex[2*p->numverts]; + YQ2_VLA(GLfloat, tex, 2*p->numverts); // FIXME: alloca in loop is bad! unsigned int index_tex = 0; for ( j = 0; j < p->numverts; j++, v += VERTEXSIZE ) @@ -230,6 +232,8 @@ R_DrawGLPolyChain(glpoly_t *p, float soffset, float toffset) glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + + YQ2_VLAFREE(tex); } } } diff --git a/src/client/refresh/gl1/gl1_warp.c b/src/client/refresh/gl1/gl1_warp.c index a940d75b..f695d35b 100644 --- a/src/client/refresh/gl1/gl1_warp.c +++ b/src/client/refresh/gl1/gl1_warp.c @@ -301,7 +301,7 @@ R_EmitWaterPolys(msurface_t *fa) { p = bp; - GLfloat tex[2*p->numverts]; + YQ2_VLA(GLfloat, tex, 2*p->numverts); // FIXME: alloca in loop is bad! unsigned int index_tex = 0; for ( i = 0, v = p->verts [ 0 ]; i < p->numverts; i++, v += VERTEXSIZE ) @@ -328,6 +328,8 @@ R_EmitWaterPolys(msurface_t *fa) glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + + YQ2_VLAFREE(tex); } } diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c index 358f1535..9af7af14 100644 --- a/src/client/refresh/gl3/gl3_main.c +++ b/src/client/refresh/gl3/gl3_main.c @@ -925,7 +925,7 @@ GL3_DrawParticles(void) } part_vtx; assert(sizeof(part_vtx)==9*sizeof(float)); // remember to update GL3_SurfInit() if this changes! - part_vtx buf[numParticles]; + YQ2_VLA(part_vtx, buf, numParticles); // TODO: viewOrg could be in UBO vec3_t viewOrg; @@ -962,6 +962,8 @@ GL3_DrawParticles(void) glDisable(GL_BLEND); glDepthMask(GL_TRUE); glDisable(GL_PROGRAM_POINT_SIZE); + + YQ2_VLAFREE(buf); } } diff --git a/src/client/refresh/gl3/gl3_misc.c b/src/client/refresh/gl3/gl3_misc.c index e1e8684f..532790de 100644 --- a/src/client/refresh/gl3/gl3_misc.c +++ b/src/client/refresh/gl3/gl3_misc.c @@ -131,7 +131,7 @@ GL3_ScreenShot(void) // so swap bottom rows with top rows { size_t bytesPerRow = 3*w; - byte rowBuffer[bytesPerRow]; + YQ2_VLA(byte, rowBuffer, bytesPerRow); byte *curRowL = buffer; // first byte of first row byte *curRowH = buffer + bytesPerRow*(h-1); // first byte of last row while(curRowL < curRowH) @@ -143,6 +143,7 @@ GL3_ScreenShot(void) curRowL += bytesPerRow; curRowH -= bytesPerRow; } + YQ2_VLAFREE(rowBuffer); } ri.Vid_WriteScreenshot(w, h, 3, buffer); diff --git a/src/client/refresh/ref_shared.h b/src/client/refresh/ref_shared.h index 194b13c1..c220a3ed 100644 --- a/src/client/refresh/ref_shared.h +++ b/src/client/refresh/ref_shared.h @@ -29,6 +29,23 @@ #include "../vid/header/ref.h" +#ifdef _MSC_VER + + #include + + #define YQ2_VLA(TYPE, VARNAME, NUMELEMS) \ + TYPE * VARNAME = (TYPE *) _malloca(sizeof(TYPE) * NUMELEMS) + #define YQ2_VLAFREE(VARNAME) \ + _freea(VARNAME); VARNAME=NULL; + +#else // other compilers hopefully support C99 VLAs (gcc/mingw and clang do) + + #define YQ2_VLA(TYPE, VARNAME, NUMELEMS) \ + TYPE VARNAME[NUMELEMS] + #define YQ2_VLAFREE(VARNAME) + +#endif + /* * skins will be outline flood filled and mip mapped * pics and sprites with alpha will be outline flood filled @@ -58,7 +75,7 @@ typedef enum #define MAX_LBM_HEIGHT 480 -extern void R_Printf(int level, const char* msg, ...) __attribute__ ((format (printf, 2, 3))); +extern void R_Printf(int level, const char* msg, ...) PRINTF_ATTR(2, 3); extern void LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height); extern void GetPCXInfo(char *filename, int *width, int *height); diff --git a/src/client/sound/sound.c b/src/client/sound/sound.c index b42c421b..6804fada 100644 --- a/src/client/sound/sound.c +++ b/src/client/sound/sound.c @@ -163,7 +163,7 @@ static qboolean S_IsSilencedMuzzleFlash(const wavinfo_t* info, const void* raw_data, const char* name) { /* Skip the prefix. */ - static const size_t base_sound_string_length = strlen("sound/"); + static const size_t base_sound_string_length = 6; //strlen("sound/"); const char* base_name = name + base_sound_string_length; /* Match to well-known muzzle flash sound names. */ diff --git a/src/client/vid/glimp_sdl.c b/src/client/vid/glimp_sdl.c index c0cbfbb7..bc70d551 100755 --- a/src/client/vid/glimp_sdl.c +++ b/src/client/vid/glimp_sdl.c @@ -135,7 +135,7 @@ CreateSDLWindow(int flags, int w, int h) Com_Printf("Likely SDL bug #4700, trying to work around it\n"); /* Mkay, try to hack around that. */ - SDL_DisplayMode wanted_mode = {}; + SDL_DisplayMode wanted_mode = {0}; wanted_mode.w = w; wanted_mode.h = h; diff --git a/src/client/vid/header/ref.h b/src/client/vid/header/ref.h index 888351c6..edb284aa 100644 --- a/src/client/vid/header/ref.h +++ b/src/client/vid/header/ref.h @@ -207,7 +207,7 @@ typedef struct typedef struct { - YQ2_ATTR_NORETURN_FUNCPTR void (IMPORT *Sys_Error) (int err_level, char *str, ...) __attribute__ ((format (printf, 2, 3))); + YQ2_ATTR_NORETURN_FUNCPTR void (IMPORT *Sys_Error) (int err_level, char *str, ...) PRINTF_ATTR(2, 3); void (IMPORT *Cmd_AddCommand) (char *name, void(*cmd)(void)); void (IMPORT *Cmd_RemoveCommand) (char *name); diff --git a/src/common/filesystem.c b/src/common/filesystem.c index 6987fd0b..9cc87915 100644 --- a/src/common/filesystem.c +++ b/src/common/filesystem.c @@ -25,7 +25,9 @@ * ======================================================================= */ +#ifndef _MSC_VER #include +#endif #include "header/common.h" #include "header/glob.h" @@ -380,7 +382,7 @@ FS_FOpenFile(const char *rawname, fileHandle_t *f, qboolean gamedir_only) // Remove self references and empty dirs from the requested path. // ZIPs and PAKs don't support them, but they may be hardcoded in // some custom maps or models. - char name[MAX_QPATH] = {}; + char name[MAX_QPATH] = {0}; size_t namelen = strlen(rawname); for (int input = 0, output = 0; input < namelen; input++) { @@ -1614,6 +1616,27 @@ FS_GetNextRawPath(const char* lastRawPath) return NULL; } +#ifdef _MSC_VER // looks like MSVC/the Windows CRT doesn't have basename() +// returns the last part of the given pathname, after last (back)slash +// NOTE: this is not a fully compliant basename() implementation, as it doesn't +// handle trailing (back)slashes at all - because we don't need that. +static char* basename( char* n ) +{ + char* r1 = strrchr( n, '\\' ); + char* r2 = strrchr( n, '/' ); + if (r1 != NULL) + { + if (r2 != NULL) + { + return (r2 > r1) ? (r2 + 1) : (r1 + 1); + } + return r1 + 1; + } + + return (r2 != NULL) ? (r2 + 1) : n; +} +#endif // _MSC_VER + void FS_AddDirToSearchPath(char *dir, qboolean create) { char *file; @@ -1971,7 +1994,7 @@ static void FS_AddDirToRawPath (const char *rawdir, qboolean create, qboolean re } // Make sure that the dir doesn't end with a slash. - for (size_t s = strlen(dir) - 1; s >= 0; s--) + for (size_t s = strlen(dir) - 1; s > 0; s--) { if (dir[s] == '/') { diff --git a/src/common/header/common.h b/src/common/header/common.h index 112071b8..33237655 100644 --- a/src/common/header/common.h +++ b/src/common/header/common.h @@ -711,11 +711,11 @@ void FS_CreatePath(char *path); void Com_BeginRedirect(int target, char *buffer, int buffersize, void (*flush)(int, char *)); void Com_EndRedirect(void); -void Com_Printf(char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -void Com_DPrintf(char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +void Com_Printf(char *fmt, ...) PRINTF_ATTR(1, 2); +void Com_DPrintf(char *fmt, ...) PRINTF_ATTR(1, 2); void Com_VPrintf(int print_level, const char *fmt, va_list argptr); /* print_level is PRINT_ALL or PRINT_DEVELOPER */ -void Com_MDPrintf(char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -YQ2_ATTR_NORETURN void Com_Error(int code, char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +void Com_MDPrintf(char *fmt, ...) PRINTF_ATTR(1, 2); +YQ2_ATTR_NORETURN void Com_Error(int code, char *fmt, ...) PRINTF_ATTR(2, 3); YQ2_ATTR_NORETURN void Com_Quit(void); /* Ugly work around for unsupported diff --git a/src/common/header/shared.h b/src/common/header/shared.h index 74b5088a..b5c30c74 100644 --- a/src/common/header/shared.h +++ b/src/common/header/shared.h @@ -65,8 +65,12 @@ typedef unsigned char byte; // must be used as prefix (YQ2_ATTR_NORETURN void bla();)! #define YQ2_ATTR_NORETURN __attribute__ ((noreturn)) #elif defined(_MSC_VER) - #define YQ2_ALIGNAS_SIZE(SIZE) __declspec( align(SIZE) ) - #define YQ2_ALIGNAS_TYPE(TYPE) __declspec( align( __alignof(TYPE) ) ) + #error "We only support MSVC in C11 mode (/std:c11) or higher, requires Visual Studio 2019 version 16.8 or higher" + // in that case, we should've used the #if __STDC_VERSION__ >= 201112L case above + + #define YQ2_ALIGNAS_SIZE( SIZE ) __declspec(align(SIZE)) + // FIXME: for some reason, the following line doesn't work, which is why we require C11 support for MSVC + #define YQ2_ALIGNAS_TYPE( TYPE ) __declspec(align(__alignof(TYPE))) // must be used as prefix (YQ2_ATTR_NORETURN void bla();)! #define YQ2_ATTR_NORETURN __declspec(noreturn) #else @@ -133,6 +137,12 @@ typedef unsigned char byte; #define Q2_DLL_EXPORTED __attribute__((__visibility__("default"))) #endif +#ifdef _MSC_VER + #define PRINTF_ATTR(FMT, VARGS) +#else // at least GCC/mingw and clang support this + #define PRINTF_ATTR(FMT, VARGS) __attribute__((format(printf, FMT , VARGS ))); +#endif + /* per-level limits */ #define MAX_CLIENTS 256 /* absolute limit */ #define MAX_EDICTS 1024 /* must change protocol to increase more */ @@ -310,7 +320,7 @@ float BigFloat(float l); float LittleFloat(float l); void Swap_Init(void); -char *va(char *format, ...) __attribute__ ((format (printf, 1, 2))); +char *va(char *format, ...) PRINTF_ATTR(1, 2); /* ============================================= */ diff --git a/src/common/shared/shared.c b/src/common/shared/shared.c index f7d8639e..260780af 100644 --- a/src/common/shared/shared.c +++ b/src/common/shared/shared.c @@ -1034,7 +1034,11 @@ Com_PageInMemory(byte *buffer, int size) int Q_stricmp(const char *s1, const char *s2) { +#ifdef _MSC_VER + return stricmp(s1, s2); +#else return strcasecmp(s1, s2); +#endif } int