diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e8755ab40..1e13814a0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,9 +4,9 @@ on: [push, pull_request] jobs: linux: name: Linux - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install Dependencies run: | sudo apt-get update @@ -15,7 +15,7 @@ jobs: run: make release env: ARCHIVE: 1 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: Linux path: build/*.zip @@ -23,27 +23,27 @@ jobs: name: Windows runs-on: windows-2019 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Compile run: | choco install zip make release env: ARCHIVE: 1 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: Windows path: build/*.zip macos: name: macOS - runs-on: macos-10.15 + runs-on: macos-12 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Compile run: make release env: ARCHIVE: 1 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: macOS path: build/*.zip diff --git a/Makefile b/Makefile index ec194f54df..9bc722bdb2 100644 --- a/Makefile +++ b/Makefile @@ -808,6 +808,8 @@ else # ifdef MINGW ############################################################################# ifeq ($(PLATFORM),freebsd) + # Use the default C compiler + TOOLS_CC=cc # flags BASE_CFLAGS = \ @@ -1102,7 +1104,6 @@ endif ifneq ($(HAVE_VM_COMPILED),true) BASE_CFLAGS += -DNO_VM_COMPILED - BUILD_GAME_QVM=0 endif TARGETS = diff --git a/README.md b/README.md index 3b013e6c1b..ce2999cba1 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ Makefile.local: USE_INTERNAL_JPEG - build and link against internal JPEG library USE_INTERNAL_OGG - build and link against internal ogg library USE_INTERNAL_OPUS - build and link against internal opus/opusfile libraries + USE_INTERNAL_VORBIS - build and link against internal Vorbis library USE_LOCAL_HEADERS - use headers local to ioq3 instead of system ones DEBUG_CFLAGS - C compiler flags to use for building debug version COPYDIR - the target installation directory diff --git a/SECURITY.md b/SECURITY.md index 449b660723..fd5c9f37fb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,4 +4,7 @@ We take security very seriously at ioquake3. We welcome any peer review of our 1 ### Where should I report security issues? In order to give the community time to respond and upgrade we strongly urge you report all security issues privately. -Please contact zachary@ioquake.org directly to provide details and repro steps and we will respond ASAP. +Please e-mail jack@ioquake.org directly to provide details and repro steps and we will respond as soon as possible, but please note: + +### This is an entirely free software project without much in the way of external funding or sponsorships. +### We cannot guarantee quick responses but we very much appreciate your discretion when reporting security vulnerabilities. diff --git a/code/autoupdater/autoupdater.c b/code/autoupdater/autoupdater.c index 4a0520273c..e013a1f433 100644 --- a/code/autoupdater/autoupdater.c +++ b/code/autoupdater/autoupdater.c @@ -933,10 +933,13 @@ static void waitToApplyUpdates(void) OS forcibly closes the pipe), we will unblock. Then we can loop on kill() until the process is truly gone. */ int x = 0; + struct timespec req; + req.tv_sec = 0; + req.tv_nsec = 100000000; read(3, &x, sizeof (x)); info("Pipe has closed, waiting for process to fully go away now."); while (kill(options.waitforprocess, 0) == 0) { - usleep(100000); + nanosleep(&req, NULL); } #endif } diff --git a/code/botlib/be_aas.h b/code/botlib/be_aas.h index dbf24bc128..cb7d73c981 100644 --- a/code/botlib/be_aas.h +++ b/code/botlib/be_aas.h @@ -217,5 +217,5 @@ typedef struct aas_predictroute_s int endcontents; //contents at the end of movement prediction int endtravelflags; //end travel flags int numareas; //number of areas predicted ahead - int time; //time predicted ahead (in hundreth of a sec) + int time; //time predicted ahead (in hundredths of a sec) } aas_predictroute_t; diff --git a/code/botlib/be_aas_file.c b/code/botlib/be_aas_file.c index f4d91720b5..3de8f78030 100644 --- a/code/botlib/be_aas_file.c +++ b/code/botlib/be_aas_file.c @@ -277,7 +277,7 @@ void AAS_FileInfo(void) aasworld.reachabilitysize * sizeof(aas_reachability_t) + aasworld.numportals * sizeof(aas_portal_t) + aasworld.numclusters * sizeof(aas_cluster_t); - botimport.Print(PRT_MESSAGE, "optimzed size %d KB\n", optimized >> 10); + botimport.Print(PRT_MESSAGE, "optimized size %d KB\n", optimized >> 10); } //end of the function AAS_FileInfo #endif //AASFILEDEBUG //=========================================================================== diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 253e5e400d..d7ede8af29 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -40,6 +40,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define CINEMATICS_LOGO "foologo.roq" #define CINEMATICS_INTRO "intro.roq" // #define LEGACY_PROTOCOL // You probably don't need this for your standalone game +// #define PROTOCOL_HANDLER "foobar" #else #define PRODUCT_NAME "ioq3" #define BASEGAME "baseq3" @@ -56,6 +57,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define CINEMATICS_LOGO "idlogo.RoQ" #define CINEMATICS_INTRO "intro.RoQ" #define LEGACY_PROTOCOL + #define PROTOCOL_HANDLER "quake3" #endif // Heartbeat for dpmaster protocol. You shouldn't change this unless you know what you're doing diff --git a/code/renderergl1/tr_sky.c b/code/renderergl1/tr_sky.c index 1d12e924ec..2f5f7786f7 100644 --- a/code/renderergl1/tr_sky.c +++ b/code/renderergl1/tr_sky.c @@ -387,12 +387,17 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max static void DrawSkyBox( shader_t *shader ) { int i; + float w_offset, w_scale; + float h_offset, h_scale; sky_min = 0; sky_max = 1; Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) ); + w_offset = h_offset = 0; + w_scale = h_scale = 1; + for (i=0 ; i<6 ; i++) { int sky_mins_subd[2], sky_maxs_subd[2]; @@ -432,6 +437,15 @@ static void DrawSkyBox( shader_t *shader ) else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; + if ( !haveClampToEdge ) + { + w_offset = 0.5f / shader->sky.outerbox[sky_texorder[i]]->width; + h_offset = 0.5f / shader->sky.outerbox[sky_texorder[i]]->height; + + w_scale = 1.0f - w_offset * 2; + h_scale = 1.0f - h_offset * 2; + } + // // iterate through the subdivisions // @@ -444,6 +458,12 @@ static void DrawSkyBox( shader_t *shader ) i, s_skyTexCoords[t][s], s_skyPoints[t][s] ); + + s_skyTexCoords[t][s][0] *= w_scale; + s_skyTexCoords[t][s][0] += w_offset; + + s_skyTexCoords[t][s][1] *= h_scale; + s_skyTexCoords[t][s][1] += h_offset; } } diff --git a/code/renderergl2/glsl/generic_vp.glsl b/code/renderergl2/glsl/generic_vp.glsl index a005526371..e6af9f8134 100644 --- a/code/renderergl2/glsl/generic_vp.glsl +++ b/code/renderergl2/glsl/generic_vp.glsl @@ -16,8 +16,16 @@ attribute vec4 attr_TexCoord0; attribute vec4 attr_TexCoord1; #endif -uniform vec4 u_DiffuseTexMatrix; -uniform vec4 u_DiffuseTexOffTurb; +#if defined(USE_TCMOD) +uniform vec4 u_DiffuseTexMatrix0; +uniform vec4 u_DiffuseTexMatrix1; +uniform vec4 u_DiffuseTexMatrix2; +uniform vec4 u_DiffuseTexMatrix3; +uniform vec4 u_DiffuseTexMatrix4; +uniform vec4 u_DiffuseTexMatrix5; +uniform vec4 u_DiffuseTexMatrix6; +uniform vec4 u_DiffuseTexMatrix7; +#endif #if defined(USE_TCGEN) || defined(USE_RGBAGEN) uniform vec3 u_LocalViewOrigin; @@ -140,19 +148,28 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 #endif #if defined(USE_TCMOD) -vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb) +vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix[8]) { - float amplitude = offTurb.z; - float phase = offTurb.w * 2.0 * M_PI; - vec2 st2; - st2.x = st.x * texMatrix.x + (st.y * texMatrix.z + offTurb.x); - st2.y = st.x * texMatrix.y + (st.y * texMatrix.w + offTurb.y); - + vec2 st2 = st; vec2 offsetPos = vec2(position.x + position.z, position.y); - - vec2 texOffset = sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(phase)); - - return st2 + texOffset * amplitude; + + st2 = vec2(st2.x * texMatrix[0].x + st2.y * texMatrix[0].y + texMatrix[0].z, + st2.x * texMatrix[1].x + st2.y * texMatrix[1].y + texMatrix[1].z); + st2 += texMatrix[0].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[1].w * 2.0 * M_PI)); + + st2 = vec2(st2.x * texMatrix[2].x + st2.y * texMatrix[2].y + texMatrix[2].z, + st2.x * texMatrix[3].x + st2.y * texMatrix[3].y + texMatrix[3].z); + st2 += texMatrix[2].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[3].w * 2.0 * M_PI)); + + st2 = vec2(st2.x * texMatrix[4].x + st2.y * texMatrix[4].y + texMatrix[4].z, + st2.x * texMatrix[5].x + st2.y * texMatrix[5].y + texMatrix[5].z); + st2 += texMatrix[4].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[5].w * 2.0 * M_PI)); + + st2 = vec2(st2.x * texMatrix[6].x + st2.y * texMatrix[6].y + texMatrix[6].z, + st2.x * texMatrix[7].x + st2.y * texMatrix[7].y + texMatrix[7].z); + st2 += texMatrix[6].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[7].w * 2.0 * M_PI)); + + return st2; } #endif @@ -236,7 +253,16 @@ void main() #endif #if defined(USE_TCMOD) - var_DiffuseTex = ModTexCoords(tex, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb); + vec4 diffuseTexMatrix[8]; + diffuseTexMatrix[0] = u_DiffuseTexMatrix0; + diffuseTexMatrix[1] = u_DiffuseTexMatrix1; + diffuseTexMatrix[2] = u_DiffuseTexMatrix2; + diffuseTexMatrix[3] = u_DiffuseTexMatrix3; + diffuseTexMatrix[4] = u_DiffuseTexMatrix4; + diffuseTexMatrix[5] = u_DiffuseTexMatrix5; + diffuseTexMatrix[6] = u_DiffuseTexMatrix6; + diffuseTexMatrix[7] = u_DiffuseTexMatrix7; + var_DiffuseTex = ModTexCoords(tex, position, diffuseTexMatrix); #else var_DiffuseTex = tex; #endif diff --git a/code/renderergl2/glsl/lightall_vp.glsl b/code/renderergl2/glsl/lightall_vp.glsl index 428cf1e6d1..8ff5e7bbfb 100644 --- a/code/renderergl2/glsl/lightall_vp.glsl +++ b/code/renderergl2/glsl/lightall_vp.glsl @@ -37,8 +37,14 @@ uniform vec3 u_LocalViewOrigin; #endif #if defined(USE_TCMOD) -uniform vec4 u_DiffuseTexMatrix; -uniform vec4 u_DiffuseTexOffTurb; +uniform vec4 u_DiffuseTexMatrix0; +uniform vec4 u_DiffuseTexMatrix1; +uniform vec4 u_DiffuseTexMatrix2; +uniform vec4 u_DiffuseTexMatrix3; +uniform vec4 u_DiffuseTexMatrix4; +uniform vec4 u_DiffuseTexMatrix5; +uniform vec4 u_DiffuseTexMatrix6; +uniform vec4 u_DiffuseTexMatrix7; #endif uniform mat4 u_ModelViewProjectionMatrix; @@ -114,19 +120,28 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 #endif #if defined(USE_TCMOD) -vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb) +vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix[8]) { - float amplitude = offTurb.z; - float phase = offTurb.w * 2.0 * M_PI; - vec2 st2; - st2.x = st.x * texMatrix.x + (st.y * texMatrix.z + offTurb.x); - st2.y = st.x * texMatrix.y + (st.y * texMatrix.w + offTurb.y); - + vec2 st2 = st; vec2 offsetPos = vec2(position.x + position.z, position.y); - vec2 texOffset = sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(phase)); + st2 = vec2(st2.x * texMatrix[0].x + st2.y * texMatrix[0].y + texMatrix[0].z, + st2.x * texMatrix[1].x + st2.y * texMatrix[1].y + texMatrix[1].z); + st2 += texMatrix[0].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[1].w * 2.0 * M_PI)); + + st2 = vec2(st2.x * texMatrix[2].x + st2.y * texMatrix[2].y + texMatrix[2].z, + st2.x * texMatrix[3].x + st2.y * texMatrix[3].y + texMatrix[3].z); + st2 += texMatrix[2].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[3].w * 2.0 * M_PI)); + + st2 = vec2(st2.x * texMatrix[4].x + st2.y * texMatrix[4].y + texMatrix[4].z, + st2.x * texMatrix[5].x + st2.y * texMatrix[5].y + texMatrix[5].z); + st2 += texMatrix[4].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[5].w * 2.0 * M_PI)); + + st2 = vec2(st2.x * texMatrix[6].x + st2.y * texMatrix[6].y + texMatrix[6].z, + st2.x * texMatrix[7].x + st2.y * texMatrix[7].y + texMatrix[7].z); + st2 += texMatrix[6].w * sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(texMatrix[7].w * 2.0 * M_PI)); - return st2 + texOffset * amplitude; + return st2; } #endif @@ -183,7 +198,16 @@ void main() #endif #if defined(USE_TCMOD) - var_TexCoords.xy = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb); + vec4 diffuseTexMatrix[8]; + diffuseTexMatrix[0] = u_DiffuseTexMatrix0; + diffuseTexMatrix[1] = u_DiffuseTexMatrix1; + diffuseTexMatrix[2] = u_DiffuseTexMatrix2; + diffuseTexMatrix[3] = u_DiffuseTexMatrix3; + diffuseTexMatrix[4] = u_DiffuseTexMatrix4; + diffuseTexMatrix[5] = u_DiffuseTexMatrix5; + diffuseTexMatrix[6] = u_DiffuseTexMatrix6; + diffuseTexMatrix[7] = u_DiffuseTexMatrix7; + var_TexCoords.xy = ModTexCoords(texCoords, position, diffuseTexMatrix); #else var_TexCoords.xy = texCoords; #endif diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c index ba3e2abb9b..0cffa4ee26 100644 --- a/code/renderergl2/tr_backend.c +++ b/code/renderergl2/tr_backend.c @@ -342,9 +342,7 @@ void RB_BeginDrawingView (void) { { FBO_t *fbo = backEnd.viewParms.targetFbo; - // FIXME: HUGE HACK: render to the screen fbo if we've already postprocessed the frame and aren't drawing more world - // drawing more world check is in case of double renders, such as skyportals - if (fbo == NULL && !(backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) + if (fbo == NULL) fbo = tr.renderFbo; if (tr.renderCubeFbo && fbo == tr.renderCubeFbo) @@ -457,7 +455,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) { if ( drawSurf->sort == oldSort && drawSurf->cubemapIndex == oldCubemapIndex) { - if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE) + if (backEnd.depthFill && shader && (shader->sort != SS_OPAQUE && shader->sort != SS_PORTAL)) continue; // fast path, same as previous sort @@ -486,7 +484,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { oldCubemapIndex = cubemapIndex; } - if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE) + if (backEnd.depthFill && shader && (shader->sort != SS_OPAQUE && shader->sort != SS_PORTAL)) continue; // @@ -708,10 +706,9 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start ); } - // FIXME: HUGE hack if (glRefConfig.framebufferObject) { - FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo); + FBO_Bind(tr.renderFbo); } RB_SetGL2D(); @@ -795,9 +792,8 @@ const void *RB_StretchPic ( const void *data ) { cmd = (const stretchPicCommand_t *)data; - // FIXME: HUGE hack if (glRefConfig.framebufferObject) - FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo); + FBO_Bind(tr.renderFbo); RB_SetGL2D(); @@ -1173,6 +1169,13 @@ const void *RB_DrawSurfs( const void *data ) { qglGenerateTextureMipmapEXT(cubemap->image->texnum, GL_TEXTURE_CUBE_MAP); } + // FIXME? backEnd.viewParms doesn't get properly initialized for 2D drawing. + // r_cubeMapping 1 generates cubemaps with R_RenderCubemapSide() + // and sets isMirror = qtrue. Clear it here to prevent it from leaking + // to 2D drawing and causing the loading screen to be culled. + backEnd.viewParms.isMirror = qfalse; + backEnd.viewParms.flags = 0; + return (const void *)(cmd + 1); } @@ -1199,6 +1202,10 @@ const void *RB_DrawBuffer( const void *data ) { // clear screen for debugging if ( r_clear->integer ) { + if (glRefConfig.framebufferObject && tr.renderFbo) { + FBO_Bind(tr.renderFbo); + } + qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } @@ -1313,14 +1320,7 @@ const void *RB_ClearDepth(const void *data) if (glRefConfig.framebufferObject) { - if (!tr.renderFbo || backEnd.framePostProcessed) - { - FBO_Bind(NULL); - } - else - { - FBO_Bind(tr.renderFbo); - } + FBO_Bind(tr.renderFbo); } qglClear(GL_DEPTH_BUFFER_BIT); @@ -1378,18 +1378,15 @@ const void *RB_SwapBuffers( const void *data ) { if (glRefConfig.framebufferObject) { - if (!backEnd.framePostProcessed) + if (tr.msaaResolveFbo && r_hdr->integer) { - if (tr.msaaResolveFbo && r_hdr->integer) - { - // Resolving an RGB16F MSAA FBO to the screen messes with the brightness, so resolve to an RGB16F FBO first - FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); - FBO_FastBlit(tr.msaaResolveFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - else if (tr.renderFbo) - { - FBO_FastBlit(tr.renderFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } + // Resolving an RGB16F MSAA FBO to the screen messes with the brightness, so resolve to an RGB16F FBO first + FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); + FBO_FastBlit(tr.msaaResolveFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else if (tr.renderFbo) + { + FBO_FastBlit(tr.renderFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); } } @@ -1401,7 +1398,6 @@ const void *RB_SwapBuffers( const void *data ) { GLimp_EndFrame(); - backEnd.framePostProcessed = qfalse; backEnd.projection2D = qfalse; return (const void *)(cmd + 1); @@ -1452,7 +1448,7 @@ RB_PostProcess const void *RB_PostProcess(const void *data) { const postProcessCommand_t *cmd = data; - FBO_t *srcFbo; + FBO_t *srcFbo, *dstFbo; ivec4_t srcBox, dstBox; qboolean autoExposure; @@ -1473,6 +1469,8 @@ const void *RB_PostProcess(const void *data) } srcFbo = tr.renderFbo; + dstFbo = tr.renderFbo; + if (tr.msaaResolveFbo) { // Resolve the MSAA before anything else @@ -1506,13 +1504,13 @@ const void *RB_PostProcess(const void *data) if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer)) { autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer; - RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure); - } - else if (r_cameraExposure->value == 0.0f) - { - FBO_FastBlit(srcFbo, srcBox, NULL, dstBox, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + // Use an intermediate FBO because it can't blit to the same FBO directly + // and can't read from an MSAA dstFbo later. + RB_ToneMap(srcFbo, srcBox, tr.screenScratchFbo, srcBox, autoExposure); + FBO_FastBlit(tr.screenScratchFbo, srcBox, srcFbo, srcBox, GL_COLOR_BUFFER_BIT, GL_NEAREST); } - else + else if (r_cameraExposure->value != 0.0f) { vec4_t color; @@ -1521,17 +1519,20 @@ const void *RB_PostProcess(const void *data) color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value); color[3] = 1.0f; - FBO_Blit(srcFbo, srcBox, NULL, NULL, dstBox, NULL, color, 0); + FBO_BlitFromTexture(tr.whiteImage, NULL, NULL, srcFbo, srcBox, NULL, color, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); } } if (r_drawSunRays->integer) - RB_SunRays(NULL, srcBox, NULL, dstBox); + RB_SunRays(srcFbo, srcBox, srcFbo, srcBox); if (1) - RB_BokehBlur(NULL, srcBox, NULL, dstBox, backEnd.refdef.blurFactor); + RB_BokehBlur(srcFbo, srcBox, srcFbo, srcBox, backEnd.refdef.blurFactor); else - RB_GaussianBlur(backEnd.refdef.blurFactor); + RB_GaussianBlur(srcFbo, srcFbo, backEnd.refdef.blurFactor); + + if (srcFbo != dstFbo) + FBO_FastBlit(srcFbo, srcBox, dstFbo, dstBox, GL_COLOR_BUFFER_BIT, GL_NEAREST); #if 0 if (0) @@ -1547,7 +1548,7 @@ const void *RB_PostProcess(const void *data) if (scale < 0.01f) scale = 5.0f; - FBO_FastBlit(NULL, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); + FBO_FastBlit(dstFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); iQtrBox[0] = backEnd.viewParms.viewportX * tr.quarterImage[0]->width / (float)glConfig.vidWidth; iQtrBox[1] = backEnd.viewParms.viewportY * tr.quarterImage[0]->height / (float)glConfig.vidHeight; @@ -1593,7 +1594,7 @@ const void *RB_PostProcess(const void *data) SetViewportAndScissor(); - FBO_FastBlit(tr.quarterFbo[1], NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); + FBO_FastBlit(tr.quarterFbo[1], NULL, dstFbo, NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); FBO_Bind(NULL); } #endif @@ -1602,42 +1603,42 @@ const void *RB_PostProcess(const void *data) { ivec4_t dstBox; VectorSet4(dstBox, 0, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 128, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 256, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 384, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.sunShadowDepthImage[3], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.sunShadowDepthImage[3], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); } if (0 && r_shadows->integer == 4) { ivec4_t dstBox; VectorSet4(dstBox, 512 + 0, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.pshadowMaps[0], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.pshadowMaps[0], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 512 + 128, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.pshadowMaps[1], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.pshadowMaps[1], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 512 + 256, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.pshadowMaps[2], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.pshadowMaps[2], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 512 + 384, glConfig.vidHeight - 128, 128, 128); - FBO_BlitFromTexture(tr.pshadowMaps[3], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.pshadowMaps[3], NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); } if (0) { ivec4_t dstBox; VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256); - FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 512, glConfig.vidHeight - 256, 256, 256); - FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); } if (0) { ivec4_t dstBox; VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256); - FBO_BlitFromTexture(tr.sunRaysImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0); + FBO_BlitFromTexture(tr.sunRaysImage, NULL, NULL, dstFbo, dstBox, NULL, NULL, 0); } #if 0 @@ -1649,14 +1650,12 @@ const void *RB_PostProcess(const void *data) if (cubemapIndex) { VectorSet4(dstBox, 0, glConfig.vidHeight - 256, 256, 256); - //FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); - FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1].image, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); + //FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, dstFbo, dstBox, &tr.testcubeShader, NULL, 0); + FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1].image, NULL, NULL, dstFbo, dstBox, &tr.testcubeShader, NULL, 0); } } #endif - backEnd.framePostProcessed = qtrue; - return (const void *)(cmd + 1); } diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index ad5fe3a30d..15f5f3cd62 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -497,6 +497,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) { } +// If FatPackU() or FatPackV() changes, update FixFatLightmapTexCoords() static float FatPackU(float input, int lightmapnum) { if (lightmapnum < 0) @@ -616,7 +617,7 @@ static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) { lightmapNum = LIGHTMAP_WHITEIMAGE; } - shader = R_FindShader( dsh->shader, lightmapNum, qtrue ); + shader = R_FindShaderEx( dsh->shader, FatLightmap( lightmapNum ), qtrue, lightmapNum ); // if the shader had errors, just use default shader if ( shader->defaultShader ) { @@ -705,7 +706,7 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, surf->fogIndex = LittleLong( ds->fogNum ) + 1; // get shader value - surf->shader = ShaderForShaderNum( ds->shaderNum, FatLightmap(realLightmapNum) ); + surf->shader = ShaderForShaderNum( ds->shaderNum, realLightmapNum ); if ( r_singleShader->integer && !surf->shader->isSky ) { surf->shader = tr.defaultShader; } @@ -812,7 +813,7 @@ static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, surf->fogIndex = LittleLong( ds->fogNum ) + 1; // get shader value - surf->shader = ShaderForShaderNum( ds->shaderNum, FatLightmap(realLightmapNum) ); + surf->shader = ShaderForShaderNum( ds->shaderNum, realLightmapNum ); if ( r_singleShader->integer && !surf->shader->isSky ) { surf->shader = tr.defaultShader; } diff --git a/code/renderergl2/tr_fbo.c b/code/renderergl2/tr_fbo.c index 26f50c3f98..223cbe7f7d 100644 --- a/code/renderergl2/tr_fbo.c +++ b/code/renderergl2/tr_fbo.c @@ -170,9 +170,13 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample) } absent = *pRenderBuffer == 0; - if (absent) + if (absent) { qglGenRenderbuffers(1, pRenderBuffer); + // workaround AMD Windows driver requiring bind to create renderbuffer + GL_BindRenderbuffer(*pRenderBuffer); + } + if (multisample && glRefConfig.framebufferMultisample) qglNamedRenderbufferStorageMultisampleEXT(*pRenderBuffer, multisample, format, fbo->width, fbo->height); else @@ -644,10 +648,30 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int bu int width = dst ? dst->width : glConfig.vidWidth; int height = dst ? dst->height : glConfig.vidHeight; + qglScissor(0, 0, width, height); + VectorSet4(dstBoxFinal, 0, 0, width, height); } else { + ivec4_t scissorBox; + + Vector4Copy(dstBox, scissorBox); + + if (scissorBox[2] < 0) + { + scissorBox[0] += scissorBox[2]; + scissorBox[2] = fabsf(scissorBox[2]); + } + + if (scissorBox[3] < 0) + { + scissorBox[1] += scissorBox[3]; + scissorBox[3] = fabsf(scissorBox[3]); + } + + qglScissor(scissorBox[0], scissorBox[1], scissorBox[2], scissorBox[3]); + VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]); } diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index 86cca5998f..2c834f101e 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -88,8 +88,14 @@ static uniformInfo_t uniformsInfo[] = { "u_EnableTextures", GLSL_VEC4 }, - { "u_DiffuseTexMatrix", GLSL_VEC4 }, - { "u_DiffuseTexOffTurb", GLSL_VEC4 }, + { "u_DiffuseTexMatrix0", GLSL_VEC4 }, + { "u_DiffuseTexMatrix1", GLSL_VEC4 }, + { "u_DiffuseTexMatrix2", GLSL_VEC4 }, + { "u_DiffuseTexMatrix3", GLSL_VEC4 }, + { "u_DiffuseTexMatrix4", GLSL_VEC4 }, + { "u_DiffuseTexMatrix5", GLSL_VEC4 }, + { "u_DiffuseTexMatrix6", GLSL_VEC4 }, + { "u_DiffuseTexMatrix7", GLSL_VEC4 }, { "u_TCGen0", GLSL_INT }, { "u_TCGen0Vector0", GLSL_VEC3 }, diff --git a/code/renderergl2/tr_image.c b/code/renderergl2/tr_image.c index 09ceff0831..101513b637 100644 --- a/code/renderergl2/tr_image.c +++ b/code/renderergl2/tr_image.c @@ -2766,7 +2766,7 @@ void R_CreateBuiltinImages( void ) { tr.renderImage = R_CreateImage("_render", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); - if (r_shadowBlur->integer) + if (r_shadowBlur->integer || r_hdr->integer) tr.screenScratchImage = R_CreateImage("screenScratch", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, rgbFormat); if (r_shadowBlur->integer || r_ssao->integer) diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index 668dbbdd34..6a0aa36f43 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -637,8 +637,14 @@ typedef enum UNIFORM_ENABLETEXTURES, - UNIFORM_DIFFUSETEXMATRIX, - UNIFORM_DIFFUSETEXOFFTURB, + UNIFORM_DIFFUSETEXMATRIX0, + UNIFORM_DIFFUSETEXMATRIX1, + UNIFORM_DIFFUSETEXMATRIX2, + UNIFORM_DIFFUSETEXMATRIX3, + UNIFORM_DIFFUSETEXMATRIX4, + UNIFORM_DIFFUSETEXMATRIX5, + UNIFORM_DIFFUSETEXMATRIX6, + UNIFORM_DIFFUSETEXMATRIX7, UNIFORM_TCGEN0, UNIFORM_TCGEN0VECTOR0, @@ -1472,7 +1478,6 @@ typedef struct { FBO_t *last2DFBO; qboolean colorMask[4]; - qboolean framePostProcessed; qboolean depthFill; } backEndState_t; @@ -1990,6 +1995,7 @@ const void *RB_TakeVideoFrameCmd( const void *data ); // tr_shader.c // shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ); +shader_t *R_FindShaderEx( const char *name, int lightmapIndex, qboolean mipRawImage, int realLightmapIndex ); shader_t *R_GetShaderByHandle( qhandle_t hShader ); shader_t *R_GetShaderByState( int index, long *cycleTime ); shader_t *R_FindShaderByName( const char *name ); diff --git a/code/renderergl2/tr_postprocess.c b/code/renderergl2/tr_postprocess.c index 9931757b82..3d71f30414 100644 --- a/code/renderergl2/tr_postprocess.c +++ b/code/renderergl2/tr_postprocess.c @@ -447,7 +447,7 @@ static void RB_VBlur(FBO_t *srcFbo, FBO_t *dstFbo, float strength) RB_BlurAxis(srcFbo, dstFbo, strength, qfalse); } -void RB_GaussianBlur(float blur) +void RB_GaussianBlur(FBO_t *srcFbo, FBO_t *dstFbo, float blur) { //float mul = 1.f; float factor = Com_Clamp(0.f, 1.f, blur); @@ -462,7 +462,7 @@ void RB_GaussianBlur(float blur) VectorSet4(color, 1, 1, 1, 1); // first, downsample the framebuffer - FBO_FastBlit(NULL, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); + FBO_FastBlit(srcFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); // set the alpha channel @@ -478,6 +478,6 @@ void RB_GaussianBlur(float blur) VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight); color[3] = factor; - FBO_Blit(tr.textureScratchFbo[0], srcBox, NULL, NULL, dstBox, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); + FBO_Blit(tr.textureScratchFbo[0], srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); } } diff --git a/code/renderergl2/tr_postprocess.h b/code/renderergl2/tr_postprocess.h index 09daf13465..a2d6d0b3f2 100644 --- a/code/renderergl2/tr_postprocess.h +++ b/code/renderergl2/tr_postprocess.h @@ -28,6 +28,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA void RB_ToneMap(FBO_t *hdrFbo, ivec4_t hdrBox, FBO_t *ldrFbo, ivec4_t ldrBox, int autoExposure); void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float blur); void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox); -void RB_GaussianBlur(float blur); +void RB_GaussianBlur(FBO_t *srcFbo, FBO_t *dstFbo, float blur); #endif diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index 5300898c3d..21f9543af1 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -181,33 +181,30 @@ extern float EvalWaveForm( const waveForm_t *wf ); extern float EvalWaveFormClamped( const waveForm_t *wf ); -static void ComputeTexMods( shaderStage_t *pStage, int bundleNum, float *outMatrix, float *outOffTurb) +static void ComputeTexMods( shaderStage_t *pStage, int bundleNum, vec4_t outMatrix[8]) { int tm; - float matrix[6], currentmatrix[6]; + float matrix[6]; + float tmpmatrix[6]; + float currentmatrix[6]; + float turb[2]; textureBundle_t *bundle = &pStage->bundle[bundleNum]; - - matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = 0.0f; - matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = 0.0f; + qboolean hasTurb = qfalse; currentmatrix[0] = 1.0f; currentmatrix[2] = 0.0f; currentmatrix[4] = 0.0f; currentmatrix[1] = 0.0f; currentmatrix[3] = 1.0f; currentmatrix[5] = 0.0f; - outMatrix[0] = 1.0f; outMatrix[2] = 0.0f; - outMatrix[1] = 0.0f; outMatrix[3] = 1.0f; - - outOffTurb[0] = 0.0f; outOffTurb[1] = 0.0f; outOffTurb[2] = 0.0f; outOffTurb[3] = 0.0f; - for ( tm = 0; tm < bundle->numTexMods ; tm++ ) { switch ( bundle->texMods[tm].type ) { case TMOD_NONE: - tm = TR_MAX_TEXMODS; // break out of for loop + matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = 0.0f; + matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = 0.0f; break; case TMOD_TURBULENT: - RB_CalcTurbulentFactors(&bundle->texMods[tm].wave, &outOffTurb[2], &outOffTurb[3]); + RB_CalcTurbulentFactors(&bundle->texMods[tm].wave, &turb[0], &turb[1]); break; case TMOD_ENTITY_TRANSLATE: @@ -246,35 +243,68 @@ static void ComputeTexMods( shaderStage_t *pStage, int bundleNum, float *outMatr switch ( bundle->texMods[tm].type ) { - case TMOD_NONE: case TMOD_TURBULENT: - default: + outMatrix[tm*2+0][0] = 1; outMatrix[tm*2+0][1] = 0; outMatrix[tm*2+0][2] = 0; + outMatrix[tm*2+1][0] = 0; outMatrix[tm*2+1][1] = 1; outMatrix[tm*2+1][2] = 0; + + outMatrix[tm*2+0][3] = turb[0]; + outMatrix[tm*2+1][3] = turb[1]; + + hasTurb = qtrue; break; + case TMOD_NONE: case TMOD_ENTITY_TRANSLATE: case TMOD_SCROLL: case TMOD_SCALE: case TMOD_STRETCH: case TMOD_TRANSFORM: case TMOD_ROTATE: - outMatrix[0] = matrix[0] * currentmatrix[0] + matrix[2] * currentmatrix[1]; - outMatrix[1] = matrix[1] * currentmatrix[0] + matrix[3] * currentmatrix[1]; + default: + outMatrix[tm*2+0][0] = matrix[0]; outMatrix[tm*2+0][1] = matrix[2]; outMatrix[tm*2+0][2] = matrix[4]; + outMatrix[tm*2+1][0] = matrix[1]; outMatrix[tm*2+1][1] = matrix[3]; outMatrix[tm*2+1][2] = matrix[5]; - outMatrix[2] = matrix[0] * currentmatrix[2] + matrix[2] * currentmatrix[3]; - outMatrix[3] = matrix[1] * currentmatrix[2] + matrix[3] * currentmatrix[3]; + outMatrix[tm*2+0][3] = 0; + outMatrix[tm*2+1][3] = 0; - outOffTurb[0] = matrix[0] * currentmatrix[4] + matrix[2] * currentmatrix[5] + matrix[4]; - outOffTurb[1] = matrix[1] * currentmatrix[4] + matrix[3] * currentmatrix[5] + matrix[5]; + tmpmatrix[0] = matrix[0] * currentmatrix[0] + matrix[2] * currentmatrix[1]; + tmpmatrix[1] = matrix[1] * currentmatrix[0] + matrix[3] * currentmatrix[1]; - currentmatrix[0] = outMatrix[0]; - currentmatrix[1] = outMatrix[1]; - currentmatrix[2] = outMatrix[2]; - currentmatrix[3] = outMatrix[3]; - currentmatrix[4] = outOffTurb[0]; - currentmatrix[5] = outOffTurb[1]; + tmpmatrix[2] = matrix[0] * currentmatrix[2] + matrix[2] * currentmatrix[3]; + tmpmatrix[3] = matrix[1] * currentmatrix[2] + matrix[3] * currentmatrix[3]; + + tmpmatrix[4] = matrix[0] * currentmatrix[4] + matrix[2] * currentmatrix[5] + matrix[4]; + tmpmatrix[5] = matrix[1] * currentmatrix[4] + matrix[3] * currentmatrix[5] + matrix[5]; + + currentmatrix[0] = tmpmatrix[0]; + currentmatrix[1] = tmpmatrix[1]; + currentmatrix[2] = tmpmatrix[2]; + currentmatrix[3] = tmpmatrix[3]; + currentmatrix[4] = tmpmatrix[4]; + currentmatrix[5] = tmpmatrix[5]; break; } } + + // if turb isn't used, only one matrix is needed + if ( !hasTurb ) { + tm = 0; + + outMatrix[tm*2+0][0] = currentmatrix[0]; outMatrix[tm*2+0][1] = currentmatrix[2]; outMatrix[tm*2+0][2] = currentmatrix[4]; + outMatrix[tm*2+1][0] = currentmatrix[1]; outMatrix[tm*2+1][1] = currentmatrix[3]; outMatrix[tm*2+1][2] = currentmatrix[5]; + + outMatrix[tm*2+0][3] = 0; + outMatrix[tm*2+1][3] = 0; + tm++; + } + + for ( ; tm < TR_MAX_TEXMODS ; tm++ ) { + outMatrix[tm*2+0][0] = 1; outMatrix[tm*2+0][1] = 0; outMatrix[tm*2+0][2] = 0; + outMatrix[tm*2+1][0] = 0; outMatrix[tm*2+1][1] = 1; outMatrix[tm*2+1][2] = 0; + + outMatrix[tm*2+0][3] = 0; + outMatrix[tm*2+1][3] = 0; + } } @@ -665,8 +695,7 @@ static void ForwardDlight( void ) { dlight_t *dl; shaderProgram_t *sp; vec4_t vector; - vec4_t texMatrix; - vec4_t texOffTurb; + vec4_t texMatrix[8]; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definitely doesn't have any of this light @@ -792,9 +821,15 @@ static void ForwardDlight( void ) { if (r_dlightMode->integer >= 2) GL_BindToTMU(tr.shadowCubemaps[l], TB_SHADOWMAP); - ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb ); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); + ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix ); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX0, texMatrix[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX1, texMatrix[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX2, texMatrix[2]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX3, texMatrix[3]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX4, texMatrix[4]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX5, texMatrix[5]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX6, texMatrix[6]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX7, texMatrix[7]); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); @@ -996,8 +1031,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { shaderStage_t *pStage = input->xstages[stage]; shaderProgram_t *sp; - vec4_t texMatrix; - vec4_t texOffTurb; + vec4_t texMatrix[8]; if ( !pStage ) { @@ -1184,19 +1218,31 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) if (r_lightmap->integer) { - vec4_t v; - VectorSet4(v, 1.0f, 0.0f, 0.0f, 1.0f); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, v); - VectorSet4(v, 0.0f, 0.0f, 0.0f, 0.0f); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, v); + vec4_t st[2]; + VectorSet4(st[0], 1.0f, 0.0f, 0.0f, 0.0f); + VectorSet4(st[1], 0.0f, 1.0f, 0.0f, 0.0f); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX0, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX1, st[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX2, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX3, st[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX4, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX5, st[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX6, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX7, st[1]); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, TCGEN_LIGHTMAP); } else { - ComputeTexMods(pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); + ComputeTexMods(pStage, TB_DIFFUSEMAP, texMatrix); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX0, texMatrix[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX1, texMatrix[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX2, texMatrix[2]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX3, texMatrix[3]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX4, texMatrix[4]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX5, texMatrix[5]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX6, texMatrix[6]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX7, texMatrix[7]); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); if (pStage->bundle[0].tcGen == TCGEN_VECTOR) diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index 0cd78a78e3..b08a932878 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -30,6 +30,7 @@ static char *s_shaderText; static shaderStage_t stages[MAX_SHADER_STAGES]; static shader_t shader; static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS]; +static int shader_realLightmapIndex; #define FILE_HASH_SIZE 1024 static shader_t* hashTable[FILE_HASH_SIZE]; @@ -1841,12 +1842,17 @@ static qboolean ParseShader( char **text ) tr.sunShadowScale = atof(token); // parse twice, since older shaders may include mapLightScale before sunShadowScale - token = COM_ParseExt( text, qfalse ); - if (token[0]) - tr.sunShadowScale = atof(token); + if (token[0]) { + token = COM_ParseExt( text, qfalse ); + if (token[0]) { + tr.sunShadowScale = atof(token); + } + } } - SkipRestOfLine( text ); + if (token[0]) { + SkipRestOfLine( text ); + } continue; } // tonemap parms @@ -2580,13 +2586,15 @@ static int CollapseStagesToGLSL(void) numStages++; } - // convert any remaining lightmap stages to a lighting pass with a white texture + // convert any remaining lightmap stages with no blending or blendfunc filter + // to a lighting pass with a white texture // only do this with r_sunlightMode non-zero, as it's only for correct shadows. if (r_sunlightMode->integer && shader.numDeforms == 0) { for (i = 0; i < MAX_SHADER_STAGES; i++) { shaderStage_t *pStage = &stages[i]; + int blendBits; if (!pStage->active) continue; @@ -2594,15 +2602,23 @@ static int CollapseStagesToGLSL(void) if (pStage->adjustColorsForFog) continue; - if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP) - { - pStage->glslShaderGroup = tr.lightallShader; - pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP; - pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP]; - pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage; - pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse; - pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE; + if (pStage->bundle[TB_DIFFUSEMAP].tcGen != TCGEN_LIGHTMAP) + continue; + + blendBits = pStage->stateBits & (GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS); + + if (blendBits != 0 && + blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO) && + blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)) { + continue; } + + pStage->glslShaderGroup = tr.lightallShader; + pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP; + pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP]; + pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage; + pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse; + pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE; } } @@ -2890,12 +2906,112 @@ static void VertexLightingCollapse( void ) { } } +/* +================= +FixFatLightmapTexCoords + +Handle edge cases of altering lightmap texcoords for fat lightmap atlas +================= +*/ +static void FixFatLightmapTexCoords(void) +{ + texModInfo_t *tmi; + int lightmapnum; + int stage; + int size; + int i; + + if ( !r_mergeLightmaps->integer || tr.fatLightmapCols <= 0) { + return; + } + + if ( shader.lightmapIndex < 0 ) { + // no internal lightmap, texcoords were not modified + return; + } + + lightmapnum = shader_realLightmapIndex; + + if (tr.worldDeluxeMapping) + lightmapnum >>= 1; + + lightmapnum %= (tr.fatLightmapCols * tr.fatLightmapRows); + + for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { + shaderStage_t *pStage = &stages[stage]; + + if ( !pStage->active ) { + break; + } + + if ( pStage->bundle[0].isLightmap ) { + // fix tcMod transform for internal lightmaps, it may be used by q3map2 lightstyles + if ( pStage->bundle[0].tcGen == TCGEN_LIGHTMAP ) { + for ( i = 0; i < pStage->bundle[0].numTexMods; i++ ) { + tmi = &pStage->bundle[0].texMods[i]; + + if ( tmi->type == TMOD_TRANSFORM ) { + tmi->translate[0] /= (float)tr.fatLightmapCols; + tmi->translate[1] /= (float)tr.fatLightmapRows; + } + } + } + + // fix tcGen environment for internal lightmaps to be limited to the sub-image of the atlas + // this is done last so other tcMods are applied first in the 0.0 to 1.0 space + if ( pStage->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED ) { + if ( pStage->bundle[0].numTexMods == TR_MAX_TEXMODS ) { + ri.Printf( PRINT_DEVELOPER, "WARNING: too many tcmods to fix lightmap texcoords for r_mergeLightmaps in shader '%s'", shader.name ); + } else { + tmi = &pStage->bundle[0].texMods[pStage->bundle[0].numTexMods]; + pStage->bundle[0].numTexMods++; + + tmi->matrix[0][0] = 1.0f / tr.fatLightmapCols; + tmi->matrix[0][1] = 0; + tmi->matrix[1][0] = 0; + tmi->matrix[1][1] = 1.0f / tr.fatLightmapRows; + + tmi->translate[0] = ( lightmapnum % tr.fatLightmapCols ) / (float)tr.fatLightmapCols; + tmi->translate[1] = ( lightmapnum / tr.fatLightmapCols ) / (float)tr.fatLightmapRows; + + tmi->type = TMOD_TRANSFORM; + } + } + } + // add a tcMod transform for external lightmaps to convert back to the original texcoords + else if ( pStage->bundle[0].tcGen == TCGEN_LIGHTMAP ) { + if ( pStage->bundle[0].numTexMods == TR_MAX_TEXMODS ) { + ri.Printf( PRINT_DEVELOPER, "WARNING: too many tcmods to fix lightmap texcoords for r_mergeLightmaps in shader '%s'", shader.name ); + } else { + size = pStage->bundle[0].numTexMods * sizeof( texModInfo_t ); + + if ( size ) { + memmove( &pStage->bundle[0].texMods[1], &pStage->bundle[0].texMods[0], size ); + } + + tmi = &pStage->bundle[0].texMods[0]; + pStage->bundle[0].numTexMods++; + + tmi->matrix[0][0] = tr.fatLightmapCols; + tmi->matrix[0][1] = 0; + tmi->matrix[1][0] = 0; + tmi->matrix[1][1] = tr.fatLightmapRows; + + tmi->translate[0] = -( lightmapnum % tr.fatLightmapCols ); + tmi->translate[1] = -( lightmapnum / tr.fatLightmapCols ); + + tmi->type = TMOD_TRANSFORM; + } + } + } +} + /* =============== InitShader =============== */ -static void InitShader( const char *name, int lightmapIndex ) { +static void InitShaderEx( const char *name, int lightmapIndex, int realLightmapIndex ) { int i; // clear the global shader @@ -2904,6 +3020,7 @@ static void InitShader( const char *name, int lightmapIndex ) { Q_strncpyz( shader.name, name, sizeof( shader.name ) ); shader.lightmapIndex = lightmapIndex; + shader_realLightmapIndex = realLightmapIndex; for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { stages[i].bundle[0].texMods = texMods[i]; @@ -2924,6 +3041,10 @@ static void InitShader( const char *name, int lightmapIndex ) { } } +static void InitShader( const char *name, int lightmapIndex ) { + InitShaderEx( name, lightmapIndex, lightmapIndex ); +} + /* ========================= FinishShader @@ -3081,6 +3202,8 @@ static shader_t *FinishShader( void ) { hasLightmapStage = qfalse; } + FixFatLightmapTexCoords(); + // // look for multitexture potential // @@ -3243,6 +3366,10 @@ most world construction surfaces. =============== */ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) { + return R_FindShaderEx( name, lightmapIndex, mipRawImage, lightmapIndex ); +} + +shader_t *R_FindShaderEx( const char *name, int lightmapIndex, qboolean mipRawImage, int realLightmapIndex ) { char strippedName[MAX_QPATH]; int hash; char *shaderText; @@ -3282,7 +3409,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag } } - InitShader( strippedName, lightmapIndex ); + InitShaderEx( strippedName, lightmapIndex, realLightmapIndex ); // // attempt to define shader from an explicit parameter file diff --git a/code/renderergl2/tr_sky.c b/code/renderergl2/tr_sky.c index 94f68d26e6..c79f48f5a6 100644 --- a/code/renderergl2/tr_sky.c +++ b/code/renderergl2/tr_sky.c @@ -435,7 +435,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max */ { shaderProgram_t *sp = &tr.lightallShader[0]; - vec4_t vector; + vec4_t st[2]; GLSL_BindProgram(sp); @@ -453,11 +453,16 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max color[3] = 0.0f; GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, color); - VectorSet4(vector, 1.0, 0.0, 0.0, 1.0); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector); - - VectorSet4(vector, 0.0, 0.0, 0.0, 0.0); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); + VectorSet4(st[0], 1.0f, 0.0f, 0.0f, 0.0f); + VectorSet4(st[1], 0.0f, 1.0f, 0.0f, 0.0f); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX0, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX1, st[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX2, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX3, st[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX4, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX5, st[1]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX6, st[0]); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX7, st[1]); GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0); } diff --git a/code/sdl/sdl_input.c b/code/sdl/sdl_input.c index 390f7b3b33..1660cf75da 100644 --- a/code/sdl/sdl_input.c +++ b/code/sdl/sdl_input.c @@ -1168,6 +1168,28 @@ static void IN_ProcessEvents( void ) } break; +#if defined(PROTOCOL_HANDLER) && defined(__APPLE__) + case SDL_DROPFILE: + { + char *filename = e.drop.file; + + // Handle macOS open URL event. URL protocol scheme must be set in Info.plist. + if( !Q_strncmp( filename, PROTOCOL_HANDLER ":", strlen( PROTOCOL_HANDLER ":" ) ) ) + { + char *protocolCommand = Sys_ParseProtocolUri( filename ); + + if( protocolCommand ) + { + Cbuf_ExecuteText( EXEC_APPEND, va( "%s\n", protocolCommand ) ); + free( protocolCommand ); + } + } + + SDL_free( filename ); + } + break; +#endif + default: break; } @@ -1250,6 +1272,10 @@ void IN_Init( void *windowData ) in_joystick = Cvar_Get( "in_joystick", "0", CVAR_ARCHIVE|CVAR_LATCH ); in_joystickThreshold = Cvar_Get( "joy_threshold", "0.15", CVAR_ARCHIVE ); +#if defined(PROTOCOL_HANDLER) && defined(__APPLE__) + SDL_EventState( SDL_DROPFILE, SDL_ENABLE ); +#endif + SDL_StartTextInput( ); mouseAvailable = ( in_mouse->value != 0 ); diff --git a/code/server/sv_client.c b/code/server/sv_client.c index 62d6456ed1..1d230c07ca 100644 --- a/code/server/sv_client.c +++ b/code/server/sv_client.c @@ -1917,7 +1917,7 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) { // NOTE: when the client message is fux0red the acknowledgement numbers // can be out of range, this could cause the server to send thousands of server // commands which the server thinks are not yet acknowledged in SV_UpdateServerCommandsToClient - if (cl->reliableAcknowledge < cl->reliableSequence - MAX_RELIABLE_COMMANDS) { + if ((cl->reliableSequence - cl->reliableAcknowledge >= MAX_RELIABLE_COMMANDS) || (cl->reliableSequence - cl->reliableAcknowledge < 0)) { // usually only hackers create messages like this // it is more annoying for them to let them hanging #ifndef NDEBUG diff --git a/code/sys/sys_local.h b/code/sys/sys_local.h index cd7fbe7fa2..248a51cdf8 100644 --- a/code/sys/sys_local.h +++ b/code/sys/sys_local.h @@ -64,3 +64,7 @@ void Sys_AnsiColorPrint( const char *msg ); int Sys_PID( void ); qboolean Sys_PIDIsRunning( int pid ); + +#ifdef PROTOCOL_HANDLER +char *Sys_ParseProtocolUri( const char *uri ); +#endif diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c index 3e8d8b3f3a..d32f989f39 100644 --- a/code/sys/sys_main.c +++ b/code/sys/sys_main.c @@ -649,6 +649,80 @@ void Sys_ParseArgs( int argc, char **argv ) } } +#ifdef PROTOCOL_HANDLER +/* +================= +Sys_ParseProtocolUri + +This parses a protocol URI, e.g. "quake3://connect/example.com:27950" +to a string that can be run in the console, or a null pointer if the +operation is invalid or unsupported. +At the moment only the "connect" command is supported. +================= +*/ +char *Sys_ParseProtocolUri( const char *uri ) +{ + // Both "quake3://" and "quake3:" can be used + if ( Q_strncmp( uri, PROTOCOL_HANDLER ":", strlen( PROTOCOL_HANDLER ":" ) ) ) + { + Com_Printf( "Sys_ParseProtocolUri: unsupported protocol.\n" ); + return NULL; + } + uri += strlen( PROTOCOL_HANDLER ":" ); + if ( !Q_strncmp( uri, "//", strlen( "//" ) ) ) + { + uri += strlen( "//" ); + } + Com_Printf( "Sys_ParseProtocolUri: %s\n", uri ); + + // At the moment, only "connect/hostname:port" is supported + if ( !Q_strncmp( uri, "connect/", strlen( "connect/" ) ) ) + { + int i, bufsize; + char *out; + + uri += strlen( "connect/" ); + if ( *uri == '\0' || *uri == '?' ) + { + Com_Printf( "Sys_ParseProtocolUri: missing argument.\n" ); + return NULL; + } + + // Check for any unsupported characters + // For safety reasons, the "hostname:port" part can only + // contain characters from: a-zA-Z0-9.:-[] + for ( i=0; uri[i] != '\0'; i++ ) + { + if ( uri[i] == '?' ) + { + // For forwards compatibility, any query string parameters are ignored (e.g. "?password=abcd") + // However, these are not passed on macOS, so it may be a bad idea to add them. + break; + } + + if ( isalpha( uri[i] ) == 0 && isdigit( uri[i] ) == 0 + && uri[i] != '.' && uri[i] != ':' && uri[i] != '-' + && uri[i] != '[' && uri[i] != ']' ) + { + Com_Printf( "Sys_ParseProtocolUri: hostname contains unsupported character.\n" ); + return NULL; + } + } + + bufsize = strlen( "connect " ) + i + 1; + out = malloc( bufsize ); + strcpy( out, "connect " ); + strncat( out, uri, i ); + return out; + } + else + { + Com_Printf( "Sys_ParseProtocolUri: unsupported command.\n" ); + return NULL; + } +} +#endif + #ifndef DEFAULT_BASEDIR # ifdef __APPLE__ # define DEFAULT_BASEDIR Sys_StripAppBundle(Sys_BinaryPath()) @@ -697,6 +771,9 @@ int main( int argc, char **argv ) { int i; char commandLine[ MAX_STRING_CHARS ] = { 0 }; +#ifdef PROTOCOL_HANDLER + char *protocolCommand = NULL; +#endif extern void Sys_LaunchAutoupdater(int argc, char **argv); Sys_LaunchAutoupdater(argc, argv); @@ -747,7 +824,22 @@ int main( int argc, char **argv ) // Concatenate the command line for passing to Com_Init for( i = 1; i < argc; i++ ) { - const qboolean containsSpaces = strchr(argv[i], ' ') != NULL; + qboolean containsSpaces; + + // For security reasons we always detect --uri, even when PROTOCOL_HANDLER is undefined + // Any arguments after "--uri quake3://..." is ignored + if ( !strcmp( argv[i], "--uri" ) ) + { +#ifdef PROTOCOL_HANDLER + if ( argc > i+1 ) + { + protocolCommand = Sys_ParseProtocolUri( argv[i+1] ); + } +#endif + break; + } + + containsSpaces = strchr(argv[i], ' ') != NULL; if (containsSpaces) Q_strcat( commandLine, sizeof( commandLine ), "\"" ); @@ -759,6 +851,15 @@ int main( int argc, char **argv ) Q_strcat( commandLine, sizeof( commandLine ), " " ); } +#ifdef PROTOCOL_HANDLER + if ( protocolCommand != NULL ) + { + Q_strcat( commandLine, sizeof( commandLine ), "+" ); + Q_strcat( commandLine, sizeof( commandLine ), protocolCommand ); + free( protocolCommand ); + } +#endif + CON_Init( ); Com_Init( commandLine ); NET_Init( ); diff --git a/code/sys/sys_unix.c b/code/sys/sys_unix.c index beae5e3596..2299c2fe20 100644 --- a/code/sys/sys_unix.c +++ b/code/sys/sys_unix.c @@ -36,6 +36,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include #ifndef __amigaos4__ #include @@ -377,6 +378,10 @@ void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, ch return; } + if ( basedir[0] == '\0' ) { + return; + } + if (strlen(subdirs)) { Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs ); } @@ -456,6 +461,11 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter return listCopy; } + if ( directory[0] == '\0' ) { + *numfiles = 0; + return NULL; + } + if ( !extension) extension = ""; @@ -570,11 +580,15 @@ void Sys_Sleep( int msec ) } else { + struct timespec req; + // With nothing to select() on, we can't wait indefinitely if( msec < 0 ) msec = 10; - usleep( msec * 1000 ); + req.tv_sec = msec/1000; + req.tv_nsec = (msec%1000)*1000000; + nanosleep(&req, NULL); } } diff --git a/code/sys/sys_win32.c b/code/sys/sys_win32.c index e40caaa06b..7d806a1674 100644 --- a/code/sys/sys_win32.c +++ b/code/sys/sys_win32.c @@ -20,6 +20,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ +// Use EnumProcesses() with Windows XP compatibility +#define PSAPI_VERSION 1 + #include "../qcommon/q_shared.h" #include "../qcommon/qcommon.h" #include "sys_local.h" @@ -483,6 +486,10 @@ void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, ch return; } + if ( basedir[0] == '\0' ) { + return; + } + if (strlen(subdirs)) { Com_sprintf( search, sizeof(search), "%s\\%s\\*", basedir, subdirs ); } @@ -584,6 +591,11 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter return listCopy; } + if ( directory[0] == '\0' ) { + *numfiles = 0; + return NULL; + } + if ( !extension) { extension = ""; } diff --git a/code/tools/lcc/cpp/lex.c b/code/tools/lcc/cpp/lex.c index 8030354efc..66092e1b9d 100644 --- a/code/tools/lcc/cpp/lex.c +++ b/code/tools/lcc/cpp/lex.c @@ -511,6 +511,25 @@ foldline(Source *s) return 0; } +// This doesn't have proper tracking across read() to only remove \r from \r\n sequence. +// The lexer doesn't correctly handle standalone \r anyway though. +int +crlf_to_lf(unsigned char *buf, int n) { + int i, count; + + count = 0; + + for (i = 0; i < n; i++) { + if (buf[i] == '\r') { + continue; + } + + buf[count++] = buf[i]; + } + + return count; +} + int fillbuf(Source *s) { @@ -521,6 +540,7 @@ fillbuf(Source *s) error(FATAL, "Input buffer overflow"); if (s->fd<0 || (n=read(s->fd, (char *)s->inl, INS/8)) <= 0) n = 0; + n = crlf_to_lf(s->inl, n); if ((*s->inp&0xff) == EOB) /* sentinel character appears in input */ *s->inp = EOFC; s->inl += n; diff --git a/code/tools/lcc/cpp/unix.c b/code/tools/lcc/cpp/unix.c index bac841d8bd..56f1fff5c1 100644 --- a/code/tools/lcc/cpp/unix.c +++ b/code/tools/lcc/cpp/unix.c @@ -65,6 +65,9 @@ setup(int argc, char **argv) fp = (char*)newstring((uchar*)argv[optind], strlen(argv[optind]), 0); if ((fd = open(fp, 0)) <= 0) error(FATAL, "Can't open input file %s", fp); +#ifdef WIN32 + _setmode(fd, _O_BINARY); +#endif } if (optind+1" fi + if [ -n "${PROTOCOL_HANDLER}" ]; then + PLIST="${PLIST} + CFBundleURLTypes + + + CFBundleURLName + ${PRODUCT_NAME} + CFBundleURLSchemes + + ${PROTOCOL_HANDLER} + + + " + fi + PLIST="${PLIST} NSHumanReadableCopyright QUAKE III ARENA Copyright © 1999-2000 id Software, Inc. All rights reserved. diff --git a/misc/msvc/.gitignore b/misc/msvc/.gitignore new file mode 100644 index 0000000000..3e8a1553fc --- /dev/null +++ b/misc/msvc/.gitignore @@ -0,0 +1,341 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ +# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true +**/wwwroot/lib/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb diff --git a/misc/msvc10/.gitignore b/misc/msvc10/.gitignore new file mode 100644 index 0000000000..3e8a1553fc --- /dev/null +++ b/misc/msvc10/.gitignore @@ -0,0 +1,341 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ +# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true +**/wwwroot/lib/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb diff --git a/misc/msvc11/.gitignore b/misc/msvc11/.gitignore new file mode 100644 index 0000000000..3e8a1553fc --- /dev/null +++ b/misc/msvc11/.gitignore @@ -0,0 +1,341 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ +# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true +**/wwwroot/lib/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb diff --git a/misc/msvc12/.gitignore b/misc/msvc12/.gitignore index 4ba92b04af..3e8a1553fc 100644 --- a/misc/msvc12/.gitignore +++ b/misc/msvc12/.gitignore @@ -211,7 +211,7 @@ _pkginfo.txt # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache -!*.[Cc]ache/ +!?*.[Cc]ache/ # Others ClientBin/ @@ -336,3 +336,6 @@ ASALocalRun/ # Local History for Visual Studio .localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb diff --git a/misc/nsis/Makefile b/misc/nsis/Makefile index 3875e4e502..a17d2a458d 100644 --- a/misc/nsis/Makefile +++ b/misc/nsis/Makefile @@ -22,9 +22,6 @@ endif ifndef USE_CURL_DLOPEN USE_CURL_DLOPEN=0 endif -ifndef USE_INTERNAL_SPEEX -USE_INTERNAL_SPEEX=1 -endif ifndef USE_INTERNAL_ZLIB USE_INTERNAL_ZLIB=1 endif @@ -56,9 +53,6 @@ endif ifeq ($(USE_CURL_DLOPEN),1) DEFINES+= -DUSE_CURL_DLOPEN endif -ifeq ($(USE_INTERNAL_SPEEX),1) - DEFINES+= -DUSE_INTERNAL_SPEEX -endif ifeq ($(USE_INTERNAL_ZLIB),1) DEFINES+= -DUSE_INTERNAL_ZLIB endif diff --git a/misc/nsis/ioquake3.nsi.in b/misc/nsis/ioquake3.nsi.in index de029e64bc..a4bf5cb5de 100644 --- a/misc/nsis/ioquake3.nsi.in +++ b/misc/nsis/ioquake3.nsi.in @@ -7,6 +7,8 @@ ; ; you have to copy OpenAL32.dll here manually +!define VERSION "XXXVERSIONXXX" + !define MULTIUSER_MUI !define MULTIUSER_EXECUTIONLEVEL Highest !define MULTIUSER_INSTALLMODE_COMMANDLINE @@ -20,11 +22,13 @@ !include "MUI2.nsh" !define MUI_ICON "../quake3.ico" +!include LogicLib.nsh + ; The name of the installer Name "ioquake3" ; The file to write -OutFile "ioquake3-XXXVERSIONXXX-XXXRELEASEXXX.x86.exe" +OutFile "ioquake3-${VERSION}-XXXRELEASEXXX.x86.exe" ; The default installation directory ; set by Multiuser.nsh @@ -45,7 +49,7 @@ OutFile "ioquake3-XXXVERSIONXXX-XXXRELEASEXXX.x86.exe" !insertmacro MULTIUSER_PAGE_INSTALLMODE ;!insertmacro MUI_PAGE_LICENSE "../../COPYING.txt" -!define MUI_COMPONENTSPAGE_NODESC +!define MUI_COMPONENTSPAGE_SMALLDESC !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES @@ -71,16 +75,14 @@ Function un.onInit FunctionEnd ; The stuff to install -Section "ioquake3 (required)" +Section "ioquake3 ${VERSION} (required)" ioquake3 SectionIn RO ; Set output path to the installation directory. SetOutPath $INSTDIR -!ifndef USE_INTERNAL_SPEEX - File "libspeex.dll" -!endif + File "../../build/release-mingw32-x86/SDL2.dll" !ifndef USE_INTERNAL_ZLIB File "zlib1.dll" !endif @@ -116,6 +118,7 @@ Section "ioquake3 (required)" ; Write the uninstall keys for Windows WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\ioquake3" "DisplayName" "ioquake3" + WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\ioquake3" "DisplayVersion" "${VERSION}" WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\ioquake3" "UninstallString" '"$INSTDIR\uninstall.exe"' WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\ioquake3" "NoModify" 1 WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\ioquake3" "NoRepair" 1 @@ -124,7 +127,7 @@ Section "ioquake3 (required)" SectionEnd ; Optional section (can be disabled by the user) -Section "Start Menu Shortcuts" +Section "Start Menu Shortcuts" StartMenuShortcuts CreateDirectory "$SMPROGRAMS\ioquake3" CreateShortCut "$SMPROGRAMS\ioquake3\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 @@ -132,16 +135,18 @@ Section "Start Menu Shortcuts" SectionEnd -Section "SDL2.dll" +Section "Protocol Handler" ProtocolHandler - SetOutPath $INSTDIR - - File "../../build/release-mingw32-x86/SDL2.dll" + WriteRegStr SHCTX "Software\Classes\quake3" "CustomUrlApplication" "$INSTDIR\ioquake3.x86.exe" + WriteRegStr SHCTX "Software\Classes\quake3" "CustomUrlArguments" '--uri "%1"' + WriteRegStr SHCTX "Software\Classes\quake3" "URL Protocol" "" + WriteRegStr SHCTX "Software\Classes\quake3\DefaultIcon" "" "$INSTDIR\ioquake3.x86.exe,0" + WriteRegStr SHCTX "Software\Classes\quake3\shell\open\command" "" '"$INSTDIR\ioquake3.x86.exe" --uri "%1"' SectionEnd !ifdef USE_OPENAL_DLOPEN -Section "OpenAL-Soft library" +Section "OpenAL-Soft library" OpenAL SetOutPath $INSTDIR @@ -151,7 +156,7 @@ SectionEnd !endif !ifdef USE_CURL_DLOPEN -Section "libcurl" +Section "libcurl" libcurl SetOutPath $INSTDIR @@ -170,6 +175,11 @@ Section "Uninstall" DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\ioquake3" DeleteRegKey SHCTX "Software\ioquake3" + ReadRegStr $0 SHCTX "Software\Classes\quake3\shell\open\command" "" + ${If} $0 == '"$INSTDIR\ioquake3.x86.exe" --uri "%1"' + DeleteRegKey SHCTX "Software\Classes\quake3" + ${EndIf} + ; Remove files and uninstaller Delete $INSTDIR\baseq3\cgamex86.dll Delete $INSTDIR\baseq3\qagamex86.dll @@ -189,9 +199,7 @@ Section "Uninstall" Delete $INSTDIR\id-readme.txt Delete $INSTDIR\voip-readme.txt -!ifndef USE_INTERNAL_SPEEX - Delete $INSTDIR\libspeex.dll -!endif + Delete $INSTDIR\SDL2.dll !ifndef USE_INTERNAL_ZLIB Delete $INSTDIR\zlib1.dll !endif @@ -199,7 +207,6 @@ Section "Uninstall" Delete $INSTDIR\jpeg8c.dll !endif - Delete $INSTDIR\SDL2.dll !ifdef USE_OPENAL_DLOPEN Delete $INSTDIR\OpenAL32.dll !endif @@ -220,3 +227,15 @@ Section "Uninstall" RMDir "$INSTDIR" SectionEnd + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${ioquake3} "The game executables." + !insertmacro MUI_DESCRIPTION_TEXT ${StartMenuShortcuts} "Create shortcuts in the start menu." + !insertmacro MUI_DESCRIPTION_TEXT ${ProtocolHandler} "The protocol handler lets you connect to a game by clicking a link in a web browser." +!ifdef USE_OPENAL_DLOPEN + !insertmacro MUI_DESCRIPTION_TEXT ${OpenAL} "Advanced audio mixer that supports surround sound." +!endif +!ifdef USE_CURL_DLOPEN + !insertmacro MUI_DESCRIPTION_TEXT ${libcurl} "Used for HTTP file downloads." +!endif +!insertmacro MUI_FUNCTION_DESCRIPTION_END diff --git a/misc/setup/ioquake3.desktop b/misc/setup/ioquake3.desktop index 0ccff3ad2f..644d424c72 100644 --- a/misc/setup/ioquake3.desktop +++ b/misc/setup/ioquake3.desktop @@ -1,9 +1,10 @@ [Desktop Entry] Name=ioquake3 -Exec=ioquake3 +Exec=ioquake3 --uri %u Icon=quake3 Type=Application Terminal=false Encoding=UTF-8 Categories=Game;ActionGame; +MimeType=x-scheme-handler/quake3; X-SuSE-translate=false diff --git a/misc/setup/org.ioquake3.ioquake3.metainfo.xml b/misc/setup/org.ioquake3.ioquake3.metainfo.xml new file mode 100644 index 0000000000..a416464cf4 --- /dev/null +++ b/misc/setup/org.ioquake3.ioquake3.metainfo.xml @@ -0,0 +1,28 @@ + + + org.ioquake3.ioquake3 + ioquake3.desktop + CC0-1.0 + GPL-2.0-or-later + ioquake3 + Free and open-source Quake 3 based engine + +

+ ioquake3 is a free and open-source software first person shooter engine based on the Quake 3: Arena and Quake 3: Team Arena source code. +

+

+ The source code is licensed under the GPL version 2, and was first released under that license by id software on August 20th, 2005. Since then, + our dedicated team has been working hard to improve it, fixing bugs, and adding just the right new features to make the engine even better than before. +

+
+ https://ioquake3.org + https://github.com/ioquake/ioq3/issues + https://github.com/ioquake/ioq3 + The ioquake Group + + intense + intense + intense + intense + +