diff --git a/.travis.yml b/.travis.yml index 9e165b81..01d2ba27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,9 @@ os: sudo: true before_script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install gcc-multilib g++-multilib; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "gcc" ]]; then sudo apt-get install mingw-w64-i686-dev binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686; fi script: - mkdir -p build && cd build - cmake ../ -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DUSE_VOICEMGR=0 && make -j3 && rm -rf * - - cmake ../ -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DUSE_VOICEMGR=1 && make -j3 && rm -rf * \ No newline at end of file + - cmake ../ -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DUSE_VOICEMGR=1 && make -j3 && rm -rf * + - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "gcc" ]]; then cd ..; mkdir build-mingw; cd build-mingw; cmake ../ -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++ && make -j3; fi diff --git a/CMakeLists.txt b/CMakeLists.txt index bd7fe664..64c48928 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,11 @@ else() message(STATUS "Building for 32 Bit") endif() +if (MINGW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--add-stdcall-alias") +endif() + # add_compile_options for older cmake versions if(${CMAKE_VERSION} VERSION_LESS "3.0.2") macro(add_compile_options) diff --git a/README.md b/README.md index a57d94b5..be0a5fa8 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ Half-Life SDK for Xash3D & GoldSource with some fixes. cmake ../ make +Crosscompiling using mingw: + + mkdir build-mingw && cd build-mingw + TOOLCHAIN_PREFIX=i686-w64-mingw32 # check up the actual mingw prefix of your mingw installation + cmake ../ -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER="$TOOLCHAIN_PREFIX-gcc" -DCMAKE_CXX_COMPILER="$TOOLCHAIN_PREFIX-g++" + You may enable or disable some build options by -Dkey=value. All available build options are defined in CMakeLists.txt at root directory. See below if you want to build the GoldSource compatible libraries. @@ -68,6 +74,8 @@ or when using make without cmake: Unlike original client by Valve the resulting client library will not depend on vgui or SDL2 just like the one that's used in FWGS Xash3d. +Note for **Windows**: it's not possible to create GoldSource compatible libraries using mingw, only msvc builds will work. + Note for **Linux**: GoldSource requires libraries (both client and server) to be compiled with libstdc++ bundled with g++ of major version 4 (versions from 4.6 to 4.9 should work). If your Linux distribution does not provide compatible g++ version you have several options. diff --git a/cl_dll/CMakeLists.txt b/cl_dll/CMakeLists.txt index 9d8cdf6f..5d4a1ff0 100644 --- a/cl_dll/CMakeLists.txt +++ b/cl_dll/CMakeLists.txt @@ -31,7 +31,10 @@ if(NOT MSVC) add_compile_options(-fno-exceptions) # GCC/Clang flag add_compile_options(-Wno-write-strings) # GCC/Clang flag add_definitions(-D_LINUX -DLINUX) # It seems enough for all non-Win32 systems - add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf ) + add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp) + if(NOT MINGW) + add_definitions(-D_snprintf=snprintf -D_vsnprintf=vsnprintf) + endif() else() add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) endif() diff --git a/cl_dll/cdll_int.cpp b/cl_dll/cdll_int.cpp index 1d7fcd5f..f4806595 100644 --- a/cl_dll/cdll_int.cpp +++ b/cl_dll/cdll_int.cpp @@ -375,7 +375,22 @@ void DLLEXPORT HUD_MobilityInterface( mobile_engfuncs_t *gpMobileEngfuncs ) gMobileEngfuncs = gpMobileEngfuncs; } -bool isXashFWGS() +bool HUD_MessageBox( const char *msg ) +{ + gEngfuncs.Con_Printf( msg ); // just in case + + if( IsXashFWGS() ) + { + gMobileEngfuncs->pfnSys_Warn( msg ); + return true; + } + + // TODO: Load SDL2 and call ShowSimpleMessageBox + + return false; +} + +bool IsXashFWGS() { return gMobileEngfuncs != NULL; } diff --git a/cl_dll/cl_util.h b/cl_dll/cl_util.h index af41c795..c7135008 100644 --- a/cl_dll/cl_util.h +++ b/cl_dll/cl_util.h @@ -181,5 +181,6 @@ inline void UnpackRGB( int &r, int &g, int &b, unsigned long ulRGB )\ HSPRITE LoadSprite( const char *pszName ); -bool isXashFWGS(); +bool HUD_MessageBox( const char *msg ); +bool IsXashFWGS(); #endif diff --git a/cl_dll/hl/hl_weapons.cpp b/cl_dll/hl/hl_weapons.cpp index b2c1d7b3..75161a9e 100644 --- a/cl_dll/hl/hl_weapons.cpp +++ b/cl_dll/hl/hl_weapons.cpp @@ -34,7 +34,6 @@ extern globalvars_t *gpGlobals; extern int g_iUser1; -extern bool g_hasPredictedFOV; // Vit_amiN: from HUD // Pool of client side entities/entvars_t static entvars_t ev[32]; @@ -882,7 +881,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm to->client.fuser2 = player.m_flNextAmmoBurn; to->client.fuser3 = player.m_flAmmoStartCharge; to->client.maxspeed = player.pev->maxspeed; - g_hasPredictedFOV = true; // Vit_amiN: ready //HL Weapons to->client.vuser1[0] = player.ammo_9mm; diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index d0963ba9..9a852a61 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -329,6 +329,18 @@ void CHud::VidInit( void ) // assumption: number_1, number_2, etc, are all listed and loaded sequentially m_HUD_number_0 = GetSpriteIndex( "number_0" ); + if( m_HUD_number_0 == -1 ) + { + const char *msg = "There is something wrong with your game data! Please, reinstall\n"; + + if( HUD_MessageBox( msg ) ) + { + gEngfuncs.pfnClientCmd( "quit\n" ); + } + + return; + } + m_iFontHeight = m_rgrcRects[m_HUD_number_0].bottom - m_rgrcRects[m_HUD_number_0].top; m_Ammo.VidInit(); @@ -464,6 +476,8 @@ int CHud::MsgFunc_SetFOV( const char *pszName, int iSize, void *pbuf ) int newfov = READ_BYTE(); int def_fov = CVAR_GET_FLOAT( "default_fov" ); + g_lastFOV = newfov; + if( newfov == 0 ) { m_iFOV = def_fov; diff --git a/cl_dll/hud_msg.cpp b/cl_dll/hud_msg.cpp index fb4b0957..53a4d0b6 100644 --- a/cl_dll/hud_msg.cpp +++ b/cl_dll/hud_msg.cpp @@ -32,6 +32,7 @@ float g_iStartDist; float g_iEndDist; extern float g_lastFOV; // Vit_amiN + /// USER-DEFINED SERVER MESSAGE HANDLERS int CHud::MsgFunc_ResetHUD( const char *pszName, int iSize, void *pbuf ) diff --git a/cl_dll/hud_redraw.cpp b/cl_dll/hud_redraw.cpp index 9afa99e8..623adffc 100644 --- a/cl_dll/hud_redraw.cpp +++ b/cl_dll/hud_redraw.cpp @@ -311,7 +311,7 @@ int CHud::DrawHudString( int xpos, int ypos, int iMaxX, const char *szIt, int r, int DrawUtfString( int xpos, int ypos, int iMaxX, const char *szIt, int r, int g, int b ) { - if (isXashFWGS()) + if (IsXashFWGS()) { // xash3d: reset unicode state gEngfuncs.pfnVGUI2DrawCharacterAdditive( 0, 0, 0, 0, 0, 0, 0 ); diff --git a/cl_dll/input_mouse.cpp b/cl_dll/input_mouse.cpp index 8d57091b..3233d797 100644 --- a/cl_dll/input_mouse.cpp +++ b/cl_dll/input_mouse.cpp @@ -69,7 +69,7 @@ void IN_Shutdown( void ) void IN_Init( void ) { #ifdef SUPPORT_GOLDSOURCE_INPUT - if (isXashFWGS()) { + if (IsXashFWGS()) { gEngfuncs.Con_Printf( "FWGS Xash3D input is in use\n" ); currentInput = &fwgsInput; } else { diff --git a/dlls/multiplay_gamerules.cpp b/dlls/multiplay_gamerules.cpp index 83c612aa..0e393997 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -1799,8 +1799,8 @@ void CHalfLifeMultiplay::SendMOTDToClient( edict_t *client ) { // read from the MOTD.txt file int length, char_count = 0; - const char *pFileList; - const char *aFileList = pFileList = (const char*)LOAD_FILE_FOR_ME( CVAR_GET_STRING( "motdfile" ), &length ); + char *pFileList; + char *aFileList = pFileList = (char*)LOAD_FILE_FOR_ME( CVAR_GET_STRING( "motdfile" ), &length ); // send the server name MESSAGE_BEGIN( MSG_ONE, gmsgServerName, NULL, client ); @@ -1828,10 +1828,10 @@ void CHalfLifeMultiplay::SendMOTDToClient( edict_t *client ) if( char_count < MAX_MOTD_LENGTH ) pFileList = aFileList + char_count; else - pFileList = 0; + *pFileList = 0; MESSAGE_BEGIN( MSG_ONE, gmsgMOTD, NULL, client ); - WRITE_BYTE( pFileList ? FALSE : TRUE ); // FALSE means there is still more message to come + WRITE_BYTE( *pFileList ? FALSE : TRUE ); // FALSE means there is still more message to come WRITE_STRING( chunk ); MESSAGE_END(); } diff --git a/dlls/sound.cpp b/dlls/sound.cpp index 141f14a2..f5e61430 100644 --- a/dlls/sound.cpp +++ b/dlls/sound.cpp @@ -1453,14 +1453,6 @@ void EMIT_GROUPNAME_SUIT( edict_t *entity, const char *groupname ) // texture name to a material type. Play footstep sound based // on material type. -int fTextureTypeInit = FALSE; - -#define CTEXTURESMAX 512 // max number of textures loaded - -int gcTextures = 0; -char grgszTextureName[CTEXTURESMAX][CBTEXTURENAMEMAX]; // texture names -char grgchTextureType[CTEXTURESMAX]; // parallel array of texture types - // open materials.txt, get size, alloc space, // save in array. Only works first time called, // ignored on subsequent calls. @@ -1512,87 +1504,17 @@ static char *memfgets( byte *pMemFile, int fileSize, int &filePos, char *pBuffer return NULL; } -void TEXTURETYPE_Init() -{ - char buffer[512]; - int i, j; - byte *pMemFile; - int fileSize, filePos = 0; - - if( fTextureTypeInit ) - return; - - memset( &( grgszTextureName[0][0] ), 0, CTEXTURESMAX * CBTEXTURENAMEMAX ); - memset( grgchTextureType, 0, CTEXTURESMAX ); - - gcTextures = 0; - - pMemFile = g_engfuncs.pfnLoadFileForMe( "sound/materials.txt", &fileSize ); - if( !pMemFile ) - return; - - memset( buffer, 0, 512 ); - // for each line in the file... - while( memfgets( pMemFile, fileSize, filePos, buffer, 511 ) != NULL && ( gcTextures < CTEXTURESMAX) ) - { - // skip whitespace - i = 0; - while( buffer[i] && isspace( buffer[i] ) ) - i++; - - if( !buffer[i] ) - continue; - - // skip comment lines - if( buffer[i] == '/' || !isalpha( buffer[i] ) ) - continue; - - // get texture type - grgchTextureType[gcTextures] = toupper( buffer[i++] ); - - // skip whitespace - while( buffer[i] && isspace( buffer[i] ) ) - i++; - - if( !buffer[i] ) - continue; - - // get sentence name - j = i; - while( buffer[j] && !isspace( buffer[j] ) ) - j++; - - if( !buffer[j] ) - continue; - - // null-terminate name and save in sentences array - j = Q_min( j, CBTEXTURENAMEMAX - 1 + i ); - buffer[j] = 0; - strcpy( &( grgszTextureName[gcTextures++][0] ), &( buffer[i] ) ); - } - - g_engfuncs.pfnFreeFile( pMemFile ); - - fTextureTypeInit = TRUE; -} - // given texture name, find texture type // if not found, return type 'concrete' // NOTE: this routine should ONLY be called if the // current texture under the player changes! +extern "C" char PM_FindTextureType( char *name ); + char TEXTURETYPE_Find( char *name ) { - // CONSIDER: pre-sort texture names and perform faster binary search here - - for( int i = 0; i < gcTextures; i++ ) - { - if( !strnicmp( name, &( grgszTextureName[i][0] ), CBTEXTURENAMEMAX - 1 ) ) - return grgchTextureType[i]; - } - - return CHAR_TEX_CONCRETE; + return PM_FindTextureType(name); } // play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the diff --git a/dlls/world.cpp b/dlls/world.cpp index b74295e3..d1acc6b1 100644 --- a/dlls/world.cpp +++ b/dlls/world.cpp @@ -492,9 +492,6 @@ void CWorld::Precache( void ) // ok to call this multiple times, calls after first are ignored. SENTENCEG_Init(); - // init texture type array from materials.txt - TEXTURETYPE_Init(); - // the area based ambient sounds MUST be the first precache_sounds // player precaches W_Precache(); // get weapon precaches diff --git a/engine/mobility_int.h b/engine/mobility_int.h index 88f63315..d8b6120a 100644 --- a/engine/mobility_int.h +++ b/engine/mobility_int.h @@ -34,7 +34,7 @@ extern "C" { #define TOUCH_FL_DEF_HIDE (1U << 6) #define TOUCH_FL_DRAW_ADDITIVE (1U << 7) #define TOUCH_FL_STROKE (1U << 8) -#define TOUCH_FL_PRECISION (1U << 9) +#define TOUCH_FL_PRECISION (1U << 9) typedef struct mobile_engfuncs_s { @@ -65,13 +65,21 @@ typedef struct mobile_engfuncs_s void (*pfnTouchSetClientOnly)( unsigned char state ); // Clean defaults list - void (*pfnTouchResetDefaultButtons)(); + void (*pfnTouchResetDefaultButtons)( void ); + // Draw scaled font for client + int (*pfnDrawScaledCharacter)( int x, int y, int number, int r, int g, int b, float scale ); + + void (*pfnSys_Warn)( const char *format, ... ); + + // Get native object for current platform. + // Pass NULL to arguments to receive an array of available objects or NULL if nothing + void *(*pfnGetNativeObject)( const char *obj ); + + void (*pfnSetCustomClientID)( const char *id ); // To be continued... } mobile_engfuncs_t; -extern mobile_engfuncs_t *gMobileEngfuncs; - // function exported from client // returns 0 on no error otherwise error typedef int (*pfnMobilityInterface)( mobile_engfuncs_t *gMobileEngfuncs ); diff --git a/pm_shared/pm_shared.c b/pm_shared/pm_shared.c index f477f197..e5286ebe 100644 --- a/pm_shared/pm_shared.c +++ b/pm_shared/pm_shared.c @@ -168,24 +168,23 @@ void PM_InitTextureTypes() char buffer[512]; int i, j; byte *pMemFile; - int fileSize, filePos; + int fileSize, filePos = 0; static qboolean bTextureTypeInit = false; if( bTextureTypeInit ) return; - memset(&( grgszTextureName[0][0] ), 0, CTEXTURESMAX * CBTEXTURENAMEMAX ); - memset( grgchTextureType, 0, CTEXTURESMAX ); + memset(&( grgszTextureName[0][0] ), 0, sizeof( grgszTextureName ) ); + memset( grgchTextureType, 0, sizeof( grgchTextureType ) ); gcTextures = 0; - fileSize = pmove->COM_FileSize( "sound/materials.txt" ); - pMemFile = pmove->COM_LoadFile( "sound/materials.txt", 5, NULL ); + pMemFile = pmove->COM_LoadFile( "sound/materials.txt", 5, &fileSize ); if( !pMemFile ) return; - memset( buffer, 0, 512 ); - filePos = 0; + memset( buffer, 0, sizeof( buffer ) ); + // for each line in the file... while( pmove->memfgets( pMemFile, fileSize, &filePos, buffer, 511 ) != NULL && (gcTextures < CTEXTURESMAX ) ) {