diff --git a/README.txt b/README.txt index 33979412..227f49f5 100644 --- a/README.txt +++ b/README.txt @@ -170,6 +170,10 @@ _________________________ > yum install cmake SDL-devel openal-devel + On ArchLinux + + > sudo pacman -S sdl2 ffmpeg openal cmake + On openSUSE (tested in 13.1) > zypper in openal-soft-devel cmake libSDL-devel libffmpeg1-devel @@ -346,6 +350,8 @@ If you want to report an issue with the game, you should make sure that your rep * If you are sending a console log, make sure to enable developer output: RBDoom3BFG.exe +set developer 1 +set logfile 2 + + You can find your qconsole.log on Windows in C:\Users\\Saved Games\id Software\RBDOOM 3 BFG\base\ NOTE: We cannot help you with OS-specific issues like configuring OpenGL correctly, configuring ALSA or configuring the network. diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt index 625fbf15..7f2ae879 100644 --- a/neo/CMakeLists.txt +++ b/neo/CMakeLists.txt @@ -8,6 +8,9 @@ option(USE_MFC_TOOLS option(MONOLITH "Embed game logic into main executable" ON) + +option(USE_PRECOMPILED_HEADERS + "Use precompiled headers during build" ON) option(SDL2 "Use SDL2 instead of SDL1.2" ON) @@ -36,6 +39,12 @@ option(USE_SYSTEM_LIBJPEG option(USE_SYSTEM_LIBGLEW "Use the system libglew instead of the bundled one" OFF) +set(CPU_TYPE "" CACHE STRING "When set, passes this string as CPU-ID which will be embedded into the binary.") + +set(CPU_OPTIMIZATION "-mmmx -msse -msse2" CACHE STRING "Which CPU specific optimitations should be used beside the compiler's default?") + +option(USE_INTRINSICS "Compile using intrinsics (e.g mmx, sse, msse2)" ON) + if(UNIX) set(OPENAL TRUE) endif() @@ -61,7 +70,15 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") #add_definitions(-Wall) add_definitions(-Werror=format-security) add_definitions(-Werror=format) - add_definitions(-mmmx -msse -msse2) + if(CPU_TYPE) + add_definitions(-DCPUSTRING="${CPU_TYPE}") + endif() + if (CPU_OPTIMIZATION) + add_definitions(${CPU_OPTIMIZATION}) + endif() + if (USE_INTRINSICS) + add_definitions(-DUSE_INTRINSICS) + endif() if(WIN32) # require msvcr70.dll or newer for _aligned_malloc etc # I think it is from Visual C++ .NET 2002, so it should be available on any remotely modern system. @@ -179,6 +196,10 @@ elseif(MSVC) if( WINRT ) # Windows RT add_definitions(-DUSE_WINRT) endif() + + if (USE_INTRINSICS) + add_definitions(-DUSE_INTRINSICS) + endif() if(NOT CMAKE_CL_64) add_definitions(-D_USE_32BIT_TIME_T) @@ -1347,33 +1368,35 @@ if(MSVC) list(REMOVE_DUPLICATES RBDOOM3_SOURCES) - set(RBDOOM3_PRECOMPILED_SOURCES ${RBDOOM3_SOURCES}) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${TIMIDITY_SOURCES} ${JPEG_SOURCES} ${PNG_SOURCES} ${ZLIB_SOURCES} ${GLEW_SOURCES}) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/libs/zlib/minizip/ioapi.c) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTDecoder.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder_SSE2.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/dynamicshadowvolume/DynamicShadowVolume.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/prelightshadowvolume/PreLightShadowVolume.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/staticshadowvolume/StaticShadowVolume.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/ShadowShared.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/RenderLog.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/framework/precompiled.cpp) - + if(USE_PRECOMPILED_HEADERS) + set(RBDOOM3_PRECOMPILED_SOURCES ${RBDOOM3_SOURCES}) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${TIMIDITY_SOURCES} ${JPEG_SOURCES} ${PNG_SOURCES} ${ZLIB_SOURCES} ${GLEW_SOURCES}) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/libs/zlib/minizip/ioapi.c) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTDecoder.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder_SSE2.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/dynamicshadowvolume/DynamicShadowVolume.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/prelightshadowvolume/PreLightShadowVolume.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/staticshadowvolume/StaticShadowVolume.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/ShadowShared.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/RenderLog.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/framework/precompiled.cpp) - set_source_files_properties( - ${RBDOOM3_PRECOMPILED_SOURCES} - PROPERTIES - COMPILE_FLAGS "/Yuprecompiled.h" - OBJECT_DEPENDS "precompiled.pch" - - ) - set_source_files_properties(framework/precompiled.cpp - PROPERTIES - COMPILE_FLAGS "/Ycprecompiled.h" - OBJECT_OUTPUTS "precompiled.pch" - ) + set_source_files_properties( + ${RBDOOM3_PRECOMPILED_SOURCES} + PROPERTIES + COMPILE_FLAGS "/Yuprecompiled.h" + OBJECT_DEPENDS "precompiled.pch" + + ) + + set_source_files_properties(framework/precompiled.cpp + PROPERTIES + COMPILE_FLAGS "/Ycprecompiled.h" + OBJECT_OUTPUTS "precompiled.pch" + ) + endif() list(APPEND RBDOOM3_SOURCES ${WIN32_RESOURCES}) @@ -1404,6 +1427,7 @@ if(MSVC) ${PNG_LIBRARY} ${JPEG_LIBRARY} ${GLEW_LIBRARY} + ${CMAKE_DL_LIBS} ) #CMAKE_BINARY_DIR @@ -1479,88 +1503,91 @@ else() list(REMOVE_DUPLICATES RBDOOM3_SOURCES) - set(RBDOOM3_PRECOMPILED_SOURCES ${RBDOOM3_SOURCES}) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${TIMIDITY_SOURCES} ${JPEG_SOURCES} ${PNG_SOURCES} ${ZLIB_SOURCES} ${GLEW_SOURCES}) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/libs/zlib/minizip/ioapi.c) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTDecoder.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder_SSE2.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/dynamicshadowvolume/DynamicShadowVolume.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/prelightshadowvolume/PreLightShadowVolume.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/staticshadowvolume/StaticShadowVolume.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/ShadowShared.cpp) - list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/RenderLog.cpp) + if(USE_PRECOMPILED_HEADERS) + set(RBDOOM3_PRECOMPILED_SOURCES ${RBDOOM3_SOURCES}) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${TIMIDITY_SOURCES} ${JPEG_SOURCES} ${PNG_SOURCES} ${ZLIB_SOURCES} ${GLEW_SOURCES}) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/libs/zlib/minizip/ioapi.c) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTDecoder.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/DXT/DXTEncoder_SSE2.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/dynamicshadowvolume/DynamicShadowVolume.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/prelightshadowvolume/PreLightShadowVolume.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/staticshadowvolume/StaticShadowVolume.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/jobs/ShadowShared.cpp) + list(REMOVE_ITEM RBDOOM3_PRECOMPILED_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/renderer/RenderLog.cpp) - foreach( src_file ${RBDOOM3_PRECOMPILED_SOURCES} ) - #message(STATUS "-include precompiled.h for ${src_file}") - set_source_files_properties( - ${src_file} - PROPERTIES - COMPILE_FLAGS "-include ${CMAKE_CURRENT_SOURCE_DIR}/idlib/precompiled.h" - ) - endforeach() - - # precompiled magic for GCC/clang, adapted from https://gist.github.com/573926 - STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name) - SET(_compiler_FLAGS ${${_flags_var_name}}) - GET_DIRECTORY_PROPERTY(_directory_flags INCLUDE_DIRECTORIES) - FOREACH(item ${_directory_flags}) - LIST(APPEND _compiler_FLAGS " -I${item}") - ENDFOREACH(item) + foreach( src_file ${RBDOOM3_PRECOMPILED_SOURCES} ) + #message(STATUS "-include precompiled.h for ${src_file}") + set_source_files_properties( + ${src_file} + PROPERTIES + COMPILE_FLAGS "-include ${CMAKE_CURRENT_SOURCE_DIR}/idlib/precompiled.h" + ) + endforeach() + # precompiled magic for GCC/clang, adapted from https://gist.github.com/573926 + STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name) + SET(_compiler_FLAGS ${${_flags_var_name}}) + GET_DIRECTORY_PROPERTY(_directory_flags INCLUDE_DIRECTORIES) + FOREACH(item ${_directory_flags}) + LIST(APPEND _compiler_FLAGS " -I${item}") + ENDFOREACH(item) + endif() + GET_DIRECTORY_PROPERTY(_directory_flags DEFINITIONS) LIST(APPEND _compiler_FLAGS ${_directory_flags}) SEPARATE_ARGUMENTS(_compiler_FLAGS) - # we need to recreate the precompiled header for RBDoom3BFG - # (i.e. can't use the one created for idlib before) - # because some definitions (e.g. -D__IDLIB__ -D__DOOM_DLL__) differ - add_custom_target(precomp_header_rbdoom3bfg ALL - COMMAND ${CMAKE_CXX_COMPILER} ${_compiler_FLAGS} -x c++-header idlib/precompiled.h -o idlib/precompiled.h.gch - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Creating idlib/precompiled.h.gch for RBDoom3BFG" - ) + if(USE_PRECOMPILED_HEADERS) + # we need to recreate the precompiled header for RBDoom3BFG + # (i.e. can't use the one created for idlib before) + # because some definitions (e.g. -D__IDLIB__ -D__DOOM_DLL__) differ + add_custom_target(precomp_header_rbdoom3bfg ALL + COMMAND ${CMAKE_CXX_COMPILER} ${_compiler_FLAGS} -x c++-header idlib/precompiled.h -o idlib/precompiled.h.gch + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Creating idlib/precompiled.h.gch for RBDoom3BFG" + ) + endif() if(WIN32) set(remove_command "del") else() set(remove_command "rm") endif() - # it's ugly enough that the precompiled header binary needs to be in the - # source directory (instead of the build directory), so let's at least - # delete it after build. - add_custom_target(rm_precomp_header ALL - COMMAND ${remove_command} "idlib/precompiled.h.gch" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "remove idlib/precompiled.h.gch" - ) - # make sure this is run after creating idlib - add_dependencies(precomp_header_rbdoom3bfg idlib) + if (USE_PRECOMPILED_HEADERS) + # it's ugly enough that the precompiled header binary needs to be in the + # source directory (instead of the build directory), so let's at least + # delete it after build. + add_custom_target(rm_precomp_header ALL + COMMAND ${remove_command} "idlib/precompiled.h.gch" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "remove idlib/precompiled.h.gch" + ) + + # make sure this is run after creating idlib + add_dependencies(precomp_header_rbdoom3bfg idlib) + endif() add_executable(RBDoom3BFG WIN32 ${RBDOOM3_SOURCES}) - - # make sure precompiled header is created before executable is compiled - add_dependencies(RBDoom3BFG precomp_header_rbdoom3bfg) - - # make sure precompiled header is deleted after executable is compiled - add_dependencies(rm_precomp_header RBDoom3BFG) - + + if (USE_PRECOMPILED_HEADERS) + # make sure precompiled header is created before executable is compiled + add_dependencies(RBDoom3BFG precomp_header_rbdoom3bfg) + + # make sure precompiled header is deleted after executable is compiled + add_dependencies(rm_precomp_header RBDoom3BFG) + endif() if(NOT WIN32) if(NOT "${CMAKE_SYSTEM}" MATCHES "Darwin") set(RT_LIBRARY rt) endif() - if(NOT "${CMAKE_SYSTEM}" MATCHES "FreeBSD") - set(DL_LIBRARY dl) - endif() - target_link_libraries(RBDoom3BFG idlib ${OPENGL_LIBRARIES} pthread - ${DL_LIBRARY} ${RT_LIBRARY} ${SDLx_LIBRARY} ${OPENAL_LIBRARY} @@ -1569,6 +1596,7 @@ else() ${PNG_LIBRARY} ${JPEG_LIBRARY} ${GLEW_LIBRARY} + ${CMAKE_DL_LIBS} ) endif() diff --git a/neo/cm/CollisionModel_files.cpp b/neo/cm/CollisionModel_files.cpp index 7fa12c2a..2fac9703 100644 --- a/neo/cm/CollisionModel_files.cpp +++ b/neo/cm/CollisionModel_files.cpp @@ -642,13 +642,21 @@ bool idCollisionModelManagerLocal::LoadCollisionModelFile( const char* name, uns file->ReadString( fileVersion ); if( fileID == CM_FILEID && fileVersion == CM_FILEVERSION && crc == mapFileCRC && numEntries > 0 ) { + loaded = true; // DG: moved this up here to prevent segfaults, see below for( int i = 0; i < numEntries; i++ ) { cm_model_t* model = LoadBinaryModelFromFile( file, currentTimeStamp ); + // DG: handle the case that loading the binary model fails gracefully + // (otherwise we'll get a segfault when someone wants to use models[numModels]) + if( model == NULL ) + { + loaded = false; + break; + } + // DG end models[ numModels ] = model; numModels++; } - loaded = true; } } diff --git a/neo/idlib/CMakeLists.txt b/neo/idlib/CMakeLists.txt index 72845fbd..4dea5b94 100644 --- a/neo/idlib/CMakeLists.txt +++ b/neo/idlib/CMakeLists.txt @@ -101,6 +101,7 @@ if(MSVC) add_library(idlib ${ID_SOURCES_ALL} ${ID_INCLUDES_ALL}) else() + if (USE_PRECOMPILED_HEADERS) foreach( src_file ${ID_PRECOMPILED_SOURCES} ) #message(STATUS "-include precompiled.h for ${src_file}") set_source_files_properties( @@ -109,9 +110,11 @@ else() COMPILE_FLAGS "-include ${CMAKE_CURRENT_SOURCE_DIR}/precompiled.h" ) endforeach() - + endif() + include_directories(.) + if (USE_PRECOMPILED_HEADERS) # precompiled magic for GCC/clang, adapted from https://gist.github.com/573926 STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name) SET(_compiler_FLAGS ${${_flags_var_name}}) @@ -119,20 +122,25 @@ else() FOREACH(item ${_directory_flags}) LIST(APPEND _compiler_FLAGS " -I${item}") ENDFOREACH(item) + endif() GET_DIRECTORY_PROPERTY(_directory_flags DEFINITIONS) LIST(APPEND _compiler_FLAGS ${_directory_flags}) SEPARATE_ARGUMENTS(_compiler_FLAGS) + if (USE_PRECOMPILED_HEADERS) add_custom_target(precomp_header_idlib ALL COMMAND ${CMAKE_CXX_COMPILER} ${_compiler_FLAGS} -x c++-header precompiled.h -o precompiled.h.gch WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Creating idlib/precompiled.h.gch for idlib" ) + endif() add_library(idlib ${ID_SOURCES_ALL} ${ID_INCLUDES_ALL}) + if (USE_PRECOMPILED_HEADERS) add_dependencies(idlib precomp_header_idlib) + endif() endif() diff --git a/neo/idlib/sys/sys_defines.h b/neo/idlib/sys/sys_defines.h index 3daa5e59..03dce5bb 100644 --- a/neo/idlib/sys/sys_defines.h +++ b/neo/idlib/sys/sys_defines.h @@ -102,12 +102,16 @@ If you have questions concerning this license or the applicable additional terms #endif -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__GNUC__) || defined(__clang__) +#ifndef CPUSTRING #if defined(__i386__) #define CPUSTRING "x86" #elif defined(__x86_64__) #define CPUSTRING "x86_86" +#else +#error unknown CPU +#endif #endif #if defined(__FreeBSD__) @@ -116,6 +120,8 @@ If you have questions concerning this license or the applicable additional terms #define BUILD_STRING "linux-" CPUSTRING #elif defined(__APPLE__) #define BUILD_STRING "osx-" CPUSTRING +#else +#define BUILD_STRING "other-" CPUSTRING #endif #define _alloca alloca @@ -146,6 +152,8 @@ If you have questions concerning this license or the applicable additional terms #define CALLBACK #define __cdecl +#else +#error unknown build enviorment #endif // RB end diff --git a/neo/idlib/sys/sys_intrinsics.h b/neo/idlib/sys/sys_intrinsics.h index 6cf1beca..eab03980 100644 --- a/neo/idlib/sys/sys_intrinsics.h +++ b/neo/idlib/sys/sys_intrinsics.h @@ -29,8 +29,6 @@ If you have questions concerning this license or the applicable additional terms #ifndef __SYS_INTRIINSICS_H__ #define __SYS_INTRIINSICS_H__ -#define USE_INTRINSICS - #if defined(USE_INTRINSICS) #include #endif diff --git a/neo/sound/XAudio2/XA2_SoundHardware.cpp b/neo/sound/XAudio2/XA2_SoundHardware.cpp index 72da11fd..27f8a203 100644 --- a/neo/sound/XAudio2/XA2_SoundHardware.cpp +++ b/neo/sound/XAudio2/XA2_SoundHardware.cpp @@ -40,6 +40,123 @@ idCVar s_device( "s_device", "-1", CVAR_INTEGER | CVAR_ARCHIVE, "Which audio dev idCVar s_showPerfData( "s_showPerfData", "0", CVAR_BOOL, "Show XAudio2 Performance data" ); extern idCVar s_volume_dB; +#if defined(USE_WINRT) +HRESULT GetAudioDeviceDetails( _In_ IMMDevice* immDevice, _Out_ AudioDevice* pInfo ) +{ + IPropertyStore* propStore = nullptr; + PROPVARIANT varName; + PROPVARIANT varId; + + PropVariantInit( &varId ); + PropVariantInit( &varName ); + + HRESULT hResult = immDevice->OpenPropertyStore( STGM_READ, &propStore ); + + if( SUCCEEDED( hResult ) ) + { + hResult = propStore->GetValue( PKEY_AudioEndpoint_Path, &varId ); + } + + if( SUCCEEDED( hResult ) ) + { + hResult = propStore->GetValue( PKEY_Device_FriendlyName, &varName ); + } + + if( SUCCEEDED( hResult ) ) + { + assert( varId.vt == VT_LPWSTR ); + assert( varName.vt == VT_LPWSTR ); + + // Now save somewhere the device display name & id + pInfo->name = varName.pwszVal; + pInfo->id = varId.pwszVal; + } + + PropVariantClear( &varName ); + PropVariantClear( &varId ); + + if( propStore != nullptr ) + { + propStore->Release(); + } + + return hResult; +} + +std::vector EnumerateAudioDevices( _Out_opt_ AudioDevice* defaultDevice = nullptr ) +{ + UINT32 deviceCount = 0; + IMMDeviceEnumerator* immDevEnum = nullptr; + IMMDeviceCollection* immDevCollection = nullptr; + IMMDevice* immDev = nullptr; + std::vector vAudioDevices; + + HRESULT hResult = CoCreateInstance( + __uuidof( MMDeviceEnumerator ), NULL, + CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ), ( void** ) &immDevEnum ); + + if( FAILED( hResult ) ) + { + idLib::Warning( "Failed to get audio enumerator" ); + return std::move( vAudioDevices ); + } + + if( defaultDevice != nullptr ) + { + ZeroMemory( defaultDevice, sizeof( AudioDevice ) ); + + IMMDevice* defaultImmDev = nullptr; + + // @pjb: get the default audio endpoint and make it the first one in the list + if( SUCCEEDED( immDevEnum->GetDefaultAudioEndpoint( eRender, eConsole, &defaultImmDev ) ) ) + { + GetAudioDeviceDetails( defaultImmDev, defaultDevice ); + defaultImmDev->Release(); + } + } + + hResult = immDevEnum->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &immDevCollection ); + if( FAILED( hResult ) ) + { + idLib::Warning( "Failed to get audio endpoints" ); + return std::move( vAudioDevices ); + } + + hResult = immDevCollection->GetCount( &deviceCount ); + if( FAILED( hResult ) ) + { + idLib::Warning( "No audio devices found" ); + return std::move( vAudioDevices ); + } + + for( UINT i = 0; i < deviceCount; i++ ) + { + AudioDevice ad; + + hResult = immDevCollection->Item( i, &immDev ); + if( SUCCEEDED( hResult ) ) + { + hResult = GetAudioDeviceDetails( immDev, &ad ); + } + + if( SUCCEEDED( hResult ) ) + { + vAudioDevices.push_back( ad ); + } + + if( immDev != nullptr ) + { + immDev->Release(); + } + } + + immDevCollection->Release(); + immDevEnum->Release(); + + return std::move( vAudioDevices ); +} +#endif + /* ======================== idSoundHardware_XAudio2::idSoundHardware_XAudio2 @@ -77,11 +194,18 @@ void listDevices_f( const idCmdArgs& args ) // RB: not available on Windows 8 SDK #if defined(USE_WINRT) //(_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) - - // FIXME + AudioDevice defaultDevice; + auto vAudioDevices = EnumerateAudioDevices( &defaultDevice ); + if( vAudioDevices.size() == 0 ) + { + idLib::Warning( "No audio devices found" ); + return; + } - idLib::Warning( "No audio devices found" ); - return; + for( size_t i = 0; i < vAudioDevices.size(); ++i ) + { + idLib::Printf( "%s %3d: %S %S\n", vAudioDevices[i].id == defaultDevice.id ? "*" : " ", i, vAudioDevices[i].name.c_str(), vAudioDevices[i].id.c_str() ); + } #else UINT32 deviceCount = 0; if( pXAudio2->GetDeviceCount( &deviceCount ) != S_OK || deviceCount == 0 ) @@ -258,110 +382,45 @@ void idSoundHardware_XAudio2::Init() // Register the sound engine callback pXAudio2->RegisterForCallbacks( &soundEngineCallback ); soundEngineCallback.hardware = this; - UINT32 deviceCount = 0; DWORD outputSampleRate = 44100; // Max( (DWORD)XAUDIO2FX_REVERB_MIN_FRAMERATE, Min( (DWORD)XAUDIO2FX_REVERB_MAX_FRAMERATE, deviceDetails.OutputFormat.Format.nSamplesPerSec ) ); + idCmdArgs args; + listDevices_f( args ); + // RB: not available on Windows 8 SDK #if defined(USE_WINRT) //(_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) + AudioDevice defaultDevice; + std::vector vAudioDevices = EnumerateAudioDevices( &defaultDevice ); - IMMDeviceEnumerator* immDevEnum = nullptr; - IMMDeviceCollection* immDevCollection = nullptr; - IMMDevice* immDev = nullptr; - std::vector vAudioDevices; - - HRESULT hResult = CoCreateInstance( - __uuidof( MMDeviceEnumerator ), NULL, - CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ), ( void** ) &immDevEnum ); - - if( FAILED( hResult ) ) - { - idLib::Warning( "Failed to get audio enumerator" ); - pXAudio2->Release(); - pXAudio2 = NULL; - return; - } - - hResult = immDevEnum->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &immDevCollection ); - if( FAILED( hResult ) ) - { - idLib::Warning( "Failed to get audio endpoints" ); - pXAudio2->Release(); - pXAudio2 = NULL; - return; - } - - hResult = immDevCollection->GetCount( &deviceCount ); - if( FAILED( hResult ) ) - { - idLib::Warning( "No audio devices found" ); - pXAudio2->Release(); - pXAudio2 = NULL; - return; - } - - for( UINT i = 0; i < deviceCount; i++ ) - { - IPropertyStore* propStore = nullptr; - PROPVARIANT varName; - PROPVARIANT varId; - - PropVariantInit( &varId ); - PropVariantInit( &varName ); - - hResult = immDevCollection->Item( i, &immDev ); - if( SUCCEEDED( hResult ) ) - { - hResult = immDev->OpenPropertyStore( STGM_READ, &propStore ); - } - if( SUCCEEDED( hResult ) ) - { - hResult = propStore->GetValue( PKEY_AudioEndpoint_Path, &varId ); - } - - if( SUCCEEDED( hResult ) ) - { - hResult = propStore->GetValue( PKEY_Device_FriendlyName, &varName ); - } - - if( SUCCEEDED( hResult ) ) - { - assert( varId.vt == VT_LPWSTR ); - assert( varName.vt == VT_LPWSTR ); - - // Now save somewhere the device display name & id - AudioDevice ad; - ad.name = varName.pwszVal; - ad.id = varId.pwszVal; - - vAudioDevices.push_back( ad ); - } - - PropVariantClear( &varName ); - PropVariantClear( &varId ); - - if( propStore != nullptr ) - { - propStore->Release(); - } - - if( immDev != nullptr ) - { - immDev->Release(); - } - } - - - immDevCollection->Release(); - immDevEnum->Release(); - - int preferredDevice = s_device.GetInteger(); if( !vAudioDevices.empty() ) { + + AudioDevice selectedDevice; + + int preferredDevice = s_device.GetInteger(); + bool validPreference = ( preferredDevice >= 0 && preferredDevice < ( int )vAudioDevices.size() ); + // Do we select a device automatically? + if( validPreference ) + { + // Use the user's selected device + selectedDevice = vAudioDevices[preferredDevice]; + } + else if( !defaultDevice.id.empty() ) + { + // Fall back to the default device if there is one + selectedDevice = defaultDevice; + } + else + { + // Fall back to first device + selectedDevice = vAudioDevices[0]; + } + if( SUCCEEDED( pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, outputSampleRate, 0, - vAudioDevices.at( 0 ).id.c_str(), + selectedDevice.id.c_str(), NULL, AudioCategory_GameEffects ) ) ) { @@ -375,7 +434,7 @@ void idSoundHardware_XAudio2::Init() pMasterVoice->GetChannelMask( &win8_channelMask ); channelMask = ( unsigned int )win8_channelMask; - idLib::Printf( "Using device %s\n", vAudioDevices.at( 0 ).name ); + idLib::Printf( "Using device %S\n", selectedDevice.name ); } else { @@ -387,6 +446,7 @@ void idSoundHardware_XAudio2::Init() } #else + UINT32 deviceCount = 0; if( pXAudio2->GetDeviceCount( &deviceCount ) != S_OK || deviceCount == 0 ) { idLib::Warning( "No audio devices found" ); @@ -395,9 +455,6 @@ void idSoundHardware_XAudio2::Init() return; } - idCmdArgs args; - listDevices_f( args ); - int preferredDevice = s_device.GetInteger(); if( preferredDevice < 0 || preferredDevice >= ( int )deviceCount ) { diff --git a/neo/sys/posix/posix_main.cpp b/neo/sys/posix/posix_main.cpp index 78699395..2cad9dfd 100644 --- a/neo/sys/posix/posix_main.cpp +++ b/neo/sys/posix/posix_main.cpp @@ -835,18 +835,6 @@ void Sys_Sleep( int msec ) #endif } -char* Sys_GetClipboardData() -{ - Sys_Printf( "TODO: Sys_GetClipboardData\n" ); - return NULL; -} - -void Sys_SetClipboardData( const char* string ) -{ - Sys_Printf( "TODO: Sys_SetClipboardData\n" ); -} - - // stub pretty much everywhere - heavy calling void Sys_FlushCacheMemory( void* base, int bytes ) { diff --git a/neo/sys/sdl/sdl_events.cpp b/neo/sys/sdl/sdl_events.cpp index 9ce8712e..b2bcda23 100644 --- a/neo/sys/sdl/sdl_events.cpp +++ b/neo/sys/sdl/sdl_events.cpp @@ -1731,6 +1731,36 @@ const char* Sys_GetKeyName( keyNum_t keynum ) return NULL; } +char* Sys_GetClipboardData() +{ +#if SDL_VERSION_ATLEAST(2, 0, 0) + char* txt = SDL_GetClipboardText(); + + if( txt == NULL ) + { + return NULL; + } + else if( txt[0] == '\0' ) + { + SDL_free( txt ); + return NULL; + } + + char* ret = Mem_CopyString( txt ); + SDL_free( txt ); + return ret; +#else + return NULL; // SDL1.2 doesn't support clipboard +#endif +} + +void Sys_SetClipboardData( const char* string ) +{ +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_SetClipboardText( string ); +#endif +} + //===================================================================================== // Joystick Input Handling