From 6d2b9c16f8e6619071f3f72650bd1ecd8a253204 Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Sat, 11 Jul 2026 02:37:16 +0000 Subject: [PATCH 1/6] update build system and support unix-like systems --- CMakeLists.txt | 180 +++++-- build_and_log.bat | 6 +- run_analysis.bat | 38 ++ src/adivtab.hpp | 164 ------- src/anorms.hpp | 83 ---- src/audio.cpp | 34 +- src/{sound.hpp => audio.hpp} | 24 +- src/bspfile.hpp | 4 +- src/chase.cpp | 33 +- src/client.cpp | 175 ++++--- src/client.hpp | 75 ++- src/cmd.cpp | 416 ++++++---------- src/cmd.hpp | 56 ++- src/common.cpp | 3 + src/console.cpp | 10 +- src/cvar.cpp | 84 +++- src/cvar.hpp | 24 +- src/d_local.hpp | 2 +- src/host.cpp | 151 +++--- src/host.hpp | 18 +- src/mathlib.cpp | 153 +----- src/mathlib.hpp | 279 +++++++++-- src/model.cpp | 17 +- src/model.hpp | 12 +- src/modelgen.hpp | 6 +- src/network.cpp | 18 +- src/{net.hpp => network.hpp} | 2 +- src/progdefs.q1 | 38 +- src/quakedef.hpp | 27 +- src/r_local.hpp | 6 +- src/r_shared.hpp | 14 +- src/rasterizer.cpp | 155 +++--- src/{d_iface.hpp => rasterizer.hpp} | 10 +- src/renderer.cpp | 709 +++++++++++++++------------- src/{render.hpp => renderer.hpp} | 30 +- src/server.cpp | 449 +++++++++--------- src/server.hpp | 25 +- src/vid_sdl.cpp | 2 + src/view.cpp | 58 +-- src/view.hpp | 2 +- src/vm.cpp | 92 ++-- src/{progs.hpp => vm.hpp} | 2 +- src/world.cpp | 186 ++++---- src/world.hpp | 16 +- 44 files changed, 1944 insertions(+), 1944 deletions(-) create mode 100644 run_analysis.bat delete mode 100644 src/adivtab.hpp delete mode 100644 src/anorms.hpp rename src/{sound.hpp => audio.hpp} (88%) rename src/{net.hpp => network.hpp} (99%) rename src/{d_iface.hpp => rasterizer.hpp} (95%) rename src/{render.hpp => renderer.hpp} (82%) rename src/{progs.hpp => vm.hpp} (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f538e0..888ba85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,26 +1,126 @@ cmake_minimum_required(VERSION 3.20) -project(CleanQuake CXX) +project(CleanQuake LANGUAGES CXX) -# Set standard C++ flags -set(CMAKE_CXX_STANDARD 20) +if(NOT CMAKE_GENERATOR MATCHES "^Visual Studio") +include(GNUInstallDirs) +include(FindPkgConfig) +endif() + +set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) -# Add SDL definition -add_compile_definitions(SDL) +if( NOT CMAKE_BUILD_TYPE ) + set( CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE ) +endif() -# Fetch SDL2 -include(FetchContent) -FetchContent_Declare( - SDL2 - GIT_REPOSITORY https://github.com/libsdl-org/SDL.git - GIT_TAG release-2.30.3 -) -# Disable unnecessary SDL2 features for faster build -set(SDL_TEST OFF CACHE BOOL "" FORCE) -set(SDL_SHARED OFF CACHE BOOL "" FORCE) -set(SDL_STATIC ON CACHE BOOL "" FORCE) +string(TOUPPER "${CMAKE_SYSTEM_PROCESSOR}" SYSTEM_PROCESSOR_UPPER) +message(STATUS "OS: ${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR} => ${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +message(STATUS "CXX: ${CMAKE_CXX_COMPILER_ID}/${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}") +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") + +add_compile_definitions(_FILE_OFFSET_BITS=64) +add_compile_definitions($<$:DEBUG=1> $<$>:NDEBUG=1>) +add_compile_definitions($<$:_DEBUG=1> $<$>:_NDEBUG=1>) + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-gnu-alignof-expression) +endif() + +if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "GNU|AppleClang") + if( NOT CMAKE_BUILD_OPTLEVEL ) + set( CMAKE_BUILD_OPTLEVEL 3 CACHE STRING "Choose the optimization level." FORCE ) + endif() + add_compile_options(-O${CMAKE_BUILD_OPTLEVEL}) + if (NOT CMAKE_CROSSCOMPILING) + add_compile_options(-march=native) + + if (${SYSTEM_PROCESSOR_UPPER} MATCHES "X64|X86_64|AMD64") + add_compile_options(-mfpmath=sse) + endif() + if (${SYSTEM_PROCESSOR_UPPER} MATCHES "PPC|POWERPC|PPC64|PPC64LE") + include(CheckCSourceCompiles) -FetchContent_MakeAvailable(SDL2) + set(CMAKE_REQUIRED_FLAGS "-maltivec") + check_c_source_compiles("#include int main() { vector int v = (vector int){0}; return 0; }" HAVE_ALTIVEC) + + if(HAVE_ALTIVEC) + add_compile_options(-maltivec) + endif() + endif() + endif() + add_compile_options(-ftree-vectorize) + add_compile_options(-fopenmp) + if(NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "AppleClang") + add_compile_options(-fopenmp-simd) + endif() + add_compile_options(-fpermissive) + add_compile_options(-fno-asynchronous-unwind-tables) + add_compile_options(-Wall) + add_compile_options(-Wextra) + add_compile_options(-Wno-write-strings) + if (CMAKE_BUILD_TYPE MATCHES Debug) + add_compile_options(-g) + else() + # Use IPO/LTO if available + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.9.0") + cmake_policy(SET CMP0069 NEW) + include(CheckIPOSupported) + check_ipo_supported(RESULT result) + if(result) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) + message(STATUS "Using IPO/LTO.") + endif() + endif() + endif() + add_compile_options(-Wunreachable-code) # Warn about unreachable code paths + add_compile_options(-ffunction-sections) # Put each function in its own section + add_compile_options(-fdata-sections) # Put each variable in its own section + if (CMAKE_BUILD_TYPE MATCHES ReleaseStrip) + add_link_options(-Wl,--gc-sections) # Garbage collect empty sections + add_link_options(-Wl,-s) # Print out everything the linker throws away + endif() + link_libraries(m) + if (WIN32 AND MINGW) + link_libraries(mingw32) + endif() +else (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + if( NOT CMAKE_BUILD_OPTLEVEL ) + set( CMAKE_BUILD_OPTLEVEL 2 CACHE STRING "Choose the optimization level." FORCE ) + endif() + add_compile_options(/openmp:experimental) + add_compile_options(/O${CMAKE_BUILD_OPTLEVEL}) + add_compile_options(/Zc:__cplusplus) + add_compile_options(/std:c++latest) + add_compile_options(/Zc:preprocessor) + add_compile_options(/W4) + add_compile_options(/Z7) + add_compile_options(/w14702) # Force C4702 (Unreachable code) to be a Level 1 Warning + add_compile_options(/wd4996) + add_compile_options(/wd4244) + add_compile_options(/wd4113) + add_compile_options(/wd4047) + add_compile_options(/wd4024) + add_compile_options(/Gy) # Function-level linking (puts each function in its own section) + add_compile_options(/Gw) # Optimize global data (puts each variable in its own section) + if (CMAKE_BUILD_TYPE MATCHES ReleaseStrip) + add_link_options(/DEBUG:NONE) + add_link_options(/OPT:REF) # Eliminate unreferenced functions and data + add_link_options(/VERBOSE:REF) # Print out everything the linker throws away + endif() + if (NOT CMAKE_CROSSCOMPILING) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS _WIN32) + if (CMAKE_VS_PLATFORM_NAME MATCHES "x64|Win32") + # add_compile_options(/Gv) + endif() + endif() + if (CMAKE_BUILD_TYPE MATCHES Debug) + add_compile_options(/Zi) + add_link_options(/DEBUG:FULL) + endif() + add_link_options(/INCREMENTAL:NO) + link_libraries(ws2_32 winmm) +endif() # Gather source files set(CORE_SRCS @@ -55,25 +155,33 @@ set(CORE_SRCS src/zone.cpp ) -add_executable(clean-quake ${CORE_SRCS}) - -target_include_directories(clean-quake PRIVATE src) +cmake_policy(SET CMP0072 NEW) #OpenGL_GL_PREFERENCE to GLVND +find_package(OpenGL) -# Link SDL2 and Windows libraries -target_link_libraries(clean-quake PRIVATE SDL2main SDL2-static ws2_32 winmm) +find_package(SDL2) +if(NOT SDL2_FOUND) + include(FetchContent) + FetchContent_Declare( + SDL2 + GIT_REPOSITORY https://github.com/libsdl-org/SDL.git + GIT_TAG release-2.30.3 + ) + # Disable unnecessary SDL2 features for faster build + set(SDL_TEST OFF CACHE BOOL "" FORCE) + set(SDL_SHARED OFF CACHE BOOL "" FORCE) + set(SDL_STATIC ON CACHE BOOL "" FORCE) -# Suppress some old C warnings for cleaner output -if(MSVC) - target_compile_options(clean-quake PRIVATE - /W4 - /Z7 - /w14702 # Force C4702 (Unreachable code) to be a Level 1 Warning - /wd4996 /wd4244 /wd4113 /wd4047 /wd4024 - ) -else() - target_compile_options(clean-quake PRIVATE - -Wall -Wextra - -Wunreachable-code # Warn about unreachable code paths - -Wno-write-strings - ) + FetchContent_MakeAvailable(SDL2) endif() +find_library(SDL2_MAIN_LIBRARY NAMES SDL2main) +set(SDL2_LIBRARIES SDL2::SDL2) +if(SDL2_MAIN_LIBRARY) + list(APPEND SDL2_LIBRARIES ${SDL2_MAIN_LIBRARY}) +endif() +add_compile_definitions(SDL) +include_directories(SDL2::SDL2) + +# clean-quake executable +add_executable(clean-quake ${CORE_SRCS}) +target_include_directories(clean-quake PRIVATE src) +target_link_libraries(clean-quake PRIVATE ${SDL2_LIBRARIES}) diff --git a/build_and_log.bat b/build_and_log.bat index f0662df..47be488 100644 --- a/build_and_log.bat +++ b/build_and_log.bat @@ -18,10 +18,10 @@ echo [2/4] Building project and capturing output... echo (This may take a minute. Please wait, no text will print here...) cmake --build build > build.log 2>&1 -:: Step 3: Filter the log for all warnings and errors +:: Step 3: Filter the log dynamically based on the src/ folder echo. -echo [3/4] Filtering log for all warnings and errors... -powershell -Command "Select-String -Path build.log -Pattern 'warning|error' | Select-String -NotMatch 'SDL2|LIBCMT|msvcrt|OLDNAMES|uuid\.lib|ws2_32\.lib|winmm\.lib|kernel32\.lib' | Out-File -FilePath clean_build.log -Encoding utf8" +echo [3/4] Filtering log for all warnings, errors, and relevant discarded code... +powershell -Command "$srcNames = (Get-ChildItem -Path '%~dp0src' -File).BaseName -join '|'; Select-String -Path build.log -Pattern 'Discarded|warning|error' | ForEach-Object { $_.Line } | Where-Object { $d = ($_ -match 'Discarded' -and $_ -match ('(' + $srcNames + ').*\.(o|obj)') -and $_ -notmatch '\.lib|SDL2'); $w = ($_ -match 'warning|error' -and $_ -notmatch 'SDL2|LIBCMT|msvcrt|OLDNAMES|uuid\.lib|ws2_32\.lib|winmm\.lib|kernel32\.lib'); $d -or $w } | Out-File -FilePath clean_build.log -Encoding utf8" :: Step 4: Finish and open the log echo. diff --git a/run_analysis.bat b/run_analysis.bat new file mode 100644 index 0000000..a82231e --- /dev/null +++ b/run_analysis.bat @@ -0,0 +1,38 @@ +@echo off +echo ========================================== +echo CleanQuake Clang-Tidy Analyzer +echo ========================================== +echo. + +:: Step 1: Wipe the old build folder so we can change the generator +echo [1/4] Deleting old MSBuild cache... +if exist build rmdir /s /q build + +:: Step 2: Configure CMake to use Ninja +echo. +echo [2/4] Configuring CMake with Ninja... +cmake -G Ninja -B build +if %ERRORLEVEL% neq 0 ( + echo. + echo ERROR: Ninja was not found! + echo Please run this script from the "x64 Native Tools Command Prompt for VS" + echo or install Ninja manually. + pause + exit /b +) + +:: Step 3: Build the project and capture output +echo. +echo [3/4] Running build and Clang-Tidy analysis... +echo (This will take longer than a normal build. Please wait...) +cmake --build build > analysis.log 2>&1 + +:: Step 4: Filter for Clang-Tidy warnings +echo. +echo [4/4] Extracting Clang-Tidy recommendations... +powershell -Command "Select-String -Path analysis.log -Pattern 'warning:.*\[misc-|warning:.*\[clang-analyzer-' | Out-File -FilePath clang_tidy_results.log -Encoding utf8" + +echo. +echo Analysis complete! +code clang_tidy_results.log +pause \ No newline at end of file diff --git a/src/adivtab.hpp b/src/adivtab.hpp deleted file mode 100644 index 342ae09..0000000 --- a/src/adivtab.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// adivtab.h -- lookup table for integer division quotients and remainders - -// numerator = -15 -{ 1, 0 }, { 1, -1 }, { 1, -2 }, { 1, -3 }, { 1, -4 }, { 1, -5 }, { 1, -6 }, { 1, -7 }, { 2, -1 }, - { 2, -3 }, { 3, 0 }, { 3, -3 }, { 5, 0 }, { 7, -1 }, { 15, 0 }, { 0, 0 }, { -15, 0 }, - { -8, 1 }, { -5, 0 }, { -4, 1 }, { -3, 0 }, { -3, 3 }, { -3, 6 }, { -2, 1 }, { -2, 3 }, - { -2, 5 }, { -2, 7 }, { -2, 9 }, { -2, 11 }, { -2, 13 }, { -1, 0 }, { -1, 1 }, - // numerator = -14 - { 0, -14 }, { 1, 0 }, { 1, -1 }, { 1, -2 }, { 1, -3 }, { 1, -4 }, { 1, -5 }, { 1, -6 }, - { 2, 0 }, { 2, -2 }, { 2, -4 }, { 3, -2 }, { 4, -2 }, { 7, 0 }, { 14, 0 }, { 0, 0 }, - { -14, 0 }, { -7, 0 }, { -5, 1 }, { -4, 2 }, { -3, 1 }, { -3, 4 }, { -2, 0 }, { -2, 2 }, - { -2, 4 }, { -2, 6 }, { -2, 8 }, { -2, 10 }, { -2, 12 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, - // numerator = -13 - { 0, -13 }, { 0, -13 }, { 1, 0 }, { 1, -1 }, { 1, -2 }, { 1, -3 }, { 1, -4 }, { 1, -5 }, - { 1, -6 }, { 2, -1 }, { 2, -3 }, { 3, -1 }, { 4, -1 }, { 6, -1 }, { 13, 0 }, { 0, 0 }, - { -13, 0 }, { -7, 1 }, { -5, 2 }, { -4, 3 }, { -3, 2 }, { -3, 5 }, { -2, 1 }, { -2, 3 }, - { -2, 5 }, { -2, 7 }, { -2, 9 }, { -2, 11 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, - // numerator = -12 - { 0, -12 }, { 0, -12 }, { 0, -12 }, { 1, 0 }, { 1, -1 }, { 1, -2 }, { 1, -3 }, { 1, -4 }, - { 1, -5 }, { 2, 0 }, { 2, -2 }, { 3, 0 }, { 4, 0 }, { 6, 0 }, { 12, 0 }, { 0, 0 }, { -12, 0 }, - { -6, 0 }, { -4, 0 }, { -3, 0 }, { -3, 3 }, { -2, 0 }, { -2, 2 }, { -2, 4 }, { -2, 6 }, - { -2, 8 }, { -2, 10 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, - // numerator = -11 - { 0, -11 }, { 0, -11 }, { 0, -11 }, { 0, -11 }, { 1, 0 }, { 1, -1 }, { 1, -2 }, { 1, -3 }, - { 1, -4 }, { 1, -5 }, { 2, -1 }, { 2, -3 }, { 3, -2 }, { 5, -1 }, { 11, 0 }, { 0, 0 }, - { -11, 0 }, { -6, 1 }, { -4, 1 }, { -3, 1 }, { -3, 4 }, { -2, 1 }, { -2, 3 }, { -2, 5 }, - { -2, 7 }, { -2, 9 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, - // numerator = -10 - { 0, -10 }, { 0, -10 }, { 0, -10 }, { 0, -10 }, { 0, -10 }, { 1, 0 }, { 1, -1 }, { 1, -2 }, - { 1, -3 }, { 1, -4 }, { 2, 0 }, { 2, -2 }, { 3, -1 }, { 5, 0 }, { 10, 0 }, { 0, 0 }, - { -10, 0 }, { -5, 0 }, { -4, 2 }, { -3, 2 }, { -2, 0 }, { -2, 2 }, { -2, 4 }, { -2, 6 }, - { -2, 8 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, { -1, 6 }, - // numerator = -9 - { 0, -9 }, { 0, -9 }, { 0, -9 }, { 0, -9 }, { 0, -9 }, { 0, -9 }, { 1, 0 }, { 1, -1 }, - { 1, -2 }, { 1, -3 }, { 1, -4 }, { 2, -1 }, { 3, 0 }, { 4, -1 }, { 9, 0 }, { 0, 0 }, - { -9, 0 }, { -5, 1 }, { -3, 0 }, { -3, 3 }, { -2, 1 }, { -2, 3 }, { -2, 5 }, { -2, 7 }, - { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, { -1, 6 }, { -1, 7 }, - // numerator = -8 - { 0, -8 }, { 0, -8 }, { 0, -8 }, { 0, -8 }, { 0, -8 }, { 0, -8 }, { 0, -8 }, { 1, 0 }, - { 1, -1 }, { 1, -2 }, { 1, -3 }, { 2, 0 }, { 2, -2 }, { 4, 0 }, { 8, 0 }, { 0, 0 }, { -8, 0 }, - { -4, 0 }, { -3, 1 }, { -2, 0 }, { -2, 2 }, { -2, 4 }, { -2, 6 }, { -1, 0 }, { -1, 1 }, - { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, { -1, 6 }, { -1, 7 }, { -1, 8 }, - // numerator = -7 - { 0, -7 }, { 0, -7 }, { 0, -7 }, { 0, -7 }, { 0, -7 }, { 0, -7 }, { 0, -7 }, { 0, -7 }, - { 1, 0 }, { 1, -1 }, { 1, -2 }, { 1, -3 }, { 2, -1 }, { 3, -1 }, { 7, 0 }, { 0, 0 }, - { -7, 0 }, { -4, 1 }, { -3, 2 }, { -2, 1 }, { -2, 3 }, { -2, 5 }, { -1, 0 }, { -1, 1 }, - { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, { -1, 6 }, { -1, 7 }, { -1, 8 }, { -1, 9 }, - // numerator = -6 - { 0, -6 }, { 0, -6 }, { 0, -6 }, { 0, -6 }, { 0, -6 }, { 0, -6 }, { 0, -6 }, { 0, -6 }, - { 0, -6 }, { 1, 0 }, { 1, -1 }, { 1, -2 }, { 2, 0 }, { 3, 0 }, { 6, 0 }, { 0, 0 }, { -6, 0 }, - { -3, 0 }, { -2, 0 }, { -2, 2 }, { -2, 4 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, - { -1, 4 }, { -1, 5 }, { -1, 6 }, { -1, 7 }, { -1, 8 }, { -1, 9 }, { -1, 10 }, - // numerator = -5 - { 0, -5 }, { 0, -5 }, { 0, -5 }, { 0, -5 }, { 0, -5 }, { 0, -5 }, { 0, -5 }, { 0, -5 }, - { 0, -5 }, { 0, -5 }, { 1, 0 }, { 1, -1 }, { 1, -2 }, { 2, -1 }, { 5, 0 }, { 0, 0 }, - { -5, 0 }, { -3, 1 }, { -2, 1 }, { -2, 3 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, - { -1, 4 }, { -1, 5 }, { -1, 6 }, { -1, 7 }, { -1, 8 }, { -1, 9 }, { -1, 10 }, { -1, 11 }, - // numerator = -4 - { 0, -4 }, { 0, -4 }, { 0, -4 }, { 0, -4 }, { 0, -4 }, { 0, -4 }, { 0, -4 }, { 0, -4 }, - { 0, -4 }, { 0, -4 }, { 0, -4 }, { 1, 0 }, { 1, -1 }, { 2, 0 }, { 4, 0 }, { 0, 0 }, { -4, 0 }, - { -2, 0 }, { -2, 2 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, - { -1, 6 }, { -1, 7 }, { -1, 8 }, { -1, 9 }, { -1, 10 }, { -1, 11 }, { -1, 12 }, - // numerator = -3 - { 0, -3 }, { 0, -3 }, { 0, -3 }, { 0, -3 }, { 0, -3 }, { 0, -3 }, { 0, -3 }, { 0, -3 }, - { 0, -3 }, { 0, -3 }, { 0, -3 }, { 0, -3 }, { 1, 0 }, { 1, -1 }, { 3, 0 }, { 0, 0 }, - { -3, 0 }, { -2, 1 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, - { -1, 6 }, { -1, 7 }, { -1, 8 }, { -1, 9 }, { -1, 10 }, { -1, 11 }, { -1, 12 }, { -1, 13 }, - // numerator = -2 - { 0, -2 }, { 0, -2 }, { 0, -2 }, { 0, -2 }, { 0, -2 }, { 0, -2 }, { 0, -2 }, { 0, -2 }, - { 0, -2 }, { 0, -2 }, { 0, -2 }, { 0, -2 }, { 0, -2 }, { 1, 0 }, { 2, 0 }, { 0, 0 }, - { -2, 0 }, { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, { -1, 6 }, - { -1, 7 }, { -1, 8 }, { -1, 9 }, { -1, 10 }, { -1, 11 }, { -1, 12 }, { -1, 13 }, { -1, 14 }, - // numerator = -1 - { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, - { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, { 0, -1 }, { 1, 0 }, { 0, 0 }, - { -1, 0 }, { -1, 1 }, { -1, 2 }, { -1, 3 }, { -1, 4 }, { -1, 5 }, { -1, 6 }, { -1, 7 }, - { -1, 8 }, { -1, 9 }, { -1, 10 }, { -1, 11 }, { -1, 12 }, { -1, 13 }, { -1, 14 }, - { -1, 15 }, - // numerator = 0 - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, - // numerator = 1 - { -1, -14 }, { -1, -13 }, { -1, -12 }, { -1, -11 }, { -1, -10 }, { -1, -9 }, { -1, -8 }, - { -1, -7 }, { -1, -6 }, { -1, -5 }, { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, - { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, - { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, - // numerator = 2 - { -1, -13 }, { -1, -12 }, { -1, -11 }, { -1, -10 }, { -1, -9 }, { -1, -8 }, { -1, -7 }, - { -1, -6 }, { -1, -5 }, { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, - { -2, 0 }, { 0, 0 }, { 2, 0 }, { 1, 0 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, - { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 2 }, - // numerator = 3 - { -1, -12 }, { -1, -11 }, { -1, -10 }, { -1, -9 }, { -1, -8 }, { -1, -7 }, { -1, -6 }, - { -1, -5 }, { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -1 }, - { -3, 0 }, { 0, 0 }, { 3, 0 }, { 1, 1 }, { 1, 0 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, - { 0, 3 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, { 0, 3 }, - // numerator = 4 - { -1, -11 }, { -1, -10 }, { -1, -9 }, { -1, -8 }, { -1, -7 }, { -1, -6 }, { -1, -5 }, - { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -2 }, { -2, 0 }, { -4, 0 }, - { 0, 0 }, { 4, 0 }, { 2, 0 }, { 1, 1 }, { 1, 0 }, { 0, 4 }, { 0, 4 }, { 0, 4 }, { 0, 4 }, - { 0, 4 }, { 0, 4 }, { 0, 4 }, { 0, 4 }, { 0, 4 }, { 0, 4 }, { 0, 4 }, { 0, 4 }, - // numerator = 5 - { -1, -10 }, { -1, -9 }, { -1, -8 }, { -1, -7 }, { -1, -6 }, { -1, -5 }, { -1, -4 }, - { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -3 }, { -2, -1 }, { -3, -1 }, - { -5, 0 }, { 0, 0 }, { 5, 0 }, { 2, 1 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 5 }, { 0, 5 }, - { 0, 5 }, { 0, 5 }, { 0, 5 }, { 0, 5 }, { 0, 5 }, { 0, 5 }, { 0, 5 }, { 0, 5 }, { 0, 5 }, - // numerator = 6 - { -1, -9 }, { -1, -8 }, { -1, -7 }, { -1, -6 }, { -1, -5 }, { -1, -4 }, { -1, -3 }, - { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -4 }, { -2, -2 }, { -2, 0 }, { -3, 0 }, { -6, 0 }, - { 0, 0 }, { 6, 0 }, { 3, 0 }, { 2, 0 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 6 }, { 0, 6 }, - { 0, 6 }, { 0, 6 }, { 0, 6 }, { 0, 6 }, { 0, 6 }, { 0, 6 }, { 0, 6 }, { 0, 6 }, - // numerator = 7 - { -1, -8 }, { -1, -7 }, { -1, -6 }, { -1, -5 }, { -1, -4 }, { -1, -3 }, { -1, -2 }, - { -1, -1 }, { -1, 0 }, { -2, -5 }, { -2, -3 }, { -2, -1 }, { -3, -2 }, { -4, -1 }, - { -7, 0 }, { 0, 0 }, { 7, 0 }, { 3, 1 }, { 2, 1 }, { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, - { 0, 7 }, { 0, 7 }, { 0, 7 }, { 0, 7 }, { 0, 7 }, { 0, 7 }, { 0, 7 }, { 0, 7 }, { 0, 7 }, - // numerator = 8 - { -1, -7 }, { -1, -6 }, { -1, -5 }, { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, - { -1, 0 }, { -2, -6 }, { -2, -4 }, { -2, -2 }, { -2, 0 }, { -3, -1 }, { -4, 0 }, { -8, 0 }, - { 0, 0 }, { 8, 0 }, { 4, 0 }, { 2, 2 }, { 2, 0 }, { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, - { 0, 8 }, { 0, 8 }, { 0, 8 }, { 0, 8 }, { 0, 8 }, { 0, 8 }, { 0, 8 }, { 0, 8 }, - // numerator = 9 - { -1, -6 }, { -1, -5 }, { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, - { -2, -7 }, { -2, -5 }, { -2, -3 }, { -2, -1 }, { -3, -3 }, { -3, 0 }, { -5, -1 }, - { -9, 0 }, { 0, 0 }, { 9, 0 }, { 4, 1 }, { 3, 0 }, { 2, 1 }, { 1, 4 }, { 1, 3 }, { 1, 2 }, - { 1, 1 }, { 1, 0 }, { 0, 9 }, { 0, 9 }, { 0, 9 }, { 0, 9 }, { 0, 9 }, { 0, 9 }, { 0, 9 }, - // numerator = 10 - { -1, -5 }, { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -8 }, - { -2, -6 }, { -2, -4 }, { -2, -2 }, { -2, 0 }, { -3, -2 }, { -4, -2 }, { -5, 0 }, - { -10, 0 }, { 0, 0 }, { 10, 0 }, { 5, 0 }, { 3, 1 }, { 2, 2 }, { 2, 0 }, { 1, 4 }, { 1, 3 }, - { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 10 }, { 0, 10 }, { 0, 10 }, { 0, 10 }, { 0, 10 }, - { 0, 10 }, - // numerator = 11 - { -1, -4 }, { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -9 }, { -2, -7 }, - { -2, -5 }, { -2, -3 }, { -2, -1 }, { -3, -4 }, { -3, -1 }, { -4, -1 }, { -6, -1 }, - { -11, 0 }, { 0, 0 }, { 11, 0 }, { 5, 1 }, { 3, 2 }, { 2, 3 }, { 2, 1 }, { 1, 5 }, { 1, 4 }, - { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 11 }, { 0, 11 }, { 0, 11 }, { 0, 11 }, { 0, 11 }, - // numerator = 12 - { -1, -3 }, { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -10 }, { -2, -8 }, { -2, -6 }, - { -2, -4 }, { -2, -2 }, { -2, 0 }, { -3, -3 }, { -3, 0 }, { -4, 0 }, { -6, 0 }, { -12, 0 }, - { 0, 0 }, { 12, 0 }, { 6, 0 }, { 4, 0 }, { 3, 0 }, { 2, 2 }, { 2, 0 }, { 1, 5 }, { 1, 4 }, - { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 12 }, { 0, 12 }, { 0, 12 }, { 0, 12 }, - // numerator = 13 - { -1, -2 }, { -1, -1 }, { -1, 0 }, { -2, -11 }, { -2, -9 }, { -2, -7 }, { -2, -5 }, - { -2, -3 }, { -2, -1 }, { -3, -5 }, { -3, -2 }, { -4, -3 }, { -5, -2 }, { -7, -1 }, - { -13, 0 }, { 0, 0 }, { 13, 0 }, { 6, 1 }, { 4, 1 }, { 3, 1 }, { 2, 3 }, { 2, 1 }, { 1, 6 }, - { 1, 5 }, { 1, 4 }, { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 13 }, { 0, 13 }, { 0, 13 }, - // numerator = 14 - { -1, -1 }, { -1, 0 }, { -2, -12 }, { -2, -10 }, { -2, -8 }, { -2, -6 }, { -2, -4 }, - { -2, -2 }, { -2, 0 }, { -3, -4 }, { -3, -1 }, { -4, -2 }, { -5, -1 }, { -7, 0 }, - { -14, 0 }, { 0, 0 }, { 14, 0 }, { 7, 0 }, { 4, 2 }, { 3, 2 }, { 2, 4 }, { 2, 2 }, { 2, 0 }, - { 1, 6 }, { 1, 5 }, { 1, 4 }, { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 14 }, { 0, 14 }, - // numerator = 15 - { -1, 0 }, { -2, -13 }, { -2, -11 }, { -2, -9 }, { -2, -7 }, { -2, -5 }, { -2, -3 }, - { -2, -1 }, { -3, -6 }, { -3, -3 }, { -3, 0 }, { -4, -1 }, { -5, 0 }, { -8, -1 }, - { -15, 0 }, { 0, 0 }, { 15, 0 }, { 7, 1 }, { 5, 0 }, { 3, 3 }, { 3, 0 }, { 2, 3 }, { 2, 1 }, - { 1, 7 }, { 1, 6 }, { 1, 5 }, { 1, 4 }, { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, { 0, 15 }, - // numerator = 16 - { -2, -14 }, { -2, -12 }, { -2, -10 }, { -2, -8 }, { -2, -6 }, { -2, -4 }, { -2, -2 }, - { -2, 0 }, { -3, -5 }, { -3, -2 }, { -4, -4 }, { -4, 0 }, { -6, -2 }, { -8, 0 }, { -16, 0 }, - { 0, 0 }, { 16, 0 }, { 8, 0 }, { 5, 1 }, { 4, 0 }, { 3, 1 }, { 2, 4 }, { 2, 2 }, { 2, 0 }, - { 1, 7 }, { 1, 6 }, { 1, 5 }, { 1, 4 }, { 1, 3 }, { 1, 2 }, { 1, 1 }, { 1, 0 }, diff --git a/src/anorms.hpp b/src/anorms.hpp deleted file mode 100644 index a33f3c2..0000000 --- a/src/anorms.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// anorms.h -- precomputed vertex normal lookup table - -{ -0.525731, 0.000000, 0.850651 }, { -0.442863, 0.238856, 0.864188 }, - { -0.295242, 0.000000, 0.955423 }, { -0.309017, 0.500000, 0.809017 }, - { -0.162460, 0.262866, 0.951056 }, { 0.000000, 0.000000, 1.000000 }, - { 0.000000, 0.850651, 0.525731 }, { -0.147621, 0.716567, 0.681718 }, - { 0.147621, 0.716567, 0.681718 }, { 0.000000, 0.525731, 0.850651 }, - { 0.309017, 0.500000, 0.809017 }, { 0.525731, 0.000000, 0.850651 }, - { 0.295242, 0.000000, 0.955423 }, { 0.442863, 0.238856, 0.864188 }, - { 0.162460, 0.262866, 0.951056 }, { -0.681718, 0.147621, 0.716567 }, - { -0.809017, 0.309017, 0.500000 }, { -0.587785, 0.425325, 0.688191 }, - { -0.850651, 0.525731, 0.000000 }, { -0.864188, 0.442863, 0.238856 }, - { -0.716567, 0.681718, 0.147621 }, { -0.688191, 0.587785, 0.425325 }, - { -0.500000, 0.809017, 0.309017 }, { -0.238856, 0.864188, 0.442863 }, - { -0.425325, 0.688191, 0.587785 }, { -0.716567, 0.681718, -0.147621 }, - { -0.500000, 0.809017, -0.309017 }, { -0.525731, 0.850651, 0.000000 }, - { 0.000000, 0.850651, -0.525731 }, { -0.238856, 0.864188, -0.442863 }, - { 0.000000, 0.955423, -0.295242 }, { -0.262866, 0.951056, -0.162460 }, - { 0.000000, 1.000000, 0.000000 }, { 0.000000, 0.955423, 0.295242 }, - { -0.262866, 0.951056, 0.162460 }, { 0.238856, 0.864188, 0.442863 }, - { 0.262866, 0.951056, 0.162460 }, { 0.500000, 0.809017, 0.309017 }, - { 0.238856, 0.864188, -0.442863 }, { 0.262866, 0.951056, -0.162460 }, - { 0.500000, 0.809017, -0.309017 }, { 0.850651, 0.525731, 0.000000 }, - { 0.716567, 0.681718, 0.147621 }, { 0.716567, 0.681718, -0.147621 }, - { 0.525731, 0.850651, 0.000000 }, { 0.425325, 0.688191, 0.587785 }, - { 0.864188, 0.442863, 0.238856 }, { 0.688191, 0.587785, 0.425325 }, - { 0.809017, 0.309017, 0.500000 }, { 0.681718, 0.147621, 0.716567 }, - { 0.587785, 0.425325, 0.688191 }, { 0.955423, 0.295242, 0.000000 }, - { 1.000000, 0.000000, 0.000000 }, { 0.951056, 0.162460, 0.262866 }, - { 0.850651, -0.525731, 0.000000 }, { 0.955423, -0.295242, 0.000000 }, - { 0.864188, -0.442863, 0.238856 }, { 0.951056, -0.162460, 0.262866 }, - { 0.809017, -0.309017, 0.500000 }, { 0.681718, -0.147621, 0.716567 }, - { 0.850651, 0.000000, 0.525731 }, { 0.864188, 0.442863, -0.238856 }, - { 0.809017, 0.309017, -0.500000 }, { 0.951056, 0.162460, -0.262866 }, - { 0.525731, 0.000000, -0.850651 }, { 0.681718, 0.147621, -0.716567 }, - { 0.681718, -0.147621, -0.716567 }, { 0.850651, 0.000000, -0.525731 }, - { 0.809017, -0.309017, -0.500000 }, { 0.864188, -0.442863, -0.238856 }, - { 0.951056, -0.162460, -0.262866 }, { 0.147621, 0.716567, -0.681718 }, - { 0.309017, 0.500000, -0.809017 }, { 0.425325, 0.688191, -0.587785 }, - { 0.442863, 0.238856, -0.864188 }, { 0.587785, 0.425325, -0.688191 }, - { 0.688191, 0.587785, -0.425325 }, { -0.147621, 0.716567, -0.681718 }, - { -0.309017, 0.500000, -0.809017 }, { 0.000000, 0.525731, -0.850651 }, - { -0.525731, 0.000000, -0.850651 }, { -0.442863, 0.238856, -0.864188 }, - { -0.295242, 0.000000, -0.955423 }, { -0.162460, 0.262866, -0.951056 }, - { 0.000000, 0.000000, -1.000000 }, { 0.295242, 0.000000, -0.955423 }, - { 0.162460, 0.262866, -0.951056 }, { -0.442863, -0.238856, -0.864188 }, - { -0.309017, -0.500000, -0.809017 }, { -0.162460, -0.262866, -0.951056 }, - { 0.000000, -0.850651, -0.525731 }, { -0.147621, -0.716567, -0.681718 }, - { 0.147621, -0.716567, -0.681718 }, { 0.000000, -0.525731, -0.850651 }, - { 0.309017, -0.500000, -0.809017 }, { 0.442863, -0.238856, -0.864188 }, - { 0.162460, -0.262866, -0.951056 }, { 0.238856, -0.864188, -0.442863 }, - { 0.500000, -0.809017, -0.309017 }, { 0.425325, -0.688191, -0.587785 }, - { 0.716567, -0.681718, -0.147621 }, { 0.688191, -0.587785, -0.425325 }, - { 0.587785, -0.425325, -0.688191 }, { 0.000000, -0.955423, -0.295242 }, - { 0.000000, -1.000000, 0.000000 }, { 0.262866, -0.951056, -0.162460 }, - { 0.000000, -0.850651, 0.525731 }, { 0.000000, -0.955423, 0.295242 }, - { 0.238856, -0.864188, 0.442863 }, { 0.262866, -0.951056, 0.162460 }, - { 0.500000, -0.809017, 0.309017 }, { 0.716567, -0.681718, 0.147621 }, - { 0.525731, -0.850651, 0.000000 }, { -0.238856, -0.864188, -0.442863 }, - { -0.500000, -0.809017, -0.309017 }, { -0.262866, -0.951056, -0.162460 }, - { -0.850651, -0.525731, 0.000000 }, { -0.716567, -0.681718, -0.147621 }, - { -0.716567, -0.681718, 0.147621 }, { -0.525731, -0.850651, 0.000000 }, - { -0.500000, -0.809017, 0.309017 }, { -0.238856, -0.864188, 0.442863 }, - { -0.262866, -0.951056, 0.162460 }, { -0.864188, -0.442863, 0.238856 }, - { -0.809017, -0.309017, 0.500000 }, { -0.688191, -0.587785, 0.425325 }, - { -0.681718, -0.147621, 0.716567 }, { -0.442863, -0.238856, 0.864188 }, - { -0.587785, -0.425325, 0.688191 }, { -0.309017, -0.500000, 0.809017 }, - { -0.147621, -0.716567, 0.681718 }, { -0.425325, -0.688191, 0.587785 }, - { -0.162460, -0.262866, 0.951056 }, { 0.442863, -0.238856, 0.864188 }, - { 0.162460, -0.262866, 0.951056 }, { 0.309017, -0.500000, 0.809017 }, - { 0.147621, -0.716567, 0.681718 }, { 0.000000, -0.525731, 0.850651 }, - { 0.425325, -0.688191, 0.587785 }, { 0.587785, -0.425325, 0.688191 }, - { 0.688191, -0.587785, 0.425325 }, { -0.955423, 0.295242, 0.000000 }, - { -0.951056, 0.162460, 0.262866 }, { -1.000000, 0.000000, 0.000000 }, - { -0.850651, 0.000000, 0.525731 }, { -0.955423, -0.295242, 0.000000 }, - { -0.951056, -0.162460, 0.262866 }, { -0.864188, 0.442863, -0.238856 }, - { -0.951056, 0.162460, -0.262866 }, { -0.809017, 0.309017, -0.500000 }, - { -0.864188, -0.442863, -0.238856 }, { -0.951056, -0.162460, -0.262866 }, - { -0.809017, -0.309017, -0.500000 }, { -0.681718, 0.147621, -0.716567 }, - { -0.681718, -0.147621, -0.716567 }, { -0.850651, 0.000000, -0.525731 }, - { -0.688191, 0.587785, -0.425325 }, { -0.587785, 0.425325, -0.688191 }, - { -0.425325, 0.688191, -0.587785 }, { -0.425325, -0.688191, -0.587785 }, - { -0.587785, -0.425325, -0.688191 }, { -0.688191, -0.587785, -0.425325 }, diff --git a/src/audio.cpp b/src/audio.cpp index df8c473..eced1dd 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -55,10 +55,10 @@ qboolean snd_initialized = false; volatile dma_t* shm = 0; volatile dma_t sn; -vec3_t listener_origin; -vec3_t listener_forward; -vec3_t listener_right; -vec3_t listener_up; +Vector3 listener_origin; +Vector3 listener_forward; +Vector3 listener_right; +Vector3 listener_up; vec_t sound_nominal_clip_dist = 1000.0; int soundtime; // sample PAIRS @@ -377,7 +377,7 @@ void SND_Spatialize(channel_t* ch) vec_t dot; vec_t dist; vec_t lscale, rscale, scale; - vec3_t source_vec; + Vector3 source_vec; sfx_t* snd; // anything coming from the view entity will allways be full volume @@ -391,11 +391,11 @@ void SND_Spatialize(channel_t* ch) // calculate stereo seperation and distance attenuation snd = ch->sfx; - VectorSubtract(ch->origin, listener_origin, source_vec); + source_vec = ch->origin - listener_origin; - dist = VectorNormalize(source_vec) * ch->dist_mult; + dist = source_vec.normalize() * ch->dist_mult; - dot = DotProduct(listener_right, source_vec); + dot = listener_right.dot(source_vec); if (shm->channels == 1) { rscale = 1.0; @@ -426,7 +426,7 @@ void SND_Spatialize(channel_t* ch) void S_StartSound(int entnum, int entchannel, sfx_t* sfx, - vec3_t origin, + const Vector3& origin, float fvol, float attenuation) { @@ -458,7 +458,7 @@ void S_StartSound(int entnum, // spatialize memset(target_chan, 0, sizeof(*target_chan)); - VectorCopy(origin, target_chan->origin); + target_chan->origin = origin; target_chan->dist_mult = attenuation / sound_nominal_clip_dist; target_chan->master_vol = vol; target_chan->entnum = entnum; @@ -564,7 +564,7 @@ void S_ClearBuffer(void) S_StaticSound ================= */ -void S_StaticSound(sfx_t* sfx, vec3_t origin, float vol, float attenuation) +void S_StaticSound(sfx_t* sfx, const Vector3& origin, float vol, float attenuation) { channel_t* ss; sfxcache_t* sc; @@ -594,7 +594,7 @@ void S_StaticSound(sfx_t* sfx, vec3_t origin, float vol, float attenuation) } ss->sfx = sfx; - VectorCopy(origin, ss->origin); + ss->origin = origin; ss->master_vol = vol; ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist; ss->end = paintedtime + sc->length; @@ -668,7 +668,7 @@ S_Update Called once each time through the main loop ============ */ -void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) +void S_Update(const Vector3& origin, const Vector3& forward, const Vector3& right, const Vector3& up) { int i, j; int total; @@ -679,10 +679,10 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) return; } - VectorCopy(origin, listener_origin); - VectorCopy(forward, listener_forward); - VectorCopy(right, listener_right); - VectorCopy(up, listener_up); + listener_origin = origin; + listener_forward = forward; + listener_right = right; + listener_up = up; // update general area ambient sound sources S_UpdateAmbientSounds(); diff --git a/src/sound.hpp b/src/audio.hpp similarity index 88% rename from src/sound.hpp rename to src/audio.hpp index cb834d8..4529aaa 100644 --- a/src/sound.hpp +++ b/src/audio.hpp @@ -1,8 +1,8 @@ -// sound.h -- client sound i/o functions +// audio.hpp -- client sound i/o functions #pragma once -#ifndef __SOUND__ -#define __SOUND__ +#ifndef __AUDIO__ +#define __AUDIO__ #define DEFAULT_SOUND_PACKET_VOLUME 255 #define DEFAULT_SOUND_PACKET_ATTENUATION 1.0 @@ -51,7 +51,7 @@ typedef struct { int looping; // where to loop, -1 = no looping int entnum; // to allow overriding a specific sound int entchannel; // - vec3_t origin; // origin of sound effect + Vector3 origin; // origin of sound effect vec_t dist_mult; // distance multiplier (attenuation/clipK) int master_vol; // 0-255 master volume } channel_t; @@ -73,14 +73,14 @@ void S_Shutdown(void); void S_StartSound(int entnum, int entchannel, sfx_t* sfx, - vec3_t origin, + const Vector3& origin, float fvol, float attenuation); -void S_StaticSound(sfx_t* sfx, vec3_t origin, float vol, float attenuation); +void S_StaticSound(sfx_t* sfx, const Vector3& origin, float vol, float attenuation); void S_StopSound(int entnum, int entchannel); void S_StopAllSounds(qboolean clear); void S_ClearBuffer(void); -void S_Update(vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up); +void S_Update(const Vector3& origin, const Vector3& v_forward, const Vector3& v_right, const Vector3& v_up); void S_ExtraUpdate(void); sfx_t* S_PrecacheSound(const char* sample); @@ -126,10 +126,10 @@ extern int total_channels; extern qboolean fakedma; extern int paintedtime; -extern vec3_t listener_origin; -extern vec3_t listener_forward; -extern vec3_t listener_right; -extern vec3_t listener_up; +extern Vector3 listener_origin; +extern Vector3 listener_forward; +extern Vector3 listener_right; +extern Vector3 listener_up; extern volatile dma_t* shm; extern volatile dma_t sn; extern vec_t sound_nominal_clip_dist; @@ -152,6 +152,4 @@ void SNDDMA_Submit(void); } // namespace Audio - - #endif diff --git a/src/bspfile.hpp b/src/bspfile.hpp index 531e717..9ca1f48 100644 --- a/src/bspfile.hpp +++ b/src/bspfile.hpp @@ -255,7 +255,7 @@ typedef struct epair_s { } epair_t; typedef struct { - vec3_t origin; + Vector3 origin; int firstbrush; int numbrushes; epair_t* epairs; @@ -272,7 +272,7 @@ char* ValueForKey(entity_t* ent, char* key); // will return "" if not present vec_t FloatForKey(entity_t* ent, char* key); -void GetVectorForKey(entity_t* ent, char* key, vec3_t vec); +void GetVectorForKey(entity_t* ent, char* key, Vector3& vec); epair_t* ParseEpair(void); diff --git a/src/chase.cpp b/src/chase.cpp index 42a901b..e1007b5 100644 --- a/src/chase.cpp +++ b/src/chase.cpp @@ -34,11 +34,11 @@ cvar_t chase_up = { "chase_up", "16" }; cvar_t chase_right = { "chase_right", "0" }; cvar_t chase_active = { "chase_active", "0" }; -vec3_t chase_pos; -vec3_t chase_angles; +Vector3 chase_pos; +Vector3 chase_angles; -vec3_t chase_dest; -vec3_t chase_dest_angles; +Vector3 chase_dest; +Vector3 chase_dest_angles; void Chase_Init(void) { @@ -48,47 +48,44 @@ void Chase_Init(void) Cvar::Register(&chase_active); } -void TraceLine(vec3_t start, vec3_t end, vec3_t impact) +void TraceLine(const Vector3& start, const Vector3& end, Vector3& impact) { trace_t trace; memset(&trace, 0, sizeof(trace)); SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); - VectorCopy(trace.endpos, impact); + impact = trace.endpos; } void Chase_Update(void) { - int i; float dist; - vec3_t forward, up, right; - vec3_t dest, stop; + Vector3 forward, up, right; + Vector3 dest, stop; // if can't see player, reset AngleVectors(cl.viewangles, forward, right, up); // calc exact destination - for (i = 0; i < 3; i++) { - chase_dest[i] = r_refdef.vieworg[i] - forward[i] * chase_back.value - right[i] * chase_right.value; - } - chase_dest[2] = r_refdef.vieworg[2] + chase_up.value; + chase_dest = r_refdef.vieworg - forward * chase_back.value - right * chase_right.value; + chase_dest.z = r_refdef.vieworg.z + chase_up.value; // find the spot the player is looking at - VectorMA(r_refdef.vieworg, 4096, forward, dest); + dest = r_refdef.vieworg + forward * 4096.0f; TraceLine(r_refdef.vieworg, dest, stop); // calculate pitch to look at the same spot from camera - VectorSubtract(stop, r_refdef.vieworg, stop); - dist = DotProduct(stop, forward); + stop = stop - r_refdef.vieworg; + dist = stop.dot(forward); if (dist < 1) { dist = 1; } - r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180; + r_refdef.viewangles[PITCH] = -atan(stop.z / dist) / M_PI * 180; // move towards destination - VectorCopy(chase_dest, r_refdef.vieworg); + r_refdef.vieworg = chase_dest; } } // namespace Client diff --git a/src/client.cpp b/src/client.cpp index 4157dff..3195487 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -46,13 +46,11 @@ cvar_t m_yaw = { "m_yaw", "0.022", true }; cvar_t m_forward = { "m_forward", "1", true }; cvar_t m_side = { "m_side", "0.8", true }; -client_static_t cls; -client_state_t cl; -efrag_t cl_efrags[MAX_EFRAGS]; -entity_t cl_entities[MAX_EDICTS]; -entity_t cl_static_entities[MAX_STATIC_ENTITIES]; -lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; -dlight_t cl_dlights[MAX_DLIGHTS]; +ClientSubsystem& GetClientSubsystem() +{ + static ClientSubsystem subsystem; + return subsystem; +} int cl_numvisedicts; entity_t* cl_visedicts[MAX_VISEDICTS]; @@ -105,8 +103,7 @@ int bitcounts[16]; // from cl_tent.cpp int num_temp_entities; -entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; -beam_t cl_beams[MAX_BEAMS]; +// cl_temp_entities and cl_beams are encapsulated in ClientSubsystem sfx_t* cl_sfx_wizhit; sfx_t* cl_sfx_knighthit; sfx_t* cl_sfx_tink1; @@ -458,9 +455,9 @@ void CL_RelinkEntities(void) entity_t* ent; int i, j; float frac, f, d; - vec3_t delta; + Vector3 delta; float bobjrotate; - vec3_t oldorg; + Vector3 oldorg; dlight_t* dl; // determine partial update time @@ -471,9 +468,7 @@ void CL_RelinkEntities(void) // // interpolate player info // - for (i = 0; i < 3; i++) { - cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); - } + cl.velocity = cl.mvelocity[1] + (cl.mvelocity[0] - cl.mvelocity[1]) * frac; if (cls.demoplayback) { // interpolate the angles @@ -507,25 +502,24 @@ void CL_RelinkEntities(void) continue; } - VectorCopy(ent->origin, oldorg); + oldorg = ent->origin; if (ent->forcelink) { // the entity was not updated in the last message // so move to the final spot - VectorCopy(ent->msg_origins[0], ent->origin); - VectorCopy(ent->msg_angles[0], ent->angles); + ent->origin = ent->msg_origins[0]; + ent->angles = ent->msg_angles[0]; } else { // if the delta is large, assume a teleport and don't lerp f = frac; + delta = ent->msg_origins[0] - ent->msg_origins[1]; for (j = 0; j < 3; j++) { - delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j]; if (delta[j] > 100 || delta[j] < -100) { f = 1; // assume a teleportation, not a motion } } // interpolate the origin and angles + ent->origin = ent->msg_origins[1] + delta * f; for (j = 0; j < 3; j++) { - ent->origin[j] = ent->msg_origins[1][j] + f * delta[j]; - d = ent->msg_angles[0][j] - ent->msg_angles[1][j]; if (d > 180) { d -= 360; @@ -547,14 +541,14 @@ void CL_RelinkEntities(void) } if (ent->effects & EF_MUZZLEFLASH) { - vec3_t fv, rv, uv; + Vector3 fv, rv, uv; dl = CL_AllocDlight(i); - VectorCopy(ent->origin, dl->origin); - dl->origin[2] += 16; + dl->origin = ent->origin; + dl->origin.z += 16; AngleVectors(ent->angles, fv, rv, uv); - VectorMA(dl->origin, 18, fv, dl->origin); + dl->origin += fv * 18; dl->radius = 200 + (rand() & 31); dl->minlight = 32; dl->die = cl.time + 0.1; @@ -1482,13 +1476,12 @@ CL_ParseStartSoundPacket */ void CL_ParseStartSoundPacket(void) { - vec3_t pos; + Vector3 pos; int channel, ent; int sound_num; int packet_vol; int field_mask; float attenuation; - int i; field_mask = MSG_ReadByte(); @@ -1514,9 +1507,9 @@ void CL_ParseStartSoundPacket(void) Host_Error("CL_ParseStartSoundPacket: ent = %i", ent); } - for (i = 0; i < 3; i++) { - pos[i] = MSG_ReadCoord(); - } + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); S_StartSound(ent, channel, cl.sound_precache[sound_num], pos, packet_vol / 255.0, attenuation); } @@ -2090,13 +2083,13 @@ CL_ParseStaticSound */ void CL_ParseStaticSound(void) { - vec3_t org; + Vector3 org; int sound_num, vol, atten; - int i; - for (i = 0; i < 3; i++) { - org[i] = MSG_ReadCoord(); - } + org.x = MSG_ReadCoord(); + org.y = MSG_ReadCoord(); + org.z = MSG_ReadCoord(); + sound_num = MSG_ReadByte(); vol = MSG_ReadByte(); atten = MSG_ReadByte(); @@ -2396,19 +2389,19 @@ CL_ParseBeam void CL_ParseBeam(model_t* m) { int ent; - vec3_t start, end; + Vector3 start, end; beam_t* b; int i; ent = MSG_ReadShort(); - start[0] = MSG_ReadCoord(); - start[1] = MSG_ReadCoord(); - start[2] = MSG_ReadCoord(); + start.x = MSG_ReadCoord(); + start.y = MSG_ReadCoord(); + start.z = MSG_ReadCoord(); - end[0] = MSG_ReadCoord(); - end[1] = MSG_ReadCoord(); - end[2] = MSG_ReadCoord(); + end.x = MSG_ReadCoord(); + end.y = MSG_ReadCoord(); + end.z = MSG_ReadCoord(); // override any beam with the same entity for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++) { @@ -2416,8 +2409,8 @@ void CL_ParseBeam(model_t* m) b->entity = ent; b->model = m; b->endtime = cl.time + 0.2; - VectorCopy(start, b->start); - VectorCopy(end, b->end); + b->start = start; + b->end = end; return; } @@ -2429,8 +2422,8 @@ void CL_ParseBeam(model_t* m) b->entity = ent; b->model = m; b->endtime = cl.time + 0.2; - VectorCopy(start, b->start); - VectorCopy(end, b->end); + b->start = start; + b->end = end; return; } @@ -2446,7 +2439,7 @@ CL_ParseTEnt void CL_ParseTEnt(void) { int type; - vec3_t pos; + Vector3 pos; dlight_t* dl; int rnd; int colorStart, colorLength; @@ -2454,25 +2447,25 @@ void CL_ParseTEnt(void) type = MSG_ReadByte(); switch (type) { case TE_WIZSPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_RunParticleEffect(pos, vec3_origin, 20, 30); S_StartSound(-1, 0, cl_sfx_wizhit, pos, 1, 1); break; case TE_KNIGHTSPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_RunParticleEffect(pos, vec3_origin, 226, 20); S_StartSound(-1, 0, cl_sfx_knighthit, pos, 1, 1); break; case TE_SPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_RunParticleEffect(pos, vec3_origin, 0, 10); if (rand() % 5) { S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1); @@ -2489,9 +2482,9 @@ void CL_ParseTEnt(void) break; case TE_SUPERSPIKE: // super spike hitting wall - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_RunParticleEffect(pos, vec3_origin, 0, 20); if (rand() % 5) { @@ -2510,19 +2503,19 @@ void CL_ParseTEnt(void) break; case TE_GUNSHOT: // bullet hitting wall - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_RunParticleEffect(pos, vec3_origin, 0, 20); break; case TE_EXPLOSION: // rocket explosion - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_ParticleExplosion(pos); dl = CL_AllocDlight(0); - VectorCopy(pos, dl->origin); + dl->origin = pos; dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; @@ -2530,9 +2523,9 @@ void CL_ParseTEnt(void) break; case TE_TAREXPLOSION: // tarbaby explosion - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_BlobExplosion(pos); S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1); @@ -2557,28 +2550,28 @@ void CL_ParseTEnt(void) // PGM 01/21/97 case TE_LAVASPLASH: - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_LavaSplash(pos); break; case TE_TELEPORT: - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); R_TeleportSplash(pos); break; case TE_EXPLOSION2: // color mapped explosion - pos[0] = MSG_ReadCoord(); - pos[1] = MSG_ReadCoord(); - pos[2] = MSG_ReadCoord(); + pos.x = MSG_ReadCoord(); + pos.y = MSG_ReadCoord(); + pos.z = MSG_ReadCoord(); colorStart = MSG_ReadByte(); colorLength = MSG_ReadByte(); R_ParticleExplosion2(pos, colorStart, colorLength); dl = CL_AllocDlight(0); - VectorCopy(pos, dl->origin); + dl->origin = pos; dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; @@ -2628,7 +2621,7 @@ void CL_UpdateTEnts(void) { int i; beam_t* b; - vec3_t dist, org; + Vector3 dist, org; float d; entity_t* ent; float yaw, pitch; @@ -2644,50 +2637,48 @@ void CL_UpdateTEnts(void) // if coming from the player, update the start position if (b->entity == cl.viewentity) { - VectorCopy(cl_entities[cl.viewentity].origin, b->start); + b->start = cl_entities[cl.viewentity].origin; } // calculate pitch and yaw - VectorSubtract(b->end, b->start, dist); + dist = b->end - b->start; - if (dist[1] == 0 && dist[0] == 0) { + if (dist.y == 0 && dist.x == 0) { yaw = 0; - if (dist[2] > 0) { + if (dist.z > 0) { pitch = 90; } else { pitch = 270; } } else { - yaw = (int)(atan2(dist[1], dist[0]) * 180 / M_PI); + yaw = (int)(atan2(dist.y, dist.x) * 180 / M_PI); if (yaw < 0) { yaw += 360; } - forward = sqrt(dist[0] * dist[0] + dist[1] * dist[1]); - pitch = (int)(atan2(dist[2], forward) * 180 / M_PI); + forward = sqrt(dist.x * dist.x + dist.y * dist.y); + pitch = (int)(atan2(dist.z, forward) * 180 / M_PI); if (pitch < 0) { pitch += 360; } } // add new entities for the lightning - VectorCopy(b->start, org); - d = VectorNormalize(dist); + org = b->start; + d = dist.normalize(); while (d > 0) { ent = CL_NewTempEntity(); if (!ent) { return; } - VectorCopy(org, ent->origin); + ent->origin = org; ent->model = b->model; ent->angles[0] = pitch; ent->angles[1] = yaw; ent->angles[2] = rand() % 360; - for (i = 0; i < 3; i++) { - org[i] += dist[i] * 30; - } + org += dist * 30; d -= 30; } } diff --git a/src/client.hpp b/src/client.hpp index c2914a5..ae2a963 100644 --- a/src/client.hpp +++ b/src/client.hpp @@ -2,7 +2,7 @@ #pragma once typedef struct { - vec3_t viewangles; + Vector3 viewangles; // intended velocities float forwardmove; @@ -45,7 +45,7 @@ typedef struct { #define MAX_DLIGHTS 32 typedef struct { - vec3_t origin; + Vector3 origin; float radius; float die; // stop lighting after this time float decay; // drop this each second @@ -59,7 +59,7 @@ typedef struct { int entity; struct model_s* model; float endtime; - vec3_t start, end; + Vector3 start, end; } beam_t; #define MAX_EFRAGS 640 @@ -109,8 +109,6 @@ typedef struct { namespace Client { -extern client_static_t cls; - // // the client_state_t structure is wiped completely at every // server signon @@ -135,15 +133,15 @@ typedef struct { // sent to the server each frame. The server sets punchangle when // the view is temporarliy offset, and an angle reset commands at the start // of each level and after teleporting. - vec3_t mviewangles[2]; // during demo playback viewangles is lerped + Vector3 mviewangles[2]; // during demo playback viewangles is lerped // between these - vec3_t viewangles; + Vector3 viewangles; - vec3_t mvelocity[2]; // update by server, used for lean+bob + Vector3 mvelocity[2]; // update by server, used for lean+bob // (0 is newest) - vec3_t velocity; // lerped between mvelocity[0] and [1] + Vector3 velocity; // lerped between mvelocity[0] and [1] - vec3_t punchangle; // temporary offset + Vector3 punchangle; // temporary offset // pitch drifting vars float idealpitch; @@ -232,16 +230,53 @@ extern cvar_t m_side; #define MAX_TEMP_ENTITIES 64 // lightning bolts, etc #define MAX_STATIC_ENTITIES 128 // torches, etc -extern client_state_t cl; - -// FIXME, allocate dynamically -extern efrag_t cl_efrags[MAX_EFRAGS]; -extern entity_t cl_entities[MAX_EDICTS]; -extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; -extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; -extern dlight_t cl_dlights[MAX_DLIGHTS]; -extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; -extern beam_t cl_beams[MAX_BEAMS]; +using EfragArray = efrag_t[MAX_EFRAGS]; +using EntityArray = entity_t[MAX_EDICTS]; +using StaticEntityArray = entity_t[MAX_STATIC_ENTITIES]; +using LightstyleArray = lightstyle_t[MAX_LIGHTSTYLES]; +using DlightArray = dlight_t[MAX_DLIGHTS]; +using TempEntityArray = entity_t[MAX_TEMP_ENTITIES]; +using BeamArray = beam_t[MAX_BEAMS]; + +class ClientSubsystem { +public: + client_static_t& GetStaticState() { return cls_; } + const client_static_t& GetStaticState() const { return cls_; } + + client_state_t& GetState() { return cl_; } + const client_state_t& GetState() const { return cl_; } + + EfragArray& GetEfrags() { return cl_efrags_; } + EntityArray& GetEntities() { return cl_entities_; } + StaticEntityArray& GetStaticEntities() { return cl_static_entities_; } + LightstyleArray& GetLightstyles() { return cl_lightstyle_; } + DlightArray& GetDlights() { return cl_dlights_; } + TempEntityArray& GetTempEntities() { return cl_temp_entities_; } + BeamArray& GetBeams() { return cl_beams_; } + +private: + client_static_t cls_; + client_state_t cl_; + efrag_t cl_efrags_[MAX_EFRAGS]; + entity_t cl_entities_[MAX_EDICTS]; + entity_t cl_static_entities_[MAX_STATIC_ENTITIES]; + lightstyle_t cl_lightstyle_[MAX_LIGHTSTYLES]; + dlight_t cl_dlights_[MAX_DLIGHTS]; + entity_t cl_temp_entities_[MAX_TEMP_ENTITIES]; + beam_t cl_beams_[MAX_BEAMS]; +}; + +ClientSubsystem& GetClientSubsystem(); + +inline client_static_t& cls = GetClientSubsystem().GetStaticState(); +inline client_state_t& cl = GetClientSubsystem().GetState(); +inline EfragArray& cl_efrags = GetClientSubsystem().GetEfrags(); +inline EntityArray& cl_entities = GetClientSubsystem().GetEntities(); +inline StaticEntityArray& cl_static_entities = GetClientSubsystem().GetStaticEntities(); +inline LightstyleArray& cl_lightstyle = GetClientSubsystem().GetLightstyles(); +inline DlightArray& cl_dlights = GetClientSubsystem().GetDlights(); +inline TempEntityArray& cl_temp_entities = GetClientSubsystem().GetTempEntities(); +inline BeamArray& cl_beams = GetClientSubsystem().GetBeams(); //============================================================================= diff --git a/src/cmd.cpp b/src/cmd.cpp index 3366559..f5650cb 100644 --- a/src/cmd.cpp +++ b/src/cmd.cpp @@ -29,121 +29,79 @@ using namespace Cmd; namespace Cmd { -void ForwardToServer(void); - -#define MAX_ALIAS_NAME 32 - -typedef struct cmdalias_s { - struct cmdalias_s* next; - char name[MAX_ALIAS_NAME]; - char* value; -} cmdalias_t; - -static cmdalias_t* cmd_alias = nullptr; - -static qboolean cmd_wait = false; +CommandRegistry& GetCommandRegistry() +{ + static CommandRegistry registry; + return registry; +} //============================================================================= /* ============ Wait_f - -Causes execution of the remainder of the command buffer to be delayed until -next frame. This allows commands like: -bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2" ============ */ static void Wait_f(void) { - cmd_wait = true; + GetCommandRegistry().GetCmdWait() = true; } //============================================================================= // COMMAND BUFFER //============================================================================= -static sizebuf_t cmd_text; - -/* -============ -BufferInit -============ -*/ -void BufferInit(void) +void CommandRegistry::BufferInit(void) { - SZ_Alloc(&cmd_text, 8192); // space for commands and script files + SZ_Alloc(&cmd_text_, 8192); // space for commands and script files } -/* -============ -BufferAddText - -Adds command text at the end of the buffer -============ -*/ -void BufferAddText(std::string_view text) +void CommandRegistry::BufferAddText(std::string_view text) { int l = static_cast(text.length()); - if (cmd_text.cursize + l >= cmd_text.maxsize) { + if (cmd_text_.cursize + l >= cmd_text_.maxsize) { Con_Printf("Cmd::BufferAddText: overflow\n"); return; } - SZ_Write(&cmd_text, const_cast(text.data()), l); + SZ_Write(&cmd_text_, const_cast(text.data()), l); } -/* -============ -BufferInsertText - -Adds command text immediately after the current command -Adds a \n to the text -============ -*/ -void BufferInsertText(std::string_view text) +void CommandRegistry::BufferInsertText(std::string_view text) { - int templen = cmd_text.cursize; + int templen = cmd_text_.cursize; char* temp = nullptr; if (templen) { temp = (char *) Z_Malloc(templen); - Q_memcpy(temp, cmd_text.data, templen); - SZ_Clear(&cmd_text); + Q_memcpy(temp, cmd_text_.data, templen); + SZ_Clear(&cmd_text_); } - // add the entire text of the file BufferAddText(text); - // add the copied off data if (templen) { - SZ_Write(&cmd_text, temp, templen); + SZ_Write(&cmd_text_, temp, templen); Z_Free(temp); } } -/* -============ -BufferExecute -============ -*/ -void BufferExecute(void) +void CommandRegistry::BufferExecute(void) { char line[1024]; - while (cmd_text.cursize) { - // find a \n or ; line break - char* text = (char*)cmd_text.data; + while (cmd_text_.cursize) { + char* text = (char*)cmd_text_.data; int quotes = 0; int i; - for (i = 0; i < cmd_text.cursize; i++) { + for (i = 0; i < cmd_text_.cursize; i++) { if (text[i] == '"') { quotes++; } if (!(quotes & 1) && text[i] == ';') { - break; // don't break if inside a quoted string + break; } if (text[i] == '\n') { @@ -154,20 +112,18 @@ void BufferExecute(void) std::memcpy(line, text, i); line[i] = 0; - // delete the text from the command buffer and move remaining commands down - if (i == cmd_text.cursize) { - cmd_text.cursize = 0; + if (i == cmd_text_.cursize) { + cmd_text_.cursize = 0; } else { i++; - cmd_text.cursize -= i; - Q_memcpy(text, text + i, cmd_text.cursize); + cmd_text_.cursize -= i; + Q_memcpy(text, text + i, cmd_text_.cursize); } - // execute the command line ExecuteString(line, Source::Command); - if (cmd_wait) { // skip out while text still remains in buffer, leaving it for next frame - cmd_wait = false; + if (cmd_wait_) { + cmd_wait_ = false; break; } } @@ -177,22 +133,13 @@ void BufferExecute(void) // SCRIPT COMMANDS //============================================================================== -/* -=============== -StuffCmds_f - -Adds command line parameters as script statements -Commands lead with a +, and continue until a - or another + -=============== -*/ static void StuffCmds_f(void) { - if (Argc() != 1) { + if (Cmd::Argc() != 1) { Con_Printf("stuffcmds : execute command line parameters\n"); return; } - // build the combined string to parse from int s = 0; for (int i = 1; i < com_argc; i++) { if (!com_argv[i]) { @@ -217,7 +164,6 @@ static void StuffCmds_f(void) } } - // pull out the commands char* build = (char *) Z_Malloc(s + 1); build[0] = 0; @@ -240,27 +186,22 @@ static void StuffCmds_f(void) } if (build[0]) { - BufferInsertText(build); + Cmd::BufferInsertText(build); } Z_Free(text); Z_Free(build); } -/* -=============== -Exec_f -=============== -*/ static void Exec_f(void) { - if (Argc() != 2) { + if (Cmd::Argc() != 2) { Con_Printf("exec : execute a script file\n"); return; } int mark = Hunk_LowMark(); - std::string_view filename = Argv(1); + std::string_view filename = Cmd::Argv(1); char* f = (char*)COM_LoadHunkFile(const_cast(filename.data())); if (!f) { Con_Printf("couldn't exec %.*s\n", static_cast(filename.length()), filename.data()); @@ -269,32 +210,18 @@ static void Exec_f(void) Con_Printf("execing %.*s\n", static_cast(filename.length()), filename.data()); - BufferInsertText(f); + Cmd::BufferInsertText(f); Hunk_FreeToLowMark(mark); } -/* -=============== -Echo_f - -Just prints the rest of the line to the console -=============== -*/ static void Echo_f(void) { - for (int i = 1; i < Argc(); i++) { - Con_Printf("%.*s ", static_cast(Argv(i).length()), Argv(i).data()); + for (int i = 1; i < Cmd::Argc(); i++) { + Con_Printf("%.*s ", static_cast(Cmd::Argv(i).length()), Cmd::Argv(i).data()); } Con_Printf("\n"); } -/* -=============== -Alias_f - -Creates a new command that executes a command string (possibly ; seperated) -=============== -*/ static char* CopyString(const char* in) { char* out = (char *) Z_Malloc(static_cast(std::strlen(in)) + 1); @@ -307,22 +234,21 @@ static void Alias_f(void) cmdalias_t* a; char cmd[1024]; - if (Argc() == 1) { + if (Cmd::Argc() == 1) { Con_Printf("Current alias commands:\n"); - for (a = cmd_alias; a; a = a->next) { + for (a = GetCommandRegistry().GetAliases(); a; a = a->next) { Con_Printf("%s : %s\n", a->name, a->value); } return; } - std::string_view alias_name = Argv(1); - if (alias_name.length() >= MAX_ALIAS_NAME) { + std::string_view alias_name = Cmd::Argv(1); + if (alias_name.length() >= 32) { // MAX_ALIAS_NAME Con_Printf("Alias name is too long\n"); return; } - // if the alias allready exists, reuse it - for (a = cmd_alias; a; a = a->next) { + for (a = GetCommandRegistry().GetAliases(); a; a = a->next) { if (alias_name == a->name) { Z_Free(a->value); break; @@ -331,18 +257,17 @@ static void Alias_f(void) if (!a) { a = (cmdalias_t *) Z_Malloc(sizeof(cmdalias_t)); - a->next = cmd_alias; - cmd_alias = a; + a->next = GetCommandRegistry().GetAliases(); + GetCommandRegistry().GetAliases() = a; } std::memcpy(a->name, alias_name.data(), alias_name.length()); a->name[alias_name.length()] = '\0'; - // copy the rest of the command line - cmd[0] = 0; // start out with a null string - int c = Argc(); + cmd[0] = 0; + int c = Cmd::Argc(); for (int i = 2; i < c; i++) { - std::strcat(cmd, Argv(i).data()); + std::strcat(cmd, Cmd::Argv(i).data()); if (i != c) { std::strcat(cmd, " "); } @@ -356,26 +281,7 @@ static void Alias_f(void) // COMMAND EXECUTION //============================================================================= -typedef struct cmd_function_s { - struct cmd_function_s* next; - char* name; - xcommand_t function; -} cmd_function_t; - -#define MAX_ARGS 80 - -static int cmd_argc = 0; -static char* cmd_argv[MAX_ARGS]; -static std::string_view cmd_args; - -static cmd_function_t* cmd_functions = nullptr; // possible commands to execute - -/* -============ -Init -============ -*/ -void Init(void) +void CommandRegistry::Init(void) { AddCommand("stuffcmds", StuffCmds_f); AddCommand("exec", Exec_f); @@ -385,55 +291,81 @@ void Init(void) AddCommand("wait", Wait_f); } -/* -============ -Argc -============ -*/ -int Argc(void) +void CommandRegistry::AddCommand(std::string_view cmd_name, xcommand_t function) +{ + if (host_initialized) { + Sys_Error("Cmd::AddCommand after host_initialized"); + } + + if (Cvar::FindVar(cmd_name) != nullptr) { + Con_Printf("Cmd::AddCommand: %.*s already defined as a var\n", static_cast(cmd_name.length()), cmd_name.data()); + return; + } + + if (Exists(cmd_name)) { + Con_Printf("Cmd::AddCommand: %.*s already defined\n", static_cast(cmd_name.length()), cmd_name.data()); + return; + } + + cmd_function_t* cmd = (cmd_function_t*) Hunk_Alloc(sizeof(cmd_function_t), "cmd"); + cmd->name = (char*) Hunk_Alloc(static_cast(cmd_name.length()) + 1, "cmdname"); + std::memcpy(cmd->name, cmd_name.data(), cmd_name.length()); + cmd->name[cmd_name.length()] = '\0'; + cmd->function = function; + cmd->next = cmd_functions_; + cmd_functions_ = cmd; +} + +bool CommandRegistry::Exists(std::string_view cmd_name) { - return cmd_argc; + for (cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { + if (cmd_name == cmd->name) { + return true; + } + } + return false; } -/* -============ -Argv -============ -*/ -std::string_view Argv(int arg) +std::string_view CommandRegistry::CompleteCommand(std::string_view partial) { - if (arg < 0 || arg >= cmd_argc) { + if (partial.empty()) { return ""; } - return cmd_argv[arg]; + + for (cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { + if (std::string_view(cmd->name).starts_with(partial)) { + return cmd->name; + } + } + return ""; } -/* -============ -Args -============ -*/ -std::string_view Args(void) +int CommandRegistry::Argc(void) { - return cmd_args; + return cmd_argc_; } -/* -============ -TokenizeString +std::string_view CommandRegistry::Argv(int arg) +{ + if (arg < 0 || arg >= cmd_argc_) { + return ""; + } + return cmd_argv_[arg]; +} -Parses the given string into command line tokens. -============ -*/ -void TokenizeString(std::string_view text) +std::string_view CommandRegistry::Args(void) +{ + return cmd_args_; +} + +void CommandRegistry::TokenizeString(std::string_view text) { - // clear the args from the last string - for (int i = 0; i < cmd_argc; i++) { - Z_Free(cmd_argv[i]); + for (int i = 0; i < cmd_argc_; i++) { + Z_Free(cmd_argv_[i]); } - cmd_argc = 0; - cmd_args = ""; + cmd_argc_ = 0; + cmd_args_ = ""; if (text.empty()) { return; @@ -443,12 +375,11 @@ void TokenizeString(std::string_view text) bool command_parsed = false; while (true) { - // skip whitespace up to a /n while (*ptr && *ptr <= ' ' && *ptr != '\n') { ptr++; } - if (*ptr == '\n') { // a newline separates commands in the buffer + if (*ptr == '\n') { ptr++; break; } @@ -457,8 +388,8 @@ void TokenizeString(std::string_view text) return; } - if (command_parsed && cmd_args.empty()) { - cmd_args = std::string_view(ptr); + if (command_parsed && cmd_args_.empty()) { + cmd_args_ = std::string_view(ptr); } char* next_ptr = COM_Parse(const_cast(ptr)); @@ -471,126 +402,42 @@ void TokenizeString(std::string_view text) command_parsed = true; } - if (cmd_argc < MAX_ARGS) { - cmd_argv[cmd_argc] = (char *) Z_Malloc(Q_strlen(com_token) + 1); - Q_strcpy(cmd_argv[cmd_argc], com_token); - cmd_argc++; - } - } -} - -/* -============ -AddCommand -============ -*/ -void AddCommand(std::string_view cmd_name, xcommand_t function) -{ - if (host_initialized) { // because hunk allocation would get stomped - Sys_Error("Cmd::AddCommand after host_initialized"); - } - - // fail if the command is a variable name - if (Cvar::FindVar(cmd_name) != nullptr) { - Con_Printf("Cmd::AddCommand: %.*s already defined as a var\n", static_cast(cmd_name.length()), cmd_name.data()); - return; - } - - // check to see if it has allready been defined - if (Exists(cmd_name)) { - Con_Printf("Cmd::AddCommand: %.*s already defined\n", static_cast(cmd_name.length()), cmd_name.data()); - return; - } - - cmd_function_t* cmd = (cmd_function_t*) Hunk_Alloc(sizeof(cmd_function_t), "cmd"); - cmd->name = (char*) Hunk_Alloc(static_cast(cmd_name.length()) + 1, "cmdname"); - std::memcpy(cmd->name, cmd_name.data(), cmd_name.length()); - cmd->name[cmd_name.length()] = '\0'; - cmd->function = function; - cmd->next = cmd_functions; - cmd_functions = cmd; -} - -/* -============ -Exists -============ -*/ -bool Exists(std::string_view cmd_name) -{ - for (cmd_function_t* cmd = cmd_functions; cmd; cmd = cmd->next) { - if (cmd_name == cmd->name) { - return true; - } - } - return false; -} - -/* -============ -CompleteCommand -============ -*/ -std::string_view CompleteCommand(std::string_view partial) -{ - if (partial.empty()) { - return ""; - } - - for (cmd_function_t* cmd = cmd_functions; cmd; cmd = cmd->next) { - if (std::string_view(cmd->name).starts_with(partial)) { - return cmd->name; + if (cmd_argc_ < 80) { // MAX_ARGS + cmd_argv_[cmd_argc_] = (char *) Z_Malloc(Q_strlen(com_token) + 1); + Q_strcpy(cmd_argv_[cmd_argc_], com_token); + cmd_argc_++; } } - return ""; } -/* -============ -ExecuteString - -A complete command line has been parsed, so try to execute it -============ -*/ -void ExecuteString(std::string_view text, Source src) +void CommandRegistry::ExecuteString(std::string_view text, Source src) { - state.source = src; + state_.source = src; TokenizeString(text); - // execute the command line if (!Argc()) { - return; // no tokens + return; } - // check functions - for (cmd_function_t* cmd = cmd_functions; cmd; cmd = cmd->next) { - if (Q_strcasecmp(cmd_argv[0], cmd->name) == 0) { + for (cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { + if (Q_strcasecmp(cmd_argv_[0], cmd->name) == 0) { cmd->function(); return; } } - // check alias - for (cmdalias_t* a = cmd_alias; a; a = a->next) { - if (Q_strcasecmp(cmd_argv[0], a->name) == 0) { + for (cmdalias_t* a = cmd_alias_; a; a = a->next) { + if (Q_strcasecmp(cmd_argv_[0], a->name) == 0) { BufferInsertText(a->value); return; } } - // check cvars if (!Cvar::Command()) { Con_Printf("Unknown command \"%.*s\"\n", static_cast(Argv(0).length()), Argv(0).data()); } } -/* -=================== -ForwardToServer - -Sends the entire command line over to the server -=================== -*/ void ForwardToServer(void) { if (cls.state != ca_connected) { @@ -599,7 +446,7 @@ void ForwardToServer(void) } if (cls.demoplayback) { - return; // not really connected + return; } MSG_WriteByte(&cls.message, clc_stringcmd); @@ -615,4 +462,27 @@ void ForwardToServer(void) } } +void CommandRegistry::Print(std::string_view text) +{ + Con_Printf("%.*s", static_cast(text.length()), text.data()); +} + +// Wrapper APIs forwarding to the singleton registry + +void BufferInit(void) { GetCommandRegistry().BufferInit(); } +void BufferAddText(std::string_view text) { GetCommandRegistry().BufferAddText(text); } +void BufferInsertText(std::string_view text) { GetCommandRegistry().BufferInsertText(text); } +void BufferExecute(void) { GetCommandRegistry().BufferExecute(); } +void Init(void) { GetCommandRegistry().Init(); } +void AddCommand(std::string_view cmd_name, xcommand_t function) { GetCommandRegistry().AddCommand(cmd_name, function); } +bool Exists(std::string_view cmd_name) { return GetCommandRegistry().Exists(cmd_name); } +std::string_view CompleteCommand(std::string_view partial) { return GetCommandRegistry().CompleteCommand(partial); } +int Argc(void) { return GetCommandRegistry().Argc(); } +std::string_view Argv(int arg) { return GetCommandRegistry().Argv(arg); } +std::string_view Args(void) { return GetCommandRegistry().Args(); } +void TokenizeString(std::string_view text) { GetCommandRegistry().TokenizeString(text); } +void ExecuteString(std::string_view text, Source src) { GetCommandRegistry().ExecuteString(text, src); } +// ForwardToServer is implemented directly above +void Print(std::string_view text) { GetCommandRegistry().Print(text); } + } // namespace Cmd \ No newline at end of file diff --git a/src/cmd.hpp b/src/cmd.hpp index 042a379..3112e20 100644 --- a/src/cmd.hpp +++ b/src/cmd.hpp @@ -14,7 +14,61 @@ enum class Source { struct State { Source source = Source::Command; }; -inline State state; + +struct cmdalias_t { + cmdalias_t* next; + char name[32]; // MAX_ALIAS_NAME + char* value; +}; + +struct cmd_function_t { + cmd_function_t* next; + char* name; + xcommand_t function; +}; + +class CommandRegistry { +public: + void BufferInit(void); + void BufferAddText(std::string_view text); + void BufferInsertText(std::string_view text); + void BufferExecute(void); + void Init(void); + void AddCommand(std::string_view cmd_name, xcommand_t function); + bool Exists(std::string_view cmd_name); + std::string_view CompleteCommand(std::string_view partial); + int Argc(void); + std::string_view Argv(int arg); + std::string_view Args(void); + void TokenizeString(std::string_view text); + void ExecuteString(std::string_view text, Source src); + void Print(std::string_view text); + + State& GetState() { return state_; } + const State& GetState() const { return state_; } + + cmd_function_t*& GetFunctions() { return cmd_functions_; } + cmdalias_t*& GetAliases() { return cmd_alias_; } + sizebuf_t& GetCmdText() { return cmd_text_; } + bool& GetCmdWait() { return cmd_wait_; } + int& GetCmdArgc() { return cmd_argc_; } + char** GetCmdArgv() { return cmd_argv_; } + std::string_view& GetCmdArgs() { return cmd_args_; } + +private: + State state_; + sizebuf_t cmd_text_; + bool cmd_wait_ = false; + cmdalias_t* cmd_alias_ = nullptr; + cmd_function_t* cmd_functions_ = nullptr; + int cmd_argc_ = 0; + char* cmd_argv_[80]; // MAX_ARGS + std::string_view cmd_args_; +}; + +CommandRegistry& GetCommandRegistry(); + +inline State& state = GetCommandRegistry().GetState(); void BufferInit(void); diff --git a/src/common.cpp b/src/common.cpp index 3cadadb..19d5e10 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -1649,6 +1649,8 @@ void COM_InitFilesystem(void) } } +/* TODO: fix cache dir for UNIX */ +#if 0 // // -cachedir // Overrides the system supplied cache directory (NULL or /qcache) @@ -1666,6 +1668,7 @@ void COM_InitFilesystem(void) } else { com_cachedir[0] = 0; } +#endif // // start up with GAMENAME by default (id1) diff --git a/src/console.cpp b/src/console.cpp index 0d3e3bb..1606826 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -1,6 +1,10 @@ // console.cpp -- console text display and input +#ifdef _MSC_VER #include +#else +#include +#endif #include #include "quakedef.hpp" @@ -343,9 +347,9 @@ void Con_DebugLog(const char* file, const char* fmt, ...) va_start(argptr, fmt); vsprintf(data, fmt, argptr); va_end(argptr); - fd = _open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); - _write(fd, data, (unsigned int)strlen(data)); - _close(fd); + fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); + write(fd, data, (unsigned int)strlen(data)); + close(fd); } /* diff --git a/src/cvar.cpp b/src/cvar.cpp index 2eb9730..445d516 100644 --- a/src/cvar.cpp +++ b/src/cvar.cpp @@ -29,14 +29,20 @@ using namespace Cmd; namespace Cvar { +CvarRegistry& GetCvarRegistry() +{ + static CvarRegistry registry; + return registry; +} + /* ============ FindVar ============ */ -cvar_t* FindVar(std::string_view var_name) +cvar_t* CvarRegistry::FindVar(std::string_view var_name) { - for (cvar_t* var = state.vars; var; var = var->next) { + for (cvar_t* var = state_.vars; var; var = var->next) { if (var_name == var->name) { return var; } @@ -49,7 +55,7 @@ cvar_t* FindVar(std::string_view var_name) VariableValue ============ */ -float VariableValue(std::string_view var_name) +float CvarRegistry::VariableValue(std::string_view var_name) { cvar_t* var = FindVar(var_name); if (!var) { @@ -63,7 +69,7 @@ float VariableValue(std::string_view var_name) VariableString ============ */ -std::string_view VariableString(std::string_view var_name) +std::string_view CvarRegistry::VariableString(std::string_view var_name) { cvar_t* var = FindVar(var_name); if (!var) { @@ -77,13 +83,13 @@ std::string_view VariableString(std::string_view var_name) CompleteVariable ============ */ -std::string_view CompleteVariable(std::string_view partial) +std::string_view CvarRegistry::CompleteVariable(std::string_view partial) { if (partial.empty()) { return ""; } - for (cvar_t* var = state.vars; var; var = var->next) { + for (cvar_t* var = state_.vars; var; var = var->next) { if (std::string_view(var->name).starts_with(partial)) { return var->name; } @@ -96,7 +102,7 @@ std::string_view CompleteVariable(std::string_view partial) Set ============ */ -void Set(std::string_view var_name, std::string_view value) +void CvarRegistry::Set(std::string_view var_name, std::string_view value) { cvar_t* var = FindVar(var_name); if (!var) { @@ -108,8 +114,8 @@ void Set(std::string_view var_name, std::string_view value) Z_Free(const_cast(var->string)); // free the old value string - char* new_str = (char *) Z_Malloc(value.length() + 1); - Q_memcpy(new_str, const_cast(value.data()), value.length()); + char* new_str = (char *) Z_Malloc(static_cast(value.length()) + 1); + Q_memcpy(new_str, const_cast(value.data()), static_cast(value.length())); new_str[value.length()] = '\0'; var->string = new_str; var->value = Q_atof(var->string); @@ -125,7 +131,7 @@ void Set(std::string_view var_name, std::string_view value) SetValue ============ */ -void SetValue(std::string_view var_name, float value) +void CvarRegistry::SetValue(std::string_view var_name, float value) { char val[32]; std::sprintf(val, "%f", value); @@ -137,7 +143,7 @@ void SetValue(std::string_view var_name, float value) Register ============ */ -void Register(cvar_t* variable) +void CvarRegistry::Register(cvar_t* variable) { // check to see if it has allready been defined if (FindVar(variable->name)) { @@ -159,8 +165,8 @@ void Register(cvar_t* variable) variable->value = Q_atof(variable->string); // link the variable in - variable->next = state.vars; - state.vars = variable; + variable->next = state_.vars; + state_.vars = variable; } /* @@ -168,7 +174,7 @@ void Register(cvar_t* variable) Command ============ */ -qboolean Command(void) +qboolean CvarRegistry::Command(void) { cvar_t* v = FindVar(Cmd::Argv(0)); if (!v) { @@ -190,13 +196,59 @@ qboolean Command(void) WriteVariables ============ */ -void WriteVariables(std::FILE* f) +void CvarRegistry::WriteVariables(std::FILE* f) { - for (cvar_t* var = state.vars; var; var = var->next) { + for (cvar_t* var = state_.vars; var; var = var->next) { if (var->archive) { std::fprintf(f, "%s \"%s\"\n", var->name, var->string); } } } +// Wrapper APIs forwarding to the singleton registry +cvar_t* FindVar(std::string_view var_name) +{ + return GetCvarRegistry().FindVar(var_name); +} + +float VariableValue(std::string_view var_name) +{ + return GetCvarRegistry().VariableValue(var_name); +} + +std::string_view VariableString(std::string_view var_name) +{ + return GetCvarRegistry().VariableString(var_name); +} + +std::string_view CompleteVariable(std::string_view partial) +{ + return GetCvarRegistry().CompleteVariable(partial); +} + +void Set(std::string_view var_name, std::string_view value) +{ + GetCvarRegistry().Set(var_name, value); +} + +void SetValue(std::string_view var_name, float value) +{ + GetCvarRegistry().SetValue(var_name, value); +} + +void Register(cvar_t* variable) +{ + GetCvarRegistry().Register(variable); +} + +qboolean Command(void) +{ + return GetCvarRegistry().Command(); +} + +void WriteVariables(std::FILE* f) +{ + GetCvarRegistry().WriteVariables(f); +} + } // namespace Cvar diff --git a/src/cvar.hpp b/src/cvar.hpp index c890a00..5f39d65 100644 --- a/src/cvar.hpp +++ b/src/cvar.hpp @@ -17,7 +17,29 @@ namespace Cvar { struct State { cvar_t* vars = nullptr; }; -inline State state; + +class CvarRegistry { +public: + void Register(cvar_t* variable); + void Set(std::string_view var_name, std::string_view value); + void SetValue(std::string_view var_name, float value); + float VariableValue(std::string_view var_name); + std::string_view VariableString(std::string_view var_name); + std::string_view CompleteVariable(std::string_view partial); + qboolean Command(void); + void WriteVariables(std::FILE* f); + cvar_t* FindVar(std::string_view var_name); + + State& GetState() { return state_; } + const State& GetState() const { return state_; } + +private: + State state_; +}; + +CvarRegistry& GetCvarRegistry(); + +inline State& state = GetCvarRegistry().GetState(); void Register(cvar_t* variable); diff --git a/src/d_local.hpp b/src/d_local.hpp index 3ea9ab8..437ffc3 100644 --- a/src/d_local.hpp +++ b/src/d_local.hpp @@ -48,7 +48,7 @@ void D_DrawSkyScans8(espan_t* pspan); void D_DrawSkyScans16(espan_t* pspan); void R_ShowSubDiv(void); -surfcache_t* D_CacheSurface(msurface_t* surface, int miplevel); +surfcache_t* D_CacheSurface(msurface_t* surface, int mip_level); extern short* d_pzbuffer; diff --git a/src/host.cpp b/src/host.cpp index 177c5ab..4c60007 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -48,8 +48,6 @@ int minimum_memory; client_t* host_client; // current client -jmp_buf host_abortserver; - byte* host_basepal; byte* host_colormap; @@ -73,7 +71,7 @@ cvar_t temp1 = { "temp1", "0" }; Host_EndGame ================ */ -void Host_EndGame(const char* message, ...) +[[noreturn]] void Host_EndGame(const char* message, ...) { va_list argptr; char string[1024]; @@ -97,7 +95,7 @@ void Host_EndGame(const char* message, ...) CL_Disconnect(); } - longjmp(host_abortserver, 1); + throw Host::HostEndGameException(string); } /* @@ -139,7 +137,7 @@ This shuts down both the client and server inerror = false; - longjmp(host_abortserver, 1); + throw Host::HostErrorException(string); } /* @@ -645,100 +643,97 @@ void _Host_Frame(float time) static double time3 = 0; int pass1, pass2, pass3; -#pragma warning(push) -#pragma warning(disable : 4611) - if (setjmp(host_abortserver)) { - return; // something bad happened, or the server disconnected - } -#pragma warning(pop) + try { + // keep the random time dependent + rand(); - // keep the random time dependent - rand(); + // decide the simulation time + if (!Host_FilterTime(time)) { + return; // don't run too fast, or packets will flood out + } - // decide the simulation time - if (!Host_FilterTime(time)) { - return; // don't run too fast, or packets will flood out - } + // get new key events + Sys_SendKeyEvents(); - // get new key events - Sys_SendKeyEvents(); + // allow mice or other external controllers to add commands + IN_Commands(); - // allow mice or other external controllers to add commands - IN_Commands(); + // process console commands + Cmd::BufferExecute(); - // process console commands - Cmd::BufferExecute(); + NET_Poll(); - NET_Poll(); + // if running the server locally, make intentions now + if (sv.active) { + CL_SendCmd(); + } - // if running the server locally, make intentions now - if (sv.active) { - CL_SendCmd(); - } + //------------------- + // + // server operations + // + //------------------- - //------------------- - // - // server operations - // - //------------------- + // check for commands typed to the host + Host_GetConsoleCommands(); - // check for commands typed to the host - Host_GetConsoleCommands(); + if (sv.active) { + Host_ServerFrame(); + } - if (sv.active) { - Host_ServerFrame(); - } + //------------------- + // + // client operations + // + //------------------- - //------------------- - // - // client operations - // - //------------------- + // if running the server remotely, send intentions now after + // the incoming messages have been read + if (!sv.active) { + CL_SendCmd(); + } - // if running the server remotely, send intentions now after - // the incoming messages have been read - if (!sv.active) { - CL_SendCmd(); - } + host_time += host_frametime; - host_time += host_frametime; + // fetch results from server + if (cls.state == ca_connected) { + CL_ReadFromServer(); + } - // fetch results from server - if (cls.state == ca_connected) { - CL_ReadFromServer(); - } + // update video + if (host_speeds.value) { + time1 = Sys_FloatTime(); + } - // update video - if (host_speeds.value) { - time1 = Sys_FloatTime(); - } + SCR_UpdateScreen(); - SCR_UpdateScreen(); + if (host_speeds.value) { + time2 = Sys_FloatTime(); + } - if (host_speeds.value) { - time2 = Sys_FloatTime(); - } + // update audio + if (cls.signon == SIGNONS) { + S_Update(r_origin, vpn, vright, vup); + CL_DecayLights(); + } else { + S_Update(vec3_origin, vec3_origin, vec3_origin, vec3_origin); + } - // update audio - if (cls.signon == SIGNONS) { - S_Update(r_origin, vpn, vright, vup); - CL_DecayLights(); - } else { - S_Update(vec3_origin, vec3_origin, vec3_origin, vec3_origin); - } + CDAudio_Update(); - CDAudio_Update(); + if (host_speeds.value) { + pass1 = (time1 - time3) * 1000; + time3 = Sys_FloatTime(); + pass2 = (time2 - time1) * 1000; + pass3 = (time3 - time2) * 1000; + Con_Printf("%3i tot %3i server %3i gfx %3i snd\n", pass1 + pass2 + pass3, + pass1, pass2, pass3); + } - if (host_speeds.value) { - pass1 = (time1 - time3) * 1000; - time3 = Sys_FloatTime(); - pass2 = (time2 - time1) * 1000; - pass3 = (time3 - time2) * 1000; - Con_Printf("%3i tot %3i server %3i gfx %3i snd\n", pass1 + pass2 + pass3, - pass1, pass2, pass3); + host_framecount++; + } catch (const Host::HostException&) { + return; // something bad happened, or the server disconnected } - - host_framecount++; } void Host_Frame(float time) diff --git a/src/host.hpp b/src/host.hpp index 2696613..93f091f 100644 --- a/src/host.hpp +++ b/src/host.hpp @@ -33,8 +33,23 @@ void Host_ServerFrame(void); void Host_InitCommands(void); void Host_Init(quakeparms_t* parms); void Host_Shutdown(void); +class HostException : public std::runtime_error { +public: + explicit HostException(const std::string& msg) : std::runtime_error(msg) {} +}; + +class HostEndGameException : public HostException { +public: + using HostException::HostException; +}; + +class HostErrorException : public HostException { +public: + using HostException::HostException; +}; + [[noreturn]] void Host_Error(const char* error, ...); -void Host_EndGame(const char* message, ...); +[[noreturn]] void Host_EndGame(const char* message, ...); void Host_Frame(float time); void Host_Quit_f(void); void Host_ClientCommands(const char* fmt, ...); @@ -46,7 +61,6 @@ extern int minimum_memory; extern qboolean noclip_anglehack; extern client_t* host_client; -extern jmp_buf host_abortserver; extern double host_time; } // namespace Host diff --git a/src/mathlib.cpp b/src/mathlib.cpp index a7b9185..3759925 100644 --- a/src/mathlib.cpp +++ b/src/mathlib.cpp @@ -30,7 +30,7 @@ using namespace Cmd; namespace Math { -vec3_t vec3_origin = { 0, 0, 0 }; +Vector3 vec3_origin = { 0, 0, 0 }; int nanmask = 255 << 23; /*-----------------------------------------------------------------*/ @@ -53,160 +53,11 @@ BOPS_Error Split out like this for ASM to call. ================== */ -inline void BOPS_Error(void) +void BOPS_Error(void) { Sys_Error("BoxOnPlaneSide: Bad signbits"); } -/* -================== -BoxOnPlaneSide - -Returns 1, 2, or 1 + 2 -================== -*/ -int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, mplane_t* p) -{ - float dist1, dist2; - int sides; - - // general case - switch (p->signbits) { - case 0: - dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; - dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; - break; - case 1: - dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; - dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; - break; - case 2: - dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; - dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; - break; - case 3: - dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; - dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; - break; - case 4: - dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; - dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; - break; - case 5: - dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; - dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; - break; - case 6: - dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; - dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; - break; - case 7: - dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; - dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; - break; - default: - dist1 = dist2 = 0; // shut up compiler - BOPS_Error(); - break; - } - - sides = 0; - if (dist1 >= p->dist) { - sides = 1; - } - - if (dist2 < p->dist) { - sides |= 2; - } - - return sides; -} - -void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI * 2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI * 2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI * 2 / 360); - sr = sin(angle); - cr = cos(angle); - - forward[0] = cp * cy; - forward[1] = cp * sy; - forward[2] = -sp; - right[0] = (-1 * sr * sp * cy + -1 * cr * -sy); - right[1] = (-1 * sr * sp * sy + -1 * cr * cy); - right[2] = -1 * sr * cp; - up[0] = (cr * sp * cy + -sr * -sy); - up[1] = (cr * sp * sy + -sr * cy); - up[2] = cr * cp; -} - -void VectorMA(vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) -{ - vecc[0] = veca[0] + scale * vecb[0]; - vecc[1] = veca[1] + scale * vecb[1]; - vecc[2] = veca[2] + scale * vecb[2]; -} - -void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross) -{ - cross[0] = v1[1] * v2[2] - v1[2] * v2[1]; - cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; - cross[2] = v1[0] * v2[1] - v1[1] * v2[0]; -} - -vec_t Length(vec3_t v) -{ - int i; - float length; - - length = 0; - for (i = 0; i < 3; i++) { - length += v[i] * v[i]; - } - length = ::sqrt(length); // FIXME - - return length; -} - -float VectorNormalize(vec3_t v) -{ - float length, ilength; - - length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; - length = ::sqrt(length); // FIXME - - if (length) { - ilength = 1 / length; - v[0] *= ilength; - v[1] *= ilength; - v[2] *= ilength; - } - - return length; -} - -void VectorInverse(vec3_t v) -{ - v[0] = -v[0]; - v[1] = -v[1]; - v[2] = -v[2]; -} - -void VectorScale(vec3_t in, vec_t scale, vec3_t out) -{ - out[0] = in[0] * scale; - out[1] = in[1] * scale; - out[2] = in[2] * scale; -} - /* ================ R_ConcatRotations diff --git a/src/mathlib.hpp b/src/mathlib.hpp index 598eb75..d40ea24 100644 --- a/src/mathlib.hpp +++ b/src/mathlib.hpp @@ -1,8 +1,98 @@ -// mathlib.h -- 3D math primitives (vectors, matrices, fixed-point) +// mathlib.hpp -- 3D math primitives (vectors, matrices, fixed-point) #pragma once +#include + +struct Vector3 { + float x; + float y; + float z; + + constexpr Vector3() : x(0.0f), y(0.0f), z(0.0f) {} + constexpr Vector3(float x, float y, float z) : x(x), y(y), z(z) {} + constexpr Vector3(const float* ptr) : x(ptr[0]), y(ptr[1]), z(ptr[2]) {} + + // Array subscript operators + constexpr float operator[](size_t index) const { + return (&x)[index]; + } + constexpr float& operator[](size_t index) { + return (&x)[index]; + } + + // Implicit conversions to raw pointers + constexpr operator float*() { return &x; } + constexpr operator const float*() const { return &x; } + + // Operator overloads + constexpr Vector3 operator+(const Vector3& other) const { + return {x + other.x, y + other.y, z + other.z}; + } + constexpr Vector3 operator-(const Vector3& other) const { + return {x - other.x, y - other.y, z - other.z}; + } + constexpr Vector3 operator-() const { + return {-x, -y, -z}; + } + constexpr Vector3 operator*(float scale) const { + return {x * scale, y * scale, z * scale}; + } + constexpr Vector3 operator/(float scale) const { + return {x / scale, y / scale, z / scale}; + } + + constexpr Vector3& operator+=(const Vector3& other) { + x += other.x; y += other.y; z += other.z; + return *this; + } + constexpr Vector3& operator-=(const Vector3& other) { + x -= other.x; y -= other.y; z -= other.z; + return *this; + } + constexpr Vector3& operator*=(float scale) { + x *= scale; y *= scale; z *= scale; + return *this; + } + constexpr Vector3& operator/=(float scale) { + x /= scale; y /= scale; z /= scale; + return *this; + } + + constexpr bool operator==(const Vector3& other) const { + return x == other.x && y == other.y && z == other.z; + } + constexpr bool operator!=(const Vector3& other) const { + return !(*this == other); + } + + // Methods + constexpr float dot(const Vector3& other) const { + return x * other.x + y * other.y + z * other.z; + } + + constexpr Vector3 cross(const Vector3& other) const { + return { + y * other.z - z * other.y, + z * other.x - x * other.z, + x * other.y - y * other.x + }; + } + + float length() const { + return std::sqrt(x * x + y * y + z * z); + } + + float normalize() { + float len = length(); + if (len != 0.0f) { + x /= len; + y /= len; + z /= len; + } + return len; + } +}; typedef float vec_t; -typedef vec_t vec3_t[3]; typedef vec_t vec5_t[5]; typedef int fixed4_t; @@ -17,38 +107,83 @@ struct mplane_s; #define IS_NAN(x) (((*(int*)&x) & nanmask) == nanmask) -#define DotProduct(x, y) (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]) -#define VectorSubtract(a, b, c) \ - { \ - c[0] = a[0] - b[0]; \ - c[1] = a[1] - b[1]; \ - c[2] = a[2] - b[2]; \ - } -#define VectorAdd(a, b, c) \ - { \ - c[0] = a[0] + b[0]; \ - c[1] = a[1] + b[1]; \ - c[2] = a[2] + b[2]; \ - } -#define VectorCopy(a, b) \ - { \ - b[0] = a[0]; \ - b[1] = a[1]; \ - b[2] = a[2]; \ - } +// Modern C++ template functions replacing legacy macros +template +inline constexpr float DotProduct(const T& a, const U& b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +template +inline constexpr void VectorSubtract(const T& a, const U& b, V&& c) { + c[0] = a[0] - b[0]; + c[1] = a[1] - b[1]; + c[2] = a[2] - b[2]; +} + +template +inline constexpr void VectorAdd(const T& a, const U& b, V&& c) { + c[0] = a[0] + b[0]; + c[1] = a[1] + b[1]; + c[2] = a[2] + b[2]; +} + +template +inline constexpr void VectorCopy(const T& a, U&& b) { + b[0] = a[0]; + b[1] = a[1]; + b[2] = a[2]; +} namespace Math { -extern vec3_t vec3_origin; +extern Vector3 vec3_origin; extern int nanmask; -void VectorMA(vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); +// Implement all vector math operations as templates in the header +template +inline void VectorMA(const T& veca, float scale, const U& vecb, V&& vecc) { + vecc[0] = veca[0] + scale * vecb[0]; + vecc[1] = veca[1] + scale * vecb[1]; + vecc[2] = veca[2] + scale * vecb[2]; +} + +template +inline vec_t Length(const T& v) { + return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +template +inline void CrossProduct(const T& v1, const U& v2, V&& cross) { + cross[0] = v1[1] * v2[2] - v1[2] * v2[1]; + cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; + cross[2] = v1[0] * v2[1] - v1[1] * v2[0]; +} + +template +inline float VectorNormalize(T&& v) { + float length = std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + if (length != 0.0f) { + float ilength = 1.0f / length; + v[0] *= ilength; + v[1] *= ilength; + v[2] *= ilength; + } + return length; +} + +template +inline void VectorInverse(T&& v) { + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} -vec_t Length(vec3_t v); -void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross); -float VectorNormalize(vec3_t v); // returns vector length -void VectorInverse(vec3_t v); -void VectorScale(vec3_t in, vec_t scale, vec3_t out); +template +inline void VectorScale(const T& in, vec_t scale, U&& out) { + out[0] = in[0] * scale; + out[1] = in[1] * scale; + out[2] = in[2] * scale; +} void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3]); void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4]); @@ -56,8 +191,90 @@ void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4]); void FloorDivMod(double numer, double denom, int* quotient, int* rem); int GreatestCommonDivisor(int i1, int i2); -void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); -int BoxOnPlaneSide(vec3_t emins, vec3_t emaxs, struct mplane_s* plane); +template +inline void AngleVectors(const T& angles, U&& forward, V&& right, W&& up) { + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[1] * (3.14159265358979323846 * 2 / 360); // YAW + sy = std::sin(angle); + cy = std::cos(angle); + angle = angles[0] * (3.14159265358979323846 * 2 / 360); // PITCH + sp = std::sin(angle); + cp = std::cos(angle); + angle = angles[2] * (3.14159265358979323846 * 2 / 360); // ROLL + sr = std::sin(angle); + cr = std::cos(angle); + + forward[0] = cp * cy; + forward[1] = cp * sy; + forward[2] = -sp; + right[0] = (-1 * sr * sp * cy + -1 * cr * -sy); + right[1] = (-1 * sr * sp * sy + -1 * cr * cy); + right[2] = -1 * sr * cp; + up[0] = (cr * sp * cy + -sr * -sy); + up[1] = (cr * sp * sy + -sr * cy); + up[2] = cr * cp; +} + +void BOPS_Error(); + +template +inline int BoxOnPlaneSide(const T& emins, const U& emaxs, P* p) { + float dist1, dist2; + int sides; + + switch (p->signbits) { + case 0: + dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; + dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; + break; + case 1: + dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; + dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; + break; + case 2: + dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; + dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; + break; + case 3: + dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; + dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; + break; + case 4: + dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; + dist2 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; + break; + case 5: + dist1 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]; + dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]; + break; + case 6: + dist1 = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; + dist2 = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; + break; + case 7: + dist1 = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]; + dist2 = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]; + break; + default: + dist1 = dist2 = 0; + BOPS_Error(); + break; + } + + sides = 0; + if (dist1 >= p->dist) { + sides = 1; + } + + if (dist2 < p->dist) { + sides |= 2; + } + + return sides; +} + float anglemod(float a); } // namespace Math @@ -67,4 +284,4 @@ float anglemod(float a); (((p)->type < 3) ? (((p)->dist <= (emins)[(p)->type]) \ ? 1 \ : (((p)->dist >= (emaxs)[(p)->type]) ? 2 : 3)) \ - : BoxOnPlaneSide((emins), (emaxs), (p))) + : BoxOnPlaneSide((emins), (emaxs), (p))) diff --git a/src/model.cpp b/src/model.cpp index 0518c9d..2551f7d 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -93,7 +93,7 @@ void* Mod_Extradata(model_t* mod) Mod_PointInLeaf =============== */ -mleaf_t* Mod_PointInLeaf(vec3_t p, model_t* model) +mleaf_t* Mod_PointInLeaf(const Vector3& p, model_t* model) { mnode_t* node; float d; @@ -110,7 +110,7 @@ mleaf_t* Mod_PointInLeaf(vec3_t p, model_t* model) } plane = node->plane; - d = DotProduct(p, plane->normal) - plane->dist; + d = p.dot(plane->normal) - plane->dist; if (d > 0) { node = node->children[0]; } else { @@ -1161,16 +1161,15 @@ void Mod_LoadPlanes(lump_t* l) RadiusFromBounds ================= */ -float RadiusFromBounds(vec3_t mins, vec3_t maxs) +float RadiusFromBounds(const Vector3& mins, const Vector3& maxs) { - int i; - vec3_t corner; + Vector3 corner; - for (i = 0; i < 3; i++) { - corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]); - } + corner.x = std::max(std::fabs(mins.x), std::fabs(maxs.x)); + corner.y = std::max(std::fabs(mins.y), std::fabs(maxs.y)); + corner.z = std::max(std::fabs(mins.z), std::fabs(maxs.z)); - return Length(corner); + return corner.length(); } /* diff --git a/src/model.hpp b/src/model.hpp index 80593dc..85547d3 100644 --- a/src/model.hpp +++ b/src/model.hpp @@ -27,7 +27,7 @@ BRUSH MODELS // // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { - vec3_t position; + Vector3 position; } mvertex_t; #define SIDE_FRONT 0 @@ -37,7 +37,7 @@ typedef struct { // plane_t structure // !!! if this is changed, it must be changed in asm_i386.h too !!! typedef struct mplane_s { - vec3_t normal; + Vector3 normal; float dist; byte type; // for texture axis selection and fast side tests byte signbits; // signx + signy<<1 + signz<<1 @@ -141,8 +141,8 @@ typedef struct { mplane_t* planes; int firstclipnode; int lastclipnode; - vec3_t clip_mins; - vec3_t clip_maxs; + Vector3 clip_mins; + Vector3 clip_maxs; } hull_t; /* @@ -270,7 +270,7 @@ typedef struct model_s { // // volume occupied by the model // - vec3_t mins, maxs; + Vector3 mins, maxs; float radius; // @@ -338,7 +338,7 @@ model_t* Mod_ForName(const char* name, qboolean crash); void* Mod_Extradata(model_t* mod); void Mod_TouchModel(char* name); -mleaf_t* Mod_PointInLeaf(float* p, model_t* model); +mleaf_t* Mod_PointInLeaf(const Vector3& p, model_t* model); byte* Mod_LeafPVS(mleaf_t* leaf, model_t* model); } // namespace Model diff --git a/src/modelgen.hpp b/src/modelgen.hpp index deabe34..69a1edd 100644 --- a/src/modelgen.hpp +++ b/src/modelgen.hpp @@ -43,10 +43,10 @@ typedef enum { ALIAS_SKIN_SINGLE = 0, typedef struct { int ident; int version; - vec3_t scale; - vec3_t scale_origin; + Vector3 scale; + Vector3 scale_origin; float boundingradius; - vec3_t eyeposition; + Vector3 eyeposition; int numskins; int skinwidth; int skinheight; diff --git a/src/network.cpp b/src/network.cpp index 4f24ed4..6d41aea 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -27,8 +27,8 @@ using namespace Wad; using namespace Cvar; using namespace Cmd; - -#include +#include +#include #ifdef _WIN32 #include @@ -45,10 +45,18 @@ using namespace Cmd; #undef errno #define errno WSAGetLastError() typedef int socklen_t; +#else +#include +#include +#include +#include +#include +#include +#endif + #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif -#endif // VCR op constants #define VCR_OP_CONNECT 1 @@ -638,7 +646,7 @@ int UDP_CheckNewConnections(void) int UDP_Read(int socket, byte* buf, int len, struct qsockaddr* addr) { - int addrlen = sizeof(struct qsockaddr); + socklen_t addrlen = sizeof(struct qsockaddr); int ret; ret = recvfrom(socket, (char*)buf, len, 0, (struct sockaddr*)addr, &addrlen); @@ -738,7 +746,7 @@ int UDP_StringToAddr(const char* string, struct qsockaddr* addr) int UDP_GetSocketAddr(int socket, struct qsockaddr* addr) { - int addrlen = sizeof(struct qsockaddr); + socklen_t addrlen = sizeof(struct qsockaddr); unsigned int a; Q_memset(addr, 0, sizeof(struct qsockaddr)); diff --git a/src/net.hpp b/src/network.hpp similarity index 99% rename from src/net.hpp rename to src/network.hpp index 12a7978..dff6127 100644 --- a/src/net.hpp +++ b/src/network.hpp @@ -1,4 +1,4 @@ -// net.h -- quake's interface to the networking layer +// network.hpp -- quake's interface to the networking layer #pragma once struct qsockaddr { diff --git a/src/progdefs.q1 b/src/progdefs.q1 index eb15c45..a6465ad 100644 --- a/src/progdefs.q1 +++ b/src/progdefs.q1 @@ -34,14 +34,14 @@ typedef struct float parm14; float parm15; float parm16; - vec3_t v_forward; - vec3_t v_up; - vec3_t v_right; + Vector3 v_forward; + Vector3 v_up; + Vector3 v_right; float trace_allsolid; float trace_startsolid; float trace_fraction; - vec3_t trace_endpos; - vec3_t trace_plane_normal; + Vector3 trace_endpos; + Vector3 trace_plane_normal; float trace_plane_dist; int trace_ent; float trace_inopen; @@ -62,25 +62,25 @@ typedef struct typedef struct { float modelindex; - vec3_t absmin; - vec3_t absmax; + Vector3 absmin; + Vector3 absmax; float ltime; float movetype; float solid; - vec3_t origin; - vec3_t oldorigin; - vec3_t velocity; - vec3_t angles; - vec3_t avelocity; - vec3_t punchangle; + Vector3 origin; + Vector3 oldorigin; + Vector3 velocity; + Vector3 angles; + Vector3 avelocity; + Vector3 punchangle; string_t classname; string_t model; float frame; float skin; float effects; - vec3_t mins; - vec3_t maxs; - vec3_t size; + Vector3 mins; + Vector3 maxs; + Vector3 size; func_t touch; func_t use; func_t think; @@ -101,13 +101,13 @@ typedef struct float takedamage; int chain; float deadflag; - vec3_t view_ofs; + Vector3 view_ofs; float button0; float button1; float button2; float impulse; float fixangle; - vec3_t v_angle; + Vector3 v_angle; float idealpitch; string_t netname; int enemy; @@ -131,7 +131,7 @@ typedef struct float dmg_save; int dmg_inflictor; int owner; - vec3_t movedir; + Vector3 movedir; string_t message; float sounds; string_t noise; diff --git a/src/quakedef.hpp b/src/quakedef.hpp index a3a5ded..d98003d 100644 --- a/src/quakedef.hpp +++ b/src/quakedef.hpp @@ -13,12 +13,13 @@ #define GAMENAME "id1" -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "core_types.hpp" inline void VID_LockBuffer(void) {} @@ -168,8 +169,8 @@ inline void VID_UnlockBuffer(void) {} #include "mathlib.hpp" typedef struct { - vec3_t origin; - vec3_t angles; + Vector3 origin; + Vector3 angles; int modelindex; int frame; int colormap; @@ -181,17 +182,17 @@ typedef struct { #include "draw.hpp" #include "cvar.hpp" #include "screen.hpp" -#include "net.hpp" +#include "network.hpp" #include "protocol.hpp" #include "cmd.hpp" #include "sbar.hpp" -#include "sound.hpp" -#include "render.hpp" +#include "audio.hpp" +#include "renderer.hpp" #include "model.hpp" #include "client.hpp" -#include "progs.hpp" +#include "vm.hpp" #include "server.hpp" -#include "d_iface.hpp" +#include "rasterizer.hpp" #include "input.hpp" #include "world.hpp" diff --git a/src/r_local.hpp b/src/r_local.hpp index e1372ef..e4df87a 100644 --- a/src/r_local.hpp +++ b/src/r_local.hpp @@ -53,7 +53,7 @@ extern cvar_t r_drawflat; // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct clipplane_s { - vec3_t normal; + Vector3 normal; float dist; struct clipplane_s* next; byte leftedge; @@ -67,7 +67,7 @@ void R_RenderWorld(void); //============================================================================= -extern vec3_t r_origin; +extern Vector3 r_origin; //============================================================================= @@ -165,7 +165,7 @@ void R_PrintAliasStats(void); void R_PrintTimes(void); void R_PrintDSpeeds(void); void R_AnimateLight(void); -int R_LightPoint(vec3_t p); +int R_LightPoint(const Vector3& p); void R_SetupFrame(void); void R_cshift_f(void); void R_EmitEdge(mvertex_t* pv0, mvertex_t* pv1); diff --git a/src/r_shared.hpp b/src/r_shared.hpp index 4219393..bcebf90 100644 --- a/src/r_shared.hpp +++ b/src/r_shared.hpp @@ -85,17 +85,17 @@ extern int r_drawnpolycount; extern int sintable[SIN_BUFFER_SIZE]; extern int intsintable[SIN_BUFFER_SIZE]; -extern vec3_t vup, base_vup; -extern vec3_t vpn, base_vpn; -extern vec3_t vright, base_vright; +extern Vector3 vup, base_vup; +extern Vector3 vpn, base_vpn; +extern Vector3 vright, base_vright; extern entity_t* currententity; extern surf_t *surfaces, *surface_p, *surf_max; -extern vec3_t sxformaxis[4]; -extern vec3_t txformaxis[4]; +extern Vector3 sxformaxis[4]; +extern Vector3 txformaxis[4]; -extern vec3_t modelorg, base_modelorg; +extern Vector3 modelorg, base_modelorg; extern float xcenter, ycenter; extern float xscale, yscale; @@ -104,7 +104,7 @@ extern float xscaleshrink, yscaleshrink; extern int d_lightstylevalue[256]; -extern void TransformVector(vec3_t in, vec3_t out); +extern void TransformVector(const Vector3& in, Vector3& out); extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, fixed8_t endvertu, diff --git a/src/rasterizer.cpp b/src/rasterizer.cpp index 3ef2b2a..3ad9785 100644 --- a/src/rasterizer.cpp +++ b/src/rasterizer.cpp @@ -84,7 +84,7 @@ float scale_for_mip; int ubasestep, errorterm, erroradjustup, erroradjustdown; int vstartscan; -vec3_t transformed_modelorg; +Vector3 transformed_modelorg; // d_surf.cpp float surfscale; @@ -120,14 +120,7 @@ typedef struct { int* prightedgevert2; } edgetable; -typedef struct { - int quotient; - int remainder; -} adivtab_t; -static adivtab_t adivtab[32 * 32] = { -#include "adivtab.hpp" -}; typedef struct { void* pdest; @@ -385,8 +378,8 @@ void D_CalcGradients(msurface_t* pface) { mplane_t* pplane; float mipscale; - vec3_t p_temp1; - vec3_t p_saxis, p_taxis; + Vector3 p_temp1; + Vector3 p_saxis, p_taxis; float t; pplane = pface->plane; @@ -397,21 +390,21 @@ void D_CalcGradients(msurface_t* pface) TransformVector(pface->texinfo->vecs[1], p_taxis); t = xscaleinv * mipscale; - d_sdivzstepu = p_saxis[0] * t; - d_tdivzstepu = p_taxis[0] * t; + d_sdivzstepu = p_saxis.x * t; + d_tdivzstepu = p_taxis.x * t; t = yscaleinv * mipscale; - d_sdivzstepv = -p_saxis[1] * t; - d_tdivzstepv = -p_taxis[1] * t; + d_sdivzstepv = -p_saxis.y * t; + d_tdivzstepv = -p_taxis.y * t; - d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv; - d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv; + d_sdivzorigin = p_saxis.z * mipscale - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv; + d_tdivzorigin = p_taxis.z * mipscale - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv; - VectorScale(transformed_modelorg, mipscale, p_temp1); + p_temp1 = transformed_modelorg * mipscale; t = 0x10000 * mipscale; - sadjust = ((fixed16_t)(DotProduct(p_temp1, p_saxis) * 0x10000 + 0.5)) - ((pface->texturemins[0] << 16) >> miplevel) + pface->texinfo->vecs[0][3] * t; - tadjust = ((fixed16_t)(DotProduct(p_temp1, p_taxis) * 0x10000 + 0.5)) - ((pface->texturemins[1] << 16) >> miplevel) + pface->texinfo->vecs[1][3] * t; + sadjust = ((fixed16_t)(p_temp1.dot(p_saxis) * 0x10000 + 0.5)) - ((pface->texturemins[0] << 16) >> miplevel) + pface->texinfo->vecs[0][3] * t; + tadjust = ((fixed16_t)(p_temp1.dot(p_taxis) * 0x10000 + 0.5)) - ((pface->texturemins[1] << 16) >> miplevel) + pface->texinfo->vecs[1][3] * t; bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; @@ -422,12 +415,12 @@ void D_DrawSurfaces(void) surf_t* s; msurface_t* pface; surfcache_t* pcurrentcache; - vec3_t world_transformed_modelorg; - vec3_t local_modelorg; + Vector3 world_transformed_modelorg; + Vector3 local_modelorg; currententity = &cl_entities[0]; TransformVector(modelorg, transformed_modelorg); - VectorCopy(transformed_modelorg, world_transformed_modelorg); + world_transformed_modelorg = transformed_modelorg; if (r_drawflat.value) { for (s = &surfaces[1]; s < surface_p; s++) { @@ -476,7 +469,7 @@ void D_DrawSurfaces(void) if (s->insubmodel) { currententity = s->entity; - VectorSubtract(r_origin, currententity->origin, local_modelorg); + local_modelorg = r_origin - currententity->origin; TransformVector(local_modelorg, transformed_modelorg); R_RotateBmodel(); @@ -488,17 +481,17 @@ void D_DrawSurfaces(void) if (s->insubmodel) { currententity = &cl_entities[0]; - VectorCopy(world_transformed_modelorg, transformed_modelorg); - VectorCopy(base_vpn, vpn); - VectorCopy(base_vup, vup); - VectorCopy(base_vright, vright); - VectorCopy(base_modelorg, modelorg); + transformed_modelorg = world_transformed_modelorg; + vpn = base_vpn; + vup = base_vup; + vright = base_vright; + modelorg = base_modelorg; R_TransformFrustum(); } } else { if (s->insubmodel) { currententity = s->entity; - VectorSubtract(r_origin, currententity->origin, local_modelorg); + local_modelorg = r_origin - currententity->origin; TransformVector(local_modelorg, transformed_modelorg); R_RotateBmodel(); @@ -520,11 +513,11 @@ void D_DrawSurfaces(void) if (s->insubmodel) { currententity = &cl_entities[0]; - VectorCopy(world_transformed_modelorg, transformed_modelorg); - VectorCopy(base_vpn, vpn); - VectorCopy(base_vup, vup); - VectorCopy(base_vright, vright); - VectorCopy(base_modelorg, modelorg); + transformed_modelorg = world_transformed_modelorg; + vpn = base_vpn; + vup = base_vup; + vright = base_vright; + modelorg = base_modelorg; R_TransformFrustum(); } } @@ -877,7 +870,7 @@ void D_DrawZSpans(espan_t* pspan) void D_Sky_uv_To_st(int u, int v, fixed16_t* s, fixed16_t* t) { float wu, wv, temp; - vec3_t end; + Vector3 end; if (r_refdef.vrect.width >= r_refdef.vrect.height) { temp = (float)r_refdef.vrect.width; @@ -888,15 +881,13 @@ void D_Sky_uv_To_st(int u, int v, fixed16_t* s, fixed16_t* t) wu = 8192.0 * (float)(u - ((int)vid.width >> 1)) / temp; wv = 8192.0 * (float)(((int)vid.height >> 1) - v) / temp; - end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; - end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; - end[2] = 4096 * vpn[2] + wu * vright[2] + wv * vup[2]; - end[2] *= 3; - VectorNormalize(end); + end = vpn * 4096.0f + vright * wu + vup * wv; + end.z *= 3.0f; + end.normalize(); temp = skytime * skyspeed; - *s = (int)((temp + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000); - *t = (int)((temp + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000); + *s = (int)((temp + 6 * (SKYSIZE / 2 - 1) * end.x) * 0x10000); + *t = (int)((temp + 6 * (SKYSIZE / 2 - 1) * end.y) * 0x10000); } void D_DrawSkyScans8(espan_t* pspan) @@ -1127,7 +1118,7 @@ surfcache_t* D_SCAlloc(int width, int size) return new_surf; } -surfcache_t* D_CacheSurface(msurface_t* surface, int miplevel) +surfcache_t* D_CacheSurface(msurface_t* surface, int mip_level) { surfcache_t* cache; @@ -1137,23 +1128,23 @@ surfcache_t* D_CacheSurface(msurface_t* surface, int miplevel) r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]]; - cache = surface->cachespots[miplevel]; + cache = surface->cachespots[mip_level]; if (cache && !cache->dlight && surface->dlightframe != r_framecount && cache->texture == r_drawsurf.texture && cache->lightadj[0] == r_drawsurf.lightadj[0] && cache->lightadj[1] == r_drawsurf.lightadj[1] && cache->lightadj[2] == r_drawsurf.lightadj[2] && cache->lightadj[3] == r_drawsurf.lightadj[3]) { return cache; } - surfscale = 1.0 / (1 << miplevel); - r_drawsurf.surfmip = miplevel; - r_drawsurf.surfwidth = surface->extents[0] >> miplevel; + surfscale = 1.0 / (1 << mip_level); + r_drawsurf.surfmip = mip_level; + r_drawsurf.surfwidth = surface->extents[0] >> mip_level; r_drawsurf.rowbytes = r_drawsurf.surfwidth; - r_drawsurf.surfheight = surface->extents[1] >> miplevel; + r_drawsurf.surfheight = surface->extents[1] >> mip_level; if (!cache) { cache = D_SCAlloc(r_drawsurf.surfwidth, r_drawsurf.surfwidth * r_drawsurf.surfheight); - surface->cachespots[miplevel] = cache; - cache->owner = &surface->cachespots[miplevel]; + surface->cachespots[mip_level] = cache; + cache->owner = &surface->cachespots[mip_level]; cache->mipscale = surfscale; } @@ -1176,7 +1167,7 @@ surfcache_t* D_CacheSurface(msurface_t* surface, int miplevel) c_surf++; R_DrawSurface(); - return surface->cachespots[miplevel]; + return surface->cachespots[mip_level]; } // ============================================================== @@ -1462,33 +1453,33 @@ void D_SpriteScanRightEdge(void) void D_SpriteCalculateGradients(void) { - vec3_t p_normal, p_saxis, p_taxis, p_temp1; + Vector3 p_normal, p_saxis, p_taxis, p_temp1; float distinv; TransformVector(r_spritedesc.vpn, p_normal); TransformVector(r_spritedesc.vright, p_saxis); TransformVector(r_spritedesc.vup, p_taxis); - VectorInverse(p_taxis); + p_taxis = -p_taxis; - distinv = 1.0 / (-DotProduct(modelorg, r_spritedesc.vpn)); + distinv = 1.0 / (-modelorg.dot(r_spritedesc.vpn)); - d_sdivzstepu = p_saxis[0] * xscaleinv; - d_tdivzstepu = p_taxis[0] * xscaleinv; + d_sdivzstepu = p_saxis.x * xscaleinv; + d_tdivzstepu = p_taxis.x * xscaleinv; - d_sdivzstepv = -p_saxis[1] * yscaleinv; - d_tdivzstepv = -p_taxis[1] * yscaleinv; + d_sdivzstepv = -p_saxis.y * yscaleinv; + d_tdivzstepv = -p_taxis.y * yscaleinv; - d_zistepu = p_normal[0] * xscaleinv * distinv; - d_zistepv = -p_normal[1] * yscaleinv * distinv; + d_zistepu = p_normal.x * xscaleinv * distinv; + d_zistepv = -p_normal.y * yscaleinv * distinv; - d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv; - d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv; - d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv; + d_sdivzorigin = p_saxis.z - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv; + d_tdivzorigin = p_taxis.z - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv; + d_ziorigin = p_normal.z * distinv - xcenter * d_zistepu - ycenter * d_zistepv; TransformVector(modelorg, p_temp1); - sadjust = ((fixed16_t)(DotProduct(p_temp1, p_saxis) * 0x10000 + 0.5)) - (-(cachewidth >> 1) << 16); - tadjust = ((fixed16_t)(DotProduct(p_temp1, p_taxis) * 0x10000 + 0.5)) - (-(sprite_height >> 1) << 16); + sadjust = ((fixed16_t)(p_temp1.dot(p_saxis) * 0x10000 + 0.5)) - (-(cachewidth >> 1) << 16); + tadjust = ((fixed16_t)(p_temp1.dot(p_taxis) * 0x10000 + 0.5)) - (-(sprite_height >> 1) << 16); bbextents = (cachewidth << 16) - 1; bbextentt = (sprite_height << 16) - 1; @@ -1857,26 +1848,18 @@ void D_PolysetSetUpForLineScan(fixed8_t startvertu, { double dm, dn; int tm, tn; - adivtab_t* ptemp; errorterm = -1; tm = endvertu - startvertu; tn = endvertv - startvertv; - if (((tm <= 16) && (tm >= -15)) && ((tn <= 16) && (tn >= -15))) { - ptemp = &adivtab[((tm + 15) << 5) + (tn + 15)]; - ubasestep = ptemp->quotient; - erroradjustup = ptemp->remainder; - erroradjustdown = tn; - } else { - dm = (double)tm; - dn = (double)tn; + dm = (double)tm; + dn = (double)tn; - FloorDivMod(dm, dn, &ubasestep, &erroradjustup); + FloorDivMod(dm, dn, &ubasestep, &erroradjustup); - erroradjustdown = dn; - } + erroradjustdown = tn; } void D_PolysetCalcGradients(int s_width) @@ -2210,25 +2193,25 @@ void D_StartParticles(void) void D_DrawParticle(particle_t* pparticle) { - vec3_t local, transformed; + Vector3 local, transformed; float zi; byte* pdest; short* pz; int i, izi, pix, count, u, v; - VectorSubtract(pparticle->org, r_origin, local); + local = pparticle->org - r_origin; - transformed[0] = DotProduct(local, r_pright); - transformed[1] = DotProduct(local, r_pup); - transformed[2] = DotProduct(local, r_ppn); + transformed.x = local.dot(r_pright); + transformed.y = local.dot(r_pup); + transformed.z = local.dot(r_ppn); - if (transformed[2] < PARTICLE_Z_CLIP) { + if (transformed.z < PARTICLE_Z_CLIP) { return; } - zi = 1.0 / transformed[2]; - u = (int)(xcenter + zi * transformed[0] + 0.5); - v = (int)(ycenter - zi * transformed[1] + 0.5); + zi = 1.0 / transformed.z; + u = (int)(xcenter + zi * transformed.x + 0.5); + v = (int)(ycenter - zi * transformed.y + 0.5); if ((v > d_vrectbottom_particle) || (u > d_vrectright_particle) || (v < d_vrecty) || (u < d_vrectx)) { return; diff --git a/src/d_iface.hpp b/src/rasterizer.hpp similarity index 95% rename from src/d_iface.hpp rename to src/rasterizer.hpp index 880845c..5d0c660 100644 --- a/src/d_iface.hpp +++ b/src/rasterizer.hpp @@ -1,4 +1,4 @@ -// d_iface.h: interface header file for rasterization driver modules +// rasterizer.hpp: interface header file for rasterization driver modules #pragma once #define WARP_WIDTH 320 @@ -26,11 +26,11 @@ typedef enum { // !!! if this is changed, it must be changed in d_ifacea.h too !!! typedef struct particle_s { // driver-usable fields - vec3_t org; + Vector3 org; float color; // drivers never touch the following fields struct particle_s* next; - vec3_t vel; + Vector3 vel; float ramp; float die; ptype_t type; @@ -80,7 +80,7 @@ typedef struct { // if the driver wants to duplicate element [0] at // element [nump] to avoid dealing with wrapping mspriteframe_t* pspriteframe; - vec3_t vup, vright, vpn; // in worldspace + Vector3 vup, vright, vpn; // in worldspace float nearzi; } spritedesc_t; @@ -114,7 +114,7 @@ extern polydesc_t r_polydesc; extern int d_con_indirect; -extern vec3_t r_pright, r_pup, r_ppn; +extern Vector3 r_pright, r_pup, r_ppn; void D_Aff8Patch(void* pcolormap); inline void D_EnableBackBufferAccess(void) diff --git a/src/renderer.cpp b/src/renderer.cpp index bb66d01..b3f99f6 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -34,7 +34,7 @@ namespace Render { namespace { int r_bmodelactive; mnode_t* r_pefragtopnode; - vec3_t r_emins, r_emaxs; + Vector3 r_emins, r_emaxs; int r_dlightframecount; int c_faceclip; clipplane_t view_clipplanes[4]; @@ -46,9 +46,9 @@ namespace { edge_t edge_head; edge_t edge_tail; edge_t edge_aftertail; - vec3_t r_entorigin; + Vector3 r_entorigin; float entity_rotation[3][3]; - vec3_t r_worldmodelorg; + Vector3 r_worldmodelorg; int r_currentbkey; mtriangle_t* ptriangles; mdl_t* pmdl; @@ -478,13 +478,13 @@ LIGHT SAMPLING ============================================================================= */ -int RecursiveLightPoint(mnode_t* node, vec3_t start, vec3_t end) +int RecursiveLightPoint(mnode_t* node, const Vector3& start, const Vector3& end) { int r; float front, back, frac; int side; mplane_t* plane; - vec3_t mid; + Vector3 mid; msurface_t* surf; int s, t, ds, dt; int i; @@ -501,8 +501,8 @@ int RecursiveLightPoint(mnode_t* node, vec3_t start, vec3_t end) // FIXME: optimize for axial plane = node->plane; - front = DotProduct(start, plane->normal) - plane->dist; - back = DotProduct(end, plane->normal) - plane->dist; + front = start.dot(plane->normal) - plane->dist; + back = end.dot(plane->normal) - plane->dist; side = front < 0; if ((back < 0) == side) { @@ -510,9 +510,7 @@ int RecursiveLightPoint(mnode_t* node, vec3_t start, vec3_t end) } frac = front / (front - back); - mid[0] = start[0] + (end[0] - start[0]) * frac; - mid[1] = start[1] + (end[1] - start[1]) * frac; - mid[2] = start[2] + (end[2] - start[2]) * frac; + mid = start + (end - start) * frac; // go down front side r = RecursiveLightPoint(node->children[side], start, mid); @@ -534,8 +532,8 @@ int RecursiveLightPoint(mnode_t* node, vec3_t start, vec3_t end) tex = surf->texinfo; - s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3]; - t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3]; + s = mid.dot(tex->vecs[0]) + tex->vecs[0][3]; + t = mid.dot(tex->vecs[1]) + tex->vecs[1][3]; ; if (s < surf->texturemins[0] || t < surf->texturemins[1]) { @@ -577,18 +575,16 @@ int RecursiveLightPoint(mnode_t* node, vec3_t start, vec3_t end) return RecursiveLightPoint(node->children[!side], mid, end); } -int R_LightPoint(vec3_t p) +int R_LightPoint(const Vector3& p) { - vec3_t end; + Vector3 end; int r; if (!cl.worldmodel->lightdata) { return 255; } - end[0] = p[0]; - end[1] = p[1]; - end[2] = p[2] - 2048; + end = p - Vector3(0.0f, 0.0f, 2048.0f); r = RecursiveLightPoint(cl.worldmodel->nodes, p, end); @@ -623,7 +619,7 @@ particle_t *active_particles, *free_particles; particle_t* particles; int r_numparticles; -vec3_t r_pright, r_pup, r_ppn; +Vector3 r_pright, r_pup, r_ppn; /* =============== @@ -657,8 +653,8 @@ R_EntityParticles */ #define NUMVERTEXNORMALS 162 -extern float r_avertexnormals[NUMVERTEXNORMALS][3]; -vec3_t avelocities[NUMVERTEXNORMALS]; +float r_avertexnormals[NUMVERTEXNORMALS][3]; +Vector3 avelocities[NUMVERTEXNORMALS]; float beamlength = 16; void R_EntityParticles(entity_t* ent) @@ -668,13 +664,13 @@ void R_EntityParticles(entity_t* ent) particle_t* p; float angle; float sr, sp, sy, cr, cp, cy; - vec3_t forward; + Vector3 forward; float dist; dist = 64; count = 50; - if (!avelocities[0][0]) { + if (!avelocities[0].x) { for (int j = 0; j < NUMVERTEXNORMALS; j++) { for (i = 0; i < 3; i++) { avelocities[j][i] = (rand() & 255) * 0.01f; @@ -683,19 +679,19 @@ void R_EntityParticles(entity_t* ent) } for (i = 0; i < NUMVERTEXNORMALS; i++) { - angle = cl.time * avelocities[i][0]; + angle = cl.time * avelocities[i].x; sy = sin(angle); cy = cos(angle); - angle = cl.time * avelocities[i][1]; + angle = cl.time * avelocities[i].y; sp = sin(angle); cp = cos(angle); - angle = cl.time * avelocities[i][2]; + angle = cl.time * avelocities[i].z; sr = sin(angle); cr = cos(angle); - forward[0] = cp * cy; - forward[1] = cp * sy; - forward[2] = -sp; + forward.x = cp * cy; + forward.y = cp * sy; + forward.z = -sp; if (!free_particles) { return; @@ -710,9 +706,7 @@ void R_EntityParticles(entity_t* ent) p->color = 0x6f; p->type = pt_explode; - p->org[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + forward[0] * beamlength; - p->org[1] = ent->origin[1] + r_avertexnormals[i][1] * dist + forward[1] * beamlength; - p->org[2] = ent->origin[2] + r_avertexnormals[i][2] * dist + forward[2] * beamlength; + p->org = ent->origin + Vector3(r_avertexnormals[i][0], r_avertexnormals[i][1], r_avertexnormals[i][2]) * dist + forward * beamlength; } } @@ -737,7 +731,7 @@ void R_ClearParticles(void) void R_ReadPointFile_f(void) { FILE* f; - vec3_t org; + Vector3 org; int r; int c; particle_t* p; @@ -775,8 +769,8 @@ void R_ReadPointFile_f(void) p->die = 99999; p->color = (-c) & 15; p->type = pt_static; - VectorCopy(vec3_origin, p->vel); - VectorCopy(org, p->org); + p->vel = vec3_origin; + p->org = org; } fclose(f); @@ -792,15 +786,17 @@ Parse an effect out of the server message */ void R_ParseParticleEffect(void) { - vec3_t org, dir; - int i, count, msgcount, color; + Vector3 org, dir; + int count, msgcount, color; + + org.x = MSG_ReadCoord(); + org.y = MSG_ReadCoord(); + org.z = MSG_ReadCoord(); + + dir.x = MSG_ReadChar() * (1.0f / 16.0f); + dir.y = MSG_ReadChar() * (1.0f / 16.0f); + dir.z = MSG_ReadChar() * (1.0f / 16.0f); - for (i = 0; i < 3; i++) { - org[i] = MSG_ReadCoord(); - } - for (i = 0; i < 3; i++) { - dir[i] = MSG_ReadChar() * (1.0 / 16); - } msgcount = MSG_ReadByte(); color = MSG_ReadByte(); @@ -819,9 +815,9 @@ R_ParticleExplosion =============== */ -void R_ParticleExplosion(vec3_t org) +void R_ParticleExplosion(const Vector3& org) { - int i, j; + int i; particle_t* p; for (i = 0; i < 1024; i++) { @@ -839,17 +835,11 @@ void R_ParticleExplosion(vec3_t org) p->ramp = rand() & 3; if (i & 1) { p->type = pt_explode; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } } else { p->type = pt_explode2; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } } + p->org = org + Vector3((rand() % 32) - 16, (rand() % 32) - 16, (rand() % 32) - 16); + p->vel = Vector3((rand() % 512) - 256, (rand() % 512) - 256, (rand() % 512) - 256); } } @@ -859,9 +849,9 @@ R_ParticleExplosion2 =============== */ -void R_ParticleExplosion2(vec3_t org, int colorStart, int colorLength) +void R_ParticleExplosion2(const Vector3& org, int colorStart, int colorLength) { - int i, j; + int i; particle_t* p; int colorMod = 0; @@ -880,10 +870,8 @@ void R_ParticleExplosion2(vec3_t org, int colorStart, int colorLength) colorMod++; p->type = pt_blob; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } + p->org = org + Vector3((rand() % 32) - 16, (rand() % 32) - 16, (rand() % 32) - 16); + p->vel = Vector3((rand() % 512) - 256, (rand() % 512) - 256, (rand() % 512) - 256); } } @@ -893,9 +881,9 @@ R_BlobExplosion =============== */ -void R_BlobExplosion(vec3_t org) +void R_BlobExplosion(const Vector3& org) { - int i, j; + int i; particle_t* p; for (i = 0; i < 1024; i++) { @@ -913,18 +901,12 @@ void R_BlobExplosion(vec3_t org) if (i & 1) { p->type = pt_blob; p->color = 66 + rand() % 6; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } } else { p->type = pt_blob2; p->color = 150 + rand() % 6; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } } + p->org = org + Vector3((rand() % 32) - 16, (rand() % 32) - 16, (rand() % 32) - 16); + p->vel = Vector3((rand() % 512) - 256, (rand() % 512) - 256, (rand() % 512) - 256); } } @@ -934,9 +916,9 @@ R_RunParticleEffect =============== */ -void R_RunParticleEffect(vec3_t org, vec3_t dir, int color, int count) +void R_RunParticleEffect(const Vector3& org, const Vector3& dir, int color, int count) { - int i, j; + int i; particle_t* p; for (i = 0; i < count; i++) { @@ -955,25 +937,17 @@ void R_RunParticleEffect(vec3_t org, vec3_t dir, int color, int count) p->ramp = rand() & 3; if (i & 1) { p->type = pt_explode; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } } else { p->type = pt_explode2; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() % 32) - 16); - p->vel[j] = (rand() % 512) - 256; - } } + p->org = org + Vector3((rand() % 32) - 16, (rand() % 32) - 16, (rand() % 32) - 16); + p->vel = Vector3((rand() % 512) - 256, (rand() % 512) - 256, (rand() % 512) - 256); } else { p->die = cl.time + 0.1 * (rand() % 5); p->color = (color & ~7) + (rand() & 7); p->type = pt_slowgrav; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((rand() & 15) - 8); - p->vel[j] = dir[j] * 15; // + (rand()%300)-150; - } + p->org = org + Vector3((rand() & 15) - 8, (rand() & 15) - 8, (rand() & 15) - 8); + p->vel = dir * 15; // + (rand()%300)-150; } } } @@ -984,12 +958,12 @@ R_LavaSplash =============== */ -void R_LavaSplash(vec3_t org) +void R_LavaSplash(const Vector3& org) { int i, j, k; particle_t* p; float vel; - vec3_t dir; + Vector3 dir; for (i = -16; i < 16; i++) { for (j = -16; j < 16; j++) { @@ -1007,17 +981,15 @@ void R_LavaSplash(vec3_t org) p->color = 224 + (rand() & 7); p->type = pt_slowgrav; - dir[0] = j * 8 + (rand() & 7); - dir[1] = i * 8 + (rand() & 7); - dir[2] = 256; + dir.x = j * 8 + (rand() & 7); + dir.y = i * 8 + (rand() & 7); + dir.z = 256; - p->org[0] = org[0] + dir[0]; - p->org[1] = org[1] + dir[1]; - p->org[2] = org[2] + (rand() & 63); + p->org = org + Vector3(dir.x, dir.y, (float)(rand() & 63)); - VectorNormalize(dir); + dir.normalize(); vel = 50 + (rand() & 63); - VectorScale(dir, vel, p->vel); + p->vel = dir * vel; } } } @@ -1029,12 +1001,12 @@ R_TeleportSplash =============== */ -void R_TeleportSplash(vec3_t org) +void R_TeleportSplash(const Vector3& org) { int i, j, k; particle_t* p; float vel; - vec3_t dir; + Vector3 dir; for (i = -16; i < 16; i += 4) { for (j = -16; j < 16; j += 4) { @@ -1052,33 +1024,28 @@ void R_TeleportSplash(vec3_t org) p->color = 7 + (rand() & 7); p->type = pt_slowgrav; - dir[0] = j * 8; - dir[1] = i * 8; - dir[2] = k * 8; + dir = Vector3(j * 8, i * 8, k * 8); - p->org[0] = org[0] + i + (rand() & 3); - p->org[1] = org[1] + j + (rand() & 3); - p->org[2] = org[2] + k + (rand() & 3); + p->org = org + Vector3(i + (rand() & 3), j + (rand() & 3), k + (rand() & 3)); - VectorNormalize(dir); + dir.normalize(); vel = 50 + (rand() & 63); - VectorScale(dir, vel, p->vel); + p->vel = dir * vel; } } } } -void R_RocketTrail(vec3_t start, vec3_t end, int type) +void R_RocketTrail(Vector3 start, const Vector3& end, int type) { - vec3_t vec; + Vector3 vec; float len; - int j; particle_t* p; int dec; static int tracercount; - VectorSubtract(end, start, vec); - len = VectorNormalize(vec); + vec = end - start; + len = vec.normalize(); if (type < 128) { dec = 3; } else { @@ -1098,7 +1065,7 @@ void R_RocketTrail(vec3_t start, vec3_t end, int type) p->next = active_particles; active_particles = p; - VectorCopy(vec3_origin, p->vel); + p->vel = vec3_origin; p->die = cl.time + 2; switch (type) { @@ -1106,26 +1073,20 @@ void R_RocketTrail(vec3_t start, vec3_t end, int type) p->ramp = (rand() & 3); p->color = ramp3[(int)p->ramp]; p->type = pt_fire; - for (j = 0; j < 3; j++) { - p->org[j] = start[j] + ((rand() % 6) - 3); - } + p->org = start + Vector3((rand() % 6) - 3, (rand() % 6) - 3, (rand() % 6) - 3); break; case 1: // smoke smoke p->ramp = (rand() & 3) + 2; p->color = ramp3[(int)p->ramp]; p->type = pt_fire; - for (j = 0; j < 3; j++) { - p->org[j] = start[j] + ((rand() % 6) - 3); - } + p->org = start + Vector3((rand() % 6) - 3, (rand() % 6) - 3, (rand() % 6) - 3); break; case 2: // blood p->type = pt_grav; p->color = 67 + (rand() & 3); - for (j = 0; j < 3; j++) { - p->org[j] = start[j] + ((rand() % 6) - 3); - } + p->org = start + Vector3((rand() % 6) - 3, (rand() % 6) - 3, (rand() % 6) - 3); break; case 3: @@ -1140,13 +1101,15 @@ void R_RocketTrail(vec3_t start, vec3_t end, int type) tracercount++; - VectorCopy(start, p->org); + p->org = start; if (tracercount & 1) { - p->vel[0] = 30 * vec[1]; - p->vel[1] = 30 * -vec[0]; + p->vel.x = 30 * vec.y; + p->vel.y = 30 * -vec.x; + p->vel.z = 0; } else { - p->vel[0] = 30 * -vec[1]; - p->vel[1] = 30 * vec[0]; + p->vel.x = 30 * -vec.y; + p->vel.y = 30 * vec.x; + p->vel.z = 0; } break; @@ -1154,9 +1117,7 @@ void R_RocketTrail(vec3_t start, vec3_t end, int type) case 4: // slight blood p->type = pt_grav; p->color = 67 + (rand() & 3); - for (j = 0; j < 3; j++) { - p->org[j] = start[j] + ((rand() % 6) - 3); - } + p->org = start + Vector3((rand() % 6) - 3, (rand() % 6) - 3, (rand() % 6) - 3); len -= 3; break; @@ -1164,13 +1125,11 @@ void R_RocketTrail(vec3_t start, vec3_t end, int type) p->color = 9 * 16 + 8 + (rand() & 3); p->type = pt_static; p->die = cl.time + 0.3; - for (j = 0; j < 3; j++) { - p->org[j] = start[j] + ((rand() & 15) - 8); - } + p->org = start + Vector3((rand() & 15) - 8, (rand() & 15) - 8, (rand() & 15) - 8); break; } - VectorAdd(start, vec, start); + start += vec; } } @@ -1483,9 +1442,8 @@ void R_AddDynamicLights(void) int lnum; int sd, td; float dist, rad, minlight; - vec3_t impact, local; + Vector3 impact, local; int s, t; - int i; int smax, tmax; mtexinfo_t* tex; @@ -1500,7 +1458,7 @@ void R_AddDynamicLights(void) } rad = cl_dlights[lnum].radius; - dist = DotProduct(cl_dlights[lnum].origin, surf->plane->normal) - surf->plane->dist; + dist = cl_dlights[lnum].origin.dot(surf->plane->normal) - surf->plane->dist; rad -= fabs(dist); minlight = cl_dlights[lnum].minlight; if (rad < minlight) { @@ -1509,24 +1467,22 @@ void R_AddDynamicLights(void) minlight = rad - minlight; - for (i = 0; i < 3; i++) { - impact[i] = cl_dlights[lnum].origin[i] - surf->plane->normal[i] * dist; - } + impact = cl_dlights[lnum].origin - surf->plane->normal * dist; - local[0] = DotProduct(impact, tex->vecs[0]) + tex->vecs[0][3]; - local[1] = DotProduct(impact, tex->vecs[1]) + tex->vecs[1][3]; + local.x = impact.dot(tex->vecs[0]) + tex->vecs[0][3]; + local.y = impact.dot(tex->vecs[1]) + tex->vecs[1][3]; - local[0] -= surf->texturemins[0]; - local[1] -= surf->texturemins[1]; + local.x -= surf->texturemins[0]; + local.y -= surf->texturemins[1]; for (t = 0; t < tmax; t++) { - td = local[1] - t * 16; + td = local.y - t * 16; if (td < 0) { td = -td; } for (s = 0; s < smax; s++) { - sd = local[0] - s * 16; + sd = local.x - s * 16; if (sd < 0) { sd = -sd; } @@ -2176,20 +2132,16 @@ R_TransformFrustum void R_TransformFrustum(void) { int i; - vec3_t v, v2; + Vector3 v, v2; for (i = 0; i < 4; i++) { - v[0] = screenedge[i].normal[2]; - v[1] = -screenedge[i].normal[0]; - v[2] = screenedge[i].normal[1]; + v = Vector3(screenedge[i].normal.z, -screenedge[i].normal.x, screenedge[i].normal.y); - v2[0] = v[1] * vright[0] + v[2] * vup[0] + v[0] * vpn[0]; - v2[1] = v[1] * vright[1] + v[2] * vup[1] + v[0] * vpn[1]; - v2[2] = v[1] * vright[2] + v[2] * vup[2] + v[0] * vpn[2]; + v2 = vright * v.y + vup * v.z + vpn * v.x; - VectorCopy(v2, view_clipplanes[i].normal); + view_clipplanes[i].normal = v2; - view_clipplanes[i].dist = DotProduct(modelorg, v2); + view_clipplanes[i].dist = modelorg.dot(v2); } } @@ -2198,11 +2150,11 @@ void R_TransformFrustum(void) TransformVector ================ */ -void TransformVector(vec3_t in, vec3_t out) +void TransformVector(const Vector3& in, Vector3& out) { - out[0] = DotProduct(in, vright); - out[1] = DotProduct(in, vup); - out[2] = DotProduct(in, vpn); + out.x = in.dot(vright); + out.y = in.dot(vup); + out.z = in.dot(vpn); } /* @@ -2430,7 +2382,7 @@ void R_EmitEdge(mvertex_t* pv0, mvertex_t* pv1) edge_t *edge, *pcheck; int64_t u_check; // Changed from int to int64_t float u, u_step; - vec3_t local, transformed; + Vector3 local, transformed; float* world; int v, v2, ceilv0; float scale, lzi0, u0, v0; @@ -2445,18 +2397,18 @@ void R_EmitEdge(mvertex_t* pv0, mvertex_t* pv1) world = &pv0->position[0]; // transform and project - VectorSubtract(world, modelorg, local); + local = Vector3(world) - modelorg; TransformVector(local, transformed); - if (transformed[2] < NEAR_CLIP) { - transformed[2] = (vec_t)NEAR_CLIP; + if (transformed.z < NEAR_CLIP) { + transformed.z = (vec_t)NEAR_CLIP; } - lzi0 = 1.0 / transformed[2]; + lzi0 = 1.0 / transformed.z; // FIXME: build x/yscale into transform? scale = xscale * lzi0; - u0 = (xcenter + scale * transformed[0]); + u0 = (xcenter + scale * transformed.x); if (u0 < r_refdef.fvrectx_adj) { u0 = r_refdef.fvrectx_adj; } @@ -2466,7 +2418,7 @@ void R_EmitEdge(mvertex_t* pv0, mvertex_t* pv1) } scale = yscale * lzi0; - v0 = (ycenter - scale * transformed[1]); + v0 = (ycenter - scale * transformed.y); if (v0 < r_refdef.fvrecty_adj) { v0 = r_refdef.fvrecty_adj; } @@ -2481,17 +2433,17 @@ void R_EmitEdge(mvertex_t* pv0, mvertex_t* pv1) world = &pv1->position[0]; // transform and project - VectorSubtract(world, modelorg, local); + local = Vector3(world) - modelorg; TransformVector(local, transformed); - if (transformed[2] < NEAR_CLIP) { - transformed[2] = (vec_t)NEAR_CLIP; + if (transformed.z < NEAR_CLIP) { + transformed.z = (vec_t)NEAR_CLIP; } - r_lzi1 = 1.0 / transformed[2]; + r_lzi1 = 1.0 / transformed.z; scale = xscale * r_lzi1; - r_u1 = (xcenter + scale * transformed[0]); + r_u1 = (xcenter + scale * transformed.x); if (r_u1 < r_refdef.fvrectx_adj) { r_u1 = r_refdef.fvrectx_adj; } @@ -2501,7 +2453,7 @@ void R_EmitEdge(mvertex_t* pv0, mvertex_t* pv1) } scale = yscale * r_lzi1; - r_v1 = (ycenter - scale * transformed[1]); + r_v1 = (ycenter - scale * transformed.y); if (r_v1 < r_refdef.fvrecty_adj) { r_v1 = r_refdef.fvrecty_adj; } @@ -2727,7 +2679,7 @@ void R_RenderFace(msurface_t* fa, int clipflags) unsigned mask; mplane_t* pplane; float distinv; - vec3_t p_normal; + Vector3 p_normal; medge_t *pedges, tedge; clipplane_t* pclip; @@ -2880,11 +2832,11 @@ void R_RenderFace(msurface_t* fa, int clipflags) // FIXME: cache this? TransformVector(pplane->normal, p_normal); // FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct(modelorg, pplane->normal)); + distinv = 1.0 / (pplane->dist - modelorg.dot(pplane->normal)); - surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; - surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; - surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; + surface_p->d_zistepu = p_normal.x * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal.y * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal.z * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; //JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); surface_p++; @@ -2901,7 +2853,7 @@ void R_RenderBmodelFace(bedge_t* pedges, msurface_t* psurf) unsigned mask; mplane_t* pplane; float distinv; - vec3_t p_normal; + Vector3 p_normal; medge_t tedge; clipplane_t* pclip; @@ -2991,11 +2943,11 @@ void R_RenderBmodelFace(bedge_t* pedges, msurface_t* psurf) // FIXME: cache this? TransformVector(pplane->normal, p_normal); // FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct(modelorg, pplane->normal)); + distinv = 1.0 / (pplane->dist - modelorg.dot(pplane->normal)); - surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; - surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; - surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; + surface_p->d_zistepu = p_normal.x * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal.y * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal.z * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; //JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); surface_p++; @@ -3011,7 +2963,7 @@ void R_RenderPoly(msurface_t* fa, int clipflags) int i, lindex, lnumverts, s_axis, t_axis; float dist, lastdist, lzi, scale, u, v, frac; unsigned mask; - vec3_t local, transformed; + Vector3 local, transformed; clipplane_t* pclip; medge_t* pedges; mplane_t* pplane; @@ -3056,20 +3008,21 @@ void R_RenderPoly(msurface_t* fa, int clipflags) // clip the polygon, done if not visible while (pclip) { lastvert = lnumverts - 1; - lastdist = DotProduct(verts[vertpage][lastvert].position, pclip->normal) - pclip->dist; + lastdist = Vector3(verts[vertpage][lastvert].position).dot(pclip->normal) - pclip->dist; visible = false; newverts = 0; newpage = vertpage ^ 1; for (i = 0; i < lnumverts; i++) { - dist = DotProduct(verts[vertpage][i].position, pclip->normal) - pclip->dist; + dist = Vector3(verts[vertpage][i].position).dot(pclip->normal) - pclip->dist; if ((lastdist > 0) != (dist > 0)) { frac = dist / (dist - lastdist); - verts[newpage][newverts].position[0] = verts[vertpage][i].position[0] + ((verts[vertpage][lastvert].position[0] - verts[vertpage][i].position[0]) * frac); - verts[newpage][newverts].position[1] = verts[vertpage][i].position[1] + ((verts[vertpage][lastvert].position[1] - verts[vertpage][i].position[1]) * frac); - verts[newpage][newverts].position[2] = verts[vertpage][i].position[2] + ((verts[vertpage][lastvert].position[2] - verts[vertpage][i].position[2]) * frac); + Vector3 interp = Vector3(verts[vertpage][i].position) + (Vector3(verts[vertpage][lastvert].position) - Vector3(verts[vertpage][i].position)) * frac; + verts[newpage][newverts].position[0] = interp.x; + verts[newpage][newverts].position[1] = interp.y; + verts[newpage][newverts].position[2] = interp.z; newverts++; } @@ -3117,14 +3070,14 @@ void R_RenderPoly(msurface_t* fa, int clipflags) for (i = 0; i < lnumverts; i++) { // transform and project - VectorSubtract(verts[vertpage][i].position, modelorg, local); + local = Vector3(verts[vertpage][i].position) - modelorg; TransformVector(local, transformed); - if (transformed[2] < NEAR_CLIP) { - transformed[2] = (vec_t)NEAR_CLIP; + if (transformed.z < NEAR_CLIP) { + transformed.z = (vec_t)NEAR_CLIP; } - lzi = 1.0 / transformed[2]; + lzi = 1.0 / transformed.z; if (lzi > r_nearzi) { // for mipmap finding r_nearzi = lzi; @@ -3132,7 +3085,7 @@ void R_RenderPoly(msurface_t* fa, int clipflags) // FIXME: build x/yscale into transform? scale = xscale * lzi; - u = (xcenter + scale * transformed[0]); + u = (xcenter + scale * transformed.x); if (u < r_refdef.fvrectx_adj) { u = r_refdef.fvrectx_adj; } @@ -3142,7 +3095,7 @@ void R_RenderPoly(msurface_t* fa, int clipflags) } scale = yscale * lzi; - v = (ycenter - scale * transformed[1]); + v = (ycenter - scale * transformed.y); if (v < r_refdef.fvrecty_adj) { v = r_refdef.fvrecty_adj; } @@ -3896,7 +3849,7 @@ void R_ScanEdges(void) // qboolean insubmodel; entity_t* currententity; -vec3_t modelorg, base_modelorg; +Vector3 modelorg, base_modelorg; typedef enum { touchessolid, drawnode, @@ -3920,14 +3873,14 @@ static qboolean makeclippededge; R_EntityRotate ================ */ -void R_EntityRotate(vec3_t vec) +void R_EntityRotate(Vector3& vec) { - vec3_t tvec; + Vector3 tvec; - VectorCopy(vec, tvec); - vec[0] = DotProduct(entity_rotation[0], tvec); - vec[1] = DotProduct(entity_rotation[1], tvec); - vec[2] = DotProduct(entity_rotation[2], tvec); + tvec = vec; + vec.x = Vector3(entity_rotation[0][0], entity_rotation[0][1], entity_rotation[0][2]).dot(tvec); + vec.y = Vector3(entity_rotation[1][0], entity_rotation[1][1], entity_rotation[1][2]).dot(tvec); + vec.z = Vector3(entity_rotation[2][0], entity_rotation[2][1], entity_rotation[2][2]).dot(tvec); } /* @@ -4268,7 +4221,7 @@ R_RecursiveWorldNode void R_RecursiveWorldNode(mnode_t* node, int clipflags) { int i, c, side, *pindex; - vec3_t acceptpt, rejectpt; + Vector3 acceptpt, rejectpt; mplane_t* plane; msurface_t *surf, **mark; mleaf_t* pleaf; @@ -4297,22 +4250,18 @@ void R_RecursiveWorldNode(mnode_t* node, int clipflags) pindex = pfrustum_indexes[i]; - rejectpt[0] = (float)node->minmaxs[pindex[0]]; - rejectpt[1] = (float)node->minmaxs[pindex[1]]; - rejectpt[2] = (float)node->minmaxs[pindex[2]]; + rejectpt = Vector3((float)node->minmaxs[pindex[0]], (float)node->minmaxs[pindex[1]], (float)node->minmaxs[pindex[2]]); - d = DotProduct(rejectpt, view_clipplanes[i].normal); + d = rejectpt.dot(view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= 0) { return; } - acceptpt[0] = (float)node->minmaxs[pindex[3 + 0]]; - acceptpt[1] = (float)node->minmaxs[pindex[3 + 1]]; - acceptpt[2] = (float)node->minmaxs[pindex[3 + 2]]; + acceptpt = Vector3((float)node->minmaxs[pindex[3 + 0]], (float)node->minmaxs[pindex[3 + 1]], (float)node->minmaxs[pindex[3 + 2]]); - d = DotProduct(acceptpt, view_clipplanes[i].normal); + d = acceptpt.dot(view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d >= 0) { @@ -4475,17 +4424,17 @@ spritedesc_t r_spritedesc; R_RotateSprite ================ */ -void R_RotateSprite(float beamlength) +void R_RotateSprite(float beam_len) { - vec3_t vec; + Vector3 vec; - if (beamlength == 0.0) { + if (beam_len == 0.0) { return; } - VectorScale(r_spritedesc.vpn, -beamlength, vec); - VectorAdd(r_entorigin, vec, r_entorigin); - VectorSubtract(modelorg, vec, modelorg); + vec = r_spritedesc.vpn * -beam_len; + r_entorigin += vec; + modelorg -= vec; } /* @@ -4573,10 +4522,10 @@ void R_SetupAndDrawSprite() int i, nump; float dot, scale, *pv; vec5_t* pverts; - vec3_t left, up, right, down, transformed, local; + Vector3 left, up, right, down, transformed, local; emitpoint_t outverts[MAXWORKINGVERTS + 1], *pout; - dot = DotProduct(r_spritedesc.vpn, modelorg); + dot = r_spritedesc.vpn.dot(modelorg); // backface cull if (dot >= 0) { @@ -4584,34 +4533,34 @@ void R_SetupAndDrawSprite() } // build the sprite poster in worldspace - VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe->right, right); - VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe->up, up); - VectorScale(r_spritedesc.vright, r_spritedesc.pspriteframe->left, left); - VectorScale(r_spritedesc.vup, r_spritedesc.pspriteframe->down, down); + right = r_spritedesc.vright * r_spritedesc.pspriteframe->right; + up = r_spritedesc.vup * r_spritedesc.pspriteframe->up; + left = r_spritedesc.vright * r_spritedesc.pspriteframe->left; + down = r_spritedesc.vup * r_spritedesc.pspriteframe->down; pverts = clip_verts[0]; - pverts[0][0] = r_entorigin[0] + up[0] + left[0]; - pverts[0][1] = r_entorigin[1] + up[1] + left[1]; - pverts[0][2] = r_entorigin[2] + up[2] + left[2]; + pverts[0][0] = r_entorigin.x + up.x + left.x; + pverts[0][1] = r_entorigin.y + up.y + left.y; + pverts[0][2] = r_entorigin.z + up.z + left.z; pverts[0][3] = 0; pverts[0][4] = 0; - pverts[1][0] = r_entorigin[0] + up[0] + right[0]; - pverts[1][1] = r_entorigin[1] + up[1] + right[1]; - pverts[1][2] = r_entorigin[2] + up[2] + right[2]; + pverts[1][0] = r_entorigin.x + up.x + right.x; + pverts[1][1] = r_entorigin.y + up.y + right.y; + pverts[1][2] = r_entorigin.z + up.z + right.z; pverts[1][3] = sprite_width; pverts[1][4] = 0; - pverts[2][0] = r_entorigin[0] + down[0] + right[0]; - pverts[2][1] = r_entorigin[1] + down[1] + right[1]; - pverts[2][2] = r_entorigin[2] + down[2] + right[2]; + pverts[2][0] = r_entorigin.x + down.x + right.x; + pverts[2][1] = r_entorigin.y + down.y + right.y; + pverts[2][2] = r_entorigin.z + down.z + right.z; pverts[2][3] = sprite_width; pverts[2][4] = sprite_height; - pverts[3][0] = r_entorigin[0] + down[0] + left[0]; - pverts[3][1] = r_entorigin[1] + down[1] + left[1]; - pverts[3][2] = r_entorigin[2] + down[2] + left[2]; + pverts[3][0] = r_entorigin.x + down.x + left.x; + pverts[3][1] = r_entorigin.y + down.y + left.y; + pverts[3][2] = r_entorigin.z + down.z + left.z; pverts[3][3] = 0; pverts[3][4] = sprite_height; @@ -4635,15 +4584,15 @@ void R_SetupAndDrawSprite() r_spritedesc.nearzi = -999999; for (i = 0; i < nump; i++) { - VectorSubtract(pv, r_origin, local); + local = Vector3(pv[0], pv[1], pv[2]) - r_origin; TransformVector(local, transformed); - if (transformed[2] < NEAR_CLIP) { - transformed[2] = (vec_t)NEAR_CLIP; + if (transformed.z < NEAR_CLIP) { + transformed.z = (vec_t)NEAR_CLIP; } pout = &outverts[i]; - pout->zi = 1.0 / transformed[2]; + pout->zi = 1.0 / transformed.z; if (pout->zi > r_spritedesc.nearzi) { r_spritedesc.nearzi = pout->zi; } @@ -4652,10 +4601,10 @@ void R_SetupAndDrawSprite() pout->t = pv[4]; scale = xscale * pout->zi; - pout->u = (xcenter + scale * transformed[0]); + pout->u = (xcenter + scale * transformed.x); scale = yscale * pout->zi; - pout->v = (ycenter - scale * transformed[1]); + pout->v = (ycenter - scale * transformed.y); pv += sizeof(vec5_t) / sizeof(*pv); } @@ -4718,9 +4667,8 @@ R_DrawSprite */ void R_DrawSprite(void) { - int i; msprite_t* psprite; - vec3_t tvec; + Vector3 tvec; float dot, angle, sr, cr; psprite = (msprite_t*)currententity->model->cache.data; @@ -4738,39 +4686,27 @@ void R_DrawSprite(void) // down, because the cross product will be between two nearly parallel // vectors and starts to approach an undefined state, so we don't draw if // the two vectors are less than 1 degree apart - tvec[0] = -modelorg[0]; - tvec[1] = -modelorg[1]; - tvec[2] = -modelorg[2]; - VectorNormalize(tvec); - dot = tvec[2]; // same as DotProduct (tvec, r_spritedesc.vup) because + tvec = -modelorg; + tvec.normalize(); + dot = tvec.z; // same as DotProduct (tvec, r_spritedesc.vup) because // r_spritedesc.vup is 0, 0, 1 if ((dot > 0.999848) || (dot < -0.999848)) { // cos(1 degree) = 0.999848 return; } - r_spritedesc.vup[0] = 0; - r_spritedesc.vup[1] = 0; - r_spritedesc.vup[2] = 1; - r_spritedesc.vright[0] = tvec[1]; - // CrossProduct(r_spritedesc.vup, -modelorg, - r_spritedesc.vright[1] = -tvec[0]; - // r_spritedesc.vright) - r_spritedesc.vright[2] = 0; - VectorNormalize(r_spritedesc.vright); - r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; - r_spritedesc.vpn[1] = r_spritedesc.vright[0]; - r_spritedesc.vpn[2] = 0; + r_spritedesc.vup = Vector3(0, 0, 1); + r_spritedesc.vright = Vector3(tvec.y, -tvec.x, 0); + r_spritedesc.vright.normalize(); + r_spritedesc.vpn = Vector3(-r_spritedesc.vright.y, r_spritedesc.vright.x, 0); // CrossProduct (r_spritedesc.vright, r_spritedesc.vup, // r_spritedesc.vpn) } else if (psprite->type == SPR_VP_PARALLEL) { // generate the sprite's axes, completely parallel to the viewplane. There // are no problem situations, because the sprite is always in the same // position relative to the viewer - for (i = 0; i < 3; i++) { - r_spritedesc.vup[i] = vup[i]; - r_spritedesc.vright[i] = vright[i]; - r_spritedesc.vpn[i] = vpn[i]; - } + r_spritedesc.vup = vup; + r_spritedesc.vright = vright; + r_spritedesc.vpn = vpn; } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { // generate the sprite's axes, with vup straight up in worldspace, and // r_spritedesc.vright parallel to the viewplane. @@ -4778,23 +4714,16 @@ void R_DrawSprite(void) // down, because the cross product will be between two nearly parallel // vectors and starts to approach an undefined state, so we don't draw if // the two vectors are less than 1 degree apart - dot = vpn[2]; // same as DotProduct (vpn, r_spritedesc.vup) because + dot = vpn.z; // same as DotProduct (vpn, r_spritedesc.vup) because // r_spritedesc.vup is 0, 0, 1 if ((dot > 0.999848) || (dot < -0.999848)) { // cos(1 degree) = 0.999848 return; } - r_spritedesc.vup[0] = 0; - r_spritedesc.vup[1] = 0; - r_spritedesc.vup[2] = 1; - r_spritedesc.vright[0] = vpn[1]; - // CrossProduct (r_spritedesc.vup, vpn, - r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright) - r_spritedesc.vright[2] = 0; - VectorNormalize(r_spritedesc.vright); - r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; - r_spritedesc.vpn[1] = r_spritedesc.vright[0]; - r_spritedesc.vpn[2] = 0; + r_spritedesc.vup = Vector3(0, 0, 1); + r_spritedesc.vright = Vector3(vpn.y, -vpn.x, 0); + r_spritedesc.vright.normalize(); + r_spritedesc.vpn = Vector3(-r_spritedesc.vright.y, r_spritedesc.vright.x, 0); // CrossProduct (r_spritedesc.vright, r_spritedesc.vup, // r_spritedesc.vpn) } else if (psprite->type == SPR_ORIENTED) { @@ -4809,11 +4738,9 @@ void R_DrawSprite(void) sr = sin(angle); cr = cos(angle); - for (i = 0; i < 3; i++) { - r_spritedesc.vpn[i] = vpn[i]; - r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr; - r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr; - } + r_spritedesc.vpn = vpn; + r_spritedesc.vright = vright * cr + vup * sr; + r_spritedesc.vup = vright * -sr + vup * cr; } else { Sys_Error("R_DrawSprite: Bad sprite type %d", psprite->type); } @@ -4840,13 +4767,13 @@ void* acolormap; // FIXME: should go away trivertx_t* r_apverts; -vec3_t r_plightvec; +Vector3 r_plightvec; int r_ambientlight; float r_shadelight; static float ziscale; static model_t* pmodel; -static vec3_t alias_forward, alias_right, alias_up; +static Vector3 alias_forward, alias_right, alias_up; static maliasskindesc_t* pskindesc; int r_anumverts; @@ -4861,18 +4788,131 @@ typedef struct { static aedge_t aedges[12] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 }, { 0, 5 }, { 1, 4 }, { 2, 7 }, { 3, 6 } }; -#define NUMVERTEXNORMALS 162 +/* +================ +R_InitVertexNormals -float r_avertexnormals[NUMVERTEXNORMALS][3] = { -#pragma warning(push) -#pragma warning(disable : 4305) -#include "anorms.hpp" -#pragma warning(pop) -}; +Generate the 162 vertex normals by subdividing an icosahedron. +This reproduces the exact set and ordering from the original +Quake Pascal tool used to create anorms.h. +================ +*/ +void R_InitVertexNormals(void) +{ + static bool initialized = false; + if (initialized) return; + initialized = true; + + const float X = 0.525731112119133606f; + const float Z = 0.850650808352039932f; + + const float verts[12][3] = { + {-X, 0.0f, Z}, {X, 0.0f, Z}, {-X, 0.0f, -Z}, {X, 0.0f, -Z}, + {0.0f, Z, X}, {0.0f, Z, -X}, {0.0f, -Z, X}, {0.0f, -Z, -X}, + {Z, X, 0.0f}, {-Z, X, 0.0f}, {Z, -X, 0.0f}, {-Z, -X, 0.0f}, + }; + + const int faces[20][3] = { + {0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1}, + {8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3}, + {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6}, + {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11} + }; + + const int subdiv = 4; + const int max_low_i = subdiv / 2 - 1; + + float temp[400][3]; + int num_temp = 0; + + for (int f = 0; f < 20; f++) { + const float* a = verts[faces[f][0]]; + const float* b = verts[faces[f][1]]; + const float* c = verts[faces[f][2]]; + + // High i part (i >= n/2) + for (int i = subdiv; i >= subdiv / 2; i--) { + for (int j = subdiv - i; j >= 0; j--) { + int k = subdiv - i - j; + float px = (i * a[0] + j * b[0] + k * c[0]) / subdiv; + float py = (i * a[1] + j * b[1] + k * c[1]) / subdiv; + float pz = (i * a[2] + j * b[2] + k * c[2]) / subdiv; + float len = std::sqrt(px * px + py * py + pz * pz); + if (len > 0) { + temp[num_temp][0] = px / len; + temp[num_temp][1] = py / len; + temp[num_temp][2] = pz / len; + num_temp++; + } + } + } + + // Low i part, high j (j >= n/2) + for (int j = subdiv; j >= subdiv / 2; j--) { + int max_i = (max_low_i < subdiv - j) ? max_low_i : (subdiv - j); + for (int i = max_i; i >= 0; i--) { + int k = subdiv - i - j; + float px = (i * a[0] + j * b[0] + k * c[0]) / subdiv; + float py = (i * a[1] + j * b[1] + k * c[1]) / subdiv; + float pz = (i * a[2] + j * b[2] + k * c[2]) / subdiv; + float len = std::sqrt(px * px + py * py + pz * pz); + if (len > 0) { + temp[num_temp][0] = px / len; + temp[num_temp][1] = py / len; + temp[num_temp][2] = pz / len; + num_temp++; + } + } + } + + // Low i part, low j (j < n/2) + for (int j = 0; j < subdiv / 2; j++) { + int max_i = (max_low_i < subdiv - j) ? max_low_i : (subdiv - j); + for (int i = 0; i <= max_i; i++) { + int k = subdiv - i - j; + float px = (i * a[0] + j * b[0] + k * c[0]) / subdiv; + float py = (i * a[1] + j * b[1] + k * c[1]) / subdiv; + float pz = (i * a[2] + j * b[2] + k * c[2]) / subdiv; + float len = std::sqrt(px * px + py * py + pz * pz); + if (len > 0) { + temp[num_temp][0] = px / len; + temp[num_temp][1] = py / len; + temp[num_temp][2] = pz / len; + num_temp++; + } + } + } + } + + // Dedup preserving first occurrence (order matches original) + int out_idx = 0; + for (int i = 0; i < num_temp && out_idx < NUMVERTEXNORMALS; i++) { + int key_x = (int)std::round(temp[i][0] * 10000.0f); + int key_y = (int)std::round(temp[i][1] * 10000.0f); + int key_z = (int)std::round(temp[i][2] * 10000.0f); + + bool dup = false; + for (int j = 0; j < out_idx; j++) { + int jx = (int)std::round(r_avertexnormals[j][0] * 10000.0f); + int jy = (int)std::round(r_avertexnormals[j][1] * 10000.0f); + int jz = (int)std::round(r_avertexnormals[j][2] * 10000.0f); + if (jx == key_x && jy == key_y && jz == key_z) { + dup = true; + break; + } + } + if (!dup) { + r_avertexnormals[out_idx][0] = temp[i][0]; + r_avertexnormals[out_idx][1] = temp[i][1]; + r_avertexnormals[out_idx][2] = temp[i][2]; + out_idx++; + } + } +} void R_AliasTransformAndProjectFinalVerts(finalvert_t* fv, stvert_t* pstverts); void R_AliasSetUpTransform(int trivial_accept); -void R_AliasTransformVector(vec3_t in, vec3_t out); +void R_AliasTransformVector(const float* in, float* out); void R_AliasTransformFinalVert(finalvert_t* fv, auxvert_t* av, trivertx_t* pverts, @@ -5035,7 +5075,7 @@ qboolean R_AliasCheckBBox(void) R_AliasTransformVector ================ */ -void R_AliasTransformVector(vec3_t in, vec3_t out) +void R_AliasTransformVector(const float* in, float* out) { out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3]; out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3]; @@ -5124,7 +5164,7 @@ void R_AliasSetUpTransform(int trivial_accept) float rotationmatrix[3][4], t2matrix[3][4]; static float tmatrix[3][4]; static float viewmatrix[3][4]; - vec3_t angles; + Vector3 angles; // TODO: should really be stored with the entity instead of being reconstructed // TODO: should use a look-up table @@ -5830,7 +5870,7 @@ void R_AliasClipTriangle(mtriangle_t* ptri) //define PASSAGES void* colormap; -vec3_t viewlightvec; +Vector3 viewlightvec; alight_t r_viewlighting = { 128, 192, viewlightvec }; qboolean r_drawpolys; qboolean r_drawculledpolys; @@ -5850,10 +5890,10 @@ byte* r_stack_start; // // view origin // -vec3_t vup, base_vup; -vec3_t vpn, base_vpn; -vec3_t vright, base_vright; -vec3_t r_origin; +Vector3 vup, base_vup; +Vector3 vpn, base_vpn; +Vector3 vright, base_vright; +Vector3 r_origin; // // screen size info @@ -5943,6 +5983,7 @@ void R_Init(void) r_stack_start = (byte*)&dummy; R_InitTurb(); + R_InitVertexNormals(); Cmd::AddCommand("timerefresh", R_TimeRefresh_f); Cmd::AddCommand("pointfile", R_ReadPointFile_f); @@ -6241,7 +6282,7 @@ void R_DrawEntitiesOnList(void) alight_t lighting; // FIXME: remove and do real lighting float lightvec[3] = { -1, 0, 0 }; - vec3_t dist; + Vector3 dist; float add; if (!r_drawentities.value) { @@ -6257,14 +6298,14 @@ void R_DrawEntitiesOnList(void) switch (currententity->model->type) { case mod_sprite: - VectorCopy(currententity->origin, r_entorigin); - VectorSubtract(r_origin, r_entorigin, modelorg); + r_entorigin = currententity->origin; + modelorg = r_origin - r_entorigin; R_DrawSprite(); break; case mod_alias: - VectorCopy(currententity->origin, r_entorigin); - VectorSubtract(r_origin, r_entorigin, modelorg); + r_entorigin = currententity->origin; + modelorg = r_origin - r_entorigin; // see if the bounding box lets us trivially reject, also sets // trivial accept status @@ -6278,9 +6319,8 @@ void R_DrawEntitiesOnList(void) for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { if (cl_dlights[lnum].die >= cl.time) { - VectorSubtract(currententity->origin, cl_dlights[lnum].origin, - dist); - add = cl_dlights[lnum].radius - Length(dist); + dist = currententity->origin - cl_dlights[lnum].origin; + add = cl_dlights[lnum].radius - dist.length(); if (add > 0) { lighting.ambientlight += add; @@ -6319,7 +6359,7 @@ void R_DrawViewModel(void) float lightvec[3] = { -1, 0, 0 }; int j; int lnum; - vec3_t dist; + Vector3 dist; float add; dlight_t* dl; @@ -6340,11 +6380,10 @@ void R_DrawViewModel(void) return; } - VectorCopy(currententity->origin, r_entorigin); - VectorSubtract(r_origin, r_entorigin, modelorg); + r_entorigin = currententity->origin; + modelorg = r_origin - r_entorigin; - VectorCopy(vup, viewlightvec); - VectorInverse(viewlightvec); + viewlightvec = -vup; j = R_LightPoint(currententity->origin); @@ -6370,8 +6409,8 @@ void R_DrawViewModel(void) continue; } - VectorSubtract(currententity->origin, dl->origin, dist); - add = dl->radius - Length(dist); + dist = currententity->origin - dl->origin; + add = dl->radius - dist.length(); if (add > 0) { r_viewlighting.ambientlight += add; } @@ -6400,14 +6439,14 @@ R_BmodelCheckBBox int R_BmodelCheckBBox(model_t* clmodel, float* minmaxs) { int i, *pindex, clipflags; - vec3_t acceptpt, rejectpt; + Vector3 acceptpt, rejectpt; double d; clipflags = 0; if (currententity->angles[0] || currententity->angles[1] || currententity->angles[2]) { for (i = 0; i < 4; i++) { - d = DotProduct(currententity->origin, view_clipplanes[i].normal); + d = currententity->origin.dot(view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= -clmodel->radius) { @@ -6426,22 +6465,18 @@ int R_BmodelCheckBBox(model_t* clmodel, float* minmaxs) pindex = pfrustum_indexes[i]; - rejectpt[0] = minmaxs[pindex[0]]; - rejectpt[1] = minmaxs[pindex[1]]; - rejectpt[2] = minmaxs[pindex[2]]; + rejectpt = Vector3(minmaxs[pindex[0]], minmaxs[pindex[1]], minmaxs[pindex[2]]); - d = DotProduct(rejectpt, view_clipplanes[i].normal); + d = rejectpt.dot(view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= 0) { return BMODEL_FULLY_CLIPPED; } - acceptpt[0] = minmaxs[pindex[3 + 0]]; - acceptpt[1] = minmaxs[pindex[3 + 1]]; - acceptpt[2] = minmaxs[pindex[3 + 2]]; + acceptpt = Vector3(minmaxs[pindex[3 + 0]], minmaxs[pindex[3 + 1]], minmaxs[pindex[3 + 2]]); - d = DotProduct(acceptpt, view_clipplanes[i].normal); + d = acceptpt.dot(view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= 0) { @@ -6460,8 +6495,8 @@ R_DrawBEntitiesOnList */ void R_DrawBEntitiesOnList(void) { - int i, j, k, clipflags; - vec3_t oldorigin; + int i, k, clipflags; + Vector3 oldorigin; model_t* clmodel; float minmaxs[6]; @@ -6469,7 +6504,7 @@ void R_DrawBEntitiesOnList(void) return; } - VectorCopy(modelorg, oldorigin); + oldorigin = modelorg; insubmodel = true; r_dlightframecount = r_framecount; @@ -6483,18 +6518,20 @@ void R_DrawBEntitiesOnList(void) // see if the bounding box lets us trivially reject, also sets // trivial accept status - for (j = 0; j < 3; j++) { - minmaxs[j] = currententity->origin[j] + clmodel->mins[j]; - minmaxs[3 + j] = currententity->origin[j] + clmodel->maxs[j]; - } + minmaxs[0] = currententity->origin.x + clmodel->mins[0]; + minmaxs[1] = currententity->origin.y + clmodel->mins[1]; + minmaxs[2] = currententity->origin.z + clmodel->mins[2]; + minmaxs[3] = currententity->origin.x + clmodel->maxs[0]; + minmaxs[4] = currententity->origin.y + clmodel->maxs[1]; + minmaxs[5] = currententity->origin.z + clmodel->maxs[2]; clipflags = R_BmodelCheckBBox(clmodel, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { - VectorCopy(currententity->origin, r_entorigin); - VectorSubtract(r_origin, r_entorigin, modelorg); + r_entorigin = currententity->origin; + modelorg = r_origin - r_entorigin; // FIXME: is this needed? - VectorCopy(modelorg, r_worldmodelorg); + r_worldmodelorg = modelorg; r_pcurrentvertbase = clmodel->vertexes; @@ -6522,10 +6559,8 @@ void R_DrawBEntitiesOnList(void) } else { r_pefragtopnode = NULL; - for (j = 0; j < 3; j++) { - r_emins[j] = minmaxs[j]; - r_emaxs[j] = minmaxs[3 + j]; - } + r_emins = Vector3(minmaxs[0], minmaxs[1], minmaxs[2]); + r_emaxs = Vector3(minmaxs[3], minmaxs[4], minmaxs[5]); R_SplitEntityOnNode2(cl.worldmodel->nodes); @@ -6549,11 +6584,11 @@ void R_DrawBEntitiesOnList(void) // put back world rotation and frustum clipping // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy(base_vpn, vpn); - VectorCopy(base_vup, vup); - VectorCopy(base_vright, vright); - VectorCopy(base_modelorg, modelorg); - VectorCopy(oldorigin, modelorg); + vpn = base_vpn; + vup = base_vup; + vright = base_vright; + modelorg = base_modelorg; + modelorg = oldorigin; R_TransformFrustum(); } diff --git a/src/render.hpp b/src/renderer.hpp similarity index 82% rename from src/render.hpp rename to src/renderer.hpp index 3df77d4..ee46b55 100644 --- a/src/render.hpp +++ b/src/renderer.hpp @@ -1,4 +1,4 @@ -// render.h -- public interface to refresh functions +// renderer.hpp -- public interface to refresh functions #pragma once #define MAXCLIPPLANES 11 @@ -23,10 +23,10 @@ typedef struct entity_s { entity_state_t baseline; // to fill in defaults in updates double msgtime; // time of last update - vec3_t msg_origins[2]; // last two updates (0 is newest) - vec3_t origin; - vec3_t msg_angles[2]; // last two updates (0 is newest) - vec3_t angles; + Vector3 msg_origins[2]; // last two updates (0 is newest) + Vector3 origin; + Vector3 msg_angles[2]; // last two updates (0 is newest) + Vector3 angles; struct model_s* model; // NULL = no model struct efrag_s* efrag; // linked list of efrags int frame; @@ -69,8 +69,8 @@ typedef struct { float xOrigin; // should probably allways be 0.5 float yOrigin; // between be around 0.3 to 0.5 - vec3_t vieworg; - vec3_t viewangles; + Vector3 vieworg; + Vector3 viewangles; float fov_x, fov_y; @@ -86,7 +86,7 @@ namespace Render { // extern refdef_t r_refdef; -extern vec3_t r_origin, vpn, vright, vup; +extern Vector3 r_origin, vpn, vright, vup; extern struct texture_s* r_notexture_mip; @@ -103,15 +103,15 @@ void R_RemoveEfrags(entity_t* ent); void R_NewMap(void); void R_ParseParticleEffect(void); -void R_RunParticleEffect(vec3_t org, vec3_t dir, int color, int count); -void R_RocketTrail(vec3_t start, vec3_t end, int type); +void R_RunParticleEffect(const Vector3& org, const Vector3& dir, int color, int count); +void R_RocketTrail(Vector3 start, const Vector3& end, int type); void R_EntityParticles(entity_t* ent); -void R_BlobExplosion(vec3_t org); -void R_ParticleExplosion(vec3_t org); -void R_ParticleExplosion2(vec3_t org, int colorStart, int colorLength); -void R_LavaSplash(vec3_t org); -void R_TeleportSplash(vec3_t org); +void R_BlobExplosion(const Vector3& org); +void R_ParticleExplosion(const Vector3& org); +void R_ParticleExplosion2(const Vector3& org, int colorStart, int colorLength); +void R_LavaSplash(const Vector3& org); +void R_TeleportSplash(const Vector3& org); void R_PushDlights(void); diff --git a/src/server.cpp b/src/server.cpp index 044c5cd..9ce74c8 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -46,8 +46,11 @@ cvar_t fraglimit = { "fraglimit", "0", false, true }; cvar_t timelimit = { "timelimit", "0", false, true }; // from sv_main.cpp -server_t sv; -server_static_t svs; +ServerSubsystem& GetServerSubsystem() +{ + static ServerSubsystem subsystem; + return subsystem; +} char localmodels[MAX_MODELS][5]; int fatbytes; byte fatpvs[MAX_MAP_LEAFS / 8]; @@ -65,7 +68,7 @@ int c_yes, c_no; // from sv_user.cpp edict_t* sv_player; cvar_t sv_edgefriction = { "edgefriction", "2" }; -vec3_t wishdir; +Vector3 wishdir; float wishspeed; float* angles; float* origin; @@ -112,7 +115,7 @@ SV_StartParticle Make sure the event gets sent to all clients ================== */ -void SV_StartParticle(vec3_t org, vec3_t dir, int color, int count) +void SV_StartParticle(const Vector3& org, const Vector3& dir, int color, int count) { int i, v; @@ -385,7 +388,7 @@ void SV_CheckForNewClients(void) // PVS //============================================================================= -void SV_AddToFatPVS(vec3_t org, mnode_t* node) +void SV_AddToFatPVS(const Vector3& org, mnode_t* node) { int i; byte* pvs; @@ -406,7 +409,7 @@ void SV_AddToFatPVS(vec3_t org, mnode_t* node) } plane = node->plane; - d = DotProduct(org, plane->normal) - plane->dist; + d = org.dot(plane->normal) - plane->dist; if (d > 8) { node = node->children[0]; } else if (d < -8) { @@ -426,7 +429,7 @@ Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the given point. ============= */ -byte* SV_FatPVS(vec3_t org) +byte* SV_FatPVS(const Vector3& org) { fatbytes = (sv.worldmodel->numleafs + 31) >> 3; Q_memset(fatpvs, 0, fatbytes); @@ -448,12 +451,12 @@ void SV_WriteEntitiesToClient(edict_t* clent, sizebuf_t* msg) int e, i; int bits; byte* pvs; - vec3_t org; + Vector3 org; float miss; edict_t* ent; // find the client's PVS - VectorAdd(clent->v.origin, clent->v.view_ofs, org); + org = clent->v.origin + clent->v.view_ofs; pvs = SV_FatPVS(org); // send over all entities (excpet the client) that touch the pvs @@ -1378,26 +1381,24 @@ returns the blocked flags (1 = floor, 2 = step / wall) */ #define STOP_EPSILON 0.1 -int ClipVelocity(vec3_t in, vec3_t normal, vec3_t out, float overbounce) +int ClipVelocity(const Vector3& in, const Vector3& normal, Vector3& out, float overbounce) { float backoff; - float change; int i, blocked; blocked = 0; - if (normal[2] > 0) { + if (normal.z > 0) { blocked |= 1; // floor } - if (!normal[2]) { + if (!normal.z) { blocked |= 2; // step } - backoff = DotProduct(in, normal) * overbounce; + backoff = in.dot(normal) * overbounce; + out = in - normal * backoff; for (i = 0; i < 3; i++) { - change = normal[i] * backoff; - out[i] = in[i] - change; if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) { out[i] = 0; } @@ -1423,46 +1424,44 @@ If steptrace is not NULL, the trace of any vertical wall hit will be stored int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) { int bumpcount, numbumps; - vec3_t dir; + Vector3 dir; float d; int numplanes; - vec3_t planes[MAX_CLIP_PLANES]; - vec3_t primal_velocity, original_velocity, new_velocity; + Vector3 planes[MAX_CLIP_PLANES]; + Vector3 primal_velocity, original_velocity, new_velocity; int i, j; trace_t trace; - vec3_t end; + Vector3 end; float time_left; int blocked; numbumps = 4; blocked = 0; - VectorCopy(ent->v.velocity, original_velocity); - VectorCopy(ent->v.velocity, primal_velocity); + original_velocity = ent->v.velocity; + primal_velocity = ent->v.velocity; numplanes = 0; time_left = time; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { - if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2]) { + if (ent->v.velocity == vec3_origin) { break; } - for (i = 0; i < 3; i++) { - end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i]; - } + end = ent->v.origin + ent->v.velocity * time_left; trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); if (trace.allsolid) { // entity is trapped in another solid - VectorCopy(vec3_origin, ent->v.velocity); + ent->v.velocity = vec3_origin; return 3; } if (trace.fraction > 0) { // actually covered some distance - VectorCopy(trace.endpos, ent->v.origin); - VectorCopy(ent->v.velocity, original_velocity); + ent->v.origin = trace.endpos; + original_velocity = ent->v.velocity; numplanes = 0; } @@ -1474,7 +1473,7 @@ int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) Sys_Error("SV_FlyMove: !trace.ent"); } - if (trace.plane.normal[2] > 0.7) { + if (trace.plane.normal.z > 0.7) { blocked |= 1; // floor if (trace.ent->v.solid == SOLID_BSP) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; @@ -1482,7 +1481,7 @@ int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) } } - if (!trace.plane.normal[2]) { + if (!trace.plane.normal.z) { blocked |= 2; // step if (steptrace) { *steptrace = trace; // save for player extrafriction @@ -1501,12 +1500,12 @@ int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen - VectorCopy(vec3_origin, ent->v.velocity); + ent->v.velocity = vec3_origin; return 3; } - VectorCopy(trace.plane.normal, planes[numplanes]); + planes[numplanes] = trace.plane.normal; numplanes++; // @@ -1516,7 +1515,7 @@ int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) ClipVelocity(original_velocity, planes[i], new_velocity, 1); for (j = 0; j < numplanes; j++) { if (j != i) { - if (DotProduct(new_velocity, planes[j]) < 0) { + if (new_velocity.dot(planes[j]) < 0) { break; // not ok } } @@ -1527,26 +1526,26 @@ int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) } if (i != numplanes) { // go along this plane - VectorCopy(new_velocity, ent->v.velocity); + ent->v.velocity = new_velocity; } else { // go along the crease if (numplanes != 2) { // Con_Printf ("clip velocity, numplanes == %i\n",numplanes); - VectorCopy(vec3_origin, ent->v.velocity); + ent->v.velocity = vec3_origin; return 7; } - CrossProduct(planes[0], planes[1], dir); - d = DotProduct(dir, ent->v.velocity); - VectorScale(dir, d, ent->v.velocity); + dir = planes[0].cross(planes[1]); + d = dir.dot(ent->v.velocity); + ent->v.velocity = dir * d; } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // - if (DotProduct(ent->v.velocity, primal_velocity) <= 0) { - VectorCopy(vec3_origin, ent->v.velocity); + if (ent->v.velocity.dot(primal_velocity) <= 0) { + ent->v.velocity = vec3_origin; return blocked; } @@ -1588,12 +1587,12 @@ SV_PushEntity Does not change the entities velocity at all ============ */ -trace_t SV_PushEntity(edict_t* ent, vec3_t push) +trace_t SV_PushEntity(edict_t* ent, const Vector3& push) { trace_t trace; - vec3_t end; + Vector3 end; - VectorAdd(ent->v.origin, push, end); + end = ent->v.origin + push; if (ent->v.movetype == MOVETYPE_FLYMISSILE) { trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, @@ -1606,7 +1605,7 @@ trace_t SV_PushEntity(edict_t* ent, vec3_t push) trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); } - VectorCopy(trace.endpos, ent->v.origin); + ent->v.origin = trace.endpos; SV_LinkEdict(ent, true); if (trace.ent) { @@ -1626,29 +1625,27 @@ void SV_PushMove(edict_t* pusher, float movetime) { int i, e; edict_t *check, *block; - vec3_t mins, maxs, move; - vec3_t entorig, pushorig; + Vector3 mins, maxs, move; + Vector3 entorig, pushorig; int num_moved; edict_t* moved_edict[MAX_EDICTS]; - vec3_t moved_from[MAX_EDICTS]; + Vector3 moved_from[MAX_EDICTS]; - if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2]) { + if (pusher->v.velocity == vec3_origin) { pusher->v.ltime += movetime; return; } - for (i = 0; i < 3; i++) { - move[i] = pusher->v.velocity[i] * movetime; - mins[i] = pusher->v.absmin[i] + move[i]; - maxs[i] = pusher->v.absmax[i] + move[i]; - } + move = pusher->v.velocity * movetime; + mins = pusher->v.absmin + move; + maxs = pusher->v.absmax + move; - VectorCopy(pusher->v.origin, pushorig); + pushorig = pusher->v.origin; // move the pusher to it's final position - VectorAdd(pusher->v.origin, move, pusher->v.origin); + pusher->v.origin += move; pusher->v.ltime += movetime; SV_LinkEdict(pusher, false); @@ -1667,7 +1664,7 @@ void SV_PushMove(edict_t* pusher, float movetime) // if the entity is standing on the pusher, it will definately be moved if (!(((int)check->v.flags & FL_ONGROUND) && PROG_TO_EDICT(check->v.groundentity) == pusher)) { - if (check->v.absmin[0] >= maxs[0] || check->v.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2]) { + if (check->v.absmin.x >= maxs.x || check->v.absmin.y >= maxs.y || check->v.absmin.z >= maxs.z || check->v.absmax.x <= mins.x || check->v.absmax.y <= mins.y || check->v.absmax.z <= mins.z) { continue; } @@ -1682,8 +1679,8 @@ void SV_PushMove(edict_t* pusher, float movetime) check->v.flags = (int)check->v.flags & ~FL_ONGROUND; } - VectorCopy(check->v.origin, entorig); - VectorCopy(check->v.origin, moved_from[num_moved]); + entorig = check->v.origin; + moved_from[num_moved] = check->v.origin; moved_edict[num_moved] = check; num_moved++; @@ -1695,20 +1692,20 @@ void SV_PushMove(edict_t* pusher, float movetime) // if it is still inside the pusher, block block = SV_TestEntityPosition(check); if (block) { // fail the move - if (check->v.mins[0] == check->v.maxs[0]) { + if (check->v.mins.x == check->v.maxs.x) { continue; } if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse - check->v.mins[0] = check->v.mins[1] = 0; - VectorCopy(check->v.mins, check->v.maxs); + check->v.mins.x = check->v.mins.y = 0; + check->v.maxs = check->v.mins; continue; } - VectorCopy(entorig, check->v.origin); + check->v.origin = entorig; SV_LinkEdict(check, true); - VectorCopy(pushorig, pusher->v.origin); + pusher->v.origin = pushorig; SV_LinkEdict(pusher, false); pusher->v.ltime -= movetime; @@ -1722,7 +1719,7 @@ void SV_PushMove(edict_t* pusher, float movetime) // move back any entities we already moved for (i = 0; i < num_moved; i++) { - VectorCopy(moved_from[i], moved_edict[i]->v.origin); + moved_edict[i]->v.origin = moved_from[i]; SV_LinkEdict(moved_edict[i], false); } @@ -1788,16 +1785,16 @@ void SV_CheckStuck(edict_t* ent) { int i, j; int z; - vec3_t org; + Vector3 org; if (!SV_TestEntityPosition(ent)) { - VectorCopy(ent->v.origin, ent->v.oldorigin); + ent->v.oldorigin = ent->v.origin; return; } - VectorCopy(ent->v.origin, org); - VectorCopy(ent->v.oldorigin, ent->v.origin); + org = ent->v.origin; + ent->v.origin = ent->v.oldorigin; if (!SV_TestEntityPosition(ent)) { Con_DPrintf("Unstuck.\n"); SV_LinkEdict(ent, true); @@ -1808,9 +1805,9 @@ void SV_CheckStuck(edict_t* ent) for (z = 0; z < 18; z++) { for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { - ent->v.origin[0] = org[0] + i; - ent->v.origin[1] = org[1] + j; - ent->v.origin[2] = org[2] + z; + ent->v.origin.x = org.x + i; + ent->v.origin.y = org.y + j; + ent->v.origin.z = org.z + z; if (!SV_TestEntityPosition(ent)) { Con_DPrintf("Unstuck.\n"); SV_LinkEdict(ent, true); @@ -1821,7 +1818,7 @@ void SV_CheckStuck(edict_t* ent) } } - VectorCopy(org, ent->v.origin); + ent->v.origin = org; Con_DPrintf("player is stuck.\n"); } @@ -1832,12 +1829,10 @@ SV_CheckWater */ qboolean SV_CheckWater(edict_t* ent) { - vec3_t point; + Vector3 point; int cont; - point[0] = ent->v.origin[0]; - point[1] = ent->v.origin[1]; - point[2] = ent->v.origin[2] + ent->v.mins[2] + 1; + point = Vector3(ent->v.origin.x, ent->v.origin.y, ent->v.origin.z + ent->v.mins.z + 1); ent->v.waterlevel = 0; ent->v.watertype = CONTENTS_EMPTY; @@ -1845,11 +1840,11 @@ qboolean SV_CheckWater(edict_t* ent) if (cont <= CONTENTS_WATER) { ent->v.watertype = cont; ent->v.waterlevel = 1; - point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2]) * 0.5; + point.z = ent->v.origin.z + (ent->v.mins.z + ent->v.maxs.z) * 0.5f; cont = SV_PointContents(point); if (cont <= CONTENTS_WATER) { ent->v.waterlevel = 2; - point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; + point.z = ent->v.origin.z + ent->v.view_ofs.z; cont = SV_PointContents(point); if (cont <= CONTENTS_WATER) { ent->v.waterlevel = 3; @@ -1869,12 +1864,12 @@ SV_WallFriction */ void SV_WallFriction(edict_t* ent, trace_t* trace) { - vec3_t forward, right, up; + Vector3 forward, right, up; float d, i; - vec3_t into, side; + Vector3 into, side; AngleVectors(ent->v.v_angle, forward, right, up); - d = DotProduct(trace->plane.normal, forward); + d = trace->plane.normal.dot(forward); d += 0.5; if (d >= 0) { @@ -1882,12 +1877,12 @@ void SV_WallFriction(edict_t* ent, trace_t* trace) } // cut the tangential velocity - i = DotProduct(trace->plane.normal, ent->v.velocity); - VectorScale(trace->plane.normal, i, into); - VectorSubtract(ent->v.velocity, into, side); + i = trace->plane.normal.dot(ent->v.velocity); + into = trace->plane.normal * i; + side = ent->v.velocity - into; - ent->v.velocity[0] = side[0] * (1 + d); - ent->v.velocity[1] = side[1] * (1 + d); + ent->v.velocity.x = side.x * (1 + d); + ent->v.velocity.y = side.y * (1 + d); } /* @@ -1902,72 +1897,70 @@ Try fixing by pushing one pixel in each direction. This is a hack, but in the interest of good gameplay... ====================== */ -int SV_TryUnstick(edict_t* ent, vec3_t oldvel) +int SV_TryUnstick(edict_t* ent, const Vector3& oldvel) { int i; - vec3_t oldorg; - vec3_t dir; + Vector3 oldorg; + Vector3 dir; int clip; trace_t steptrace; - VectorCopy(ent->v.origin, oldorg); - VectorCopy(vec3_origin, dir); + oldorg = ent->v.origin; + dir = vec3_origin; for (i = 0; i < 8; i++) { // try pushing a little in an axial direction switch (i) { case 0: - dir[0] = 2; - dir[1] = 0; + dir.x = 2; + dir.y = 0; break; case 1: - dir[0] = 0; - dir[1] = 2; + dir.x = 0; + dir.y = 2; break; case 2: - dir[0] = -2; - dir[1] = 0; + dir.x = -2; + dir.y = 0; break; case 3: - dir[0] = 0; - dir[1] = -2; + dir.x = 0; + dir.y = -2; break; case 4: - dir[0] = 2; - dir[1] = 2; + dir.x = 2; + dir.y = 2; break; case 5: - dir[0] = -2; - dir[1] = 2; + dir.x = -2; + dir.y = 2; break; case 6: - dir[0] = 2; - dir[1] = -2; + dir.x = 2; + dir.y = -2; break; case 7: - dir[0] = -2; - dir[1] = -2; + dir.x = -2; + dir.y = -2; break; } SV_PushEntity(ent, dir); // retry the original move - ent->v.velocity[0] = oldvel[0]; - ent->v.velocity[1] = oldvel[1]; - ent->v.velocity[2] = 0; + ent->v.velocity = Vector3(oldvel.x, oldvel.y, 0.0f); clip = SV_FlyMove(ent, 0.1f, &steptrace); - if (fabs(oldorg[1] - ent->v.origin[1]) > 4 || fabs(oldorg[0] - ent->v.origin[0]) > 4) { + if (fabs(oldorg.y - ent->v.origin.y) > 4 || fabs(oldorg.x - ent->v.origin.x) > 4) { //Con_DPrintf ("unstuck!\n"); return clip; } // go back to the original pos and try again - VectorCopy(oldorg, ent->v.origin); + ent->v.origin = oldorg; } - VectorCopy(vec3_origin, ent->v.velocity); + ent->v.velocity = vec3_origin; return 7; // still not moving } @@ -1983,9 +1976,9 @@ Only used by players void SV_WalkMove(edict_t* ent) { - vec3_t upmove, downmove; - vec3_t oldorg, oldvel; - vec3_t nosteporg, nostepvel; + Vector3 upmove, downmove; + Vector3 oldorg, oldvel; + Vector3 nosteporg, nostepvel; int clip; int oldonground; trace_t steptrace, downtrace; @@ -1996,8 +1989,8 @@ void SV_WalkMove(edict_t* ent) oldonground = (int)ent->v.flags & FL_ONGROUND; ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND; - VectorCopy(ent->v.origin, oldorg); - VectorCopy(ent->v.velocity, oldvel); + oldorg = ent->v.origin; + oldvel = ent->v.velocity; clip = SV_FlyMove(ent, host_frametime, &steptrace); @@ -2021,32 +2014,30 @@ void SV_WalkMove(edict_t* ent) return; } - VectorCopy(ent->v.origin, nosteporg); - VectorCopy(ent->v.velocity, nostepvel); + nosteporg = ent->v.origin; + nostepvel = ent->v.velocity; // // try moving up and forward to go up a step // - VectorCopy(oldorg, ent->v.origin); // back to start pos + ent->v.origin = oldorg; // back to start pos - VectorCopy(vec3_origin, upmove); - VectorCopy(vec3_origin, downmove); - upmove[2] = STEPSIZE; - downmove[2] = -STEPSIZE + oldvel[2] * host_frametime; + upmove = vec3_origin; + downmove = vec3_origin; + upmove.z = STEPSIZE; + downmove.z = -STEPSIZE + oldvel.z * host_frametime; // move up SV_PushEntity(ent, upmove); // FIXME: don't link? // move forward - ent->v.velocity[0] = oldvel[0]; - ent->v.velocity[1] = oldvel[1]; - ent->v.velocity[2] = 0; + ent->v.velocity = Vector3(oldvel.x, oldvel.y, 0.0f); clip = SV_FlyMove(ent, host_frametime, &steptrace); // check for stuckness, possibly due to the limited precision of floats // in the clipping hulls if (clip) { - if (fabs(oldorg[1] - ent->v.origin[1]) < 0.03125 && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125) { // stepping up didn't make any progress + if (fabs(oldorg.y - ent->v.origin.y) < 0.03125 && fabs(oldorg.x - ent->v.origin.x) < 0.03125) { // stepping up didn't make any progress clip = SV_TryUnstick(ent, oldvel); } } @@ -2059,7 +2050,7 @@ void SV_WalkMove(edict_t* ent) // move down downtrace = SV_PushEntity(ent, downmove); // FIXME: don't link? - if (downtrace.plane.normal[2] > 0.7) { + if (downtrace.plane.normal.z > 0.7) { if (ent->v.solid == SOLID_BSP) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = EDICT_TO_PROG(downtrace.ent); @@ -2068,8 +2059,8 @@ void SV_WalkMove(edict_t* ent) // if the push down didn't end up on good ground, use the move without // the step up. This happens near wall / slope combinations, and can // cause the player to hop up higher on a slope too steep to climb - VectorCopy(nosteporg, ent->v.origin); - VectorCopy(nostepvel, ent->v.velocity); + ent->v.origin = nosteporg; + ent->v.velocity = nostepvel; } } @@ -2242,7 +2233,7 @@ Toss, bounce, and fly movement. When onground, do nothing. void SV_Physics_Toss(edict_t* ent) { trace_t trace; - vec3_t move; + Vector3 move; float backoff; // regular thinking if (!SV_RunThink(ent)) { @@ -2263,10 +2254,10 @@ void SV_Physics_Toss(edict_t* ent) // move angles - VectorMA(ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); + ent->v.angles += ent->v.avelocity * host_frametime; // move origin - VectorScale(ent->v.velocity, host_frametime, move); + move = ent->v.velocity * host_frametime; trace = SV_PushEntity(ent, move); if (trace.fraction == 1) { return; @@ -2287,13 +2278,13 @@ void SV_Physics_Toss(edict_t* ent) ClipVelocity(ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff); // stop if on ground - if (trace.plane.normal[2] > 0.7) { - if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE) + if (trace.plane.normal.z > 0.7) { + if (ent->v.velocity.z < 60 || ent->v.movetype != MOVETYPE_BOUNCE) { ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = EDICT_TO_PROG(trace.ent); - VectorCopy(vec3_origin, ent->v.velocity); - VectorCopy(vec3_origin, ent->v.avelocity); + ent->v.velocity = vec3_origin; + ent->v.avelocity = vec3_origin; } } @@ -2322,7 +2313,7 @@ void SV_Physics_Step(edict_t* ent) // freefall if not onground if (!((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) { - if (ent->v.velocity[2] < sv_gravity.value * -0.1) { + if (ent->v.velocity.z < sv_gravity.value * -0.1) { hitsound = true; } else { hitsound = false; @@ -2423,22 +2414,22 @@ is not a staircase. */ qboolean SV_CheckBottom(edict_t* ent) { - vec3_t mins, maxs, start, stop; + Vector3 mins, maxs, start, stop; trace_t trace; int x, y; float mid, bottom; - VectorAdd(ent->v.origin, ent->v.mins, mins); - VectorAdd(ent->v.origin, ent->v.maxs, maxs); + mins = ent->v.origin + ent->v.mins; + maxs = ent->v.origin + ent->v.maxs; // if all of the points under the corners are solid world, don't bother // with the tougher checks // the corners must be within 16 of the midpoint - start[2] = mins[2] - 1; + start.z = mins.z - 1; for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { - start[0] = x ? maxs[0] : mins[0]; - start[1] = y ? maxs[1] : mins[1]; + start.x = x ? maxs.x : mins.x; + start.y = y ? maxs.y : mins.y; if (SV_PointContents(start) != CONTENTS_SOLID) { goto realcheck; } @@ -2454,33 +2445,33 @@ qboolean SV_CheckBottom(edict_t* ent) // // check it for real... // - start[2] = mins[2]; + start.z = mins.z; // the midpoint must be within 16 of the bottom - start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5; - start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5; - stop[2] = start[2] - 2 * STEPSIZE; + start.x = stop.x = (mins.x + maxs.x) * 0.5f; + start.y = stop.y = (mins.y + maxs.y) * 0.5f; + stop.z = start.z - 2 * STEPSIZE; trace = SV_Move(start, vec3_origin, vec3_origin, stop, true, ent); if (trace.fraction == 1.0) { return false; } - mid = bottom = trace.endpos[2]; + mid = bottom = trace.endpos.z; // the corners must be within 16 of the midpoint for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { - start[0] = stop[0] = x ? maxs[0] : mins[0]; - start[1] = stop[1] = y ? maxs[1] : mins[1]; + start.x = stop.x = x ? maxs.x : mins.x; + start.y = stop.y = y ? maxs.y : mins.y; trace = SV_Move(start, vec3_origin, vec3_origin, stop, true, ent); - if (trace.fraction != 1.0 && trace.endpos[2] > bottom) { - bottom = trace.endpos[2]; + if (trace.fraction != 1.0 && trace.endpos.z > bottom) { + bottom = trace.endpos.z; } - if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE) { + if (trace.fraction == 1.0 || mid - trace.endpos.z > STEPSIZE) { return false; } } @@ -2501,32 +2492,32 @@ possible, no move is done, false is returned, and pr_global_struct->trace_normal is set to the normal of the blocking wall ============= */ -qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) +qboolean SV_movestep(edict_t* ent, const Vector3& move, qboolean relink) { float dz; - vec3_t oldorg, neworg, end; + Vector3 oldorg, neworg, end; trace_t trace; int i; edict_t* enemy; // try the move VectorCopy(ent->v.origin, oldorg); - VectorAdd(ent->v.origin, move, neworg); + neworg = ent->v.origin + move; // flying monsters don't step up if ((int)ent->v.flags & (FL_SWIM | FL_FLY)) { // try one move with vertical motion, then one without for (i = 0; i < 2; i++) { - VectorAdd(ent->v.origin, move, neworg); + neworg = ent->v.origin + move; enemy = PROG_TO_EDICT(ent->v.enemy); if (i == 0 && enemy != sv.edicts) { - dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2]; + dz = ent->v.origin.z - PROG_TO_EDICT(ent->v.enemy)->v.origin.z; if (dz > 40) { - neworg[2] -= 8; + neworg.z -= 8; } if (dz < 30) { - neworg[2] += 8; + neworg.z += 8; } } @@ -2537,7 +2528,7 @@ qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) return false; // swim monster left water } - VectorCopy(trace.endpos, ent->v.origin); + ent->v.origin = trace.endpos; if (relink) { SV_LinkEdict(ent, true); } @@ -2554,9 +2545,9 @@ qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) } // push down from a step height above the wished position - neworg[2] += STEPSIZE; - VectorCopy(neworg, end); - end[2] -= STEPSIZE * 2; + neworg.z += STEPSIZE; + end = neworg; + end.z -= STEPSIZE * 2; trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, false, ent); @@ -2565,7 +2556,7 @@ qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) } if (trace.startsolid) { - neworg[2] -= STEPSIZE; + neworg.z -= STEPSIZE; trace = SV_Move(neworg, ent->v.mins, ent->v.maxs, end, false, ent); if (trace.allsolid || trace.startsolid) { return false; @@ -2575,7 +2566,7 @@ qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) if (trace.fraction == 1) { // if monster had the ground pulled out, go ahead and fall if ((int)ent->v.flags & FL_PARTIALGROUND) { - VectorAdd(ent->v.origin, move, ent->v.origin); + ent->v.origin += move; if (relink) { SV_LinkEdict(ent, true); } @@ -2590,7 +2581,7 @@ qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) } // check point traces down for dangling corners - VectorCopy(trace.endpos, ent->v.origin); + ent->v.origin = trace.endpos; if (!SV_CheckBottom(ent)) { if ((int)ent->v.flags & FL_PARTIALGROUND) { // entity had floor mostly pulled out from underneath it @@ -2602,7 +2593,7 @@ qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) return true; } - VectorCopy(oldorg, ent->v.origin); + ent->v.origin = oldorg; return false; } @@ -2622,8 +2613,6 @@ qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink) return true; } -//============================================================================ - /* ====================== SV_StepDirection @@ -2636,22 +2625,22 @@ facing it. qboolean SV_StepDirection(edict_t* ent, float yaw, float dist) { - vec3_t move, oldorigin; + Vector3 move, oldorigin; float delta; ent->v.ideal_yaw = yaw; VM::PF_changeyaw(); yaw = yaw * M_PI * 2 / 360; - move[0] = cos(yaw) * dist; - move[1] = sin(yaw) * dist; - move[2] = 0; + move.x = cos(yaw) * dist; + move.y = sin(yaw) * dist; + move.z = 0; - VectorCopy(ent->v.origin, oldorigin); + oldorigin = ent->v.origin; if (SV_movestep(ent, move, false)) { delta = ent->v.angles[YAW] - ent->v.ideal_yaw; if (delta > 45 && delta < 315) { // not turned far enough, so don't take the step - VectorCopy(oldorigin, ent->v.origin); + ent->v.origin = oldorigin; } SV_LinkEdict(ent, true); @@ -2846,7 +2835,7 @@ void SV_SetIdealPitch(void) { float angleval, sinval, cosval; trace_t tr; - vec3_t top, bottom; + Vector3 top, bottom; float z[MAX_FORWARD]; int i, j; int step, dir, steps; @@ -2860,13 +2849,13 @@ void SV_SetIdealPitch(void) cosval = cos(angleval); for (i = 0; i < MAX_FORWARD; i++) { - top[0] = sv_player->v.origin[0] + cosval * (i + 3) * 12; - top[1] = sv_player->v.origin[1] + sinval * (i + 3) * 12; - top[2] = sv_player->v.origin[2] + sv_player->v.view_ofs[2]; + top.x = sv_player->v.origin.x + cosval * (i + 3) * 12; + top.y = sv_player->v.origin.y + sinval * (i + 3) * 12; + top.z = sv_player->v.origin.z + sv_player->v.view_ofs.z; - bottom[0] = top[0]; - bottom[1] = top[1]; - bottom[2] = top[2] - 160; + bottom.x = top.x; + bottom.y = top.y; + bottom.z = top.z - 160; tr = SV_Move(top, vec3_origin, vec3_origin, bottom, 1, sv_player); if (tr.allsolid) { @@ -2877,7 +2866,7 @@ void SV_SetIdealPitch(void) return; // near a dropoff } - z[i] = top[2] + tr.fraction * (bottom[2] - top[2]); + z[i] = top.z + tr.fraction * (bottom.z - top.z); } dir = 0; @@ -2917,24 +2906,21 @@ SV_UserFriction */ void SV_UserFriction(void) { - float* vel; float speed, newspeed, control; - vec3_t start, stop; + Vector3 start, stop; float friction; trace_t trace; - vel = velocity; - - speed = sqrt(vel[0] * vel[0] + vel[1] * vel[1]); + speed = sqrt(velocity[0] * velocity[0] + velocity[1] * velocity[1]); if (!speed) { return; } // if the leading edge is over a dropoff, increase friction - start[0] = stop[0] = origin[0] + vel[0] / speed * 16; - start[1] = stop[1] = origin[1] + vel[1] / speed * 16; - start[2] = origin[2] + sv_player->v.mins[2]; - stop[2] = start[2] - 34; + start.x = stop.x = origin[0] + velocity[0] / speed * 16; + start.y = stop.y = origin[1] + velocity[1] / speed * 16; + start.z = origin[2] + sv_player->v.mins.z; + stop.z = start.z - 34; trace = SV_Move(start, vec3_origin, vec3_origin, stop, true, sv_player); @@ -2954,9 +2940,9 @@ void SV_UserFriction(void) newspeed /= speed; - vel[0] = vel[0] * newspeed; - vel[1] = vel[1] * newspeed; - vel[2] = vel[2] * newspeed; + velocity[0] = velocity[0] * newspeed; + velocity[1] = velocity[1] * newspeed; + velocity[2] = velocity[2] * newspeed; } /* @@ -2985,12 +2971,12 @@ void SV_Accelerate(void) } } -void SV_AirAccelerate(vec3_t wishveloc) +void SV_AirAccelerate(Vector3 wishveloc) { int i; float addspeed, wishspd, accelspeed, currentspeed; - wishspd = VectorNormalize(wishveloc); + wishspd = wishveloc.normalize(); if (wishspd > 30) { wishspd = 30; } @@ -3016,14 +3002,14 @@ void DropPunchAngle(void) { float len; - len = VectorNormalize(sv_player->v.punchangle); + len = sv_player->v.punchangle.normalize(); len -= 10 * host_frametime; if (len < 0) { len = 0; } - VectorScale(sv_player->v.punchangle, len, sv_player->v.punchangle); + sv_player->v.punchangle *= len; } /* @@ -3035,8 +3021,8 @@ SV_WaterMove void SV_WaterMove(void) { int i; - vec3_t wishvel; - vec3_t forward, right, up; + Vector3 wishvel; + Vector3 forward, right, up; float speed, newspeed, w_speed, addspeed, accelspeed; // @@ -3044,19 +3030,17 @@ void SV_WaterMove(void) // AngleVectors(sv_player->v.v_angle, forward, right, up); - for (i = 0; i < 3; i++) { - wishvel[i] = forward[i] * cmd.forwardmove + right[i] * cmd.sidemove; - } + wishvel = forward * cmd.forwardmove + right * cmd.sidemove; if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove) { - wishvel[2] -= 60; // drift towards bottom + wishvel.z -= 60; // drift towards bottom } else { - wishvel[2] += cmd.upmove; + wishvel.z += cmd.upmove; } - w_speed = Length(wishvel); + w_speed = wishvel.length(); if (w_speed > sv_maxspeed.value) { - VectorScale(wishvel, sv_maxspeed.value / w_speed, wishvel); + wishvel *= sv_maxspeed.value / w_speed; w_speed = sv_maxspeed.value; } @@ -3089,7 +3073,7 @@ void SV_WaterMove(void) return; } - VectorNormalize(wishvel); + wishvel.normalize(); accelspeed = sv_accelerate.value * w_speed * host_frametime; if (accelspeed > addspeed) { accelspeed = addspeed; @@ -3107,8 +3091,8 @@ void SV_WaterJump(void) sv_player->v.teleport_time = 0; } - sv_player->v.velocity[0] = sv_player->v.movedir[0]; - sv_player->v.velocity[1] = sv_player->v.movedir[1]; + sv_player->v.velocity.x = sv_player->v.movedir.x; + sv_player->v.velocity.y = sv_player->v.movedir.y; } /* @@ -3119,9 +3103,8 @@ SV_AirMove */ void SV_AirMove(void) { - int i; - vec3_t wishvel; - vec3_t forward, right, up; + Vector3 wishvel; + Vector3 forward, right, up; float fmove, smove; AngleVectors(sv_player->v.angles, forward, right, up); @@ -3134,20 +3117,18 @@ void SV_AirMove(void) fmove = 0; } - for (i = 0; i < 3; i++) { - wishvel[i] = forward[i] * fmove + right[i] * smove; - } + wishvel = forward * fmove + right * smove; if ((int)sv_player->v.movetype != MOVETYPE_WALK) { - wishvel[2] = cmd.upmove; + wishvel.z = cmd.upmove; } else { - wishvel[2] = 0; + wishvel.z = 0; } - VectorCopy(wishvel, wishdir); - wishspeed = VectorNormalize(wishdir); + wishdir = wishvel; + wishspeed = wishdir.normalize(); if (wishspeed > sv_maxspeed.value) { - VectorScale(wishvel, sv_maxspeed.value / wishspeed, wishvel); + wishvel *= sv_maxspeed.value / wishspeed; wishspeed = sv_maxspeed.value; } @@ -3171,7 +3152,7 @@ the angle fields specify an exact angular motion in degrees */ void SV_ClientThink(void) { - vec3_t v_angle; + Vector3 v_angle; if (sv_player->v.movetype == MOVETYPE_NONE) { return; @@ -3197,7 +3178,7 @@ void SV_ClientThink(void) cmd = host_client->cmd; angles = sv_player->v.angles; - VectorAdd(sv_player->v.v_angle, sv_player->v.punchangle, v_angle); + v_angle = sv_player->v.v_angle + sv_player->v.punchangle; angles[ROLL] = V_CalcRoll(sv_player->v.angles, sv_player->v.velocity) * 4; if (!sv_player->v.fixangle) { angles[PITCH] = -v_angle[PITCH] / 3; @@ -3230,7 +3211,7 @@ SV_ReadClientMove void SV_ReadClientMove(usercmd_t* move) { int i; - vec3_t angle; + Vector3 angle; int bits; // read ping time @@ -3238,11 +3219,11 @@ void SV_ReadClientMove(usercmd_t* move) host_client->num_pings++; // read current angles - for (i = 0; i < 3; i++) { - angle[i] = MSG_ReadAngle(); - } + angle.x = MSG_ReadAngle(); + angle.y = MSG_ReadAngle(); + angle.z = MSG_ReadAngle(); - VectorCopy(angle, host_client->edict->v.v_angle); + host_client->edict->v.v_angle = angle; // read movement move->forwardmove = MSG_ReadShort(); diff --git a/src/server.hpp b/src/server.hpp index d7b3101..703e282 100644 --- a/src/server.hpp +++ b/src/server.hpp @@ -65,7 +65,7 @@ typedef struct client_s { struct qsocket_s* netconnection; // communications handle usercmd_t cmd; // movement - vec3_t wishdir; // intended motion calced from cmd + Vector3 wishdir; // intended motion calced from cmd sizebuf_t message; // can be added to at any time, // copied and clear once per frame @@ -157,8 +157,23 @@ extern cvar_t timelimit; extern cvar_t sv_gravity; -extern server_static_t svs; // persistant server info -extern server_t sv; // local server +class ServerSubsystem { +public: + server_static_t& GetStaticState() { return svs_; } + const server_static_t& GetStaticState() const { return svs_; } + + server_t& GetState() { return sv_; } + const server_t& GetState() const { return sv_; } + +private: + server_static_t svs_; + server_t sv_; +}; + +ServerSubsystem& GetServerSubsystem(); + +inline server_static_t& svs = GetServerSubsystem().GetStaticState(); +inline server_t& sv = GetServerSubsystem().GetState(); extern edict_t* sv_player; @@ -166,7 +181,7 @@ extern edict_t* sv_player; void SV_Init(void); -void SV_StartParticle(vec3_t org, vec3_t dir, int color, int count); +void SV_StartParticle(const Vector3& org, const Vector3& dir, int color, int count); void SV_StartSound(edict_t* entity, int channel, const char* sample, @@ -192,7 +207,7 @@ void SV_BroadcastPrintf(const char* fmt, ...); void SV_Physics(void); qboolean SV_CheckBottom(edict_t* ent); -qboolean SV_movestep(edict_t* ent, vec3_t move, qboolean relink); +qboolean SV_movestep(edict_t* ent, const Vector3& move, qboolean relink); void SV_WriteClientdataToMessage(edict_t* ent, sizebuf_t* msg); diff --git a/src/vid_sdl.cpp b/src/vid_sdl.cpp index c8dad40..e82cbd9 100644 --- a/src/vid_sdl.cpp +++ b/src/vid_sdl.cpp @@ -35,8 +35,10 @@ viddef_t vid; unsigned short d_8to16table[256]; +#ifdef _MSC_VER #include "winquake.hpp" modestate_t modestate = MS_WINDOWED; +#endif cvar_t _windowed_mouse = {"_windowed_mouse", "1"}; void VID_HandlePause() diff --git a/src/view.cpp b/src/view.cpp index f0ba4a8..2722ec3 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -83,16 +83,16 @@ V_CalcRoll Used by view and sv_user =============== */ -vec3_t forward, right, up; +Vector3 forward, right, up; -float V_CalcRoll(vec3_t angles, vec3_t velocity) +float V_CalcRoll(const Vector3& angles, const Vector3& velocity) { float sign; float side; float value; AngleVectors(angles, forward, right, up); - side = DotProduct(velocity, right); + side = velocity.dot(right); sign = side < 0 ? -1 : 1; side = fabs(side); @@ -312,18 +312,17 @@ V_ParseDamage void V_ParseDamage(void) { int armor, blood; - vec3_t from; - int i; - vec3_t v_forward, v_right, v_up; + Vector3 from; + Vector3 v_forward, v_right, v_up; entity_t* ent; float side; float count; armor = MSG_ReadByte(); blood = MSG_ReadByte(); - for (i = 0; i < 3; i++) { - from[i] = MSG_ReadCoord(); - } + from.x = MSG_ReadCoord(); + from.y = MSG_ReadCoord(); + from.z = MSG_ReadCoord(); count = blood * 0.5 + armor * 0.5; if (count < 10) { @@ -360,15 +359,15 @@ void V_ParseDamage(void) // ent = &cl_entities[cl.viewentity]; - VectorSubtract(from, ent->origin, from); - VectorNormalize(from); + from = from - ent->origin; + from.normalize(); AngleVectors(ent->angles, v_forward, v_right, v_up); - side = DotProduct(from, v_right); + side = from.dot(v_right); v_dmg_roll = count * side * v_kickroll.value; - side = DotProduct(from, v_forward); + side = from.dot(v_forward); v_dmg_pitch = count * side * v_kickpitch.value; v_dmg_time = v_kicktime.value; @@ -730,9 +729,8 @@ V_CalcRefdef void V_CalcRefdef(void) { entity_t *ent, *view; - int i; - vec3_t v_forward, v_right, v_up; - vec3_t angles; + Vector3 v_forward, v_right, v_up; + Vector3 angles; float bob; static float oldz = 0; @@ -753,17 +751,15 @@ void V_CalcRefdef(void) bob = V_CalcBob(); // refresh position - VectorCopy(ent->origin, r_refdef.vieworg); - r_refdef.vieworg[2] += cl.viewheight + bob; + r_refdef.vieworg = ent->origin; + r_refdef.vieworg.z += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis - r_refdef.vieworg[0] += 1.0 / 32; - r_refdef.vieworg[1] += 1.0 / 32; - r_refdef.vieworg[2] += 1.0 / 32; + r_refdef.vieworg += Vector3(1.0f / 32.0f, 1.0f / 32.0f, 1.0f / 32.0f); - VectorCopy(cl.viewangles, r_refdef.viewangles); + r_refdef.viewangles = cl.viewangles; V_CalcViewRoll(); V_AddIdle(); @@ -775,26 +771,20 @@ void V_CalcRefdef(void) AngleVectors(angles, v_forward, v_right, v_up); - for (i = 0; i < 3; i++) { - r_refdef.vieworg[i] += scr_ofsx.value * v_forward[i] + scr_ofsy.value * v_right[i] + scr_ofsz.value * v_up[i]; - } + r_refdef.vieworg += v_forward * scr_ofsx.value + v_right * scr_ofsy.value + v_up * scr_ofsz.value; V_BoundOffsets(); // set up gun position - VectorCopy(cl.viewangles, view->angles); + view->angles = cl.viewangles; CalcGunAngle(); - VectorCopy(ent->origin, view->origin); - view->origin[2] += cl.viewheight; + view->origin = ent->origin; + view->origin.z += cl.viewheight; - for (i = 0; i < 3; i++) { - view->origin[i] += forward[i] * bob * 0.4; - // view->origin[i] += right[i]*bob*0.4; - // view->origin[i] += up[i]*bob*0.8; - } - view->origin[2] += bob; + view->origin += forward * (bob * 0.4f); + view->origin.z += bob; // fudge position around to keep amount of weapon visible // roughly equal with different FOV diff --git a/src/view.hpp b/src/view.hpp index 1a820a8..27c4d3b 100644 --- a/src/view.hpp +++ b/src/view.hpp @@ -15,7 +15,7 @@ extern cvar_t lcd_x; void V_Init(void); void V_RenderView(void); -float V_CalcRoll(vec3_t angles, vec3_t velocity); +float V_CalcRoll(const Vector3& angles, const Vector3& velocity); void V_UpdatePalette(void); void V_StartPitchDrift(void); void V_StopPitchDrift(void); diff --git a/src/vm.cpp b/src/vm.cpp index 19894e8..24efbab 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -2028,11 +2028,11 @@ void PF_setorigin(void) void SetMinMaxSize(edict_t* e, float* min, float* max, qboolean rotate) { float* angles; - vec3_t rmin, rmax; + Vector3 rmin, rmax; float bounds[2][3]; float xvector[2], yvector[2]; float a; - vec3_t base, transformed; + Vector3 base, transformed; int i, j, k, l; for (i = 0; i < 3; i++) { @@ -2044,8 +2044,8 @@ void SetMinMaxSize(edict_t* e, float* min, float* max, qboolean rotate) rotate = false; // FIXME: implement rotation properly again if (!rotate) { - VectorCopy(min, rmin); - VectorCopy(max, rmax); + rmin = Vector3(min); + rmax = Vector3(max); } else { // find min / max for rotations angles = e->v.angles; @@ -2090,9 +2090,9 @@ void SetMinMaxSize(edict_t* e, float* min, float* max, qboolean rotate) } // set derived values - VectorCopy(rmin, e->v.mins); - VectorCopy(rmax, e->v.maxs); - VectorSubtract(max, min, e->v.size); + e->v.mins = rmin; + e->v.maxs = rmax; + e->v.size = Vector3(max) - Vector3(min); SV_LinkEdict(e, false); } @@ -2244,7 +2244,7 @@ vector normalize(vector) void PF_normalize(void) { float* value1; - vec3_t newvalue; + Vector3 newvalue; float new_val; value1 = G_VECTOR(OFS_PARM0); @@ -2506,15 +2506,15 @@ void PF_traceline(void) { float *v1, *v2; trace_t trace; - int nomonsters; + int no_monsters; edict_t* ent; v1 = G_VECTOR(OFS_PARM0); v2 = G_VECTOR(OFS_PARM1); - nomonsters = G_FLOAT(OFS_PARM2); + no_monsters = G_FLOAT(OFS_PARM2); ent = G_EDICT(OFS_PARM3); - trace = SV_Move(v1, vec3_origin, vec3_origin, v2, nomonsters, ent); + trace = SV_Move(v1, vec3_origin, vec3_origin, v2, no_monsters, ent); pr_global_struct->trace_allsolid = trace.allsolid; pr_global_struct->trace_startsolid = trace.startsolid; @@ -2542,7 +2542,7 @@ int PF_newcheckclient(int check) byte* pvs; edict_t* ent; mleaf_t* leaf; - vec3_t org; + Vector3 org; // cycle to the next one @@ -2588,7 +2588,7 @@ int PF_newcheckclient(int check) } // get the PVS for the entity - VectorAdd(ent->v.origin, ent->v.view_ofs, org); + org = ent->v.origin + ent->v.view_ofs; leaf = Mod_PointInLeaf(org, sv.worldmodel); pvs = Mod_LeafPVS(leaf, sv.worldmodel); memcpy(checkpvs, pvs, (sv.worldmodel->numleafs + 7) >> 3); @@ -2619,7 +2619,7 @@ void PF_checkclient(void) edict_t *ent, *self; mleaf_t* leaf; int l; - vec3_t view; + Vector3 view; // find a new check if on a new frame if (sv.time - sv.lastchecktime >= 0.1) { @@ -2637,7 +2637,7 @@ void PF_checkclient(void) // if current entity can't possibly see the check entity, return 0 self = PROG_TO_EDICT(pr_global_struct->self); - VectorAdd(self->v.origin, self->v.view_ofs, view); + view = self->v.origin + self->v.view_ofs; leaf = Mod_PointInLeaf(view, sv.worldmodel); l = (leaf - sv.worldmodel->leafs) - 1; if ((l < 0) || !(checkpvs[l >> 3] & (1 << (l & 7)))) { @@ -2746,8 +2746,8 @@ void PF_findradius(void) edict_t *ent, *chain; float rad; float* org; - vec3_t eorg; - int i, j; + Vector3 eorg; + int i; chain = (edict_t*)sv.edicts; @@ -2764,10 +2764,8 @@ void PF_findradius(void) continue; } - for (j = 0; j < 3; j++) { - eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j]) * 0.5); - } - if (Length(eorg) > rad) { + eorg = Vector3(org) - (ent->v.origin + (ent->v.mins + ent->v.maxs) * 0.5f); + if (eorg.length() > rad) { continue; } @@ -2969,7 +2967,7 @@ void PF_walkmove(void) { edict_t* ent; float yaw, dist; - vec3_t move; + Vector3 move; dfunction_t* oldf; int oldself; @@ -2985,9 +2983,9 @@ void PF_walkmove(void) yaw = yaw * M_PI * 2 / 360; - move[0] = cos(yaw) * dist; - move[1] = sin(yaw) * dist; - move[2] = 0; + move.x = cos(yaw) * dist; + move.y = sin(yaw) * dist; + move.z = 0; // save program state, because SV_movestep may call other progs oldf = pr_xfunction; @@ -3010,20 +3008,20 @@ void() droptofloor void PF_droptofloor(void) { edict_t* ent; - vec3_t end; + Vector3 end; trace_t trace; ent = PROG_TO_EDICT(pr_global_struct->self); - VectorCopy(ent->v.origin, end); - end[2] -= 256; + end = ent->v.origin; + end.z -= 256; trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); if (trace.fraction == 1 || trace.allsolid) { G_FLOAT(OFS_RETURN) = 0; } else { - VectorCopy(trace.endpos, ent->v.origin); + ent->v.origin = trace.endpos; SV_LinkEdict(ent, false); ent->v.flags = (int)ent->v.flags | FL_ONGROUND; ent->v.groundentity = EDICT_TO_PROG(trace.ent); @@ -3157,8 +3155,8 @@ cvar_t sv_aim = { "sv_aim", "0.93" }; void PF_aim(void) { edict_t *ent, *check, *bestent; - vec3_t start, dir, end, bestdir; - int i, j; + Vector3 start, dir, end, bestdir; + int i; trace_t tr; float dist, bestdist; float speed; @@ -3166,12 +3164,12 @@ void PF_aim(void) ent = G_EDICT(OFS_PARM0); speed = G_FLOAT(OFS_PARM1); - VectorCopy(ent->v.origin, start); - start[2] += 20; + start = ent->v.origin; + start.z += 20; // try sending a trace straight - VectorCopy(pr_global_struct->v_forward, dir); - VectorMA(start, 2048, dir, end); + dir = pr_global_struct->v_forward; + end = start + dir * 2048.0f; tr = SV_Move(start, vec3_origin, vec3_origin, end, false, ent); if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM && (!teamplay.value || ent->v.team <= 0 || ent->v.team != tr.ent->v.team)) { VectorCopy(pr_global_struct->v_forward, G_VECTOR(OFS_RETURN)); @@ -3180,7 +3178,7 @@ void PF_aim(void) } // try all possible entities - VectorCopy(dir, bestdir); + bestdir = dir; bestdist = sv_aim.value; bestent = NULL; @@ -3198,12 +3196,10 @@ void PF_aim(void) continue; // don't aim at teammate } - for (j = 0; j < 3; j++) { - end[j] = check->v.origin[j] + 0.5 * (check->v.mins[j] + check->v.maxs[j]); - } - VectorSubtract(end, start, dir); - VectorNormalize(dir); - dist = DotProduct(dir, pr_global_struct->v_forward); + end = check->v.origin + (check->v.mins + check->v.maxs) * 0.5f; + dir = end - start; + dir.normalize(); + dist = dir.dot(pr_global_struct->v_forward); if (dist < bestdist) { continue; // to far to turn } @@ -3216,11 +3212,11 @@ void PF_aim(void) } if (bestent) { - VectorSubtract(bestent->v.origin, ent->v.origin, dir); - dist = DotProduct(dir, pr_global_struct->v_forward); - VectorScale(pr_global_struct->v_forward, dist, end); - end[2] = dir[2]; - VectorNormalize(end); + dir = bestent->v.origin - ent->v.origin; + dist = dir.dot(pr_global_struct->v_forward); + end = pr_global_struct->v_forward * dist; + end.z = dir.z; + end.normalize(); VectorCopy(end, G_VECTOR(OFS_RETURN)); } else { VectorCopy(bestdir, G_VECTOR(OFS_RETURN)); @@ -3362,8 +3358,6 @@ inline void PF_WriteEntity(void) //============================================================================= -int ::SV_ModelIndex(const char* name); - void PF_makestatic(void) { edict_t* ent; diff --git a/src/progs.hpp b/src/vm.hpp similarity index 98% rename from src/progs.hpp rename to src/vm.hpp index 29ceaad..22d414b 100644 --- a/src/progs.hpp +++ b/src/vm.hpp @@ -1,4 +1,4 @@ -// progs.h -- QuakeC program runtime structures +// vm.hpp -- QuakeC program runtime structures #pragma once #include "pr_comp.hpp" // defs shared with qcc diff --git a/src/world.cpp b/src/world.cpp index 817cd02..d315a00 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -38,16 +38,16 @@ line of sight checks trace->crosscontent, but bullets don't */ typedef struct { - vec3_t boxmins, boxmaxs; // enclose the test object along entire move - float *mins, *maxs; // size of the moving object - vec3_t mins2, maxs2; // size when clipping against mosnters - float *start, *end; + Vector3 boxmins, boxmaxs; // enclose the test object along entire move + Vector3 mins, maxs; // size of the moving object + Vector3 mins2, maxs2; // size when clipping against mosnters + Vector3 start, end; trace_t trace; int type; edict_t* passedict; } moveclip_t; -int SV_HullPointContents(hull_t* hull, int num, vec3_t p); +int SV_HullPointContents(hull_t* hull, int num, const Vector3& p); /* =============================================================================== @@ -104,14 +104,14 @@ To keep everything totally uniform, bounding boxes are turned into small BSP trees instead of being compared directly. =================== */ -hull_t* SV_HullForBox(vec3_t mins, vec3_t maxs) +hull_t* SV_HullForBox(const Vector3& mins, const Vector3& maxs) { - box_planes[0].dist = maxs[0]; - box_planes[1].dist = mins[0]; - box_planes[2].dist = maxs[1]; - box_planes[3].dist = mins[1]; - box_planes[4].dist = maxs[2]; - box_planes[5].dist = mins[2]; + box_planes[0].dist = maxs.x; + box_planes[1].dist = mins.x; + box_planes[2].dist = maxs.y; + box_planes[3].dist = mins.y; + box_planes[4].dist = maxs.z; + box_planes[5].dist = mins.z; return &box_hull; } @@ -127,13 +127,13 @@ testing object's origin to get a point to use with the returned hull. ================ */ hull_t* SV_HullForEntity(edict_t* ent, - vec3_t mins, - vec3_t maxs, - vec3_t offset) + const Vector3& mins, + const Vector3& maxs, + Vector3& offset) { model_t* model; - vec3_t size; - vec3_t hullmins, hullmaxs; + Vector3 size; + Vector3 hullmins, hullmaxs; hull_t* hull; // decide which clipping hull to use, based on the size @@ -148,25 +148,25 @@ hull_t* SV_HullForEntity(edict_t* ent, Sys_Error("MOVETYPE_PUSH with a non bsp model"); } - VectorSubtract(maxs, mins, size); - if (size[0] < 3) { + size = maxs - mins; + if (size.x < 3) { hull = &model->hulls[0]; - } else if (size[0] <= 32) { + } else if (size.x <= 32) { hull = &model->hulls[1]; } else { hull = &model->hulls[2]; } // calculate an offset value to center the origin - VectorSubtract(hull->clip_mins, mins, offset); - VectorAdd(offset, ent->v.origin, offset); + offset = hull->clip_mins - mins; + offset += ent->v.origin; } else { // create a temp hull from bounding box sizes - VectorSubtract(ent->v.mins, maxs, hullmins); - VectorSubtract(ent->v.maxs, mins, hullmaxs); + hullmins = ent->v.mins - maxs; + hullmaxs = ent->v.maxs - mins; hull = SV_HullForBox(hullmins, hullmaxs); - VectorCopy(ent->v.origin, offset); + offset = ent->v.origin; } return hull; @@ -200,11 +200,11 @@ SV_CreateAreaNode =============== */ -areanode_t* SV_CreateAreaNode(int depth, vec3_t mins, vec3_t maxs) +areanode_t* SV_CreateAreaNode(int depth, const Vector3& mins, const Vector3& maxs) { areanode_t* anode; - vec3_t size; - vec3_t mins1, maxs1, mins2, maxs2; + Vector3 size; + Vector3 mins1, maxs1, mins2, maxs2; anode = &sv_areanodes[sv_numareanodes]; sv_numareanodes++; @@ -219,18 +219,18 @@ areanode_t* SV_CreateAreaNode(int depth, vec3_t mins, vec3_t maxs) return anode; } - VectorSubtract(maxs, mins, size); - if (size[0] > size[1]) { + size = maxs - mins; + if (size.x > size.y) { anode->axis = 0; } else { anode->axis = 1; } anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]); - VectorCopy(mins, mins1); - VectorCopy(mins, mins2); - VectorCopy(maxs, maxs1); - VectorCopy(maxs, maxs2); + mins1 = mins; + mins2 = mins; + maxs1 = maxs; + maxs2 = maxs; maxs1[anode->axis] = mins2[anode->axis] = anode->dist; @@ -294,7 +294,7 @@ void SV_TouchLinks(edict_t* ent, areanode_t* node) continue; } - if (ent->v.absmin[0] > touch->v.absmax[0] || ent->v.absmin[1] > touch->v.absmax[1] || ent->v.absmin[2] > touch->v.absmax[2] || ent->v.absmax[0] < touch->v.absmin[0] || ent->v.absmax[1] < touch->v.absmin[1] || ent->v.absmax[2] < touch->v.absmin[2]) { + if (ent->v.absmin.x > touch->v.absmax.x || ent->v.absmin.y > touch->v.absmax.y || ent->v.absmin.z > touch->v.absmax.z || ent->v.absmax.x < touch->v.absmin.x || ent->v.absmax.y < touch->v.absmin.y || ent->v.absmax.z < touch->v.absmin.z) { continue; } @@ -397,8 +397,8 @@ void SV_LinkEdict(edict_t* ent, qboolean touch_triggers) // set the abs box { - VectorAdd(ent->v.origin, ent->v.mins, ent->v.absmin); - VectorAdd(ent->v.origin, ent->v.maxs, ent->v.absmax); + ent->v.absmin = ent->v.origin + ent->v.mins; + ent->v.absmax = ent->v.origin + ent->v.maxs; } // @@ -406,18 +406,18 @@ void SV_LinkEdict(edict_t* ent, qboolean touch_triggers) // of shelves, the abs sizes are expanded // if ((int)ent->v.flags & FL_ITEM) { - ent->v.absmin[0] -= 15; - ent->v.absmin[1] -= 15; - ent->v.absmax[0] += 15; - ent->v.absmax[1] += 15; + ent->v.absmin.x -= 15; + ent->v.absmin.y -= 15; + ent->v.absmax.x += 15; + ent->v.absmax.y += 15; } else { // because movement is clipped an epsilon away from an actual edge, // we must fully check even when bounding boxes don't quite touch - ent->v.absmin[0] -= 1; - ent->v.absmin[1] -= 1; - ent->v.absmin[2] -= 1; - ent->v.absmax[0] += 1; - ent->v.absmax[1] += 1; - ent->v.absmax[2] += 1; + ent->v.absmin.x -= 1; + ent->v.absmin.y -= 1; + ent->v.absmin.z -= 1; + ent->v.absmax.x += 1; + ent->v.absmax.y += 1; + ent->v.absmax.z += 1; } // link to PVS leafs @@ -474,7 +474,7 @@ SV_HullPointContents ================== */ -int SV_HullPointContents(hull_t* hull, int num, vec3_t p) +int SV_HullPointContents(hull_t* hull, int num, const Vector3& p) { float d; dclipnode_t* node; @@ -491,7 +491,7 @@ int SV_HullPointContents(hull_t* hull, int num, vec3_t p) if (plane->type < 3) { d = p[plane->type] - plane->dist; } else { - d = DotProduct(plane->normal, p) - plane->dist; + d = plane->normal.dot(p) - plane->dist; } if (d < 0) { @@ -510,7 +510,7 @@ SV_PointContents ================== */ -int SV_PointContents(vec3_t p) +int SV_PointContents(const Vector3& p) { int cont; @@ -565,16 +565,15 @@ qboolean SV_RecursiveHullCheck(hull_t* hull, int num, float p1f, float p2f, - vec3_t p1, - vec3_t p2, + const Vector3& p1, + const Vector3& p2, trace_t* trace) { dclipnode_t* node; mplane_t* plane; float t1, t2; float frac; - int i; - vec3_t mid; + Vector3 mid; int side; float midf; @@ -608,8 +607,8 @@ qboolean SV_RecursiveHullCheck(hull_t* hull, t1 = p1[plane->type] - plane->dist; t2 = p2[plane->type] - plane->dist; } else { - t1 = DotProduct(plane->normal, p1) - plane->dist; - t2 = DotProduct(plane->normal, p2) - plane->dist; + t1 = plane->normal.dot(p1) - plane->dist; + t2 = plane->normal.dot(p2) - plane->dist; } #if 1 @@ -652,9 +651,7 @@ qboolean SV_RecursiveHullCheck(hull_t* hull, } midf = p1f + (p2f - p1f) * frac; - for (i = 0; i < 3; i++) { - mid[i] = p1[i] + frac * (p2[i] - p1[i]); - } + mid = p1 + (p2 - p1) * frac; side = (t1 < 0); @@ -687,10 +684,10 @@ qboolean SV_RecursiveHullCheck(hull_t* hull, // the other side of the node is solid, this is the impact point //================== if (!side) { - VectorCopy(plane->normal, trace->plane.normal); + trace->plane.normal = plane->normal; trace->plane.dist = plane->dist; } else { - VectorSubtract(vec3_origin, plane->normal, trace->plane.normal); + trace->plane.normal = -plane->normal; trace->plane.dist = -plane->dist; } @@ -698,20 +695,18 @@ qboolean SV_RecursiveHullCheck(hull_t* hull, frac -= 0.1f; if (frac < 0) { trace->fraction = midf; - VectorCopy(mid, trace->endpos); + trace->endpos = mid; Con_DPrintf("backup past 0\n"); return false; } midf = p1f + (p2f - p1f) * frac; - for (i = 0; i < 3; i++) { - mid[i] = p1[i] + frac * (p2[i] - p1[i]); - } + mid = p1 + (p2 - p1) * frac; } trace->fraction = midf; - VectorCopy(mid, trace->endpos); + trace->endpos = mid; return false; } @@ -725,27 +720,27 @@ eventually rotation) of the end points ================== */ trace_t SV_ClipMoveToEntity(edict_t* ent, - vec3_t start, - vec3_t mins, - vec3_t maxs, - vec3_t end) + const Vector3& start, + const Vector3& mins, + const Vector3& maxs, + const Vector3& end) { trace_t trace; - vec3_t offset; - vec3_t start_l, end_l; + Vector3 offset; + Vector3 start_l, end_l; hull_t* hull; // fill in a default trace memset(&trace, 0, sizeof(trace_t)); trace.fraction = 1; trace.allsolid = true; - VectorCopy(end, trace.endpos); + trace.endpos = end; // get the clipping hull hull = SV_HullForEntity(ent, mins, maxs, offset); - VectorSubtract(start, offset, start_l); - VectorSubtract(end, offset, end_l); + start_l = start - offset; + end_l = end - offset; // trace a line through the apropriate clipping hull @@ -755,7 +750,7 @@ trace_t SV_ClipMoveToEntity(edict_t* ent, // fix trace up by the offset if (trace.fraction != 1) { - VectorAdd(trace.endpos, offset, trace.endpos); + trace.endpos += offset; } // did we clip the move? @@ -801,11 +796,11 @@ void SV_ClipToLinks(areanode_t* node, moveclip_t* clip) continue; } - if (clip->boxmins[0] > touch->v.absmax[0] || clip->boxmins[1] > touch->v.absmax[1] || clip->boxmins[2] > touch->v.absmax[2] || clip->boxmaxs[0] < touch->v.absmin[0] || clip->boxmaxs[1] < touch->v.absmin[1] || clip->boxmaxs[2] < touch->v.absmin[2]) { + if (clip->boxmins.x > touch->v.absmax.x || clip->boxmins.y > touch->v.absmax.y || clip->boxmins.z > touch->v.absmax.z || clip->boxmaxs.x < touch->v.absmin.x || clip->boxmaxs.y < touch->v.absmin.y || clip->boxmaxs.z < touch->v.absmin.z) { continue; } - if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0]) { + if (clip->passedict && clip->passedict->v.size.x && !touch->v.size.x) { continue; // points never interact } @@ -864,12 +859,12 @@ void SV_ClipToLinks(areanode_t* node, moveclip_t* clip) SV_MoveBounds ================== */ -void SV_MoveBounds(vec3_t start, - vec3_t mins, - vec3_t maxs, - vec3_t end, - vec3_t boxmins, - vec3_t boxmaxs) +void SV_MoveBounds(const Vector3& start, + const Vector3& mins, + const Vector3& maxs, + const Vector3& end, + Vector3& boxmins, + Vector3& boxmaxs) { int i; @@ -889,17 +884,14 @@ void SV_MoveBounds(vec3_t start, SV_Move ================== */ -trace_t SV_Move(vec3_t start, - vec3_t mins, - vec3_t maxs, - vec3_t end, +trace_t SV_Move(const Vector3& start, + const Vector3& mins, + const Vector3& maxs, + const Vector3& end, int type, edict_t* passedict) { - moveclip_t clip; - int i; - - memset(&clip, 0, sizeof(moveclip_t)); + moveclip_t clip{}; // clip to world clip.trace = SV_ClipMoveToEntity(sv.edicts, start, mins, maxs, end); @@ -912,13 +904,11 @@ trace_t SV_Move(vec3_t start, clip.passedict = passedict; if (type == MOVE_MISSILE) { - for (i = 0; i < 3; i++) { - clip.mins2[i] = -15; - clip.maxs2[i] = 15; - } + clip.mins2 = Vector3(-15, -15, -15); + clip.maxs2 = Vector3(15, 15, 15); } else { - VectorCopy(mins, clip.mins2); - VectorCopy(maxs, clip.maxs2); + clip.mins2 = mins; + clip.maxs2 = maxs; } // create the bounding box of the entire move diff --git a/src/world.hpp b/src/world.hpp index 0031f0f..37f1a8e 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -2,7 +2,7 @@ #pragma once typedef struct { - vec3_t normal; + Vector3 normal; float dist; } plane_t; @@ -11,7 +11,7 @@ typedef struct { qboolean startsolid; // if true, the initial point was in a solid area qboolean inopen, inwater; float fraction; // time completed, 1.0 = didn't hit anything - vec3_t endpos; // final position + Vector3 endpos; // final position plane_t plane; // surface normal at impact edict_t* ent; // entity the surface is on } trace_t; @@ -36,17 +36,17 @@ void SV_LinkEdict(edict_t* ent, qboolean touch_triggers); // sets ent->v.absmin and ent->v.absmax // if touchtriggers, calls prog functions for the intersected triggers -int SV_PointContents(vec3_t p); +int SV_PointContents(const Vector3& p); // returns the CONTENTS_* value from the world at the given point. // does not check any entities at all // the non-true version remaps the water current contents to content_water edict_t* SV_TestEntityPosition(edict_t* ent); -trace_t SV_Move(vec3_t start, - vec3_t mins, - vec3_t maxs, - vec3_t end, +trace_t SV_Move(const Vector3& start, + const Vector3& mins, + const Vector3& maxs, + const Vector3& end, int type, edict_t* passedict); // mins and maxs are reletive @@ -60,6 +60,6 @@ trace_t SV_Move(vec3_t start, // shouldn't be considered solid objects // passedict is explicitly excluded from clipping checks (normally NULL) -qboolean SV_RecursiveHullCheck(hull_t* hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t* trace); +qboolean SV_RecursiveHullCheck(hull_t* hull, int num, float p1f, float p2f, const Vector3& p1, const Vector3& p2, trace_t* trace); } // namespace Server From ffa3aa6f9c71a0ba77c1ced90cb0ef723a9b6444 Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Sat, 11 Jul 2026 02:58:56 +0000 Subject: [PATCH 2/6] use windows.h only in _WIN32 compile --- src/vid_sdl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vid_sdl.cpp b/src/vid_sdl.cpp index c0091d9..577aaee 100644 --- a/src/vid_sdl.cpp +++ b/src/vid_sdl.cpp @@ -27,7 +27,10 @@ using namespace Wad; using namespace Cvar; using namespace Cmd; #include "d_local.hpp" + +#ifdef _WIN32 #include "winquake.hpp" +#endif cvar_t _windowed_mouse = {"_windowed_mouse", "1", {}, {}, {}, {}}; From 104978a51f32b184afc845f5eb6ace06deee7c76 Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Sat, 11 Jul 2026 14:20:47 +0000 Subject: [PATCH 3/6] sync with master --- CMakeLists.txt | 41 +++-------------------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 98bc966..c5339fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(CleanQuake LANGUAGES CXX) +project(Quake.cpp LANGUAGES CXX) if(NOT CMAKE_GENERATOR MATCHES "^Visual Studio") include(GNUInstallDirs) @@ -182,42 +182,7 @@ add_compile_definitions(SDL) include_directories(SDL2::SDL2) # clean-quake executable -add_executable(clean-quake ${CORE_SRCS}) -target_include_directories(clean-quake PRIVATE src) -target_link_libraries(clean-quake PRIVATE ${SDL2_LIBRARIES}) -add_executable(Quake.cpp ${CORE_SRCS}) - +add_executable(Quake.cpo ${CORE_SRCS}) target_include_directories(Quake.cpp PRIVATE src) +target_link_libraries(Quake.cpp PRIVATE ${SDL2_LIBRARIES}) -# Link SDL2 and Windows libraries -target_link_libraries(Quake.cpp PRIVATE SDL2main SDL2-static ws2_32 winmm) - -# Suppress some old C warnings for cleaner output -if(MSVC) - target_compile_options(Quake.cpp PRIVATE - /W4 - /Z7 - /w14702 # Force C4702 (Unreachable code) to be a Level 1 Warning - /Gy # Function-level linking (puts each function in its own section) - /Gw # Optimize global data (puts each variable in its own section) - ) - # Target-specific linker overrides - # NOTE: /INCREMENTAL:NO is required to allow /OPT:REF to function. - target_link_options(Quake.cpp PRIVATE - /INCREMENTAL:NO - /OPT:REF # Eliminate unreferenced functions and data - /VERBOSE:REF # Print out everything the linker throws away - ) -else() - target_compile_options(Quake.cpp PRIVATE - -Wall -Wextra - -Wunreachable-code # Warn about unreachable code paths - -Wno-write-strings - -ffunction-sections # Put each function in its own section - -fdata-sections # Put each variable in its own section - ) - target_link_options(Quake.cpp PRIVATE - -Wl,--gc-sections # Garbage collect empty sections - -Wl,--print-gc-sections # Print out everything the linker throws away - ) -endif() From 89f49042dcc61bd2755ffc819768d0cbdc20da83 Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Sat, 11 Jul 2026 14:25:15 +0000 Subject: [PATCH 4/6] use PROJECT_NAME for executable --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5339fd..36a3eb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,7 +182,7 @@ add_compile_definitions(SDL) include_directories(SDL2::SDL2) # clean-quake executable -add_executable(Quake.cpo ${CORE_SRCS}) -target_include_directories(Quake.cpp PRIVATE src) -target_link_libraries(Quake.cpp PRIVATE ${SDL2_LIBRARIES}) +add_executable(${PROJECT_NAME} ${CORE_SRCS}) +target_include_directories(${PROJECT_NAME} PRIVATE src) +target_link_libraries(${PROJECT_NAME} PRIVATE ${SDL2_LIBRARIES}) From f20c335583103b0c41e96d8aa3b6d91fc7c46e91 Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Sun, 12 Jul 2026 11:52:41 +0000 Subject: [PATCH 5/6] replace msvc only "*_s" functions --- src/audio.cpp | 1333 ++++++++++++++++++++++++++++------------------ src/audio.hpp | 123 ++--- src/client.cpp | 45 +- src/client.hpp | 137 ++--- src/cmd.cpp | 43 +- src/cmd.hpp | 4 +- src/common.cpp | 118 ++-- src/common.hpp | 10 +- src/console.cpp | 48 +- src/cvar.cpp | 12 +- src/draw.cpp | 102 ++-- src/draw.hpp | 6 +- src/host.cpp | 48 +- src/host_cmd.cpp | 68 +-- src/keys.cpp | 12 +- src/mathlib.cpp | 4 +- src/mathlib.hpp | 10 +- src/menu.cpp | 24 +- src/menu.hpp | 2 +- src/model.cpp | 8 +- src/model.hpp | 196 +++---- src/network.cpp | 8 +- src/quakedef.hpp | 13 +- src/renderer.cpp | 4 +- src/renderer.hpp | 70 +-- src/sbar.cpp | 62 +-- src/screen.cpp | 28 +- src/server.cpp | 54 +- src/server.hpp | 95 ++-- src/sys_sdl.cpp | 37 +- src/vid.hpp | 8 +- src/vid_sdl.cpp | 32 +- src/view.cpp | 31 +- src/vm.cpp | 78 +-- src/vm.hpp | 6 +- src/wad.cpp | 15 +- src/wad.hpp | 6 +- src/world.cpp | 70 ++- src/world.hpp | 24 +- src/zone.cpp | 86 ++- 40 files changed, 1641 insertions(+), 1439 deletions(-) diff --git a/src/audio.cpp b/src/audio.cpp index 259f238..94f4a97 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -1,7 +1,21 @@ // audio.cpp -- merged audio subsystem (snd_*.cpp) // Contains: sound control, caching, mixing, and SDL audio driver +#pragma warning(disable: 4324) +#include #include "quakedef.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace CDAudio; using namespace Client; @@ -30,57 +44,173 @@ using namespace Cmd; namespace Audio { -// ============================================================================ -// snd_dma.cpp -- main control for any streaming sound output device -// ============================================================================ +namespace { + +enum class AudioCommandType { + StartSound, + StaticSound, + StopSound, + StopAllSounds, + ListenerUpdate, + ClearBuffer +}; + +struct AudioCommand { + AudioCommandType type; + int entnum; + int entchannel; + sfx_t* sfx; + Vector3 origin; + float vol; + float attenuation; + bool clear; + Vector3 v_forward; + Vector3 v_right; + Vector3 v_up; + std::array ambient_vols; + float host_frametime; + float ambient_fade; + bool snd_ambient; + int random_offset; +}; + +template +class SPSCQueue { +public: + static_assert((Capacity & (Capacity - 1)) == 0, "Capacity must be a power of 2"); + static_assert(std::is_trivially_copyable_v, "Queue objects must be trivially copyable to ensure lock-free safety"); + + [[nodiscard]] bool Push(const T& value) { + size_t write_idx = write_idx_.load(std::memory_order_relaxed); + size_t read_idx = read_idx_.load(std::memory_order_acquire); + if (write_idx - read_idx >= Capacity) { + return false; // Queue full + } + buffer_[write_idx & (Capacity - 1)] = value; + write_idx_.store(write_idx + 1, std::memory_order_release); + return true; + } + + [[nodiscard]] bool Pop(T& value) { + size_t read_idx = read_idx_.load(std::memory_order_relaxed); + size_t write_idx = write_idx_.load(std::memory_order_acquire); + if (read_idx == write_idx) { + return false; // Queue empty + } + value = buffer_[read_idx & (Capacity - 1)]; + read_idx_.store(read_idx + 1, std::memory_order_release); + return true; + } + +private: + std::array buffer_; + alignas(64) std::atomic write_idx_{0}; + alignas(64) std::atomic read_idx_{0}; +}; + +SPSCQueue command_queue; +float local_volume = 0.7f; +dma_t the_shm; + +void S_StartSoundInternal(int entnum, int entchannel, sfx_t* sfx, const Vector3& origin, float fvol, float attenuation, int random_offset); +void S_StaticSoundInternal(sfx_t* sfx, const Vector3& origin, float vol, float attenuation); +void S_StopSoundInternal(int entnum, int entchannel); +void S_StopAllSoundsInternal(bool clear); +void S_ClearBufferInternal(void); +void S_UpdateInternal(const Vector3& origin, + const Vector3& forward, + const Vector3& right, + const Vector3& up, + float vol_val, + const std::array& ambient_vols, + float host_frametime_val, + float ambient_fade_val, + bool snd_ambient_val); +void ExecuteAudioCommand(const AudioCommand& cmd); + +template +[[nodiscard]] constexpr T byteswap(T val) noexcept { + static_assert(std::is_integral_v, "byteswap requires integral type"); + if constexpr (sizeof(T) == 2) { + return static_cast((static_cast(val) << 8) | (static_cast(val) >> 8)); + } else if constexpr (sizeof(T) == 4) { + unsigned int u = static_cast(val); + return static_cast( + ((u << 24) & 0xFF000000) | + ((u << 8) & 0x00FF0000) | + ((u >> 8) & 0x0000FF00) | + ((u >> 24) & 0x000000FF) + ); + } else { + return val; + } +} void S_Play(void); void S_PlayVol(void); void S_SoundList(void); void S_Update_(); -void S_StopAllSounds(qboolean clear); + +} // namespace + +void S_StopAllSounds(bool clear); // ======================================================================= // Internal sound data & structures // ======================================================================= -channel_t channels[MAX_CHANNELS]; -int total_channels; - -int snd_blocked = 0; -static qboolean snd_ambient = 1; -qboolean snd_initialized = false; +namespace { -// pointer should go away -volatile dma_t* shm = 0; -volatile dma_t sn; +std::array channels; +std::atomic total_channels{MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS}; +bool snd_ambient = true; Vector3 listener_origin; Vector3 listener_forward; Vector3 listener_right; Vector3 listener_up; -vec_t sound_nominal_clip_dist = 1000.0; int soundtime; // sample PAIRS int paintedtime; // sample PAIRS -#define MAX_SFX 512 -sfx_t* known_sfx; // hunk allocated [MAX_SFX] -int num_sfx; +bool fakedma = false; +dma_t* shm = nullptr; +bool snd_initialized = false; -sfx_t* ambient_sfx[NUM_AMBIENTS]; +} // namespace + +int snd_blocked = 0; +vec_t sound_nominal_clip_dist = 1000.0; + +namespace { + +constexpr int MAX_SFX = 512; +sfx_t* known_sfx = nullptr; // hunk allocated [MAX_SFX] +size_t num_sfx; + +std::array ambient_sfx; int desired_speed = 11025; int desired_bits = 16; -int sound_started = 0; +qboolean sound_started = false; + +} // namespace cvar_t bgmvolume = { "bgmvolume", "1", true, {}, {}, {} }; cvar_t volume = { "volume", "0.7", true, {}, {}, {} }; +namespace { + cvar_t nosound = { "nosound", "0", {}, {}, {}, {} }; cvar_t precache = { "precache", "1", {}, {}, {}, {} }; + +} // namespace + cvar_t loadas8bit = { "loadas8bit", "0", {}, {}, {}, {} }; + +namespace { + cvar_t bgmbuffer = { "bgmbuffer", "4096", {}, {}, {}, {} }; cvar_t ambient_level = { "ambient_level", "0.3", {}, {}, {}, {} }; cvar_t ambient_fade = { "ambient_fade", "100", {}, {}, {}, {} }; @@ -88,11 +218,15 @@ cvar_t snd_noextraupdate = { "snd_noextraupdate", "0", {}, {}, {}, {} }; cvar_t snd_show = { "snd_show", "0", {}, {}, {}, {} }; cvar_t _snd_mixahead = { "_snd_mixahead", "0.1", true, {}, {}, {} }; +} // namespace + // ==================================================================== // User-setable variables // ==================================================================== -qboolean fakedma = false; + + +namespace { void S_SoundInfo_f(void) { @@ -102,16 +236,18 @@ void S_SoundInfo_f(void) return; } - Con_Printf("%5d stereo\n", shm->channels - 1); - Con_Printf("%5d samples\n", shm->samples); - Con_Printf("%5d samplepos\n", shm->samplepos); - Con_Printf("%5d samplebits\n", shm->samplebits); - Con_Printf("%5d submission_chunk\n", shm->submission_chunk); - Con_Printf("%5d speed\n", shm->speed); - Con_Printf("0x%x dma buffer\n", shm->buffer); - Con_Printf("%5d total_channels\n", total_channels); + Con_Printf("%5d stereo\n", shm->channels.load() - 1); + Con_Printf("%5d samples\n", shm->samples.load()); + Con_Printf("%5d samplepos\n", shm->samplepos.load()); + Con_Printf("%5d samplebits\n", shm->samplebits.load()); + Con_Printf("%5d submission_chunk\n", shm->submission_chunk.load()); + Con_Printf("%5d speed\n", shm->speed.load()); + Con_Printf("0x%x dma buffer\n", shm->buffer.load()); + Con_Printf("%5d total_channels\n", total_channels.load(std::memory_order_relaxed)); } +} // namespace + /* ================ S_Startup @@ -120,7 +256,7 @@ S_Startup void S_Startup(void) { - int rc; + bool rc; if (!snd_initialized) { return; @@ -186,27 +322,27 @@ void S_Init(void) SND_InitScaletable(); - known_sfx = (sfx_t *) Hunk_Alloc(MAX_SFX * sizeof(sfx_t), "sfx_t"); + known_sfx = static_cast(Hunk_Alloc(MAX_SFX * sizeof(sfx_t), "sfx_t")); num_sfx = 0; // create a piece of DMA memory if (fakedma) { - shm = (volatile dma_t*)(void*)Hunk_Alloc(sizeof(*shm), "shm"); - shm->splitbuffer = 0; - shm->samplebits = 16; - shm->speed = 22050; - shm->channels = 2; - shm->samples = 32768; - shm->samplepos = 0; - shm->soundalive = true; - shm->gamealive = true; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) Hunk_Alloc(1 << 16, "shmbuf"); + shm = &the_shm; + shm->splitbuffer.store(0, std::memory_order_relaxed); + shm->samplebits.store(16, std::memory_order_relaxed); + shm->speed.store(22050, std::memory_order_relaxed); + shm->channels.store(2, std::memory_order_relaxed); + shm->samples.store(32768, std::memory_order_relaxed); + shm->samplepos.store(0, std::memory_order_relaxed); + shm->soundalive.store(true, std::memory_order_relaxed); + shm->gamealive.store(true, std::memory_order_relaxed); + shm->submission_chunk.store(1, std::memory_order_relaxed); + shm->buffer.store(static_cast(Hunk_Alloc(1 << 16, "shmbuf")), std::memory_order_release); } if (shm) { - Con_Printf("Sound sampling rate: %i\n", shm->speed); + Con_Printf("Sound sampling rate: %i\n", shm->speed.load()); } ambient_sfx[AMBIENT_WATER] = S_PrecacheSound("ambience/water1.wav"); @@ -226,10 +362,10 @@ void S_Shutdown(void) } if (shm) { - shm->gamealive = 0; + shm->gamealive.store(0, std::memory_order_release); } - shm = 0; + shm = nullptr; sound_started = 0; if (!fakedma) { @@ -247,23 +383,22 @@ S_FindName ================== */ -sfx_t* S_FindName(const char* name) -{ - int i; - sfx_t* sfx; +namespace { - if (!name) { +[[nodiscard]] sfx_t* S_FindName(std::string_view name) +{ + if (name.empty()) { Sys_Error("S_FindName: NULL\n"); } - if (Q_strlen(name) >= MAX_QPATH) { - Sys_Error("Sound name too long: %s", name); + if (name.length() >= MAX_QPATH) { + Sys_Error("Sound name too long: %.*s", static_cast(name.length()), name.data()); } // see if already loaded - for (i = 0; i < num_sfx; i++) { - if (!Q_strcmp(known_sfx[i].name, name)) { - return &known_sfx[i]; + for (auto& sfx : std::span(known_sfx, num_sfx)) { + if (sfx.name == name) { + return &sfx; } } @@ -271,29 +406,30 @@ sfx_t* S_FindName(const char* name) Sys_Error("S_FindName: out of sfx_t"); } - sfx = &known_sfx[i]; - strcpy_s(sfx->name, sizeof(sfx->name), name); + sfx_t* sfx = &known_sfx[num_sfx]; + name.copy(sfx->name, name.length()); + sfx->name[name.length()] = '\0'; num_sfx++; return sfx; } +} // namespace + /* ================== S_TouchSound ================== */ -void S_TouchSound(const char* name) +void S_TouchSound(std::string_view name) { - sfx_t* sfx; - if (!sound_started) { return; } - sfx = S_FindName(name); + sfx_t* sfx = S_FindName(name); Cache_Check(&sfx->cache); } @@ -303,19 +439,17 @@ S_PrecacheSound ================== */ -sfx_t* S_PrecacheSound(const char* name) +sfx_t* S_PrecacheSound(std::string_view name) { - sfx_t* sfx; - if (!sound_started || nosound.value) { - return NULL; + return nullptr; } - sfx = S_FindName(name); + sfx_t* sfx = S_FindName(name); // cache it in if (precache.value) { - S_LoadSound(sfx); + static_cast(S_LoadSound(sfx)); } return sfx; @@ -330,41 +464,36 @@ SND_PickChannel */ channel_t* SND_PickChannel(int entnum, int entchannel) { - int ch_idx; - int first_to_die; - int life_left; - // Check for replacement sound, or find the best one to replace - first_to_die = -1; - life_left = 0x7fffffff; - for (ch_idx = NUM_AMBIENTS; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS; - ch_idx++) { + channel_t* first_to_die = nullptr; + int life_left = std::numeric_limits::max(); + for (auto& chan : std::span(channels).subspan(NUM_AMBIENTS, MAX_DYNAMIC_CHANNELS)) { if (entchannel != 0 // channel 0 never overrides - && channels[ch_idx].entnum == entnum && (channels[ch_idx].entchannel == entchannel || entchannel == -1)) { // allways override sound from same entity - first_to_die = ch_idx; + && chan.entnum == entnum && (chan.entchannel == entchannel || entchannel == -1)) { // allways override sound from same entity + first_to_die = &chan; break; } // don't let monster sounds override player sounds - if (channels[ch_idx].entnum == cl.viewentity && entnum != cl.viewentity && channels[ch_idx].sfx) { + if (chan.entnum == cl.viewentity && entnum != cl.viewentity && chan.sfx) { continue; } - if (channels[ch_idx].end - paintedtime < life_left) { - life_left = channels[ch_idx].end - paintedtime; - first_to_die = ch_idx; + if (chan.end - paintedtime < life_left) { + life_left = chan.end - paintedtime; + first_to_die = &chan; } } - if (first_to_die == -1) { - return NULL; + if (!first_to_die) { + return nullptr; } - if (channels[first_to_die].sfx) { - channels[first_to_die].sfx = NULL; + if (first_to_die->sfx) { + first_to_die->sfx = nullptr; } - return &channels[first_to_die]; + return first_to_die; } /* @@ -395,7 +524,7 @@ void SND_Spatialize(channel_t* ch) dot = listener_right.dot(source_vec); - if (shm->channels == 1) { + if (shm->channels.load(std::memory_order_relaxed) == 1) { rscale = 1.0; lscale = 1.0; } else { @@ -405,13 +534,13 @@ void SND_Spatialize(channel_t* ch) // add in distance effect scale = static_cast((1.0 - dist) * rscale); - ch->rightvol = (int)(ch->master_vol * scale); + ch->rightvol = static_cast(ch->master_vol * scale); if (ch->rightvol < 0) { ch->rightvol = 0; } scale = static_cast((1.0 - dist) * lscale); - ch->leftvol = (int)(ch->master_vol * scale); + ch->leftvol = static_cast(ch->master_vol * scale); if (ch->leftvol < 0) { ch->leftvol = 0; } @@ -421,30 +550,21 @@ void SND_Spatialize(channel_t* ch) // Start a sound effect // ======================================================================= -void S_StartSound(int entnum, + + +namespace { + +void S_StartSoundInternal(int entnum, int entchannel, sfx_t* sfx, const Vector3& origin, float fvol, - float attenuation) + float attenuation, + int random_offset) { - channel_t *target_chan, *check; + channel_t *target_chan; sfxcache_t* sc; int vol; - int ch_idx; - int skip; - - if (!sound_started) { - return; - } - - if (!sfx) { - return; - } - - if (nosound.value) { - return; - } vol = static_cast(fvol * 255); @@ -467,12 +587,11 @@ void S_StartSound(int entnum, return; // not audible at all } - // new channel - sc = S_LoadSound(sfx); + // new channel (strictly check cache only, no I/O or heap allocation on audio thread) + sc = static_cast(Cache_Check(&sfx->cache)); if (!sc) { - target_chan->sfx = NULL; - - return; // couldn't load the sound's data + target_chan->sfx = nullptr; + return; } target_chan->sfx = sfx; @@ -481,18 +600,19 @@ void S_StartSound(int entnum, // if an identical sound has also been started this frame, offset the pos // a bit to keep it from just making the first one louder - check = &channels[NUM_AMBIENTS]; - for (ch_idx = NUM_AMBIENTS; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS; - ch_idx++, check++) { - if (check == target_chan) { + for (auto& check : std::span(channels).subspan(NUM_AMBIENTS, MAX_DYNAMIC_CHANNELS)) { + if (&check == target_chan) { continue; } - if (check->sfx == sfx && !check->pos) { - skip = rand() % (int)(0.1 * shm->speed); + if (check.sfx == sfx && !check.pos) { + int skip = random_offset; if (skip >= target_chan->end) { skip = target_chan->end - 1; } + if (skip < 0) { + skip = 0; + } target_chan->pos += skip; target_chan->end -= skip; @@ -501,93 +621,59 @@ void S_StartSound(int entnum, } } -void S_StopSound(int entnum, int entchannel) +void S_StopSoundInternal(int entnum, int entchannel) { - int i; - - for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++) { - if (channels[i].entnum == entnum && channels[i].entchannel == entchannel) { - channels[i].end = 0; - channels[i].sfx = NULL; + for (auto& chan : std::span(channels).first(MAX_DYNAMIC_CHANNELS)) { + if (chan.entnum == entnum && chan.entchannel == entchannel) { + chan.end = 0; + chan.sfx = nullptr; return; } } } -void S_StopAllSounds(qboolean clear) +void S_StopAllSoundsInternal(bool clear) { - int i; - - if (!sound_started) { - return; - } - total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics - for (i = 0; i < MAX_CHANNELS; i++) { - if (channels[i].sfx) { - channels[i].sfx = NULL; + for (auto& chan : channels) { + if (chan.sfx) { + chan.sfx = nullptr; } } - Q_memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); + channels.fill({}); if (clear) { - S_ClearBuffer(); + S_ClearBufferInternal(); } } - - -void S_ClearBuffer(void) +void S_ClearBufferInternal(void) { -#if 0 - int clear; - - if (shm->samplebits == 8) { - clear = 0x80; - } else { - clear = 0; - } - - { - Q_memset(shm->buffer, clear, shm->samples * shm->samplebits / 8); - } -#endif } -/* -================= -S_StaticSound -================= -*/ -void S_StaticSound(sfx_t* sfx, const Vector3& origin, float vol, float attenuation) +void S_StaticSoundInternal(sfx_t* sfx, const Vector3& origin, float vol, float attenuation) { channel_t* ss; sfxcache_t* sc; - if (!sfx) { - return; - } - if (total_channels == MAX_CHANNELS) { - Con_Printf("total_channels == MAX_CHANNELS\n"); - return; } ss = &channels[total_channels]; total_channels++; - sc = S_LoadSound(sfx); + // strictly check cache only + sc = static_cast(Cache_Check(&sfx->cache)); if (!sc) { + total_channels--; // Revert increment since sound could not be loaded/found in cache return; } if (sc->loopstart == -1) { - Con_Printf("Sound %s not looped\n", sfx->name); - return; } @@ -600,102 +686,212 @@ void S_StaticSound(sfx_t* sfx, const Vector3& origin, float vol, float attenuati SND_Spatialize(ss); } -//============================================================================= - -/* -=================== -S_UpdateAmbientSounds -=================== -*/ -void S_UpdateAmbientSounds(void) +void ExecuteAudioCommand(const AudioCommand& cmd) { - mleaf_t* l; - float vol; - int ambient_channel; - channel_t* chan; + switch (cmd.type) { + case AudioCommandType::StartSound: + S_StartSoundInternal(cmd.entnum, cmd.entchannel, cmd.sfx, cmd.origin, cmd.vol, cmd.attenuation, cmd.random_offset); + break; + case AudioCommandType::StaticSound: + S_StaticSoundInternal(cmd.sfx, cmd.origin, cmd.vol, cmd.attenuation); + break; + case AudioCommandType::StopSound: + S_StopSoundInternal(cmd.entnum, cmd.entchannel); + break; + case AudioCommandType::StopAllSounds: + S_StopAllSoundsInternal(cmd.clear); + break; + case AudioCommandType::ListenerUpdate: + S_UpdateInternal(cmd.origin, cmd.v_forward, cmd.v_right, cmd.v_up, cmd.vol, cmd.ambient_vols, cmd.host_frametime, cmd.ambient_fade, cmd.snd_ambient); + break; + case AudioCommandType::ClearBuffer: + S_ClearBufferInternal(); + break; + } +} - if (!snd_ambient) { +} // namespace + +void S_StartSound(int entnum, + int entchannel, + sfx_t* sfx, + const Vector3& origin, + float fvol, + float attenuation) +{ + if (!sound_started || !sfx || nosound.value) { return; } - // calc ambient sound levels - if (!cl.worldmodel) { + // strictly check cache only during active gameplay; drop sound if not precached + if (!Cache_Check(&sfx->cache)) { return; } - l = Mod_PointInLeaf(listener_origin, cl.worldmodel); - if (!l || !ambient_level.value) { - for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS; - ambient_channel++) { - channels[ambient_channel].sfx = NULL; + AudioCommand cmd{}; + cmd.type = AudioCommandType::StartSound; + cmd.entnum = entnum; + cmd.entchannel = entchannel; + cmd.sfx = sfx; + cmd.origin = origin; + cmd.vol = fvol; + cmd.attenuation = attenuation; + + // Calculate random offset on main thread (thread-safe, no system calls on audio thread) + int random_offset = 0; + if (shm) { + int max_skip = static_cast(0.1 * shm->speed.load(std::memory_order_relaxed)); + if (max_skip > 0) { + thread_local std::mt19937 generator(std::random_device{}()); + std::uniform_int_distribution distribution(0, max_skip - 1); + random_offset = distribution(generator); } + } + cmd.random_offset = random_offset; + + if (!command_queue.Push(cmd)) { + Con_Printf("WARNING: Audio command queue overflow!\n"); + } +} + +void S_StaticSound(sfx_t* sfx, const Vector3& origin, float vol, float attenuation) +{ + if (!sound_started || !sfx) { + return; + } + // strictly check cache only during active gameplay; drop sound if not precached + if (!Cache_Check(&sfx->cache)) { return; } - for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++) { - chan = &channels[ambient_channel]; - chan->sfx = ambient_sfx[ambient_channel]; + AudioCommand cmd{}; + cmd.type = AudioCommandType::StaticSound; + cmd.sfx = sfx; + cmd.origin = origin; + cmd.vol = vol; + cmd.attenuation = attenuation; - vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; - if (vol < 8) { - vol = 0; - } + if (!command_queue.Push(cmd)) { + Con_Printf("WARNING: Audio command queue overflow!\n"); + } +} - // don't adjust volume too fast - if (chan->master_vol < vol) { - chan->master_vol = static_cast(chan->master_vol + host_frametime * ambient_fade.value); - if (chan->master_vol > vol) { - chan->master_vol = static_cast(vol); - } - } else if (chan->master_vol > vol) { - chan->master_vol = static_cast(chan->master_vol - host_frametime * ambient_fade.value); - if (chan->master_vol < vol) { - chan->master_vol = static_cast(vol); - } - } +void S_StopSound(int entnum, int entchannel) +{ + if (!sound_started) { + return; + } - chan->leftvol = chan->rightvol = chan->master_vol; + AudioCommand cmd{}; + cmd.type = AudioCommandType::StopSound; + cmd.entnum = entnum; + cmd.entchannel = entchannel; + + if (!command_queue.Push(cmd)) { + Con_Printf("WARNING: Audio command queue overflow!\n"); } } -/* -============ -S_Update +void S_StopAllSounds(bool clear) +{ + if (!sound_started) { + return; + } -Called once each time through the main loop -============ + AudioCommand cmd{}; + cmd.type = AudioCommandType::StopAllSounds; + cmd.clear = clear; + + if (!command_queue.Push(cmd)) { + Con_Printf("WARNING: Audio command queue overflow!\n"); + } +} + +void S_ClearBuffer(void) +{ + if (!sound_started) { + return; + } + + AudioCommand cmd{}; + cmd.type = AudioCommandType::ClearBuffer; + + if (!command_queue.Push(cmd)) { + Con_Printf("WARNING: Audio command queue overflow!\n"); + } +} + +//============================================================================= + +/* +=================== +S_UpdateAmbientSounds +=================== */ -void S_Update(const Vector3& origin, const Vector3& forward, const Vector3& right, const Vector3& up) +namespace { + +void S_UpdateInternal(const Vector3& origin, + const Vector3& forward, + const Vector3& right, + const Vector3& up, + float vol_val, + const std::array& ambient_vols, + float host_frametime_val, + float ambient_fade_val, + bool snd_ambient_val) { - int i, j; int total; - channel_t* ch; channel_t* combine; - if (!sound_started || (snd_blocked > 0)) { - return; - } - listener_origin = origin; listener_forward = forward; listener_right = right; listener_up = up; + local_volume = vol_val; + + // update general area ambient sound sources (thread-safe volume interpolation on the audio thread) + if (!snd_ambient_val) { + for (auto& ambient_chan : std::span(channels).first(NUM_AMBIENTS)) { + ambient_chan.sfx = nullptr; + } + } else { + for (int ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++) { + channel_t* chan = &channels[ambient_channel]; + chan->sfx = ambient_sfx[ambient_channel]; + + int target_vol = ambient_vols[ambient_channel]; + + // don't adjust volume too fast + if (chan->master_vol < target_vol) { + chan->master_vol = static_cast(chan->master_vol + host_frametime_val * ambient_fade_val); + if (chan->master_vol > target_vol) { + chan->master_vol = target_vol; + } + } else if (chan->master_vol > target_vol) { + chan->master_vol = static_cast(chan->master_vol - host_frametime_val * ambient_fade_val); + if (chan->master_vol < target_vol) { + chan->master_vol = target_vol; + } + } - // update general area ambient sound sources - S_UpdateAmbientSounds(); + chan->leftvol = chan->rightvol = chan->master_vol; + } + } - combine = NULL; + combine = nullptr; // update spatialization for static and dynamic sounds - ch = channels + NUM_AMBIENTS; - for (i = NUM_AMBIENTS; i < total_channels; i++, ch++) { - if (!ch->sfx) { + int i = NUM_AMBIENTS; + for (auto& ch : std::span(channels).subspan(NUM_AMBIENTS, total_channels - NUM_AMBIENTS)) { + if (!ch.sfx) { + i++; continue; } - SND_Spatialize(ch); // respatialize channel - if (!ch->leftvol && !ch->rightvol) { + SND_Spatialize(&ch); // respatialize channel + if (!ch.leftvol && !ch.rightvol) { + i++; continue; } @@ -704,53 +900,97 @@ void S_Update(const Vector3& origin, const Vector3& forward, const Vector3& righ if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) { // see if it can just use the last one - if (combine && combine->sfx == ch->sfx) { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; + if (combine && combine->sfx == ch.sfx) { + combine->leftvol += ch.leftvol; + combine->rightvol += ch.rightvol; + ch.leftvol = ch.rightvol = 0; + i++; continue; } // search for one - combine = channels + MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; + combine = &channels[MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS]; + int j; for (j = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; j < i; j++, combine++) { - if (combine->sfx == ch->sfx) { + if (combine->sfx == ch.sfx) { break; } } if (j == total_channels) { - combine = NULL; + combine = nullptr; } else { - if (combine != ch) { - combine->leftvol += ch->leftvol; - combine->rightvol += ch->rightvol; - ch->leftvol = ch->rightvol = 0; + if (combine != &ch) { + combine->leftvol += ch.leftvol; + combine->rightvol += ch.rightvol; + ch.leftvol = ch.rightvol = 0; } + i++; continue; } } + i++; } - // - // debugging output - // - if (snd_show.value) { + // debugging output (only printed if fakedma is active to preserve real-time safety of background audio thread) + if (fakedma && snd_show.value) { total = 0; - ch = channels; - for (i = 0; i < total_channels; i++, ch++) { - if (ch->sfx && (ch->leftvol || ch->rightvol)) { - //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name); + for (auto& ch : std::span(channels).first(total_channels)) { + if (ch.sfx && (ch.leftvol || ch.rightvol)) { total++; } } Con_Printf("----(%i)----\n", total); } +} - // mix some sound - S_Update_(); +} // namespace + +void S_Update(const Vector3& origin, const Vector3& forward, const Vector3& right, const Vector3& up) +{ + if (!sound_started || (snd_blocked > 0)) { + return; + } + + AudioCommand cmd{}; + cmd.type = AudioCommandType::ListenerUpdate; + cmd.origin = origin; + cmd.v_forward = forward; + cmd.v_right = right; + cmd.v_up = up; + cmd.vol = volume.value; + + // Calculate ambient sound levels on the main thread (thread-safe worldmodel leaf traversal) + cmd.snd_ambient = snd_ambient; + cmd.ambient_fade = ambient_fade.value; + cmd.host_frametime = static_cast(host_frametime); + cmd.ambient_vols.fill(0); + + if (snd_ambient && cl.worldmodel && ambient_level.value) { + mleaf_t* l = Mod_PointInLeaf(origin, cl.worldmodel); + if (l) { + for (int ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++) { + float vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; + if (vol < 8) { + vol = 0; + } + cmd.ambient_vols[ambient_channel] = static_cast(vol); + } + } + } + + if (!command_queue.Push(cmd)) { + Con_Printf("WARNING: Audio command queue overflow!\n"); + } + + if (fakedma) { + AudioCommand c{}; + while (command_queue.Pop(c)) { + ExecuteAudioCommand(c); + } + } } void S_ExtraUpdate(void) @@ -763,6 +1003,8 @@ void S_ExtraUpdate(void) S_Update_(); } +namespace { + void S_Update_(void) { } @@ -777,60 +1019,64 @@ console functions void S_Play(void) { - static int hash = 345; - int i; - char name[256]; + thread_local std::mt19937 rng(std::random_device{}()); + std::uniform_int_distribution dist(0, 1000); + int hash = dist(rng); sfx_t* sfx; - i = 1; + int i = 1; while (i < Cmd::Argc()) { - if (Cmd::Argv(i).find('.') == std::string_view::npos) { - Q_strcpy(name, Cmd::Argv(i)); - Q_strcat(name, ".wav"); + std::string name; + auto arg = Cmd::Argv(i); + if (arg.find('.') == std::string_view::npos) { + name = std::string(arg) + ".wav"; } else { - Q_strcpy(name, Cmd::Argv(i)); + name = std::string(arg); } sfx = S_PrecacheSound(name); - S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0); + Vector3 play_origin = cl_entities[cl.viewentity].origin; + S_StartSound(hash++, 0, sfx, play_origin, 1.0, 1.0); i++; } } void S_PlayVol(void) { - static int hash = 543; - int i; + thread_local std::mt19937 rng(std::random_device{}()); + std::uniform_int_distribution dist(0, 1000); + int hash = dist(rng); float vol; - char name[256]; sfx_t* sfx; - i = 1; + int i = 1; while (i < Cmd::Argc()) { - if (Cmd::Argv(i).find('.') == std::string_view::npos) { - Q_strcpy(name, Cmd::Argv(i)); - Q_strcat(name, ".wav"); + std::string name; + auto arg = Cmd::Argv(i); + if (arg.find('.') == std::string_view::npos) { + name = std::string(arg) + ".wav"; } else { - Q_strcpy(name, Cmd::Argv(i)); + name = std::string(arg); } sfx = S_PrecacheSound(name); - vol = Q_atof(Cmd::Argv(i + 1)); - S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0); + auto arg_vol = Cmd::Argv(i + 1); + vol = 1.0f; + std::from_chars(arg_vol.data(), arg_vol.data() + arg_vol.size(), vol); + Vector3 play_origin = cl_entities[cl.viewentity].origin; + S_StartSound(hash++, 0, sfx, play_origin, vol, 1.0); i += 2; } } void S_SoundList(void) { - int i; - sfx_t* sfx; sfxcache_t* sc; int size, total; total = 0; - for (sfx = known_sfx, i = 0; i < num_sfx; i++, sfx++) { - sc = (sfxcache_t *) Cache_Check(&sfx->cache); + for (auto& sfx : std::span(known_sfx, num_sfx)) { + sc = static_cast(Cache_Check(&sfx.cache)); if (!sc) { continue; } @@ -843,31 +1089,27 @@ void S_SoundList(void) Con_Printf(" "); } - Con_Printf("(%2db) %6i : %s\n", sc->width * 8, size, sfx->name); + Con_Printf("%s\n", sfx.name); } - Con_Printf("Total resident: %i\n", total); + Con_Printf("Total sound memory: %i\n", total); } -void S_LocalSound(const char* sound) -{ - sfx_t* sfx; +} // namespace - if (nosound.value) { +void S_LocalSound(std::string_view sound) +{ + if (nosound.value || !sound_started) { return; } - if (!sound_started) { + sfx_t* sfx = S_FindName(sound); + if (!sfx || !Cache_Check(&sfx->cache)) { + Con_Printf("WARNING: S_LocalSound attempted to play non-precached sound: %.*s\n", + static_cast(sound.length()), sound.data()); return; } - sfx = S_PrecacheSound(sound); - if (!sfx) { - Con_Printf("S_LocalSound: can't cache %s\n", sound); - - return; - } - - S_StartSound(cl.viewentity, -1, sfx, vec3_origin, 1, 1); + S_StartSound(cl.viewentity, -1, sfx, vec3_origin, 1.0f, 1.0f); } void S_BeginPrecaching(void) @@ -891,21 +1133,22 @@ byte* S_Alloc(int size); ResampleSfx ================ */ +namespace { + void ResampleSfx(sfx_t* sfx, int inrate, int inwidth, byte* data) { int outcount; int srcsample; float stepscale; - int i; int sample, samplefrac, fracstep; sfxcache_t* sc; - sc = (sfxcache_t *) Cache_Check(&sfx->cache); + sc = static_cast(Cache_Check(&sfx->cache)); if (!sc) { return; } - stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 + stepscale = static_cast(inrate) / shm->speed.load(); // this is usually 0.5, 1, or 2 outcount = static_cast(sc->length / stepscale); sc->length = outcount; @@ -913,7 +1156,7 @@ void ResampleSfx(sfx_t* sfx, int inrate, int inwidth, byte* data) sc->loopstart = static_cast(sc->loopstart / stepscale); } - sc->speed = shm->speed; + sc->speed = shm->speed.load(); if (loadas8bit.value) { sc->width = 1; } else { @@ -926,31 +1169,39 @@ void ResampleSfx(sfx_t* sfx, int inrate, int inwidth, byte* data) if (stepscale == 1 && inwidth == 1 && sc->width == 1) { // fast special case - for (i = 0; i < outcount; i++) { - ((signed char*)sc->data)[i] = (int)((unsigned char)(data[i]) - 128); + for (int i = 0; i < outcount; i++) { + reinterpret_cast(sc->data)[i] = static_cast(data[i] - 128); } } else { // general case samplefrac = 0; fracstep = static_cast(stepscale * 256); - for (i = 0; i < outcount; i++) { + for (int i = 0; i < outcount; i++) { srcsample = samplefrac >> 8; samplefrac += fracstep; if (inwidth == 2) { - sample = LittleShort(((short*)data)[srcsample]); + short val; + std::memcpy(&val, &data[srcsample * 2], sizeof(short)); + if constexpr (std::endian::native == std::endian::big) { + val = byteswap(val); + } + sample = val; } else { - sample = (int)((unsigned char)(data[srcsample]) - 128) << 8; + sample = static_cast(data[srcsample] - 128) << 8; } if (sc->width == 2) { - ((short*)sc->data)[i] = static_cast(sample); + short s = static_cast(sample); + std::memcpy(&sc->data[i * sizeof(short)], &s, sizeof(short)); } else { - ((signed char*)sc->data)[i] = static_cast(sample >> 8); + reinterpret_cast(sc->data)[i] = static_cast(sample >> 8); } } } } +} // namespace + //============================================================================= /* @@ -960,50 +1211,47 @@ S_LoadSound */ sfxcache_t* S_LoadSound(sfx_t* s) { - char namebuffer[256]; byte* data; wavinfo_t info; int len; float stepscale; sfxcache_t* sc; - byte stackbuf[1 * 1024]; // avoid dirtying the cache heap + std::array stackbuf; // avoid dirtying the cache heap // see if still in memory - sc = (sfxcache_t *) Cache_Check(&s->cache); + sc = static_cast(Cache_Check(&s->cache)); if (sc) { return sc; } - //Con_Printf ("S_LoadSound: %x\n", (int)stackbuf); - // load it in - Q_strcpy(namebuffer, "sound/"); - Q_strcat(namebuffer, s->name); - - // Con_Printf ("loading %s\n",namebuffer); + // load it in using stack allocation for path construction (no heap alloc) + std::array namebuffer; + std::snprintf(namebuffer.data(), namebuffer.size(), "sound/%s", s->name); - data = COM_LoadStackFile(namebuffer, stackbuf, sizeof(stackbuf)); + data = COM_LoadStackFile(namebuffer.data(), stackbuf.data(), sizeof(stackbuf)); if (!data) { - Con_Printf("Couldn't load %s\n", namebuffer); + Con_Printf("Couldn't load %s\n", namebuffer.data()); - return NULL; + return nullptr; } - info = GetWavinfo(s->name, data, com_filesize); + // Call GetWavinfo using a std::span for strict bounds checking + info = GetWavinfo(s->name, std::span(data, com_filesize)); if (info.channels != 1) { Con_Printf("%s is a stereo sample\n", s->name); - return NULL; + return nullptr; } - stepscale = (float)info.rate / shm->speed; + stepscale = static_cast(info.rate) / shm->speed.load(std::memory_order_relaxed); len = static_cast(info.samples / stepscale); len = len * info.width * info.channels; - sc = (sfxcache_t *) Cache_Alloc(&s->cache, len + sizeof(sfxcache_t), s->name); + sc = static_cast(Cache_Alloc(&s->cache, len + sizeof(sfxcache_t), s->name)); if (!sc) { - return NULL; + return nullptr; } sc->length = info.samples; @@ -1025,139 +1273,170 @@ WAV loading =============================================================================== */ -byte* data_p; -byte* iff_end; -byte* last_chunk; -byte* iff_data; -int iff_chunk_len; +namespace { -short GetLittleShort(void) -{ - short val = 0; - val = *data_p; - val = val + (*(data_p + 1) << 8); - data_p += 2; - - return val; -} +class WavParser { +public: + explicit WavParser(std::span wav_data) + : file_data_(wav_data), iff_data_offset_(0), last_chunk_offset_(0), current_chunk_offset_(wav_data.size()), iff_chunk_len_(0) {} -int GetLittleLong(void) -{ - int val = 0; - val = *data_p; - val = val + (*(data_p + 1) << 8); - val = val + (*(data_p + 2) << 16); - val = val + (*(data_p + 3) << 24); - data_p += 4; - - return val; -} + [[nodiscard]] bool FindNextChunk(std::string_view name) { + while (true) { + size_t offset = last_chunk_offset_; + if (offset + 8 > file_data_.size()) { + current_chunk_offset_ = file_data_.size(); + return false; + } -void FindNextChunk(const char* name) -{ - while (1) { - data_p = last_chunk; + int len = static_cast(file_data_[offset + 4] | + (file_data_[offset + 5] << 8) | + (file_data_[offset + 6] << 16) | + (file_data_[offset + 7] << 24)); + if (len < 0) { + current_chunk_offset_ = file_data_.size(); + return false; + } - if (data_p >= iff_end) { // didn't find the chunk - data_p = NULL; + iff_chunk_len_ = static_cast(len); + current_chunk_offset_ = offset; + last_chunk_offset_ = offset + 8 + ((iff_chunk_len_ + 1) & ~1); - return; + if (std::string_view(reinterpret_cast(&file_data_[offset]), 4) == name) { + return true; + } } + } - data_p += 4; - iff_chunk_len = GetLittleLong(); - if (iff_chunk_len < 0) { - data_p = NULL; + void FindChunk(std::string_view name) { + last_chunk_offset_ = iff_data_offset_; + static_cast(FindNextChunk(name)); + } - return; + [[nodiscard]] short ReadShort(size_t& offset) const { + if (offset + 2 > file_data_.size()) { + return 0; } + short val = static_cast(file_data_[offset] | (file_data_[offset + 1] << 8)); + offset += 2; + return val; + } - // if (iff_chunk_len > 1024*1024) - // Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); - data_p -= 8; - last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1); - if (!Q_strncmp((char*)data_p, name, 4)) { - return; + [[nodiscard]] int ReadLong(size_t& offset) const { + if (offset + 4 > file_data_.size()) { + return 0; } + int val = static_cast(file_data_[offset] | + (file_data_[offset + 1] << 8) | + (file_data_[offset + 2] << 16) | + (file_data_[offset + 3] << 24)); + offset += 4; + return val; } -} -void FindChunk(const char* name) -{ - last_chunk = iff_data; - FindNextChunk(name); -} + [[nodiscard]] bool HasFoundChunk() const { + return current_chunk_offset_ < file_data_.size(); + } + + [[nodiscard]] size_t GetCurrentChunkPayloadOffset() const { + return current_chunk_offset_ + 8; + } + + [[nodiscard]] size_t GetCurrentChunkLength() const { + return iff_chunk_len_; + } + + void SetIffDataOffset(size_t offset) { + iff_data_offset_ = offset; + } + +private: + std::span file_data_; + size_t iff_data_offset_; + size_t last_chunk_offset_; + size_t current_chunk_offset_; + size_t iff_chunk_len_; +}; + +} // namespace /* ============ GetWavinfo ============ */ -wavinfo_t GetWavinfo(char* name, byte* wav, int wavlength) +wavinfo_t GetWavinfo(std::string_view name, std::span wav_data) { - wavinfo_t info; - int i; - int format; - int samples; - - memset(&info, 0, sizeof(info)); + wavinfo_t info{}; - if (!wav) { + if (wav_data.empty()) { return info; } - iff_data = wav; - iff_end = wav + wavlength; + WavParser parser(wav_data); // find "RIFF" chunk - FindChunk("RIFF"); - if (!(data_p && !Q_strncmp((char*)data_p + 8, "WAVE", 4))) { - Con_Printf("Missing RIFF/WAVE chunks\n"); + parser.FindChunk("RIFF"); + if (!parser.HasFoundChunk()) { + Con_Printf("Missing RIFF chunk\n"); return info; } - // get "fmt " chunk - iff_data = data_p + 12; - // DumpChunks (); + size_t riff_payload_offset = parser.GetCurrentChunkPayloadOffset(); + if (riff_payload_offset + 4 > wav_data.size()) { + Con_Printf("Malformed RIFF chunk\n"); - FindChunk("fmt "); - if (!data_p) { + return info; + } + + if (std::string_view(reinterpret_cast(&wav_data[riff_payload_offset]), 4) != "WAVE") { + Con_Printf("Missing WAVE format inside RIFF\n"); + + return info; + } + + // fmt chunk searches inside the RIFF chunk. RIFF subchunks start at payload + 4 (after "WAVE") + parser.SetIffDataOffset(riff_payload_offset + 4); + + parser.FindChunk("fmt "); + if (!parser.HasFoundChunk()) { Con_Printf("Missing fmt chunk\n"); return info; } - data_p += 8; - format = GetLittleShort(); + size_t fmt_offset = parser.GetCurrentChunkPayloadOffset(); + int format = parser.ReadShort(fmt_offset); if (format != 1) { Con_Printf("Microsoft PCM format only\n"); return info; } - info.channels = GetLittleShort(); - info.rate = GetLittleLong(); - data_p += 4 + 2; - info.width = GetLittleShort() / 8; + info.channels = parser.ReadShort(fmt_offset); + info.rate = parser.ReadLong(fmt_offset); + + // Skip 4 + 2 bytes: dwAvgBytesPerSec (4) and wBlockAlign (2) + fmt_offset += 4 + 2; + + info.width = parser.ReadShort(fmt_offset) / 8; // get cue chunk - FindChunk("cue "); - if (data_p) { - data_p += 32; - info.loopstart = GetLittleLong(); - // Con_Printf("loopstart=%d\n", sfx->loopstart); + parser.FindChunk("cue "); + if (parser.HasFoundChunk()) { + size_t cue_offset = parser.GetCurrentChunkPayloadOffset(); + cue_offset += 32; // Skip to loopstart + info.loopstart = parser.ReadLong(cue_offset); // if the next chunk is a LIST chunk, look for a cue length marker - FindNextChunk("LIST"); - if (data_p) { - if (!strncmp( - (char*)data_p + 28, "mark", - 4)) { // this is not a proper parse, but it works with cooledit... - data_p += 24; - i = GetLittleLong(); // samples in loop - info.samples = info.loopstart + i; - // Con_Printf("looped length: %i\n", i); + if (parser.FindNextChunk("LIST")) { + size_t list_offset = parser.GetCurrentChunkPayloadOffset(); + if (list_offset + 32 <= wav_data.size()) { + if (std::string_view(reinterpret_cast(&wav_data[list_offset + 28]), 4) == "mark") { + list_offset += 24; + int i = parser.ReadLong(list_offset); // samples in loop + info.samples = info.loopstart + i; + } } } } else { @@ -1165,25 +1444,25 @@ wavinfo_t GetWavinfo(char* name, byte* wav, int wavlength) } // find data chunk - FindChunk("data"); - if (!data_p) { + parser.FindChunk("data"); + if (!parser.HasFoundChunk()) { Con_Printf("Missing data chunk\n"); return info; } - data_p += 4; - samples = GetLittleLong() / info.width; + size_t data_offset = parser.GetCurrentChunkPayloadOffset(); + int samples = static_cast(parser.GetCurrentChunkLength()) / info.width; if (info.samples) { if (samples < info.samples) { - Sys_Error("Sound %s has a bad loop length", name); + Sys_Error("Sound %.*s has a bad loop length", static_cast(name.length()), name.data()); } } else { info.samples = samples; } - info.dataofs = static_cast(data_p - wav); + info.dataofs = static_cast(data_offset); return info; } @@ -1192,36 +1471,33 @@ wavinfo_t GetWavinfo(char* name, byte* wav, int wavlength) // snd_mix.cpp -- portable code to mix sounds // ============================================================================ -#include +#include -#define PAINTBUFFER_SIZE 512 -portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; -int snd_scaletable[32][256]; -int *snd_p, snd_linear_count, snd_vol; -short* snd_out; +namespace { -void Snd_WriteLinearBlastStereo16(void); +constexpr int PAINTBUFFER_SIZE = 512; +std::array paintbuffer; +std::array, 32> snd_scaletable; -void Snd_WriteLinearBlastStereo16(void) +void Snd_WriteLinearBlastStereo16(const int* snd_p, short* snd_out, int snd_linear_count, int snd_vol) { - int i; int val; - for (i = 0; i < snd_linear_count; i += 2) { + for (int i = 0; i < snd_linear_count; i += 2) { val = (snd_p[i] * snd_vol) >> 8; - if (val > 0x7fff) { - snd_out[i] = 0x7fff; - } else if (val < -32768) { - snd_out[i] = -32768; + if (val > std::numeric_limits::max()) { + snd_out[i] = std::numeric_limits::max(); + } else if (val < std::numeric_limits::min()) { + snd_out[i] = std::numeric_limits::min(); } else { snd_out[i] = static_cast(val); } val = (snd_p[i + 1] * snd_vol) >> 8; - if (val > 0x7fff) { - snd_out[i + 1] = 0x7fff; - } else if (val < -32768) { - snd_out[i + 1] = -32768; + if (val > std::numeric_limits::max()) { + snd_out[i + 1] = std::numeric_limits::max(); + } else if (val < std::numeric_limits::min()) { + snd_out[i + 1] = std::numeric_limits::min(); } else { snd_out[i + 1] = static_cast(val); } @@ -1230,26 +1506,17 @@ void Snd_WriteLinearBlastStereo16(void) void S_TransferStereo16(int endtime) { - int lpos; - int lpaintedtime; - unsigned char* pbuf; - - snd_vol = static_cast(volume.value * 256); + int lpaintedtime = paintedtime; - snd_p = (int*)paintbuffer; - lpaintedtime = paintedtime; - - { - pbuf = (unsigned char*)shm->buffer; - } + auto snd_p = reinterpret_cast(paintbuffer.data()); + int snd_vol = static_cast(local_volume * 256); while (lpaintedtime < endtime) { - // handle recirculating buffer issues - lpos = lpaintedtime & ((shm->samples >> 1) - 1); + int lpos = lpaintedtime & ((shm->samples.load() >> 1) - 1); - snd_out = (short*)pbuf + (lpos << 1); + auto snd_out = reinterpret_cast(shm->buffer.load()) + (lpos << 1); - snd_linear_count = (shm->samples >> 1) - lpos; + int snd_linear_count = (shm->samples.load() >> 1) - lpos; if (lpaintedtime + snd_linear_count > endtime) { snd_linear_count = endtime - lpaintedtime; } @@ -1257,12 +1524,11 @@ void S_TransferStereo16(int endtime) snd_linear_count <<= 1; // write a linear blast of samples - Snd_WriteLinearBlastStereo16(); + Snd_WriteLinearBlastStereo16(snd_p, snd_out, snd_linear_count, snd_vol); snd_p += snd_linear_count; lpaintedtime += (snd_linear_count >> 1); } - } void S_TransferPaintBuffer(int endtime) @@ -1276,55 +1542,59 @@ void S_TransferPaintBuffer(int endtime) int mix_vol; unsigned char* pbuf; - if (shm->samplebits == 16 && shm->channels == 2) { + int samplebits_val = shm->samplebits.load(std::memory_order_relaxed); + int channels_val = shm->channels.load(std::memory_order_relaxed); + + if (samplebits_val == 16 && channels_val == 2) { S_TransferStereo16(endtime); return; } - p = (int*)paintbuffer; - count = (endtime - paintedtime) * shm->channels; - out_mask = shm->samples - 1; - out_idx = paintedtime * shm->channels & out_mask; - step = 3 - shm->channels; - mix_vol = static_cast(volume.value * 256); + p = reinterpret_cast(paintbuffer.data()); + count = (endtime - paintedtime) * channels_val; + out_mask = shm->samples.load(std::memory_order_relaxed) - 1; + out_idx = paintedtime * channels_val & out_mask; + step = 3 - channels_val; + mix_vol = static_cast(local_volume * 256); { - pbuf = (unsigned char*)shm->buffer; + pbuf = static_cast(shm->buffer.load()); } - if (shm->samplebits == 16) { - short* out = (short*)pbuf; + if (samplebits_val == 16) { + short* out = reinterpret_cast(pbuf); while (count--) { val = (*p * mix_vol) >> 8; p += step; - if (val > 0x7fff) { - val = 0x7fff; - } else if (val < -32768) { - val = -32768; + if (val > std::numeric_limits::max()) { + val = std::numeric_limits::max(); + } else if (val < std::numeric_limits::min()) { + val = std::numeric_limits::min(); } out[out_idx] = static_cast(val); out_idx = (out_idx + 1) & out_mask; } - } else if (shm->samplebits == 8) { - unsigned char* out = (unsigned char*)pbuf; + } else if (samplebits_val == 8) { + unsigned char* out = static_cast(pbuf); while (count--) { val = (*p * mix_vol) >> 8; p += step; - if (val > 0x7fff) { - val = 0x7fff; - } else if (val < -32768) { - val = -32768; + if (val > std::numeric_limits::max()) { + val = std::numeric_limits::max(); + } else if (val < std::numeric_limits::min()) { + val = std::numeric_limits::min(); } out[out_idx] = static_cast((val >> 8) + 128); out_idx = (out_idx + 1) & out_mask; } } - } +} // namespace + /* =============================================================================== @@ -1333,14 +1603,16 @@ CHANNEL MIXING =============================================================================== */ +namespace { + void SND_PaintChannelFrom8(channel_t* ch, sfxcache_t* sc, int count, int offset); void SND_PaintChannelFrom16(channel_t* ch, sfxcache_t* sc, int count, int offset); +} // namespace + void S_PaintChannels(int endtime) { - int i; int end; - channel_t* ch; sfxcache_t* sc; int ltime, count; @@ -1352,51 +1624,51 @@ void S_PaintChannels(int endtime) } // clear the paint buffer - Q_memset(paintbuffer, 0, - (end - paintedtime) * sizeof(portable_samplepair_t)); + std::fill_n(paintbuffer.begin(), end - paintedtime, portable_samplepair_t{0, 0}); // paint in the channels. - ch = channels; - for (i = 0; i < total_channels; i++, ch++) { - if (!ch->sfx) { + for (int i = 0; i < total_channels; i++) { + auto& chan = channels[i]; + if (!chan.sfx) { continue; } - if (!ch->leftvol && !ch->rightvol) { + if (!chan.leftvol && !chan.rightvol) { continue; } - sc = S_LoadSound(ch->sfx); + sc = static_cast(Cache_Check(&chan.sfx->cache)); if (!sc) { + chan.sfx = nullptr; continue; } ltime = paintedtime; while (ltime < end) { // paint up to end - if (ch->end < end) { - count = ch->end - ltime; + if (chan.end < end) { + count = chan.end - ltime; } else { count = end - ltime; } if (count > 0) { if (sc->width == 1) { - SND_PaintChannelFrom8(ch, sc, count, ltime - paintedtime); + SND_PaintChannelFrom8(&chan, sc, count, ltime - paintedtime); } else { - SND_PaintChannelFrom16(ch, sc, count, ltime - paintedtime); + SND_PaintChannelFrom16(&chan, sc, count, ltime - paintedtime); } ltime += count; } // if at end of loop, restart - if (ltime >= ch->end) { + if (ltime >= chan.end) { if (sc->loopstart >= 0) { - ch->pos = sc->loopstart; - ch->end = ltime + sc->length - ch->pos; + chan.pos = sc->loopstart; + chan.end = ltime + sc->length - chan.pos; } else { // channel just stopped - ch->sfx = NULL; + chan.sfx = nullptr; break; } } @@ -1411,21 +1683,20 @@ void S_PaintChannels(int endtime) void SND_InitScaletable(void) { - int i, j; - - for (i = 0; i < 32; i++) { - for (j = 0; j < 256; j++) { - snd_scaletable[i][j] = ((signed char)j) * i * 8; + for (int i = 0; i < 32; i++) { + for (int j = 0; j < 256; j++) { + snd_scaletable[i][j] = static_cast(j) * i * 8; } } } +namespace { + void SND_PaintChannelFrom8(channel_t* ch, sfxcache_t* sc, int count, int offset) { int data; int *lscale, *rscale; unsigned char* sfx; - int i; if (ch->leftvol > 255) { ch->leftvol = 255; @@ -1435,11 +1706,11 @@ void SND_PaintChannelFrom8(channel_t* ch, sfxcache_t* sc, int count, int offset) ch->rightvol = 255; } - lscale = snd_scaletable[ch->leftvol >> 3]; - rscale = snd_scaletable[ch->rightvol >> 3]; - sfx = (unsigned char*)sc->data + ch->pos; + lscale = snd_scaletable[ch->leftvol >> 3].data(); + rscale = snd_scaletable[ch->rightvol >> 3].data(); + sfx = static_cast(sc->data) + ch->pos; - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { data = sfx[i]; paintbuffer[offset + i].left += lscale[data]; paintbuffer[offset + i].right += rscale[data]; @@ -1450,20 +1721,17 @@ void SND_PaintChannelFrom8(channel_t* ch, sfxcache_t* sc, int count, int offset) void SND_PaintChannelFrom16(channel_t* ch, sfxcache_t* sc, int count, int offset) { - int data; - int left, right; - int leftvol, rightvol; - signed short* sfx; - int i; + int leftvol = ch->leftvol; + int rightvol = ch->rightvol; - leftvol = ch->leftvol; - rightvol = ch->rightvol; - sfx = (signed short*)sc->data + ch->pos; + for (int i = 0; i < count; i++) { + short data_val; + // safely extract the 16-bit sample + std::memcpy(&data_val, sc->data + ((ch->pos + i) * 2), sizeof(short)); + + int left = (data_val * leftvol) >> 8; + int right = (data_val * rightvol) >> 8; - for (i = 0; i < count; i++) { - data = sfx[i]; - left = (data * leftvol) >> 8; - right = (data * rightvol) >> 8; paintbuffer[offset + i].left += left; paintbuffer[offset + i].right += right; } @@ -1471,27 +1739,37 @@ void SND_PaintChannelFrom16(channel_t* ch, sfxcache_t* sc, int count, int offset ch->pos += count; } +} // namespace + // ============================================================================ // snd_sdl.cpp -- SDL audio output driver // ============================================================================ -#include -#include +namespace { -static dma_t the_shm; -static int snd_inited; +int snd_inited; -static void paint_audio(void* /*unused*/, Uint8* stream, int len) +void paint_audio(void* /*unused*/, Uint8* stream, int len) { if (shm) { - shm->buffer = stream; - shm->samplepos += len / (shm->samplebits / 8) / 2; - // Check for samplepos overflow? - S_PaintChannels(shm->samplepos); + AudioCommand cmd{}; + while (command_queue.Pop(cmd)) { + ExecuteAudioCommand(cmd); + } + + shm->buffer.store(stream, std::memory_order_release); + int samplebits_val = shm->samplebits.load(std::memory_order_relaxed); + int current_pos = shm->samplepos.load(std::memory_order_acquire); + int next_pos = current_pos + len / (samplebits_val / 8) / 2; + shm->samplepos.store(next_pos, std::memory_order_release); + + S_PaintChannels(next_pos); } } -qboolean SNDDMA_Init(void) +} // namespace + +bool SNDDMA_Init(void) { SDL_AudioSpec desired; @@ -1504,7 +1782,7 @@ qboolean SNDDMA_Init(void) desired.format = AUDIO_U8; break; case 16: - if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + if constexpr (SDL_BYTEORDER == SDL_BIG_ENDIAN) { desired.format = AUDIO_S16MSB; } else { desired.format = AUDIO_S16LSB; @@ -1514,34 +1792,41 @@ qboolean SNDDMA_Init(void) default: Con_Printf("Unknown number of audio bits: %d\n", desired_bits); - return 0; + return false; } desired.channels = 2; desired.samples = 512; + static_assert((512 & (512 - 1)) == 0, "SDL desired samples must be a power of two for bitwise modulo to work"); desired.callback = paint_audio; /* Open the audio device */ - if (SDL_OpenAudio(&desired, NULL) < 0) { + if (SDL_OpenAudio(&desired, nullptr) < 0) { Con_Printf("Couldn't open SDL audio: %s\n", SDL_GetError()); - return 0; + return false; } SDL_PauseAudio(0); + // Ensure samples count is a power of two to support fast bitwise modulo operations + int negotiated_samples = desired.samples * desired.channels; + if ((negotiated_samples & (negotiated_samples - 1)) != 0) { + Sys_Error("SNDDMA_Init: Negotiated buffer size (%d) is not a power of two", negotiated_samples); + } + /* Fill the audio DMA information block */ shm = &the_shm; - shm->splitbuffer = 0; - shm->samplebits = (desired.format & 0xFF); - shm->speed = desired.freq; - shm->channels = desired.channels; - shm->samples = desired.samples * shm->channels; - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = NULL; + shm->splitbuffer.store(0, std::memory_order_relaxed); + shm->samplebits.store(static_cast(desired.format & 0xFF), std::memory_order_relaxed); + shm->speed.store(desired.freq, std::memory_order_relaxed); + shm->channels.store(desired.channels, std::memory_order_relaxed); + shm->samples.store(desired.samples * desired.channels, std::memory_order_relaxed); + shm->samplepos.store(0, std::memory_order_relaxed); + shm->submission_chunk.store(1, std::memory_order_relaxed); + shm->buffer.store(nullptr, std::memory_order_release); snd_inited = 1; - return 1; + return true; } void SNDDMA_Shutdown(void) diff --git a/src/audio.hpp b/src/audio.hpp index 4529aaa..8f6db5f 100644 --- a/src/audio.hpp +++ b/src/audio.hpp @@ -1,48 +1,57 @@ // audio.hpp -- client sound i/o functions #pragma once -#ifndef __AUDIO__ -#define __AUDIO__ +#include +#include +#include +#include -#define DEFAULT_SOUND_PACKET_VOLUME 255 -#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0 +namespace Audio { + +inline constexpr int DEFAULT_SOUND_PACKET_VOLUME = 255; +inline constexpr float DEFAULT_SOUND_PACKET_ATTENUATION = 1.0f; // !!! if this is changed, it much be changed in asm_i386.h too !!! -typedef struct { +struct portable_samplepair_t { int left; int right; -} portable_samplepair_t; +}; -typedef struct sfx_s { +struct sfx_s { char name[MAX_QPATH]; cache_user_t cache; -} sfx_t; +}; + +using sfx_t = sfx_s; // !!! if this is changed, it much be changed in asm_i386.h too !!! -typedef struct { +#pragma warning(push) +#pragma warning(disable: 4200) // Silence nonstandard extension: zero-sized array warning +struct sfxcache_t { int length; int loopstart; int speed; int width; int stereo; - byte data[1]; // variable sized -} sfxcache_t; - -typedef struct { - qboolean gamealive; - qboolean soundalive; - qboolean splitbuffer; - int channels; - int samples; // mono samples in buffer - int submission_chunk; // don't mix less than this # - int samplepos; // in mono samples - int samplebits; - int speed; - unsigned char* buffer; -} dma_t; + byte data[]; // variable sized +}; +#pragma warning(pop) + +struct dma_t { + std::atomic gamealive; + std::atomic soundalive; + std::atomic splitbuffer; + std::atomic channels; + std::atomic samples; // mono samples in buffer + std::atomic submission_chunk; // don't mix less than this # + std::atomic samplepos; // in mono samples + std::atomic samplebits; + std::atomic speed; + std::atomic buffer; +}; // !!! if this is changed, it much be changed in asm_i386.h too !!! -typedef struct { +struct channel_t { sfx_t* sfx; // sfx number int leftvol; // 0-255 volume int rightvol; // 0-255 volume @@ -54,18 +63,16 @@ typedef struct { Vector3 origin; // origin of sound effect vec_t dist_mult; // distance multiplier (attenuation/clipK) int master_vol; // 0-255 master volume -} channel_t; +}; -typedef struct { +struct wavinfo_t { int rate; int width; int channels; int loopstart; int samples; int dataofs; // chunk starts this many bytes from file start -} wavinfo_t; - -namespace Audio { +}; void S_Init(void); void S_Startup(void); @@ -78,28 +85,26 @@ void S_StartSound(int entnum, float attenuation); void S_StaticSound(sfx_t* sfx, const Vector3& origin, float vol, float attenuation); void S_StopSound(int entnum, int entchannel); -void S_StopAllSounds(qboolean clear); +void S_StopAllSounds(bool clear); void S_ClearBuffer(void); void S_Update(const Vector3& origin, const Vector3& v_forward, const Vector3& v_right, const Vector3& v_up); void S_ExtraUpdate(void); -sfx_t* S_PrecacheSound(const char* sample); -void S_TouchSound(const char* sample); +[[nodiscard]] sfx_t* S_PrecacheSound(std::string_view sample); +void S_TouchSound(std::string_view sample); void S_BeginPrecaching(void); void S_EndPrecaching(void); void S_PaintChannels(int endtime); void S_InitPaintChannels(void); // picks a channel based on priorities, empty slots, number of channels -channel_t* SND_PickChannel(int entnum, int entchannel); +[[nodiscard]] channel_t* SND_PickChannel(int entnum, int entchannel); // spatializes a channel void SND_Spatialize(channel_t* ch); // initializes cycling through a DMA buffer and returns information on it -qboolean SNDDMA_Init(void); - -// gets the current DMA position +[[nodiscard]] bool SNDDMA_Init(void); // shutdown the DMA xfer. void SNDDMA_Shutdown(void); @@ -108,48 +113,32 @@ void SNDDMA_Shutdown(void); // User-setable variables // ==================================================================== -#define MAX_CHANNELS 128 -#define MAX_DYNAMIC_CHANNELS 8 - -extern channel_t channels[MAX_CHANNELS]; -// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds -// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc -// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds - -extern int total_channels; - -// -// Fake dma is a synchronous faking of the DMA progress used for -// isolating performance in the renderer. The fakedma_updates is -// number of times S_Update() is called per second. -// - -extern qboolean fakedma; -extern int paintedtime; -extern Vector3 listener_origin; -extern Vector3 listener_forward; -extern Vector3 listener_right; -extern Vector3 listener_up; -extern volatile dma_t* shm; -extern volatile dma_t sn; +inline constexpr int MAX_CHANNELS = 128; +inline constexpr int MAX_DYNAMIC_CHANNELS = 8; + extern vec_t sound_nominal_clip_dist; extern cvar_t loadas8bit; extern cvar_t bgmvolume; extern cvar_t volume; -extern qboolean snd_initialized; - extern int snd_blocked; -void S_LocalSound(const char* s); -sfxcache_t* S_LoadSound(sfx_t* s); +void S_LocalSound(std::string_view s); +[[nodiscard]] sfxcache_t* S_LoadSound(sfx_t* s); -wavinfo_t GetWavinfo(char* name, byte* wav, int wavlength); +[[nodiscard]] wavinfo_t GetWavinfo(std::string_view name, std::span wav_data); void SND_InitScaletable(void); void SNDDMA_Submit(void); } // namespace Audio -#endif +// TODO: Refactor other engine subsystems to use explicit Audio:: scope, then remove these global using aliases. +using Audio::portable_samplepair_t; +using Audio::sfx_s; +using Audio::sfx_t; +using Audio::sfxcache_t; +using Audio::dma_t; +using Audio::channel_t; +using Audio::wavinfo_t; diff --git a/src/client.cpp b/src/client.cpp index b094dd5..a4f4042 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -137,11 +137,11 @@ void CL_ClearState(void) // clear other arrays memset(cl_efrags, 0, sizeof(cl_efrags)); - for (auto& e : cl_entities) e = {}; - for (auto& dl : cl_dlights) dl = {}; + std::fill(std::begin(cl_entities), std::end(cl_entities), entity_t{}); + std::fill(std::begin(cl_dlights), std::end(cl_dlights), dlight_t{}); memset(cl_lightstyle, 0, sizeof(cl_lightstyle)); - for (auto& e : cl_temp_entities) e = {}; - for (auto& b : cl_beams) b = {}; + std::fill(std::begin(cl_temp_entities), std::end(cl_temp_entities), entity_t{}); + std::fill(std::begin(cl_beams), std::end(cl_beams), beam_t{}); // // allocate the efrags and chain together into a free list @@ -259,7 +259,7 @@ void CL_SignonReply(void) ((int)cl_color.value) & 15)); MSG_WriteByte(&cls.message, clc_stringcmd); - sprintf_s(str, sizeof(str), "spawn %s", cls.spawnparms); + snprintf(str, sizeof(str), "spawn %s", cls.spawnparms); MSG_WriteString(&cls.message, str); break; @@ -292,7 +292,7 @@ void CL_NextDemo(void) SCR_BeginLoadingPlaque(); - if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) { + if (!cls.demos[cls.demonum][0] || cls.demonum >= MAX_DEMOS) { cls.demonum = 0; if (!cls.demos[cls.demonum][0]) { Con_Printf("No demos listed with startdemos\n"); @@ -302,7 +302,7 @@ void CL_NextDemo(void) } } - sprintf_s(str, sizeof(str), "playdemo %s\n", cls.demos[cls.demonum]); + snprintf(str, sizeof(str), "playdemo %s\n", cls.demos[cls.demonum]); Cmd::BufferInsertText(str); cls.demonum++; } @@ -977,7 +977,7 @@ void CL_BaseMove(usercmd_t* cmd) CL_SendMove ============== */ -void CL_SendMove(usercmd_t* cmd) +void CL_SendMove(const usercmd_t* cmd) { int i; int bits; @@ -1154,7 +1154,6 @@ Handles recording and playback of demos, on top of NET_ code */ int CL_GetMessage(void) { - int r, i; float f; if (cls.demoplayback) { @@ -1180,7 +1179,7 @@ int CL_GetMessage(void) // get the next message fread(&net_message.cursize, 4, 1, cls.demofile); VectorCopy(cl.mviewangles[0], cl.mviewangles[1]); - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { fread(&f, 4, 1, cls.demofile); cl.mviewangles[0][i] = LittleFloat(f); } @@ -1190,7 +1189,7 @@ int CL_GetMessage(void) Sys_Error("Demo message > MAX_MSGLEN"); } - r = (int)fread(net_message.data, net_message.cursize, 1, cls.demofile); + int r = (int)fread(net_message.data, net_message.cursize, 1, cls.demofile); if (r != 1) { CL_StopPlayback(); @@ -1200,6 +1199,8 @@ int CL_GetMessage(void) return 1; } + int r; + while (1) { r = NET_GetMessage(cls.netcon); @@ -1299,7 +1300,7 @@ void CL_Record_f(void) track = -1; } - sprintf_s(name, sizeof(name), "%s/%s", com_gamedir, std::string(Cmd::Argv(1)).c_str()); + snprintf(name, sizeof(name), "%s/%s", com_gamedir, std::string(Cmd::Argv(1)).c_str()); // // start the map up @@ -1314,7 +1315,7 @@ void CL_Record_f(void) COM_DefaultExtension(name, ".dem"); Con_Printf("recording to %s.\n", name); - fopen_s(&cls.demofile, name, "wb"); + cls.demofile = fopen(name, "wb"); if (!cls.demofile) { Con_Printf("ERROR: couldn't open.\n"); @@ -1622,7 +1623,7 @@ void CL_ParseServerInfo(void) // parse signon message str = MSG_ReadString(); - strncpy_s(cl.levelname, sizeof(cl.levelname), str, _TRUNCATE); + strlcpy(cl.levelname, str, sizeof(cl.levelname)); // seperate the printfs so the server message can have a color Con_Printf( @@ -1650,7 +1651,7 @@ void CL_ParseServerInfo(void) return; } - strcpy_s(model_precache[nummodels], sizeof(model_precache[nummodels]), str); + strlcpy(model_precache[nummodels], str, sizeof(model_precache[nummodels])); Mod_TouchModel(str); } @@ -1668,7 +1669,7 @@ void CL_ParseServerInfo(void) return; } - strcpy_s(sound_precache[numsounds], sizeof(sound_precache[numsounds]), str); + strlcpy(sound_precache[numsounds], str, sizeof(sound_precache[numsounds])); S_TouchSound(str); } @@ -1931,7 +1932,7 @@ void CL_ParseClientdata(int bits) if (cl.items != i) { // set flash times Sbar_Changed(); for (j = 0; j < 32; j++) { - if ((i & (1 << j)) && !(cl.items & (1 << j))) { + if ((i & (1U << static_cast(j))) && !(cl.items & (1U << static_cast(j)))) { cl.item_gettime[j] = static_cast(cl.time); } } @@ -2108,7 +2109,6 @@ CL_ParseServerMessage */ void CL_ParseServerMessage(void) { - int cmd; int i; // @@ -2131,9 +2131,8 @@ void CL_ParseServerMessage(void) Host_Error("CL_ParseServerMessage: Bad server message"); } - cmd = MSG_ReadByte(); - - if (cmd == -1) { + int cmd = MSG_ReadByte(); + if (msg_badread) { SHOWNET("END OF MESSAGE"); return; // end of message @@ -2238,7 +2237,7 @@ void CL_ParseServerMessage(void) Host_Error("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD"); } - strcpy_s(cl.scores[i].name, sizeof(cl.scores[i].name), MSG_ReadString()); + strlcpy(cl.scores[i].name, MSG_ReadString(), sizeof(cl.scores[i].name)); break; case svc_updatefrags: @@ -2406,7 +2405,7 @@ void CL_ParseBeam(model_t* m) // override any beam with the same entity for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++) { if (b->entity == ent) { - b->entity = ent; + // b->entity already matches ent, just update the rest b->model = m; b->endtime = static_cast(cl.time + 0.2); b->start = start; diff --git a/src/client.hpp b/src/client.hpp index ae2a963..f8a19f3 100644 --- a/src/client.hpp +++ b/src/client.hpp @@ -1,13 +1,13 @@ // client.h -- client state, connection, and entity structures #pragma once -typedef struct { +typedef struct usercmd_s { Vector3 viewangles; // intended velocities - float forwardmove; - float sidemove; - float upmove; + float forwardmove = 0.0f; + float sidemove = 0.0f; + float upmove = 0.0f; } usercmd_t; typedef struct { @@ -15,12 +15,12 @@ typedef struct { char map[MAX_STYLESTRING]; } lightstyle_t; -typedef struct { - char name[MAX_SCOREBOARDNAME]; - float entertime; - int frags; - int colors; // two 4 bit fields - byte translations[VID_GRADES * 256]; +typedef struct scoreboard_s { + char name[MAX_SCOREBOARDNAME] = {}; + float entertime = 0.0f; + int frags = 0; + int colors = 0; // two 4 bit fields + byte translations[VID_GRADES * 256] = {}; } scoreboard_t; typedef struct { @@ -44,21 +44,21 @@ typedef struct { #define MAX_DLIGHTS 32 -typedef struct { +typedef struct dlight_s { Vector3 origin; - float radius; - float die; // stop lighting after this time - float decay; // drop this each second - float minlight; // don't add when contributing less - int key; + float radius = 0.0f; + float die = 0.0f; // stop lighting after this time + float decay = 0.0f; // drop this each second + float minlight = 0.0f; // don't add when contributing less + int key = 0; } dlight_t; #define MAX_BEAMS 24 -typedef struct { - int entity; - struct model_s* model; - float endtime; +typedef struct beam_s { + int entity = 0; + struct model_s* model = nullptr; + float endtime = 0.0f; Vector3 start, end; } beam_t; @@ -113,21 +113,21 @@ namespace Client { // the client_state_t structure is wiped completely at every // server signon // -typedef struct { - int movemessages; // since connecting to this server +typedef struct client_state_s { + int movemessages = 0; // since connecting to this server // throw out the first couple, so the player // doesn't accidentally do something the // first frame - usercmd_t cmd; // last command sent to the server + usercmd_t cmd = {}; // last command sent to the server // information for local display - int stats[MAX_CL_STATS]; // health, etc - int items; // inventory bit flags - float item_gettime[32]; // cl.time of aquiring item, for blinking - float faceanimtime; // use anim frame if cl.time < this + int stats[MAX_CL_STATS] = {}; // health, etc + int items = 0; // inventory bit flags + float item_gettime[32] = {}; // cl.time of aquiring item, for blinking + float faceanimtime = 0.0f; // use anim frame if cl.time < this - cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups - cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types + cshift_t cshifts[NUM_CSHIFTS] = {}; // color shifts for damage, powerups + cshift_t prev_cshifts[NUM_CSHIFTS] = {}; // and content types // the client maintains its own idea of view angles, which are // sent to the server each frame. The server sets punchangle when @@ -144,53 +144,53 @@ typedef struct { Vector3 punchangle; // temporary offset // pitch drifting vars - float idealpitch; - float pitchvel; - qboolean nodrift; - float driftmove; - double laststop; + float idealpitch = 0.0f; + float pitchvel = 0.0f; + qboolean nodrift = false; + float driftmove = 0.0f; + double laststop = 0.0; - float viewheight; - float crouch; // local amount for smoothing stepups + float viewheight = 0.0f; + float crouch = 0.0f; // local amount for smoothing stepups - qboolean paused; // send over by server - qboolean onground; - qboolean inwater; + qboolean paused = false; // send over by server + qboolean onground = false; + qboolean inwater = false; - int intermission; // don't change view angle, full screen, etc - int completed_time; // latched at intermission start + int intermission = 0; // don't change view angle, full screen, etc + int completed_time = 0; // latched at intermission start - double mtime[2]; // the timestamp of last two messages - double time; // clients view of time, should be between + double mtime[2] = {}; // the timestamp of last two messages + double time = 0.0; // clients view of time, should be between // servertime and oldservertime to generate // a lerp point for other data - double oldtime; // previous cl.time, time-oldtime is used + double oldtime = 0.0; // previous cl.time, time-oldtime is used // to decay light values and smooth step ups - float last_received_message; // (realtime) for net trouble icon + float last_received_message = 0.0f; // (realtime) for net trouble icon // // information that is static for the entire time connected to a server // - struct model_s* model_precache[MAX_MODELS]; - struct sfx_s* sound_precache[MAX_SOUNDS]; + struct model_s* model_precache[MAX_MODELS] = {}; + struct sfx_s* sound_precache[MAX_SOUNDS] = {}; - char levelname[40]; // for display on solo scoreboard - int viewentity; // cl_entitites[cl.viewentity] = player - int maxclients; - int gametype; + char levelname[40] = {}; // for display on solo scoreboard + int viewentity = 0; // cl_entitites[cl.viewentity] = player + int maxclients = 0; + int gametype = 0; // refresh related state - struct model_s* worldmodel; // cl_entitites[0].model - struct efrag_s* free_efrags; - int num_entities; // held in cl_entities array - int num_statics; // held in cl_staticentities array - entity_t viewent; // the gun model + struct model_s* worldmodel = nullptr; // cl_entitites[0].model + struct efrag_s* free_efrags = nullptr; + int num_entities = 0; // held in cl_entities array + int num_statics = 0; // held in cl_staticentities array + entity_t viewent = {}; // the gun model - int cdtrack, looptrack; // cd audio + int cdtrack = 0, looptrack = 0; // cd audio // frag scoreboard - scoreboard_t* scores; // [cl.maxclients] + scoreboard_t* scores = nullptr; // [cl.maxclients] } client_state_t; @@ -240,6 +240,7 @@ using BeamArray = beam_t[MAX_BEAMS]; class ClientSubsystem { public: + ClientSubsystem() = default; client_static_t& GetStaticState() { return cls_; } const client_static_t& GetStaticState() const { return cls_; } @@ -255,15 +256,15 @@ class ClientSubsystem { BeamArray& GetBeams() { return cl_beams_; } private: - client_static_t cls_; - client_state_t cl_; - efrag_t cl_efrags_[MAX_EFRAGS]; - entity_t cl_entities_[MAX_EDICTS]; - entity_t cl_static_entities_[MAX_STATIC_ENTITIES]; - lightstyle_t cl_lightstyle_[MAX_LIGHTSTYLES]; - dlight_t cl_dlights_[MAX_DLIGHTS]; - entity_t cl_temp_entities_[MAX_TEMP_ENTITIES]; - beam_t cl_beams_[MAX_BEAMS]; + client_static_t cls_ = {}; + client_state_t cl_ = {}; + efrag_t cl_efrags_[MAX_EFRAGS] = {}; + entity_t cl_entities_[MAX_EDICTS] = {}; + entity_t cl_static_entities_[MAX_STATIC_ENTITIES] = {}; + lightstyle_t cl_lightstyle_[MAX_LIGHTSTYLES] = {}; + dlight_t cl_dlights_[MAX_DLIGHTS] = {}; + entity_t cl_temp_entities_[MAX_TEMP_ENTITIES] = {}; + beam_t cl_beams_[MAX_BEAMS] = {}; }; ClientSubsystem& GetClientSubsystem(); @@ -316,7 +317,7 @@ extern kbutton_t in_speed; void CL_InitInput(void); void CL_SendCmd(void); -void CL_SendMove(usercmd_t* cmd); +void CL_SendMove(const usercmd_t* cmd); void CL_ParseTEnt(void); void CL_UpdateTEnts(void); diff --git a/src/cmd.cpp b/src/cmd.cpp index fe500db..82675ca 100644 --- a/src/cmd.cpp +++ b/src/cmd.cpp @@ -74,7 +74,7 @@ void CommandRegistry::BufferInsertText(std::string_view text) int templen = cmd_text_.cursize; char* temp = nullptr; if (templen) { - temp = (char *) Z_Malloc(templen); + temp = static_cast(Z_Malloc(templen)); Q_memcpy(temp, cmd_text_.data, templen); SZ_Clear(&cmd_text_); } @@ -92,7 +92,7 @@ void CommandRegistry::BufferExecute(void) char line[1024]; while (cmd_text_.cursize) { - char* text = (char*)cmd_text_.data; + char* text = reinterpret_cast(cmd_text_.data); int quotes = 0; int i; @@ -152,7 +152,7 @@ static void StuffCmds_f(void) return; } - char* text = (char *) Z_Malloc(s + 1); + char* text = static_cast(Z_Malloc(s + 1)); text[0] = 0; for (int i = 1; i < com_argc; i++) { if (!com_argv[i]) { @@ -165,7 +165,7 @@ static void StuffCmds_f(void) } } - char* build = (char *) Z_Malloc(s + 1); + char* build = static_cast(Z_Malloc(s + 1)); build[0] = 0; for (int i = 0; i < s - 1; i++) { @@ -203,7 +203,7 @@ static void Exec_f(void) int mark = Hunk_LowMark(); std::string_view filename = Cmd::Argv(1); - char* f = (char*)COM_LoadHunkFile(const_cast(filename.data())); + char* f = reinterpret_cast(COM_LoadHunkFile(const_cast(filename.data()))); if (!f) { Con_Printf("couldn't exec %.*s\n", static_cast(filename.length()), filename.data()); return; @@ -226,7 +226,7 @@ static void Echo_f(void) static char* CopyString(const char* in) { char* out = (char *) Z_Malloc(static_cast(std::strlen(in)) + 1); - strcpy_s(out, std::strlen(in) + 1, in); + strlcpy(out, in, std::strlen(in) + 1); return out; } @@ -257,7 +257,7 @@ static void Alias_f(void) } if (!a) { - a = (cmdalias_t *) Z_Malloc(sizeof(cmdalias_t)); + a = static_cast(Z_Malloc(sizeof(cmdalias_t))); a->next = GetCommandRegistry().GetAliases(); GetCommandRegistry().GetAliases() = a; } @@ -268,12 +268,12 @@ static void Alias_f(void) cmd[0] = 0; int c = Cmd::Argc(); for (int i = 2; i < c; i++) { - strcat_s(cmd, sizeof(cmd), Cmd::Argv(i).data()); + strlcat(cmd, Cmd::Argv(i).data(), sizeof(cmd)); if (i != c) { - strcat_s(cmd, sizeof(cmd), " "); + strlcat(cmd, " ", sizeof(cmd)); } } - strcat_s(cmd, sizeof(cmd), "\n"); + strlcat(cmd, "\n", sizeof(cmd)); a->value = CopyString(cmd); } @@ -308,8 +308,8 @@ void CommandRegistry::AddCommand(std::string_view cmd_name, xcommand_t function) return; } - cmd_function_t* cmd = (cmd_function_t*) Hunk_Alloc(sizeof(cmd_function_t), "cmd"); - cmd->name = (char*) Hunk_Alloc(static_cast(cmd_name.length()) + 1, "cmdname"); + cmd_function_t* cmd = static_cast(Hunk_Alloc(sizeof(cmd_function_t), "cmd")); + cmd->name = static_cast(Hunk_Alloc(static_cast(cmd_name.length()) + 1, "cmdname")); std::memcpy(cmd->name, cmd_name.data(), cmd_name.length()); cmd->name[cmd_name.length()] = '\0'; cmd->function = function; @@ -319,7 +319,7 @@ void CommandRegistry::AddCommand(std::string_view cmd_name, xcommand_t function) bool CommandRegistry::Exists(std::string_view cmd_name) { - for (cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { + for (const cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { if (cmd_name == cmd->name) { return true; } @@ -333,7 +333,7 @@ std::string_view CommandRegistry::CompleteCommand(std::string_view partial) return ""; } - for (cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { + for (const cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { if (std::string_view(cmd->name).starts_with(partial)) { return cmd->name; } @@ -381,7 +381,6 @@ void CommandRegistry::TokenizeString(std::string_view text) } if (*ptr == '\n') { - ptr++; break; } @@ -393,18 +392,16 @@ void CommandRegistry::TokenizeString(std::string_view text) cmd_args_ = std::string_view(ptr); } - char* next_ptr = COM_Parse(const_cast(ptr)); + const char* next_ptr = COM_Parse(const_cast(ptr)); if (!next_ptr) { return; } ptr = next_ptr; - if (!command_parsed) { - command_parsed = true; - } + command_parsed = true; if (cmd_argc_ < 80) { // MAX_ARGS - cmd_argv_[cmd_argc_] = (char *) Z_Malloc(Q_strlen(com_token) + 1); + cmd_argv_[cmd_argc_] = static_cast(Z_Malloc(Q_strlen(com_token) + 1)); Q_strcpy(cmd_argv_[cmd_argc_], com_token); cmd_argc_++; } @@ -420,14 +417,14 @@ void CommandRegistry::ExecuteString(std::string_view text, Source src) return; } - for (cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { + for (const cmd_function_t* cmd = cmd_functions_; cmd; cmd = cmd->next) { if (Q_strcasecmp(cmd_argv_[0], cmd->name) == 0) { cmd->function(); return; } } - for (cmdalias_t* a = cmd_alias_; a; a = a->next) { + for (const cmdalias_t* a = cmd_alias_; a; a = a->next) { if (Q_strcasecmp(cmd_argv_[0], a->name) == 0) { BufferInsertText(a->value); return; @@ -479,4 +476,4 @@ std::string_view Args(void) { return GetCommandRegistry().Args(); } void ExecuteString(std::string_view text, Source src) { GetCommandRegistry().ExecuteString(text, src); } // ForwardToServer is implemented directly above -} // namespace Cmd \ No newline at end of file +} // namespace Cmd diff --git a/src/cmd.hpp b/src/cmd.hpp index 5f858ee..dd16a49 100644 --- a/src/cmd.hpp +++ b/src/cmd.hpp @@ -56,12 +56,12 @@ class CommandRegistry { private: State state_; - sizebuf_t cmd_text_; + sizebuf_t cmd_text_ = {}; bool cmd_wait_ = false; cmdalias_t* cmd_alias_ = nullptr; cmd_function_t* cmd_functions_ = nullptr; int cmd_argc_ = 0; - char* cmd_argv_[80]; // MAX_ARGS + char* cmd_argv_[80] = {}; // MAX_ARGS std::string_view cmd_args_; }; diff --git a/src/common.cpp b/src/common.cpp index 344e302..24dea62 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -143,11 +143,11 @@ void Q_memset(void* dest, int fill, int count) count >>= 2; fill = fill | (fill << 8) | (fill << 16) | (fill << 24); for (i = 0; i < count; i++) { - ((int*)dest)[i] = fill; + static_cast(dest)[i] = fill; } } else { for (i = 0; i < count; i++) { - ((byte*)dest)[i] = static_cast(fill); + static_cast(dest)[i] = static_cast(fill); } } } @@ -160,11 +160,11 @@ void Q_memcpy(void* dest, const void* src, int count) if ((((size_t)dest | (size_t)src | count) & 3) == 0) { count >>= 2; for (i = 0; i < count; i++) { - ((int*)dest)[i] = ((const int*)src)[i]; + static_cast(dest)[i] = static_cast(src)[i]; } } else { for (i = 0; i < count; i++) { - ((byte*)dest)[i] = ((const byte*)src)[i]; + static_cast(dest)[i] = static_cast(src)[i]; } } } @@ -260,11 +260,9 @@ int Q_strncmp(const char* s1, const char* s2, int count) int Q_strncasecmp(const char* s1, const char* s2, int n) { - int c1, c2; - while (1) { - c1 = *s1++; - c2 = *s2++; + int c1 = *s1++; + int c2 = *s2++; if (!n--) { return 0; // strings are equal until end point @@ -529,7 +527,7 @@ void MSG_WriteChar(sizebuf_t* sb, int c) #endif - buf = (byte*)SZ_GetSpace(sb, 1); + buf = static_cast(SZ_GetSpace(sb, 1)); buf[0] = static_cast(c); } @@ -544,7 +542,7 @@ void MSG_WriteByte(sizebuf_t* sb, int c) #endif - buf = (byte*)SZ_GetSpace(sb, 1); + buf = static_cast(SZ_GetSpace(sb, 1)); buf[0] = static_cast(c); } @@ -553,26 +551,26 @@ void MSG_WriteShort(sizebuf_t* sb, int c) byte* buf; #ifdef PARANOID - if (c < ((short)0x8000) || c > (short)0x7fff) { + if (c < -32768 || c > 32767) { Sys_Error("MSG_WriteShort: range error"); } #endif - buf = (byte*)SZ_GetSpace(sb, 2); + buf = static_cast(SZ_GetSpace(sb, 2)); buf[0] = c & 0xff; - buf[1] = static_cast(c >> 8); + buf[1] = static_cast(static_cast(c) >> 8); } void MSG_WriteLong(sizebuf_t* sb, int c) { byte* buf; - buf = (byte*)SZ_GetSpace(sb, 4); + buf = static_cast(SZ_GetSpace(sb, 4)); buf[0] = c & 0xff; - buf[1] = (c >> 8) & 0xff; - buf[2] = (c >> 16) & 0xff; - buf[3] = c >> 24; + buf[1] = (static_cast(c) >> 8) & 0xff; + buf[2] = (static_cast(c) >> 16) & 0xff; + buf[3] = static_cast(static_cast(c) >> 24); } void MSG_WriteFloat(sizebuf_t* sb, float f) @@ -698,11 +696,9 @@ float MSG_ReadFloat(void) char* MSG_ReadString(void) { static char string[2048]; - int l, c; - - l = 0; + int l = 0; do { - c = MSG_ReadChar(); + int c = MSG_ReadChar(); if (c == -1 || c == 0) { break; } @@ -724,7 +720,7 @@ void SZ_Alloc(sizebuf_t* buf, int startsize) startsize = 256; } - buf->data = (byte *) Hunk_Alloc(startsize, "sizebuf"); + buf->data = static_cast(Hunk_Alloc(startsize, "sizebuf")); buf->maxsize = startsize; buf->cursize = 0; } @@ -766,9 +762,9 @@ void SZ_Print(sizebuf_t* buf, const char* data) // byte * cast to keep VC++ happy if (buf->data[buf->cursize - 1]) { - Q_memcpy((byte*)SZ_GetSpace(buf, len), data, len); // no trailing 0 + Q_memcpy(SZ_GetSpace(buf, len), data, len); // no trailing 0 } else { - Q_memcpy((byte*)SZ_GetSpace(buf, len - 1) - 1, data, + Q_memcpy(static_cast(SZ_GetSpace(buf, len - 1)) - 1, data, len); // write over trailing 0 } } @@ -822,10 +818,10 @@ void COM_FileBase(const char* in, char* out) } if (s - s2 < 2) { - strcpy_s(out, 32, "?model?"); + strlcpy(out, "?model?", 32); } else { s--; - strncpy_s(out, 32, s2 + 1, s - s2); + strlcpy(out, s2 + 1, 32); out[s - s2] = 0; } } @@ -852,7 +848,7 @@ void COM_DefaultExtension(char* path, const char* extension) src--; } - strcat_s(path, 256, extension); + strlcat(path, extension, 256); } /* @@ -1081,7 +1077,7 @@ void COM_Init() if (SDL_BYTEORDER == SDL_LIL_ENDIAN) #else byte swaptest[2] = { 1, 0 }; - if (*(short*)swaptest == 1) + if (*reinterpret_cast(swaptest) == 1) #endif { bigendien = false; @@ -1124,7 +1120,7 @@ char* va(const char* format, ...) static char string[1024]; va_start(argptr, format); - vsprintf_s(string, sizeof(string), format, argptr); + vsnprintf(string, sizeof(string), format, argptr); va_end(argptr); return string; @@ -1210,12 +1206,12 @@ COM_WriteFile The filename will be prefixed by the current game directory ============ */ -void COM_WriteFile(const char* filename, void* data, int len) +void COM_WriteFile(const char* filename, const void* data, int len) { int handle; char name[MAX_OSPATH]; - sprintf_s(name, sizeof(name), "%s/%s", com_gamedir, filename); + snprintf(name, sizeof(name), "%s/%s", com_gamedir, filename); handle = Sys_FileOpenWrite(name); if (handle == -1) { @@ -1257,7 +1253,7 @@ Copies a file over from the net to the local cache, creating any directories needed. This is for the convenience of developers using ISDN from home. =========== */ -void COM_CopyFile(char* netpath, char* cachepath) +void COM_CopyFile(const char* netpath, char* cachepath) { int in, out; int remaining, count; @@ -1330,7 +1326,7 @@ int COM_FindFile(const char* filename, int* handle, FILE** file) *handle = pak->handle; Sys_FileSeek(pak->handle, pak->files[i].filepos); } else { // open a new file on the pakfile - fopen_s(file, pak->filename, "rb"); + *file = fopen(pak->filename, "rb"); if (*file) { fseek(*file, pak->files[i].filepos, SEEK_SET); } @@ -1349,7 +1345,7 @@ int COM_FindFile(const char* filename, int* handle, FILE** file) } } - sprintf_s(netpath, sizeof(netpath), "%s/%s", search->filename, filename); + snprintf(netpath, sizeof(netpath), "%s/%s", search->filename, filename); findtime = Sys_FileTime(netpath); if (findtime == -1) { @@ -1358,9 +1354,9 @@ int COM_FindFile(const char* filename, int* handle, FILE** file) // see if the file needs to be updated in the cache if (!com_cachedir[0]) { - strcpy_s(cachepath, sizeof(cachepath), netpath); + strlcpy(cachepath, netpath, sizeof(cachepath)); } else { - sprintf_s(cachepath, sizeof(cachepath), "%s/%s", com_cachedir, netpath); + snprintf(cachepath, sizeof(cachepath), "%s/%s", com_cachedir, netpath); cachetime = Sys_FileTime(cachepath); @@ -1368,7 +1364,7 @@ int COM_FindFile(const char* filename, int* handle, FILE** file) COM_CopyFile(netpath, cachepath); } - strcpy_s(netpath, sizeof(netpath), cachepath); + strlcpy(netpath, cachepath, sizeof(netpath)); } Sys_Printf("FindFile: %s\n", netpath); @@ -1377,7 +1373,7 @@ int COM_FindFile(const char* filename, int* handle, FILE** file) *handle = i; } else { Sys_FileClose(i); - fopen_s(file, netpath, "rb"); + *file = fopen(netpath, "rb"); } return com_filesize; @@ -1406,9 +1402,7 @@ If it is a pak file handle, don't really close it */ void COM_CloseFile(int h) { - searchpath_t* s; - - for (s = com_searchpaths; s; s = s->next) { + for (const searchpath_t* s = com_searchpaths; s; s = s->next) { if (s->pack && s->pack->handle == h) { return; } @@ -1448,16 +1442,16 @@ byte* COM_LoadFile(const char* path, int usehunk) COM_FileBase(path, base); if (usehunk == 1) { - buf = (byte *) Hunk_Alloc(len + 1, base); + buf = static_cast(Hunk_Alloc(len + 1, base)); } else if (usehunk == 2) { - buf = (byte *) Hunk_TempAlloc(len + 1); + buf = static_cast(Hunk_TempAlloc(len + 1)); } else if (usehunk == 0) { - buf = (byte *) Z_Malloc(len + 1); + buf = static_cast(Z_Malloc(len + 1)); } else if (usehunk == 3) { - buf = (byte *) Cache_Alloc(loadcache, len + 1, base); + buf = static_cast(Cache_Alloc(loadcache, len + 1, base)); } else if (usehunk == 4) { if (len + 1 > loadsize) { - buf = (byte *) Hunk_TempAlloc(len + 1); + buf = static_cast(Hunk_TempAlloc(len + 1)); } else { buf = loadbuf; } @@ -1469,7 +1463,7 @@ byte* COM_LoadFile(const char* path, int usehunk) Sys_Error("COM_LoadFile: not enough space for %s", path); } - ((byte*)buf)[len] = 0; + buf[len] = 0; Draw_BeginDisc(); Sys_FileRead(h, buf, len); @@ -1490,7 +1484,7 @@ byte* COM_LoadStackFile(const char* path, void* buffer, int bufsize) { byte* buf; - loadbuf = (byte*)buffer; + loadbuf = static_cast(buffer); loadsize = bufsize; buf = COM_LoadFile(path, 4); @@ -1523,7 +1517,7 @@ pack_t* COM_LoadPackFile(char* packfile) return NULL; } - Sys_FileRead(packhandle, (void*)&header, sizeof(header)); + Sys_FileRead(packhandle, &header, sizeof(header)); if (header.id[0] != 'P' || header.id[1] != 'A' || header.id[2] != 'C' || header.id[3] != 'K') { Sys_Error("%s is not a packfile", packfile); } @@ -1541,15 +1535,15 @@ pack_t* COM_LoadPackFile(char* packfile) com_modified = true; // not the original file } - newfiles = (packfile_t *) Hunk_Alloc(numpackfiles * sizeof(packfile_t), "packfile"); + newfiles = static_cast(Hunk_Alloc(numpackfiles * sizeof(packfile_t), "packfile")); Sys_FileSeek(packhandle, header.dirofs); - Sys_FileRead(packhandle, (void*)info, header.dirlen); + Sys_FileRead(packhandle, info, header.dirlen); // crc the directory to check for modifications CRC_Init(&crc); for (i = 0; i < header.dirlen; i++) { - CRC_ProcessByte(&crc, ((byte*)info)[i]); + CRC_ProcessByte(&crc, reinterpret_cast(info)[i]); } if (crc != PAK0_CRC) { com_modified = true; @@ -1557,13 +1551,13 @@ pack_t* COM_LoadPackFile(char* packfile) // parse the directory for (i = 0; i < numpackfiles; i++) { - strcpy_s(newfiles[i].name, sizeof(newfiles[i].name), info[i].name); + strlcpy(newfiles[i].name, info[i].name, sizeof(newfiles[i].name)); newfiles[i].filepos = LittleLong(info[i].filepos); newfiles[i].filelen = LittleLong(info[i].filelen); } pack = (pack_t *) Hunk_Alloc(sizeof(pack_t)); - strcpy_s(pack->filename, sizeof(pack->filename), packfile); + strlcpy(pack->filename, packfile, sizeof(pack->filename)); pack->handle = packhandle; pack->numfiles = numpackfiles; pack->files = newfiles; @@ -1588,13 +1582,13 @@ void COM_AddGameDirectory(char* dir) pack_t* pak; char pakfile[MAX_OSPATH]; - strcpy_s(com_gamedir, sizeof(com_gamedir), dir); + strlcpy(com_gamedir, dir, sizeof(com_gamedir)); // // add the directory to the search path // search = (searchpath_t *) Hunk_Alloc(sizeof(searchpath_t)); - strcpy_s(search->filename, sizeof(search->filename), dir); + strlcpy(search->filename, dir, sizeof(search->filename)); search->next = com_searchpaths; com_searchpaths = search; @@ -1602,13 +1596,13 @@ void COM_AddGameDirectory(char* dir) // add any pak files in the format pak0.pak pak1.pak, ... // for (i = 0;; i++) { - sprintf_s(pakfile, sizeof(pakfile), "%s/pak%i.pak", dir, i); + snprintf(pakfile, sizeof(pakfile), "%s/pak%i.pak", dir, i); pak = COM_LoadPackFile(pakfile); if (!pak) { break; } - search = (searchpath_t *) Hunk_Alloc(sizeof(searchpath_t)); + search = static_cast(Hunk_Alloc(sizeof(searchpath_t))); search->pack = pak; search->next = com_searchpaths; com_searchpaths = search; @@ -1636,9 +1630,9 @@ void COM_InitFilesystem(void) // i = COM_CheckParm("-basedir"); if (i && i < com_argc - 1) { - strcpy_s(basedir, sizeof(basedir), com_argv[i + 1]); + strlcpy(basedir, com_argv[i + 1], sizeof(basedir)); } else { - strcpy_s(basedir, sizeof(basedir), host_parms.basedir); + strlcpy(basedir, host_parms.basedir, sizeof(basedir)); } j = (int)strlen(basedir); @@ -1706,14 +1700,14 @@ void COM_InitFilesystem(void) break; } - search = (searchpath_t *) Hunk_Alloc(sizeof(searchpath_t)); + search = static_cast(Hunk_Alloc(sizeof(searchpath_t))); if (!strcmp(COM_FileExtension(com_argv[i]), "pak")) { search->pack = COM_LoadPackFile(com_argv[i]); if (!search->pack) { Sys_Error("Couldn't load packfile: %s", com_argv[i]); } } else { - strcpy_s(search->filename, sizeof(search->filename), com_argv[i]); + strlcpy(search->filename, com_argv[i], sizeof(search->filename)); } search->next = com_searchpaths; diff --git a/src/common.hpp b/src/common.hpp index a551402..1038b34 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -26,10 +26,12 @@ typedef struct link_s { struct link_s *prev, *next; } link_t; +#include + // (type *)STRUCT_FROM_LINK(link_t *link, type, member) // ent = STRUCT_FROM_LINK(link,entity_t,order) // FIXME: remove this mess! -#define STRUCT_FROM_LINK(l, t, m) ((t*)((byte*)l - (intptr_t)&(((t*)0)->m))) +#define STRUCT_FROM_LINK(l, t, m) (reinterpret_cast(reinterpret_cast(l) - offsetof(t, m))) //============================================================================ @@ -156,10 +158,10 @@ inline void SZ_Write(sizebuf_t* buf, const void* data, int length) inline int Q_strcasecmp(const char* s1, const char* s2) { - int c1, c2; + int c1; do { c1 = *s1++; - c2 = *s2++; + int c2 = *s2++; if (c1 != c2) { if (c1 >= 'a' && c1 <= 'z') c1 -= ('a' - 'A'); if (c2 >= 'a' && c2 <= 'z') c2 -= ('a' - 'A'); @@ -219,7 +221,7 @@ extern int com_filesize; extern char com_gamedir[MAX_OSPATH]; -void COM_WriteFile(const char* filename, void* data, int len); +void COM_WriteFile(const char* filename, const void* data, int len); int COM_FindFile(const char* filename, int* handle, FILE** file); byte* COM_LoadFile(const char* path, int usehunk); diff --git a/src/console.cpp b/src/console.cpp index 3426cee..84d2c3b 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -2,11 +2,11 @@ #ifdef _MSC_VER #include +#include #else #include #endif #include -#include #include #include "quakedef.hpp" @@ -146,7 +146,7 @@ If the line width has changed, reformat the buffer. */ void Con_CheckResize(void) { - int i, j, width, oldwidth, oldtotallines, numlines, numchars; + int width; char tbuf[CON_TEXTSIZE]; width = (vid.width >> 3) - 2; @@ -162,17 +162,17 @@ void Con_CheckResize(void) con_totallines = CON_TEXTSIZE / con_linewidth; Q_memset(con_text, ' ', CON_TEXTSIZE); } else { - oldwidth = con_linewidth; + int oldwidth = con_linewidth; con_linewidth = width; - oldtotallines = con_totallines; + int oldtotallines = con_totallines; con_totallines = CON_TEXTSIZE / con_linewidth; - numlines = oldtotallines; + int numlines = oldtotallines; if (con_totallines < numlines) { numlines = con_totallines; } - numchars = oldwidth; + int numchars = oldwidth; if (con_linewidth < numchars) { numchars = con_linewidth; @@ -181,8 +181,8 @@ void Con_CheckResize(void) Q_memcpy(tbuf, con_text, CON_TEXTSIZE); Q_memset(con_text, ' ', CON_TEXTSIZE); - for (i = 0; i < numlines; i++) { - for (j = 0; j < numchars; j++) { + for (int i = 0; i < numlines; i++) { + for (int j = 0; j < numchars; j++) { con_text[(con_totallines - 1 - i) * con_linewidth + j] = tbuf[((con_current - i + oldtotallines) % oldtotallines) * oldwidth + j]; } } @@ -209,12 +209,12 @@ void Con_Init(void) if (con_debuglog) { if (strlen(com_gamedir) < (MAXGAMEDIRLEN - strlen(t2))) { - sprintf_s(temp, sizeof(temp), "%s%s", com_gamedir, t2); - _unlink(temp); + snprintf(temp, sizeof(temp), "%s%s", com_gamedir, t2); + unlink(temp); } } - con_text = (char *) Hunk_Alloc(CON_TEXTSIZE, "context"); + con_text = static_cast(Hunk_Alloc(CON_TEXTSIZE, "context")); Q_memset(con_text, ' ', CON_TEXTSIZE); con_linewidth = -1; Con_CheckResize(); @@ -347,7 +347,7 @@ void Con_DebugLog(const char* file, const char* fmt, ...) int fd; va_start(argptr, fmt); - vsprintf_s(data, sizeof(data), fmt, argptr); + vsnprintf(data, sizeof(data), fmt, argptr); va_end(argptr); fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); write(fd, data, (unsigned int)strlen(data)); @@ -371,7 +371,7 @@ void Con_Printf(const char* fmt, ...) static qboolean inupdate; va_start(argptr, fmt); - vsprintf_s(msg, sizeof(msg), fmt, argptr); + vsnprintf(msg, sizeof(msg), fmt, argptr); va_end(argptr); // also echo to debugging console @@ -422,7 +422,7 @@ void Con_DPrintf(const char* fmt, ...) } va_start(argptr, fmt); - vsprintf_s(msg, sizeof(msg), fmt, argptr); + vsnprintf(msg, sizeof(msg), fmt, argptr); va_end(argptr); Con_Printf("%s", msg); @@ -486,11 +486,9 @@ Draws the last few lines of output transparently over the game top void Con_DrawNotify(void) { int x, v; - char* text; - int i; float time; - v = 0; - for (i = con_current - NUM_CON_TIMES + 1; i <= con_current; i++) { + v = 0; + for (int i = con_current - NUM_CON_TIMES + 1; i <= con_current; i++) { if (i < 0) { continue; } @@ -505,7 +503,7 @@ void Con_DrawNotify(void) continue; } - text = con_text + (i % con_totallines) * con_linewidth; + const char* text = con_text + (i % con_totallines) * con_linewidth; clearnotify = 0; scr_copytop = 1; @@ -548,10 +546,8 @@ The typing input line at the bottom should only be drawn if typing is allowed */ void Con_DrawConsole(int lines, qboolean drawinput) { - int i, x, y; + int x, y; int rows; - char* text; - int j; if (lines <= 0) { return; @@ -563,16 +559,16 @@ void Con_DrawConsole(int lines, qboolean drawinput) // draw the text con_vislines = lines; - rows = (lines - 16) >> 3; // rows of text to draw + rows = (lines - 16) / 8; // rows of text to draw y = lines - 16 - (rows << 3); // may start slightly negative - for (i = con_current - rows + 1; i <= con_current; i++, y += 8) { - j = i - con_backscroll; + for (int i = con_current - rows + 1; i <= con_current; i++, y += 8) { + int j = i - con_backscroll; if (j < 0) { j = 0; } - text = con_text + (j % con_totallines) * con_linewidth; + const char* text = con_text + (j % con_totallines) * con_linewidth; for (x = 0; x < con_linewidth; x++) { Draw_Character((x + 1) << 3, y, text[x]); diff --git a/src/cvar.cpp b/src/cvar.cpp index d645282..3a121ac 100644 --- a/src/cvar.cpp +++ b/src/cvar.cpp @@ -57,7 +57,7 @@ VariableValue */ float CvarRegistry::VariableValue(std::string_view var_name) { - cvar_t* var = FindVar(var_name); + const cvar_t* var = FindVar(var_name); if (!var) { return 0.0f; } @@ -71,7 +71,7 @@ VariableString */ std::string_view CvarRegistry::VariableString(std::string_view var_name) { - cvar_t* var = FindVar(var_name); + const cvar_t* var = FindVar(var_name); if (!var) { return ""; } @@ -114,7 +114,7 @@ void CvarRegistry::Set(std::string_view var_name, std::string_view value) Z_Free(const_cast(var->string)); // free the old value string - char* new_str = (char *) Z_Malloc(static_cast(value.length()) + 1); + char* new_str = static_cast(Z_Malloc(static_cast(value.length()) + 1)); Q_memcpy(new_str, const_cast(value.data()), static_cast(value.length())); new_str[value.length()] = '\0'; var->string = new_str; @@ -134,7 +134,7 @@ SetValue void CvarRegistry::SetValue(std::string_view var_name, float value) { char val[32]; - sprintf_s(val, sizeof(val), "%f", value); + snprintf(val, sizeof(val), "%f", value); Set(var_name, val); } @@ -159,7 +159,7 @@ void CvarRegistry::Register(cvar_t* variable) // copy the value off, because future sets will Z_Free it const char* oldstr = variable->string; - char* new_str = (char *) Z_Malloc(Q_strlen(oldstr) + 1); + char* new_str = static_cast(Z_Malloc(Q_strlen(oldstr) + 1)); Q_strcpy(new_str, oldstr); variable->string = new_str; variable->value = Q_atof(variable->string); @@ -198,7 +198,7 @@ WriteVariables */ void CvarRegistry::WriteVariables(std::FILE* f) { - for (cvar_t* var = state_.vars; var; var = var->next) { + for (const cvar_t* var = state_.vars; var; var = var->next) { if (var->archive) { std::fprintf(f, "%s \"%s\"\n", var->name, var->string); } diff --git a/src/draw.cpp b/src/draw.cpp index c535cd3..59a0904 100644 --- a/src/draw.cpp +++ b/src/draw.cpp @@ -79,10 +79,10 @@ qpic_t* Draw_CachePic(const char* path) } menu_numcachepics++; - strcpy_s(pic->name, sizeof(pic->name), path); + strlcpy(pic->name, path, sizeof(pic->name)); } - dat = (qpic_t *) Cache_Check(&pic->cache); + dat = static_cast(Cache_Check(&pic->cache)); if (dat) { return dat; @@ -93,7 +93,7 @@ qpic_t* Draw_CachePic(const char* path) // COM_LoadCacheFile(path, &pic->cache); - dat = (qpic_t*)pic->cache.data; + dat = static_cast(pic->cache.data); if (!dat) { Sys_Error("Draw_CachePic: failed to load %s", path); } @@ -110,9 +110,9 @@ Draw_Init */ void Draw_Init(void) { - draw_chars = (byte*)W_GetLumpName("conchars"); - draw_disc = (qpic_t*)W_GetLumpName("disc"); - draw_backtile = (qpic_t*)W_GetLumpName("backtile"); + draw_chars = static_cast(W_GetLumpName("conchars")); + draw_disc = static_cast(W_GetLumpName("disc")); + draw_backtile = static_cast(W_GetLumpName("backtile")); r_rectdesc.width = draw_backtile->width; r_rectdesc.height = draw_backtile->height; @@ -207,7 +207,7 @@ void Draw_Character(int x, int y, int num) } } else { // FIXME: pre-expand to native format? - pusdest = (unsigned short*)((byte*)vid.conbuffer + y * vid.conrowbytes + (x << 1)); + pusdest = reinterpret_cast(static_cast(vid.conbuffer) + y * vid.conrowbytes + (x << 1)); while (drawline--) { if (source[0]) { @@ -267,11 +267,10 @@ void Draw_String(int x, int y, const char* str) Draw_Pic ============= */ -void Draw_Pic(int x, int y, qpic_t* pic) +void Draw_Pic(int x, int y, const qpic_t* pic) { - byte *dest, *source; - unsigned short* pusdest; - int v, u; + const byte* source; + int v; if ((x < 0) || (unsigned)(x + pic->width) > vid.width || (y < 0) || (unsigned)(y + pic->height) > vid.height) { Sys_Error("Draw_Pic: bad coordinates"); @@ -280,7 +279,7 @@ void Draw_Pic(int x, int y, qpic_t* pic) source = pic->data; if (r_pixbytes == 1) { - dest = vid.buffer + y * vid.rowbytes + x; + byte* dest = vid.buffer + y * vid.rowbytes + x; for (v = 0; v < pic->height; v++) { Q_memcpy(dest, source, pic->width); @@ -289,10 +288,10 @@ void Draw_Pic(int x, int y, qpic_t* pic) } } else { // FIXME: pretranslate at load time? - pusdest = (unsigned short*)vid.buffer + y * (vid.rowbytes >> 1) + x; + unsigned short* pusdest = reinterpret_cast(vid.buffer) + y * (vid.rowbytes >> 1) + x; for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u++) { + for (int u = 0; u < pic->width; u++) { pusdest[u] = d_8to16table[source[u]]; } @@ -307,10 +306,10 @@ void Draw_Pic(int x, int y, qpic_t* pic) Draw_TransPic ============= */ -void Draw_TransPic(int x, int y, qpic_t* pic) +void Draw_TransPic(int x, int y, const qpic_t* pic) { - byte *dest, *source, tbyte; - unsigned short* pusdest; + const byte* source; + byte tbyte; int v, u; if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || (unsigned)(y + pic->height) > vid.height) { @@ -320,7 +319,7 @@ void Draw_TransPic(int x, int y, qpic_t* pic) source = pic->data; if (r_pixbytes == 1) { - dest = vid.buffer + y * vid.rowbytes + x; + byte* dest = vid.buffer + y * vid.rowbytes + x; if (pic->width & 7) { // general for (v = 0; v < pic->height; v++) { @@ -374,7 +373,7 @@ void Draw_TransPic(int x, int y, qpic_t* pic) } } else { // FIXME: pretranslate at load time? - pusdest = (unsigned short*)vid.buffer + y * (vid.rowbytes >> 1) + x; + unsigned short* pusdest = reinterpret_cast(vid.buffer) + y * (vid.rowbytes >> 1) + x; for (v = 0; v < pic->height; v++) { for (u = 0; u < pic->width; u++) { @@ -396,10 +395,10 @@ void Draw_TransPic(int x, int y, qpic_t* pic) Draw_TransPicTranslate ============= */ -void Draw_TransPicTranslate(int x, int y, qpic_t* pic, byte* translation) +void Draw_TransPicTranslate(int x, int y, const qpic_t* pic, const byte* translation) { - byte *dest, *source, tbyte; - unsigned short* pusdest; + const byte* source; + byte tbyte; int v, u; if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || (unsigned)(y + pic->height) > vid.height) { @@ -409,7 +408,7 @@ void Draw_TransPicTranslate(int x, int y, qpic_t* pic, byte* translation) source = pic->data; if (r_pixbytes == 1) { - dest = vid.buffer + y * vid.rowbytes + x; + byte* dest = vid.buffer + y * vid.rowbytes + x; if (pic->width & 7) { // general for (v = 0; v < pic->height; v++) { @@ -463,7 +462,7 @@ void Draw_TransPicTranslate(int x, int y, qpic_t* pic, byte* translation) } } else { // FIXME: pretranslate at load time? - pusdest = (unsigned short*)vid.buffer + y * (vid.rowbytes >> 1) + x; + unsigned short* pusdest = reinterpret_cast(vid.buffer) + y * (vid.rowbytes >> 1) + x; for (v = 0; v < pic->height; v++) { for (u = 0; u < pic->width; u++) { @@ -513,17 +512,17 @@ Draw_ConsoleBackground void Draw_ConsoleBackground(int lines) { int y, v, x; - byte *src, *dest; - unsigned short* pusdest; + const byte* src; + byte* dest; int f, fstep; - qpic_t* conback; + const qpic_t* conback; char ver[100]; conback = Draw_CachePic("gfx/conback.lmp"); // hack the version number directly into the pic - dest = conback->data + 320 - 43 + 320 * 186; - sprintf_s(ver, sizeof(ver), "%4.2f", VERSION); + dest = (byte*)conback->data + 320 - 43 + 320 * 186; + snprintf(ver, sizeof(ver), "%4.2f", VERSION); for (x = 0; x < static_cast(strlen(ver)); x++) { Draw_CharToConback(ver[x], dest + (x << 3)); @@ -554,7 +553,7 @@ void Draw_ConsoleBackground(int lines) } } } else { - pusdest = (unsigned short*)vid.conbuffer; + unsigned short* pusdest = reinterpret_cast(vid.conbuffer); for (y = 0; y < lines; y++, pusdest += (vid.conrowbytes >> 1)) { // FIXME: pre-expand to native format? @@ -582,10 +581,9 @@ void Draw_ConsoleBackground(int lines) R_DrawRect8 ============== */ -void R_DrawRect8(vrect_t* prect, int rowbytes, byte* psrc, int transparent) +void R_DrawRect8(const vrect_t* prect, int rowbytes, const byte* psrc, int transparent) { - byte t; - int i, j, srcdelta, destdelta; + int i, srcdelta, destdelta; byte* pdest; pdest = vid.buffer + (prect->y * vid.rowbytes) + prect->x; @@ -595,8 +593,8 @@ void R_DrawRect8(vrect_t* prect, int rowbytes, byte* psrc, int transparent) if (transparent) { for (i = 0; i < prect->height; i++) { - for (j = 0; j < prect->width; j++) { - t = *psrc; + for (int j = 0; j < prect->width; j++) { + byte t = *psrc; if (t != TRANSPARENT_COLOR) { *pdest = t; } @@ -622,23 +620,22 @@ void R_DrawRect8(vrect_t* prect, int rowbytes, byte* psrc, int transparent) R_DrawRect16 ============== */ -void R_DrawRect16(vrect_t* prect, int rowbytes, byte* psrc, int transparent) +void R_DrawRect16(const vrect_t* prect, int rowbytes, const byte* psrc, int transparent) { - byte t; - int i, j, srcdelta, destdelta; + int i, srcdelta, destdelta; unsigned short* pdest; // FIXME: would it be better to pre-expand native-format versions? - pdest = (unsigned short*)vid.buffer + (prect->y * (vid.rowbytes >> 1)) + prect->x; + pdest = reinterpret_cast(vid.buffer) + (prect->y * (vid.rowbytes >> 1)) + prect->x; srcdelta = rowbytes - prect->width; destdelta = (vid.rowbytes >> 1) - prect->width; if (transparent) { for (i = 0; i < prect->height; i++) { - for (j = 0; j < prect->width; j++) { - t = *psrc; + for (int j = 0; j < prect->width; j++) { + byte t = *psrc; if (t != TRANSPARENT_COLOR) { *pdest = d_8to16table[t]; } @@ -652,7 +649,7 @@ void R_DrawRect16(vrect_t* prect, int rowbytes, byte* psrc, int transparent) } } else { for (i = 0; i < prect->height; i++) { - for (j = 0; j < prect->width; j++) { + for (int j = 0; j < prect->width; j++) { *pdest = d_8to16table[*psrc]; psrc++; pdest++; @@ -674,8 +671,7 @@ refresh window. */ void Draw_TileClear(int x, int y, int w, int h) { - int width, height, tileoffsetx, tileoffsety; - byte* psrc; + int height, tileoffsety; vrect_t vr; r_rectdesc.rect.x = x; @@ -690,7 +686,7 @@ void Draw_TileClear(int x, int y, int w, int h) while (height > 0) { vr.x = r_rectdesc.rect.x; - width = r_rectdesc.rect.width; + int width = r_rectdesc.rect.width; if (tileoffsety != 0) { vr.height = r_rectdesc.height - tileoffsety; @@ -702,7 +698,7 @@ void Draw_TileClear(int x, int y, int w, int h) vr.height = height; } - tileoffsetx = vr.x % r_rectdesc.width; + int tileoffsetx = vr.x % r_rectdesc.width; while (width > 0) { if (tileoffsetx != 0) { @@ -715,7 +711,7 @@ void Draw_TileClear(int x, int y, int w, int h) vr.width = width; } - psrc = r_rectdesc.ptexbytes + (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx; + const byte* psrc = r_rectdesc.ptexbytes + (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx; if (r_pixbytes == 1) { R_DrawRect8(&vr, r_rectdesc.rowbytes, psrc, 0); @@ -743,22 +739,19 @@ Fills a box of pixels with a single color */ void Draw_Fill(int x, int y, int w, int h, int c) { - byte* dest; - unsigned short* pusdest; - unsigned uc; int u, v; if (r_pixbytes == 1) { - dest = vid.buffer + y * vid.rowbytes + x; + byte* dest = vid.buffer + y * vid.rowbytes + x; for (v = 0; v < h; v++, dest += vid.rowbytes) { for (u = 0; u < w; u++) { dest[u] = static_cast(c); } } } else { - uc = d_8to16table[c]; + unsigned uc = d_8to16table[c]; - pusdest = (unsigned short*)vid.buffer + y * (vid.rowbytes >> 1) + x; + unsigned short* pusdest = reinterpret_cast(vid.buffer) + y * (vid.rowbytes >> 1) + x; for (v = 0; v < h; v++, pusdest += (vid.rowbytes >> 1)) { for (u = 0; u < w; u++) { pusdest[u] = static_cast(uc); @@ -778,7 +771,6 @@ Draw_FadeScreen void Draw_FadeScreen(void) { int x, y; - byte* pbuf; VID_UnlockBuffer(); S_ExtraUpdate(); @@ -787,7 +779,7 @@ void Draw_FadeScreen(void) for (y = 0; y < (int)vid.height; y++) { int t; - pbuf = (byte*)(vid.buffer + vid.rowbytes * y); + byte* pbuf = vid.buffer + vid.rowbytes * y; t = (y & 1) << 1; for (x = 0; x < (int)vid.width; x++) { diff --git a/src/draw.hpp b/src/draw.hpp index 27c7e9a..0b2c04f 100644 --- a/src/draw.hpp +++ b/src/draw.hpp @@ -8,9 +8,9 @@ extern qpic_t* draw_disc; void Draw_Init(void); void Draw_Character(int x, int y, int num); -void Draw_Pic(int x, int y, qpic_t* pic); -void Draw_TransPic(int x, int y, qpic_t* pic); -void Draw_TransPicTranslate(int x, int y, qpic_t* pic, byte* translation); +void Draw_Pic(int x, int y, const qpic_t* pic); +void Draw_TransPic(int x, int y, const qpic_t* pic); +void Draw_TransPicTranslate(int x, int y, const qpic_t* pic, const byte* translation); void Draw_ConsoleBackground(int lines); void Draw_BeginDisc(void); void Draw_EndDisc(void); diff --git a/src/host.cpp b/src/host.cpp index 941ef1a..ae34f20 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -77,7 +77,7 @@ Host_EndGame char string[1024]; va_start(argptr, message); - vsprintf_s(string, sizeof(string), message, argptr); + vsnprintf(string, sizeof(string), message, argptr); va_end(argptr); Con_DPrintf("Host_EndGame: %s\n", string); @@ -120,7 +120,7 @@ This shuts down both the client and server SCR_EndLoadingPlaque(); // reenable screen updates va_start(argptr, error); - vsprintf_s(string, sizeof(string), error, argptr); + vsnprintf(string, sizeof(string), error, argptr); va_end(argptr); Con_Printf("Host_Error: %s\n", string); @@ -187,7 +187,7 @@ void Host_FindMaxClients(void) svs.maxclientslimit = 4; } - svs.clients = (client_s *) Hunk_Alloc(svs.maxclientslimit * sizeof(client_t), "clients"); + svs.clients = static_cast(Hunk_Alloc(svs.maxclientslimit * sizeof(client_t), "clients")); if (svs.maxclients > 1) { Cvar::SetValue("deathmatch", 1.0); @@ -244,7 +244,7 @@ void Host_WriteConfiguration(void) // dedicated servers initialize the host but don't parse and set the // config.cfg cvars if (host_initialized & !isDedicated) { - fopen_s(&f, va("%s/config.cfg", com_gamedir), "w"); + f = fopen(va("%s/config.cfg", com_gamedir), "w"); if (!f) { Con_Printf("Couldn't write config.cfg.\n"); @@ -278,7 +278,7 @@ void SV_ClientPrintf(const char* fmt, ...) char string[1024]; va_start(argptr, fmt); - vsprintf_s(string, sizeof(string), fmt, argptr); + vsnprintf(string, sizeof(string), fmt, argptr); va_end(argptr); MSG_WriteByte(&host_client->message, svc_print); @@ -299,7 +299,7 @@ void SV_BroadcastPrintf(const char* fmt, ...) int i; va_start(argptr, fmt); - vsprintf_s(string, sizeof(string), fmt, argptr); + vsnprintf(string, sizeof(string), fmt, argptr); va_end(argptr); for (i = 0; i < svs.maxclients; i++) { @@ -322,7 +322,6 @@ if (crash = true), don't bother sending signofs */ void SV_DropClient(qboolean crash) { - int saveSelf; int i; client_t* client; @@ -336,7 +335,7 @@ void SV_DropClient(qboolean crash) if (host_client->edict && host_client->spawned) { // call the prog function for removing a client // this will set the body to a dead frame, among other things - saveSelf = pr_global_struct->self; + int saveSelf = pr_global_struct->self; pr_global_struct->self = static_cast(EDICT_TO_PROG(host_client->edict)); PR_ExecuteProgram(pr_global_struct->ClientDisconnect); pr_global_struct->self = saveSelf; @@ -390,7 +389,7 @@ void Host_ClientCommands(const char* fmt, ...) char string[1024]; va_start(argptr, fmt); - vsprintf_s(string, sizeof(string), fmt, argptr); + vsnprintf(string, sizeof(string), fmt, argptr); va_end(argptr); MSG_WriteByte(&host_client->message, svc_stufftext); @@ -409,7 +408,7 @@ void Host_ShutdownServer(qboolean crash) int i; int count; sizebuf_t buf; - char message[4]; + char message[4] = {}; double start; if (!sv.active) { @@ -445,7 +444,7 @@ void Host_ShutdownServer(qboolean crash) } while (count); // make sure all the clients know we're disconnecting - buf.data = (byte*)message; + buf.data = reinterpret_cast(message); buf.maxsize = 4; buf.cursize = 0; MSG_WriteByte(&buf, svc_disconnect); @@ -537,10 +536,8 @@ Add them exactly as if they had been typed at the console */ void Host_GetConsoleCommands(void) { - char* cmd; - while (1) { - cmd = Sys_ConsoleInput(); + char* cmd = Sys_ConsoleInput(); if (!cmd) { break; } @@ -640,14 +637,10 @@ Runs all active servers */ void _Host_Frame(float time) { - static double time1 = 0; - static double time2 = 0; - static double time3 = 0; - int pass1, pass2, pass3; try { // keep the random time dependent - rand(); + (void)rand(); // decide the simulation time if (!Host_FilterTime(time)) { @@ -703,12 +696,14 @@ void _Host_Frame(float time) } // update video + double time1 = 0; if (host_speeds.value) { time1 = Sys_FloatTime(); } SCR_UpdateScreen(); + double time2 = 0; if (host_speeds.value) { time2 = Sys_FloatTime(); } @@ -724,10 +719,11 @@ void _Host_Frame(float time) CDAudio_Update(); if (host_speeds.value) { - pass1 = static_cast((time1 - time3) * 1000); + static double time3 = 0; + int pass1 = static_cast((time1 - time3) * 1000); time3 = Sys_FloatTime(); - pass2 = static_cast((time2 - time1) * 1000); - pass3 = static_cast((time3 - time2) * 1000); + int pass2 = static_cast((time2 - time1) * 1000); + int pass3 = static_cast((time3 - time2) * 1000); Con_Printf("%3i tot %3i server %3i gfx %3i snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3); } @@ -802,11 +798,11 @@ void Host_InitVCR(quakeparms_t* parms) } Sys_FileRead(vcrFile, &com_argc, sizeof(int)); - com_argv = (char**)malloc(com_argc * sizeof(char*)); + com_argv = static_cast(malloc(com_argc * sizeof(char*))); com_argv[0] = parms->argv[0]; for (i = 0; i < com_argc; i++) { Sys_FileRead(vcrFile, &len, sizeof(int)); - p = (char*)malloc(len); + p = static_cast(malloc(len)); Sys_FileRead(vcrFile, p, len); com_argv[i + 1] = p; } @@ -890,12 +886,12 @@ void Host_Init(quakeparms_t* parms) R_InitTextures(); // needed even for dedicated servers if (cls.state != ca_dedicated) { - host_basepal = (byte*)COM_LoadHunkFile("gfx/palette.lmp"); + host_basepal = COM_LoadHunkFile("gfx/palette.lmp"); if (!host_basepal) { Sys_Error("Couldn't load gfx/palette.lmp"); } - host_colormap = (byte*)COM_LoadHunkFile("gfx/colormap.lmp"); + host_colormap = COM_LoadHunkFile("gfx/colormap.lmp"); if (!host_colormap) { Sys_Error("Couldn't load gfx/colormap.lmp"); } diff --git a/src/host_cmd.cpp b/src/host_cmd.cpp index cd318bc..00f0533 100644 --- a/src/host_cmd.cpp +++ b/src/host_cmd.cpp @@ -288,7 +288,7 @@ void Host_Map_f(void) Q_strcat(cls.mapstring, Cmd::Argv(i)); Q_strcat(cls.mapstring, " "); } - strcat_s(cls.mapstring, sizeof(cls.mapstring), "\n"); + strlcat(cls.mapstring, "\n", sizeof(cls.mapstring)); svs.serverflags = 0; // haven't completed an episode yet Q_strcpy(name, Cmd::Argv(1)); @@ -298,7 +298,7 @@ void Host_Map_f(void) } if (cls.state != ca_dedicated) { - strcpy_s(cls.spawnparms, sizeof(cls.spawnparms), ""); + strlcpy(cls.spawnparms, "", sizeof(cls.spawnparms)); for (i = 2; i < Cmd::Argc(); i++) { Q_strcat(cls.spawnparms, Cmd::Argv(i)); @@ -356,7 +356,7 @@ void Host_Restart_f(void) return; } - strcpy_s(mapname, sizeof(mapname), sv.name); // must copy out, because it gets cleared + strlcpy(mapname, sv.name, sizeof(mapname)); // must copy out, because it gets cleared // in sv_spawnserver SV_SpawnServer(mapname); } @@ -423,7 +423,7 @@ void Host_SavegameComment(char* text) text[i] = ' '; } memcpy(text, cl.levelname, strlen(cl.levelname)); - sprintf_s(kills, sizeof(kills), "kills:%3i/%3i", cl.stats[STAT_MONSTERS], + snprintf(kills, sizeof(kills), "kills:%3i/%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]); memcpy(text + 22, kills, strlen(kills)); // convert space to _ to make stdio happy @@ -489,11 +489,11 @@ void Host_Savegame_f(void) } } - sprintf_s(name, sizeof(name), "%s/%s", com_gamedir, std::string(Cmd::Argv(1)).c_str()); + snprintf(name, sizeof(name), "%s/%s", com_gamedir, std::string(Cmd::Argv(1)).c_str()); COM_DefaultExtension(name, ".sav"); Con_Printf("Saving game to %s...\n", name); - fopen_s(&f, name, "w"); + f = fopen(name, "w"); if (!f) { Con_Printf("ERROR: couldn't open.\n"); @@ -540,8 +540,8 @@ void Host_Loadgame_f(void) FILE* f; char mapname[MAX_QPATH]; float time, tfloat; - char str[32768], *start; - int i, r; + char str[32768]; + int i; edict_t* ent; int entnum; int version; @@ -559,7 +559,7 @@ void Host_Loadgame_f(void) cls.demonum = -1; // stop demo loop in case this fails - sprintf_s(name, sizeof(name), "%s/%s", com_gamedir, std::string(Cmd::Argv(1)).c_str()); + snprintf(name, sizeof(name), "%s/%s", com_gamedir, std::string(Cmd::Argv(1)).c_str()); COM_DefaultExtension(name, ".sav"); // we can't call SCR_BeginLoadingPlaque, because too much stack space has @@ -567,14 +567,14 @@ void Host_Loadgame_f(void) // SCR_BeginLoadingPlaque (); Con_Printf("Loading game from %s...\n", name); - fopen_s(&f, name, "r"); + f = fopen(name, "r"); if (!f) { Con_Printf("ERROR: couldn't open.\n"); return; } - fscanf_s(f, "%i\n", &version); + fscanf(f, "%i\n", &version); if (version != SAVEGAME_VERSION) { fclose(f); Con_Printf("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION); @@ -582,18 +582,18 @@ void Host_Loadgame_f(void) return; } - fscanf_s(f, "%s\n", str, (unsigned)sizeof(str)); + fscanf(f, "%s\n", str, (unsigned)sizeof(str)); for (i = 0; i < NUM_SPAWN_PARMS; i++) { - fscanf_s(f, "%f\n", &spawn_parms[i]); + fscanf(f, "%f\n", &spawn_parms[i]); } // this silliness is so we can load 1.06 save files, which have float skill values - fscanf_s(f, "%f\n", &tfloat); + fscanf(f, "%f\n", &tfloat); current_skill = (int)(tfloat + 0.1); Cvar::SetValue("skill", (float)current_skill); - fscanf_s(f, "%s\n", mapname, (unsigned)sizeof(mapname)); - fscanf_s(f, "%f\n", &time); + fscanf(f, "%s\n", mapname, (unsigned)sizeof(mapname)); + fscanf(f, "%f\n", &time); CL_Disconnect_f(); @@ -610,16 +610,16 @@ void Host_Loadgame_f(void) // load the light styles for (i = 0; i < MAX_LIGHTSTYLES; i++) { - fscanf_s(f, "%s\n", str, (unsigned)sizeof(str)); + fscanf(f, "%s\n", str, (unsigned)sizeof(str)); sv.lightstyles[i] = (char *) Hunk_Alloc((int)strlen(str) + 1); - strcpy_s(sv.lightstyles[i], strlen(str) + 1, str); + strlcpy(sv.lightstyles[i], str, strlen(str) + 1); } // load the edicts out of the savegame file entnum = -1; // -1 is the globals while (!feof(f)) { for (i = 0; i < static_cast(sizeof(str) - 1); i++) { - r = fgetc(f); + int r = fgetc(f); if (r == EOF || !r) { break; } @@ -635,7 +635,7 @@ void Host_Loadgame_f(void) } str[i] = 0; - start = COM_Parse(str); + const char* start = COM_Parse(str); if (!com_token[0]) { break; // end of file } @@ -645,13 +645,13 @@ void Host_Loadgame_f(void) } if (entnum == -1) { // parse the global vars - ED_ParseGlobals(start); + ED_ParseGlobals(const_cast(start)); } else { // parse an edict ent = EDICT_NUM(entnum); std::memset(reinterpret_cast(&ent->v), 0, static_cast(progs->entityfields) * 4); ent->free = false; - ED_ParseEdict(start, ent); + ED_ParseEdict(const_cast(start), ent); // link it into the bsp tree if (!ent->free) { @@ -778,19 +778,19 @@ void Host_Say(qboolean teamonly) // turn on color set 1 if (!fromServer) { - sprintf_s((char*)text, sizeof(text), "%c%s: ", 1, save->name); + snprintf((char*)text, sizeof(text), "%c%s: ", 1, save->name); } else { - sprintf_s((char*)text, sizeof(text), "%c<%s> ", 1, hostname.string); + snprintf((char*)text, sizeof(text), "%c<%s> ", 1, hostname.string); } - j = sizeof(text) - 2 - Q_strlen((char*)text); // -2 for /n and null terminator + j = sizeof(text) - 2 - Q_strlen(reinterpret_cast(text)); // -2 for /n and null terminator if (arg_str.length() > (size_t)j) { arg_str.resize(j); } const char* p = arg_str.c_str(); - strcat_s((char*)text, sizeof(text), p); - strcat_s((char*)text, sizeof(text), "\n"); + strlcat((char*)text, p, sizeof(text)); + strlcat((char*)text, "\n", sizeof(text)); for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++) { if (!client || !client->active || !client->spawned) { @@ -846,8 +846,8 @@ void Host_Tell_f(void) } const char* p = arg_str.c_str(); - strcat_s(text, sizeof(text), p); - strcat_s(text, sizeof(text), "\n"); + strlcat(text, p, sizeof(text)); + strlcat(text, "\n", sizeof(text)); save = host_client; for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++) { @@ -1151,8 +1151,6 @@ Kicks a user off of the server */ void Host_Kick_f(void) { - const char* who; - const char* message = NULL; client_t* save; int i; qboolean byNumber = false; @@ -1196,6 +1194,8 @@ void Host_Kick_f(void) } if (i < svs.maxclients) { + const char* who; + const char* message = nullptr; if (Cmd::state.source == Cmd::Source::Command) { if (cls.state == ca_dedicated) { who = "Console"; @@ -1222,7 +1222,7 @@ void Host_Kick_f(void) message += Cmd::Argv(2).length(); // skip the number } - while (*message && *message == ' ') { + while (*message == ' ') { message++; } } @@ -1461,7 +1461,7 @@ void Host_Viewframe_f(void) return; } - m = cl.model_precache[(int)e->v.modelindex]; + m = cl.model_precache[static_cast(e->v.modelindex)]; f = Q_atoi(Cmd::Argv(1)); if (f >= m->numframes) { @@ -1476,7 +1476,7 @@ void PrintFrameName(model_t* m, int frame) aliashdr_t* hdr; maliasframedesc_t* pframedesc; - hdr = (aliashdr_t*)Mod_Extradata(m); + hdr = static_cast(Mod_Extradata(m)); if (!hdr) { return; } diff --git a/src/keys.cpp b/src/keys.cpp index 6bd5bb0..04d8833 100644 --- a/src/keys.cpp +++ b/src/keys.cpp @@ -378,13 +378,13 @@ FIXME: handle quote special (general escape sequence?) const char* Key_KeynumToString(int keynum) { keyname_t* kn; - static char tinystr[2]; if (keynum == -1) { return ""; } if (keynum > 32 && keynum < 127) { // printable ascii + static char tinystr[2]; tinystr[0] = static_cast(keynum); tinystr[1] = 0; @@ -422,7 +422,7 @@ void Key_SetBinding(int keynum, const char* binding) // allocate memory for new binding l = Q_strlen(binding); - new_binding = (char*)Z_Malloc(l + 1); + new_binding = static_cast(Z_Malloc(l + 1)); Q_strcpy(new_binding, binding); new_binding[l] = 0; keybindings[keynum] = new_binding; @@ -687,14 +687,14 @@ void Key_Event(int key, qboolean down) if (!down) { kb = keybindings[key]; if (kb && kb[0] == '+') { - sprintf_s(cmd, sizeof(cmd), "-%s %i\n", kb + 1, key); + snprintf(cmd, sizeof(cmd), "-%s %i\n", kb + 1, key); Cmd::BufferAddText(cmd); } if (keyshift[key] != key) { kb = keybindings[keyshift[key]]; if (kb && kb[0] == '+') { - sprintf_s(cmd, sizeof(cmd), "-%s %i\n", kb + 1, key); + snprintf(cmd, sizeof(cmd), "-%s %i\n", kb + 1, key); Cmd::BufferAddText(cmd); } } @@ -705,7 +705,7 @@ void Key_Event(int key, qboolean down) // // during demo playback, most keys bring up the main menu // - if (cls.demoplayback && down && consolekeys[key] && key_dest == key_game) { + if (cls.demoplayback && consolekeys[key] && key_dest == key_game) { M_ToggleMenu_f(); return; @@ -718,7 +718,7 @@ void Key_Event(int key, qboolean down) kb = keybindings[key]; if (kb) { if (kb[0] == '+') { // button commands add keynum as a parm - sprintf_s(cmd, sizeof(cmd), "%s %i\n", kb, key); + snprintf(cmd, sizeof(cmd), "%s %i\n", kb, key); Cmd::BufferAddText(cmd); } else { Cmd::BufferAddText(kb); diff --git a/src/mathlib.cpp b/src/mathlib.cpp index f9787d4..8dc1060 100644 --- a/src/mathlib.cpp +++ b/src/mathlib.cpp @@ -63,7 +63,7 @@ void BOPS_Error(void) R_ConcatRotations ================ */ -void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3]) +void R_ConcatRotations(const float in1[3][3], const float in2[3][3], float out[3][3]) { out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; @@ -81,7 +81,7 @@ void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3]) R_ConcatTransforms ================ */ -void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4]) +void R_ConcatTransforms(const float in1[3][4], const float in2[3][4], float out[3][4]) { out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1]; diff --git a/src/mathlib.hpp b/src/mathlib.hpp index b016ffc..dbfdcc2 100644 --- a/src/mathlib.hpp +++ b/src/mathlib.hpp @@ -13,10 +13,10 @@ struct Vector3 { // Array subscript operators constexpr float operator[](size_t index) const { - return (&x)[index]; + return (index == 0) ? x : ((index == 1) ? y : z); } constexpr float& operator[](size_t index) { - return (&x)[index]; + return (index == 0) ? x : ((index == 1) ? y : z); } // Implicit conversions to raw pointers @@ -105,7 +105,7 @@ typedef int fixed16_t; struct mplane_s; -#define IS_NAN(x) (((*(int*)&x) & nanmask) == nanmask) +#define IS_NAN(x) std::isnan(x) // Modern C++ template functions replacing legacy macros template @@ -185,8 +185,8 @@ inline void VectorScale(const T& in, vec_t scale, U&& out) { out[2] = in[2] * scale; } -void R_ConcatRotations(float in1[3][3], float in2[3][3], float out[3][3]); -void R_ConcatTransforms(float in1[3][4], float in2[3][4], float out[3][4]); +void R_ConcatRotations(const float in1[3][3], const float in2[3][3], float out[3][3]); +void R_ConcatTransforms(const float in1[3][4], const float in2[3][4], float out[3][4]); void FloorDivMod(double numer, double denom, int* quotient, int* rem); int GreatestCommonDivisor(int i1, int i2); diff --git a/src/menu.cpp b/src/menu.cpp index 4f553b7..d275c80 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -166,7 +166,7 @@ inline void M_DrawTransPic(int x, int y, qpic_t* pic) Draw_TransPic(x + ((vid.width - 320) >> 1), y, pic); } -void M_DrawPic(int x, int y, qpic_t* pic) +void M_DrawPic(int x, int y, const qpic_t* pic) { Draw_Pic(x + ((vid.width - 320) >> 1), y, pic); } @@ -486,17 +486,17 @@ void M_ScanSaves(void) int version; for (i = 0; i < MAX_SAVEGAMES; i++) { - strcpy_s(m_filenames[i], sizeof(m_filenames[i]), "--- UNUSED SLOT ---"); + strlcpy(m_filenames[i], "--- UNUSED SLOT ---", sizeof(m_filenames[i])); loadable[i] = false; - sprintf_s(name, sizeof(name), "%s/s%i.sav", com_gamedir, i); - fopen_s(&f, name, "r"); + snprintf(name, sizeof(name), "%s/s%i.sav", com_gamedir, i); + f = fopen(name, "r"); if (!f) { continue; } - fscanf_s(f, "%i\n", &version); - fscanf_s(f, "%79s\n", name, (unsigned)sizeof(name)); - strncpy_s(m_filenames[i], sizeof(m_filenames[i]), name, sizeof(m_filenames[i]) - 1); + fscanf(f, "%i\n", &version); + fscanf(f, "%79s\n", name, (unsigned)sizeof(name)); + strlcpy(m_filenames[i], name, sizeof(m_filenames[i]) - 1); // change _ back to space for (j = 0; j < SAVEGAME_COMMENT_LENGTH; j++) { @@ -1510,7 +1510,7 @@ void M_Keys_Key(int k) if (k == K_ESCAPE) { bind_grab = false; } else if (k != '`') { - sprintf_s(cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(k), + snprintf(cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(k), bindnames[keys_cursor][0]); Cmd::BufferInsertText(cmd); } @@ -2177,7 +2177,7 @@ void M_Menu_LanConfig_f(void) } lanConfig_port = DEFAULTnet_hostport; - sprintf_s(lanConfig_portname, sizeof(lanConfig_portname), "%u", lanConfig_port); + snprintf(lanConfig_portname, sizeof(lanConfig_portname), "%u", lanConfig_port); m_return_onerror = false; m_return_reason[0] = 0; @@ -2360,7 +2360,7 @@ void M_LanConfig_Key(int key) lanConfig_port = l; } - sprintf_s(lanConfig_portname, sizeof(lanConfig_portname), "%u", lanConfig_port); + snprintf(lanConfig_portname, sizeof(lanConfig_portname), "%u", lanConfig_port); } //============================================================================= @@ -2965,10 +2965,10 @@ void M_ServerList_Draw(void) M_DrawPic((320 - p->width) / 2, 4, p); for (n = 0; n < hostCacheCount; n++) { if (hostcache[n].maxusers) { - sprintf_s(string, sizeof(string), "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, + snprintf(string, sizeof(string), "%-15.15s %-15.15s %2u/%2u\n", hostcache[n].name, hostcache[n].map, hostcache[n].users, hostcache[n].maxusers); } else { - sprintf_s(string, sizeof(string), "%-15.15s %-15.15s\n", hostcache[n].name, + snprintf(string, sizeof(string), "%-15.15s %-15.15s\n", hostcache[n].name, hostcache[n].map); } diff --git a/src/menu.hpp b/src/menu.hpp index 913445a..3a4fac4 100644 --- a/src/menu.hpp +++ b/src/menu.hpp @@ -14,7 +14,7 @@ void M_ToggleMenu_f(void); void M_Menu_Main_f(void); void M_Menu_Quit_f(void); -void M_DrawPic(int x, int y, qpic_t* pic); +void M_DrawPic(int x, int y, const qpic_t* pic); extern int m_state; extern int m_return_state; diff --git a/src/model.cpp b/src/model.cpp index ed0290a..8d97b1d 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -237,7 +237,7 @@ model_t* Mod_FindName(const char* name) mod_numknown++; } - strcpy_s(mod->name, sizeof(mod->name), name); + strlcpy(mod->name, name, sizeof(mod->name)); mod->needload = NL_NEEDS_LOADED; } @@ -1247,10 +1247,10 @@ void Mod_LoadBrushModel(model_t* mod, void* buffer) if (i < mod->numsubmodels - 1) { // duplicate the basic information char name[10]; - sprintf_s(name, sizeof(name), "*%i", i + 1); + snprintf(name, sizeof(name), "*%i", i + 1); loadmodel = Mod_FindName(name); *loadmodel = *mod; - strcpy_s(loadmodel->name, sizeof(loadmodel->name), name); + strlcpy(loadmodel->name, name, sizeof(loadmodel->name)); mod = loadmodel; } } @@ -1283,7 +1283,7 @@ void* Mod_LoadAliasFrame(void* pin, pdaliasframe = (daliasframe_t*)pin; - strcpy_s(name, 16, pdaliasframe->name); + strlcpy(name, pdaliasframe->name, 16); for (i = 0; i < 3; i++) { // these are byte values, so we don't have to worry about diff --git a/src/model.hpp b/src/model.hpp index 85547d3..3b196ee 100644 --- a/src/model.hpp +++ b/src/model.hpp @@ -38,10 +38,10 @@ typedef struct { // !!! if this is changed, it must be changed in asm_i386.h too !!! typedef struct mplane_s { Vector3 normal; - float dist; - byte type; // for texture axis selection and fast side tests - byte signbits; // signx + signy<<1 + signz<<1 - byte pad[2]; + float dist = 0.0f; + byte type = 0; // for texture axis selection and fast side tests + byte signbits = 0; // signx + signy<<1 + signz<<1 + byte pad[2] = {}; } mplane_t; typedef struct texture_s { @@ -75,28 +75,28 @@ typedef struct { } mtexinfo_t; typedef struct msurface_s { - int visframe; // should be drawn when node is crossed + int visframe = 0; // should be drawn when node is crossed - int dlightframe; - int dlightbits; + int dlightframe = 0; + int dlightbits = 0; - mplane_t* plane; - int flags; + mplane_t* plane = nullptr; + int flags = 0; - int firstedge; // look up in model->surfedges[], negative numbers - int numedges; // are backwards edges + int firstedge = 0; // look up in model->surfedges[], negative numbers + int numedges = 0; // are backwards edges // surface generation data - struct surfcache_s* cachespots[MIPLEVELS]; + struct surfcache_s* cachespots[MIPLEVELS] = {}; - short texturemins[2]; - short extents[2]; + short texturemins[2] = {}; + short extents[2] = {}; - mtexinfo_t* texinfo; + mtexinfo_t* texinfo = nullptr; // lighting info - byte styles[MAXLIGHTMAPS]; - byte* samples; // [numstyles*surfsize] + byte styles[MAXLIGHTMAPS] = {}; + byte* samples = nullptr; // [numstyles*surfsize] } msurface_t; typedef struct mnode_s { @@ -118,29 +118,29 @@ typedef struct mnode_s { typedef struct mleaf_s { // common with node - int contents; // wil be a negative contents number - int visframe; // node needs to be traversed if current + int contents = 0; // wil be a negative contents number + int visframe = 0; // node needs to be traversed if current - short minmaxs[6]; // for bounding box culling + short minmaxs[6] = {}; // for bounding box culling - struct mnode_s* parent; + struct mnode_s* parent = nullptr; // leaf specific - byte* compressed_vis; - efrag_t* efrags; + byte* compressed_vis = nullptr; + efrag_t* efrags = nullptr; - msurface_t** firstmarksurface; - int nummarksurfaces; - int key; // BSP sequence number for leaf's contents - byte ambient_sound_level[NUM_AMBIENTS]; + msurface_t** firstmarksurface = nullptr; + int nummarksurfaces = 0; + int key = 0; // BSP sequence number for leaf's contents + byte ambient_sound_level[NUM_AMBIENTS] = {}; } mleaf_t; // !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct { - dclipnode_t* clipnodes; - mplane_t* planes; - int firstclipnode; - int lastclipnode; +typedef struct hull_s { + dclipnode_t* clipnodes = nullptr; + mplane_t* planes = nullptr; + int firstclipnode = 0; + int lastclipnode = 0; Vector3 clip_mins; Vector3 clip_maxs; } hull_t; @@ -155,17 +155,17 @@ SPRITE MODELS // FIXME: shorten these? typedef struct mspriteframe_s { - int width; - int height; - void* pcachespot; // remove? - float up, down, left, right; - byte pixels[4]; + int width = 0; + int height = 0; + void* pcachespot = nullptr; // remove? + float up = 0.0f, down = 0.0f, left = 0.0f, right = 0.0f; + byte pixels[4] = {}; } mspriteframe_t; -typedef struct { - int numframes; - float* intervals; - mspriteframe_t* frames[1]; +typedef struct mspritegroup_s { + int numframes = 0; + float* intervals = nullptr; + mspriteframe_t* frames[1] = {}; } mspritegroup_t; typedef struct { @@ -192,12 +192,12 @@ Alias models are position independent, so the cache manager can move them. ============================================================================== */ -typedef struct { - aliasframetype_t type; - trivertx_t bboxmin; - trivertx_t bboxmax; - int frame; - char name[16]; +typedef struct maliasframedesc_s { + aliasframetype_t type = {}; + trivertx_t bboxmin = {}; + trivertx_t bboxmax = {}; + int frame = 0; + char name[16] = {}; } maliasframedesc_t; typedef struct { @@ -206,16 +206,16 @@ typedef struct { int skin; } maliasskindesc_t; -typedef struct { - trivertx_t bboxmin; - trivertx_t bboxmax; - int frame; +typedef struct maliasgroupframedesc_s { + trivertx_t bboxmin = {}; + trivertx_t bboxmax = {}; + int frame = 0; } maliasgroupframedesc_t; -typedef struct { - int numframes; - int intervals; - maliasgroupframedesc_t frames[1]; +typedef struct maliasgroup_s { + int numframes = 0; + int intervals = 0; + maliasgroupframedesc_t frames[1] = {}; } maliasgroup_t; typedef struct { @@ -230,12 +230,12 @@ typedef struct mtriangle_s { int vertindex[3]; } mtriangle_t; -typedef struct { - int model; - int stverts; - int skindesc; - int triangles; - maliasframedesc_t frames[1]; +typedef struct aliashdr_s { + int model = 0; + int stverts = 0; + int skindesc = 0; + int triangles = 0; + maliasframedesc_t frames[1] = {}; } aliashdr_t; //=================================================================== @@ -258,72 +258,72 @@ typedef enum { mod_brush, #define EF_TRACER3 128 // purple trail typedef struct model_s { - char name[MAX_QPATH]; - int needload; // bmodels and sprites don't cache normally + char name[MAX_QPATH] = {}; + int needload = 0; // bmodels and sprites don't cache normally - modtype_t type; - int numframes; - synctype_t synctype; + modtype_t type = {}; + int numframes = 0; + synctype_t synctype = {}; - int flags; + int flags = 0; // // volume occupied by the model // Vector3 mins, maxs; - float radius; + float radius = 0.0f; // // brush model // - int firstmodelsurface, nummodelsurfaces; + int firstmodelsurface = 0, nummodelsurfaces = 0; - int numsubmodels; - dmodel_t* submodels; + int numsubmodels = 0; + dmodel_t* submodels = nullptr; - int numplanes; - mplane_t* planes; + int numplanes = 0; + mplane_t* planes = nullptr; - int numleafs; // number of visible leafs, not counting 0 - mleaf_t* leafs; + int numleafs = 0; // number of visible leafs, not counting 0 + mleaf_t* leafs = nullptr; - int numvertexes; - mvertex_t* vertexes; + int numvertexes = 0; + mvertex_t* vertexes = nullptr; - int numedges; - medge_t* edges; + int numedges = 0; + medge_t* edges = nullptr; - int numnodes; - mnode_t* nodes; + int numnodes = 0; + mnode_t* nodes = nullptr; - int numtexinfo; - mtexinfo_t* texinfo; + int numtexinfo = 0; + mtexinfo_t* texinfo = nullptr; - int numsurfaces; - msurface_t* surfaces; + int numsurfaces = 0; + msurface_t* surfaces = nullptr; - int numsurfedges; - int* surfedges; + int numsurfedges = 0; + int* surfedges = nullptr; - int numclipnodes; - dclipnode_t* clipnodes; + int numclipnodes = 0; + dclipnode_t* clipnodes = nullptr; - int nummarksurfaces; - msurface_t** marksurfaces; + int nummarksurfaces = 0; + msurface_t** marksurfaces = nullptr; - hull_t hulls[MAX_MAP_HULLS]; + hull_t hulls[MAX_MAP_HULLS] = {}; - int numtextures; - texture_t** textures; + int numtextures = 0; + texture_t** textures = nullptr; - byte* visdata; - byte* lightdata; - char* entities; + byte* visdata = nullptr; + byte* lightdata = nullptr; + char* entities = nullptr; // // additional model data // - cache_user_t cache; // only access through Mod_Extradata + cache_user_t cache = {}; // only access through Mod_Extradata } model_t; diff --git a/src/network.cpp b/src/network.cpp index a36ed70..7e92dd1 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -580,7 +580,7 @@ static int PartialIPAddress(const char* in, struct qsockaddr* hostaddr) buff[0] = '.'; b = buff; - strcpy_s(buff + 1, sizeof(buff) - 1, in); + strlcpy(buff + 1, in, sizeof(buff) - 1); if (buff[1] == '.') { b++; } @@ -726,7 +726,7 @@ char* UDP_AddrToString(struct qsockaddr* addr) int haddr; haddr = ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr); - sprintf_s(buffer, sizeof(buffer), "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, + snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in*)addr)->sin_port)); @@ -740,7 +740,7 @@ int UDP_StringToAddr(const char* string, struct qsockaddr* addr) int ha1, ha2, ha3, ha4, hp; int ipaddr; - sscanf_s(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); + sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp); ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4; addr->sa_family = AF_INET; @@ -895,7 +895,7 @@ char* StrAddr(struct qsockaddr* addr) int n; for (n = 0; n < 16; n++) { - sprintf_s(buf + n * 2, sizeof(buf) - n * 2, "%02x", *p++); + snprintf(buf + n * 2, sizeof(buf) - n * 2, "%02x", *p++); } return buf; diff --git a/src/quakedef.hpp b/src/quakedef.hpp index d98003d..e99b313 100644 --- a/src/quakedef.hpp +++ b/src/quakedef.hpp @@ -13,6 +13,7 @@ #define GAMENAME "id1" +#include #include #include #include @@ -168,14 +169,14 @@ inline void VID_UnlockBuffer(void) {} #include "zone.hpp" #include "mathlib.hpp" -typedef struct { +typedef struct entity_state_s { Vector3 origin; Vector3 angles; - int modelindex; - int frame; - int colormap; - int skin; - int effects; + int modelindex = 0; + int frame = 0; + int colormap = 0; + int skin = 0; + int effects = 0; } entity_state_t; #include "wad.hpp" diff --git a/src/renderer.cpp b/src/renderer.cpp index f547907..239a0b3 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -732,7 +732,7 @@ void R_ReadPointFile_f(void) particle_t* p; char name[MAX_OSPATH]; - sprintf_s(name, sizeof(name), "maps/%s.pts", sv.name); + snprintf(name, sizeof(name), "maps/%s.pts", sv.name); COM_FOpenFile(name, &f); if (!f) { @@ -744,7 +744,7 @@ void R_ReadPointFile_f(void) Con_Printf("Reading %s...\n", name); c = 0; for (;;) { - r = fscanf_s(f, "%f %f %f\n", &org[0], &org[1], &org[2]); + r = fscanf(f, "%f %f %f\n", &org[0], &org[1], &org[2]); if (r != 3) { break; } diff --git a/src/renderer.hpp b/src/renderer.hpp index 675368e..edaba37 100644 --- a/src/renderer.hpp +++ b/src/renderer.hpp @@ -16,65 +16,65 @@ typedef struct efrag_s { } efrag_t; typedef struct entity_s { - qboolean forcelink; // model changed + qboolean forcelink = false; // model changed - int update_type; + int update_type = 0; - entity_state_t baseline; // to fill in defaults in updates + entity_state_t baseline = {}; // to fill in defaults in updates - double msgtime; // time of last update + double msgtime = 0.0; // time of last update Vector3 msg_origins[2]; // last two updates (0 is newest) Vector3 origin; Vector3 msg_angles[2]; // last two updates (0 is newest) Vector3 angles; - struct model_s* model; // NULL = no model - struct efrag_s* efrag; // linked list of efrags - int frame; - float syncbase; // for client-side animations - byte* colormap; - int effects; // light, particals, etc - int skinnum; // for Alias models - int visframe; // last frame this entity was + struct model_s* model = nullptr; // NULL = no model + struct efrag_s* efrag = nullptr; // linked list of efrags + int frame = 0; + float syncbase = 0.0f; // for client-side animations + byte* colormap = nullptr; + int effects = 0; // light, particals, etc + int skinnum = 0; // for Alias models + int visframe = 0; // last frame this entity was // found in an active leaf - int dlightframe; // dynamic lighting - int dlightbits; + int dlightframe = 0; // dynamic lighting + int dlightbits = 0; // FIXME: could turn these into a union - int trivial_accept; - struct mnode_s* topnode; // for bmodels, first world node + int trivial_accept = 0; + struct mnode_s* topnode = nullptr; // for bmodels, first world node // that splits bmodel, or NULL if // not split } entity_t; // !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct { - vrect_t vrect; // subwindow in video for refresh +typedef struct refdef_s { + vrect_t vrect = {}; // subwindow in video for refresh // FIXME: not need vrect next field here? - vrect_t aliasvrect; // scaled Alias version - int vrectright, vrectbottom; // right & bottom screen coords - int aliasvrectright, aliasvrectbottom; // scaled Alias versions - float vrectrightedge; // rightmost right edge we care about, + vrect_t aliasvrect = {}; // scaled Alias version + int vrectright = 0, vrectbottom = 0; // right & bottom screen coords + int aliasvrectright = 0, aliasvrectbottom = 0; // scaled Alias versions + float vrectrightedge = 0.0f; // rightmost right edge we care about, // for use in edge list - float fvrectx, fvrecty; // for floating-point compares - float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping - int64_t vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20 - int64_t vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20 - float fvrectright_adj, fvrectbottom_adj; + float fvrectx = 0.0f, fvrecty = 0.0f; // for floating-point compares + float fvrectx_adj = 0.0f, fvrecty_adj = 0.0f; // left and top edges, for clamping + int64_t vrect_x_adj_shift20 = 0; // (vrect.x + 0.5 - epsilon) << 20 + int64_t vrectright_adj_shift20 = 0; // (vrectright + 0.5 - epsilon) << 20 + float fvrectright_adj = 0.0f, fvrectbottom_adj = 0.0f; // right and bottom edges, for clamping - float fvrectright; // rightmost edge, for Alias clamping - float fvrectbottom; // bottommost edge, for Alias clamping - float horizontalFieldOfView; // at Z = 1.0, this many X is visible + float fvrectright = 0.0f; // rightmost edge, for Alias clamping + float fvrectbottom = 0.0f; // bottommost edge, for Alias clamping + float horizontalFieldOfView = 0.0f; // at Z = 1.0, this many X is visible // 2.0 = 90 degrees - float xOrigin; // should probably allways be 0.5 - float yOrigin; // between be around 0.3 to 0.5 + float xOrigin = 0.0f; // should probably allways be 0.5 + float yOrigin = 0.0f; // between be around 0.3 to 0.5 Vector3 vieworg; Vector3 viewangles; - float fov_x, fov_y; + float fov_x = 0.0f, fov_y = 0.0f; - int ambientlight; + int ambientlight = 0; } refdef_t; struct texture_s; @@ -124,6 +124,6 @@ int D_SurfaceCacheForRes(int width, int height); void D_FlushCaches(void); void D_DeleteSurfaceCache(void); void D_InitCaches(void* buffer, int size); -void R_SetVrect(vrect_t* pvrect, vrect_t* pvrectin, int lineadj); +void R_SetVrect(vrect_t* pvrectin, vrect_t* pvrect, int lineadj); } // namespace Render diff --git a/src/sbar.cpp b/src/sbar.cpp index abdd764..6cf83e2 100644 --- a/src/sbar.cpp +++ b/src/sbar.cpp @@ -260,7 +260,7 @@ void Sbar_Init(void) Sbar_DrawPic ============= */ -void Sbar_DrawPic(int x, int y, qpic_t* pic) +void Sbar_DrawPic(int x, int y, const qpic_t* pic) { if (cl.gametype == GAME_DEATHMATCH) { Draw_Pic(x /* + ((vid.width - 320)>>1)*/, y + (vid.height - SBAR_HEIGHT), @@ -275,7 +275,7 @@ void Sbar_DrawPic(int x, int y, qpic_t* pic) Sbar_DrawTransPic ============= */ -void Sbar_DrawTransPic(int x, int y, qpic_t* pic) +void Sbar_DrawTransPic(int x, int y, const qpic_t* pic) { if (cl.gametype == GAME_DEATHMATCH) { Draw_TransPic(x /*+ ((vid.width - 320)>>1)*/, @@ -309,7 +309,7 @@ void Sbar_DrawCharacter(int x, int y, int num) Sbar_DrawString ================ */ -void Sbar_DrawString(int x, int y, char* str) +void Sbar_DrawString(int x, int y, const char* str) { if (cl.gametype == GAME_DEATHMATCH) { Draw_String(x /*+ ((vid.width - 320)>>1)*/, y + vid.height - SBAR_HEIGHT, @@ -329,7 +329,6 @@ int Sbar_itoa(int num, char* buf) { char* str; int pow10; - int dig; str = buf; @@ -344,7 +343,7 @@ int Sbar_itoa(int num, char* buf) do { pow10 /= 10; - dig = num / pow10; + int dig = num / pow10; *str++ = static_cast('0' + dig); num -= dig * pow10; } while (pow10 != 1); @@ -405,7 +404,7 @@ Sbar_SortFrags */ void Sbar_SortFrags(void) { - int i, j, k; + int i, j; // sort by frags scoreboardlines = 0; @@ -419,7 +418,7 @@ void Sbar_SortFrags(void) for (i = 0; i < scoreboardlines; i++) { for (j = 0; j < scoreboardlines - 1 - i; j++) { if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j + 1]].frags) { - k = fragsort[j]; + int k = fragsort[j]; fragsort[j] = fragsort[j + 1]; fragsort[j + 1] = k; } @@ -429,7 +428,7 @@ void Sbar_SortFrags(void) int Sbar_ColorForMap(int m) { - return m < 128 ? m + 8 : m + 8; + return m + 8; } /* @@ -443,11 +442,11 @@ void Sbar_SoloScoreboard(void) int minutes, seconds, tens, units; int l; - sprintf_s(str, sizeof(str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], + snprintf(str, sizeof(str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]); Sbar_DrawString(8, 4, str); - sprintf_s(str, sizeof(str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS], + snprintf(str, sizeof(str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]); Sbar_DrawString(8, 12, str); @@ -456,7 +455,7 @@ void Sbar_SoloScoreboard(void) seconds = static_cast(cl.time - 60 * minutes); tens = seconds / 10; units = seconds - 10 * tens; - sprintf_s(str, sizeof(str), "Time :%3i:%i%i", minutes, tens, units); + snprintf(str, sizeof(str), "Time :%3i:%i%i", minutes, tens, units); Sbar_DrawString(184, 4, str); // draw level name @@ -584,7 +583,7 @@ flashon = static_cast((cl.time - time) * 10); // ammo counts for (i = 0; i < 4; i++) { - sprintf_s(num, sizeof(num), "%3i", cl.stats[STAT_SHELLS + i]); + snprintf(num, sizeof(num), "%3i", cl.stats[STAT_SHELLS + i]); if (num[0] != ' ') { Sbar_DrawCharacter((6 * i + 1) * 8 - 2, -24, 18 + num[0] - '0'); } @@ -598,7 +597,7 @@ flashon = static_cast((cl.time - time) * 10); } } - flashon = 0; + flashon = (cl.time < 0.0f) ? 1 : 0; // items for (i = 0; i < 6; i++) { if (cl.items & (1 << (17 + i))) { @@ -656,7 +655,7 @@ flashon = static_cast((cl.time - time) * 10); } else { // sigils for (i = 0; i < 4; i++) { - if (cl.items & (1 << (28 + i))) { + if (cl.items & (1U << (28 + i))) { time = cl.item_gettime[28 + i]; if (time && time > cl.time - 2 && flashon) { // flash frame sb_updates = 0; @@ -681,12 +680,11 @@ Sbar_DrawFrags */ void Sbar_DrawFrags(void) { - int i, k, l; + int i, l; int top, bottom; int x, y, f; int xofs; char num[12]; - scoreboard_t* s; Sbar_SortFrags(); @@ -703,8 +701,8 @@ void Sbar_DrawFrags(void) y = vid.height - SBAR_HEIGHT - 23; for (i = 0; i < l; i++) { - k = fragsort[i]; - s = &cl.scores[k]; + int k = fragsort[i]; + const scoreboard_t* s = &cl.scores[k]; if (!s->name[0]) { continue; } @@ -720,7 +718,7 @@ void Sbar_DrawFrags(void) // draw number f = s->frags; - sprintf_s(num, sizeof(num), "%3i", f); + snprintf(num, sizeof(num), "%3i", f); Sbar_DrawCharacter((x + 1) * 8, -24, num[0]); Sbar_DrawCharacter((x + 2) * 8, -24, num[1]); @@ -773,7 +771,7 @@ void Sbar_DrawFace(void) // draw number f = s->frags; - sprintf_s(num, sizeof(num), "%3i", f); + snprintf(num, sizeof(num), "%3i", f); if (top == 8) { if (num[0] != ' ') { @@ -1005,12 +1003,11 @@ Sbar_DeathmatchOverlay */ void Sbar_DeathmatchOverlay(void) { - qpic_t* pic; - int i, k, l; + const qpic_t* pic; + int i, l; int top, bottom; int x, y, f; char num[12]; - scoreboard_t* s; scr_copyeverything = 1; scr_fullupdate = 0; @@ -1027,8 +1024,8 @@ void Sbar_DeathmatchOverlay(void) x = 80 + ((vid.width - 320) >> 1); y = 40; for (i = 0; i < l; i++) { - k = fragsort[i]; - s = &cl.scores[k]; + int k = fragsort[i]; + const scoreboard_t* s = &cl.scores[k]; if (!s->name[0]) { continue; } @@ -1044,7 +1041,7 @@ void Sbar_DeathmatchOverlay(void) // draw number f = s->frags; - sprintf_s(num, sizeof(num), "%3i", f); + snprintf(num, sizeof(num), "%3i", f); Draw_Character(x + 8, y, num[0]); Draw_Character(x + 16, y, num[1]); @@ -1069,11 +1066,10 @@ Sbar_DeathmatchOverlay */ void Sbar_MiniDeathmatchOverlay(void) { - int i, k; + int i; int top, bottom; int x, y, f; char num[12]; - scoreboard_t* s; int numlines; if (vid.width < 512 || !sb_lines) { @@ -1116,8 +1112,8 @@ void Sbar_MiniDeathmatchOverlay(void) x = 324; for (/* */; i < scoreboardlines && y < static_cast(vid.height) - 8; i++) { - k = fragsort[i]; - s = &cl.scores[k]; + int k = fragsort[i]; + const scoreboard_t* s = &cl.scores[k]; if (!s->name[0]) { continue; } @@ -1133,7 +1129,7 @@ void Sbar_MiniDeathmatchOverlay(void) // draw number f = s->frags; - sprintf_s(num, sizeof(num), "%3i", f); + snprintf(num, sizeof(num), "%3i", f); Draw_Character(x + 8, y, num[0]); Draw_Character(x + 16, y, num[1]); @@ -1159,7 +1155,7 @@ Sbar_IntermissionOverlay */ void Sbar_IntermissionOverlay(void) { - qpic_t* pic; + const qpic_t* pic; int dig; int num; @@ -1203,7 +1199,7 @@ Sbar_FinaleOverlay */ void Sbar_FinaleOverlay(void) { - qpic_t* pic; + const qpic_t* pic; scr_copyeverything = 1; diff --git a/src/screen.cpp b/src/screen.cpp index 14a203c..32712c4 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -95,7 +95,7 @@ for a few moments */ void SCR_CenterPrint(const char* str) { - strncpy_s(scr_centerstring, sizeof(scr_centerstring), str, sizeof(scr_centerstring) - 1); + strlcpy(scr_centerstring, str, sizeof(scr_centerstring) - 1); scr_centertime_off = scr_centertime.value; scr_centertime_start = static_cast(cl.time); @@ -132,10 +132,10 @@ void SCR_EraseCenterString(void) void SCR_DrawCenterString(void) { - char* start; + const char* start; int l; int j; - int x, y; + int y; int remaining; // the finale prints the characters one at a time @@ -161,7 +161,7 @@ void SCR_DrawCenterString(void) break; } } - x = (vid.width - l * 8) / 2; + int x = (vid.width - l * 8) / 2; for (j = 0; j < l; j++, x += 8) { Draw_Character(x, y, start[j]); if (!remaining--) { @@ -432,7 +432,7 @@ DrawPause */ void SCR_DrawPause(void) { - qpic_t* pic; + const qpic_t* pic; if (!scr_showpause.value) { // turn off for screenshots return; @@ -454,7 +454,7 @@ SCR_DrawLoading */ void SCR_DrawLoading(void) { - qpic_t* pic; + const qpic_t* pic; if (!scr_drawloading) { return; @@ -565,18 +565,18 @@ typedef struct { WritePCXfile ============== */ -void WritePCXfile(char* filename, +void WritePCXfile(const char* filename, byte* data, int width, int height, int rowbytes, - byte* palette) + const byte* palette) { int i, j, length; pcx_t* pcx; byte* pack; - pcx = (pcx_t *) Hunk_TempAlloc(width * height * 2 + 1000); + pcx = static_cast(Hunk_TempAlloc(width * height * 2 + 1000)); if (pcx == NULL) { Con_Printf("SCR_ScreenShot_f: not enough memory\n"); @@ -622,7 +622,7 @@ void WritePCXfile(char* filename, } // write output file - length = static_cast(pack - (byte*)pcx); + length = static_cast(pack - reinterpret_cast(pcx)); COM_WriteFile(filename, pcx, length); } @@ -640,12 +640,12 @@ void SCR_ScreenShot_f(void) // // find a file name to save it to // - strcpy_s(pcxname, sizeof(pcxname), "quake00.pcx"); + strlcpy(pcxname, "quake00.pcx", sizeof(pcxname)); for (i = 0; i <= 99; i++) { pcxname[5] = static_cast(i / 10 + '0'); pcxname[6] = static_cast(i % 10 + '0'); - sprintf_s(checkname, sizeof(checkname), "%s/%s", com_gamedir, pcxname); + snprintf(checkname, sizeof(checkname), "%s/%s", com_gamedir, pcxname); if (Sys_FileTime(checkname) == -1) { break; // file doesn't exist } @@ -730,7 +730,7 @@ void SCR_DrawNotifyString(void) const char* start; int l; int j; - int x, y; + int y; start = scr_notifystring; @@ -743,7 +743,7 @@ void SCR_DrawNotifyString(void) break; } } - x = (vid.width - l * 8) / 2; + int x = (vid.width - l * 8) / 2; for (j = 0; j < l; j++, x += 8) { Draw_Character(x, y, start[j]); } diff --git a/src/server.cpp b/src/server.cpp index 9aad8da..f4c3c4d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -104,7 +104,7 @@ void SV_Init(void) Cvar::Register(&sv_nostep); for (i = 0; i < MAX_MODELS; i++) { - sprintf_s(localmodels[i], sizeof(localmodels[i]), "*%i", i); + snprintf(localmodels[i], sizeof(localmodels[i]), "*%i", i); } } @@ -117,7 +117,7 @@ Make sure the event gets sent to all clients */ void SV_StartParticle(const Vector3& org, const Vector3& dir, int color, int count) { - int i, v; + int i; if (sv.datagram.cursize > MAX_DATAGRAM - 16) { return; @@ -128,7 +128,7 @@ void SV_StartParticle(const Vector3& org, const Vector3& dir, int color, int cou MSG_WriteCoord(&sv.datagram, org[1]); MSG_WriteCoord(&sv.datagram, org[2]); for (i = 0; i < 3; i++) { - v = static_cast(dir[i] * 16); + int v = static_cast(dir[i] * 16); if (v > 127) { v = 127; } else if (v < -128) { @@ -244,7 +244,7 @@ void SV_SendServerinfo(client_t* client) char message[2048]; MSG_WriteByte(&client->message, svc_print); - sprintf_s(message, sizeof(message), "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc); + snprintf(message, sizeof(message), "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc); MSG_WriteString(&client->message, message); MSG_WriteByte(&client->message, svc_serverinfo); @@ -257,7 +257,7 @@ void SV_SendServerinfo(client_t* client) MSG_WriteByte(&client->message, GAME_COOP); } - sprintf_s(message, sizeof(message), "%s", PR_GetString(sv.edicts->v.message)); + snprintf(message, sizeof(message), "%s", PR_GetString(sv.edicts->v.message)); MSG_WriteString(&client->message, message); @@ -301,7 +301,6 @@ void SV_ConnectClient(int clientnum) client_t* client; int edictnum; struct qsocket_s* netconnection; - int i; float spawn_parms[NUM_SPAWN_PARMS]; client = svs.clients + clientnum; @@ -319,10 +318,10 @@ void SV_ConnectClient(int clientnum) memcpy(spawn_parms, client->spawn_parms, sizeof(spawn_parms)); } - memset(client, 0, sizeof(*client)); + *client = client_t{}; client->netconnection = netconnection; - strcpy_s(client->name, sizeof(client->name), "unconnected"); + strlcpy(client->name, "unconnected", sizeof(client->name)); client->active = true; client->spawned = false; client->edict = ent; @@ -337,7 +336,7 @@ void SV_ConnectClient(int clientnum) } else { // call the progs to get default spawn parms for the new client PR_ExecuteProgram(pr_global_struct->SetNewParms); - for (i = 0; i < NUM_SPAWN_PARMS; i++) { + for (int i = 0; i < NUM_SPAWN_PARMS; i++) { client->spawn_parms[i] = (&pr_global_struct->parm1)[i]; } } @@ -390,17 +389,12 @@ void SV_CheckForNewClients(void) void SV_AddToFatPVS(const Vector3& org, mnode_t* node) { - int i; - byte* pvs; - mplane_t* plane; - float d; - while (1) { // if this is a leaf, accumulate the pvs bits if (node->contents < 0) { if (node->contents != CONTENTS_SOLID) { - pvs = Mod_LeafPVS((mleaf_t*)node, sv.worldmodel); - for (i = 0; i < fatbytes; i++) { + byte* pvs = Mod_LeafPVS(reinterpret_cast(node), sv.worldmodel); + for (int i = 0; i < fatbytes; i++) { fatpvs[i] |= pvs[i]; } } @@ -408,8 +402,8 @@ void SV_AddToFatPVS(const Vector3& org, mnode_t* node) return; } - plane = node->plane; - d = org.dot(plane->normal) - plane->dist; + const mplane_t* plane = node->plane; + float d = org.dot(plane->normal) - plane->dist; if (d > 8) { node = node->children[0]; } else if (d < -8) { @@ -630,7 +624,6 @@ void SV_WriteClientdataToMessage(edict_t* ent, sizebuf_t* msg) { int bits; int i; - edict_t* other; int items; eval_t* val; @@ -638,7 +631,7 @@ void SV_WriteClientdataToMessage(edict_t* ent, sizebuf_t* msg) // send a damage message // if (ent->v.dmg_take || ent->v.dmg_save) { - other = PROG_TO_EDICT(ent->v.dmg_inflictor); + edict_t* other = PROG_TO_EDICT(ent->v.dmg_inflictor); MSG_WriteByte(msg, svc_damage); MSG_WriteByte(msg, static_cast(ent->v.dmg_save)); MSG_WriteByte(msg, static_cast(ent->v.dmg_take)); @@ -1046,7 +1039,7 @@ void SV_SendReconnect(void) char data[128]; sizebuf_t msg; - msg.data = (byte*)data; + msg.data = reinterpret_cast(data); msg.cursize = 0; msg.maxsize = sizeof(data); @@ -1141,9 +1134,9 @@ void SV_SpawnServer(char* server) // Host_ClearMemory(); - memset(&sv, 0, sizeof(sv)); + sv = server_t{}; - strcpy_s(sv.name, sizeof(sv.name), server); + strlcpy(sv.name, server, sizeof(sv.name)); // load progs to get entity field count PR_LoadProgs(); @@ -1151,7 +1144,7 @@ void SV_SpawnServer(char* server) // allocate server memory sv.max_edicts = MAX_EDICTS; - sv.edicts = (edict_t *) Hunk_Alloc(sv.max_edicts * pr_edict_size, "edicts"); + sv.edicts = static_cast(Hunk_Alloc(sv.max_edicts * pr_edict_size, "edicts")); sv.datagram.maxsize = sizeof(sv.datagram_buf); sv.datagram.cursize = 0; @@ -1177,8 +1170,8 @@ void SV_SpawnServer(char* server) sv.time = 1.0; - strcpy_s(sv.name, sizeof(sv.name), server); - sprintf_s(sv.modelname, sizeof(sv.modelname), "maps/%s.bsp", server); + strlcpy(sv.name, server, sizeof(sv.name)); + snprintf(sv.modelname, sizeof(sv.modelname), "maps/%s.bsp", server); sv.worldmodel = Mod_ForName(sv.modelname, false); if (!sv.worldmodel) { Con_Printf("Couldn't spawn server %s\n", sv.modelname); @@ -1424,13 +1417,10 @@ If steptrace is not NULL, the trace of any vertical wall hit will be stored int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) { int bumpcount, numbumps; - Vector3 dir; - float d; int numplanes; Vector3 planes[MAX_CLIP_PLANES]; Vector3 primal_velocity, original_velocity, new_velocity; int i, j; - trace_t trace; Vector3 end; float time_left; int blocked; @@ -1451,7 +1441,7 @@ int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) end = ent->v.origin + ent->v.velocity * time_left; - trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); + trace_t trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent); if (trace.allsolid) { // entity is trapped in another solid ent->v.velocity = vec3_origin; @@ -1535,8 +1525,8 @@ int SV_FlyMove(edict_t* ent, float time, trace_t* steptrace) return 7; } - dir = planes[0].cross(planes[1]); - d = dir.dot(ent->v.velocity); + Vector3 dir = planes[0].cross(planes[1]); + float d = dir.dot(ent->v.velocity); ent->v.velocity = dir * d; } diff --git a/src/server.hpp b/src/server.hpp index 703e282..afc27a6 100644 --- a/src/server.hpp +++ b/src/server.hpp @@ -1,12 +1,12 @@ // server.h -- server state and entity management structures #pragma once -typedef struct { - int maxclients; - int maxclientslimit; - struct client_s* clients; // [maxclients] - int serverflags; // episode completion information - qboolean changelevel_issued; // cleared when at SV_SpawnServer +typedef struct server_static_s { + int maxclients = 0; + int maxclientslimit = 0; + struct client_s* clients = nullptr; // [maxclients] + int serverflags = 0; // episode completion information + qboolean changelevel_issued = false; // cleared when at SV_SpawnServer } server_static_t; //============================================================================= @@ -14,74 +14,74 @@ typedef struct { typedef enum { ss_loading, ss_active } server_state_t; -typedef struct { - qboolean active; // false if only a net client +typedef struct server_s { + qboolean active = false; // false if only a net client - qboolean paused; - qboolean loadgame; // handle connections specially + qboolean paused = false; + qboolean loadgame = false; // handle connections specially - double time; + double time = 0.0; - int lastcheck; // used by PF_checkclient - double lastchecktime; + int lastcheck = 0; // used by PF_checkclient + double lastchecktime = 0.0; - char name[64]; // map name - char modelname[64]; // maps/.bsp, for model_precache[0] - struct model_s* worldmodel; - char* model_precache[MAX_MODELS]; // NULL terminated - struct model_s* models[MAX_MODELS]; - char* sound_precache[MAX_SOUNDS]; // NULL terminated - char* lightstyles[MAX_LIGHTSTYLES]; - int num_edicts; - int max_edicts; - edict_t* edicts; // can NOT be array indexed, because + char name[64] = {}; // map name + char modelname[64] = {}; // maps/.bsp, for model_precache[0] + struct model_s* worldmodel = nullptr; + char* model_precache[MAX_MODELS] = {}; // NULL terminated + struct model_s* models[MAX_MODELS] = {}; + char* sound_precache[MAX_SOUNDS] = {}; // NULL terminated + char* lightstyles[MAX_LIGHTSTYLES] = {}; + int num_edicts = 0; + int max_edicts = 0; + edict_t* edicts = nullptr; // can NOT be array indexed, because // edict_t is variable sized, but can // be used to reference the world ent - server_state_t state; // some actions are only valid during load + server_state_t state = ss_loading; // some actions are only valid during load - sizebuf_t datagram; - byte datagram_buf[MAX_DATAGRAM]; + sizebuf_t datagram = {}; + byte datagram_buf[MAX_DATAGRAM] = {}; - sizebuf_t reliable_datagram; // copied to all clients at end of frame - byte reliable_datagram_buf[MAX_DATAGRAM]; + sizebuf_t reliable_datagram = {}; // copied to all clients at end of frame + byte reliable_datagram_buf[MAX_DATAGRAM] = {}; - sizebuf_t signon; - byte signon_buf[8192]; + sizebuf_t signon = {}; + byte signon_buf[8192] = {}; } server_t; #define NUM_PING_TIMES 16 #define NUM_SPAWN_PARMS 16 typedef struct client_s { - qboolean active; // false = client is free - qboolean spawned; // false = don't send datagrams - qboolean dropasap; // has been told to go to another level - qboolean privileged; // can execute any host command - qboolean sendsignon; // only valid before spawned + qboolean active = false; // false = client is free + qboolean spawned = false; // false = don't send datagrams + qboolean dropasap = false; // has been told to go to another level + qboolean privileged = false; // can execute any host command + qboolean sendsignon = false; // only valid before spawned - double last_message; // reliable messages must be sent + double last_message = 0.0; // reliable messages must be sent // periodically - struct qsocket_s* netconnection; // communications handle + struct qsocket_s* netconnection = nullptr; // communications handle - usercmd_t cmd; // movement + usercmd_t cmd = {}; // movement Vector3 wishdir; // intended motion calced from cmd - sizebuf_t message; // can be added to at any time, + sizebuf_t message = {}; // can be added to at any time, // copied and clear once per frame - byte msgbuf[MAX_MSGLEN]; - edict_t* edict; // EDICT_NUM(clientnum+1) - char name[32]; // for printing to other people - int colors; + byte msgbuf[MAX_MSGLEN] = {}; + edict_t* edict = nullptr; // EDICT_NUM(clientnum+1) + char name[32] = {}; // for printing to other people + int colors = 0; - float ping_times[NUM_PING_TIMES]; - int num_pings; // ping_times[num_pings%NUM_PING_TIMES] + float ping_times[NUM_PING_TIMES] = {}; + int num_pings = 0; // ping_times[num_pings%NUM_PING_TIMES] // spawn parms are carried from level to level - float spawn_parms[NUM_SPAWN_PARMS]; + float spawn_parms[NUM_SPAWN_PARMS] = {}; // client known data for deltas - int old_frags; + int old_frags = 0; } client_t; //============================================================================= @@ -159,6 +159,7 @@ extern cvar_t sv_gravity; class ServerSubsystem { public: + ServerSubsystem() = default; server_static_t& GetStaticState() { return svs_; } const server_static_t& GetStaticState() const { return svs_; } diff --git a/src/sys_sdl.cpp b/src/sys_sdl.cpp index e1dad1b..9d920bb 100644 --- a/src/sys_sdl.cpp +++ b/src/sys_sdl.cpp @@ -56,7 +56,7 @@ void Sys_Printf(const char* fmt, ...) char text[1024]; va_start(argptr, fmt); - vsprintf_s(text, sizeof(text), fmt, argptr); + vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); fprintf(stderr, "%s", text); @@ -99,7 +99,7 @@ void Sys_HighFPPrecision(void) char string[1024]; va_start(argptr, error); - vsprintf_s(string, sizeof(string), error, argptr); + vsnprintf(string, sizeof(string), error, argptr); va_end(argptr); fprintf(stderr, "Error: %s\n", string); @@ -155,7 +155,7 @@ int Sys_FileOpenRead(const char* path, int* hndl) i = findhandle(); - if (fopen_s(&f, path, "rb") != 0) { + if ((f = fopen(path, "rb")) == NULL) { *hndl = -1; return -1; @@ -174,9 +174,9 @@ int Sys_FileOpenWrite(const char* path) i = findhandle(); - if (fopen_s(&f, path, "wb") != 0) { + if ((f = fopen(path, "wb")) == NULL) { char errbuf[256]; - strerror_s(errbuf, sizeof(errbuf), errno); + strerror_r(errno, errbuf, sizeof(errbuf)); Sys_Error("Error opening %s: %s", path, errbuf); } @@ -202,14 +202,11 @@ void Sys_FileSeek(int handle, int position) int Sys_FileRead(int handle, void* dst, int count) { - char* data; - int size, done; - - size = 0; + int size = 0; if (handle >= 0) { - data = (char*)dst; + char* data = static_cast(dst); while (count > 0) { - done = (int)fread(data, 1, count, sys_handles[handle]); + int done = static_cast(fread(data, 1, count, sys_handles[handle])); if (done == 0) { break; } @@ -225,14 +222,11 @@ int Sys_FileRead(int handle, void* dst, int count) int Sys_FileWrite(int handle, const void* src, int count) { - const char* data; - int size, done; - - size = 0; + int size = 0; if (handle >= 0) { - data = (const char*)src; + const char* data = static_cast(src); while (count > 0) { - done = (int)fwrite(data, 1, count, sys_handles[handle]); + int done = static_cast(fwrite(data, 1, count, sys_handles[handle])); if (done == 0) { break; } @@ -250,7 +244,7 @@ int Sys_FileTime(const char* path) { FILE* f; - if (fopen_s(&f, path, "rb") == 0) { + if ((f = fopen(path, "rb")) != NULL) { fclose(f); return 1; @@ -286,7 +280,6 @@ void moncontrol() int main(int c, char** v) { - double time, oldtime, newtime; quakeparms_t parms; extern int vcrFile; extern qboolean recording; @@ -312,11 +305,11 @@ int main(int c, char** v) Cvar::Register(&sys_nostdout); - oldtime = Sys_FloatTime() - 0.1; + double oldtime = Sys_FloatTime() - 0.1; while (1) { // find time spent rendering last frame - newtime = Sys_FloatTime(); - time = newtime - oldtime; + double newtime = Sys_FloatTime(); + double time = newtime - oldtime; if (cls.state == ca_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate.value && (vcrFile == -1 || recording)) { diff --git a/src/vid.hpp b/src/vid.hpp index 978ded0..5171933 100644 --- a/src/vid.hpp +++ b/src/vid.hpp @@ -41,18 +41,18 @@ extern unsigned d_8to24table[256]; extern void (*vid_menudrawfn)(void); extern void (*vid_menukeyfn)(int key); -void VID_SetPalette(unsigned char* palette); +void VID_SetPalette(const unsigned char* palette); -inline void VID_ShiftPalette(unsigned char* palette) +inline void VID_ShiftPalette(const unsigned char* palette) { VID_SetPalette(palette); } -void VID_Init(unsigned char* palette); +void VID_Init(const unsigned char* palette); void VID_Shutdown(void); -void VID_Update(vrect_t* rects); +void VID_Update(const vrect_t* rects); int VID_SetMode(int modenum, unsigned char* palette); diff --git a/src/vid_sdl.cpp b/src/vid_sdl.cpp index a23ec7a..70dc9c0 100644 --- a/src/vid_sdl.cpp +++ b/src/vid_sdl.cpp @@ -2,6 +2,7 @@ #include "SDL.h" #include "quakedef.hpp" +#include using namespace CDAudio; using namespace Client; @@ -58,7 +59,7 @@ static qboolean mouse_avail; static float mouse_x, mouse_y; static int mouse_oldbuttonstate = 0; -void VID_SetPalette(unsigned char* palette) +void VID_SetPalette(const unsigned char* palette) { int i; SDL_Color colors[256]; @@ -74,7 +75,7 @@ void VID_SetPalette(unsigned char* palette) } } -void VID_Init(unsigned char* palette) +void VID_Init(const unsigned char* palette) { int pnum, chunk; byte* cache; @@ -154,8 +155,8 @@ void VID_Init(unsigned char* palette) vid.aspect = static_cast(((float)vid.height / (float)vid.width) * (320.0 / 240.0)); vid.numpages = 1; vid.colormap = host_colormap; - vid.fullbright = 256 - LittleLong(*((int*)vid.colormap + 2048)); - VGA_pagebase = vid.buffer = (pixel_t*)screen->pixels; + vid.fullbright = 256 - LittleLong(reinterpret_cast(vid.colormap)[2048]); + VGA_pagebase = vid.buffer = static_cast(screen->pixels); VGA_rowbytes = vid.rowbytes = screen->pitch; vid.conbuffer = vid.buffer; vid.conrowbytes = vid.rowbytes; @@ -165,13 +166,13 @@ void VID_Init(unsigned char* palette) chunk = vid.width * vid.height * sizeof(*d_pzbuffer); cachesize = D_SurfaceCacheForRes(vid.width, vid.height); chunk += cachesize; - d_pzbuffer = (short *) Hunk_HighAllocName(chunk, "video"); + d_pzbuffer = static_cast(Hunk_HighAllocName(chunk, "video")); if (d_pzbuffer == NULL) { Sys_Error("Not enough memory for video mode\n"); } // Initialize the cache memory - cache = (byte*)d_pzbuffer + vid.width * vid.height * sizeof(*d_pzbuffer); + cache = reinterpret_cast(d_pzbuffer) + vid.width * vid.height * sizeof(*d_pzbuffer); D_InitCaches(cache, cachesize); // Initialize the mouse @@ -188,11 +189,10 @@ void VID_Shutdown(void) SDL_Quit(); } -void VID_Update(vrect_t* rects) +void VID_Update(const vrect_t* rects) { - SDL_Rect* sdlrects; - int n, i; - vrect_t* rect; + int n; + const vrect_t* rect; // Two-pass system, since Quake doesn't do it the SDL way... @@ -203,11 +203,9 @@ void VID_Update(vrect_t* rects) } // Second, copy them to SDL rectangles and update - if (!(sdlrects = (SDL_Rect*)alloca(n * sizeof(*sdlrects)))) { - Sys_Error("Out of memory"); - } + std::vector sdlrects(n); - i = 0; + int i = 0; for (rect = rects; rect; rect = rect->pnext) { sdlrects[i].x = rect->x; sdlrects[i].y = rect->y; @@ -220,9 +218,9 @@ void VID_Update(vrect_t* rects) SDL_Surface* window_surface = SDL_GetWindowSurface(window); if (screen != window_surface) { SDL_BlitSurface(screen, NULL, window_surface, NULL); - SDL_UpdateWindowSurfaceRects(window, sdlrects, n); + SDL_UpdateWindowSurfaceRects(window, sdlrects.data(), n); } else { - SDL_UpdateWindowSurfaceRects(window, sdlrects, n); + SDL_UpdateWindowSurfaceRects(window, sdlrects.data(), n); } } @@ -243,7 +241,7 @@ void D_BeginDirectRect(int x, int y, byte* pbitmap, int width, int height) x = screen->w + x - 1; } - offset = (Uint8*)screen->pixels + y * screen->pitch + x; + offset = static_cast(screen->pixels) + y * screen->pitch + x; while (height--) { memcpy(offset, pbitmap, width); offset += screen->pitch; diff --git a/src/view.cpp b/src/view.cpp index 490481d..053d1d3 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -259,18 +259,8 @@ byte gammatable[256]; // palette is sent through this void BuildGammaTable(float g) { - int i, inf; - - if (g == 1.0) { - for (i = 0; i < 256; i++) { - gammatable[i] = static_cast(i); - } - - return; - } - - for (i = 0; i < 256; i++) { - inf = static_cast(255 * pow((i + 0.5) / 255.5, g) + 0.5); + for (int i = 0; i < 256; i++) { + int inf = static_cast(255 * pow((i + 0.5) / 255.5, g) + 0.5); if (inf < 0) { inf = 0; } @@ -475,7 +465,6 @@ void V_UpdatePalette(void) qboolean new_shift; byte *basepal, *newpal; byte pal[768]; - int r, g, b; qboolean force; V_CalcPowerupCshift(); @@ -517,15 +506,15 @@ void V_UpdatePalette(void) newpal = pal; for (i = 0; i < 256; i++) { - r = basepal[0]; - g = basepal[1]; - b = basepal[2]; + int r = basepal[0]; + int g = basepal[1]; + int b = basepal[2]; basepal += 3; - for (j = 0; j < NUM_CSHIFTS; j++) { - r += (cl.cshifts[j].percent * (cl.cshifts[j].destcolor[0] - r)) >> 8; - g += (cl.cshifts[j].percent * (cl.cshifts[j].destcolor[1] - g)) >> 8; - b += (cl.cshifts[j].percent * (cl.cshifts[j].destcolor[2] - b)) >> 8; + for (int k = 0; k < NUM_CSHIFTS; k++) { + r += (cl.cshifts[k].percent * (cl.cshifts[k].destcolor[0] - r)) >> 8; + g += (cl.cshifts[k].percent * (cl.cshifts[k].destcolor[1] - g)) >> 8; + b += (cl.cshifts[k].percent * (cl.cshifts[k].destcolor[2] - b)) >> 8; } newpal[0] = gammatable[r]; @@ -626,7 +615,7 @@ V_BoundOffsets */ void V_BoundOffsets(void) { - entity_t* ent; + const entity_t* ent; ent = &cl_entities[cl.viewentity]; diff --git a/src/vm.cpp b/src/vm.cpp index 948376f..c9b2f7b 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -276,7 +276,7 @@ eval_t* GetEdictFieldValue(edict_t* ed, const char* field) if (strlen(field) < MAX_FIELD_LEN) { gefvCache[rep].pcache = def; - strcpy_s(gefvCache[rep].field, sizeof(gefvCache[rep].field), field); + strlcpy(gefvCache[rep].field, field, sizeof(gefvCache[rep].field)); rep ^= 1; } @@ -305,34 +305,34 @@ char* PR_ValueString(etype_t type, eval_t* val) switch (type) { case ev_string: - sprintf_s(line, sizeof(line), "%s", PR_GetString(val->string)); + snprintf(line, sizeof(line), "%s", PR_GetString(val->string)); break; case ev_entity: - sprintf_s(line, sizeof(line), "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); + snprintf(line, sizeof(line), "entity %i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); break; case ev_function: f = pr_functions + val->function; - sprintf_s(line, sizeof(line), "%s()", PR_GetString(f->s_name)); + snprintf(line, sizeof(line), "%s()", PR_GetString(f->s_name)); break; case ev_field: def = ED_FieldAtOfs(val->_int); - sprintf_s(line, sizeof(line), ".%s", PR_GetString(def->s_name)); + snprintf(line, sizeof(line), ".%s", PR_GetString(def->s_name)); break; case ev_void: - sprintf_s(line, sizeof(line), "void"); + snprintf(line, sizeof(line), "void"); break; case ev_float: - sprintf_s(line, sizeof(line), "%5.1f", val->_float); + snprintf(line, sizeof(line), "%5.1f", val->_float); break; case ev_vector: - sprintf_s(line, sizeof(line), "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], + snprintf(line, sizeof(line), "'%5.1f %5.1f %5.1f'", val->vector[0], val->vector[1], val->vector[2]); break; case ev_pointer: - sprintf_s(line, sizeof(line), "pointer"); + snprintf(line, sizeof(line), "pointer"); break; default: - sprintf_s(line, sizeof(line), "bad type %i", type); + snprintf(line, sizeof(line), "bad type %i", type); break; } @@ -357,30 +357,30 @@ char* PR_UglyValueString(etype_t type, eval_t* val) switch (type) { case ev_string: - sprintf_s(line, sizeof(line), "%s", PR_GetString(val->string)); + snprintf(line, sizeof(line), "%s", PR_GetString(val->string)); break; case ev_entity: - sprintf_s(line, sizeof(line), "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); + snprintf(line, sizeof(line), "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); break; case ev_function: f = pr_functions + val->function; - sprintf_s(line, sizeof(line), "%s", PR_GetString(f->s_name)); + snprintf(line, sizeof(line), "%s", PR_GetString(f->s_name)); break; case ev_field: def = ED_FieldAtOfs(val->_int); - sprintf_s(line, sizeof(line), "%s", PR_GetString(def->s_name)); + snprintf(line, sizeof(line), "%s", PR_GetString(def->s_name)); break; case ev_void: - sprintf_s(line, sizeof(line), "void"); + snprintf(line, sizeof(line), "void"); break; case ev_float: - sprintf_s(line, sizeof(line), "%f", val->_float); + snprintf(line, sizeof(line), "%f", val->_float); break; case ev_vector: - sprintf_s(line, sizeof(line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]); + snprintf(line, sizeof(line), "%f %f %f", val->vector[0], val->vector[1], val->vector[2]); break; default: - sprintf_s(line, sizeof(line), "bad type %i", type); + snprintf(line, sizeof(line), "bad type %i", type); break; } @@ -406,17 +406,17 @@ char* PR_GlobalString(int ofs) val = (void*)&pr_globals[ofs]; def = ED_GlobalAtOfs(ofs); if (!def) { - sprintf_s(line, sizeof(line), "%i(??? unknown)", ofs); + snprintf(line, sizeof(line), "%i(??? unknown)", ofs); } else { s = PR_ValueString((etype_t)def->type, (eval_t*)val); - sprintf_s(line, sizeof(line), "%i(%s)%s", ofs, PR_GetString(def->s_name), s); + snprintf(line, sizeof(line), "%i(%s)%s", ofs, PR_GetString(def->s_name), s); } i = (int)strlen(line); for (; i < 20; i++) { - strcat_s(line, sizeof(line), " "); + strlcat(line, " ", sizeof(line)); } - strcat_s(line, sizeof(line), " "); + strlcat(line, " ", sizeof(line)); return line; } @@ -429,16 +429,16 @@ char* PR_GlobalStringNoContents(int ofs) def = ED_GlobalAtOfs(ofs); if (!def) { - sprintf_s(line, sizeof(line), "%i(???)", ofs); + snprintf(line, sizeof(line), "%i(???)", ofs); } else { - sprintf_s(line, sizeof(line), "%i(%s)", ofs, PR_GetString(def->s_name)); + snprintf(line, sizeof(line), "%i(%s)", ofs, PR_GetString(def->s_name)); } i = (int)strlen(line); for (; i < 20; i++) { - strcat_s(line, sizeof(line), " "); + strlcat(line, " ", sizeof(line)); } - strcat_s(line, sizeof(line), " "); + strlcat(line, " ", sizeof(line)); return line; } @@ -695,7 +695,7 @@ void ED_ParseGlobals(char* data) Sys_Error("ED_ParseEntity: EOF without closing brace"); } - strcpy_s(keyname, sizeof(keyname), com_token); + strlcpy(keyname, com_token, sizeof(keyname)); // parse value data = COM_Parse(data); @@ -783,7 +783,7 @@ qboolean ED_ParseEpair(void* base, ddef_t* key, char* s) break; case ev_vector: - strcpy_s(string, sizeof(string), s); + strlcpy(string, s, sizeof(string)); v = string; w = string; for (i = 0; i < 3; i++) { @@ -868,7 +868,7 @@ char* ED_ParseEdict(char* data, edict_t* ent) // anglehack is to allow QuakeEd to write single scalar angles // and allow them to be turned into vectors. (FIXME...) if (!strcmp(com_token, "angle")) { - strcpy_s(com_token, sizeof(com_token), "angles"); + strlcpy(com_token, "angles", sizeof(com_token)); anglehack = true; } else { anglehack = false; @@ -876,10 +876,10 @@ char* ED_ParseEdict(char* data, edict_t* ent) // FIXME: change light to _light to get rid of this hack if (!strcmp(com_token, "light")) { - strcpy_s(com_token, sizeof(com_token), "light_lev"); // hack for single light def + strlcpy(com_token, "light_lev", sizeof(com_token)); // hack for single light def } - strcpy_s(keyname, sizeof(keyname), com_token); + strlcpy(keyname, com_token, sizeof(keyname)); // another hack to fix heynames with trailing spaces n = (int)strlen(keyname); @@ -914,8 +914,8 @@ char* ED_ParseEdict(char* data, edict_t* ent) if (anglehack) { char temp[32]; - strcpy_s(temp, sizeof(temp), com_token); - sprintf_s(com_token, sizeof(com_token), "0 %s 0", temp); + strlcpy(temp, com_token, sizeof(temp)); + snprintf(com_token, sizeof(com_token), "0 %s 0", temp); } if (!ED_ParseEpair((void*)&ent->v, key, com_token)) { @@ -1505,7 +1505,7 @@ Aborts the currently executing function char string[1024]; va_start(argptr, error); - vsprintf_s(string, sizeof(string), error, argptr); + vsnprintf(string, sizeof(string), error, argptr); va_end(argptr); PR_PrintStatement(pr_statements + pr_xstatement); @@ -1936,7 +1936,7 @@ char* PF_VarString(int first) out[0] = 0; for (i = first; i < pr_argc; i++) { - strcat_s(out, sizeof(out), G_STRING((OFS_PARM0 + i * 3))); + strlcat(out, G_STRING((OFS_PARM0 + i * 3)), sizeof(out)); } return out; @@ -2487,7 +2487,7 @@ break() void PF_break(void) { Con_Printf("break statement\n"); - *(int*)-4 = 0; // dump to debugger + *reinterpret_cast(-4) = 0; // dump to debugger // PR_RunError ("break statement"); } @@ -2794,9 +2794,9 @@ void PF_ftos(void) v = G_FLOAT(OFS_PARM0); if (v == (int)v) { - sprintf_s(pr_string_temp, sizeof(pr_string_temp), "%d", (int)v); + snprintf(pr_string_temp, sizeof(pr_string_temp), "%d", (int)v); } else { - sprintf_s(pr_string_temp, sizeof(pr_string_temp), "%5.1f", v); + snprintf(pr_string_temp, sizeof(pr_string_temp), "%5.1f", v); } G_INT(OFS_RETURN) = PR_SetString(pr_string_temp); @@ -2811,7 +2811,7 @@ void PF_fabs(void) void PF_vtos(void) { - sprintf_s(pr_string_temp, sizeof(pr_string_temp), "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], + snprintf(pr_string_temp, sizeof(pr_string_temp), "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); G_INT(OFS_RETURN) = PR_SetString(pr_string_temp); } diff --git a/src/vm.hpp b/src/vm.hpp index ac704aa..a6e7e29 100644 --- a/src/vm.hpp +++ b/src/vm.hpp @@ -76,10 +76,10 @@ void ED_LoadFromFile(char* data); edict_t* EDICT_NUM(int n); int NUM_FOR_EDICT(edict_t* e); -#define NEXT_EDICT(e) ((edict_t*)((byte*)e + pr_edict_size)) +#define NEXT_EDICT(e) (reinterpret_cast(reinterpret_cast(e) + pr_edict_size)) -#define EDICT_TO_PROG(e) ((byte*)e - (byte*)sv.edicts) -#define PROG_TO_EDICT(e) ((edict_t*)((byte*)sv.edicts + e)) +#define EDICT_TO_PROG(e) (reinterpret_cast(e) - reinterpret_cast(sv.edicts)) +#define PROG_TO_EDICT(e) (reinterpret_cast(reinterpret_cast(sv.edicts) + e)) //============================================================================ diff --git a/src/wad.cpp b/src/wad.cpp index 5af95db..8b0b61b 100644 --- a/src/wad.cpp +++ b/src/wad.cpp @@ -49,10 +49,9 @@ Can safely be performed in place. void W_CleanupName(const char* in, char* out) { int i; - int c; for (i = 0; i < 16; i++) { - c = in[i]; + int c = in[i]; if (!c) { break; } @@ -86,7 +85,7 @@ void W_LoadWadFile(const char* filename) Sys_Error("W_LoadWadFile: couldn't load %s", filename); } - header = (wadinfo_t*)wad_base; + header = reinterpret_cast(wad_base); if (header->identification[0] != 'W' || header->identification[1] != 'A' || header->identification[2] != 'D' || header->identification[3] != '2') { Sys_Error("Wad file %s doesn't have WAD2 id\n", filename); @@ -94,14 +93,14 @@ void W_LoadWadFile(const char* filename) wad_numlumps = LittleLong(header->numlumps); infotableofs = LittleLong(header->infotableofs); - wad_lumps = (lumpinfo_t*)(wad_base + infotableofs); + wad_lumps = reinterpret_cast(wad_base + infotableofs); for (i = 0, lump_p = wad_lumps; i < (unsigned)wad_numlumps; i++, lump_p++) { lump_p->filepos = LittleLong(lump_p->filepos); lump_p->size = LittleLong(lump_p->size); W_CleanupName(lump_p->name, lump_p->name); if (lump_p->type == TYP_QPIC) { - SwapPic((qpic_t*)(wad_base + lump_p->filepos)); + SwapPic(reinterpret_cast(wad_base + lump_p->filepos)); } } } @@ -130,11 +129,9 @@ lumpinfo_t* W_GetLumpinfo(const char* name) void* W_GetLumpName(const char* name) { - lumpinfo_t* lump; + const lumpinfo_t* lump = W_GetLumpinfo(name); - lump = W_GetLumpinfo(name); - - return (void*)(wad_base + lump->filepos); + return static_cast(wad_base + lump->filepos); } /* diff --git a/src/wad.hpp b/src/wad.hpp index b7789f7..d29b734 100644 --- a/src/wad.hpp +++ b/src/wad.hpp @@ -18,9 +18,9 @@ #define TYP_SOUND 67 #define TYP_MIPTEX 68 -typedef struct { - int width, height; - byte data[4]; // variably sized +typedef struct qpic_s { + int width = 0, height = 0; + byte data[4] = {}; // variably sized } qpic_t; typedef struct { diff --git a/src/world.cpp b/src/world.cpp index 88575bd..dbcd213 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -37,17 +37,17 @@ line of sight checks trace->crosscontent, but bullets don't */ -typedef struct { - Vector3 boxmins, boxmaxs; // enclose the test object along entire move - Vector3 mins, maxs; // size of the moving object - Vector3 mins2, maxs2; // size when clipping against mosnters - Vector3 start, end; - trace_t trace; - int type; - edict_t* passedict; +typedef struct moveclip_s { + Vector3 boxmins = {}, boxmaxs = {}; // enclose the test object along entire move + Vector3 mins = {}, maxs = {}; // size of the moving object + Vector3 mins2 = {}, maxs2 = {}; // size when clipping against mosnters + Vector3 start = {}, end = {}; + trace_t trace = {}; + int type = 0; + edict_t* passedict = nullptr; } moveclip_t; -int SV_HullPointContents(hull_t* hull, int num, const Vector3& p); +int SV_HullPointContents(const hull_t* hull, int num, const Vector3& p); /* =============================================================================== @@ -72,7 +72,6 @@ can just be stored out and get a proper hull_t structure. void SV_InitBoxHull(void) { int i; - int side; box_hull.clipnodes = box_clipnodes; box_hull.planes = box_planes; @@ -82,7 +81,7 @@ void SV_InitBoxHull(void) for (i = 0; i < 6; i++) { box_clipnodes[i].planenum = i; - side = i & 1; + int side = i & 1; box_clipnodes[i].children[side] = CONTENTS_EMPTY; if (i != 5) { @@ -132,8 +131,6 @@ hull_t* SV_HullForEntity(edict_t* ent, Vector3& offset) { model_t* model; - Vector3 size; - Vector3 hullmins, hullmaxs; hull_t* hull; // decide which clipping hull to use, based on the size @@ -148,7 +145,7 @@ hull_t* SV_HullForEntity(edict_t* ent, Sys_Error("MOVETYPE_PUSH with a non bsp model"); } - size = maxs - mins; + Vector3 size = maxs - mins; if (size.x < 3) { hull = &model->hulls[0]; } else if (size.x <= 32) { @@ -162,8 +159,8 @@ hull_t* SV_HullForEntity(edict_t* ent, offset += ent->v.origin; } else { // create a temp hull from bounding box sizes - hullmins = ent->v.mins - maxs; - hullmaxs = ent->v.maxs - mins; + Vector3 hullmins = ent->v.mins - maxs; + Vector3 hullmaxs = ent->v.maxs - mins; hull = SV_HullForBox(hullmins, hullmaxs); offset = ent->v.origin; @@ -181,11 +178,11 @@ ENTITY AREA CHECKING */ typedef struct areanode_s { - int axis; // -1 = leaf node - float dist; - struct areanode_s* children[2]; - link_t trigger_edicts; - link_t solid_edicts; + int axis = 0; // -1 = leaf node + float dist = 0.0f; + struct areanode_s* children[2] = { nullptr, nullptr }; + link_t trigger_edicts = {}; + link_t solid_edicts = {}; } areanode_t; #define AREA_DEPTH 4 @@ -250,7 +247,9 @@ void SV_ClearWorld(void) { SV_InitBoxHull(); - memset(sv_areanodes, 0, sizeof(sv_areanodes)); + for (auto& node : sv_areanodes) { + node = areanode_t{}; + } sv_numareanodes = 0; SV_CreateAreaNode(0, sv.worldmodel->mins, sv.worldmodel->maxs); } @@ -279,13 +278,12 @@ SV_TouchLinks void SV_TouchLinks(edict_t* ent, areanode_t* node) { link_t *l, *next; - edict_t* touch; int old_self, old_other; // touch linked edicts for (l = node->trigger_edicts.next; l != &node->trigger_edicts; l = next) { next = l->next; - touch = EDICT_FROM_AREA(l); + edict_t* touch = EDICT_FROM_AREA(l); if (touch == ent) { continue; } @@ -333,9 +331,7 @@ SV_FindTouchedLeafs void SV_FindTouchedLeafs(edict_t* ent, mnode_t* node) { mplane_t* splitplane; - mleaf_t* leaf; int sides; - int leafnum; if (node->contents == CONTENTS_SOLID) { return; @@ -348,8 +344,8 @@ void SV_FindTouchedLeafs(edict_t* ent, mnode_t* node) return; } - leaf = (mleaf_t*)node; - leafnum = static_cast(leaf - sv.worldmodel->leafs - 1); + const mleaf_t* leaf = reinterpret_cast(node); + int leafnum = static_cast(leaf - sv.worldmodel->leafs - 1); ent->leafnums[ent->num_leafs] = static_cast(leafnum); ent->num_leafs++; @@ -474,19 +470,17 @@ SV_HullPointContents ================== */ -int SV_HullPointContents(hull_t* hull, int num, const Vector3& p) +int SV_HullPointContents(const hull_t* hull, int num, const Vector3& p) { float d; - dclipnode_t* node; - mplane_t* plane; while (num >= 0) { if (num < hull->firstclipnode || num > hull->lastclipnode) { Sys_Error("SV_HullPointContents: bad node number"); } - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; + const dclipnode_t* node = hull->clipnodes + num; + const mplane_t* plane = hull->planes + node->planenum; if (plane->type < 3) { d = p[plane->type] - plane->dist; @@ -561,7 +555,7 @@ SV_RecursiveHullCheck ================== */ -qboolean SV_RecursiveHullCheck(hull_t* hull, +qboolean SV_RecursiveHullCheck(const hull_t* hull, int num, float p1f, float p2f, @@ -569,8 +563,6 @@ qboolean SV_RecursiveHullCheck(hull_t* hull, const Vector3& p2, trace_t* trace) { - dclipnode_t* node; - mplane_t* plane; float t1, t2; float frac; Vector3 mid; @@ -600,8 +592,8 @@ qboolean SV_RecursiveHullCheck(hull_t* hull, // // find the point distances // - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; + const dclipnode_t* node = hull->clipnodes + num; + const mplane_t* plane = hull->planes + node->planenum; if (plane->type < 3) { t1 = p1[plane->type] - plane->dist; @@ -731,7 +723,7 @@ trace_t SV_ClipMoveToEntity(edict_t* ent, hull_t* hull; // fill in a default trace - memset(&trace, 0, sizeof(trace_t)); + trace = trace_t{}; trace.fraction = 1; trace.allsolid = true; trace.endpos = end; diff --git a/src/world.hpp b/src/world.hpp index 37f1a8e..950d947 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -1,19 +1,19 @@ // world.h -- collision detection structures (trace, plane, hull) #pragma once -typedef struct { - Vector3 normal; - float dist; +typedef struct plane_s { + Vector3 normal = {}; + float dist = 0.0f; } plane_t; -typedef struct { - qboolean allsolid; // if true, plane is not valid - qboolean startsolid; // if true, the initial point was in a solid area - qboolean inopen, inwater; - float fraction; // time completed, 1.0 = didn't hit anything - Vector3 endpos; // final position - plane_t plane; // surface normal at impact - edict_t* ent; // entity the surface is on +typedef struct trace_s { + qboolean allsolid = false; // if true, plane is not valid + qboolean startsolid = false; // if true, the initial point was in a solid area + qboolean inopen = false, inwater = false; + float fraction = 1.0f; // time completed, 1.0 = didn't hit anything + Vector3 endpos = {}; // final position + plane_t plane = {}; // surface normal at impact + edict_t* ent = nullptr; // entity the surface is on } trace_t; #define MOVE_NORMAL 0 @@ -60,6 +60,6 @@ trace_t SV_Move(const Vector3& start, // shouldn't be considered solid objects // passedict is explicitly excluded from clipping checks (normally NULL) -qboolean SV_RecursiveHullCheck(hull_t* hull, int num, float p1f, float p2f, const Vector3& p1, const Vector3& p2, trace_t* trace); +qboolean SV_RecursiveHullCheck(const hull_t* hull, int num, float p1f, float p2f, const Vector3& p1, const Vector3& p2, trace_t* trace); } // namespace Server diff --git a/src/zone.cpp b/src/zone.cpp index 36df0ab..53d8404 100644 --- a/src/zone.cpp +++ b/src/zone.cpp @@ -83,7 +83,7 @@ void Z_ClearZone(memzone_t* zone, int size) // set the entire zone to one free block - zone->blocklist.next = zone->blocklist.prev = block = (memblock_t*)((byte*)zone + sizeof(memzone_t)); + zone->blocklist.next = zone->blocklist.prev = block = reinterpret_cast(reinterpret_cast(zone) + sizeof(memzone_t)); zone->blocklist.tag = 1; // in use block zone->blocklist.id = 0; zone->blocklist.size = 0; @@ -108,7 +108,7 @@ void Z_Free(void* ptr) Sys_Error("Z_Free: NULL pointer"); } - block = (memblock_t*)((byte*)ptr - sizeof(memblock_t)); + block = reinterpret_cast(reinterpret_cast(ptr) - sizeof(memblock_t)); if (block->id != ZONEID) { Sys_Error("Z_Free: freed a pointer without ZONEID"); } @@ -169,7 +169,7 @@ void* Z_Realloc(void* ptr, int new_size) } // Validate the existing block - memblock_t* block = (memblock_t*)((byte*)ptr - sizeof(memblock_t)); + const memblock_t* block = reinterpret_cast(reinterpret_cast(ptr) - sizeof(memblock_t)); if (block->id != ZONEID) { Sys_Error("Z_Realloc: pointer missing ZONEID"); } @@ -215,7 +215,7 @@ void* Z_Realloc(void* ptr, int new_size) } // Zero-fill the newly expanded space - Q_memset((char*)new_ptr + usable_old_size, 0, new_size - usable_old_size); + Q_memset(static_cast(new_ptr) + usable_old_size, 0, new_size - usable_old_size); return new_ptr; } @@ -223,7 +223,7 @@ void* Z_Realloc(void* ptr, int new_size) void* Z_TagMalloc(int size, int tag) { int extra; - memblock_t *start, *rover, *new_block, *base; + memblock_t *new_block, *base; if (!tag) { Sys_Error("Z_TagMalloc: tried to use a 0 tag"); @@ -237,8 +237,9 @@ void* Z_TagMalloc(int size, int tag) size += 4; // space for memory trash tester size = (size + 7) & ~7; // align to 8-byte boundary - base = rover = mainzone->rover; - start = base->prev; + base = mainzone->rover; + const memblock_t* rover = base; + const memblock_t* start = base->prev; do { if (rover == start) { // scaned all the way around the list @@ -246,7 +247,8 @@ void* Z_TagMalloc(int size, int tag) } if (rover->tag) { - base = rover = rover->next; + base = rover->next; + rover = base; } else { rover = rover->next; } @@ -257,7 +259,7 @@ void* Z_TagMalloc(int size, int tag) // extra = base->size - size; if (extra > MINFRAGMENT) { // there will be a free fragment after the allocated block - new_block = (memblock_t*)((byte*)base + size); + new_block = reinterpret_cast(reinterpret_cast(base) + size); new_block->size = extra; new_block->tag = 0; // free block new_block->prev = base; @@ -275,9 +277,9 @@ void* Z_TagMalloc(int size, int tag) base->id = ZONEID; // marker for memory trash testing - *(int*)((byte*)base + base->size - 4) = ZONEID; + *reinterpret_cast(reinterpret_cast(base) + base->size - 4) = ZONEID; - return (void*)((byte*)base + sizeof(memblock_t)); + return reinterpret_cast(base) + sizeof(memblock_t); } /* @@ -287,14 +289,12 @@ Z_CheckHeap */ void Z_CheckHeap(void) { - memblock_t* block; - - for (block = mainzone->blocklist.next;; block = block->next) { + for (const memblock_t* block = mainzone->blocklist.next;; block = block->next) { if (block->next == &mainzone->blocklist) { break; // all blocks have been hit } - if ((byte*)block + block->size != (byte*)block->next) { + if (reinterpret_cast(block) + block->size != reinterpret_cast(block->next)) { Sys_Error("Z_CheckHeap: block size does not touch the next block\n"); } @@ -338,18 +338,18 @@ Run consistancy and sentinal trahing checks */ void Hunk_Check(void) { - hunk_t* h; + const hunk_t* h; - for (h = (hunk_t*)hunk_base; (byte*)h != hunk_base + hunk_low_used;) { + for (h = reinterpret_cast(hunk_base); reinterpret_cast(h) != hunk_base + hunk_low_used;) { if (h->sentinal != HUNK_SENTINAL) { Sys_Error("Hunk_Check: trahsed sentinal"); } - if (h->size < 16 || h->size + (byte*)h - hunk_base > hunk_size) { + if (h->size < 16 || h->size + reinterpret_cast(h) - hunk_base > hunk_size) { Sys_Error("Hunk_Check: bad size"); } - h = (hunk_t*)((byte*)h + h->size); + h = reinterpret_cast(reinterpret_cast(h) + h->size); } } @@ -376,7 +376,7 @@ void* Hunk_Alloc(int size, const char* name) Sys_Error("Hunk_Alloc: failed on %i bytes", size); } - h = (hunk_t*)(hunk_base + hunk_low_used); + h = reinterpret_cast(hunk_base + hunk_low_used); hunk_low_used += size; Cache_FreeLow(hunk_low_used); @@ -463,7 +463,7 @@ void* Hunk_HighAllocName(int size, const char* name) hunk_high_used += size; Cache_FreeHigh(hunk_high_used); - h = (hunk_t*)(hunk_base + hunk_size - hunk_high_used); + h = reinterpret_cast(hunk_base + hunk_size - hunk_high_used); memset(h, 0, size); h->size = size; @@ -538,7 +538,7 @@ void Cache_Move(cache_system_t* c) new_cs->user = c->user; Q_memcpy(new_cs->name, c->name, sizeof(new_cs->name)); Cache_Free(c->user); - new_cs->user->data = (void*)(new_cs + 1); + new_cs->user->data = new_cs + 1; } else { // Con_Printf ("cache_move failed\n"); @@ -555,15 +555,13 @@ Throw things out until the hunk can be expanded to the given point */ void Cache_FreeLow(int new_low_hunk) { - cache_system_t* c; - while (1) { - c = cache_head.next; + cache_system_t* c = cache_head.next; if (c == &cache_head) { return; // nothing in cache at all } - if ((byte*)c >= hunk_base + new_low_hunk) { + if (reinterpret_cast(c) >= hunk_base + new_low_hunk) { return; // there is space to grow the hunk } @@ -580,16 +578,14 @@ Throw things out until the hunk can be expanded to the given point */ void Cache_FreeHigh(int new_high_hunk) { - cache_system_t *c, *prev; - - prev = NULL; + cache_system_t* prev = NULL; while (1) { - c = cache_head.prev; + cache_system_t* c = cache_head.prev; if (c == &cache_head) { return; // nothing in cache at all } - if ((byte*)c + c->size <= hunk_base + hunk_size - new_high_hunk) { + if (reinterpret_cast(c) + c->size <= hunk_base + hunk_size - new_high_hunk) { return; // there is space to grow the hunk } @@ -645,7 +641,7 @@ cache_system_t* Cache_TryAlloc(int size, qboolean nobottom) Sys_Error("Cache_TryAlloc: %i is greater then free hunk", size); } - new_cs = (cache_system_t*)(hunk_base + hunk_low_used); + new_cs = reinterpret_cast(hunk_base + hunk_low_used); memset(new_cs, 0, sizeof(*new_cs)); new_cs->size = size; @@ -659,12 +655,12 @@ cache_system_t* Cache_TryAlloc(int size, qboolean nobottom) // search from the bottom up for space - new_cs = (cache_system_t*)(hunk_base + hunk_low_used); + new_cs = reinterpret_cast(hunk_base + hunk_low_used); cs = cache_head.next; do { if (!nobottom || cs != cache_head.next) { - if ((byte*)cs - (byte*)new_cs >= size) { // found space + if (reinterpret_cast(cs) - reinterpret_cast(new_cs) >= size) { // found space memset(new_cs, 0, sizeof(*new_cs)); new_cs->size = size; @@ -680,12 +676,12 @@ cache_system_t* Cache_TryAlloc(int size, qboolean nobottom) } // continue looking - new_cs = (cache_system_t*)((byte*)cs + cs->size); + new_cs = reinterpret_cast(reinterpret_cast(cs) + cs->size); // FIX: If the block we just checked was below the new Hunk boundary, // clamp new_cs back up to the Hunk boundary to prevent overlapping! - if ((byte*)new_cs < hunk_base + hunk_low_used) { - new_cs = (cache_system_t*)(hunk_base + hunk_low_used); + if (reinterpret_cast(new_cs) < hunk_base + hunk_low_used) { + new_cs = reinterpret_cast(hunk_base + hunk_low_used); } cs = cs->next; @@ -693,7 +689,7 @@ cache_system_t* Cache_TryAlloc(int size, qboolean nobottom) } while (cs != &cache_head); // try to allocate one at the very end - if (hunk_base + hunk_size - hunk_high_used - (byte*)new_cs >= size) { + if (hunk_base + hunk_size - hunk_high_used - reinterpret_cast(new_cs) >= size) { memset(new_cs, 0, sizeof(*new_cs)); new_cs->size = size; @@ -766,7 +762,7 @@ void Cache_Free(cache_user_t* c) Sys_Error("Cache_Free: not allocated"); } - cs = ((cache_system_t*)c->data) - 1; + cs = reinterpret_cast(c->data) - 1; cs->prev->next = cs->next; cs->next->prev = cs->prev; @@ -790,7 +786,7 @@ void* Cache_Check(cache_user_t* c) return NULL; } - cs = ((cache_system_t*)c->data) - 1; + cs = reinterpret_cast(c->data) - 1; // move to head of LRU Cache_UnlinkLRU(cs); @@ -806,8 +802,6 @@ Cache_Alloc */ void* Cache_Alloc(cache_user_t* c, int size, const char* name) { - cache_system_t* cs; - if (c->data) { Sys_Error("Cache_Alloc: allready allocated"); } @@ -820,9 +814,9 @@ void* Cache_Alloc(cache_user_t* c, int size, const char* name) // find memory for it while (1) { - cs = Cache_TryAlloc(size, false); + cache_system_t* cs = Cache_TryAlloc(size, false); if (cs) { - strncpy_s(cs->name, sizeof(cs->name), name, sizeof(cs->name) - 1); + strlcpy(cs->name, name, sizeof(cs->name) - 1); c->data = (void*)(cs + 1); cs->user = c; break; @@ -852,7 +846,7 @@ void Memory_Init(void* buf, int size) int p; int zonesize = DYNAMIC_SIZE; - hunk_base = (byte*)buf; // C++ Fix: Explicitly cast void* to byte* + hunk_base = static_cast(buf); // C++ Fix: Explicitly cast void* to byte* hunk_size = size; hunk_low_used = 0; hunk_high_used = 0; @@ -868,7 +862,7 @@ void Memory_Init(void* buf, int size) } // C++ Fix: Explicitly cast void* returned from Hunk_AllocName - mainzone = (memzone_t*)Hunk_Alloc(zonesize, "zone"); + mainzone = static_cast(Hunk_Alloc(zonesize, "zone")); Z_ClearZone(mainzone, zonesize); } From eee275400c9325980cce9d020dc316356d2357fc Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Sun, 12 Jul 2026 12:05:37 +0000 Subject: [PATCH 6/6] fix warnings --- CMakeLists.txt | 3 +++ src/audio.cpp | 1 - src/audio.hpp | 6 ++---- src/host_cmd.cpp | 6 +++--- src/menu.cpp | 2 +- src/server.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36a3eb1..acf7c10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,9 @@ if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "GNU|AppleClang") message(STATUS "Using IPO/LTO.") endif() endif() + add_compile_options(-Wno-unused-result) + add_compile_options(-Wno-unused-variable) + add_compile_options(-Wno-unused-but-set-variable) endif() add_compile_options(-Wunreachable-code) # Warn about unreachable code paths add_compile_options(-ffunction-sections) # Put each function in its own section diff --git a/src/audio.cpp b/src/audio.cpp index 94f4a97..61bc123 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -1,6 +1,5 @@ // audio.cpp -- merged audio subsystem (snd_*.cpp) // Contains: sound control, caching, mixing, and SDL audio driver -#pragma warning(disable: 4324) #include #include "quakedef.hpp" diff --git a/src/audio.hpp b/src/audio.hpp index 8f6db5f..79c8c53 100644 --- a/src/audio.hpp +++ b/src/audio.hpp @@ -24,9 +24,7 @@ struct sfx_s { using sfx_t = sfx_s; -// !!! if this is changed, it much be changed in asm_i386.h too !!! -#pragma warning(push) -#pragma warning(disable: 4200) // Silence nonstandard extension: zero-sized array warning +#pragma pack(push,1) struct sfxcache_t { int length; int loopstart; @@ -35,7 +33,7 @@ struct sfxcache_t { int stereo; byte data[]; // variable sized }; -#pragma warning(pop) +#pragma pack(pop) struct dma_t { std::atomic gamealive; diff --git a/src/host_cmd.cpp b/src/host_cmd.cpp index 00f0533..a0036e3 100644 --- a/src/host_cmd.cpp +++ b/src/host_cmd.cpp @@ -582,7 +582,7 @@ void Host_Loadgame_f(void) return; } - fscanf(f, "%s\n", str, (unsigned)sizeof(str)); + fscanf(f, "%s\n", str); for (i = 0; i < NUM_SPAWN_PARMS; i++) { fscanf(f, "%f\n", &spawn_parms[i]); } @@ -592,7 +592,7 @@ void Host_Loadgame_f(void) Cvar::SetValue("skill", (float)current_skill); - fscanf(f, "%s\n", mapname, (unsigned)sizeof(mapname)); + fscanf(f, "%s\n", mapname); fscanf(f, "%f\n", &time); CL_Disconnect_f(); @@ -610,7 +610,7 @@ void Host_Loadgame_f(void) // load the light styles for (i = 0; i < MAX_LIGHTSTYLES; i++) { - fscanf(f, "%s\n", str, (unsigned)sizeof(str)); + fscanf(f, "%s\n", str); sv.lightstyles[i] = (char *) Hunk_Alloc((int)strlen(str) + 1); strlcpy(sv.lightstyles[i], str, strlen(str) + 1); } diff --git a/src/menu.cpp b/src/menu.cpp index d275c80..d748f7f 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -495,7 +495,7 @@ void M_ScanSaves(void) } fscanf(f, "%i\n", &version); - fscanf(f, "%79s\n", name, (unsigned)sizeof(name)); + fscanf(f, "%79s\n", name); strlcpy(m_filenames[i], name, sizeof(m_filenames[i]) - 1); // change _ back to space diff --git a/src/server.cpp b/src/server.cpp index f4c3c4d..547848a 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3241,7 +3241,7 @@ Returns false if the client should be killed */ qboolean SV_ReadClientMessage(void) { - int ret; + int ret = 1; int msg_cmd; char* s;