diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..3f066560 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.c text eol=lf diff=cpp +*.h text eol=lf diff=cpp +wscript text eol=lf diff=python diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 4b4e0df2..7cbf2b4c 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -40,8 +40,6 @@ jobs: ANDROID_SDK_TOOLS_VER: 4333796 ANDROID_NDK_VER: r10e UPLOADTOOL_ISPRERELEASE: true - PVS_URL: https://files.pvs-studio.com/pvs-studio-7.14.50353.142-x86_64.tgz - PVS_VERSION: pvs-studio-7.14.50353.142-x86_64 steps: - name: Checkout uses: actions/checkout@v2 @@ -59,41 +57,15 @@ jobs: - name: Build engine run: bash scripts/gha/build_${{ matrix.targetos }}.sh - # - name: Upload engine (android) - # if: matrix.targetos == 'android' - # run: bash scripts/continious_upload.sh xashdroid-${{ matrix.targetarch }}.apk - # - name: Upload engine (motomagx) - # if: matrix.targetos == 'motomagx' - # run: bash scripts/continious_upload.sh xash3d-fwgs-magx.7z - # - name: Upload engine (linux) - # if: matrix.targetos == 'linux' - # run: bash scripts/continious_upload.sh xash3d-fwgs-${{ matrix.targetarch }}.AppImage xashds-linux-${{ matrix.targetarch }} - # - name: Upload engine (windows) - # if: matrix.targetos == 'win32' - # run: bash scripts/continious_upload.sh xash3d-fwgs-win32-${{ matrix.targetarch }}.7z xash3d-fwgs-vc2008-sln-${{ matrix.targetarch }}.7z - # - # - name: Cache PVS-Studio - # if: matrix.targetos == 'linux' && matrix.targetarch == 'amd64' - # id: cache-pvs-studio - # uses: actions/cache@v2 - # with: - # path: pvs-studio.tgz - # key: pvs-studio-key - # - name: Get PVS-Studio - # if: matrix.targetos == 'linux' && matrix.targetarch == 'amd64' && steps.cache-pvs-studio.outputs.cache-hit != 'true' - # run: wget --no-verbose ${{ env.PVS_URL }} -O pvs-studio.tgz - # - # - name: Static analysis - # if: matrix.targetos == 'linux' && matrix.targetarch == 'amd64' - # run: | - # tar -xvf pvs-studio.tgz && mv ${{ env.PVS_VERSION }} pvs-studio - # mkdir -p ~/.config/PVS-Studio - # echo ${{ secrets.PVS_NAME }} > ~/.config/PVS-Studio/PVS-Studio.lic - # echo ${{ secrets.PVS_KEY }} >> ~/.config/PVS-Studio/PVS-Studio.lic - # pvs-studio/bin/pvs-studio-analyzer analyze --file build/compile_commands.json -j3 - # pvs-studio/bin/plog-converter -a GA:1,2 -t sarif -o report.sarif PVS-Studio.log - # - name: Upload SARIF - # if: matrix.targetos == 'linux' && matrix.targetarch == 'amd64' - # uses: github/codeql-action/upload-sarif@v1 - # with: - # sarif_file: report.sarif + - name: Upload engine (android) + if: matrix.targetos == 'android' + run: bash scripts/continious_upload.sh xashdroid-${{ matrix.targetarch }}.apk + - name: Upload engine (motomagx) + if: matrix.targetos == 'motomagx' + run: bash scripts/continious_upload.sh xash3d-fwgs-magx.7z + - name: Upload engine (linux) + if: matrix.targetos == 'linux' + run: bash scripts/continious_upload.sh xash3d-fwgs-${{ matrix.targetarch }}.AppImage xashds-linux-${{ matrix.targetarch }} + - name: Upload engine (windows) + if: matrix.targetos == 'win32' + run: bash scripts/continious_upload.sh xash3d-fwgs-win32-${{ matrix.targetarch }}.7z diff --git a/common/port.h b/common/port.h index 102b6dff..183f1fe7 100644 --- a/common/port.h +++ b/common/port.h @@ -61,7 +61,6 @@ GNU General Public License for more details. #define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) #define LoadLibrary( x ) dlopen( x, RTLD_NOW ) #define GetProcAddress( x, y ) dlsym( x, y ) - #define SetCurrentDirectory( x ) (!chdir( x )) #define FreeLibrary( x ) dlclose( x ) #define tell( a ) lseek(a, 0, SEEK_CUR) #define HAVE_DUP @@ -72,7 +71,6 @@ GNU General Public License for more details. #define LoadLibrary( x ) (0) #define GetProcAddress( x, y ) (0) #define FreeLibrary( x ) (0) - #define SetCurrentDirectory( x ) (!chdir( x )) #endif //#define MAKEWORD( a, b ) ((short int)(((unsigned char)(a))|(((short int)((unsigned char)(b)))<<8))) #define max( a, b ) (((a) > (b)) ? (a) : (b)) diff --git a/engine/client/cl_efx.c b/engine/client/cl_efx.c index df02c7ce..9db01f93 100644 --- a/engine/client/cl_efx.c +++ b/engine/client/cl_efx.c @@ -513,19 +513,19 @@ void CL_ReadLineFile_f( void ) while( 1 ) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; p1[0] = Q_atof( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; p1[1] = Q_atof( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; p1[2] = Q_atof( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; if( token[0] != '-' ) @@ -534,15 +534,15 @@ void CL_ReadLineFile_f( void ) break; } - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; p2[0] = Q_atof( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; p2[1] = Q_atof( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; p2[2] = Q_atof( token ); @@ -2020,15 +2020,15 @@ void CL_ReadPointFile_f( void ) while( 1 ) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; org[0] = Q_atof( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; org[1] = Q_atof( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !pfile ) break; org[2] = Q_atof( token ); diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 64dda1d2..259a5bc1 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -234,7 +234,7 @@ void CL_InitCDAudio( const char *filename ) pfile = (char *)afile; // format: trackname\n [num] - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { if( !Q_stricmp( token, "blank" )) token[0] = '\0'; Q_strncpy( clgame.cdtracks[c], token, sizeof( clgame.cdtracks[0] )); @@ -966,7 +966,7 @@ static void CL_DrawLoadingOrPaused( qboolean paused, float percent ) SPR_AdjustSizei( &x, &y, &width, &height ); - if( !paused && cl_allow_levelshots->value ) + if( !paused ) { float step, s2; @@ -1535,7 +1535,7 @@ static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount ) if( !afile ) return NULL; pfile = (char *)afile; - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); numSprites = Q_atoi( token ); Q_strncpy( pEntry->szListName, psz, sizeof( pEntry->szListName )); @@ -1545,30 +1545,30 @@ static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount ) for( index = 0; index < numSprites; index++ ) { - if(( pfile = COM_ParseFile( pfile, token )) == NULL ) + if(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) == NULL ) break; Q_strncpy( pEntry->pList[index].szName, token, sizeof( pEntry->pList[0].szName )); // read resolution - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); pEntry->pList[index].iRes = Q_atoi( token ); // read spritename - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); Q_strncpy( pEntry->pList[index].szSprite, token, sizeof( pEntry->pList[0].szSprite )); // parse rectangle - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); pEntry->pList[index].rc.left = Q_atoi( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); pEntry->pList[index].rc.top = Q_atoi( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); pEntry->pList[index].rc.right = pEntry->pList[index].rc.left + Q_atoi( token ); - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); pEntry->pList[index].rc.bottom = pEntry->pList[index].rc.top + Q_atoi( token ); pEntry->count++; @@ -3078,9 +3078,7 @@ char *pfnParseFile( char *data, char *token ) { char *out; - host.com_handlecolon = true; - out = COM_ParseFile( data, token ); - host.com_handlecolon = false; + out = _COM_ParseFileSafe( data, token, INT_MAX, PFILE_HANDLECOLON, NULL ); return out; } diff --git a/engine/client/cl_gameui.c b/engine/client/cl_gameui.c index 05362add..382a5e21 100644 --- a/engine/client/cl_gameui.c +++ b/engine/client/cl_gameui.c @@ -1106,6 +1106,17 @@ static void GAME_EXPORT UI_ShellExecute( const char *path, const char *parms, in Sys_Quit(); } +/* +============== +pfnParseFile + +legacy wrapper +============== +*/ +static char *pfnParseFile( char *buf, char *token ) +{ + return COM_ParseFile( buf, token, INT_MAX ); +} // engine callbacks static ui_enginefuncs_t gEngfuncs = @@ -1159,7 +1170,7 @@ static ui_enginefuncs_t gEngfuncs = CL_Active, pfnClientJoin, COM_LoadFileForMe, - COM_ParseFile, + pfnParseFile, COM_FreeFile, Key_ClearStates, Key_SetKeyDest, @@ -1221,7 +1232,8 @@ static ui_extendedfuncs_t gExtendedfuncs = Con_UtfMoveLeft, Con_UtfMoveRight, pfnGetRenderers, - Sys_DoubleTime + Sys_DoubleTime, + _COM_ParseFileSafe }; void UI_UnloadProgs( void ) diff --git a/engine/client/cl_mobile.c b/engine/client/cl_mobile.c index 54d0d0e4..52d6df2b 100644 --- a/engine/client/cl_mobile.c +++ b/engine/client/cl_mobile.c @@ -108,7 +108,8 @@ static mobile_engfuncs_t gpMobileEngfuncs = pfnDrawScaledCharacter, Sys_Warn, pfnGetNativeObject, - ID_SetCustomClientID + ID_SetCustomClientID, + _COM_ParseFileSafe }; qboolean Mobile_Init( void ) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 6294f91b..917da93c 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1743,7 +1743,7 @@ void CL_ParseResLocation( sizebuf_t *msg ) return; } - while( ( data = COM_ParseFile( data, token ) ) ) + while( ( data = COM_ParseFile( data, token, sizeof( token ) ) ) ) { Con_Reportf( "Adding %s as download location\n", token ); diff --git a/engine/client/cl_qparse.c b/engine/client/cl_qparse.c index 37b94930..be3015ad 100644 --- a/engine/client/cl_qparse.c +++ b/engine/client/cl_qparse.c @@ -861,9 +861,7 @@ void CL_QuakeExecStuff( void ) if( !*text ) break; - host.com_ignorebracket = true; - text = COM_ParseFile( text, token ); - host.com_ignorebracket = false; + text = _COM_ParseFileSafe( text, token, sizeof( token ), PFILE_IGNOREBRACKET, NULL ); if( !text ) break; diff --git a/engine/client/cl_video.c b/engine/client/cl_video.c index 7884871e..1b4ad6e5 100644 --- a/engine/client/cl_video.c +++ b/engine/client/cl_video.c @@ -104,7 +104,7 @@ void SCR_CheckStartupVids( void ) pfile = (char *)afile; - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { Q_strncpy( cls.movies[c], token, sizeof( cls.movies[0] )); diff --git a/engine/client/console.c b/engine/client/console.c index 45410973..e5009f9c 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -675,7 +675,9 @@ static void Con_LoadConchars( void ) Con_LoadConsoleFont( i, con.chars + i ); // select properly fontsize - if( refState.width <= 640 ) + if( con_fontnum->value >= 0 && con_fontnum->value <= CON_NUMFONTS - 1 ) + fontSize = con_fontnum->value; + else if( refState.width <= 640 ) fontSize = 0; else if( refState.width >= 1280 ) fontSize = 2; diff --git a/engine/client/mod_dbghulls.c b/engine/client/mod_dbghulls.c index 53f7b28f..e1c7e6f2 100644 --- a/engine/client/mod_dbghulls.c +++ b/engine/client/mod_dbghulls.c @@ -17,7 +17,7 @@ GNU General Public License for more details. #include "mod_local.h" #include "xash3d_mathlib.h" #include "world.h" - +#include "eiface.h" // offsetof #define MAX_CLIPNODE_DEPTH 256 // should never exceeds @@ -67,7 +67,7 @@ _inline void list_del( hullnode_t *entry ) static winding_t * winding_alloc( uint numpoints ) { - return (winding_t *)malloc( (int)((winding_t *)0)->p[numpoints] ); + return (winding_t *)malloc( offsetof( winding_t, p[numpoints] ) ); } static void free_winding( winding_t *w ) @@ -84,7 +84,7 @@ static winding_t *winding_copy( winding_t *w ) winding_t *neww; neww = winding_alloc( w->numpoints ); - memcpy( neww, w, (int)((winding_t *)0)->p[w->numpoints] ); + memcpy( neww, w, offsetof( winding_t, p[w->numpoints] ) ); return neww; } @@ -111,7 +111,7 @@ static void winding_reverse( winding_t *w ) static winding_t *winding_shrink( winding_t *w ) { winding_t *neww = winding_alloc( w->numpoints ); - memcpy( neww, w, (int)((winding_t *)0)->p[w->numpoints] ); + memcpy( neww, w, offsetof( winding_t, p[w->numpoints] )); free_winding( w ); return neww; diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index d366c573..636ea315 100644 --- a/engine/client/ref_common.c +++ b/engine/client/ref_common.c @@ -335,7 +335,6 @@ static ref_api_t gEngfuncs = COM_GetProcAddress, FS_LoadFile, - COM_ParseFile, FS_FileExists, FS_AllowDirectPaths, diff --git a/engine/client/s_dsp.c b/engine/client/s_dsp.c index 2aee0483..39a54d4d 100644 --- a/engine/client/s_dsp.c +++ b/engine/client/s_dsp.c @@ -114,6 +114,45 @@ const sx_preset_t rgsxpre[MAXPRESETS] = { 0.0, 0.0, 0.001, 0.999, 0.0, 0.2, 0.8, 2.0, 0.05 } // 28 }; +// 0x0045dca8 enginegl.exe +// SHA256: 42383d32cd712e59ee2c1bd78b7ba48814e680e7026c4223e730111f34a60d66 +const sx_preset_t rgsxpre_hlalpha052[MAXPRESETS] = +{ +// -------reverb-------- -------delay-------- +// lp mod size refl rvblp delay feedback dlylp left +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0 }, // 0 off +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.08, 0.8, 2.0, 0.0 }, // 1 generic +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.02, 0.75, 0.0, 0.001 }, // 2 metalic +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.03, 0.78, 0.0, 0.002 }, // 3 +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.06, 0.77, 0.0, 0.003 }, // 4 +{ 0.0, 0.0, 0.05, 0.85, 1.0, 0.008, 0.96, 2.0, 0.01 }, // 5 tunnel +{ 0.0, 0.0, 0.05, 0.88, 1.0, 0.01, 0.98, 2.0, 0.02 }, // 6 +{ 0.0, 0.0, 0.05, 0.92, 1.0, 0.015, 0.995, 2.0, 0.04 }, // 7 +{ 0.0, 0.0, 0.05, 0.84, 1.0, 0.0, 0.0, 2.0, 0.003 }, // 8 chamber +{ 0.0, 0.0, 0.05, 0.9, 1.0, 0.0, 0.0, 2.0, 0.002 }, // 9 +{ 0.0, 0.0, 0.05, 0.95, 1.0, 0.0, 0.0, 2.0, 0.001 }, // 10 +{ 0.0, 0.0, 0.05, 0.7, 0.0, 0.0, 0.0, 2.0, 0.003 }, // 11 brite +{ 0.0, 0.0, 0.055, 0.78, 0.0, 0.0, 0.0, 2.0, 0.002 }, // 12 +{ 0.0, 0.0, 0.05, 0.86, 0.0, 0.0, 0.0, 2.0, 0.001 }, // 13 +{ 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.01 }, // 14 water +{ 1.0, 1.0, 0.0, 0.0, 1.0, 0.06, 0.85, 2.0, 0.02 }, // 15 +{ 1.0, 1.0, 0.0, 0.0, 1.0, 0.2, 0.6, 2.0, 0.05 }, // 16 +{ 0.0, 0.0, 0.05, 0.8, 1.0, 0.15, 0.48, 2.0, 0.008 }, // 17 concrete +{ 0.0, 0.0, 0.06, 0.9, 1.0, 0.22, 0.52, 2.0, 0.005 }, // 18 +{ 0.0, 0.0, 0.07, 0.94, 1.0, 0.3, 0.6, 2.0, 0.001 }, // 19 +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.3, 0.42, 2.0, 0.0 }, // 20 outside +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.35, 0.48, 2.0, 0.0 }, // 21 +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.38, 0.6, 2.0, 0.0 }, // 22 +{ 0.0, 0.0, 0.05, 0.9, 1.0, 0.2, 0.28, 0.0, 0.0 }, // 23 cavern +{ 0.0, 0.0, 0.07, 0.9, 1.0, 0.3, 0.4, 0.0, 0.0 }, // 24 +{ 0.0, 0.0, 0.09, 0.9, 1.0, 0.35, 0.5, 0.0, 0.0 }, // 25 +{ 0.0, 1.0, 0.01, 0.9, 0.0, 0.0, 0.0, 2.0, 0.05 }, // 26 weirdo +{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.009, 0.999, 2.0, 0.04 }, // 27 +{ 0.0, 0.0, 0.001, 0.999, 0.0, 0.2, 0.8, 2.0, 0.05 }, // 28 +}; + +const sx_preset_t *ptable = rgsxpre; + // cvars convar_t *dsp_off; // disable dsp convar_t *roomwater_type; // water room_type @@ -138,6 +177,8 @@ convar_t *sxdly_feedback; // cycles convar_t *sxdly_delay; // current delay in seconds convar_t *dsp_room; // for compability + +convar_t *dsp_coeff_table; // use release or 0.52 style int idsp_dma_speed; int idsp_room; int room_typeprev; @@ -194,6 +235,8 @@ void SX_Init( void ) sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k ); dsp_off = Cvar_Get( "dsp_off", "0", FCVAR_ARCHIVE, "disable DSP processing" ); + dsp_coeff_table = Cvar_Get( "dsp_coeff_table", "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" ); + roomwater_type = Cvar_Get( "waterroom_type", "14", 0, "water room type" ); room_type = Cvar_Get( "room_type", "0", 0, "current room type preset" ); @@ -352,8 +395,6 @@ void DLY_CheckNewStereoDelayVal( void ) if( dly->delaysamples == 0 ) DLY_Free( STEREODLY ); } - - ClearBits( sxste_delay->flags, FCVAR_CHANGED ); } /* @@ -463,7 +504,6 @@ void DLY_CheckNewDelayVal( void ) } } - ClearBits( sxdly_delay->flags, FCVAR_CHANGED ); dly->lp = sxdly_lp->value; dly->delayfeedback = 255 * sxdly_feedback->value; } @@ -497,9 +537,9 @@ void DLY_DoDelay( int count ) if( dly->lp ) // lowpass { + val = ( dly->lp0 + dly->lp1 + val ) / 3; dly->lp0 = dly->lp1; dly->lp1 = val; - val = ( dly->lp0 + dly->lp1 + (val << 1) ) >> 2; } dly->lpdelayline[dly->idelayinput] = val; @@ -512,7 +552,7 @@ void DLY_DoDelay( int count ) else { dly->lpdelayline[dly->idelayinput] = 0; - dly->lp0 = dly->lp1 = 0; + dly->lp0 = dly->lp1 = dly->lp2 = 0; } DLY_MovePointer( dly ); @@ -547,7 +587,7 @@ void RVB_SetUpDly( int pos, float delay, int kmod ) rgsxdly[pos].idelayoutputxf = rgsxdly[pos].idelayinput - samples; if( rgsxdly[pos].idelayoutputxf < 0 ) rgsxdly[pos].idelayoutputxf += rgsxdly[pos].cdelaysamplesmax; - rgsxdly[pos].xfade = 32; + rgsxdly[pos].xfade = REVERB_XFADE; } if( !rgsxdly[pos].delaysamples ) @@ -582,7 +622,6 @@ void RVB_CheckNewReverbVal( void ) } } - ClearBits( sxrvb_size->flags, FCVAR_CHANGED ); dly1->lp = dly2->lp = sxrvb_lp->value; dly1->delayfeedback = dly2->delayfeedback = (int)(255 * sxrvb_feedback->value); } @@ -609,14 +648,14 @@ int RVB_DoReverbForOneDly( dly_t *dly, const int vlr, const portable_samplepair_ if( dly->xfade || delay || samplepair->left || samplepair->right ) { // modulate delay rate - if( !dly->xfade && !dly->modcur && dly->mod ) + if( !dly->mod ) { dly->idelayoutputxf = dly->idelayoutput + ((COM_RandomLong( 0, 255 ) * delay) >> 9 ); - //dly->xfade = 32; - } + dly->idelayoutputxf %= dly->cdelaysamplesmax; - dly->idelayoutputxf %= dly->cdelaysamplesmax; + dly->xfade = REVERB_XFADE; + } if( dly->xfade ) { @@ -685,7 +724,9 @@ void RVB_DoReverb( int count ) voutm = RVB_DoReverbForOneDly( dly1, vlr, paint ); voutm += RVB_DoReverbForOneDly( dly2, vlr, paint ); - voutm = (11 * voutm) >> 6; + if( dsp_coeff_table->value == 1.0f ) + voutm /= 6; // alpha + else voutm = (11 * voutm) >> 6; paint->left = CLIP( paint->left + voutm ); paint->right = CLIP( paint->right + voutm ); @@ -718,17 +759,18 @@ void RVB_DoAMod( int count ) res.left >>= 2; res.right >>= 2; + rgsxlp[4] = paint->left; + rgsxlp[9] = paint->right; + rgsxlp[0] = rgsxlp[1]; rgsxlp[1] = rgsxlp[2]; rgsxlp[2] = rgsxlp[3]; rgsxlp[3] = rgsxlp[4]; - rgsxlp[4] = paint->left; - + rgsxlp[4] = rgsxlp[5]; rgsxlp[5] = rgsxlp[6]; rgsxlp[6] = rgsxlp[7]; rgsxlp[7] = rgsxlp[8]; rgsxlp[8] = rgsxlp[9]; - rgsxlp[9] = paint->right; } if( sxmod_mod->value ) @@ -814,6 +856,27 @@ void CheckNewDspPresets( void ) if( dsp_off->value != 0.0f ) return; + if( FBitSet( dsp_coeff_table->flags, FCVAR_CHANGED )) + { + switch( (int)dsp_coeff_table->value ) + { + case 0: // release + ptable = rgsxpre; + break; + case 1: // alpha + ptable = rgsxpre_hlalpha052; + break; + default: + ptable = rgsxpre; + break; + } + + SX_ReloadRoomFX(); + room_typeprev = -1; + + ClearBits( dsp_coeff_table->flags, FCVAR_CHANGED ); + } + if( s_listener.waterlevel > 2 ) idsp_room = roomwater_type->value; else idsp_room = room_type->value; @@ -835,7 +898,9 @@ void CheckNewDspPresets( void ) if( idsp_room != room_typeprev ) { - const sx_preset_t *cur = rgsxpre + idsp_room; + const sx_preset_t *cur; + + cur = ptable + idsp_room; Cvar_SetValue( "room_lp", cur->room_lp ); Cvar_SetValue( "room_mod", cur->room_mod ); @@ -853,6 +918,10 @@ void CheckNewDspPresets( void ) RVB_CheckNewReverbVal( ); DLY_CheckNewDelayVal( ); DLY_CheckNewStereoDelayVal(); + + ClearBits( sxrvb_size->flags, FCVAR_CHANGED ); + ClearBits( sxdly_delay->flags, FCVAR_CHANGED ); + ClearBits( sxste_delay->flags, FCVAR_CHANGED ); } void SX_Profiling_f( void ) diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 96c23924..a23a3943 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -1662,7 +1662,7 @@ void SND_UpdateSound( void ) VectorSet( info.color, 1.0f, 1.0f, 1.0f ); info.index = 0; - Con_NXPrintf( &info, "room_type: %i ----(%i)---- painted: %i\n", idsp_room, total - 1, paintedtime ); + Con_NXPrintf( &info, "room_type: %i (%s) ----(%i)---- painted: %i\n", idsp_room, Cvar_VariableString( "dsp_coeff_table" ), total - 1, paintedtime ); } S_StreamBackgroundTrack (); diff --git a/engine/client/s_mix.c b/engine/client/s_mix.c index 78bef1db..f79f7aee 100644 --- a/engine/client/s_mix.c +++ b/engine/client/s_mix.c @@ -988,6 +988,7 @@ void MIX_UpsampleAllPaintbuffers( int end, int count ) // mix 11khz sounds: MIX_MixChannelsToPaintbuffer( end, SOUND_11k, SOUND_11k ); +#if SOUND_DMA_SPEED >= SOUND_22k // upsample all 11khz buffers by 2x // only upsample roombuffer if dsp fx are on KDB: perf MIX_SetCurrentPaintbuffer( IROOMBUFFER ); // operates on MixUpSample @@ -995,7 +996,9 @@ void MIX_UpsampleAllPaintbuffers( int end, int count ) // mix 22khz sounds: MIX_MixChannelsToPaintbuffer( end, SOUND_22k, SOUND_22k ); +#endif +#if SOUND_DMA_SPEED >= SOUND_44k // upsample all 22khz buffers by 2x // only upsample roombuffer if dsp fx are on KDB: perf MIX_SetCurrentPaintbuffer( IROOMBUFFER ); @@ -1003,6 +1006,7 @@ void MIX_UpsampleAllPaintbuffers( int end, int count ) // mix all 44khz sounds to all active paintbuffers MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED ); +#endif // mix raw samples from the video streams MIX_SetCurrentPaintbuffer( IROOMBUFFER ); diff --git a/engine/common/cfgscript.c b/engine/common/cfgscript.c index f426640f..56bd8006 100644 --- a/engine/common/cfgscript.c +++ b/engine/common/cfgscript.c @@ -54,7 +54,7 @@ Return true if next token is pExpext and skip it */ qboolean CSCR_ExpectString( parserstate_t *ps, const char *pExpect, qboolean skip, qboolean error ) { - char *tmp = COM_ParseFile( ps->buf, ps->token ); + char *tmp = COM_ParseFile( ps->buf, ps->token, sizeof( ps->token )); if( !Q_stricmp( ps->token, pExpect ) ) { @@ -99,13 +99,13 @@ CSCR_ParseSingleCvar qboolean CSCR_ParseSingleCvar( parserstate_t *ps, scrvardef_t *result ) { // read the name - ps->buf = COM_ParseFile( ps->buf, result->name ); + ps->buf = COM_ParseFile( ps->buf, result->name, sizeof( result->name )); if( !CSCR_ExpectString( ps, "{", false, true )) return false; // read description - ps->buf = COM_ParseFile( ps->buf, result->desc ); + ps->buf = COM_ParseFile( ps->buf, result->desc, sizeof( result->desc )); if( !CSCR_ExpectString( ps, "{", false, true )) return false; @@ -121,11 +121,11 @@ qboolean CSCR_ParseSingleCvar( parserstate_t *ps, scrvardef_t *result ) break; case T_NUMBER: // min - ps->buf = COM_ParseFile( ps->buf, ps->token ); + ps->buf = COM_ParseFile( ps->buf, ps->token, sizeof( ps->token )); result->fMin = Q_atof( ps->token ); // max - ps->buf = COM_ParseFile( ps->buf, ps->token ); + ps->buf = COM_ParseFile( ps->buf, ps->token, sizeof( ps->token )); result->fMax = Q_atof( ps->token ); if( !CSCR_ExpectString( ps, "}", false, true )) @@ -149,7 +149,7 @@ qboolean CSCR_ParseSingleCvar( parserstate_t *ps, scrvardef_t *result ) return false; // default value - ps->buf = COM_ParseFile( ps->buf, result->value ); + ps->buf = COM_ParseFile( ps->buf, result->value, sizeof( result->value )); if( !CSCR_ExpectString( ps, "}", false, true )) return false; @@ -177,7 +177,7 @@ qboolean CSCR_ParseHeader( parserstate_t *ps ) // Parse in the version # // Get the first token. - ps->buf = COM_ParseFile( ps->buf, ps->token ); + ps->buf = COM_ParseFile( ps->buf, ps->token, sizeof( ps->token )); if( Q_atof( ps->token ) != 1 ) { @@ -188,7 +188,7 @@ qboolean CSCR_ParseHeader( parserstate_t *ps ) if( !CSCR_ExpectString( ps, "DESCRIPTION", false, true )) return false; - ps->buf = COM_ParseFile( ps->buf, ps->token ); + ps->buf = COM_ParseFile( ps->buf, ps->token, sizeof( ps->token )); if( Q_stricmp( ps->token, "INFO_OPTIONS") && Q_stricmp( ps->token, "SERVER_OPTIONS" )) { @@ -247,7 +247,7 @@ static int CSCR_ParseFile( const char *scriptfilename, break; } - if( COM_ParseFile( state.buf, state.token )) + if( COM_ParseFile( state.buf, state.token, sizeof( state.token ))) Con_DPrintf( S_ERROR "Got extra tokens!\n" ); else success = true; finish: diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 481a78ff..e1cc7493 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -595,9 +595,7 @@ void Cmd_TokenizeString( const char *text ) if( cmd_argc == 1 ) cmd_args = text; - host.com_ignorebracket = true; - text = COM_ParseFile( (char*)text, cmd_token ); - host.com_ignorebracket = false; + text = _COM_ParseFileSafe( (char*)text, cmd_token, sizeof( cmd_token ), PFILE_IGNOREBRACKET, NULL ); if( !text ) return; diff --git a/engine/common/common.c b/engine/common/common.c index 8b694e77..06088642 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -429,31 +429,6 @@ uint LZSS_Decompress( const byte *pInput, byte *pOutput ) return totalBytes; } - - - - -/* -============== -COM_IsSingleChar - -interpert this character as single -============== -*/ -static int COM_IsSingleChar( char c ) -{ - if( c == '{' || c == '}' || c == '\'' || c == ',' ) - return true; - - if( !host.com_ignorebracket && ( c == ')' || c == '(' )) - return true; - - if( host.com_handlecolon && c == ':' ) - return true; - - return false; -} - /* ============== COM_IsWhiteSpace @@ -469,100 +444,6 @@ static int COM_IsWhiteSpace( char space ) return 0; } -/* -============== -COM_ParseFile - -text parser -============== -*/ -char *COM_ParseFile( char *data, char *token ) -{ - int c, len; - - if( !token ) - return NULL; - - len = 0; - token[0] = 0; - - if( !data ) - return NULL; -// skip whitespace -skipwhite: - while(( c = ((byte)*data)) <= ' ' ) - { - if( c == 0 ) - return NULL; // end of file; - data++; - } - - // skip // comments - if( c=='/' && data[1] == '/' ) - { - while( *data && *data != '\n' ) - data++; - goto skipwhite; - } - - // handle quoted strings specially - if( c == '\"' ) - { - data++; - while( 1 ) - { - c = (byte)*data; - - // unexpected line end - if( !c ) - { - token[len] = 0; - return data; - } - data++; - - if( c == '\\' && *data == '"' ) - { - token[len++] = (byte)*data++; - continue; - } - - if( c == '\"' ) - { - token[len] = 0; - return data; - } - token[len] = c; - len++; - } - } - - // parse single characters - if( COM_IsSingleChar( c )) - { - token[len] = c; - len++; - token[len] = 0; - return data + 1; - } - - // parse a regular word - do - { - token[len] = c; - data++; - len++; - c = ((byte)*data); - - if( COM_IsSingleChar( c )) - break; - } while( c > 32 ); - - token[len] = 0; - - return data; -} - /* ================ COM_ParseVector @@ -583,14 +464,14 @@ qboolean COM_ParseVector( char **pfile, float *v, size_t size ) if( size == 1 ) { - *pfile = COM_ParseFile( *pfile, token ); + *pfile = COM_ParseFile( *pfile, token, sizeof( token )); v[0] = Q_atof( token ); return true; } saved = *pfile; - if(( *pfile = COM_ParseFile( *pfile, token )) == NULL ) + if(( *pfile = COM_ParseFile( *pfile, token, sizeof( token ))) == NULL ) return false; if( token[0] == '(' ) @@ -599,13 +480,13 @@ qboolean COM_ParseVector( char **pfile, float *v, size_t size ) for( i = 0; i < size; i++ ) { - *pfile = COM_ParseFile( *pfile, token ); + *pfile = COM_ParseFile( *pfile, token, sizeof( token )); v[i] = Q_atof( token ); } if( !bracket ) return true; // done - if(( *pfile = COM_ParseFile( *pfile, token )) == NULL ) + if(( *pfile = COM_ParseFile( *pfile, token, sizeof( token ))) == NULL ) return false; if( token[0] == ')' ) @@ -613,21 +494,6 @@ qboolean COM_ParseVector( char **pfile, float *v, size_t size ) return false; } -/* -============= -COM_CheckString - -============= -*/ -#if 0 -int COM_CheckString( const char *string ) -{ - if( !string || !*string ) - return 0; - return 1; -} -#endif - /* ============= COM_FileSize @@ -1296,3 +1162,35 @@ only exists in PlayStation version void GAME_EXPORT pfnResetTutorMessageDecayData( void ) { } + +#if XASH_ENGINE_TESTS + +#include "tests.h" + +void Test_RunCommon( void ) +{ + char *file = (char *)"q asdf \"qwerty\" \"f \\\"f\" meowmeow\n// comment \"stuff ignored\"\nbark"; + int len; + char buf[5]; + + Msg( "Checking COM_ParseFile...\n" ); + + file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len ); + TASSERT( !Q_strcmp( buf, "q" ) && len == 1); + + file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len ); + TASSERT( !Q_strcmp( buf, "asdf" ) && len == 4); + + file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len ); + TASSERT( !Q_strcmp( buf, "qwer" ) && len == -1); + + file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len ); + TASSERT( !Q_strcmp( buf, "f \"f" ) && len == 4); + + file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len ); + TASSERT( !Q_strcmp( buf, "meow" ) && len == -1); + + file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len ); + TASSERT( !Q_strcmp( buf, "bark" ) && len == 4); +} +#endif diff --git a/engine/common/common.h b/engine/common/common.h index 7470877e..37ba3d54 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -422,8 +422,6 @@ typedef struct host_parm_s qboolean stuffcmds_pending; // should execute stuff commands qboolean allow_cheats; // this host will allow cheating qboolean con_showalways; // show console always (developer and dedicated) - qboolean com_handlecolon; // allow COM_ParseFile to handle colon as single char - qboolean com_ignorebracket; // allow COM_ParseFile to ignore () as single char qboolean change_game; // initialize when game is changed qboolean mouse_visible; // vgui override cursor control qboolean shutdown_issued; // engine is shutting down @@ -566,6 +564,7 @@ int FS_FileTime( const char *filename, qboolean gamedironly ); int FS_Print( file_t *file, const char *msg ); qboolean FS_Rename( const char *oldname, const char *newname ); int FS_FileExists( const char *filename, int gamedironly ); +int FS_SetCurrentDirectory( const char *path ); qboolean FS_SysFileExists( const char *path, qboolean casesensitive ); qboolean FS_FileCopy( file_t *pOutput, file_t *pInput, int fileSize ); qboolean FS_Delete( const char *path ); @@ -853,7 +852,6 @@ void CL_LegacyUpdateInfo( void ); void CL_CharEvent( int key ); qboolean CL_DisableVisibility( void ); int CL_PointContents( const vec3_t point ); -char *COM_ParseFile( char *data, char *token ); byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ); int CL_GetDemoComment( const char *demoname, char *comment ); void COM_AddAppDirectoryToSearchPath( const char *pszBaseDir, const char *appName ); diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index 55b9676d..c6b2cd3c 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -120,24 +120,24 @@ int Cmd_ListMaps( search_t *t, char *lastmapname, size_t len ) message[0] = 0; // remove 'error' pfile = ents; - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { if( !Q_strcmp( token, "{" )) continue; else if( !Q_strcmp( token, "}" )) break; else if( !Q_strcmp( token, "message" )) { // get the message contents - pfile = COM_ParseFile( pfile, message ); + pfile = COM_ParseFile( pfile, message, sizeof( message )); } else if( !Q_strcmp( token, "compiler" ) || !Q_strcmp( token, "_compiler" )) { // get the message contents - pfile = COM_ParseFile( pfile, compiler ); + pfile = COM_ParseFile( pfile, compiler, sizeof( compiler )); } else if( !Q_strcmp( token, "generator" ) || !Q_strcmp( token, "_generator" )) { // get the message contents - pfile = COM_ParseFile( pfile, generator ); + pfile = COM_ParseFile( pfile, generator, sizeof( generator )); } } Mem_Free( ents ); @@ -942,18 +942,18 @@ qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir ) Q_strncpy( message, "No Title", MAX_STRING ); pfile = ents; - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { if( token[0] == '}' && worldspawn ) worldspawn = false; else if( !Q_strcmp( token, "message" ) && worldspawn ) { // get the message contents - pfile = COM_ParseFile( pfile, message ); + pfile = COM_ParseFile( pfile, message, sizeof( message )); } else if( !Q_strcmp( token, "classname" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !Q_strcmp( token, GI->mp_entity ) || use_filter ) num_spawnpoints++; } diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index c0fe69cd..3b8ac690 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -463,6 +463,22 @@ static const char *FS_FixFileCase( const char *path ) return path; } +#if XASH_WIN32 +/* +==================== +FS_PathToWideChar + +Converts input UTF-8 string to wide char string. +==================== +*/ +const wchar_t *FS_PathToWideChar( const char *path ) +{ + static wchar_t pathBuffer[MAX_PATH]; + MultiByteToWideChar( CP_UTF8, 0, path, -1, pathBuffer, MAX_PATH ); + return pathBuffer; +} +#endif + /* ==================== FS_AddFileToPack @@ -1581,69 +1597,69 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool qboolean found_linux = false, found_osx = false; string token; - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { // different names in liblist/gameinfo if( !Q_stricmp( token, isGameInfo ? "title" : "game" )) { - pfile = COM_ParseFile( pfile, GameInfo->title ); + pfile = COM_ParseFile( pfile, GameInfo->title, sizeof( GameInfo->title )); } // valid for both else if( !Q_stricmp( token, "fallback_dir" )) { - pfile = COM_ParseFile( pfile, GameInfo->falldir ); + pfile = COM_ParseFile( pfile, GameInfo->falldir, sizeof( GameInfo->falldir )); } // valid for both else if( !Q_stricmp( token, "startmap" )) { - pfile = COM_ParseFile( pfile, GameInfo->startmap ); + pfile = COM_ParseFile( pfile, GameInfo->startmap, sizeof( GameInfo->startmap )); COM_StripExtension( GameInfo->startmap ); // HQ2:Amen has extension .bsp } // only trainmap is valid for gameinfo else if( !Q_stricmp( token, "trainmap" ) || (!isGameInfo && !Q_stricmp( token, "trainingmap" ))) { - pfile = COM_ParseFile( pfile, GameInfo->trainmap ); + pfile = COM_ParseFile( pfile, GameInfo->trainmap, sizeof( GameInfo->trainmap )); COM_StripExtension( GameInfo->trainmap ); // HQ2:Amen has extension .bsp } // valid for both else if( !Q_stricmp( token, "url_info" )) { - pfile = COM_ParseFile( pfile, GameInfo->game_url ); + pfile = COM_ParseFile( pfile, GameInfo->game_url, sizeof( GameInfo->game_url )); } // different names else if( !Q_stricmp( token, isGameInfo ? "url_update" : "url_dl" )) { - pfile = COM_ParseFile( pfile, GameInfo->update_url ); + pfile = COM_ParseFile( pfile, GameInfo->update_url, sizeof( GameInfo->update_url )); } // valid for both else if( !Q_stricmp( token, "gamedll" )) { - pfile = COM_ParseFile( pfile, GameInfo->game_dll ); + pfile = COM_ParseFile( pfile, GameInfo->game_dll, sizeof( GameInfo->game_dll )); COM_FixSlashes( GameInfo->game_dll ); } // valid for both else if( !Q_stricmp( token, "gamedll_linux" )) { - pfile = COM_ParseFile( pfile, GameInfo->game_dll_linux ); + pfile = COM_ParseFile( pfile, GameInfo->game_dll_linux, sizeof( GameInfo->game_dll_linux )); found_linux = true; } // valid for both else if( !Q_stricmp( token, "gamedll_osx" )) { - pfile = COM_ParseFile( pfile, GameInfo->game_dll_osx ); + pfile = COM_ParseFile( pfile, GameInfo->game_dll_osx, sizeof( GameInfo->game_dll_osx )); found_osx = true; } // valid for both else if( !Q_stricmp( token, "icon" )) { - pfile = COM_ParseFile( pfile, GameInfo->iconpath ); + pfile = COM_ParseFile( pfile, GameInfo->iconpath, sizeof( GameInfo->iconpath )); COM_FixSlashes( GameInfo->iconpath ); COM_DefaultExtension( GameInfo->iconpath, ".ico" ); } else if( !Q_stricmp( token, "type" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( !isGameInfo && !Q_stricmp( token, "singleplayer_only" )) { @@ -1673,43 +1689,43 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool // valid for both else if( !Q_stricmp( token, "version" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->version = Q_atof( token ); } // valid for both else if( !Q_stricmp( token, "size" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->size = Q_atoi( token ); } else if( !Q_stricmp( token, "edicts" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->max_edicts = Q_atoi( token ); } else if( !Q_stricmp( token, isGameInfo ? "mp_entity" : "mpentity" )) { - pfile = COM_ParseFile( pfile, GameInfo->mp_entity ); + pfile = COM_ParseFile( pfile, GameInfo->mp_entity, sizeof( GameInfo->mp_entity )); } else if( !Q_stricmp( token, isGameInfo ? "mp_filter" : "mpfilter" )) { - pfile = COM_ParseFile( pfile, GameInfo->mp_filter ); + pfile = COM_ParseFile( pfile, GameInfo->mp_filter, sizeof( GameInfo->mp_filter )); } // valid for both else if( !Q_stricmp( token, "secure" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->secure = Q_atoi( token ); } // valid for both else if( !Q_stricmp( token, "nomodels" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->nomodels = Q_atoi( token ); } else if( !Q_stricmp( token, isGameInfo ? "max_edicts" : "edicts" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->max_edicts = bound( MIN_EDICTS, Q_atoi( token ), MAX_EDICTS ); } // only for gameinfo @@ -1718,40 +1734,40 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool if( !Q_stricmp( token, "basedir" )) { string fs_path; - pfile = COM_ParseFile( pfile, fs_path ); + pfile = COM_ParseFile( pfile, fs_path, sizeof( fs_path )); if( Q_stricmp( fs_path, GameInfo->basedir ) || Q_stricmp( fs_path, GameInfo->gamefolder )) Q_strncpy( GameInfo->basedir, fs_path, sizeof( GameInfo->basedir )); } else if( !Q_stricmp( token, "sp_entity" )) { - pfile = COM_ParseFile( pfile, GameInfo->sp_entity ); + pfile = COM_ParseFile( pfile, GameInfo->sp_entity, sizeof( GameInfo->sp_entity )); } else if( isGameInfo && !Q_stricmp( token, "dllpath" )) { - pfile = COM_ParseFile( pfile, GameInfo->dll_path ); + pfile = COM_ParseFile( pfile, GameInfo->dll_path, sizeof( GameInfo->dll_path )); } else if( isGameInfo && !Q_stricmp( token, "date" )) { - pfile = COM_ParseFile( pfile, GameInfo->date ); + pfile = COM_ParseFile( pfile, GameInfo->date, sizeof( GameInfo->date )); } else if( !Q_stricmp( token, "max_tempents" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->max_tents = bound( 300, Q_atoi( token ), 2048 ); } else if( !Q_stricmp( token, "max_beams" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->max_beams = bound( 64, Q_atoi( token ), 512 ); } else if( !Q_stricmp( token, "max_particles" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->max_particles = bound( 4096, Q_atoi( token ), 32768 ); } else if( !Q_stricmp( token, "gamemode" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); // TODO: Remove this ugly hack too. // This was made because Half-Life has multiplayer, // but for some reason it's marked as singleplayer_only. @@ -1767,11 +1783,12 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool if( ambientNum < 0 || ambientNum > ( NUM_AMBIENTS - 1 )) ambientNum = 0; - pfile = COM_ParseFile( pfile, GameInfo->ambientsound[ambientNum] ); + pfile = COM_ParseFile( pfile, GameInfo->ambientsound[ambientNum], + sizeof( GameInfo->ambientsound[ambientNum] )); } else if( !Q_stricmp( token, "noskills" )) { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); GameInfo->noskills = Q_atoi( token ); } } @@ -2240,7 +2257,11 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode ) file->filetime = FS_SysFileTime( filepath ); file->ungetc = EOF; +#if XASH_WIN32 + file->handle = _wopen( FS_PathToWideChar(filepath), mod | opt, 0666 ); +#else file->handle = open( filepath, mod|opt, 0666 ); +#endif #if !XASH_WIN32 if( file->handle < 0 ) @@ -2394,6 +2415,24 @@ qboolean FS_SysFileExists( const char *path, qboolean caseinsensitive ) #endif } +/* +================== +FS_SetCurrentDirectory + +Sets current directory, path should be in UTF-8 encoding +================== +*/ +int FS_SetCurrentDirectory( const char *path ) +{ +#if XASH_WIN32 + return SetCurrentDirectoryW( FS_PathToWideChar(path) ); +#elif XASH_POSIX + return !chdir( path ); +#else +#error +#endif +} + /* ================== FS_SysFolderExists diff --git a/engine/common/host.c b/engine/common/host.c index d014c46e..b9f24904 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -783,6 +783,7 @@ static void Host_RunTests( int stage ) case 0: // early engine load memset( &tests_stats, 0, sizeof( tests_stats )); Test_RunLibCommon(); + Test_RunCommon(); break; case 1: // after FS load Test_RunImagelib(); @@ -980,7 +981,7 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha if( len && host.rodir[len - 1] == '/' ) host.rodir[len - 1] = 0; - if( !COM_CheckStringEmpty( host.rootdir ) || SetCurrentDirectory( host.rootdir ) != 0 ) + if( !COM_CheckStringEmpty( host.rootdir ) || FS_SetCurrentDirectory( host.rootdir ) != 0 ) Con_Reportf( "%s is working directory now\n", host.rootdir ); else Sys_Error( "Changing working directory to %s failed.\n", host.rootdir ); @@ -1131,10 +1132,9 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa if( Host_IsDedicated() && GameState->nextstate == STATE_RUNFRAME ) { - Con_Printf( "type 'map ' to run server... (TAB-autocomplete is working too)\n" ); - // execute server.cfg after commandline // so we have a chance to set servercfgfile + Con_Printf( "Type 'map ' to start game... (TAB-autocomplete is working too)\n" ); Cbuf_AddText( va( "exec %s\n", Cvar_VariableString( "servercfgfile" ))); Cbuf_Execute(); } diff --git a/engine/common/identification.c b/engine/common/identification.c index dc9857f3..872f38e1 100644 --- a/engine/common/identification.c +++ b/engine/common/identification.c @@ -445,8 +445,8 @@ int ID_ProcessWMIC( bloomfilter_t *value, const char *cmdline ) if( !ID_RunWMIC( buffer, cmdline ) ) return 0; - pbuf = COM_ParseFile( buffer, token ); // Header - while( pbuf = COM_ParseFile( pbuf, token ) ) + pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header + while( pbuf = COM_ParseFile( pbuf, token, sizeof( token ) ) ) { if( !ID_VerifyHEX( token ) ) continue; @@ -465,8 +465,8 @@ int ID_CheckWMIC( bloomfilter_t value, const char *cmdline ) if( !ID_RunWMIC( buffer, cmdline ) ) return 0; - pbuf = COM_ParseFile( buffer, token ); // Header - while( pbuf = COM_ParseFile( pbuf, token ) ) + pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header + while( pbuf = COM_ParseFile( pbuf, token, sizeof( token ) ) ) { bloomfilter_t filter; diff --git a/engine/common/imagelib/img_main.c b/engine/common/imagelib/img_main.c index 919143db..70e67ce1 100644 --- a/engine/common/imagelib/img_main.c +++ b/engine/common/imagelib/img_main.c @@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ +#include #include "imagelib.h" // global image variables diff --git a/engine/common/masterlist.c b/engine/common/masterlist.c index b3a1acd3..4dbd325b 100644 --- a/engine/common/masterlist.c +++ b/engine/common/masterlist.c @@ -189,11 +189,11 @@ static void NET_LoadMasters( void ) pfile = (char*)afile; // format: master \n - while( ( pfile = COM_ParseFile( pfile, token ) ) ) + while( ( pfile = COM_ParseFile( pfile, token, sizeof( token ) ) ) ) { if( !Q_strcmp( token, "master" ) ) // load addr { - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token ) ); NET_AddMaster( token, true ); } diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index da8443ad..eda98786 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -785,7 +785,7 @@ static void Mod_FindModelOrigin( const char *entities, const char *modelname, ve pfile = (char *)entities; - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { if( token[0] != '{' ) Host_Error( "Mod_FindModelOrigin: found %s when expecting {\n", token ); @@ -796,14 +796,14 @@ static void Mod_FindModelOrigin( const char *entities, const char *modelname, ve while( 1 ) { // parse key - if(( pfile = COM_ParseFile( pfile, token )) == NULL ) + if(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) == NULL ) Host_Error( "Mod_FindModelOrigin: EOF without closing brace\n" ); if( token[0] == '}' ) break; // end of desc Q_strncpy( keyname, token, sizeof( keyname )); // parse value - if(( pfile = COM_ParseFile( pfile, token )) == NULL ) + if(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) == NULL ) Host_Error( "Mod_FindModelOrigin: EOF without closing brace\n" ); if( token[0] == '}' ) @@ -1679,7 +1679,7 @@ static void Mod_LoadEntities( dbspmodel_t *bmod ) bmod->wadlist.count = 0; // parse all the wads for loading textures in right ordering - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { if( token[0] != '{' ) Host_Error( "Mod_LoadEntities: found %s when expecting {\n", token ); @@ -1687,14 +1687,14 @@ static void Mod_LoadEntities( dbspmodel_t *bmod ) while( 1 ) { // parse key - if(( pfile = COM_ParseFile( pfile, token )) == NULL ) + if(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) == NULL ) Host_Error( "Mod_LoadEntities: EOF without closing brace\n" ); if( token[0] == '}' ) break; // end of desc Q_strncpy( keyname, token, sizeof( keyname )); // parse value - if(( pfile = COM_ParseFile( pfile, token )) == NULL ) + if(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) == NULL ) Host_Error( "Mod_LoadEntities: EOF without closing brace\n" ); if( token[0] == '}' ) diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index ea4c6bad..3c4c8c37 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -561,7 +561,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt delta_field_t *pFieldInfo; char *oldpos; - *delta_script = COM_ParseFile( *delta_script, token ); + *delta_script = COM_ParseFile( *delta_script, token, sizeof( token )); if( Q_strcmp( token, "(" )) { Con_DPrintf( S_ERROR "Delta_ParseField: expected '(', found '%s' instead\n", token ); @@ -569,7 +569,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt } // read the variable name - if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) + if(( *delta_script = COM_ParseFile( *delta_script, token, sizeof( token ))) == NULL ) { Con_DPrintf( S_ERROR "Delta_ParseField: missing field name\n" ); return false; @@ -582,7 +582,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt return false; } - *delta_script = COM_ParseFile( *delta_script, token ); + *delta_script = COM_ParseFile( *delta_script, token, sizeof( token )); if( Q_strcmp( token, "," )) { Con_DPrintf( S_ERROR "Delta_ParseField: expected ',', found '%s' instead\n", token ); @@ -596,7 +596,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt pField->flags = 0; // read delta-flags - while(( *delta_script = COM_ParseFile( *delta_script, token )) != NULL ) + while(( *delta_script = COM_ParseFile( *delta_script, token, sizeof( token ))) != NULL ) { if( !Q_strcmp( token, "," )) break; // end of flags argument @@ -631,7 +631,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt } // read delta-bits - if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) + if(( *delta_script = COM_ParseFile( *delta_script, token, sizeof( token ))) == NULL ) { Con_DPrintf( S_ERROR "Delta_ReadField: %s field bits argument is missing\n", pField->name ); return false; @@ -639,7 +639,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt pField->bits = Q_atoi( token ); - *delta_script = COM_ParseFile( *delta_script, token ); + *delta_script = COM_ParseFile( *delta_script, token, sizeof( token )); if( Q_strcmp( token, "," )) { Con_DPrintf( S_ERROR "Delta_ReadField: expected ',', found '%s' instead\n", token ); @@ -647,7 +647,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt } // read delta-multiplier - if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) + if(( *delta_script = COM_ParseFile( *delta_script, token, sizeof( token ))) == NULL ) { Con_DPrintf( S_ERROR "Delta_ReadField: %s missing 'multiplier' argument\n", pField->name ); return false; @@ -657,7 +657,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt if( bPost ) { - *delta_script = COM_ParseFile( *delta_script, token ); + *delta_script = COM_ParseFile( *delta_script, token, sizeof( token )); if( Q_strcmp( token, "," )) { Con_DPrintf( S_ERROR "Delta_ReadField: expected ',', found '%s' instead\n", token ); @@ -665,7 +665,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt } // read delta-postmultiplier - if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) + if(( *delta_script = COM_ParseFile( *delta_script, token, sizeof( token ))) == NULL ) { Con_DPrintf( S_ERROR "Delta_ReadField: %s missing 'post_multiply' argument\n", pField->name ); return false; @@ -680,7 +680,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt } // closing brace... - *delta_script = COM_ParseFile( *delta_script, token ); + *delta_script = COM_ParseFile( *delta_script, token, sizeof( token )); if( Q_strcmp( token, ")" )) { Con_DPrintf( S_ERROR "Delta_ParseField: expected ')', found '%s' instead\n", token ); @@ -689,7 +689,7 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt // ... and trying to parse optional ',' post-symbol oldpos = *delta_script; - *delta_script = COM_ParseFile( *delta_script, token ); + *delta_script = COM_ParseFile( *delta_script, token, sizeof( token )); if( token[0] != ',' ) *delta_script = oldpos; // not a ',' return true; @@ -709,7 +709,7 @@ void Delta_ParseTable( char **delta_script, delta_info_t *dt, const char *encode dt->numFields = 0; // assume we have handled '{' - while(( *delta_script = COM_ParseFile( *delta_script, token )) != NULL ) + while(( *delta_script = COM_ParseFile( *delta_script, token, sizeof( token ))) != NULL ) { Assert( dt->numFields <= dt->maxFields ); @@ -761,7 +761,7 @@ void Delta_InitFields( void ) pfile = (char *)afile; - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { dt = Delta_FindStruct( token ); @@ -770,14 +770,14 @@ void Delta_InitFields( void ) Sys_Error( "%s: unknown struct %s\n", DELTA_PATH, token ); } - pfile = COM_ParseFile( pfile, encodeDll ); + pfile = COM_ParseFile( pfile, encodeDll, sizeof( encodeDll )); if( !Q_stricmp( encodeDll, "none" )) Q_strcpy( encodeFunc, "null" ); - else pfile = COM_ParseFile( pfile, encodeFunc ); + else pfile = COM_ParseFile( pfile, encodeFunc, sizeof( encodeFunc )); // jump to '{' - pfile = COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); if( token[0] != '{' ) { diff --git a/engine/common/net_encode.h b/engine/common/net_encode.h index a00c9131..85d533c9 100644 --- a/engine/common/net_encode.h +++ b/engine/common/net_encode.h @@ -28,8 +28,6 @@ GNU General Public License for more details. #define DT_STRING BIT( 7 ) // A null terminated string, sent as 8 byte chars #define DT_SIGNED BIT( 8 ) // sign modificator -#undef offsetof -#define offsetof( s, m ) (size_t)&(((s *)0)->m) #define NUM_FIELDS( x ) ((sizeof( x ) / sizeof( x[0] )) - 1) // helper macroses diff --git a/engine/common/net_ws.c b/engine/common/net_ws.c index edf0095a..896ff442 100644 --- a/engine/common/net_ws.c +++ b/engine/common/net_ws.c @@ -2559,7 +2559,7 @@ void HTTP_Init( void ) if( serverfile ) { - while( ( line = COM_ParseFile( line, token ) ) ) + while( ( line = COM_ParseFile( line, token, sizeof( token ) ) ) ) { httpserver_t *server = HTTP_ParseURL( token ); diff --git a/engine/common/tests.h b/engine/common/tests.h index 042baac9..fbe70cb0 100644 --- a/engine/common/tests.h +++ b/engine/common/tests.h @@ -17,12 +17,13 @@ extern struct tests_stats_s tests_stats; if(!( exp )) \ { \ tests_stats.failed++; \ - Msg( "assert failed at %s:%i\n", __FILE__, __LINE__ ); \ + Msg( S_ERROR "assert failed at %s:%i\n", __FILE__, __LINE__ ); \ } \ else tests_stats.passed++; void Test_RunImagelib( void ); void Test_RunLibCommon( void ); +void Test_RunCommon( void ); #endif diff --git a/engine/eiface.h b/engine/eiface.h index ddea7f96..87b21130 100644 --- a/engine/eiface.h +++ b/engine/eiface.h @@ -366,7 +366,11 @@ typedef enum _fieldtypes } FIELDTYPE; #ifndef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) +#ifdef __GNUC__ +#define offsetof(s,m) __builtin_offsetof(s,m) +#else +#define offsetof(s,m) (size_t)&(((s *)0)->m) +#endif #endif #define _FIELD(type,name,fieldtype,count,flags) { fieldtype, #name, offsetof(type, name), count, flags } diff --git a/engine/menu_int.h b/engine/menu_int.h index ccace287..85353c28 100644 --- a/engine/menu_int.h +++ b/engine/menu_int.h @@ -31,6 +31,10 @@ typedef int HIMAGE; // handle to a graphic #define PIC_KEEP_SOURCE (1<<1) // some images keep source #define PIC_NOFLIP_TGA (1<<2) // Steam background completely ignore tga attribute 0x20 +// flags for COM_ParseFileSafe +#define PFILE_IGNOREBRACKET (1<<0) +#define PFILE_HANDLECOLON (1<<1) + typedef struct ui_globalvars_s { float time; // unclamped host.realtime @@ -206,6 +210,8 @@ typedef struct ui_extendedfuncs_s { int (*pfnGetRenderers)( unsigned int num, char *shortName, size_t size1, char *readableName, size_t size2 ); double (*pfnDoubleTime)( void ); + + char *(*pfnParseFile)( char *data, char *buf, const int size, unsigned int flags, int *len ); } ui_extendedfuncs_t; // deprecated export from old engine diff --git a/engine/mobility_int.h b/engine/mobility_int.h index d8b6120a..c6471dff 100644 --- a/engine/mobility_int.h +++ b/engine/mobility_int.h @@ -36,6 +36,10 @@ extern "C" { #define TOUCH_FL_STROKE (1U << 8) #define TOUCH_FL_PRECISION (1U << 9) +// flags for COM_ParseFileSafe +#define PFILE_IGNOREBRACKET (1<<0) +#define PFILE_HANDLECOLON (1<<1) + typedef struct mobile_engfuncs_s { // indicates version of API. Should be equal to MOBILITY_API_VERSION @@ -77,6 +81,9 @@ typedef struct mobile_engfuncs_s void *(*pfnGetNativeObject)( const char *obj ); void (*pfnSetCustomClientID)( const char *id ); + + // COM_ParseFile but with buffer size limit, len reports written size or -1 on overflow + char* (*pfnParseFile)( char *data, char *buf, const int size, unsigned int flags, int *len ); // To be continued... } mobile_engfuncs_t; diff --git a/engine/physint.h b/engine/physint.h index e1e15c42..9c246023 100644 --- a/engine/physint.h +++ b/engine/physint.h @@ -16,9 +16,11 @@ GNU General Public License for more details. #ifndef PHYSINT_H #define PHYSINT_H +#include "eiface.h" // offsetof + #define SV_PHYSICS_INTERFACE_VERSION 6 -#define STRUCT_FROM_LINK( l, t, m ) ((t *)((byte *)l - (int)&(((t *)0)->m))) +#define STRUCT_FROM_LINK( l, t, m ) ((t *)((byte *)l - offsetof(t, m))) #define EDICT_FROM_AREA( l ) STRUCT_FROM_LINK( l, edict_t, area ) // values that can be returned with pfnServerState diff --git a/engine/ref_api.h b/engine/ref_api.h index dbcc6c96..2c62ffb8 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -371,7 +371,6 @@ typedef struct ref_api_s // filesystem byte* (*COM_LoadFile)( const char *path, fs_offset_t *pLength, qboolean gamedironly ); - char* (*COM_ParseFile)( char *data, char *token ); // use Mem_Free instead // void (*COM_FreeFile)( void *buffer ); int (*FS_FileExists)( const char *filename, int gamedironly ); diff --git a/engine/server/server.h b/engine/server/server.h index 4e35c77f..3f4fd518 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -352,6 +352,7 @@ typedef struct typedef struct { qboolean initialized; // sv_init has completed + qboolean game_library_loaded; // is game library loaded in SV_InitGame double timestart; // just for profiling int maxclients; // server max clients @@ -467,7 +468,6 @@ void SV_AddToMaster( netadr_t from, sizebuf_t *msg ); qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent ); void Host_SetServerState( int state ); qboolean SV_IsSimulating( void ); -qboolean SV_InitGame( void ); void SV_FreeClients( void ); void Master_Add( void ); void Master_Heartbeat( void ); @@ -476,6 +476,7 @@ void Master_Packet( void ); // // sv_init.c // +qboolean SV_InitGame( void ); void SV_ActivateServer( int runPhysics ); qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background ); model_t *SV_ModelHandle( int modelindex ); diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index ceedd785..494f1262 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -908,12 +908,12 @@ uint SV_MapIsValid( const char *filename, const char *spawn_entity, const char * pfile = ents; - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { if( !Q_strcmp( token, "classname" )) { // check classname for spawn entity - pfile = COM_ParseFile( pfile, check_name ); + pfile = COM_ParseFile( pfile, check_name, sizeof( check_name )); if( !Q_strcmp( spawn_entity, check_name )) { SetBits( flags, MAP_HAS_SPAWNPOINT ); @@ -926,7 +926,7 @@ uint SV_MapIsValid( const char *filename, const char *spawn_entity, const char * else if( need_landmark && !Q_strcmp( token, "targetname" )) { // check targetname for landmark entity - pfile = COM_ParseFile( pfile, check_name ); + pfile = COM_ParseFile( pfile, check_name, sizeof( check_name )); if( !Q_strcmp( landmark_name, check_name )) { @@ -4747,14 +4747,14 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent ) string keyname; // parse key - if(( *pfile = COM_ParseFile( *pfile, token )) == NULL ) + if(( *pfile = COM_ParseFile( *pfile, token, sizeof( token ))) == NULL ) Host_Error( "ED_ParseEdict: EOF without closing brace\n" ); if( token[0] == '}' ) break; // end of desc Q_strncpy( keyname, token, sizeof( keyname )); // parse value - if(( *pfile = COM_ParseFile( *pfile, token )) == NULL ) + if(( *pfile = COM_ParseFile( *pfile, token, sizeof( token ))) == NULL ) Host_Error( "ED_ParseEdict: EOF without closing brace\n" ); if( token[0] == '}' ) @@ -4916,7 +4916,7 @@ void SV_LoadFromFile( const char *mapname, char *entities ) inhibited = 0; // parse ents - while(( entities = COM_ParseFile( entities, token )) != NULL ) + while(( entities = COM_ParseFile( entities, token, sizeof( token ))) != NULL ) { if( token[0] != '{' ) Host_Error( "ED_LoadFromFile: found %s when expecting {\n", token ); @@ -5028,6 +5028,7 @@ void SV_UnloadProgs( void ) Mod_ResetStudioAPI (); + svs.game_library_loaded = false; COM_FreeLibrary( svgame.hInstance ); Mem_FreePool( &svgame.mempool ); memset( &svgame, 0, sizeof( svgame )); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 4d691074..b045fdfd 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -287,7 +287,7 @@ void SV_ReadResourceList( const char *filename ) Con_DPrintf( "Precaching from %s\n", filename ); Con_DPrintf( "----------------------------------\n" ); - while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { if( !COM_IsSafeFileToDownload( token )) continue; @@ -668,8 +668,8 @@ qboolean SV_InitGame( void ) { string dllpath; - if( svs.initialized ) - return true; // already initialized ? + if( svs.game_library_loaded ) + return true; // first initialize? COM_ResetLibraryError(); @@ -683,8 +683,7 @@ qboolean SV_InitGame( void ) } // client frames will be allocated in SV_ClientConnect - svs.initialized = true; - + svs.game_library_loaded = true; return true; } @@ -862,6 +861,7 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba if( !SV_InitGame( )) return false; + svs.initialized = true; Log_Open(); Log_Printf( "Loading map \"%s\"\n", mapname ); Log_PrintServerVars(); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index a748a0fc..bcc433bf 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -959,6 +959,7 @@ void SV_Init( void ) SV_InitFilter(); SV_ClearGameState (); // delete all temporary *.hl files + SV_InitGame(); } /* diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 0052ba73..2e754ce1 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -2115,6 +2115,7 @@ qboolean SV_LoadGame( const char *pPath ) if( !SV_InitGame( )) return false; + svs.initialized = true; pFile = FS_Open( pPath, "rb", true ); if( pFile ) diff --git a/mainui b/mainui index d8e2adbc..fc786630 160000 --- a/mainui +++ b/mainui @@ -1 +1 @@ -Subproject commit d8e2adbc5b6a30a5c676e2b450ca9e1f93f44104 +Subproject commit fc7866300794c14ec4577478ed8a96de99815c7f diff --git a/public/crtlib.c b/public/crtlib.c index 7aa6646f..e9321f9a 100644 --- a/public/crtlib.c +++ b/public/crtlib.c @@ -967,6 +967,159 @@ void COM_Hex2String( uint8_t hex, char *str ) *str = '\0'; } +/* +============== +COM_IsSingleChar + +interpert this character as single +============== +*/ +static int COM_IsSingleChar( unsigned int flags, char c ) +{ + if( c == '{' || c == '}' || c == '\'' || c == ',' ) + return true; + + if( !FBitSet( flags, PFILE_IGNOREBRACKET ) && ( c == ')' || c == '(' )) + return true; + + if( FBitSet( flags, PFILE_HANDLECOLON ) && c == ':' ) + return true; + + return false; +} + +/* +============== +COM_ParseFile + +text parser +============== +*/ +char *_COM_ParseFileSafe( char *data, char *token, const int size, unsigned int flags, int *plen ) +{ + int c, len = 0; + qboolean overflow = false; + + if( !token || !size ) + { + if( plen ) *plen = 0; + return NULL; + } + + token[0] = 0; + + if( !data ) + return NULL; +// skip whitespace +skipwhite: + while(( c = ((byte)*data)) <= ' ' ) + { + if( c == 0 ) + { + if( plen ) *plen = overflow ? -1 : len; + return NULL; // end of file; + } + data++; + } + + // skip // comments + if( c == '/' && data[1] == '/' ) + { + while( *data && *data != '\n' ) + data++; + goto skipwhite; + } + + // handle quoted strings specially + if( c == '\"' ) + { + data++; + while( 1 ) + { + c = (byte)*data; + + // unexpected line end + if( !c ) + { + token[len] = 0; + if( plen ) *plen = overflow ? -1 : len; + return data; + } + data++; + + if( c == '\\' && *data == '"' ) + { + if( len + 1 < size ) + { + token[len] = (byte)*data; + len++; + } + else overflow = true; + + data++; + continue; + } + + if( c == '\"' ) + { + token[len] = 0; + if( plen ) *plen = overflow ? -1 : len; + return data; + } + + if( len + 1 < size ) + { + token[len] = c; + len++; + } + else overflow = true; + } + } + + // parse single characters + if( COM_IsSingleChar( flags, c )) + { + if( size >= 2 ) // char and \0 + { + token[len] = c; + len++; + token[len] = 0; + if( plen ) *plen = overflow ? -1 : len; + return data + 1; + } + else + { + // couldn't pass anything + token[0] = 0; + if( plen ) *plen = overflow ? -1 : len; + return data; + } + } + + // parse a regular word + do + { + if( len + 1 < size ) + { + token[len] = c; + len++; + } + else overflow = true; + + data++; + c = ((byte)*data); + + if( COM_IsSingleChar( flags, c )) + break; + } while( c > 32 ); + + token[len] = 0; + + if( plen ) *plen = overflow ? -1 : len; + + return data; +} + int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive ) { return matchpattern_with_separator( in, pattern, caseinsensitive, "/\\:", false ); diff --git a/public/crtlib.h b/public/crtlib.h index 2dd7ad29..8848226a 100644 --- a/public/crtlib.h +++ b/public/crtlib.h @@ -38,6 +38,11 @@ enum TIME_FILENAME, }; +// a1ba: not using BIT macro, so flags can be copypasted into +// exported APIs headers and will get nice warning in case of changing values +#define PFILE_IGNOREBRACKET (1<<0) +#define PFILE_HANDLECOLON (1<<1) + // // crtlib.c // @@ -89,6 +94,9 @@ char COM_Hex2Char( uint8_t hex ); void COM_Hex2String( uint8_t hex, char *str ); #define COM_CheckString( string ) ( ( !string || !*string ) ? 0 : 1 ) #define COM_CheckStringEmpty( string ) ( ( !*string ) ? 0 : 1 ) +char *_COM_ParseFileSafe( char *data, char *token, const int size, unsigned int flags, int *len ); +#define COM_ParseFile( data, token, size ) _COM_ParseFileSafe( data, token, size, 0, NULL ) +#define COM_ParseFileLegacy( data, token ) COM_ParseFileSafe( data, token, INT_MAX ) int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive ); int matchpattern_with_separator( const char *in, const char *pattern, qboolean caseinsensitive, const char *separators, qboolean wildcard_least_one ); diff --git a/ref_gl/gl_local.h b/ref_gl/gl_local.h index d3f49836..a50f7f0c 100644 --- a/ref_gl/gl_local.h +++ b/ref_gl/gl_local.h @@ -36,8 +36,12 @@ GNU General Public License for more details. #include "wadfile.h" #ifndef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif // offsetof +#ifdef __GNUC__ +#define offsetof(s,m) __builtin_offsetof(s,m) +#else +#define offsetof(s,m) (size_t)&(((s *)0)->m) +#endif +#endif #define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) #define Assert(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) diff --git a/ref_gl/gl_rmisc.c b/ref_gl/gl_rmisc.c index f687d15e..c402e337 100644 --- a/ref_gl/gl_rmisc.c +++ b/ref_gl/gl_rmisc.c @@ -35,7 +35,7 @@ static void R_ParseDetailTextures( const char *filename ) pfile = (char *)afile; // format: 'texturename' 'detailtexture' 'xScale' 'yScale' - while(( pfile = gEngfuncs.COM_ParseFile( pfile, token )) != NULL ) + while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL ) { texname[0] = '\0'; detail_texname[0] = '\0'; @@ -45,26 +45,26 @@ static void R_ParseDetailTextures( const char *filename ) { // NOTE: COM_ParseFile handled some symbols seperately // this code will be fix it - pfile = gEngfuncs.COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); Q_strncat( texname, "{", sizeof( texname )); Q_strncat( texname, token, sizeof( texname )); } else Q_strncpy( texname, token, sizeof( texname )); // read detailtexture name - pfile = gEngfuncs.COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); Q_strncat( detail_texname, token, sizeof( detail_texname )); // trying the scales or '{' - pfile = gEngfuncs.COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); // read second part of detailtexture name if( token[0] == '{' ) { Q_strncat( detail_texname, token, sizeof( detail_texname )); - pfile = gEngfuncs.COM_ParseFile( pfile, token ); // read scales + pfile = COM_ParseFile( pfile, token, sizeof( token )); // read scales Q_strncat( detail_texname, token, sizeof( detail_texname )); - pfile = gEngfuncs.COM_ParseFile( pfile, token ); // parse scales + pfile = COM_ParseFile( pfile, token, sizeof( token )); // parse scales } Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname ); @@ -72,7 +72,7 @@ static void R_ParseDetailTextures( const char *filename ) // read scales xScale = Q_atof( token ); - pfile = gEngfuncs.COM_ParseFile( pfile, token ); + pfile = COM_ParseFile( pfile, token, sizeof( token )); yScale = Q_atof( token ); if( xScale <= 0.0f || yScale <= 0.0f ) diff --git a/ref_soft/r_local.h b/ref_soft/r_local.h index b75b072a..8a893bbb 100644 --- a/ref_soft/r_local.h +++ b/ref_soft/r_local.h @@ -36,10 +36,6 @@ typedef struct mip_s mip_t; typedef int fixed8_t; typedef int fixed16_t; -#ifndef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif // offsetof - #define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) #define Assert(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) diff --git a/scripts/continious_upload.sh b/scripts/continious_upload.sh index c51c16af..de3cefd0 100755 --- a/scripts/continious_upload.sh +++ b/scripts/continious_upload.sh @@ -1,13 +1,329 @@ -################################## +#!/bin/bash + +# MIT License # -# GitHub Releases +# Copyright (c) 2016 Simon Peter # -################################## +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. -set +x +set +x # Do not leak information -curl "https://raw.githubusercontent.com/FWGS/uploadtool/gha-fixes/upload.sh" -o upload.sh -chmod +x upload.sh +# Exit immediately if one of the files given as arguments is not there +# because we don't want to delete the existing release if we don't have +# the new files that should be uploaded +for file in "$@" +do + if [ ! -e "$file" ] + then echo "$file is missing, giving up." >&2; exit 1 + fi +done -bash ./upload.sh $* +if [ $# -eq 0 ]; then + echo "No artifacts to use for release, giving up." + exit 0 +fi +if command -v sha256sum >/dev/null 2>&1 ; then + shatool="sha256sum" +elif command -v shasum >/dev/null 2>&1 ; then + shatool="shasum -a 256" # macOS fallback +else + echo "Neither sha256sum nor shasum is available, cannot check hashes" +fi + +RELEASE_BODY="" +GIT_REPO_SLUG="$REPO_SLUG" + +GIT_COMMIT="$TRAVIS_COMMIT" +GIT_TAG="$TRAVIS_TAG" + +if [ ! -z "$TRAVIS_REPO_SLUG" ] ; then + GIT_REPO_SLUG="$TRAVIS_REPO_SLUG" + RELEASE_BODY="Travis CI build log: ${TRAVIS_BUILD_WEB_URL}" +elif [ ! -z "$GITHUB_ACTIONS" ] ; then + GIT_COMMIT="$GITHUB_SHA" + GIT_REPO_SLUG="$GITHUB_REPOSITORY" + if [[ "$GITHUB_REF" == "refs/tags/"* ]] ; then + GIT_TAG="${GITHUB_REF#refs/tags/}" + fi + RELEASE_BODY="GitHub Actions build log: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" +fi + +if [ ! -z "$UPLOADTOOL_BODY" ] ; then + RELEASE_BODY="$UPLOADTOOL_BODY" +fi + +# The calling script (usually .travis.yml) can set a suffix to be used for +# the tag and release name. This way it is possible to have a release for +# the output of the CI/CD pipeline (marked as 'continuous') and also test +# builds for other branches. +# If this build was triggered by a tag, call the result a Release +if [ ! -z "$UPLOADTOOL_SUFFIX" ] ; then + if [ "$UPLOADTOOL_SUFFIX" = "$GIT_TAG" ] ; then + RELEASE_NAME="$GIT_TAG" + RELEASE_TITLE="Release build ($GIT_TAG)" + is_prerelease="false" + else + RELEASE_NAME="continuous-$UPLOADTOOL_SUFFIX" + RELEASE_TITLE="Continuous build ($UPLOADTOOL_SUFFIX)" + if [ -z "$UPLOADTOOL_ISPRERELEASE" ] ; then + is_prerelease="false" + else + is_prerelease="true" + fi + + fi +else + # ,, is a bash-ism to convert variable to lower case + case $(tr '[:upper:]' '[:lower:]' <<< "$GIT_TAG") in + "") + # Do not use "latest" as it is reserved by GitHub + RELEASE_NAME="continuous" + RELEASE_TITLE="Continuous build" + if [ -z "$UPLOADTOOL_ISPRERELEASE" ] ; then + is_prerelease="false" + else + is_prerelease="true" + fi + ;; + *-alpha*|*-beta*|*-rc*) + RELEASE_NAME="$GIT_TAG" + RELEASE_TITLE="Pre-release build ($GIT_TAG)" + is_prerelease="true" + ;; + *) + RELEASE_NAME="$GIT_TAG" + RELEASE_TITLE="Release build ($GIT_TAG)" + is_prerelease="false" + ;; + esac +fi + +if [ "$ARTIFACTORY_BASE_URL" != "" ]; then + echo "ARTIFACTORY_BASE_URL set, trying to upload to artifactory" + + if [ "$ARTIFACTORY_API_KEY" == "" ]; then + echo "Please set ARTIFACTORY_API_KEY" + exit 1 + fi + + files="$@" + + # artifactory doesn't support any kind of "artifact description", so we're uploading a text file containing the + # relevant details along with the other artifacts + tempdir=$(mktemp -d) + info_file="$tempdir"/build-info.txt + echo "Travis CI build log: ${TRAVIS_BUILD_WEB_URL}" > "$info_file" + files+=("$info_file") + + set +x + + for file in ${files[@]}; do + url="${ARTIFACTORY_BASE_URL}/travis-${TRAVIS_BUILD_NUMBER}/"$(basename "$file") + md5sum=$(md5sum "$file" | cut -d' ' -f1) + sha1sum=$(sha1sum "$file" | cut -d' ' -f1) + sha256sum=$(sha256sum "$file" | cut -d' ' -f1) + echo "Uploading $file to $url" + hashsums=(-H "X-Checksum-Md5:$md5sum") + hashsums+=(-H "X-Checksum-Sha1:$sha1sum") + hashsums+=(-H "X-Checksum-Sha256:$sha256sum") + if ! curl -H 'X-JFrog-Art-Api:'"$ARTIFACTORY_API_KEY" "${hashsums[@]}" -T "$file" "$url"; then + echo "Failed to upload file, exiting" + rm -r "$tempdir" + exit 1 + fi + echo + echo "MD5 checksum: $md5sum" + echo "SHA1 checksum: $sha1sum" + echo "SHA256 checksum: $sha256sum" + done + rm -r "$tempdir" +fi + +# Do not upload non-master branch builds +# if [ "$GIT_TAG" != "$TRAVIS_BRANCH" ] && [ "$TRAVIS_BRANCH" != "master" ]; then export TRAVIS_EVENT_TYPE=pull_request; fi +if [ "$TRAVIS_EVENT_TYPE" == "pull_request" ] || [ "$GITHUB_EVENT_NAME" == "pull_request" ] ; then + echo "Release uploading disabled for pull requests" + if [ "$ARTIFACTORY_BASE_URL" != "" ]; then + echo "Releases have already been uploaded to Artifactory, exiting" + exit 0 + else + echo "Release uploading disabled for pull requests, uploading to transfersh.com instead" + rm -f ./uploaded-to + for FILE in "$@" ; do + BASENAME="$(basename "${FILE}")" + curl --upload-file $FILE "https://transfersh.com/$BASENAME" > ./one-upload + echo "$(cat ./one-upload)" # this way we get a newline + echo -n "$(cat ./one-upload)\\n" >> ./uploaded-to # this way we get a \n but no newline + done + fi +# review_url="https://api.github.com/repos/${GIT_REPO_SLUG}/pulls/${TRAVIS_PULL_REQUEST}/reviews" +# if [ -z $UPLOADTOOL_PR_BODY ] ; then +# body="Travis CI has created build artifacts for this PR here:" +# else +# body="$UPLOADTOOL_PR_BODY" +# fi +# body="$body\n$(cat ./uploaded-to)\nThe link(s) will expire 14 days from now." +# review_comment=$(curl -X POST \ +# --header "Authorization: token ${GITHUB_TOKEN}" \ +# --data '{"commit_id": "'"$GIT_COMMIT"'","body": "'"$body"'","event": "COMMENT"}' \ +# $review_url) +# if echo $review_comment | grep -q "Bad credentials" 2>/dev/null ; then +# echo '"Bad credentials" response for --data {"commit_id": "'"$GIT_COMMIT"'","body": "'"$body"'","event": "COMMENT"}' +# fi + $shatool "$@" + exit 0 +fi + +if [ ! -z "$TRAVIS_REPO_SLUG" ] ; then + echo "Running on Travis CI" + echo "TRAVIS_COMMIT: $TRAVIS_COMMIT" + if [ -z "$GITHUB_TOKEN" ] ; then + echo "\$GITHUB_TOKEN missing, please set it in the Travis CI settings of this project" + echo "You can get one from https://github.com/settings/tokens" + exit 1 + fi +elif [ ! -z "$GITHUB_ACTIONS" ] ; then + echo "Running on GitHub Actions" + if [ -z "$GITHUB_TOKEN" ] ; then + echo "\$GITHUB_TOKEN missing, please add the following to your run action:" + echo "env:" + echo " GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}" + exit 1 + fi +else + echo "Not running on known CI" + if [ -z "$GIT_REPO_SLUG" ] ; then + read -r -p "Repo Slug (GitHub and Travis CI username/reponame): " GIT_REPO_SLUG + fi + if [ -z "$GITHUB_TOKEN" ] ; then + read -r -s -p "Token (https://github.com/settings/tokens): " GITHUB_TOKEN + fi +fi + +tag_url="https://api.github.com/repos/$GIT_REPO_SLUG/git/refs/tags/$RELEASE_NAME" +tag_infos=$(curl -XGET --header "Authorization: token ${GITHUB_TOKEN}" "${tag_url}") +echo "tag_infos: $tag_infos" +tag_sha=$(echo "$tag_infos" | grep '"sha":' | head -n 1 | cut -d '"' -f 4 | cut -d '{' -f 1) +echo "tag_sha: $tag_sha" + +release_url="https://api.github.com/repos/$GIT_REPO_SLUG/releases/tags/$RELEASE_NAME" +echo "Getting the release ID..." +echo "release_url: $release_url" +release_infos=$(curl -XGET --header "Authorization: token ${GITHUB_TOKEN}" "${release_url}") +echo "release_infos: $release_infos" +release_id=$(echo "$release_infos" | grep "\"id\":" | head -n 1 | tr -s " " | cut -f 3 -d" " | cut -f 1 -d ",") +echo "release ID: $release_id" +upload_url=$(echo "$release_infos" | grep '"upload_url":' | head -n 1 | cut -d '"' -f 4 | cut -d '{' -f 1) +echo "upload_url: $upload_url" +release_url=$(echo "$release_infos" | grep '"url":' | head -n 1 | cut -d '"' -f 4 | cut -d '{' -f 1) +echo "release_url: $release_url" +target_commit_sha=$(echo "$release_infos" | grep '"target_commitish":' | head -n 1 | cut -d '"' -f 4 | cut -d '{' -f 1) +echo "target_commit_sha: $target_commit_sha" + +if [ "$GIT_COMMIT" != "$target_commit_sha" ] ; then + + echo "GIT_COMMIT != target_commit_sha, hence deleting $RELEASE_NAME..." + + if [ ! -z "$release_id" ]; then + delete_url="https://api.github.com/repos/$GIT_REPO_SLUG/releases/$release_id" + echo "Delete the release..." + echo "delete_url: $delete_url" + curl -XDELETE \ + --header "Authorization: token ${GITHUB_TOKEN}" \ + "${delete_url}" + fi + + # echo "Checking if release with the same name is still there..." + # echo "release_url: $release_url" + # curl -XGET --header "Authorization: token ${GITHUB_TOKEN}" \ + # "$release_url" + + if [ "$RELEASE_NAME" == "continuous" ] ; then + # if this is a continuous build tag, then delete the old tag + # in preparation for the new release + echo "Delete the tag..." + delete_url="https://api.github.com/repos/$GIT_REPO_SLUG/git/refs/tags/$RELEASE_NAME" + echo "delete_url: $delete_url" + curl -XDELETE \ + --header "Authorization: token ${GITHUB_TOKEN}" \ + "${delete_url}" + fi + + echo "Create release..." + + release_infos=$(curl -H "Authorization: token ${GITHUB_TOKEN}" \ + --data '{"tag_name": "'"$RELEASE_NAME"'","target_commitish": "'"$GIT_COMMIT"'","name": "'"$RELEASE_TITLE"'","body": "'"$RELEASE_BODY"'","draft": false,"prerelease": '$is_prerelease'}' "https://api.github.com/repos/$GIT_REPO_SLUG/releases") + + echo "$release_infos" + + unset upload_url + upload_url=$(echo "$release_infos" | grep '"upload_url":' | head -n 1 | cut -d '"' -f 4 | cut -d '{' -f 1) + echo "upload_url: $upload_url" + + unset release_url + release_url=$(echo "$release_infos" | grep '"url":' | head -n 1 | cut -d '"' -f 4 | cut -d '{' -f 1) + echo "release_url: $release_url" + +fi # if [ "$GIT_COMMIT" != "$tag_sha" ] + +if [ -z "$release_url" ] ; then + echo "Cannot figure out the release URL for $RELEASE_NAME" + exit 1 +fi + +echo "Upload binaries to the release..." + +# Need to URL encode the basename, so we have this function to do so +urlencode() { + # urlencode + old_lc_collate=$LC_COLLATE + LC_COLLATE=C + local length="${#1}" + for (( i = 0; i < length; i++ )); do + local c="${1:$i:1}" + case $c in + [a-zA-Z0-9.~_-]) printf '%s' "$c" ;; + *) printf '%%%02X' "'$c" ;; + esac + done + LC_COLLATE=$old_lc_collate +} + +for FILE in "$@" ; do + FULLNAME="${FILE}" + BASENAME="$(basename "${FILE}")" + curl -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github.manifold-preview" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@$FULLNAME" \ + "$upload_url?name=$(urlencode "$BASENAME")" + echo "" +done + +$shatool "$@" + +if [ "$GIT_COMMIT" != "$tag_sha" ] ; then + echo "Publish the release..." + + release_infos=$(curl -H "Authorization: token ${GITHUB_TOKEN}" \ + --data '{"draft": false}' "$release_url") + + echo "$release_infos" +fi # if [ "$GIT_COMMIT" != "$tag_sha" ] diff --git a/scripts/gha/build_win32.sh b/scripts/gha/build_win32.sh index 0b36b187..7143d7a5 100755 --- a/scripts/gha/build_win32.sh +++ b/scripts/gha/build_win32.sh @@ -28,13 +28,3 @@ else fi 7z a -t7z $BUILDDIR/xash3d-fwgs-win32-$ARCH.7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on *.dll *.exe *.pdb - -echo "Generating VC2008 project" -rm -rf vc2008/ -mkdir vc2008/ -./waf.bat msdev -cp *.sln vc2008/ -find . -name "*.vcproj" -exec cp --parents \{\} vc2008/ \; -rm -rf vc2008/vc2008 # HACKHACK - -7z a -t7z $BUILDDIR/xash3d-fwgs-vc2008-sln-$ARCH.7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on -r vc2008 diff --git a/scripts/waifulib/compiler_optimizations.py b/scripts/waifulib/compiler_optimizations.py index 5c911eed..a832c7ae 100644 --- a/scripts/waifulib/compiler_optimizations.py +++ b/scripts/waifulib/compiler_optimizations.py @@ -39,8 +39,8 @@ LINKFLAGS = { 'owcc': ['-Wl,option stack=512k'] }, 'sanitize': { - 'clang': ['-fsanitize=undefined', '-fsanitize=address'], - 'gcc': ['-fsanitize=undefined', '-fsanitize=address'], + 'clang': ['-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'gcc': ['-fsanitize=undefined', '-fsanitize=address', '-pthread'], }, 'debug': { 'msvc': ['/INCREMENTAL', '/SAFESEH:NO'] @@ -82,8 +82,8 @@ CFLAGS = { }, 'sanitize': { 'msvc': ['/Od', '/RTC1', '/Zi'], - 'gcc': ['-Og', '-fsanitize=undefined', '-fsanitize=address'], - 'clang': ['-O0', '-fsanitize=undefined', '-fsanitize=address'], + 'gcc': ['-Og', '-fsanitize=undefined', '-fsanitize=address', '-pthread'], + 'clang': ['-O0', '-fsanitize=undefined', '-fsanitize=address', '-pthread'], 'default': ['-O0'] }, 'nooptimize': {