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 314d61f0..89e9c9db 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 fec09792..dc9199ba 100644 --- a/cl_dll/cdll_int.cpp +++ b/cl_dll/cdll_int.cpp @@ -376,7 +376,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 23f12230..0cb65f32 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_objects.cpp b/cl_dll/hl/hl_objects.cpp index 13e32638..dfeb4e1f 100644 --- a/cl_dll/hl/hl_objects.cpp +++ b/cl_dll/hl/hl_objects.cpp @@ -31,36 +31,6 @@ void HUD_GetLastOrg( float *org ); void UpdateBeams( void ) { - vec3_t forward, vecSrc, vecEnd, origin, angles, right, up; - vec3_t view_ofs; - pmtrace_t tr; - cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer(); - int idx = pthisplayer->index; - - // Get our exact viewangles from engine - gEngfuncs.GetViewAngles( (float *)angles ); - - // Determine our last predicted origin - HUD_GetLastOrg( (float *)&origin ); - - AngleVectors( angles, forward, right, up ); - - VectorCopy( origin, vecSrc ); - - VectorMA( vecSrc, 2048, forward, vecEnd ); - - gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true ); - - // Store off the old count - gEngfuncs.pEventAPI->EV_PushPMStates(); - - // Now add in all of the players. - gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 ); - - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); - - gEngfuncs.pEventAPI->EV_PopPMStates(); } /* diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index e4573004..ee0aa2f6 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -381,6 +381,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(); @@ -514,11 +526,6 @@ int CHud::MsgFunc_SetFOV( const char *pszName, int iSize, void *pbuf ) int newfov = READ_BYTE(); int def_fov = CVAR_GET_FLOAT( "default_fov" ); -#ifdef CLIENT_WEAPONS - //Weapon prediction already takes care of changing the fog. ( g_lastFOV ). - if( g_hasPredictedFOV ) - return 1; -#endif g_lastFOV = newfov; if( newfov == 0 ) diff --git a/cl_dll/hud_msg.cpp b/cl_dll/hud_msg.cpp index fff49fd7..f161d36a 100644 --- a/cl_dll/hud_msg.cpp +++ b/cl_dll/hud_msg.cpp @@ -24,7 +24,6 @@ #define MAX_CLIENTS 32 extern float g_lastFOV; // Vit_amiN -extern bool g_hasPredictedFOV; // Vit_amiN /// USER-DEFINED SERVER MESSAGE HANDLERS @@ -51,7 +50,6 @@ int CHud::MsgFunc_ResetHUD( const char *pszName, int iSize, void *pbuf ) // Vit_amiN: reset the FOV m_iFOV = 0; // default_fov g_lastFOV = 0.0f; - g_hasPredictedFOV = false; return 1; } diff --git a/cl_dll/hud_redraw.cpp b/cl_dll/hud_redraw.cpp index 06b25a33..4a46a519 100644 --- a/cl_dll/hud_redraw.cpp +++ b/cl_dll/hud_redraw.cpp @@ -235,7 +235,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 7922d413..de91ac6e 100644 --- a/dlls/multiplay_gamerules.cpp +++ b/dlls/multiplay_gamerules.cpp @@ -1650,8 +1650,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 ); @@ -1679,10 +1679,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 53501253..c1c1fe87 100644 --- a/dlls/sound.cpp +++ b/dlls/sound.cpp @@ -1454,14 +1454,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. @@ -1513,87 +1505,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 3b9a1f1e..ae5a41bc 100644 --- a/dlls/world.cpp +++ b/dlls/world.cpp @@ -500,9 +500,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 abe7b317..ace56595 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 ) ) {