diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 393b88fd..5d2cc660 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ jobs: name: Linux runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v3 + - 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@v3 + - uses: actions/upload-artifact@v4 with: name: Linux path: build/*.zip @@ -23,14 +23,14 @@ jobs: name: Windows runs-on: windows-2019 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Compile run: | choco install zip make release env: ARCHIVE: 1 - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: Windows path: build/*.zip @@ -38,12 +38,12 @@ jobs: name: macOS runs-on: macos-11 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Compile run: make release env: ARCHIVE: 1 - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: macOS path: build/*.zip diff --git a/Makefile b/Makefile index 7834521e..2ad34f29 100644 --- a/Makefile +++ b/Makefile @@ -1086,7 +1086,6 @@ endif ifneq ($(HAVE_VM_COMPILED),true) BASE_CFLAGS += -DNO_VM_COMPILED - BUILD_GAME_QVM=0 endif TARGETS = diff --git a/code/botlib/be_aas.h b/code/botlib/be_aas.h index dbf24bc1..cb7d73c9 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 f4d91720..3de8f780 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/renderergl2/glsl/generic_vp.glsl b/code/renderergl2/glsl/generic_vp.glsl index a0055263..e6af9f81 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 428cf1e6..8ff5e7bb 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 ba3e2abb..5c160ab4 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 && (!r_postProcess->integer || !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) 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(r_postProcess->integer ? NULL : 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(r_postProcess->integer ? NULL : 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); } @@ -1201,6 +1204,13 @@ const void *RB_DrawBuffer( const void *data ) { if ( r_clear->integer ) { qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + if (glRefConfig.framebufferObject && tr.renderFbo) { + FBO_Bind(tr.renderFbo); + + qglClearColor( 1, 0, 0.5, 1 ); + qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + } } return (const void *)(cmd + 1); @@ -1313,14 +1323,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,7 +1381,7 @@ const void *RB_SwapBuffers( const void *data ) { if (glRefConfig.framebufferObject) { - if (!backEnd.framePostProcessed) + if (!r_postProcess->integer) { if (tr.msaaResolveFbo && r_hdr->integer) { @@ -1401,7 +1404,6 @@ const void *RB_SwapBuffers( const void *data ) { GLimp_EndFrame(); - backEnd.framePostProcessed = qfalse; backEnd.projection2D = qfalse; return (const void *)(cmd + 1); @@ -1655,8 +1657,6 @@ const void *RB_PostProcess(const void *data) } #endif - backEnd.framePostProcessed = qtrue; - return (const void *)(cmd + 1); } diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index ad5fe3a3..15f5f3cd 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 26f50c3f..223cbe7f 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 86cca599..2c834f10 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_local.h b/code/renderergl2/tr_local.h index 668dbbdd..6a0aa36f 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_shade.c b/code/renderergl2/tr_shade.c index 5300898c..21f9543a 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 0cd78a78..b08a9328 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 94f68d26..c79f48f5 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/sys/sys_unix.c b/code/sys/sys_unix.c index a0d67db9..98c65483 100644 --- a/code/sys/sys_unix.c +++ b/code/sys/sys_unix.c @@ -369,6 +369,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 ); } @@ -448,6 +452,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/sys/sys_win32.c b/code/sys/sys_win32.c index 67cf0e97..cdd41a1b 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" @@ -478,6 +481,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 ); } @@ -579,6 +586,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 8030354e..66092e1b 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 bac841d8..56f1fff5 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 + + 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 + +