diff --git a/.gitignore b/.gitignore index 981dff0b..a6cdeac6 100644 --- a/.gitignore +++ b/.gitignore @@ -328,9 +328,13 @@ __pycache__ *.sln *.vcxproj -# vim/coc/clangd -.cache +# vim/cscope/coc/clangd compile_commands.json cscope.out - core + +# Visual Studio Code +.vscode/* +*.code-workspace +.history/* +.cache/* diff --git a/.travis.yml b/.travis.yml index 50b9a99c..b070a7f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ jobs: script: - sh scripts/build_${TRAVIS_OS_NAME}_engine.sh after_script: - - sh scripts/continious_upload.sh xash3d-vc.7z xash3d-vc2008-sln.7z + - sh scripts/continious_upload.sh xash3d-win32-vc.7z xash3d-vc2008-sln.7z - # ... name: "Build for Linux i686" cache: ccache @@ -210,4 +210,4 @@ jobs: os: linux cache: false script: - - sh scripts/travis-deploy.sh xash3d-fwgs-i686.AppImage xash3d-fwgs-x86_64.AppImage xash3d-vc.7z xash3d-vc2008-sln.7z xashdroid.apk xashdroid-64-test.apk xashds-linux-i686 xashds-linux-x86_64 xash3d-magx.7z + - sh scripts/travis-deploy.sh xash3d-fwgs-i686.AppImage xash3d-fwgs-x86_64.AppImage xash3d-win32-vc.7z xash3d-vc2008-sln.7z xashdroid.apk xashdroid-64-test.apk xashds-linux-i686 xashds-linux-x86_64 xash3d-magx.7z diff --git a/Documentation/opensource-mods.md b/Documentation/opensource-mods.md index 71e36d20..4f282836 100644 --- a/Documentation/opensource-mods.md +++ b/Documentation/opensource-mods.md @@ -1,8 +1,11 @@ Source code of this mods is available for modders and porters in public access. # Original Work +## Absolute Zero +Official gitlab repository - https://gitlab.com/Cobalt-57/half-life-absolute-zero/ + ## Adrenaline Gamer -Oficial github repository by Martin \"Bullet\" Webrant - https://github.com/martinwebrant/agmod +Official github repository by Martin \"Bullet\" Webrant - https://github.com/martinwebrant/agmod ## Arrangement Mirrored on github - https://github.com/JoelTroch/am_src_30jan2011 @@ -14,10 +17,10 @@ Mirrored on github - https://github.com/JoelTroch/am_src_rebirth Mirrored on github - https://github.com/nekonomicon/BattleGrounds ## Bubblemod -Download page on oficial site - http://www.bubblemod.org/dl_default.php +Download page on official site - http://www.bubblemod.org/dl_default.php ## Chicken Fortress -Oficial github repository - https://github.com/CKFDevPowered/CKF3Alpha +Official github repository - https://github.com/CKFDevPowered/CKF3Alpha ## Cold Ice Version 1.9 is available on ModDB - https://www.moddb.com/mods/cold-ice/downloads/cold-ice-sdk @@ -28,59 +31,83 @@ Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Ct ## Deathmatch Classic Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/dmc +## ESHQ +Official github repository - https://github.com/adslbarxatov/xash3d-for-ESHQ + +## Flat-Life +Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/Half-Life_2D_(Flat-Life) + ## Gang Wars Mirrored on github - https://github.com/hammermaps/gw1.45src ## Go-mod -Available in mod archives on ModDB - https://www.moddb.com/mods/go-mod/downloads +Versions 2.0 and 3.0, available in mod archives on ModDB - https://www.moddb.com/mods/go-mod/downloads + +## GT mod +Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/GT_mod_(Polnie_ishodniki) ## Half-Life: Echoes Download link on dropbox - https://www.dropbox.com/s/s6j8gtegn10wgvj/dlls.zip?dl=1 +## Half-Life: Expanded Arsenal +Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal + ## Half-Life: Gravgun mod Branch **gravgun** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/gravgun ## Half-Life: Invasion -oficial github repository - https://github.com/jlecorre/hlinvasion +official github repository - https://github.com/jlecorre/hlinvasion ## Half-Life: Quest Mode Available on cs-mapping.com.ua - https://old.cs-mapping.com.ua/forum/showthread.php?t=38030 ## Half-Life: Top-Down -Oficial gitlab repository - https://gitlab.com/Sockman/hltopdown +Official gitlab repository - https://gitlab.com/Sockman/hltopdown ## Half-Life: Update -Oficial github repository - https://github.com/Fograin/hl-subsmod-ex +Official github repository - https://github.com/Fograin/hl-subsmod-ex ## Half-Life: Weapon Edition Available on ModDB - https://www.moddb.com/mods/half-life-weapon-edition/downloads/half-life-weapon-edition-1508-alpha-open-src +## Half-Life: Year of the Dragon +Available on ModDB - https://www.moddb.com/mods/year-of-the-dragon + ## Half-Nuked Available on ModDB - https://www.moddb.com/mods/half-nuked/downloads/half-nuked-src ## Half-Payne -Oficial github repository - https://github.com/suXinjke/HalfPayne +Official github repository - https://github.com/suXinjke/HalfPayne ## Half-Quake -Oficial github repository - https://github.com/muddasheep/hqtrilogy +Official github repository - https://github.com/muddasheep/hqtrilogy ## Half-Rats: Parasomnia -Oficial github repository - https://github.com/HeathGames/half_rats_parasomnia_src +Official github repository - https://github.com/HeathGames/half_rats_parasomnia_src ## Half-Screwed -Oficial github repository - https://github.com/desukuran/half-screwed +Official github repository - https://github.com/desukuran/half-screwed ## Headcrab Frenzy Version 1.3 on ModDB - https://www.moddb.com/mods/headcrab-frenzy/downloads/headcrab-frenzy-13-beta-source-code +## Heart of Evil +Available on ModDB - https://www.moddb.com/mods/heart-of-evil/downloads/heart-of-evil-dlls-source-code + ## Ingram Chillin' Mod -Oficial SourceForge repository - https://sourceforge.net/projects/icm-hl/ +Official SourceForge repository - https://sourceforge.net/projects/icm-hl/ ## MechMod -Oficial github repository - https://github.com/vermagav/mechmod +Official github repository - https://github.com/vermagav/mechmod + +## Mortal Combat Forever +Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/Mortal_Combat_Forever_(Polnie_ishodniki) ## Natural Selection -Oficial github repository - https://github.com/unknownworlds/NS +Official github repository - https://github.com/unknownworlds/NS + +## Overturn +Available in mod archive on ModDB - https://www.moddb.com/mods/overturn ## Spirit of Half-Life [Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life @@ -102,6 +129,8 @@ Available on ModDB: https://www.moddb.com/mods/paranoia/downloads/paranoia-toolk ## Paranoia 2: The Savior Prealpha, mirrored on github - https://github.com/a1batross/Paranoia2_ancient +Version 1.51, mirrored on github - https://github.com/a1batross/Paranoia2_original + ## Raven City *Unfinished mod* @@ -111,7 +140,7 @@ Was found on HLFX - http://hlfx.ru/forum/showthread.php?s=2c892dfc52f72be52a89c3 Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/ricochet ## Wizard Wars -Download page on oficial site - http://www.thothie.com/ww/ +Download page on official site - http://www.thothie.com/ww/ ## XashXT Mirrored on github - https://github.com/a1batross/XashXT_original @@ -128,6 +157,9 @@ Mirrored on github - https://github.com/ZXCmod/ZXCmod ## Absolute Redemption Branch **redempt** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/redempt +## Adrenaline Gamer +OpenAG by YaLTeR - https://github.com/YaLTeR/OpenAG + ## Afraid of Monsters malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-aom diff --git a/README.md b/README.md index 1def0067..1ba6ad24 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Xash3D FWGS Engine -[![Build Status](https://api.travis-ci.org/FWGS/xash3d-fwgs.svg?branch=master)](https://travis-ci.org/FWGS/xash3d-fwgs) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](https://discord.gg/TbnHcVb) \ +[![Build Status](https://api.travis-ci.org/FWGS/xash3d-fwgs.svg?branch=master)](https://travis-ci.org/FWGS/xash3d-fwgs) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://discord.fwgs.ru/) \ [![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-deploy/tree/anewengine-master) Xash3D FWGS is a fork of Xash3D Engine by Unkle Mike with extended features and crossplatform. @@ -26,8 +26,21 @@ Read more about Xash3D on ModDB: https://www.moddb.com/engines/xash3d-engine * Voice support * Vulkan renderer +## Installation & Running +0) Download Xash3D binaries: you can use [testing](https://github.com/FWGS/xash3d-deploy/tree/anewengine-master) build, also you can compile engine from sources. +Choose proper build package depending on which platform you're using. +1) Copy engine binaries to some directory. +2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to mentioned above directory with engine binaries. +Also if you're using Windows: you should copy `vgui.dll` library from Half-Life directory to Xash3D directory. +But instead, you can compile [hlsdk-xash3d](https://github.com/FWGS/hlsdk-xash3d) yourself instead of using official Valve game binaries, but you still needed to copy `valve` directory because all resources like sounds/models/maps located in there. +3) Download [extras.pak](https://github.com/FWGS/xash-extras/releases/tag/v0.19.2) and place it to `valve` directory. +4) Run `xash3d.exe`/`xash3d.sh`/`xash3d` depending on which platform you're using. + +For additional info, run Xash3D with `-help` command line key. + ## Contributing * Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html +* Issues are accepted in both English and Russian * Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file. ## Build instructions @@ -38,7 +51,7 @@ If you're stuck somewhere and you need a clear example, read `.travis.yml` and ` NOTE: NEVER USE GitHub's ZIP ARCHIVES. They are broken and don't contain external dependencies sources we're using. ### Prerequisites -#### Windows(Visual Studio) +#### Windows (Visual Studio) * Install Visual Studio. * Install latest [Python](https://python.org) **OR** run `cinst python.install` if you have Chocolatey. * Install latest [Git](https://git-scm.com/download/win) **OR** run `cinst git.install` if you have Chocolatey. @@ -64,7 +77,7 @@ Even if Xash3D FWGS does support targetting 64-bit, you can't load games without `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs` ### Building -#### Windows(Visual Studio) +#### Windows (Visual Studio) 0) Open command line 1) Navigate to `xash3d-fwgs` directory. 2) Carefully examine which build options are available: `waf --help` @@ -79,9 +92,4 @@ Even if Xash3D FWGS does support targetting 64-bit, you can't load games without 2) Compile: `./waf build` 3) Install(optional): `./waf install` -## Running -0) Copy libraries and main executable somewhere, if you're skipped installation stage. -1) Copy game files to same directory -2) Run `xash3d.exe`/`xash3d.sh`/`xash3d` depending on which platform you're using. -For additional info, run Xash3D with `-help` command line key. diff --git a/common/com_model.h b/common/com_model.h index 0a914555..9f8ceda8 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -291,7 +291,7 @@ typedef struct model_s // shared modelinfo modtype_t type; // model type int numframes; // sprite's framecount - byte *mempool; // private mempool (was synctype) + poolhandle_t mempool; // private mempool (was synctype) int flags; // hl compatibility // diff --git a/common/const.h b/common/const.h index 7fa83a44..2533ec09 100644 --- a/common/const.h +++ b/common/const.h @@ -606,13 +606,6 @@ #define CONTENT_GRAVITY_FLYFIELD -18 #define CONTENT_FOG -19 -#define CONTENT_EMPTY -1 -#define CONTENT_SOLID -2 -#define CONTENT_WATER -3 -#define CONTENT_SLIME -4 -#define CONTENT_LAVA -5 -#define CONTENT_SKY -6 - // channels #define CHAN_AUTO 0 #define CHAN_WEAPON 1 diff --git a/common/xash3d_types.h b/common/xash3d_types.h index 7f979601..e1d1a0ae 100644 --- a/common/xash3d_types.h +++ b/common/xash3d_types.h @@ -20,6 +20,7 @@ typedef byte rgba_t[4]; // unsigned byte colorpack typedef byte rgb_t[3]; // unsigned byte colorpack typedef vec_t matrix3x4[3][4]; typedef vec_t matrix4x4[4][4]; +typedef uint32_t poolhandle_t; #undef true #undef false diff --git a/engine/cdll_int.h b/engine/cdll_int.h index a748eef2..345b3c84 100644 --- a/engine/cdll_int.h +++ b/engine/cdll_int.h @@ -285,9 +285,9 @@ typedef struct cl_enginefuncs_s const char *(*LocalPlayerInfo_ValueForKey)( const char* key ); int (*pfnVGUI2DrawCharacter)( int x, int y, int ch, unsigned int font ); int (*pfnVGUI2DrawCharacterAdditive)( int x, int y, int ch, int r, int g, int b, unsigned int font ); - unsigned int (*pfnGetApproxWavePlayLen)( char *filename ); + unsigned int (*pfnGetApproxWavePlayLen)( const char *filename ); void* (*GetCareerGameUI)( void ); // g-cont. !!!! potential crash-point! - void (*Cvar_Set)( char *name, char *value ); + void (*Cvar_Set)( const char *name, const char *value ); int (*pfnIsPlayingCareerMatch)( void ); void (*pfnPlaySoundVoiceByName)( char *szSound, float volume, int pitch ); void (*pfnPrimeMusicStream)( char *filename, int looping ); diff --git a/engine/client/cl_cmds.c b/engine/client/cl_cmds.c index 1da66afa..fcc3f3cc 100644 --- a/engine/client/cl_cmds.c +++ b/engine/client/cl_cmds.c @@ -418,3 +418,32 @@ void SCR_Viewpos_f( void ) Con_Printf( "org ( %g %g %g )\n", refState.vieworg[0], refState.vieworg[1], refState.vieworg[2] ); Con_Printf( "ang ( %g %g %g )\n", refState.viewangles[0], refState.viewangles[1], refState.viewangles[2] ); } + +/* +============= +CL_WavePlayLen_f + +============= +*/ +void CL_WavePlayLen_f( void ) +{ + const char *name; + uint msecs; + + if( Cmd_Argc() != 2 ) + { + Con_Printf( "waveplaylen : returns approximate number of milliseconds a wave file will take to play.\n" ); + return; + } + + name = Cmd_Argv( 1 ); + msecs = Sound_GetApproxWavePlayLen( name ); + + if( msecs == 0 ) + { + Con_Printf( "Unable to read %s, file may be missing or incorrectly formatted.\n", name ); + return; + } + + Con_Printf( "Play time is approximately %dms\n", msecs ); +} diff --git a/engine/client/cl_events.c b/engine/client/cl_events.c index fd1fe7ec..bcf3f76d 100644 --- a/engine/client/cl_events.c +++ b/engine/client/cl_events.c @@ -78,23 +78,48 @@ CL_DescribeEvent ============= */ -void CL_DescribeEvent( int slot, int flags, const char *eventname ) +void CL_DescribeEvent( event_info_t *ei, int slot ) { - int idx = (slot & 31); + int idx = (slot & 63) * 2; con_nprint_t info; + string origin_str = { 0 }; //, angles_str = { 0 }; - if( !eventname || !cl_showevents->value ) + if( !cl_showevents->value ) return; - // mark reliable as green and unreliable as red - if( FBitSet( flags, FEV_RELIABLE )) - VectorSet( info.color, 0.0f, 1.0f, 0.0f ); - else VectorSet( info.color, 1.0f, 0.0f, 0.0f ); - - info.time_to_live = 0.5f; + info.time_to_live = 1.0f; info.index = idx; - Con_NXPrintf( &info, "%i %f %s", slot, cl.time, eventname ); + // mark reliable as green and unreliable as red + if( FBitSet( ei->flags, FEV_RELIABLE )) + VectorSet( info.color, 0.5f, 1.0f, 0.5f ); + else VectorSet( info.color, 1.0f, 0.5f, 0.5f ); + + if( !VectorIsNull( ei->args.origin )) + { + Q_snprintf( origin_str, sizeof( origin_str ), "(%.2f,%.2f,%.2f)", + ei->args.origin[0], ei->args.origin[1], ei->args.origin[2]); + } + + /*if( !VectorIsNull( ei->args.angles )) + { + Q_snprintf( angles_str, sizeof( angles_str ), "ang %.2f %.2f %.2f", + ei->args.angles[0], ei->args.angles[1], ei->args.angles[2]); + }*/ + + Con_NXPrintf( &info, "%i %.2f %c %s %s", + slot, cl.time, + (FBitSet( ei->flags, FEV_CLIENT ) ? 'c' : + FBitSet( ei->flags, FEV_SERVER ) ? 's' : '?'), + cl.event_precache[ei->index], + origin_str); + + info.index++; + + Con_NXPrintf( &info, "b(%i,%i) i(%i,%i) f(%.2f,%.2f)", + ei->args.bparam1, ei->args.bparam2, + ei->args.iparam1, ei->args.iparam2, + ei->args.fparam1, ei->args.fparam2); } /* @@ -202,7 +227,7 @@ qboolean CL_FireEvent( event_info_t *ei, int slot ) { if( ev->func ) { - CL_DescribeEvent( slot, ei->flags, cl.event_precache[ei->index] ); + CL_DescribeEvent( ei, slot ); ev->func( &ei->args ); return true; } diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index e16eaea1..5b550ac1 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -131,6 +131,9 @@ some ents will be ignore lerping */ qboolean CL_EntityIgnoreLerp( cl_entity_t *e ) { + if( cl_nointerp->value > 0.f ) + return true; + if( e->model && e->model->type == mod_alias ) return false; @@ -529,6 +532,13 @@ void CL_ComputePlayerOrigin( cl_entity_t *ent ) if( !ent->player || ent->index == ( cl.playernum + 1 )) return; + if( cl_nointerp->value > 0.f ) + { + VectorCopy( ent->curstate.angles, ent->angles ); + VectorCopy( ent->curstate.origin, ent->origin ); + return; + } + if( cls.demoplayback == DEMO_QUAKE1 ) { // quake lerping is easy @@ -1368,17 +1378,13 @@ qboolean CL_GetEntitySpatialization( channel_t *ch ) ent = CL_GetEntityByIndex( ch->entnum ); // entity is not present on the client but has valid origin - if( !ent || !ent->index || ent->curstate.messagenum == 0 ) + if( !ent || !ent->model || ent->curstate.messagenum != cl.parsecount ) return valid_origin; -#if 0 - // uncomment this if you want enable additional check by PVS - if( ent->curstate.messagenum != cl.parsecount ) - return valid_origin; -#endif - // setup origin - VectorAverage( ent->curstate.mins, ent->curstate.maxs, ch->origin ); - VectorAdd( ch->origin, ent->curstate.origin, ch->origin ); + VectorCopy( ent->origin, ch->origin ); + + if( ent->model->type == mod_brush ) + VectorAverage( ent->curstate.mins, ent->curstate.maxs, ch->origin ); return true; } @@ -1396,12 +1402,10 @@ qboolean CL_GetMovieSpatialization( rawchan_t *ch ) return valid_origin; // setup origin - VectorAverage( ent->curstate.mins, ent->curstate.maxs, ch->origin ); - VectorAdd( ch->origin, ent->curstate.origin, ch->origin ); + VectorCopy( ent->origin, ch->origin ); - // setup radius - if( ent->model != NULL && ent->model->radius ) ch->radius = ent->model->radius; - else ch->radius = RadiusFromBounds( ent->curstate.mins, ent->curstate.maxs ); + if( ent->model->type == mod_brush ) + VectorAverage( ent->curstate.mins, ent->curstate.maxs, ch->origin ); return true; } diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index e17b5555..55bb14c0 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -2417,12 +2417,15 @@ pfnIndexFromTrace */ int GAME_EXPORT pfnIndexFromTrace( struct pmtrace_s *pTrace ) { +#if 0 // Velaron: breaks compatibility with mods that call the function after CL_PopPMStates if( pTrace->ent >= 0 && pTrace->ent < clgame.pmove->numphysent ) { // return cl.entities number return clgame.pmove->physents[pTrace->ent].info; } return -1; +#endif + return clgame.pmove->physents[pTrace->ent].info; } /* @@ -3402,7 +3405,8 @@ void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double char fullquery[512] = "1\xFF" "0.0.0.0:0\0" "\\gamedir\\"; // make sure what port is specified - if( !nr->resp.remote_address.port ) nr->resp.remote_address.port = MSG_BigShort( PORT_MASTER ); + if( !nr->resp.remote_address.port ) + nr->resp.remote_address.port = MSG_BigShort( PORT_MASTER ); // grab the list from the master server Q_strcpy( &fullquery[22], GI->gamefolder ); @@ -3873,9 +3877,9 @@ static cl_enginefunc_t gEngfuncs = LocalPlayerInfo_ValueForKey, pfnVGUI2DrawCharacter, pfnVGUI2DrawCharacterAdditive, - (void*)Sound_GetApproxWavePlayLen, + Sound_GetApproxWavePlayLen, GetCareerGameInterface, - (void*)Cvar_Set, + Cvar_Set, pfnIsCareerMatch, pfnPlaySoundVoiceByName, pfnMP3_InitStream, diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 999864b3..f6b39230 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -43,7 +43,6 @@ convar_t *rcon_client_password; convar_t *rcon_address; convar_t *cl_timeout; convar_t *cl_nopred; -convar_t *cl_showfps; convar_t *cl_nodelta; convar_t *cl_crosshair; convar_t *cl_cmdbackup; @@ -64,6 +63,7 @@ convar_t *cl_updaterate; convar_t *cl_showevents; convar_t *cl_cmdrate; convar_t *cl_interp; +convar_t *cl_nointerp; convar_t *cl_dlmax; convar_t *cl_upmax; @@ -241,6 +241,11 @@ void CL_SignonReply( void ) } } +float CL_LerpInterval( void ) +{ + return max( cl_interp->value, 1.f / cl_updaterate->value ); +} + /* =============== CL_LerpPoint @@ -251,25 +256,29 @@ should be put at. */ static float CL_LerpPoint( void ) { - float f, frac = 1.0f; + float frac = 1.0f; + float server_frametime = cl_serverframetime(); - f = cl_serverframetime(); - - if( f == 0.0f || cls.timedemo ) + if( server_frametime == 0.0f || cls.timedemo ) { cl.time = cl.mtime[0]; return 1.0f; } - if( f > 0.1f ) + if( server_frametime > 0.1f ) { // dropped packet, or start of demo cl.mtime[1] = cl.mtime[0] - 0.1f; - f = 0.1f; + server_frametime = 0.1f; } -#if 1 +#if 0 + /* + g-cont: this code more suitable for singleplayer + NOTE in multiplayer causes significant framerate stutter/jitter and + occuring frames with zero time delta and even with negative time delta. + game becomes more twitchy and as if without interpolation. + */ frac = (cl.time - cl.mtime[1]) / f; - if( frac < 0.0f ) { if( frac < -0.01f ) @@ -283,15 +292,17 @@ static float CL_LerpPoint( void ) frac = 1.0f; } #else + // for multiplayer if( cl_interp->value > 0.001f ) { // manual lerp value (goldsrc mode) - frac = ( cl.time - cl.mtime[0] ) / cl_interp->value; + float td = max( 0.f, cl.time - cl.mtime[0] ); + frac = td / CL_LerpInterval(); } - else if( f > 0.001f ) + else if( server_frametime > 0.001f ) { // automatic lerp (classic mode) - frac = ( cl.time - cl.mtime[1] ) / f; + frac = ( cl.time - cl.mtime[1] ) / server_frametime; } #endif return frac; @@ -334,10 +345,10 @@ Validate interpolation cvars, calc interpolation window */ void CL_ComputeClientInterpolationAmount( usercmd_t *cmd ) { - int min_interp = MIN_EX_INTERP; - int max_interp = MAX_EX_INTERP; - int interpolation_msec; - qboolean forced = false; + const float epsilon = 0.001f; // to avoid float invalid comparision + float min_interp = MIN_EX_INTERP; + float max_interp = MAX_EX_INTERP; + float interpolation_time; if( cl_updaterate->value < MIN_UPDATERATE ) { @@ -352,29 +363,24 @@ void CL_ComputeClientInterpolationAmount( usercmd_t *cmd ) } if( cls.spectator ) - max_interp = 200; + max_interp = 0.2f; - min_interp = 1000.0f / cl_updaterate->value; - min_interp = Q_max( 1, min_interp ); - interpolation_msec = cl_interp->value * 1000.0f; - - if(( interpolation_msec + 1 ) < min_interp ) + min_interp = 1.0f / cl_updaterate->value; + interpolation_time = CL_LerpInterval( ); + + if( (cl_interp->value + epsilon) < min_interp ) { - Con_Printf( "ex_interp forced up to %i msec\n", interpolation_msec ); - interpolation_msec = min_interp; - forced = true; + Con_Printf( "ex_interp forced up to %.1f msec\n", min_interp * 1000.f ); + Cvar_SetValue( "ex_interp", min_interp ); } - else if(( interpolation_msec - 1 ) > max_interp ) + else if( (cl_interp->value - epsilon) > max_interp ) { - Con_Printf( "ex_interp forced down to %i msec\n", interpolation_msec ); - interpolation_msec = max_interp; - forced = true; + Con_Printf( "ex_interp forced down to %.1f msec\n", max_interp * 1000.f ); + Cvar_SetValue( "ex_interp", max_interp ); } - if( forced ) Cvar_SetValue( "ex_interp", (float)interpolation_msec * 0.001f ); - interpolation_msec = bound( min_interp, interpolation_msec, max_interp ); - - cmd->lerp_msec = CL_DriftInterpolationAmount( interpolation_msec ); + interpolation_time = bound( min_interp, interpolation_time, max_interp ); + cmd->lerp_msec = CL_DriftInterpolationAmount( interpolation_time * 1000 ); } /* @@ -2840,8 +2846,8 @@ void CL_InitLocal( void ) Cvar_Get( "team", "", FCVAR_USERINFO, "player team" ); Cvar_Get( "skin", "", FCVAR_USERINFO, "player skin" ); - cl_showfps = Cvar_Get( "cl_showfps", "1", FCVAR_ARCHIVE, "show client fps" ); - cl_nosmooth = Cvar_Get( "cl_nosmooth", "0", FCVAR_ARCHIVE, "disable smooth up stair climbing and interpolate position in multiplayer" ); + cl_nosmooth = Cvar_Get( "cl_nosmooth", "0", FCVAR_ARCHIVE, "disable smooth up stair climbing" ); + cl_nointerp = Cvar_Get( "cl_nointerp", "0", FCVAR_CLIENTDLL, "disable interpolation of entities and players" ); cl_smoothtime = Cvar_Get( "cl_smoothtime", "0", FCVAR_ARCHIVE, "time to smooth up" ); cl_cmdbackup = Cvar_Get( "cl_cmdbackup", "10", FCVAR_ARCHIVE, "how many additional history commands are sent" ); cl_cmdrate = Cvar_Get( "cl_cmdrate", "30", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" ); @@ -2881,6 +2887,7 @@ void CL_InitLocal( void ) Cmd_AddCommand ("internetservers", CL_InternetServers_f, "collect info about internet servers" ); Cmd_AddCommand ("cd", CL_PlayCDTrack_f, "Play cd-track (not real cd-player of course)" ); Cmd_AddCommand ("mp3", CL_PlayCDTrack_f, "Play mp3-track (based on virtual cd-player)" ); + Cmd_AddCommand ("waveplaylen", CL_WavePlayLen_f, "Get approximate length of wave file"); Cmd_AddCommand ("setinfo", CL_SetInfo_f, "examine or change the userinfo string (alias of userinfo)" ); Cmd_AddCommand ("userinfo", CL_SetInfo_f, "examine or change the userinfo string (alias of setinfo)" ); @@ -2966,12 +2973,12 @@ Host_ClientBegin */ void Host_ClientBegin( void ) { - // if client is not active, do nothing - if( !cls.initialized ) return; - // exec console commands Cbuf_Execute (); + // if client is not active, do nothing + if( !cls.initialized ) return; + // finalize connection process if needs CL_CheckClientState(); diff --git a/engine/client/cl_netgraph.c b/engine/client/cl_netgraph.c index a573b9dc..a361c9bd 100644 --- a/engine/client/cl_netgraph.c +++ b/engine/client/cl_netgraph.c @@ -15,6 +15,7 @@ GNU General Public License for more details. #include "common.h" #include "client.h" +#include "kbutton.h" #if XASH_LOW_MEMORY == 0 #define NET_TIMINGS 1024 @@ -33,11 +34,11 @@ GNU General Public License for more details. #define NUM_LATENCY_SAMPLES 8 convar_t *net_graph; -convar_t *net_graphpos; -convar_t *net_graphwidth; -convar_t *net_graphheight; -convar_t *net_graphsolid; -convar_t *net_scale; +static convar_t *net_graphpos; +static convar_t *net_graphwidth; +static convar_t *net_graphheight; +static convar_t *net_graphsolid; +static convar_t *net_scale; static struct packet_latency_t { @@ -95,7 +96,7 @@ NetGraph_AtEdge edge detect ========== */ -qboolean NetGraph_AtEdge( int x, int width ) +static qboolean NetGraph_AtEdge( int x, int width ) { if( x > 3 ) { @@ -113,7 +114,7 @@ NetGraph_InitColors init netgraph colors ========== */ -void NetGraph_InitColors( void ) +static void NetGraph_InitColors( void ) { byte mincolor[2][3]; byte maxcolor[2][3]; @@ -167,7 +168,7 @@ NetGraph_GetFrameData get frame data info, like chokes, packet losses, also update graph, packet and cmdinfo ========== */ -void NetGraph_GetFrameData( float *latency, int *latency_count ) +static void NetGraph_GetFrameData( float *latency, int *latency_count ) { int i, choke_count = 0, loss_count = 0; double newtime = Sys_DoubleTime(); @@ -249,7 +250,7 @@ NetGraph_DrawTimes =========== */ -void NetGraph_DrawTimes( wrect_t rect, int x, int w ) +static void NetGraph_DrawTimes( wrect_t rect, int x, int w ) { int i, j, extrap_point = NETGRAPH_LERP_HEIGHT / 3, a, h; rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 }; @@ -324,7 +325,7 @@ NetGraph_DrawHatches =========== */ -void NetGraph_DrawHatches( int x, int y ) +static void NetGraph_DrawHatches( int x, int y ) { int ystep = (int)( 10.0f / net_scale->value ); byte colorminor[4] = { 0, 63, 63, 200 }; @@ -353,7 +354,7 @@ NetGraph_DrawTextFields =========== */ -void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke ) +static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke, int graphtype ) { static int lastout; rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 }; @@ -400,7 +401,7 @@ void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, floa Con_DrawString( x, y, va( "out: %i %.2f k/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors ); y += 15; - if( net_graph->value > 2 ) + if( graphtype > 2 ) { int loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01f ); int choke = (int)(( packet_choke + PACKETCHOKE_AVG_FRAC ) - 0.01f ); @@ -409,7 +410,7 @@ void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, floa } } - if( net_graph->value < 3 ) + if( graphtype < 3 ) Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors ); Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors ); @@ -423,7 +424,7 @@ NetGraph_DrawDataSegment =========== */ -int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b, byte a ) +static int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b, byte a ) { float h = bytes / net_scale->value; byte colors[4] = { r, g, b, a }; @@ -450,7 +451,7 @@ NetGraph_ColorForHeight color based on packet latency =========== */ -void NetGraph_ColorForHeight( struct packet_latency_t *packet, byte color[4], int *ping ) +static void NetGraph_ColorForHeight( struct packet_latency_t *packet, byte color[4], int *ping ) { switch( packet->latency ) { @@ -485,7 +486,7 @@ NetGraph_DrawDataUsage =========== */ -void NetGraph_DrawDataUsage( int x, int y, int w ) +static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype ) { int a, i, h, lastvalidh = 0, ping; int pingheight = net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2; @@ -540,7 +541,7 @@ void NetGraph_DrawDataUsage( int x, int y, int w ) if( NetGraph_AtEdge( a, w )) NetGraph_DrawRect( &fill, color ); - if( net_graph->value < 2 ) + if( graphtype < 2 ) continue; color[0] = color[1] = color[2] = color[3] = 255; @@ -587,7 +588,7 @@ void NetGraph_DrawDataUsage( int x, int y, int w ) continue; } - if( net_graph->value >= 2 ) + if( graphtype >= 2 ) NetGraph_DrawHatches( x, y - net_graphheight->value - 1 ); } @@ -597,7 +598,7 @@ NetGraph_GetScreenPos =========== */ -void NetGraph_GetScreenPos( wrect_t *rect, int *w, int *x, int *y ) +static void NetGraph_GetScreenPos( wrect_t *rect, int *w, int *x, int *y ) { rect->left = rect->top = 0; rect->right = refState.width; @@ -636,6 +637,8 @@ void SCR_DrawNetGraph( void ) float avg_ping; int ping_count; int w, x, y; + kbutton_t *in_graph; + int graphtype; if( !host.allow_console ) return; @@ -643,8 +646,20 @@ void SCR_DrawNetGraph( void ) if( cls.state != ca_active ) return; - if( !net_graph->value ) + in_graph = clgame.dllFuncs.KB_Find( "in_graph" ); + + if( in_graph->state & 1 ) + { + graphtype = 2; + } + else if( net_graph->value != 0.0f ) + { + graphtype = (int)net_graph->value; + } + else + { return; + } if( net_scale->value <= 0 ) Cvar_SetValue( "net_scale", 0.1f ); @@ -653,16 +668,16 @@ void SCR_DrawNetGraph( void ) NetGraph_GetFrameData( &avg_ping, &ping_count ); - NetGraph_DrawTextFields( x, y, w, rect, ping_count, avg_ping, packet_loss, packet_choke ); + NetGraph_DrawTextFields( x, y, w, rect, ping_count, avg_ping, packet_loss, packet_choke, graphtype ); - if( net_graph->value < 3 ) + if( graphtype < 3 ) { ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd ); ref.dllFuncs.GL_Bind( XASH_TEXTURE0, R_GetBuiltinTexture( REF_WHITE_TEXTURE ) ); ref.dllFuncs.Begin( TRI_QUADS ); // draw all the fills as a long solid sequence of quads for speedup reasons // NOTE: fill colors without texture at this point - NetGraph_DrawDataUsage( x, y, w ); + NetGraph_DrawDataUsage( x, y, w, graphtype ); NetGraph_DrawTimes( rect, x, w ); ref.dllFuncs.End(); diff --git a/engine/client/cl_pmove.c b/engine/client/cl_pmove.c index 35e61937..897a717b 100644 --- a/engine/client/cl_pmove.c +++ b/engine/client/cl_pmove.c @@ -264,7 +264,9 @@ void CL_CheckPredictionError( void ) // save for error interpolation VectorCopy( delta, cl.local.prediction_error ); - if( dist > MIN_CORRECTION_DISTANCE ) + // GoldSrc checks for singleplayer + // we would check for local server + if( dist > MIN_CORRECTION_DISTANCE && !SV_Active() ) cls.correction_time = cl_smoothtime->value; } } @@ -1048,7 +1050,7 @@ void CL_FinishPMove( playermove_t *pmove, local_state_t *to ) VectorCopy( pmove->angles, ps->angles ); VectorCopy( pmove->basevelocity, ps->basevelocity ); VectorCopy( pmove->punchangle, cd->punchangle ); - ps->oldbuttons = pmove->oldbuttons; + ps->oldbuttons = pmove->cmd.buttons; ps->friction = pmove->friction; ps->movetype = pmove->movetype; ps->onground = pmove->onground; @@ -1080,13 +1082,14 @@ Runs prediction code for user cmd void CL_RunUsercmd( local_state_t *from, local_state_t *to, usercmd_t *u, qboolean runfuncs, double *time, unsigned int random_seed ) { usercmd_t cmd; - local_state_t temp; - usercmd_t split; - - memset( &temp, 0, sizeof( temp )); if( u->msec > 50 ) { + local_state_t temp; + usercmd_t split; + + memset( &temp, 0, sizeof( temp )); + split = *u; split.msec /= 2; CL_RunUsercmd( from, &temp, &split, runfuncs, time, random_seed ); @@ -1153,12 +1156,12 @@ Sets cl.predicted.origin and cl.predicted.angles */ void CL_PredictMovement( qboolean repredicting ) { - runcmd_t *to_cmd, *from_cmd; + runcmd_t *to_cmd = NULL, *from_cmd; local_state_t *from = NULL, *to = NULL; - int current_command; - int current_command_mod; + uint current_command; + uint current_command_mod; frame_t *frame = NULL; - int i, stoppoint; + uint i, stoppoint; qboolean runfuncs; double f = 1.0; cl_entity_t *ent; @@ -1227,10 +1230,6 @@ void CL_PredictMovement( qboolean repredicting ) if( to_cmd->senttime >= host.realtime ) break; - // now interpolate some fraction of the final frame - if( to_cmd->senttime != from_cmd->senttime ) - f = (host.realtime - from_cmd->senttime) / (to_cmd->senttime - from_cmd->senttime) * 0.1; - from = to; from_cmd = to_cmd; } @@ -1263,8 +1262,10 @@ void CL_PredictMovement( qboolean repredicting ) return; } - f = bound( 0.0f, f, 1.0f ); - f = 0.0; // FIXME: make work, do revision + // now interpolate some fraction of the final frame + if( to_cmd->senttime != from_cmd->senttime ) + f = bound( 0.0, (host.realtime - from_cmd->senttime) / (to_cmd->senttime - from_cmd->senttime) * 0.1, 1.0 ); + else f = 0.0; if( CL_PlayerTeleported( from, to )) { diff --git a/engine/client/cl_remap.c b/engine/client/cl_remap.c index fd6350df..3a9c74c8 100644 --- a/engine/client/cl_remap.c +++ b/engine/client/cl_remap.c @@ -98,7 +98,7 @@ CL_DuplicateTexture Dupliacte texture with remap pixels ==================== */ -void CL_DuplicateTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) +void CL_DuplicateTexture( cl_entity_t *entity, model_t *model, mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { const char *name; texture_t *tx = NULL; @@ -114,9 +114,9 @@ void CL_DuplicateTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, int t Q_snprintf( texname, sizeof( texname ), "#%i_%s", entity->curstate.number, name + 1 ); // search for pixels - for( i = 0; i < entity->model->numtextures; i++ ) + for( i = 0; i < model->numtextures; i++ ) { - tx = entity->model->textures[i]; + tx = model->textures[i]; if( tx->gl_texturenum == index ) break; // found } @@ -242,7 +242,7 @@ Allocate new remap info per entity and make copy of remap textures ==================== */ -void CL_AllocRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor ) +void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor ) { remap_info_t *info; studiohdr_t *phdr; @@ -253,7 +253,7 @@ void CL_AllocRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor ) if( !entity ) return; i = ( entity == &clgame.viewent ) ? clgame.maxEntities : entity->curstate.number; - if( !entity->model || ( entity->model->type != mod_alias && entity->model->type != mod_studio )) + if( !model || ( model->type != mod_alias && model->type != mod_studio )) { // entity has changed model by another type, release remap info if( clgame.remap_info[i] ) @@ -265,7 +265,7 @@ void CL_AllocRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor ) } // model doesn't contains remap textures - if( entity->model->numtextures <= 0 ) + if( model->numtextures <= 0 ) { // entity has changed model with no remap textures if( clgame.remap_info[i] ) @@ -276,16 +276,16 @@ void CL_AllocRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor ) return; } - if( entity->model->type == mod_studio ) + if( model->type == mod_studio ) { - phdr = (studiohdr_t *)Mod_StudioExtradata( entity->model ); + phdr = (studiohdr_t *)Mod_StudioExtradata( model ); if( !phdr ) return; // bad model? src = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex); dst = (clgame.remap_info[i] ? clgame.remap_info[i]->ptexture : NULL); // NOTE: we must copy all the structures 'mstudiotexture_t' for easy access when model is rendering - if( !CL_CmpStudioTextures( phdr->numtextures, src, dst ) || clgame.remap_info[i]->model != entity->model ) + if( !CL_CmpStudioTextures( phdr->numtextures, src, dst ) || clgame.remap_info[i]->model != model ) { // this code catches studiomodel change with another studiomodel with remap textures // e.g. playermodel 'barney' with playermodel 'gordon' @@ -314,16 +314,16 @@ void CL_AllocRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor ) for( i = 0; i < info->numtextures; i++ ) { if( dst[i].flags & STUDIO_NF_COLORMAP ) - CL_DuplicateTexture( entity, &dst[i], topcolor, bottomcolor ); + CL_DuplicateTexture( entity, model, &dst[i], topcolor, bottomcolor ); } } - else if( entity->model->type == mod_alias ) + else if( model->type == mod_alias ) { - ahdr = (aliashdr_t *)Mod_AliasExtradata( entity->model ); + ahdr = (aliashdr_t *)Mod_AliasExtradata( model ); if( !ahdr ) return; // bad model? // NOTE: we must copy all the structures 'mstudiotexture_t' for easy access when model is rendering - if( !clgame.remap_info[i] || clgame.remap_info[i]->model != entity->model ) + if( !clgame.remap_info[i] || clgame.remap_info[i]->model != model ) { // this code catches studiomodel change with another studiomodel with remap textures // e.g. playermodel 'barney' with playermodel 'gordon' @@ -336,7 +336,7 @@ void CL_AllocRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor ) return; } - info->numtextures = entity->model->numtextures; + info->numtextures = model->numtextures; // alias remapping is easy CL_UpdateRemapInfo( entity, topcolor, bottomcolor ); @@ -347,7 +347,7 @@ void CL_AllocRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor ) return; } - info->model = entity->model; + info->model = model; } /* diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index 70e8acb5..125dc0e2 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -27,8 +27,11 @@ convar_t *scr_viewsize; convar_t *cl_testlights; convar_t *cl_allow_levelshots; convar_t *cl_levelshot_name; -convar_t *cl_envshot_size; +static convar_t *cl_envshot_size; convar_t *v_dark; +static convar_t *net_speeds; +static convar_t *cl_showfps; +static convar_t *cl_showpos; typedef struct { @@ -102,6 +105,41 @@ void SCR_DrawFPS( int height ) Con_DrawString( refState.width - offset - 4, height, fpsstring, color ); } +/* +============== +SCR_DrawPos + +Draw local player position, angles and velocity +============== +*/ +void SCR_DrawPos( void ) +{ + static char msg[MAX_SYSPATH]; + float speed; + cl_entity_t *ent; + rgba_t color; + + if( cls.state != ca_active || !cl_showpos->value || cl.background ) + return; + + ent = CL_GetLocalPlayer(); + speed = VectorLength( cl.simvel ); + + Q_snprintf( msg, MAX_SYSPATH, + "pos: %.2f %.2f %.2f\n" + "ang: %.2f %.2f %.2f\n" + "velocity: %.2f", + cl.simorg[0], cl.simorg[1], cl.simorg[2], + // should we use entity angles or viewangles? + // view isn't always bound to player + ent->angles[0], ent->angles[1], ent->angles[2], + speed ); + + MakeRGBA( color, 255, 255, 255, 255 ); + + Con_DrawString( refState.width / 2, 4, msg, color ); +} + /* ============== SCR_NetSpeeds @@ -777,6 +815,9 @@ void SCR_Init( void ) cl_envshot_size = Cvar_Get( "cl_envshot_size", "256", FCVAR_ARCHIVE, "envshot size of cube side" ); v_dark = Cvar_Get( "v_dark", "0", 0, "starts level from dark screen" ); scr_viewsize = Cvar_Get( "viewsize", "120", FCVAR_ARCHIVE, "screen size" ); + net_speeds = Cvar_Get( "net_speeds", "0", FCVAR_ARCHIVE, "show network packets" ); + cl_showfps = Cvar_Get( "cl_showfps", "1", FCVAR_ARCHIVE, "show client fps" ); + cl_showpos = Cvar_Get( "cl_showpos", "0", FCVAR_ARCHIVE, "show local player position and velocity" ); // register our commands Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" ); diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index f349eb72..26930bd1 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -475,6 +475,7 @@ void V_PostRender( void ) { SCR_RSpeeds(); SCR_NetSpeeds(); + SCR_DrawPos(); SCR_DrawNetGraph(); SV_DrawOrthoTriangles(); CL_DrawDemoRecording(); diff --git a/engine/client/client.h b/engine/client/client.h index cde2c275..8e4dafaa 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -107,8 +107,8 @@ extern int CL_UPDATE_BACKUP; #define MIN_UPDATERATE 10.0f #define MAX_UPDATERATE 102.0f -#define MIN_EX_INTERP 50.0f -#define MAX_EX_INTERP 100.0f +#define MIN_EX_INTERP 0.005f +#define MAX_EX_INTERP 0.1f #define CL_MIN_RESEND_TIME 1.5f // mininum time gap (in seconds) before a subsequent connection request is sent. #define CL_MAX_RESEND_TIME 20.0f // max time. The cvar cl_resend is bounded by these. @@ -437,7 +437,7 @@ typedef struct void *hInstance; // pointer to client.dll cldll_func_t dllFuncs; // dll exported funcs render_interface_t drawFuncs; // custom renderer support - byte *mempool; // client edicts pool + poolhandle_t mempool; // client edicts pool string mapname; // map name string maptitle; // display map title string itemspath; // path to items description for auto-complete func @@ -496,7 +496,7 @@ typedef struct void *hInstance; // pointer to client.dll UI_FUNCTIONS dllFuncs; // dll exported funcs UI_EXTENDED_FUNCTIONS dllFuncs2; // fwgs extension - byte *mempool; // client edicts pool + poolhandle_t mempool; // client edicts pool cl_entity_t playermodel; // uiPlayerSetup drawing model player_info_t playerinfo; // local playerinfo @@ -534,7 +534,7 @@ typedef struct keydest_t key_dest; - byte *mempool; // client premamnent pool: edicts etc + poolhandle_t mempool; // client premamnent pool: edicts etc netadr_t hltv_listen_address; @@ -655,11 +655,10 @@ extern convar_t cl_allow_download; extern convar_t cl_allow_upload; extern convar_t cl_download_ingame; extern convar_t *cl_nopred; -extern convar_t *cl_showfps; -extern convar_t *cl_envshot_size; extern convar_t *cl_timeout; extern convar_t *cl_nodelta; extern convar_t *cl_interp; +extern convar_t *cl_nointerp; extern convar_t *cl_showerror; extern convar_t *cl_nosmooth; extern convar_t *cl_smoothtime; @@ -719,6 +718,7 @@ void CL_SaveShot_f( void ); void CL_LevelShot_f( void ); void CL_SetSky_f( void ); void SCR_Viewpos_f( void ); +void CL_WavePlayLen_f( void ); // // cl_custom.c @@ -882,6 +882,7 @@ void SCR_MakeLevelShot( void ); void SCR_NetSpeeds( void ); void SCR_RSpeeds( void ); void SCR_DrawFPS( int height ); +void SCR_DrawPos( void ); // // cl_netgraph.c @@ -953,7 +954,7 @@ void CL_EmitEntities( void ); // cl_remap.c // remap_info_t *CL_GetRemapInfoForEntity( cl_entity_t *e ); -void CL_AllocRemapInfo( cl_entity_t *ent, int topcolor, int bottomcolor ); +void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor ); void CL_FreeRemapInfo( remap_info_t *info ); void CL_UpdateRemapInfo( cl_entity_t *ent, int topcolor, int bottomcolor ); void CL_ClearAllRemaps( void ); diff --git a/engine/client/in_touch.c b/engine/client/in_touch.c index dec3a20b..ce398f1c 100644 --- a/engine/client/in_touch.c +++ b/engine/client/in_touch.c @@ -95,7 +95,7 @@ struct touch_s qboolean initialized; qboolean config_loaded; touchbuttonlist_t list_user, list_edit; - byte *mempool; + poolhandle_t mempool; touchState state; int look_finger; diff --git a/engine/client/input.c b/engine/client/input.c index 79d94ee3..47a17109 100644 --- a/engine/client/input.c +++ b/engine/client/input.c @@ -669,8 +669,6 @@ void Host_InputFrame( void ) } } - Cbuf_Execute (); - if( !in_mouseinitialized ) return; diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index 465fb515..a7e54dcf 100644 --- a/engine/client/ref_common.c +++ b/engine/client/ref_common.c @@ -178,7 +178,7 @@ static int pfnGetStudioModelInterface( int version, struct r_studio_interface_s 0; } -static byte *pfnImage_GetPool( void ) +static poolhandle_t pfnImage_GetPool( void ) { return host.imagepool; } diff --git a/engine/client/ref_common.h b/engine/client/ref_common.h index 1e8521cb..a8ee1405 100644 --- a/engine/client/ref_common.h +++ b/engine/client/ref_common.h @@ -53,4 +53,6 @@ qboolean R_Init( void ); void R_Shutdown( void ); void R_UpdateRefState( void ); +extern triangleapi_t gTriApi; + #endif // REF_COMMON_H diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 05354a34..89b8da66 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -23,7 +23,7 @@ GNU General Public License for more details. #define SND_CLIP_DISTANCE 1000.0f dma_t dma; -byte *sndpool; +poolhandle_t sndpool; static soundfade_t soundfade; channel_t channels[MAX_CHANNELS]; sound_t ambient_sfx[NUM_AMBIENTS]; @@ -35,17 +35,17 @@ int total_channels; int soundtime; // sample PAIRS int paintedtime; // sample PAIRS -convar_t *s_volume; -convar_t *s_musicvolume; -convar_t *s_show; -convar_t *s_mixahead; -convar_t *s_lerping; -convar_t *s_ambient_level; -convar_t *s_ambient_fade; -convar_t *s_combine_sounds; -convar_t *snd_mute_losefocus; -convar_t *s_test; // cvar for testing new effects -convar_t *s_samplecount; +static CVAR_DEFINE( s_volume, "volume", "0.7", FCVAR_ARCHIVE, "sound volume" ); +CVAR_DEFINE( s_musicvolume, "MP3Volume", "1.0", FCVAR_ARCHIVE, "background music volume" ); +static CVAR_DEFINE( s_mixahead, "_snd_mixahead", "0.12", 0, "how much sound to mix ahead of time" ); +static CVAR_DEFINE_AUTO( s_show, "0", FCVAR_ARCHIVE, "show playing sounds" ); +CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE, "apply interpolation to sound output" ); +static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE, "volume of environment noises (water and wind)" ); +static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE, "rate of volume fading when client is moving" ); +static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE, "combine channels with same sounds" ); +CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE, "silence the audio when game window loses focus" ); +CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" ); +CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE, "sample count (0 for default value)" ); /* ============================================================================= @@ -68,7 +68,7 @@ float S_GetMasterVolume( void ) scale = bound( 0.0f, soundfade.percent / 100.0f, 1.0f ); scale = 1.0f - scale; } - return s_volume->value * scale; + return s_volume.value * scale; } /* @@ -945,7 +945,7 @@ void S_UpdateAmbientSounds( void ) leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes ); - if( !leaf || !s_ambient_level->value ) + if( !leaf || !s_ambient_level.value ) { for( ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++ ) channels[ambient_channel].sfx = NULL; @@ -965,18 +965,18 @@ void S_UpdateAmbientSounds( void ) continue; } - vol = s_ambient_level->value * leaf->ambient_sound_level[ambient_channel]; + vol = s_ambient_level.value * leaf->ambient_sound_level[ambient_channel]; if( vol < 0 ) vol = 0; // don't adjust volume too fast if( chan->master_vol < vol ) { - chan->master_vol += s_listener.frametime * s_ambient_fade->value; + chan->master_vol += s_listener.frametime * s_ambient_fade.value; if( chan->master_vol > vol ) chan->master_vol = vol; } else if( chan->master_vol > vol ) { - chan->master_vol -= s_listener.frametime * s_ambient_fade->value; + chan->master_vol -= s_listener.frametime * s_ambient_fade.value; if( chan->master_vol < vol ) chan->master_vol = vol; } @@ -1192,7 +1192,7 @@ void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float sy ch->s_rawend = soundtime; // position is changed, synchronization is lost etc - if( fabs( ch->oldtime - synctime ) > s_mixahead->value ) + if( fabs( ch->oldtime - synctime ) > s_mixahead.value ) ch->sound_info.loopStart = AVI_TimeToSoundPosition( Avi, synctime * 1000 ); ch->oldtime = synctime; // keep actual time @@ -1450,6 +1450,45 @@ void S_StopAllSounds( qboolean ambient ) memset( &soundfade, 0, sizeof( soundfade )); } +/* +============== +S_GetSoundtime + +update global soundtime + +(was part of platform code) +=============== +*/ +static int S_GetSoundtime( void ) +{ + static int buffers, oldsamplepos; + int samplepos, fullsamples; + + fullsamples = dma.samples / 2; + + // it is possible to miscount buffers + // if it has wrapped twice between + // calls to S_Update. Oh well. + samplepos = dma.samplepos; + + if( samplepos < oldsamplepos ) + { + buffers++; // buffer wrapped + + if( paintedtime > 0x40000000 ) + { + // time to chop things off to avoid 32 bit limits + buffers = 0; + paintedtime = fullsamples; + S_StopAllSounds( true ); + } + } + + oldsamplepos = samplepos; + + return ( buffers * fullsamples + samplepos / 2 ); +} + //============================================================================= void S_UpdateChannels( void ) { @@ -1461,12 +1500,12 @@ void S_UpdateChannels( void ) if( !dma.buffer ) return; // updates DMA time - soundtime = SNDDMA_GetSoundtime(); + soundtime = S_GetSoundtime(); // soundtime - total samples that have been played out to hardware at dmaspeed // paintedtime - total samples that have been mixed at speed // endtime - target for samples in mixahead buffer at speed - endtime = soundtime + s_mixahead->value * SOUND_DMA_SPEED; + endtime = soundtime + s_mixahead.value * SOUND_DMA_SPEED; samps = dma.samples >> 1; if((int)(endtime - soundtime) > samps ) @@ -1562,7 +1601,7 @@ void SND_UpdateSound( void ) // try to combine static sounds with a previous channel of the same // sound effect so we don't mix five torches every frame // g-cont: perfomance option, probably kill stereo effect in most cases - if( i >= MAX_DYNAMIC_CHANNELS && s_combine_sounds->value ) + if( i >= MAX_DYNAMIC_CHANNELS && s_combine_sounds.value ) { // see if it can just use the last one if( combine && combine->sfx == ch->sfx ) @@ -1602,7 +1641,7 @@ void SND_UpdateSound( void ) S_SpatializeRawChannels(); // debugging output - if( CVAR_TO_BOOL( s_show )) + if( s_show.value != 0.0f ) { info.color[0] = 1.0f; info.color[1] = 0.6f; @@ -1679,26 +1718,41 @@ void S_PlayVol_f( void ) S_StartLocalSound( Cmd_Argv( 1 ), Q_atof( Cmd_Argv( 2 )), false ); } +static void S_Say( const char *name, qboolean reliable ) +{ + char sentence[1024]; + + // predefined vox sentence + if( name[0] == '!' ) + { + S_StartLocalSound( name, 1.0f, reliable ); + return; + } + + Q_snprintf( sentence, sizeof( sentence ), "!#%s", name ); + S_StartLocalSound( sentence, 1.0f, reliable ); +} + void S_Say_f( void ) { if( Cmd_Argc() == 1 ) { - Con_Printf( S_USAGE "speak \n" ); + Con_Printf( S_USAGE "speak \n" ); return; } - S_StartLocalSound( Cmd_Argv( 1 ), 1.0f, false ); + S_Say( Cmd_Argv( 1 ), false ); } void S_SayReliable_f( void ) { if( Cmd_Argc() == 1 ) { - Con_Printf( S_USAGE "spk \n" ); + Con_Printf( S_USAGE "spk \n" ); return; } - S_StartLocalSound( Cmd_Argv( 1 ), 1.0f, true ); + S_Say( Cmd_Argv( 1 ), true ); } /* @@ -1815,17 +1869,17 @@ qboolean S_Init( void ) return false; } - s_volume = Cvar_Get( "volume", "0.7", FCVAR_ARCHIVE, "sound volume" ); - s_musicvolume = Cvar_Get( "MP3Volume", "1.0", FCVAR_ARCHIVE, "background music volume" ); - s_mixahead = Cvar_Get( "_snd_mixahead", "0.12", 0, "how much sound to mix ahead of time" ); - s_show = Cvar_Get( "s_show", "0", FCVAR_ARCHIVE, "show playing sounds" ); - s_lerping = Cvar_Get( "s_lerping", "0", FCVAR_ARCHIVE, "apply interpolation to sound output" ); - s_ambient_level = Cvar_Get( "ambient_level", "0.3", FCVAR_ARCHIVE, "volume of environment noises (water and wind)" ); - s_ambient_fade = Cvar_Get( "ambient_fade", "1000", FCVAR_ARCHIVE, "rate of volume fading when client is moving" ); - s_combine_sounds = Cvar_Get( "s_combine_channels", "0", FCVAR_ARCHIVE, "combine channels with same sounds" ); - snd_mute_losefocus = Cvar_Get( "snd_mute_losefocus", "1", FCVAR_ARCHIVE, "silence the audio when game window loses focus" ); - s_test = Cvar_Get( "s_test", "0", 0, "engine developer cvar for quick testing new features" ); - s_samplecount = Cvar_Get( "s_samplecount", "0", FCVAR_ARCHIVE, "sample count (0 for default value)" ); + Cvar_RegisterVariable( &s_volume ); + Cvar_RegisterVariable( &s_musicvolume ); + Cvar_RegisterVariable( &s_mixahead ); + Cvar_RegisterVariable( &s_show ); + Cvar_RegisterVariable( &s_lerping ); + Cvar_RegisterVariable( &s_ambient_level ); + Cvar_RegisterVariable( &s_ambient_fade ); + Cvar_RegisterVariable( &s_combine_sounds ); + Cvar_RegisterVariable( &snd_mute_losefocus ); + Cvar_RegisterVariable( &s_test ); + Cvar_RegisterVariable( &s_samplecount ); Cmd_AddCommand( "play", S_Play_f, "playing a specified sound file" ); Cmd_AddCommand( "play2", S_Play2_f, "playing a group of specified sound files" ); // nehahra stuff diff --git a/engine/client/s_mix.c b/engine/client/s_mix.c index 87aa09d7..78bef1db 100644 --- a/engine/client/s_mix.c +++ b/engine/client/s_mix.c @@ -991,7 +991,7 @@ void MIX_UpsampleAllPaintbuffers( int end, int count ) // upsample all 11khz buffers by 2x // only upsample roombuffer if dsp fx are on KDB: perf MIX_SetCurrentPaintbuffer( IROOMBUFFER ); // operates on MixUpSample - S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_11k ), s_lerping->value ); + S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_11k ), s_lerping.value ); // mix 22khz sounds: MIX_MixChannelsToPaintbuffer( end, SOUND_22k, SOUND_22k ); @@ -999,7 +999,7 @@ void MIX_UpsampleAllPaintbuffers( int end, int count ) // upsample all 22khz buffers by 2x // only upsample roombuffer if dsp fx are on KDB: perf MIX_SetCurrentPaintbuffer( IROOMBUFFER ); - S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_22k ), s_lerping->value ); + S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_22k ), s_lerping.value ); // mix all 44khz sounds to all active paintbuffers MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED ); diff --git a/engine/client/s_stream.c b/engine/client/s_stream.c index 7debfcca..10ed064a 100644 --- a/engine/client/s_stream.c +++ b/engine/client/s_stream.c @@ -63,7 +63,7 @@ float S_GetMusicVolume( void ) scale = 1.0f - scale; } - return s_musicvolume->value * scale; + return s_musicvolume.value * scale; } /* @@ -183,7 +183,7 @@ void S_StreamBackgroundTrack( void ) return; // don't bother playing anything if musicvolume is 0 - if( !s_musicvolume->value || s_listener.paused || s_listener.stream_paused ) + if( !s_musicvolume.value || s_listener.paused || s_listener.stream_paused ) return; if( !cl.background ) diff --git a/engine/client/s_vox.c b/engine/client/s_vox.c index 4f7d5f81..b421fe35 100644 --- a/engine/client/s_vox.c +++ b/engine/client/s_vox.c @@ -469,7 +469,10 @@ void VOX_LoadSound( channel_t *pchan, const char *pszin ) // lookup actual string in g_Sentences, // set pointer to string data - psz = VOX_LookupString( pszin, NULL ); + if( pszin[0] == '#' ) + psz = (char *)pszin + 1; + else + psz = VOX_LookupString( pszin, NULL ); if( !psz ) { diff --git a/engine/client/sound.h b/engine/client/sound.h index 9ae1232b..a955882c 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -16,7 +16,7 @@ GNU General Public License for more details. #ifndef SOUND_H #define SOUND_H -extern byte *sndpool; +extern poolhandle_t sndpool; #include "xash3d_mathlib.h" @@ -138,7 +138,6 @@ typedef struct rawchan_s int rightvol; // 0-255 right volume float dist_mult; // distance multiplier (attenuation/clipK) vec3_t origin; // only use if fixed_origin is set - float radius; // radius of this sound effect volatile uint s_rawend; wavdata_t sound_info; // advance play position float oldtime; // catch time jumps @@ -217,15 +216,12 @@ extern listener_t s_listener; extern int idsp_room; extern dma_t dma; -extern convar_t *s_volume; -extern convar_t *s_musicvolume; -extern convar_t *s_show; -extern convar_t *s_mixahead; -extern convar_t *s_lerping; +extern convar_t s_musicvolume; +extern convar_t s_lerping; extern convar_t *dsp_off; -extern convar_t *s_test; // cvar to testify new effects -extern convar_t *s_samplecount; -extern convar_t *snd_mute_losefocus; +extern convar_t s_test; // cvar to testify new effects +extern convar_t s_samplecount; +extern convar_t snd_mute_losefocus; void S_InitScaletable( void ); wavdata_t *S_LoadSound( sfx_t *sfx ); diff --git a/engine/common/build.c b/engine/common/build.c index 78f9c8f9..eef0454a 100644 --- a/engine/common/build.c +++ b/engine/common/build.c @@ -93,6 +93,8 @@ const char *Q_buildos( void ) osname = "emscripten"; #elif XASH_DOS4GW osname = "DOS4GW"; +#elif XASH_HAIKU + osname = "haiku"; #else #error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug" #endif diff --git a/engine/common/cfgscript.c b/engine/common/cfgscript.c index da8c12db..3ff96b5e 100644 --- a/engine/common/cfgscript.c +++ b/engine/common/cfgscript.c @@ -203,83 +203,15 @@ qboolean CSCR_ParseHeader( parserstate_t *ps ) } /* -====================== -CSCR_WriteGameCVars +============== +CSCR_ParseFile -Print all cvars declared in script to game.cfg file -====================== +generic scr parser +will callback on each scrvardef_t +============== */ -int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename ) -{ - parserstate_t state = { 0 }; - qboolean success = false; - int count = 0; - fs_offset_t length = 0; - char *start; - - state.filename = scriptfilename; - state.buf = start = (char *)FS_LoadFile( scriptfilename, &length, true ); - - if( !state.buf || !length ) - return 0; - - Con_DPrintf( "Reading config script file %s\n", scriptfilename ); - - if( !CSCR_ParseHeader( &state )) - goto finish; - - while( !CSCR_ExpectString( &state, "}", false, false )) - { - scrvardef_t var = { 0 }; - - if( CSCR_ParseSingleCvar( &state, &var ) ) - { - convar_t *cvar = Cvar_FindVar( var.name ); - - if( cvar && !FBitSet( cvar->flags, FCVAR_SERVER|FCVAR_ARCHIVE )) - { - // cvars will be placed in game.cfg and restored on map start - if( var.flags & FCVAR_USERINFO ) - FS_Printf( cfg, "setinfo %s \"%s\"\n", var.name, cvar->string ); - else FS_Printf( cfg, "%s \"%s\"\n", var.name, cvar->string ); - } - count++; - } - else - { - break; - } - - if( count > 1024 ) - break; - } - - if( COM_ParseFile( state.buf, state.token )) - Con_DPrintf( S_ERROR "Got extra tokens!\n" ); - else success = true; -finish: - if( !success ) - { - state.token[sizeof( state.token ) - 1] = 0; - - if( start && state.buf ) - Con_DPrintf( S_ERROR "Parse error in %s, byte %d, token %s\n", scriptfilename, (int)( state.buf - start ), state.token ); - else Con_DPrintf( S_ERROR "Parse error in %s, token %s\n", scriptfilename, state.token ); - } - - if( start ) Mem_Free( start ); - - return count; -} - -/* -====================== -CSCR_LoadDefaultCVars - -Register all cvars declared in config file and set default values -====================== -*/ -int CSCR_LoadDefaultCVars( const char *scriptfilename ) +static int CSCR_ParseFile( const char *scriptfilename, + void (*callback)( scrvardef_t *var, void * ), void *userdata ) { parserstate_t state = { 0 }; qboolean success = false; @@ -305,7 +237,7 @@ int CSCR_LoadDefaultCVars( const char *scriptfilename ) // Create a new object if( CSCR_ParseSingleCvar( &state, &var ) ) { - Cvar_Get( var.name, var.value, var.flags|FCVAR_TEMPORARY, var.desc ); + callback( &var, userdata ); count++; } else @@ -331,3 +263,47 @@ finish: return count; } + +static void CSCR_WriteVariableToFile( scrvardef_t *var, void *file ) +{ + file_t *cfg = (file_t*)file; + convar_t *cvar = Cvar_FindVar( var->name ); + + if( cvar && !FBitSet( cvar->flags, FCVAR_SERVER|FCVAR_ARCHIVE )) + { + // cvars will be placed in game.cfg and restored on map start + if( var->flags & FCVAR_USERINFO ) + FS_Printf( cfg, "setinfo %s \"%s\"\n", var->name, cvar->string ); + else FS_Printf( cfg, "%s \"%s\"\n", var->name, cvar->string ); + } +} + +/* +====================== +CSCR_WriteGameCVars + +Print all cvars declared in script to game.cfg file +====================== +*/ +int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename ) +{ + return CSCR_ParseFile( scriptfilename, CSCR_WriteVariableToFile, cfg ); +} + +static void CSCR_RegisterVariable( scrvardef_t *var, void *unused ) +{ + if( !Cvar_FindVar( var->name )) + Cvar_Get( var->name, var->value, var->flags|FCVAR_TEMPORARY, var->desc ); +} + +/* +====================== +CSCR_LoadDefaultCVars + +Register all cvars declared in config file and set default values +====================== +*/ +int CSCR_LoadDefaultCVars( const char *scriptfilename ) +{ + return CSCR_ParseFile( scriptfilename, CSCR_RegisterVariable, NULL ); +} diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 7d058910..8e7b0a57 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -545,7 +545,7 @@ cmd_t *GAME_EXPORT Cmd_GetNextFunctionHandle( cmd_t *cmd ) Cmd_GetName ============ */ -char *GAME_EXPORT Cmd_GetName( cmd_t *cmd ) +const char *GAME_EXPORT Cmd_GetName( cmd_t *cmd ) { return cmd->name; } diff --git a/engine/common/common.c b/engine/common/common.c index 40096a41..8b694e77 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -521,6 +521,12 @@ skipwhite: } data++; + if( c == '\\' && *data == '"' ) + { + token[len++] = (byte)*data++; + continue; + } + if( c == '\"' ) { token[len] = 0; @@ -836,7 +842,7 @@ Cache_Check consistency check ==================== */ -void *Cache_Check( byte *mempool, cache_user_t *c ) +void *Cache_Check( poolhandle_t mempool, cache_user_t *c ) { if( !c->data ) return NULL; @@ -1171,7 +1177,7 @@ qboolean COM_IsSafeFileToDownload( const char *filename ) return true; } -char *_copystring( byte *mempool, const char *s, const char *filename, int fileline ) +char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline ) { char *b; diff --git a/engine/common/common.h b/engine/common/common.h index c3af0c9b..c5f962f9 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -325,11 +325,12 @@ typedef struct typedef struct host_redirect_s { - rdtype_t target; - char *buffer; - int buffersize; - netadr_t address; - void (*flush)( netadr_t adr, rdtype_t target, char *buffer ); + rdtype_t target; + char *buffer; + size_t buffersize; + netadr_t address; + void (*flush)( netadr_t adr, rdtype_t target, char *buffer ); + int lines; } host_redirect_t; typedef struct @@ -391,7 +392,7 @@ typedef struct host_parm_s uint type; // running at jmp_buf abortframe; // abort current frame dword errorframe; // to prevent multiple host error - byte *mempool; // static mempool for misc allocations + poolhandle_t mempool; // static mempool for misc allocations string finalmsg; // server shutdown final message string downloadfile; // filename to be downloading int downloadcount; // how many files remain to downloading @@ -445,8 +446,8 @@ typedef struct host_parm_s char rootdir[MAX_OSPATH]; // member root directory char rodir[MAX_OSPATH]; // readonly root char gamefolder[MAX_QPATH]; // it's a default gamefolder - byte *imagepool; // imagelib mempool - byte *soundpool; // soundlib mempool + poolhandle_t imagepool; // imagelib mempool + poolhandle_t soundpool; // soundlib mempool uint features; // custom features that enables by mod-maker request @@ -504,14 +505,14 @@ void Cmd_ForwardToServer( void ); // zone.c // void Memory_Init( void ); -void *_Mem_Realloc( byte *poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ); -void *_Mem_Alloc( byte *poolptr, size_t size, qboolean clear, const char *filename, int fileline ); -byte *_Mem_AllocPool( const char *name, const char *filename, int fileline ); -void _Mem_FreePool( byte **poolptr, const char *filename, int fileline ); -void _Mem_EmptyPool( byte *poolptr, const char *filename, int fileline ); +void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ); +void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ); +poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline ); +void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline ); +void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline ); void _Mem_Free( void *data, const char *filename, int fileline ); void _Mem_Check( const char *filename, int fileline ); -qboolean Mem_IsAllocatedExt( byte *poolptr, void *data ); +qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data ); void Mem_PrintList( size_t minallocationsize ); void Mem_PrintStats( void ); @@ -745,7 +746,7 @@ cvar_t *pfnCVarGetPointer( const char *szVarName ); int pfnDrawConsoleString( int x, int y, char *string ); void pfnDrawSetTextColor( float r, float g, float b ); void pfnDrawConsoleStringLen( const char *pText, int *length, int *height ); -void *Cache_Check( byte *mempool, struct cache_user_s *c ); +void *Cache_Check( poolhandle_t mempool, struct cache_user_s *c ); void COM_TrimSpace( const char *source, char *dest ); edict_t* pfnPEntityOfEntIndex( int iEntIndex ); void pfnGetModelBounds( model_t *mod, float *mins, float *maxs ); @@ -764,7 +765,7 @@ float pfnTime( void ); #define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ ) #define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ ) #define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; } -char *_copystring( byte *mempool, const char *s, const char *filename, int fileline ); +char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline ); // CS:CS engfuncs (stubs) void *pfnSequenceGet( const char *fileName, const char *entryName ); @@ -858,7 +859,7 @@ int COM_ExpandFilename( const char *fileName, char *nameOutBuffer, int nameOutBu struct cmd_s *Cmd_GetFirstFunctionHandle( void ); struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd ); struct cmdalias_s *Cmd_AliasGetList( void ); -char *Cmd_GetName( struct cmd_s *cmd ); +const char *Cmd_GetName( struct cmd_s *cmd ); struct pmtrace_s *PM_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe ); void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch ); void SV_StartMusic( const char *curtrack, const char *looptrack, int position ); @@ -947,6 +948,7 @@ void VID_Init( void ); void UI_SetActiveMenu( qboolean fActive ); void UI_ShowConnectionWarning( void ); void Cmd_Null_f( void ); +void Rcon_Print( const char *pMsg ); // soundlib shared exports qboolean S_Init( void ); diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index e09fae3c..c90d10b1 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -876,7 +876,7 @@ qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir ) if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "bsp" )) continue; - if( use_filter && !Q_strnicmp( t->filenames[i], mpfilter, size)) + if( use_filter && !Q_stristr( t->filenames[i], mpfilter )) continue; f = FS_Open( t->filenames[i], "rb", onlyingamedir ); diff --git a/engine/common/cvar.h b/engine/common/cvar.h index ce65e6b3..1eb5b1ee 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -45,8 +45,12 @@ typedef struct convar_s #define FCVAR_TEMPORARY (1<<21) // these cvars holds their values and can be unlink in any time #define FCVAR_LOCALONLY (1<<22) // can be set only from local buffers -#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) convar_t cv = { cvname, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc } -#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) convar_t cv = { #cv, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc } +#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \ + convar_t cv = { cvname, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc, NULL } + +#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) \ + CVAR_DEFINE( cv, #cv, cvstr, cvflags, cvdesc ) + #define CVAR_TO_BOOL( x ) ((x) && ((x)->value != 0.0f) ? true : false ) cvar_t *Cvar_GetList( void ); diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index 26ec7878..5b3495b7 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -81,10 +81,10 @@ typedef struct wadtype_s struct file_s { int handle; // file descriptor + int ungetc; // single stored character from ungetc, cleared to EOF when read fs_offset_t real_length; // uncompressed file size (for files opened in "read" mode) fs_offset_t position; // current position in the file fs_offset_t offset; // offset into the package (0 if external file) - int ungetc; // single stored character from ungetc, cleared to EOF when read time_t filetime; // pak, wad or real filetime // contents buffer fs_offset_t buff_ind, buff_len; // buffer current index and length @@ -100,8 +100,8 @@ struct wfile_s { string filename; int infotableofs; - byte *mempool; // W_ReadLump temp buffers int numlumps; + poolhandle_t mempool; // W_ReadLump temp buffers file_t *handle; dlumpinfo_t *lumps; time_t filetime; @@ -144,7 +144,7 @@ typedef struct searchpath_s struct searchpath_s *next; } searchpath_t; -static byte *fs_mempool; +static poolhandle_t fs_mempool; static searchpath_t *fs_searchpaths = NULL; // chain static searchpath_t fs_directpath; // static direct path static char fs_basedir[MAX_SYSPATH]; // base game directory @@ -1821,7 +1821,7 @@ static qboolean FS_ParseLiblistGam( const char *filename, const char *gamedir, g char *afile; if( !GameInfo ) return false; - afile = (char *)FS_LoadFile( filename, NULL, false ); + afile = (char *)FS_LoadDirectFile( filename, NULL ); if( !afile ) return false; FS_InitGameInfo( GameInfo, gamedir ); @@ -1922,6 +1922,8 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo ) string filepath_ro, liblist_ro; fs_offset_t roLibListTime, roGameInfoTime, rwGameInfoTime; + FS_AllowDirectPaths( true ); + Q_snprintf( filepath_ro, sizeof( filepath_ro ), "%s/%s/gameinfo.txt", host.rodir, gamedir ); Q_snprintf( liblist_ro, sizeof( liblist_ro ), "%s/%s/liblist.gam", host.rodir, gamedir ); @@ -1949,6 +1951,8 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo ) Mem_Free( afile_ro ); } } + + FS_AllowDirectPaths( false ); } // if user change liblist.gam update the gameinfo.txt @@ -2344,7 +2348,10 @@ file_t *FS_OpenZipFile( zip_t *zip, int pack_ind ) // compressed files handled in Zip_LoadFile if( pfile->flags != ZIP_COMPRESSION_NO_COMPRESSION ) + { + Con_Printf( S_ERROR "%s: can't open compressed file %s", __FUNCTION__, pfile->name ); return NULL; + } return FS_OpenHandle( zip->filename, zip->handle, pfile->offset, pfile->size ); } diff --git a/engine/common/imagelib/img_png.c b/engine/common/imagelib/img_png.c index bdc1230f..9569a241 100644 --- a/engine/common/imagelib/img_png.c +++ b/engine/common/imagelib/img_png.c @@ -427,12 +427,10 @@ qboolean Image_SavePNG( const char *name, rgbdata_t *pix ) // get image description switch( pix->type ) { - case PF_RGB_24: - pixel_size = 3; - break; - case PF_RGBA_32: - pixel_size = 4; - break; + case PF_BGR_24: + case PF_RGB_24: pixel_size = 3; break; + case PF_BGRA_32: + case PF_RGBA_32: pixel_size = 4; break; default: return false; } @@ -443,19 +441,48 @@ qboolean Image_SavePNG( const char *name, rgbdata_t *pix ) filtered_size = ( rowsize + 1 ) * pix->height; out = filtered_buffer = Mem_Malloc( host.imagepool, filtered_size ); - in = pix->buffer; // apply adaptive filter to image - for( y = 0; y < pix->height; y++ ) + switch( pix->type ) { - *out++ = PNG_F_NONE; - rowend = in + rowsize; - for( ; in < rowend; ) + case PF_RGB_24: + case PF_RGBA_32: + for( y = 0; y < pix->height; y++ ) { - *out++ = *in++; + in = pix->buffer + y * pix->width * pixel_size; + *out++ = PNG_F_NONE; + rowend = in + rowsize; + for( ; in < rowend; in += pixel_size ) + { + *out++ = in[0]; + *out++ = in[1]; + *out++ = in[2]; + if( pix->flags & IMAGE_HAS_ALPHA ) + *out++ = in[3]; + } } + break; + case PF_BGR_24: + case PF_BGRA_32: + for( y = 0; y < pix->height; y++ ) + { + in = pix->buffer + y * pix->width * pixel_size; + *out++ = PNG_F_NONE; + rowend = in + rowsize; + for( ; in < rowend; in += pixel_size ) + { + *out++ = in[2]; + *out++ = in[1]; + *out++ = in[0]; + if( pix->flags & IMAGE_HAS_ALPHA ) + *out++ = in[3]; + } + } + break; } + + // get IHDR chunk length ihdr_len = sizeof( png_ihdr_t ); diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index c6a4978c..da8443ad 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -1305,7 +1305,7 @@ static void Mod_MakeHull0( void ) Mod_SetupHull ================= */ -static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, byte *mempool, int headnode, int hullnum ) +static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, poolhandle_t mempool, int headnode, int hullnum ) { hull_t *hull = &mod->hulls[hullnum]; int count; @@ -1469,7 +1469,7 @@ for embedded submodels static void Mod_SetupSubmodels( dbspmodel_t *bmod ) { qboolean colored = false; - byte *mempool; + poolhandle_t mempool; char *ents; model_t *mod; dmodel_t *bm; @@ -1550,7 +1550,7 @@ static void Mod_SetupSubmodels( dbspmodel_t *bmod ) loadmodel = Mod_FindName( name, true ); *loadmodel = *mod; Q_strncpy( loadmodel->name, name, sizeof( loadmodel->name )); - loadmodel->mempool = NULL; + loadmodel->mempool = 0; mod = loadmodel; } } diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 7b1d8cdf..0a794e5f 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -117,7 +117,7 @@ typedef struct world_static_s #ifndef REF_DLL extern world_static_t world; -extern byte *com_studiocache; +extern poolhandle_t com_studiocache; extern model_t *loadmodel; extern convar_t *mod_studiocache; extern convar_t *r_wadtextures; diff --git a/engine/common/model.c b/engine/common/model.c index 9075676d..1b75a2df 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -27,7 +27,7 @@ GNU General Public License for more details. static model_info_t mod_crcinfo[MAX_MODELS]; static model_t mod_known[MAX_MODELS]; static int mod_numknown = 0; -byte *com_studiocache; // cache for submodels +poolhandle_t com_studiocache; // cache for submodels convar_t *mod_studiocache; convar_t *r_wadtextures; convar_t *r_showhull; diff --git a/engine/common/net_buffer.c b/engine/common/net_buffer.c index 067d6047..ebf58599 100644 --- a/engine/common/net_buffer.c +++ b/engine/common/net_buffer.c @@ -27,7 +27,7 @@ GNU General Public License for more details. static dword BitWriteMasks[32][33]; static dword ExtraMasks[32]; -short MSG_BigShort( short swap ) +unsigned short MSG_BigShort( unsigned short swap ) { return (swap >> 8)|(swap << 8); } @@ -214,11 +214,11 @@ void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits ) } } -void MSG_WriteBitLong( sizebuf_t *sb, int data, int numbits, qboolean bSigned ) +void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned ) { if( bSigned ) - MSG_WriteSBitLong( sb, data, numbits ); - else MSG_WriteUBitLong( sb, (uint)data, numbits ); + MSG_WriteSBitLong( sb, (int)data, numbits ); + else MSG_WriteUBitLong( sb, data, numbits ); } qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits ) diff --git a/engine/common/net_buffer.h b/engine/common/net_buffer.h index 1d662da2..50cb7361 100644 --- a/engine/common/net_buffer.h +++ b/engine/common/net_buffer.h @@ -63,7 +63,7 @@ void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove ); _inline int MSG_TellBit( sizebuf_t *sb ) { return sb->iCurBit; } _inline const char *MSG_GetName( sizebuf_t *sb ) { return sb->pDebugName; } qboolean MSG_CheckOverflow( sizebuf_t *sb ); -short MSG_BigShort( short swap ); +unsigned short MSG_BigShort( unsigned short swap ); // init writing void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits ); @@ -73,7 +73,7 @@ void MSG_Clear( sizebuf_t *sb ); void MSG_WriteOneBit( sizebuf_t *sb, int nValue ); void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits ); void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits ); -void MSG_WriteBitLong( sizebuf_t *sb, int data, int numbits, qboolean bSigned ); +void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned ); qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits ); void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits ); void MSG_WriteBitFloat( sizebuf_t *sb, float val ); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 8b097959..ea65e1ea 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -87,13 +87,12 @@ unacknowledged reliable convar_t *net_showpackets; convar_t *net_chokeloopback; convar_t *net_showdrop; -convar_t *net_speeds; convar_t *net_qport; int net_drop; netadr_t net_from; sizebuf_t net_message; -byte *net_mempool; +static poolhandle_t net_mempool; byte net_message_buffer[NET_MAX_MESSAGE]; const char *ns_strings[NS_COUNT] = @@ -252,7 +251,6 @@ void Netchan_Init( void ) net_showpackets = Cvar_Get ("net_showpackets", "0", 0, "show network packets" ); net_chokeloopback = Cvar_Get( "net_chokeloop", "0", 0, "apply bandwidth choke to loopback packets" ); net_showdrop = Cvar_Get( "net_showdrop", "0", 0, "show packets that are dropped" ); - net_speeds = Cvar_Get( "net_speeds", "0", FCVAR_ARCHIVE, "show network packets" ); net_qport = Cvar_Get( "net_qport", va( "%i", port ), FCVAR_READ_ONLY, "current quake netport" ); net_mempool = Mem_AllocPool( "Network Pool" ); diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index 47deff99..cfc1ecca 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -904,7 +904,7 @@ int Delta_ClampIntegerField( delta_t *pField, int iValue, qboolean bSigned, int { int signbits = bSigned ? (numbits - 1) : numbits; int maxnum = BIT( signbits ) - 1; - int minnum = bSigned ? -maxnum : 0; + int minnum = bSigned ? ( -maxnum - 1 ) : 0; iValue = bound( minnum, iValue, maxnum ); } @@ -989,7 +989,6 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba #if defined __GNUC__ && __GNUC_MAJOR < 9 && !defined __clang__ #pragma GCC diagnostic pop #endif - fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits ); if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; @@ -1126,21 +1125,37 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to if( pField->flags & DT_BYTE ) { - iValue = *(byte *)((byte *)to + pField->offset ); + if( bSigned ) + iValue = *(int8_t *)((int8_t *)to + pField->offset ); + else + iValue = *(uint8_t *)((int8_t *)to + pField->offset ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); } else if( pField->flags & DT_SHORT ) { - iValue = *(word *)((byte *)to + pField->offset ); + if( bSigned ) + iValue = *(int16_t *)((int8_t *)to + pField->offset ); + else + iValue = *(uint16_t *)((int8_t *)to + pField->offset ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); } else if( pField->flags & DT_INTEGER ) { - iValue = *(uint *)((byte *)to + pField->offset ); +#if defined __GNUC__ && __GNUC_MAJOR < 9 && !defined __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wduplicated-branches" +#endif + if( bSigned ) + iValue = *(int32_t *)((int8_t *)to + pField->offset ); + else + iValue = *(uint32_t *)((int8_t *)to + pField->offset ); +#if defined __GNUC__ && __GNUC_MAJOR < 9 && !defined __clang__ +#pragma GCC diagnostic pop +#endif iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits ); if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); @@ -1214,9 +1229,15 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, } else { - iValue = *(byte *)((byte *)from + pField->offset ); + if( bSigned ) + iValue = *(int8_t *)((uint8_t *)from + pField->offset ); + else + iValue = *(uint8_t *)((uint8_t *)from + pField->offset ); } - *(byte *)((byte *)to + pField->offset ) = iValue; + if( bSigned ) + *(int8_t *)((uint8_t *)to + pField->offset ) = iValue; + else + *(uint8_t *)((uint8_t *)to + pField->offset ) = iValue; } else if( pField->flags & DT_SHORT ) { @@ -1227,12 +1248,22 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, } else { - iValue = *(word *)((byte *)from + pField->offset ); + if( bSigned ) + iValue = *(int16_t *)((uint8_t *)from + pField->offset ); + else + iValue = *(uint16_t *)((uint8_t *)from + pField->offset ); } - *(word *)((byte *)to + pField->offset ) = iValue; + if( bSigned ) + *(int16_t *)((uint8_t *)to + pField->offset ) = iValue; + else + *(uint16_t *)((uint8_t *)to + pField->offset ) = iValue; } else if( pField->flags & DT_INTEGER ) { +#if defined __GNUC__ && __GNUC_MAJOR < 9 && !defined __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wduplicated-branches" +#endif if( bChanged ) { iValue = MSG_ReadBitLong( msg, pField->bits, bSigned ); @@ -1240,9 +1271,18 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, } else { - iValue = *(uint *)((byte *)from + pField->offset ); + if( bSigned ) + iValue = *(int32_t *)((uint8_t *)from + pField->offset ); + else + iValue = *(uint32_t *)((uint8_t *)from + pField->offset ); } - *(uint *)((byte *)to + pField->offset ) = iValue; + if( bSigned ) + *(int32_t *)((uint8_t *)to + pField->offset ) = iValue; + else + *(uint32_t *)((uint8_t *)to + pField->offset ) = iValue; +#if defined __GNUC__ && __GNUC_MAJOR < 9 && !defined __clang__ +#pragma GCC diagnostic pop +#endif } else if( pField->flags & DT_FLOAT ) { @@ -1830,7 +1870,7 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state } else { - baseline_offset = abs( baseline_offset ); + baseline_offset = abs( baseline_offset + 1 ); if( baseline_offset < cl.instanced_baseline_count ) from = &cl.instanced_baseline[baseline_offset]; } diff --git a/engine/common/netchan.h b/engine/common/netchan.h index 3980090e..f3205795 100644 --- a/engine/common/netchan.h +++ b/engine/common/netchan.h @@ -282,7 +282,6 @@ extern netadr_t net_from; extern netadr_t net_local; extern sizebuf_t net_message; extern byte net_message_buffer[NET_MAX_MESSAGE]; -extern convar_t *net_speeds; extern convar_t sv_lan; extern convar_t sv_lan_rate; extern int net_drop; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index ea63d8f1..f2321459 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -318,7 +318,11 @@ extern const char *clc_strings[clc_lastmsg+1]; #define MAX_LEGACY_ENTITY_BITS 12 #define MAX_LEGACY_WEAPON_BITS 5 #define MAX_LEGACY_MODEL_BITS 11 -#define MAX_LEGACY_SERVERS 32 +#if XASH_LOW_MEMORY >= 1 +#define MAX_LEGACY_SERVERS 32 +#else +#define MAX_LEGACY_SERVERS 256 +#endif #define MAX_LEGACY_TOTAL_CMDS 28 // magic number from old engine's sv_client.c #endif//NET_PROTOCOL_H diff --git a/engine/common/soundlib/snd_utils.c b/engine/common/soundlib/snd_utils.c index 5c9d53b6..e6ffd977 100644 --- a/engine/common/soundlib/snd_utils.c +++ b/engine/common/soundlib/snd_utils.c @@ -95,14 +95,14 @@ byte *Sound_Copy( size_t size ) uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath ) { - file_t *f; - wavehdr_t wav; - size_t filesize; - float seconds; - uint samples; + file_t *f; + wavehdr_t wav; + size_t filesize; + uint msecs; f = FS_Open( filepath, "rb", false ); - if( !f ) return 0; + if( !f ) + return 0; if( FS_Read( f, &wav, sizeof( wav )) != sizeof( wav )) { @@ -111,7 +111,7 @@ uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath ) } filesize = FS_FileLength( f ); - filesize -= ( sizeof( wavehdr_t ) + sizeof( chunkhdr_t )); + filesize -= 128; // magic number from GoldSrc, seems to be header size FS_Close( f ); @@ -119,21 +119,11 @@ uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath ) if( wav.riff_id != RIFFHEADER || wav.wave_id != WAVEHEADER || wav.fmt_id != FORMHEADER ) return 0; - if( wav.wFormatTag != 1 ) - return 0; + if( wav.nAvgBytesPerSec >= 1000 ) + msecs = (uint)((float)filesize / ((float)wav.nAvgBytesPerSec / 1000.0f)); + else msecs = (uint)(((float)filesize / (float)wav.nAvgBytesPerSec) * 1000.0f); - if( wav.nChannels != 1 && wav.nChannels != 2 ) - return 0; - - if( wav.nBitsPerSample != 8 && wav.nBitsPerSample != 16 ) - return 0; - - // calc samplecount - seconds = (float)filesize / wav.nAvgBytesPerSec / wav.nChannels; - samples = (uint)(( wav.nSamplesPerSec * wav.nChannels ) * seconds ); - - // g-cont. this function returns samplecount or time in milliseconds ??? - return (uint)(seconds * 1000); + return msecs; } /* diff --git a/engine/common/soundlib/soundlib.h b/engine/common/soundlib/soundlib.h index bcdcbf60..9ce2af46 100644 --- a/engine/common/soundlib/soundlib.h +++ b/engine/common/soundlib/soundlib.h @@ -94,23 +94,23 @@ struct stream_s typedef struct { - int riff_id; // 'RIFF' - int rLen; - int wave_id; // 'WAVE' - int fmt_id; // 'fmt ' - int pcm_header_len; // varies... - short wFormatTag; - short nChannels; // 1,2 for stereo data is (l,r) pairs - int nSamplesPerSec; - int nAvgBytesPerSec; - short nBlockAlign; - short nBitsPerSample; + int32_t riff_id; // 'RIFF' + int32_t rLen; + int32_t wave_id; // 'WAVE' + int32_t fmt_id; // 'fmt ' + int32_t pcm_header_len; // varies... + int16_t wFormatTag; + int16_t nChannels; // 1,2 for stereo data is (l,r) pairs + int32_t nSamplesPerSec; + int32_t nAvgBytesPerSec; + int16_t nBlockAlign; + int16_t nBitsPerSample; } wavehdr_t; typedef struct { - int data_id; // 'data' or 'fact' - int dLen; + int32_t data_id; // 'data' or 'fact' + int32_t dLen; } chunkhdr_t; extern sndlib_t sound; diff --git a/engine/common/sys_con.c b/engine/common/sys_con.c index 0f30ef9f..1f29cb83 100644 --- a/engine/common/sys_con.c +++ b/engine/common/sys_con.c @@ -22,10 +22,10 @@ GNU General Public License for more details. #define XASH_COLORIZE_CONSOLE // use with caution, running engine in Qt Creator may cause a freeze in read() call // I was never encountered this bug anywhere else, so still enable by default -// #define XASH_USE_SELECT +// #define XASH_USE_SELECT 1 #endif -#ifdef XASH_USE_SELECT +#if XASH_USE_SELECT // non-blocking console input #include #endif @@ -42,7 +42,7 @@ static LogData s_ld; char *Sys_Input( void ) { -#ifdef XASH_USE_SELECT +#if XASH_USE_SELECT { fd_set rfds; static char line[1024]; diff --git a/engine/common/system.c b/engine/common/system.c index 7d42ded7..aaa600e4 100644 --- a/engine/common/system.c +++ b/engine/common/system.c @@ -553,5 +553,5 @@ void Sys_Print( const char *pMsg ) Sys_PrintLog( pMsg ); - // Rcon_Print( pMsg ); + Rcon_Print( pMsg ); } diff --git a/engine/common/zone.c b/engine/common/zone.c index 03d70fb5..f3200ed1 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -50,19 +50,44 @@ typedef struct mempool_s struct mempool_s *next; // linked into global mempool list const char *filename; // file name and line where Mem_AllocPool was called int fileline; + poolhandle_t idx; char name[64]; // name of the pool uint sentinel2; // should always be MEMHEADER_SENTINEL1 } mempool_t; -mempool_t *poolchain = NULL; // critical stuff +static mempool_t *poolchain = NULL; // critical stuff -void *_Mem_Alloc( byte *poolptr, size_t size, qboolean clear, const char *filename, int fileline ) +// a1ba: due to mempool being passed with the model through reused 32-bit field +// which makes engine incompatible with 64-bit pointers I changed mempool type +// from pointer to 32-bit handle, thankfully mempool structure is private +// But! Mempools are handled through linked list so we can't index them safely +static uint lastidx = 0; + +static mempool_t *Mem_FindPool( poolhandle_t poolptr ) { - memheader_t *mem; - mempool_t *pool = (mempool_t *)poolptr; + mempool_t *pool; + + for( pool = poolchain; pool; pool = pool->next ) + { + if( pool->idx == poolptr ) + return pool; + } + + Sys_Error( "%s: not allocated or double freed pool %d", __FUNCTION__, poolptr ); + + return NULL; +} + +void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) +{ + memheader_t *mem; + mempool_t *pool; if( size <= 0 ) return NULL; - if( poolptr == NULL ) Sys_Error( "Mem_Alloc: pool == NULL (alloc at %s:%i)\n", filename, fileline ); + if( !poolptr ) Sys_Error( "Mem_Alloc: pool == NULL (alloc at %s:%i)\n", filename, fileline ); + + pool = Mem_FindPool( poolptr ); + pool->totalsize += size; // big allocations are not clumped @@ -147,7 +172,7 @@ void _Mem_Free( void *data, const char *filename, int fileline ) Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline ); } -void *_Mem_Realloc( byte *poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) +void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) { memheader_t *memhdr = NULL; char *nb; @@ -172,12 +197,16 @@ void *_Mem_Realloc( byte *poolptr, void *memptr, size_t size, qboolean clear, co return (void *)nb; } -byte *_Mem_AllocPool( const char *name, const char *filename, int fileline ) +poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline ) { mempool_t *pool; pool = (mempool_t *)Q_malloc( sizeof( mempool_t )); - if( pool == NULL ) Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline ); + if( pool == NULL ) + { + Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline ); + return 0; + } memset( pool, 0, sizeof( mempool_t )); // fill header @@ -190,17 +219,18 @@ byte *_Mem_AllocPool( const char *name, const char *filename, int fileline ) pool->realsize = sizeof( mempool_t ); Q_strncpy( pool->name, name, sizeof( pool->name )); pool->next = poolchain; + pool->idx = ++lastidx; poolchain = pool; - return (byte *)pool; + return pool->idx; } -void _Mem_FreePool( byte **poolptr, const char *filename, int fileline ) +void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline ) { - mempool_t *pool = (mempool_t *)*poolptr; + mempool_t *pool; mempool_t **chainaddress; - if( pool ) + if( *poolptr && ( pool = Mem_FindPool( *poolptr ))) { // unlink pool from chain for( chainaddress = &poolchain; *chainaddress && *chainaddress != pool; chainaddress = &((*chainaddress)->next)); @@ -214,14 +244,14 @@ void _Mem_FreePool( byte **poolptr, const char *filename, int fileline ) // free the pool itself memset( pool, 0xBF, sizeof( mempool_t )); Q_free( pool ); - *poolptr = NULL; + *poolptr = 0; } } -void _Mem_EmptyPool( byte *poolptr, const char *filename, int fileline ) +void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline ) { - mempool_t *pool = (mempool_t *)poolptr; - if( poolptr == NULL ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline ); + mempool_t *pool = Mem_FindPool( poolptr ); + if( !poolptr ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline ); if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline ); @@ -230,7 +260,7 @@ void _Mem_EmptyPool( byte *poolptr, const char *filename, int fileline ) while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline ); } -qboolean Mem_CheckAlloc( mempool_t *pool, void *data ) +static qboolean Mem_CheckAlloc( mempool_t *pool, void *data ) { memheader_t *header, *target; @@ -256,15 +286,15 @@ qboolean Mem_CheckAlloc( mempool_t *pool, void *data ) Check pointer for memory ======================== */ -qboolean Mem_IsAllocatedExt( byte *poolptr, void *data ) +qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data ) { mempool_t *pool = NULL; - if( poolptr ) pool = (mempool_t *)poolptr; + if( poolptr ) pool = Mem_FindPool( poolptr ); return Mem_CheckAlloc( pool, data ); } -void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline ) +static void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline ) { memheader_t *mem; @@ -288,8 +318,8 @@ void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline ) void _Mem_Check( const char *filename, int fileline ) { - memheader_t *mem; - mempool_t *pool; + memheader_t *mem; + mempool_t *pool; for( pool = poolchain; pool; pool = pool->next ) { @@ -306,8 +336,8 @@ void _Mem_Check( const char *filename, int fileline ) void Mem_PrintStats( void ) { - size_t count = 0, size = 0, realsize = 0; - mempool_t *pool; + size_t count = 0, size = 0, realsize = 0; + mempool_t *pool; Mem_Check(); for( pool = poolchain; pool; pool = pool->next ) diff --git a/engine/eiface.h b/engine/eiface.h index 932a42ff..3e1032e1 100644 --- a/engine/eiface.h +++ b/engine/eiface.h @@ -264,7 +264,7 @@ typedef struct enginefuncs_s void* (*pfnSequenceGet) ( const char* fileName, const char* entryName ); void* (*pfnSequencePickSentence) ( const char* groupName, int pickMethod, int *picked ); - int (*pfnGetFileSize) ( char *filename ); + int (*pfnGetFileSize) ( const char *filename ); unsigned int (*pfnGetApproxWavePlayLen) (const char *filepath); int (*pfnIsCareerMatch) ( void ); int (*pfnGetLocalizedStringLength) (const char *label); diff --git a/engine/platform/android/snd_opensles.c b/engine/platform/android/snd_opensles.c index 09f3821d..012d9313 100644 --- a/engine/platform/android/snd_opensles.c +++ b/engine/platform/android/snd_opensles.c @@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "pthread.h" #include "sound.h" -extern convar_t *s_primary; extern dma_t dma; static SLObjectItf snddma_android_engine = NULL; @@ -36,7 +35,6 @@ static SLPlayItf snddma_android_play; static pthread_mutex_t snddma_android_mutex = PTHREAD_MUTEX_INITIALIZER; -static int snddma_android_pos; static int snddma_android_size; static const SLInterfaceID *pSL_IID_ENGINE; @@ -64,8 +62,6 @@ void SNDDMA_Activate( qboolean active ) } else { - //if( s_globalfocus->integer ) - //return; (*snddma_android_play)->SetPlayState( snddma_android_play, SL_PLAYSTATE_STOPPED ); (*snddma_android_bufferQueue)->Clear( snddma_android_bufferQueue ); } @@ -81,7 +77,7 @@ static void SNDDMA_Android_Callback( SLBufferQueueItf bq, void *context ) (*bq)->Enqueue( bq, buffer2, snddma_android_size ); memcpy( buffer2, dma.buffer, snddma_android_size ); memset( dma.buffer, 0, snddma_android_size ); - snddma_android_pos += dma.samples; + dma.samplepos += dma.samples; pthread_mutex_unlock( &snddma_android_mutex ); } @@ -175,7 +171,7 @@ static const char *SNDDMA_Android_Init( void ) result = (*snddma_android_bufferQueue)->RegisterCallback( snddma_android_bufferQueue, SNDDMA_Android_Callback, NULL ); if( result != SL_RESULT_SUCCESS ) return "bufferQueue->RegisterCallback"; - samples = s_samplecount->value; + samples = s_samplecount.value; if( !samples ) samples = 4096; @@ -191,7 +187,6 @@ static const char *SNDDMA_Android_Init( void ) //snddma_android_mutex = trap_Mutex_Create(); - snddma_android_pos = 0; dma.initialized = true; SNDDMA_Activate( true ); @@ -218,11 +213,6 @@ qboolean SNDDMA_Init( void ) return true; } -int SNDDMA_GetDMAPos( void ) -{ - return snddma_android_pos; -} - void SNDDMA_Shutdown( void ) { Msg( "Closing OpenSL ES audio device...\n" ); @@ -264,42 +254,4 @@ void SNDDMA_BeginPainting( void ) { pthread_mutex_lock( &snddma_android_mutex ); } - - -/* -============== -SNDDMA_GetSoundtime - -update global soundtime -=============== -*/ -int SNDDMA_GetSoundtime( void ) -{ - static int buffers, oldsamplepos; - int samplepos, fullsamples; - - fullsamples = dma.samples / 2; - - // it is possible to miscount buffers - // if it has wrapped twice between - // calls to S_Update. Oh well. - samplepos = SNDDMA_GetDMAPos(); - - if( samplepos < oldsamplepos ) - { - buffers++; // buffer wrapped - - if( paintedtime > 0x40000000 ) - { - // time to chop things off to avoid 32 bit limits - buffers = 0; - paintedtime = fullsamples; - S_StopAllSounds( true ); - } - } - - oldsamplepos = samplepos; - - return (buffers * fullsamples + samplepos / 2); -} #endif diff --git a/engine/platform/linux/s_alsa.c b/engine/platform/linux/s_alsa.c index 85a0332f..4cddee95 100644 --- a/engine/platform/linux/s_alsa.c +++ b/engine/platform/linux/s_alsa.c @@ -198,58 +198,6 @@ qboolean SNDDMA_Init( void ) return true; } -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos( void ) -{ - return dma.samplepos; -} - -/* -============== -SNDDMA_GetSoundtime - -update global soundtime -=============== -*/ -int SNDDMA_GetSoundtime( void ) -{ - static int buffers, oldsamplepos; - int samplepos, fullsamples; - - fullsamples = dma.samples / 2; - - // it is possible to miscount buffers - // if it has wrapped twice between - // calls to S_Update. Oh well. - samplepos = SNDDMA_GetDMAPos( ); - - if( samplepos < oldsamplepos ) - { - buffers++; // buffer wrapped - - if( paintedtime > 0x40000000 ) - { - // time to chop things off to avoid 32 bit limits - buffers = 0; - paintedtime = fullsamples; - S_StopAllSounds( true ); - } - } - - oldsamplepos = samplepos; - - return ( buffers * fullsamples + samplepos / 2 ); -} - - /* ============== SNDDMA_Shutdown @@ -376,6 +324,9 @@ between a deactivate and an activate. */ void SNDDMA_Activate( qboolean active ) { + if( !dma.initialized ) + return; + s_alsa.paused = !active; if( !s_alsa.paused ) diff --git a/engine/platform/platform.h b/engine/platform/platform.h index a9472eb0..d10d8ed0 100644 --- a/engine/platform/platform.h +++ b/engine/platform/platform.h @@ -165,7 +165,6 @@ void IN_EvdevFrame ( void ); */ // initializes cycling through a DMA buffer and returns information on it qboolean SNDDMA_Init( void ); -int SNDDMA_GetSoundtime( void ); void SNDDMA_Shutdown( void ); void SNDDMA_BeginPainting( void ); void SNDDMA_Submit( void ); diff --git a/engine/platform/sdl/events.c b/engine/platform/sdl/events.c index 08100be5..59c80192 100644 --- a/engine/platform/sdl/events.c +++ b/engine/platform/sdl/events.c @@ -90,6 +90,21 @@ GNU General Public License for more details. #define SDL_GetScancodeName( x ) "unknown" #endif +static qboolean SDLash_IsInstanceIDAGameController( SDL_JoystickID joyId ) +{ +#if !SDL_VERSION_ATLEAST( 2, 0, 4 ) + // HACKHACK: if we're not initialized g_joy, then we're probably using gamecontroller api + // so return true + if( !g_joy ) + return true; + return false; +#else + if( SDL_GameControllerFromInstanceID( joyId ) ) + return true; + return false; +#endif +} + /* ============= SDLash_KeyEvent @@ -325,8 +340,8 @@ static void SDLash_ActiveEvent( int gain ) if( gain ) { host.status = HOST_FRAME; - IN_ActivateMouse(true); - if( snd_mute_losefocus->value ) + IN_ActivateMouse( true ); + if( dma.initialized && snd_mute_losefocus.value ) { SNDDMA_Activate( true ); } @@ -346,7 +361,7 @@ static void SDLash_ActiveEvent( int gain ) #endif host.status = HOST_NOFOCUS; IN_DeactivateMouse(); - if( snd_mute_losefocus->value ) + if( dma.initialized && snd_mute_losefocus.value ) { SNDDMA_Activate( false ); } @@ -432,23 +447,23 @@ static void SDLash_EventFilter( SDL_Event *event ) /* Joystick events */ case SDL_JOYAXISMOTION: - if ( SDL_GameControllerFromInstanceID( event->jaxis.which ) == NULL ) + if ( !SDLash_IsInstanceIDAGameController( event->jaxis.which )) Joy_AxisMotionEvent( event->jaxis.axis, event->jaxis.value ); break; case SDL_JOYBALLMOTION: - if ( SDL_GameControllerFromInstanceID( event->jball.which ) == NULL ) + if ( !SDLash_IsInstanceIDAGameController( event->jball.which )) Joy_BallMotionEvent( event->jball.ball, event->jball.xrel, event->jball.yrel ); break; case SDL_JOYHATMOTION: - if ( SDL_GameControllerFromInstanceID( event->jhat.which ) == NULL ) + if ( !SDLash_IsInstanceIDAGameController( event->jhat.which )) Joy_HatMotionEvent( event->jhat.hat, event->jhat.value ); break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: - if ( SDL_GameControllerFromInstanceID( event->jbutton.which ) == NULL ) + if ( !SDLash_IsInstanceIDAGameController( event->jbutton.which )) Joy_ButtonEvent( event->jbutton.button, event->jbutton.state ); break; diff --git a/engine/platform/sdl/events.h b/engine/platform/sdl/events.h index 452f7286..1d4a69fc 100644 --- a/engine/platform/sdl/events.h +++ b/engine/platform/sdl/events.h @@ -30,5 +30,8 @@ qboolean GL_UpdateContext( void ); qboolean GL_DeleteContext( void ); void VID_SaveWindowSize( int width, int height ); +// joystick events +extern SDL_Joystick *g_joy; + #endif // XASH_SDL #endif // KEYWRAPPER_H diff --git a/engine/platform/sdl/in_sdl.c b/engine/platform/sdl/in_sdl.c index d4749a75..b2635ea6 100644 --- a/engine/platform/sdl/in_sdl.c +++ b/engine/platform/sdl/in_sdl.c @@ -24,7 +24,7 @@ GNU General Public License for more details. #include "sound.h" #include "vid_common.h" -static SDL_Joystick *joy; +SDL_Joystick *g_joy = NULL; #if !SDL_VERSION_ATLEAST( 2, 0, 0 ) #define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) ) #endif @@ -143,9 +143,9 @@ static int SDLash_JoyInit_Old( int numjoy ) return 0; } - if( joy ) + if( g_joy ) { - SDL_JoystickClose( joy ); + SDL_JoystickClose( g_joy ); } num = SDL_NumJoysticks(); @@ -165,9 +165,9 @@ static int SDLash_JoyInit_Old( int numjoy ) Con_Reportf( "Pass +set joy_index N to command line, where N is number, to select active joystick\n" ); - joy = SDL_JoystickOpen( numjoy ); + g_joy = SDL_JoystickOpen( numjoy ); - if( !joy ) + if( !g_joy ) { Con_Reportf( "Failed to select joystick: %s\n", SDL_GetError( ) ); return 0; @@ -179,8 +179,8 @@ static int SDLash_JoyInit_Old( int numjoy ) "\tHats: %i\n" "\tButtons: %i\n" "\tBalls: %i\n", - SDL_JoystickName( joy ), SDL_JoystickNumAxes( joy ), SDL_JoystickNumHats( joy ), - SDL_JoystickNumButtons( joy ), SDL_JoystickNumBalls( joy ) ); + SDL_JoystickName( g_joy ), SDL_JoystickNumAxes( g_joy ), SDL_JoystickNumHats( g_joy ), + SDL_JoystickNumButtons( g_joy ), SDL_JoystickNumBalls( g_joy ) ); SDL_GameControllerEventState( SDL_DISABLE ); #endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) diff --git a/engine/platform/sdl/s_sdl.c b/engine/platform/sdl/s_sdl.c index 6a260489..8763969c 100644 --- a/engine/platform/sdl/s_sdl.c +++ b/engine/platform/sdl/s_sdl.c @@ -126,7 +126,7 @@ qboolean SNDDMA_Init( void ) dma.format.speed = obtained.freq; dma.format.channels = obtained.channels; dma.format.width = 2; - samplecount = s_samplecount->value; + samplecount = s_samplecount.value; if( !samplecount ) samplecount = 0x8000; dma.samples = samplecount * obtained.channels; @@ -135,9 +135,10 @@ qboolean SNDDMA_Init( void ) Con_Printf( "Using SDL audio driver: %s @ %d Hz\n", SDL_GetCurrentAudioDriver( ), obtained.freq ); + dma.initialized = true; + SNDDMA_Activate( true ); - dma.initialized = true; return true; fail: @@ -145,56 +146,6 @@ fail: return false; } -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos( void ) -{ - return dma.samplepos; -} - -/* -============== -SNDDMA_GetSoundtime - -update global soundtime -=============== -*/ -int SNDDMA_GetSoundtime( void ) -{ - static int buffers, oldsamplepos; - int samplepos, fullsamples; - - fullsamples = dma.samples / 2; - - // it is possible to miscount buffers - // if it has wrapped twice between - // calls to S_Update. Oh well. - samplepos = SNDDMA_GetDMAPos( ); - - if( samplepos < oldsamplepos ) - { - buffers++; // buffer wrapped - - if( paintedtime > 0x40000000 ) - { - // time to chop things off to avoid 32 bit limits - buffers = 0; - paintedtime = fullsamples; - S_StopAllSounds( true ); - } - } - - oldsamplepos = samplepos; - - return ( buffers * fullsamples + samplepos / 2 ); -} /* ============== @@ -264,6 +215,9 @@ between a deactivate and an activate. */ void SNDDMA_Activate( qboolean active ) { + if( !dma.initialized ) + return; + SDL_PauseAudioDevice( sdl_dev, !active ); } #endif // XASH_SOUND == SOUND_SDL diff --git a/engine/platform/stub/s_stub.c b/engine/platform/stub/s_stub.c index f99c2b29..509ae9b7 100644 --- a/engine/platform/stub/s_stub.c +++ b/engine/platform/stub/s_stub.c @@ -51,57 +51,6 @@ qboolean SNDDMA_Init( void ) return false; } -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos( void ) -{ - return dma.samplepos; -} - -/* -============== -SNDDMA_GetSoundtime - -update global soundtime -=============== -*/ -int SNDDMA_GetSoundtime( void ) -{ - static int buffers, oldsamplepos; - int samplepos, fullsamples; - - fullsamples = dma.samples / 2; - - // it is possible to miscount buffers - // if it has wrapped twice between - // calls to S_Update. Oh well. - samplepos = SNDDMA_GetDMAPos(); - - if( samplepos < oldsamplepos ) - { - buffers++; // buffer wrapped - - if( paintedtime > 0x40000000 ) - { - // time to chop things off to avoid 32 bit limits - buffers = 0; - paintedtime = fullsamples; - S_StopAllSounds( true ); - } - } - - oldsamplepos = samplepos; - - return (buffers * fullsamples + samplepos / 2); -} - /* ============== SNDDMA_BeginPainting diff --git a/engine/ref_api.h b/engine/ref_api.h index c3221cf9..084697bf 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -338,9 +338,9 @@ typedef struct ref_api_s // remap struct remap_info_s *(*CL_GetRemapInfoForEntity)( cl_entity_t *e ); - void (*CL_AllocRemapInfo)( cl_entity_t *ent, int topcolor, int bottomcolor ); + void (*CL_AllocRemapInfo)( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor ); void (*CL_FreeRemapInfo)( struct remap_info_s *info ); - void (*CL_UpdateRemapInfo)( cl_entity_t *ent, int topcolor, int bottomcolor ); + void (*CL_UpdateRemapInfo)( cl_entity_t *entity, int topcolor, int bottomcolor ); // utils void (*CL_ExtraUpdate)( void ); @@ -365,10 +365,10 @@ typedef struct ref_api_s int (*pfnGetStudioModelInterface)( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio ); // memory - byte *(*_Mem_AllocPool)( const char *name, const char *filename, int fileline ); - void (*_Mem_FreePool)( byte **poolptr, const char *filename, int fileline ); - void *(*_Mem_Alloc)( byte *poolptr, size_t size, qboolean clear, const char *filename, int fileline ); - void *(*_Mem_Realloc)( byte *poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ); + poolhandle_t (*_Mem_AllocPool)( const char *name, const char *filename, int fileline ); + void (*_Mem_FreePool)( poolhandle_t *poolptr, const char *filename, int fileline ); + void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ); + void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ); void (*_Mem_Free)( void *data, const char *filename, int fileline ); // library management @@ -433,7 +433,7 @@ typedef struct ref_api_s rgbdata_t *(*FS_CopyImage)( rgbdata_t *in ); void (*FS_FreeImage)( rgbdata_t *pack ); void (*Image_SetMDLPointer)( byte *p ); - byte *(*Image_GetPool)( void ); + poolhandle_t (*Image_GetPool)( void ); const struct bpc_desc_s *(*Image_GetPFDesc)( int idx ); // client exports diff --git a/engine/server/server.h b/engine/server/server.h index f8fb8def..cb068f51 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -206,7 +206,7 @@ typedef struct sv_client_s cl_state_t state; cl_upload_t upstate; // uploading state char name[32]; // extracted from userinfo, color string allowed - int flags; // client flags, some info + uint flags; // client flags, some info CRC32_t crcValue; char userinfo[MAX_INFO_STRING]; // name, etc (received from client) @@ -345,8 +345,8 @@ typedef struct NEW_DLL_FUNCTIONS dllFuncs2; // new dll exported funcs (may be NULL) physics_interface_t physFuncs; // physics interface functions (Xash3D extension) - byte *mempool; // server premamnent pool: edicts etc - byte *stringspool; // for engine strings + poolhandle_t mempool; // server premamnent pool: edicts etc + poolhandle_t stringspool; // for engine strings } svgame_static_t; typedef struct @@ -395,6 +395,8 @@ extern convar_t sv_instancedbaseline; extern convar_t sv_background_freeze; extern convar_t sv_minupdaterate; extern convar_t sv_maxupdaterate; +extern convar_t sv_minrate; +extern convar_t sv_maxrate; extern convar_t sv_downloadurl; extern convar_t sv_newunit; extern convar_t sv_clienttrace; @@ -615,7 +617,7 @@ void SV_EmptyStringPool( void ); void SV_PrintStr64Stats_f( void ); #endif sv_client_t *SV_ClientFromEdict( const edict_t *pEdict, qboolean spawned_only ); -int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name ); +uint SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name ); void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch ); edict_t *SV_FindGlobalEntity( string_t classname, string_t globalname ); qboolean SV_CreateStaticEntity( struct sizebuf_s *msg, int index ); diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index 0fc3fd60..8262ae0f 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -122,9 +122,9 @@ int SV_GetFragmentSize( void *pcl, fragsize_t mode ) int frmax = Q_atoi( Info_ValueForKey( cl->userinfo, "cl_frmax" )); if( frmax < FRAGMENT_MIN_SIZE || frmax > FRAGMENT_MAX_SIZE ) - cl_frag_size = frmax; + cl_frag_size /= 2; // add window for unreliable else - cl_frag_size /= 2;// add window for unreliable + cl_frag_size = frmax; } return cl_frag_size - HEADER_BYTES; @@ -376,17 +376,6 @@ void SV_ConnectClient( netadr_t from ) // build a new connection // accept the new client - if( Q_strncpy( newcl->useragent, Cmd_Argv( 6 ), MAX_INFO_STRING ) ) - { - const char *id = Info_ValueForKey( newcl->useragent, "i" ); - - if( *id ) - { - //sscanf( id, "%llx", &newcl->WonID ); - } - - // Q_strncpy( cl->auth_id, id, sizeof( cl->auth_id ) ); - } sv.current_client = newcl; newcl->edict = EDICT_NUM( (newcl - svs.clients) + 1 ); @@ -396,6 +385,7 @@ void SV_ConnectClient( netadr_t from ) newcl->userid = g_userid++; // create unique userid newcl->state = cs_connected; newcl->extensions = extensions & (NET_EXT_SPLITSIZE); + Q_strncpy( newcl->useragent, protinfo, MAX_INFO_STRING ); // reset viewentities (from previous level) memset( newcl->viewentity, 0, sizeof( newcl->viewentity )); @@ -411,7 +401,7 @@ void SV_ConnectClient( netadr_t from ) // build protinfo answer protinfo[0] = '\0'; - Info_SetValueForKey( protinfo, "ext", va( "%d",newcl->extensions ), sizeof( protinfo ) ); + Info_SetValueForKey( protinfo, "ext", va( "%d", newcl->extensions ), sizeof( protinfo ) ); // send the connect packet to the client Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect %s", protinfo ); @@ -608,7 +598,7 @@ SVC COMMAND REDIRECT ============================================================================== */ -void SV_BeginRedirect( netadr_t adr, int target, char *buffer, int buffersize, void (*flush)) +void SV_BeginRedirect( netadr_t adr, rdtype_t target, char *buffer, size_t buffersize, void (*flush)) { if( !target || !buffer || !buffersize || !flush ) return; @@ -619,6 +609,8 @@ void SV_BeginRedirect( netadr_t adr, int target, char *buffer, int buffersize, v host.rd.flush = flush; host.rd.address = adr; host.rd.buffer[0] = 0; + if( host.rd.lines == 0 ) + host.rd.lines = -1; } void SV_FlushRedirect( netadr_t adr, int dest, char *buf ) @@ -644,6 +636,9 @@ void SV_FlushRedirect( netadr_t adr, int dest, char *buf ) void SV_EndRedirect( void ) { + if( host.rd.lines > 0 ) + return; + if( host.rd.flush ) host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer ); @@ -653,6 +648,34 @@ void SV_EndRedirect( void ) host.rd.flush = NULL; } +/* +================ +Rcon_Print + +Print message to rcon buffer and send to rcon redirect target +================ +*/ +void Rcon_Print( const char *pMsg ) +{ + if( host.rd.target && host.rd.lines && host.rd.flush && host.rd.buffer ) + { + size_t len = Q_strncat( host.rd.buffer, pMsg, host.rd.buffersize ); + + if( len && host.rd.buffer[len-1] == '\n' ) + { + host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer ); + + if( host.rd.lines > 0 ) + host.rd.lines--; + + host.rd.buffer[0] = 0; + + if( !host.rd.lines ) + Msg( "End of redirection!\n" ); + } + } +} + /* =============== SV_GetClientIDString @@ -798,7 +821,6 @@ The second parameter should be the current protocol version number. void SV_Info( netadr_t from ) { char string[MAX_INFO_STRING]; - int i, count = 0; int version; // ignore in single player @@ -814,6 +836,9 @@ void SV_Info( netadr_t from ) } else { + int i, count = 0; + qboolean havePassword = COM_CheckStringEmpty( sv_password.string ); + for( i = 0; i < svs.maxclients; i++ ) if( svs.clients[i].state >= cs_connected ) count++; @@ -826,6 +851,7 @@ void SV_Info( netadr_t from ) Info_SetValueForKey( string, "numcl", va( "%i", count ), MAX_INFO_STRING ); Info_SetValueForKey( string, "maxcl", va( "%i", svs.maxclients ), MAX_INFO_STRING ); Info_SetValueForKey( string, "gamedir", GI->gamefolder, MAX_INFO_STRING ); + Info_SetValueForKey( string, "password", havePassword ? "1" : "0", MAX_INFO_STRING ); } Netchan_OutOfBandPrint( NS_SERVER, from, "info\n%s", string ); @@ -1725,7 +1751,7 @@ void SV_UserinfoChanged( sv_client_t *cl ) // rate command val = Info_ValueForKey( cl->userinfo, "rate" ); if( COM_CheckString( val ) ) - cl->netchan.rate = bound( MIN_RATE, Q_atoi( val ), MAX_RATE ); + cl->netchan.rate = bound( sv_minrate.value, Q_atoi( val ), sv_maxrate.value ); else cl->netchan.rate = DEFAULT_RATE; // movement prediction @@ -1749,8 +1775,7 @@ void SV_UserinfoChanged( sv_client_t *cl ) { if( Q_atoi( val ) != 0 ) { - int i = bound( 10, Q_atoi( val ), 300 ); - cl->cl_updaterate = 1.0 / i; + cl->cl_updaterate = 1.0 / bound( sv_minupdaterate.value, Q_atoi( val ), sv_maxupdaterate.value ); } else cl->cl_updaterate = 0.0; } diff --git a/engine/server/sv_cmds.c b/engine/server/sv_cmds.c index a1be19b3..c0ce1cf4 100644 --- a/engine/server/sv_cmds.c +++ b/engine/server/sv_cmds.c @@ -931,6 +931,30 @@ void SV_EntityInfo_f( void ) } } +/* +================ +Rcon_Redirect_f + +Force redirect N lines of console output to client +================ +*/ +void Rcon_Redirect_f( void ) +{ + int lines = 2000; + + if( !host.rd.target ) + { + Msg( "redirect is only valid from rcon\n" ); + return; + } + + if( Cmd_Argc() == 2 ) + lines = Q_atoi( Cmd_Argv( 1 ) ); + + host.rd.lines = lines; + Msg( "Redirection enabled for next %d lines\n", lines ); +} + /* ================== SV_InitHostCommands @@ -978,6 +1002,7 @@ void SV_InitOperatorCommands( void ) Cmd_AddCommand( "shutdownserver", SV_KillServer_f, "shutdown current server" ); Cmd_AddCommand( "changelevel", SV_ChangeLevel_f, "change level" ); Cmd_AddCommand( "changelevel2", SV_ChangeLevel2_f, "smooth change level" ); + Cmd_AddCommand( "redirect", Rcon_Redirect_f, "force enable rcon redirection" ); if( host.type == HOST_NORMAL ) { diff --git a/engine/server/sv_filter.c b/engine/server/sv_filter.c index b2b5355c..22edf085 100644 --- a/engine/server/sv_filter.c +++ b/engine/server/sv_filter.c @@ -184,7 +184,7 @@ static void SV_BanID_f( void ) for( i = 0, cl1 = svs.clients; i < sv_maxclients->value; i++, cl1++ ) { - if( !Q_strncmp( id, Info_ValueForKey( cl1->useragent, "i" ), len ) ) + if( !Q_strncmp( id, Info_ValueForKey( cl1->useragent, "uuid" ), len ) ) { cl = cl1; break; @@ -197,7 +197,7 @@ static void SV_BanID_f( void ) Con_DPrintf( S_WARN "banid: no such player\n" ); } else - id = Info_ValueForKey( cl->useragent, "i" ); + id = Info_ValueForKey( cl->useragent, "uuid" ); if( !id[0] ) { @@ -254,7 +254,7 @@ static void SV_RemoveID_f( void ) if( num >= sv_maxclients->value || num < 0 ) return; - id = Info_ValueForKey( svs.clients[num].useragent, "i" ); + id = Info_ValueForKey( svs.clients[num].useragent, "uuid" ); } if( !id[0] ) diff --git a/engine/server/sv_frame.c b/engine/server/sv_frame.c index 8c8d1406..55c871f5 100644 --- a/engine/server/sv_frame.c +++ b/engine/server/sv_frame.c @@ -356,7 +356,7 @@ static void SV_EmitPacketEntities( sv_client_t *cl, client_frame_t *to, sizebuf_ if( !Q_strcmp( classname, sv.instanced[i].classname )) { baseline = &sv.instanced[i].baseline; - offset = -i; + offset = -i - 1; // to avoid zero offset break; } } @@ -838,8 +838,10 @@ SV_SendClientMessages */ void SV_SendClientMessages( void ) { - sv_client_t *cl; - int i; + sv_client_t *cl; + int i; + double updaterate_time; + double time_until_next_message; if( sv.state == ss_dead ) return; @@ -865,7 +867,14 @@ void SV_SendClientMessages( void ) if( cl->state == cs_spawned ) { - if(( host.realtime + sv.frametime ) >= cl->next_messagetime ) + // Try to send a message as soon as we can. + // If the target time for sending is within the next frame interval ( based on last frame ), + // trigger the send now. Note that in single player, + // FCL_SEND_NET_MESSAGE flag is also set any time a packet arrives from the client. + time_until_next_message = cl->next_messagetime - ( host.realtime + sv.frametime ); + if( time_until_next_message <= 0.0 ) + SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); + else if( time_until_next_message > 2.0 ) // something got hosed SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); } @@ -901,7 +910,9 @@ void SV_SendClientMessages( void ) } // now that we were able to send, reset timer to point to next possible send time. - cl->next_messagetime = host.realtime + sv.frametime + cl->cl_updaterate; + // check here also because sv_max/minupdaterate could been changed in runtime + updaterate_time = bound( 1.0 / sv_maxupdaterate.value, cl->cl_updaterate, 1.0 / sv_minupdaterate.value ); + cl->next_messagetime = host.realtime + sv.frametime + updaterate_time; ClearBits( cl->flags, FCL_SEND_NET_MESSAGE ); // NOTE: we should send frame even if server is not simulated to prevent overflow diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index d62445af..bccac6f5 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -681,7 +681,7 @@ Issue changing level */ void SV_QueueChangeLevel( const char *level, const char *landname ) { - int flags, smooth = false; + uint flags, smooth = false; char mapname[MAX_QPATH]; char *spawn_entity; @@ -880,9 +880,9 @@ SV_MapIsValid Validate map ============== */ -int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name ) +uint SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name ) { - int flags = 0; + uint flags = 0; char *pfile; char *ents; @@ -3679,7 +3679,7 @@ vaild map must contain one info_player_deatchmatch */ int GAME_EXPORT pfnIsMapValid( char *filename ) { - int flags = SV_MapIsValid( filename, GI->mp_entity, NULL ); + uint flags = SV_MapIsValid( filename, GI->mp_entity, NULL ); if( FBitSet( flags, MAP_IS_EXIST ) && FBitSet( flags, MAP_HAS_SPAWNPOINT )) return true; @@ -4556,15 +4556,7 @@ pfnEngineStub extended iface stubs ============= */ -static int GAME_EXPORT pfnGetFileSize( char *filename ) -{ - return 0; -} -static unsigned int GAME_EXPORT pfnGetApproxWavePlayLen(const char *filepath) -{ - return 0; -} -static int GAME_EXPORT pfnGetLocalizedStringLength(const char *label) +static int GAME_EXPORT pfnGetLocalizedStringLength( const char *label ) { return 0; } @@ -4718,8 +4710,8 @@ static enginefuncs_t gEngfuncs = pfnGetPlayerAuthId, pfnSequenceGet, pfnSequencePickSentence, - pfnGetFileSize, - pfnGetApproxWavePlayLen, + COM_FileSize, + Sound_GetApproxWavePlayLen, pfnIsCareerMatch, pfnGetLocalizedStringLength, pfnRegisterTutorMessageShown, @@ -4794,6 +4786,17 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent ) if( ++numpairs >= 256 ) break; } + if( classname == NULL ) + { + // release allocated strings + for( i = 0; i < numpairs; i++ ) + { + Mem_Free( pkvd[i].szKeyName ); + Mem_Free( pkvd[i].szValue ); + } + return false; + } + ent = SV_AllocPrivateData( ent, ALLOC_STRING( classname )); if( !SV_IsValidEdict( ent ) || FBitSet( ent->v.flags, FL_KILLME )) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index f46a7b46..a748a0fc 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -32,10 +32,10 @@ CVAR_DEFINE_AUTO( sv_filterban, "1", 0, "filter banned users" ); CVAR_DEFINE_AUTO( sv_cheats, "0", FCVAR_SERVER, "allow cheats on server" ); CVAR_DEFINE_AUTO( sv_instancedbaseline, "1", 0, "allow to use instanced baselines to saves network overhead" ); CVAR_DEFINE_AUTO( sv_contact, "", FCVAR_ARCHIVE|FCVAR_SERVER, "server techincal support contact address or web-page" ); -CVAR_DEFINE_AUTO( sv_minupdaterate, "10.0", FCVAR_ARCHIVE, "minimal value for 'cl_updaterate' window" ); -CVAR_DEFINE_AUTO( sv_maxupdaterate, "30.0", FCVAR_ARCHIVE, "maximal value for 'cl_updaterate' window" ); -CVAR_DEFINE_AUTO( sv_minrate, "0", FCVAR_SERVER, "min bandwidth rate allowed on server, 0 == unlimited" ); -CVAR_DEFINE_AUTO( sv_maxrate, "0", FCVAR_SERVER, "max bandwidth rate allowed on server, 0 == unlimited" ); +CVAR_DEFINE_AUTO( sv_minupdaterate, "25.0", FCVAR_ARCHIVE, "minimal value for 'cl_updaterate' window" ); +CVAR_DEFINE_AUTO( sv_maxupdaterate, "60.0", FCVAR_ARCHIVE, "maximal value for 'cl_updaterate' window" ); +CVAR_DEFINE_AUTO( sv_minrate, "5000", FCVAR_SERVER, "min bandwidth rate allowed on server, 0 == unlimited" ); +CVAR_DEFINE_AUTO( sv_maxrate, "50000", FCVAR_SERVER, "max bandwidth rate allowed on server, 0 == unlimited" ); CVAR_DEFINE_AUTO( sv_logrelay, "0", FCVAR_ARCHIVE, "allow log messages from remote machines to be logged on this server" ); CVAR_DEFINE_AUTO( sv_newunit, "0", 0, "clear level-saves from previous SP game chapter to help keep .sav file size as minimum" ); CVAR_DEFINE_AUTO( sv_clienttrace, "1", FCVAR_SERVER, "0 = big box(Quake), 0.5 = halfsize, 1 = normal (100%), otherwise it's a scaling factor" ); @@ -64,6 +64,8 @@ CVAR_DEFINE_AUTO( coop, "0", 0, "cooperative mode in multiplayer game" ); CVAR_DEFINE_AUTO( teamplay, "0", 0, "team mode in multiplayer game" ); CVAR_DEFINE_AUTO( skill, "1", 0, "skill level in singleplayer game" ); CVAR_DEFINE_AUTO( temp1, "0", 0, "temporary cvar that used by some mods" ); +CVAR_DEFINE_AUTO( listipcfgfile, "listip.cfg", 0, "name of listip.cfg file" ); +CVAR_DEFINE_AUTO( mapchangecfgfile, "", 0, "name of map change configuration file" ); // physic-related variables CVAR_DEFINE_AUTO( sv_gravity, "800", FCVAR_MOVEVARS, "world gravity value" ); @@ -780,7 +782,7 @@ send error message and return false on wrong input devices qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent ) { const char *input_devices_str = Info_ValueForKey( useragent, "d" ); - const char *id = Info_ValueForKey( useragent, "i" ); + const char *id = Info_ValueForKey( useragent, "uuid" ); if( !sv_allow_noinputdevices->value && ( !input_devices_str || !input_devices_str[0] ) ) { @@ -850,10 +852,8 @@ void SV_Init( void ) Cvar_Get( "sv_alltalk", "1", 0, "allow to talking for all players (legacy, unused)" ); Cvar_Get( "sv_allow_PhysX", "1", FCVAR_ARCHIVE, "allow XashXT to usage PhysX engine" ); // XashXT cvar Cvar_Get( "sv_precache_meshes", "1", FCVAR_ARCHIVE, "cache SOLID_CUSTOM meshes before level loading" ); // Paranoia 2 cvar - Cvar_Get( "mapcyclefile", "mapcycle.txt", 0, "name of config file for map changing rules" ); Cvar_Get( "servercfgfile", "server.cfg", 0, "name of dedicated server configuration file" ); Cvar_Get( "lservercfgfile", "listenserver.cfg", 0, "name of listen server configuration file" ); - Cvar_Get( "logsdir", "logs", 0, "default folder to write server logs" ); Cvar_RegisterVariable( &sv_zmax ); Cvar_RegisterVariable( &sv_wateramp ); @@ -866,12 +866,15 @@ void SV_Init( void ) Cvar_RegisterVariable( &sv_skyname ); Cvar_RegisterVariable( &sv_footsteps ); Cvar_RegisterVariable( &sv_wateralpha ); + Cvar_RegisterVariable( &sv_minupdaterate ); + Cvar_RegisterVariable( &sv_maxupdaterate ); + Cvar_RegisterVariable( &sv_minrate ); + Cvar_RegisterVariable( &sv_maxrate ); Cvar_RegisterVariable( &sv_cheats ); Cvar_RegisterVariable( &sv_airmove ); Cvar_RegisterVariable( &sv_fps ); Cvar_RegisterVariable( &showtriggers ); Cvar_RegisterVariable( &sv_aim ); - Cvar_RegisterVariable( &motdfile ); Cvar_RegisterVariable( &deathmatch ); Cvar_RegisterVariable( &coop ); Cvar_RegisterVariable( &teamplay ); @@ -884,7 +887,7 @@ void SV_Init( void ) Cvar_RegisterVariable( &hostname ); timeout = Cvar_Get( "timeout", "125", FCVAR_SERVER, "connection timeout" ); sv_pausable = Cvar_Get( "pausable", "1", FCVAR_SERVER, "allow players to pause or not" ); - sv_validate_changelevel = Cvar_Get( "sv_validate_changelevel", "1", FCVAR_ARCHIVE, "test change level for level-designer errors" ); + sv_validate_changelevel = Cvar_Get( "sv_validate_changelevel", "0", 0, "test change level for level-designer errors" ); Cvar_RegisterVariable( &sv_clienttrace ); Cvar_RegisterVariable( &sv_bounce ); Cvar_RegisterVariable( &sv_spectatormaxspeed ); @@ -931,6 +934,13 @@ void SV_Init( void ) Cvar_RegisterVariable( &mp_logfile ); Cvar_RegisterVariable( &sv_background_freeze ); + Cvar_RegisterVariable( &mapcyclefile ); + Cvar_RegisterVariable( &motdfile ); + Cvar_RegisterVariable( &logsdir ); + Cvar_RegisterVariable( &bannedcfgfile ); + Cvar_RegisterVariable( &listipcfgfile ); + Cvar_RegisterVariable( &mapchangecfgfile ); + sv_allow_joystick = Cvar_Get( "sv_allow_joystick", "1", FCVAR_ARCHIVE, "allow connect with joystick enabled" ); sv_allow_mouse = Cvar_Get( "sv_allow_mouse", "1", FCVAR_ARCHIVE, "allow connect with mouse" ); sv_allow_touch = Cvar_Get( "sv_allow_touch", "1", FCVAR_ARCHIVE, "allow connect with touch controls" ); diff --git a/engine/server/sv_pmove.c b/engine/server/sv_pmove.c index df8bf71d..34008241 100644 --- a/engine/server/sv_pmove.c +++ b/engine/server/sv_pmove.c @@ -753,7 +753,7 @@ static void SV_FinishPMove( playermove_t *pmove, sv_client_t *cl ) VectorCopy( pmove->movedir, clent->v.movedir ); clent->v.flTimeStepSound = pmove->flTimeStepSound; clent->v.flFallVelocity = pmove->flFallVelocity; - clent->v.oldbuttons = pmove->oldbuttons; + clent->v.oldbuttons = pmove->cmd.buttons; clent->v.waterlevel = pmove->waterlevel; clent->v.watertype = pmove->watertype; clent->v.maxspeed = pmove->clientmaxspeed; diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 2162e2f1..8fdc2b9b 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -2096,7 +2096,7 @@ qboolean SV_LoadGame( const char *pPath ) qboolean validload = false; GAME_HEADER gameHeader; file_t *pFile; - int flags; + uint flags; if( Host_IsDedicated() ) return false; @@ -2289,7 +2289,7 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment ) if( tag == 0x0065 ) { - Q_strncpy( comment, "old version Xash3D ", MAX_STRING ); + Q_strncpy( comment, "", MAX_STRING ); FS_Close( f ); return 0; } @@ -2409,7 +2409,7 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment ) time_t fileTime; const struct tm *file_tm; string timestring; - int flags; + uint flags; // now check for map problems flags = SV_MapIsValid( mapName, GI->sp_entity, NULL ); diff --git a/engine/wscript b/engine/wscript index f57c09f6..38022b5a 100644 --- a/engine/wscript +++ b/engine/wscript @@ -62,6 +62,10 @@ def configure(conf): conf.fatal('SDL2 not availiable! If you want to build dedicated server, specify --dedicated') conf.define('XASH_SDL', 2) + if conf.env.DEST_OS == 'haiku': + conf.env.LIB_HAIKU = ['network'] + conf.env.LIBPATH_HAIKU = ['/boot/system/lib'] + if conf.options.USE_SELECT == None: conf.options.USE_SELECT = conf.options.DEDICATED @@ -112,6 +116,8 @@ def build(bld): source += bld.path.ant_glob(['platform/dos/*.c']) source += bld.path.ant_glob(['platform/stub/s_stub.c']) + if bld.env.DEST_OS == 'haiku': + libs.append('HAIKU') if bld.get_define('XASH_CUSTOM_SWAP'): source += bld.path.ant_glob(['platform/misc/kmalloc.c', 'platform/misc/sbrk.c']) diff --git a/game_launch/game.cpp b/game_launch/game.cpp index 9ce8c262..0ab28635 100644 --- a/game_launch/game.cpp +++ b/game_launch/game.cpp @@ -20,7 +20,7 @@ GNU General Public License for more details. #include #include -#if defined(__APPLE__) || defined(__unix__) +#if defined(__APPLE__) || defined(__unix__) || defined(__HAIKU__) #define XASHLIB "libxash." OS_LIB_EXT #elif _WIN32 #if !__MINGW32__ && _MSC_VER >= 1200 diff --git a/mainui b/mainui index aa22e707..47af8063 160000 --- a/mainui +++ b/mainui @@ -1 +1 @@ -Subproject commit aa22e7075b86d2f2af9ac724903d6172a203d689 +Subproject commit 47af806327114b777d87833232aaff050658a12c diff --git a/public/build.h b/public/build.h index f94ffce9..4edb351b 100644 --- a/public/build.h +++ b/public/build.h @@ -67,6 +67,7 @@ For more information, please refer to #undef XASH_MSVC #undef XASH_NETBSD #undef XASH_OPENBSD +#undef XASH_HAIKU #undef XASH_WIN32 #undef XASH_WIN64 #undef XASH_X86 @@ -115,6 +116,9 @@ For more information, please refer to #elif defined __WATCOMC__ && defined __DOS__ #define XASH_DOS4GW 1 #define XASH_LITTLE_ENDIAN +#elif defined __HAIKU__ + #define XASH_HAIKU 1 + #define XASH_POSIX 1 #else #error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug" #endif diff --git a/public/crtlib.c b/public/crtlib.c index bec512d2..33128253 100644 --- a/public/crtlib.c +++ b/public/crtlib.c @@ -60,9 +60,9 @@ qboolean Q_isdigit( const char *str ) return false; } -int Q_strlen( const char *string ) +size_t Q_strlen( const char *string ) { - int len; + size_t len; const char *p; if( !string ) return 0; @@ -77,9 +77,9 @@ int Q_strlen( const char *string ) return len; } -int Q_colorstr( const char *string ) +size_t Q_colorstr( const char *string ) { - int len; + size_t len; const char *p; if( !string ) return 0; @@ -325,7 +325,7 @@ void Q_atov( float *vec, const char *str, size_t siz ) char *Q_strchr( const char *s, char c ) { - int len = Q_strlen( s ); + size_t len = Q_strlen( s ); while( len-- ) { @@ -337,7 +337,7 @@ char *Q_strchr( const char *s, char c ) char *Q_strrchr( const char *s, char c ) { - int len = Q_strlen( s ); + size_t len = Q_strlen( s ); s += len; @@ -504,7 +504,8 @@ const char* Q_timestamp( int format ) char *Q_strstr( const char *string, const char *string2 ) { - int c, len; + int c; + size_t len; if( !string || !string2 ) return NULL; @@ -528,7 +529,8 @@ char *Q_strstr( const char *string, const char *string2 ) char *Q_stristr( const char *string, const char *string2 ) { - int c, len; + int c; + size_t len; if( !string || !string2 ) return NULL; @@ -552,7 +554,7 @@ char *Q_stristr( const char *string, const char *string2 ) int Q_vsnprintf( char *buffer, size_t buffersize, const char *format, va_list args ) { - size_t result; + int result; #ifndef _MSC_VER result = vsnprintf( buffer, buffersize, format, args ); diff --git a/public/crtlib.h b/public/crtlib.h index 22939aba..2dd7ad29 100644 --- a/public/crtlib.h +++ b/public/crtlib.h @@ -45,8 +45,8 @@ enum void Q_strnupr( const char *in, char *out, size_t size_out ); #define Q_strlwr( in, out ) Q_strnlwr( in, out, 99999 ) void Q_strnlwr( const char *in, char *out, size_t size_out ); -int Q_strlen( const char *string ); -int Q_colorstr( const char *string ); +size_t Q_strlen( const char *string ); +size_t Q_colorstr( const char *string ); char Q_toupper( const char in ); char Q_tolower( const char in ); #define Q_strcat( dst, src ) Q_strncat( dst, src, 99999 ) diff --git a/public/unittest.h b/public/unittest.h deleted file mode 100644 index a094f77a..00000000 --- a/public/unittest.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -unittest.h - simple unnamed unit testing framework -Copyright (C) 2019 a1batross - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ -#ifndef UNITTEST_H -#define UNITTEST_H - -#include - -struct unittest_s; -typedef void (*pfnTest_t)( struct unittest_s *_self ); -typedef struct unittest_s -{ - int status; // 0 if succeeded otherwise failed, you can use it as return code - const char *name; - pfnTest_t pfn; - struct unittest_s *next; -} unittest_t; - -#define TEST_FIRST_FUNC3(_name, _pfn, _readname) \ - static unittest_t _name = { 0, ( _readname ), ( _pfn ), NULL } - -#define TEST_FIRST_FUNC2(_name, _pfn) \ - TEST_FIRST_FUNC3(_name, _pfn, #_name) - -#define TEST_FUNC4(_name, _prevname, _pfn, _readname) \ - static unittest_t _name = { 0, ( _readname ), ( _pfn ), &( _prevname ) } - -#define TEST_FUNC3(_name, _prevname, _pfn) \ - TEST_FUNC4(_name, _prevname, _pfn, #_name) - -#define DECLARE_TEST_FUNC(_name) \ - static void fn ## _name( struct unittest_s *_self ) - -#define TEST3(_name, _prevname, _readname) \ - DECLARE_TEST_FUNC(_name); \ - TEST_FUNC4(_name, _prevname, fn ## _name, _readname ); \ - DECLARE_TEST_FUNC(_name) - // { - // your code goes here; - // } - -#define TEST(_name, _prevname) \ - TEST3(_name, _prevname, #_name) - -#define TEST_FIRST2(_name, _readname) \ - DECLARE_TEST_FUNC(_name); \ - TEST_FIRST_FUNC3(_name, fn ## _name, _readname); \ - DECLARE_TEST_FUNC(_name) - -#define TEST_FIRST(_name) \ - TEST_FIRST2(_name, #_name) - -#define IMPLEMENT_RUNNER(_fnname, _lasttest, _msgfunc, _msg ) \ - void _fnname( void ) \ - { \ - unittest_t *last = &(_lasttest); \ - int failed = 0, total = 0; \ - _msgfunc( "Starting to test '%s'\n", _msg ); \ - for( ; last; last = last->next ) \ - { \ - _msgfunc( "Checking '%s'\t\t: ", last->name ); \ - last->pfn( last ); \ - if( last->status ) \ - { \ - _msgfunc( "FAIL %d\n", last->status ); \ - failed++; \ - } \ - else _msgfunc( "PASS\n" ); \ - total++; \ - } \ - _msgfunc( "Summary: %d failed from %d total\n", failed, total ); \ - } - -#define IMPLEMENT_MAIN(_lasttest, _msg) IMPLEMENT_RUNNER(main, _lasttest, printf, _msg) - -#endif // UNITTEST_H diff --git a/ref_gl/gl4es b/ref_gl/gl4es index 69f911dc..a0e87aa3 160000 --- a/ref_gl/gl4es +++ b/ref_gl/gl4es @@ -1 +1 @@ -Subproject commit 69f911dcaf7e30de89675d8d8e22fe54748b9012 +Subproject commit a0e87aa362efa072598b7b671df67f8565b387fe diff --git a/ref_gl/gl_alias.c b/ref_gl/gl_alias.c index dada8092..77b27b77 100644 --- a/ref_gl/gl_alias.c +++ b/ref_gl/gl_alias.c @@ -1005,7 +1005,7 @@ R_AliasSetRemapColors */ void R_AliasSetRemapColors( int newTop, int newBottom ) { - gEngfuncs.CL_AllocRemapInfo( RI.currententity, newTop, newBottom ); + gEngfuncs.CL_AllocRemapInfo( RI.currententity, RI.currentmodel, newTop, newBottom ); if( gEngfuncs.CL_GetRemapInfoForEntity( RI.currententity )) { diff --git a/ref_gl/gl_local.h b/ref_gl/gl_local.h index 38145dd7..d3f49836 100644 --- a/ref_gl/gl_local.h +++ b/ref_gl/gl_local.h @@ -56,7 +56,7 @@ GNU General Public License for more details. #define LM_SAMPLE_SIZE 16 -extern byte *r_temppool; +extern poolhandle_t r_temppool; #define BLOCK_SIZE tr.block_size // lightmap blocksize #define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility @@ -93,6 +93,8 @@ extern byte *r_temppool; #define CULL_VISFRAME 3 // culled by PVS #define CULL_OTHER 4 // culled by other reason +#define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time + typedef struct gltexture_s { char name[256]; // game path, including extension (can be store image programs) @@ -718,7 +720,6 @@ extern cvar_t *gl_lightmap_nearest; extern cvar_t *gl_keeptjunctions; extern cvar_t *gl_emboss_scale; extern cvar_t *gl_round_down; -extern cvar_t *gl_detailscale; extern cvar_t *gl_wireframe; extern cvar_t *gl_polyoffset; extern cvar_t *gl_finish; diff --git a/ref_gl/gl_opengl.c b/ref_gl/gl_opengl.c index 547ead4a..49802a19 100644 --- a/ref_gl/gl_opengl.c +++ b/ref_gl/gl_opengl.c @@ -8,7 +8,6 @@ cvar_t *gl_texture_nearest; cvar_t *gl_lightmap_nearest; cvar_t *gl_keeptjunctions; cvar_t *gl_emboss_scale; -cvar_t *gl_detailscale; cvar_t *gl_check_errors; cvar_t *gl_polyoffset; cvar_t *gl_wireframe; @@ -50,7 +49,7 @@ cvar_t *tracergreen; cvar_t *tracerblue; cvar_t *traceralpha; -byte *r_temppool; +poolhandle_t r_temppool; gl_globals_t tr; glconfig_t glConfig; @@ -836,7 +835,7 @@ void GL_InitCommands( void ) r_lighting_ambient = gEngfuncs.Cvar_Get( "r_lighting_ambient", "0.3", FCVAR_ARCHIVE, "map ambient lighting scale" ); r_novis = gEngfuncs.Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" ); r_nocull = gEngfuncs.Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" ); - r_detailtextures = gEngfuncs.Cvar_Get( "r_detailtextures", "1", FCVAR_ARCHIVE, "enable detail textures support, use '2' for autogenerate detail.txt" ); + r_detailtextures = gEngfuncs.Cvar_Get( "r_detailtextures", "1", FCVAR_ARCHIVE, "enable detail textures support" ); r_lockpvs = gEngfuncs.Cvar_Get( "r_lockpvs", "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" ); r_lockfrustum = gEngfuncs.Cvar_Get( "r_lockfrustum", "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" ); r_dynamic = gEngfuncs.Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" ); @@ -851,7 +850,6 @@ void GL_InitCommands( void ) gl_lightmap_nearest = gEngfuncs.Cvar_Get( "gl_lightmap_nearest", "0", FCVAR_ARCHIVE, "disable lightmap filter" ); gl_check_errors = gEngfuncs.Cvar_Get( "gl_check_errors", "1", FCVAR_ARCHIVE, "ignore video engine errors" ); gl_vsync = gEngfuncs.pfnGetCvarPointer( "gl_vsync", 0 ); - gl_detailscale = gEngfuncs.Cvar_Get( "gl_detailscale", "4.0", FCVAR_ARCHIVE, "default scale applies while auto-generate list of detail textures" ); gl_texture_anisotropy = gEngfuncs.Cvar_Get( "gl_anisotropy", "8", FCVAR_ARCHIVE, "textures anisotropic filter" ); gl_texture_lodbias = gEngfuncs.Cvar_Get( "gl_texture_lodbias", "0.0", FCVAR_ARCHIVE, "LOD bias for mipmapped textures (perfomance|quality)" ); gl_keeptjunctions = gEngfuncs.Cvar_Get( "gl_keeptjunctions", "1", FCVAR_ARCHIVE, "removing tjuncs causes blinking pixels" ); diff --git a/ref_gl/gl_rsurf.c b/ref_gl/gl_rsurf.c index 5302fb0b..c720feff 100644 --- a/ref_gl/gl_rsurf.c +++ b/ref_gl/gl_rsurf.c @@ -1734,7 +1734,7 @@ extern decal_t gDecalPool[MAX_RENDER_DECALS]; struct vbo_static_s { // quickly free all allocations on map change - byte *mempool; + poolhandle_t mempool; // arays vbodecaldata_t *decaldata; // array diff --git a/ref_gl/gl_studio.c b/ref_gl/gl_studio.c index dd53eb5a..3326bcd6 100644 --- a/ref_gl/gl_studio.c +++ b/ref_gl/gl_studio.c @@ -2670,7 +2670,7 @@ R_StudioSetRemapColors */ static void R_StudioSetRemapColors( int newTop, int newBottom ) { - gEngfuncs.CL_AllocRemapInfo( RI.currententity, newTop, newBottom ); + gEngfuncs.CL_AllocRemapInfo( RI.currententity, RI.currentmodel, newTop, newBottom ); if( gEngfuncs.CL_GetRemapInfoForEntity( RI.currententity )) { diff --git a/ref_soft/r_context.c b/ref_soft/r_context.c index e0b1e6a9..2e688db0 100644 --- a/ref_soft/r_context.c +++ b/ref_soft/r_context.c @@ -19,7 +19,7 @@ ref_api_t gEngfuncs; ref_globals_t *gpGlobals; gl_globals_t tr; ref_speeds_t r_stats; -byte *r_temppool; +poolhandle_t r_temppool; cvar_t *gl_emboss_scale; cvar_t *r_norefresh; cvar_t *vid_brightness; @@ -48,12 +48,12 @@ static void GAME_EXPORT R_IncrementSpeedsCounter( int type ) static const byte * GAME_EXPORT R_GetTextureOriginalBuffer( unsigned int idx ) { - /*gl_texture_t *glt = R_GetTexture( idx ); + image_t *glt = R_GetTexture( idx ); if( !glt || !glt->original || !glt->original->buffer ) - return NULL;*/ + return NULL; - return NULL; + return glt->original->buffer; } /* @@ -244,15 +244,15 @@ static float GAME_EXPORT R_GetFrameTime( void ) static const char * GAME_EXPORT GL_TextureName( unsigned int texnum ) { - return "";//return R_GetTexture( texnum )->name; + return R_GetTexture( texnum )->name; } const byte * GAME_EXPORT GL_TextureData( unsigned int texnum ) { -// rgbdata_t *pic = R_GetTexture( texnum )->original; + rgbdata_t *pic = R_GetTexture( texnum )->original; - //if( pic != NULL ) - //return pic->buffer; + if( pic != NULL ) + return pic->buffer; return NULL; } diff --git a/ref_soft/r_local.h b/ref_soft/r_local.h index b5d5f250..b75b072a 100644 --- a/ref_soft/r_local.h +++ b/ref_soft/r_local.h @@ -57,7 +57,7 @@ typedef int fixed16_t; #define LM_SAMPLE_SIZE 16 -extern byte *r_temppool; +extern poolhandle_t r_temppool; #define BLOCK_SIZE tr.block_size // lightmap blocksize #define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility @@ -714,7 +714,6 @@ extern cvar_t *gl_lightmap_nearest; extern cvar_t *gl_keeptjunctions; extern cvar_t *gl_round_down; -extern cvar_t *gl_detailscale; extern cvar_t *gl_wireframe; extern cvar_t *gl_polyoffset; extern cvar_t *gl_finish; diff --git a/ref_soft/r_studio.c b/ref_soft/r_studio.c index 03994bcd..672ca6aa 100644 --- a/ref_soft/r_studio.c +++ b/ref_soft/r_studio.c @@ -2434,7 +2434,7 @@ R_StudioSetRemapColors */ static void R_StudioSetRemapColors( int newTop, int newBottom ) { - gEngfuncs.CL_AllocRemapInfo( RI.currententity, newTop, newBottom ); + gEngfuncs.CL_AllocRemapInfo( RI.currententity, RI.currentmodel, newTop, newBottom ); if( gEngfuncs.CL_GetRemapInfoForEntity( RI.currententity )) { diff --git a/scripts/build_freebsd_engine.sh b/scripts/build_freebsd_engine.sh index 215de2e2..6fdcec8e 100755 --- a/scripts/build_freebsd_engine.sh +++ b/scripts/build_freebsd_engine.sh @@ -14,7 +14,7 @@ build_engine() if [ "$APP" = "xashds" ]; then ./waf configure -T release -d -W || die elif [ "$APP" = "xash3d-fwgs" ]; then - ./waf configure -T release --enable-stb -W || die + ./waf configure -T release --enable-stb -W --enable-utils || die else die fi diff --git a/scripts/build_linux_engine.sh b/scripts/build_linux_engine.sh index a5fca691..fcb63485 100755 --- a/scripts/build_linux_engine.sh +++ b/scripts/build_linux_engine.sh @@ -52,7 +52,7 @@ build_engine() ./waf configure -T release -d -W $AMD64 || die elif [ "$APP" = "xash3d-fwgs" ]; then APPDIR=$APPNAME.AppDir - ./waf configure --sdl2=SDL2_linux -T release --enable-stb --prefix="$APPDIR" -W $AMD64 || die + ./waf configure --sdl2=SDL2_linux -T release --enable-stb --prefix="$APPDIR" -W $AMD64 --enable-utils || die else die fi diff --git a/scripts/build_mingw_engine.sh b/scripts/build_mingw_engine.sh index def946cb..7eea0e71 100755 --- a/scripts/build_mingw_engine.sh +++ b/scripts/build_mingw_engine.sh @@ -11,7 +11,7 @@ export CXXFLAGS="-static-libgcc -static-libstdc++ -no-pthread -msse2" export LDFLAGS="-static-libgcc -static-libstdc++ -no-pthread -Wl,--allow-multiple-definition" # workaround some other mingw bugs export WINRC="i686-w64-mingw32-windres" rm -rf build # clean build directory -./waf configure -s "SDL2_mingw/i686-w64-mingw32/" --build-type=none --prefix="." --win-style-install -v || die # can't compile VGUI support on MinGW, due to differnet C++ ABI +./waf configure -s "SDL2_mingw/i686-w64-mingw32/" --build-type=none --prefix="." --win-style-install -v --enable-utils || die # can't compile VGUI support on MinGW, due to differnet C++ ABI ./waf build -v || die cp $TRAVIS_BUILD_DIR/SDL2_mingw/i686-w64-mingw32//bin/SDL2.dll . # Install SDL2 cp vgui_support_bin/vgui_support.dll . diff --git a/scripts/build_osx_engine.sh b/scripts/build_osx_engine.sh index c3d6a0da..e5626608 100755 --- a/scripts/build_osx_engine.sh +++ b/scripts/build_osx_engine.sh @@ -5,7 +5,7 @@ # Build engine cd $TRAVIS_BUILD_DIR -python waf configure -s "$HOME/Library/Frameworks/SDL2.framework/" -T debug --prefix="pkg/" --win-style-install || die +python waf configure -s "$HOME/Library/Frameworks/SDL2.framework/" -T debug --prefix="pkg/" --win-style-install --enable-utils || die python waf build || die python waf install || die cp ~/Library/Frameworks/SDL2.framework/SDL2 pkg/libSDL2.dylib diff --git a/scripts/build_windows_engine.sh b/scripts/build_windows_engine.sh index ef01369b..34c02e93 100644 --- a/scripts/build_windows_engine.sh +++ b/scripts/build_windows_engine.sh @@ -7,7 +7,7 @@ cd $TRAVIS_BUILD_DIR # NOTE: to build with other version use --msvc_version during configuration # NOTE: sometimes you may need to add WinSDK to %PATH% -./waf.bat configure -s "$TRAVIS_BUILD_DIR/SDL2_VC" -T "debug" --prefix=`pwd` || die +./waf.bat configure -s "$TRAVIS_BUILD_DIR/SDL2_VC" -T "debug" --prefix=`pwd` --enable-utils || die ./waf.bat build -v || die echo After build @@ -15,7 +15,7 @@ echo After build cp $TRAVIS_BUILD_DIR/SDL2_VC/lib/x86/SDL2.dll . # Install SDL2 cp vgui-dev/lib/win32_vc6/vgui.dll . -7z a -t7z $TRAVIS_BUILD_DIR/xash3d-vc.7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on *.dll *.exe *.pdb +7z a -t7z $TRAVIS_BUILD_DIR/xash3d-win32-vc.7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on *.dll *.exe *.pdb echo "Generating VC2008 project" rm -rf vc2008/ diff --git a/scripts/travis_android_deps.sh b/scripts/travis_android_deps.sh index 06d6a8d9..ce9c9b2b 100755 --- a/scripts/travis_android_deps.sh +++ b/scripts/travis_android_deps.sh @@ -3,7 +3,7 @@ echo "Download HLSDK" cd $TRAVIS_BUILD_DIR -git clone --depth 1 --recursive https://github.com/FWGS/hlsdk-xash3d hlsdk || exit 1 +git clone --depth 1 --recursive https://github.com/FWGS/hlsdk-xash3d -b mobile_hacks hlsdk || exit 1 echo "Download and unpack Android SDK" mkdir -p sdk && cd sdk diff --git a/scripts/waifulib/compiler_optimizations.py b/scripts/waifulib/compiler_optimizations.py index fb8c7424..5c911eed 100644 --- a/scripts/waifulib/compiler_optimizations.py +++ b/scripts/waifulib/compiler_optimizations.py @@ -41,19 +41,22 @@ LINKFLAGS = { 'sanitize': { 'clang': ['-fsanitize=undefined', '-fsanitize=address'], 'gcc': ['-fsanitize=undefined', '-fsanitize=address'], + }, + 'debug': { + 'msvc': ['/INCREMENTAL', '/SAFESEH:NO'] } } CFLAGS = { 'common': { # disable thread-safe local static initialization for C++11 code, as it cause crashes on Windows XP - 'msvc': ['/D_USING_V110_SDK71_', '/Zi', '/FS', '/Zc:threadSafeInit-', '/MT'], + 'msvc': ['/D_USING_V110_SDK71_', '/FS', '/Zc:threadSafeInit-', '/MT'], 'clang': ['-g', '-gdwarf-2', '-fvisibility=hidden'], 'gcc': ['-g', '-fvisibility=hidden'], 'owcc': ['-fno-short-enum', '-ffloat-store', '-g3'] }, 'fast': { - 'msvc': ['/O2', '/Oy'], + 'msvc': ['/O2', '/Oy', '/Zi'], 'gcc': { '3': ['-O3', '-fomit-frame-pointer'], 'default': ['-Ofast', '-funsafe-math-optimizations', '-funsafe-loop-optimizations', '-fomit-frame-pointer'] @@ -62,30 +65,29 @@ CFLAGS = { 'default': ['-O3'] }, 'fastnative': { - 'msvc': ['/O2', '/Oy'], + 'msvc': ['/O2', '/Oy', '/Zi'], 'gcc': ['-Ofast', '-march=native', '-funsafe-math-optimizations', '-funsafe-loop-optimizations', '-fomit-frame-pointer'], 'clang': ['-Ofast', '-march=native'], 'default': ['-O3'] }, 'release': { - 'msvc': ['/O2'], + 'msvc': ['/O2', '/Zi'], 'owcc': ['-O3', '-foptimize-sibling-calls', '-fomit-leaf-frame-pointer', '-fomit-frame-pointer', '-fschedule-insns', '-funsafe-math-optimizations', '-funroll-loops', '-frerun-optimizer', '-finline-functions', '-finline-limit=512', '-fguess-branch-probability', '-fno-strict-aliasing', '-floop-optimize'], 'default': ['-O3'] }, 'debug': { - 'msvc': ['/Od'], - 'gcc': ['-Og'], + 'msvc': ['/Od', '/ZI'], 'owcc': ['-O0', '-fno-omit-frame-pointer', '-funwind-tables', '-fno-omit-leaf-frame-pointer'], - 'default': ['-O1'] + 'default': ['-O0'] }, 'sanitize': { - 'msvc': ['/Od', '/RTC1'], + 'msvc': ['/Od', '/RTC1', '/Zi'], 'gcc': ['-Og', '-fsanitize=undefined', '-fsanitize=address'], 'clang': ['-O0', '-fsanitize=undefined', '-fsanitize=address'], 'default': ['-O0'] }, 'nooptimize': { - 'msvc': ['/Od'], + 'msvc': ['/Od', '/Zi'], 'default': ['-O0'] } } diff --git a/utils/mdldec/wscript b/utils/mdldec/wscript new file mode 100644 index 00000000..48619987 --- /dev/null +++ b/utils/mdldec/wscript @@ -0,0 +1,33 @@ +#! /usr/bin/env python +# encoding: utf-8 +# a1batross, mittorn, 2018 + +def options(opt): + # TODO: any options for mdldec? + grp = opt.get_option_group('Utilities options') + + grp.add_option('--disable-utils-mdldec', action = 'store_true', dest = 'DISABLE_UTILS_MDLDEC', default = False, + help = 'disable studio model decompiler utility [default: %default]') + +def configure(conf): + conf.env.DISABLE_UTILS_MDLDEC = conf.options.DISABLE_UTILS_MDLDEC + +def build(bld): + if bld.env.DISABLE_UTILS_MDLDEC: + return + + source = bld.path.ant_glob('*.c') + includes = '. ../../common ../../engine ../../engine/common ../../engine/common/imagelib ../../public' + libs = [ 'public', 'M' ] + + bld( + source = source, + target = 'mdldec', + features = 'c cprogram', + includes = includes, + use = libs, + install_path = bld.env.BINDIR, + subsystem = bld.env.CONSOLE_SUBSYSTEM + ) + + bld.install_files(bld.env.SHAREDIR, 'res/activities.txt') diff --git a/wscript b/wscript index ef0fac93..1b0f32df 100644 --- a/wscript +++ b/wscript @@ -20,11 +20,12 @@ class Subproject: ignore = False # if true will be ignored, set by user request mandatory = False - def __init__(self, name, dedicated=True, singlebin=False, mandatory = False): + def __init__(self, name, dedicated=True, singlebin=False, mandatory = False, utility = False): self.name = name self.dedicated = dedicated self.singlebin = singlebin self.mandatory = mandatory + self.utility = utility def is_enabled(self, ctx): if not self.mandatory: @@ -43,6 +44,9 @@ class Subproject: if ctx.env.DEDICATED and self.dedicated: return False + if self.utility and not ctx.env.ENABLE_UTILS: + return False + return True SUBDIRS = [ @@ -57,6 +61,7 @@ SUBDIRS = [ Subproject('stub/client'), Subproject('dllemu'), Subproject('engine', dedicated=False), + Subproject('utils/mdldec', utility=True) ] def subdirs(): @@ -86,6 +91,11 @@ def options(opt): grp.add_option('--ignore-projects', action = 'store', dest = 'IGNORE_PROJECTS', default = None, help = 'disable selected projects from build [default: %default]') + grp = opt.add_option_group('Utilities options') + + grp.add_option('--enable-utils', action = 'store_true', dest = 'ENABLE_UTILS', default = False, + help = 'enable building various development utilities [default: %default]') + opt.load('compiler_optimizations subproject') for i in SUBDIRS: @@ -105,10 +115,6 @@ def configure(conf): if conf.options.IGNORE_PROJECTS: conf.env.IGNORE_PROJECTS = conf.options.IGNORE_PROJECTS.split(',') - # Force XP compability, all build targets should add - # subsystem=bld.env.MSVC_SUBSYSTEM - # TODO: wrapper around bld.stlib, bld.shlib and so on? - conf.env.MSVC_SUBSYSTEM = 'WINDOWS,5.01' conf.env.MSVC_TARGETS = ['x86' if not conf.options.ALLOW64 else 'x64'] # Load compilers early @@ -123,6 +129,14 @@ def configure(conf): conf.load('msvs msdev subproject gitversion clang_compilation_database strip_on_install waf_unit_test enforce_pic') + # Force XP compatibility, all build targets should add subsystem=bld.env.MSVC_SUBSYSTEM + if conf.env.MSVC_TARGETS[0] == 'x86': + conf.env.MSVC_SUBSYSTEM = 'WINDOWS,5.01' + conf.env.CONSOLE_SUBSYSTEM = 'CONSOLE,5.01' + else: + conf.env.MSVC_SUBSYSTEM = 'WINDOWS' + conf.env.CONSOLE_SUBSYSTEM = 'CONSOLE' + enforce_pic = True # modern defaults # modify options dictionary early @@ -213,17 +227,6 @@ def configure(conf): conf.env.append_unique('CXXFLAGS', cxxflags) conf.env.append_unique('LINKFLAGS', linkflags) - # check if we can use C99 tgmath - if conf.check_cc(header_name='tgmath.h', mandatory=False): - if conf.env.COMPILER_CC == 'msvc': - conf.define('_CRT_SILENCE_NONCONFORMING_TGMATH_H', 1) - tgmath_usable = conf.check_cc(fragment='''#include - int main(void){ return (int)sin(2.0f); }''', - msg='Checking if tgmath.h is usable', mandatory=False) - conf.define_cond('HAVE_TGMATH_H', tgmath_usable) - else: - conf.undefine('HAVE_TGMATH_H') - # check if we can use C99 stdint if conf.check_cc(header_name='stdint.h', mandatory=False): # use system @@ -232,6 +235,7 @@ def configure(conf): # include portable stdint by Paul Hsich conf.define('STDINT_H', 'pstdint.h') + conf.env.ENABLE_UTILS = conf.options.ENABLE_UTILS conf.env.DEDICATED = conf.options.DEDICATED conf.env.SINGLE_BINARY = conf.options.SINGLE_BINARY or conf.env.DEDICATED if conf.env.DEST_OS == 'dos': @@ -268,11 +272,24 @@ def configure(conf): # conf.multicheck(*a, run_all_tests = True, mandatory = True) + # check if we can use C99 tgmath + if conf.check_cc(header_name='tgmath.h', mandatory=False): + if conf.env.COMPILER_CC == 'msvc': + conf.define('_CRT_SILENCE_NONCONFORMING_TGMATH_H', 1) + tgmath_usable = conf.check_cc(fragment='''#include + const float val = 2, val2 = 3; + int main(void){ return (int)(-asin(val) + cos(val2)); }''', + msg='Checking if tgmath.h is usable', mandatory=False, use='M') + conf.define_cond('HAVE_TGMATH_H', tgmath_usable) + else: + conf.undefine('HAVE_TGMATH_H') + # indicate if we are packaging for Linux/BSD if not conf.options.WIN_INSTALL and conf.env.DEST_OS not in ['win32', 'darwin', 'android']: conf.env.LIBDIR = conf.env.BINDIR = '${PREFIX}/lib/xash3d' + conf.env.SHAREDIR = '${PREFIX}/share/xash3d' else: - conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX + conf.env.SHAREDIR = conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX conf.define('XASH_BUILD_COMMIT', conf.env.GIT_VERSION if conf.env.GIT_VERSION else 'notset') conf.define('XASH_LOW_MEMORY', conf.options.LOW_MEMORY)