diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 633b70729..967a175d7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,22 +66,25 @@ jobs: run: | sudo apt update sudo apt install -y --no-install-recommends \ - ninja-build cmake g++ libgtest-dev libsdl2-dev zlib1g-dev libspdlog-dev + ninja-build cmake g++ curl pkg-config autoconf automake libtool libltdl-dev make python3-jinja2 libx11-dev libxft-dev libxext-dev libwayland-dev libxkbcommon-dev libegl1-mesa-dev libibus-1.0-dev libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev - name: Install Windows dependencies if: ${{ matrix.os.runner == 'windows-latest' }} run: choco install ninja - + - uses: ilammy/msvc-dev-cmd@v1 if: ${{ matrix.os.runner == 'windows-latest' }} with: arch: win64 + - uses: lukka/run-vcpkg@v11 + with: + vcpkgJsonGlob: vcpkg.json + - name: Configure CMake env: CC: ${{ matrix.os.cc }} CXX: ${{ matrix.os.cxx }} - VCPKG_ROOT: C:/vcpkg run: cmake --preset ${{ matrix.os.preset }} -DBUILD_TESTING=ON -DENABLE_LOGGER=ON -DFORCE_PORTABLE_INSTALL=ON -DBUILD_EDITOR=ON - name: Build ${{ matrix.build_type }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..fefaa13a7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,30 @@ +name: Release source tarball +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Generate git hash and tarball + run: | + sudo apt update + sudo apt install -y ninja-build cmake g++ libsdl2-dev zlib1g-dev + cmake --preset linux + cmake --build --preset linux -t get_git_hash + cmake --build --preset linux -t package_source + + - name: Release + uses: ncipollo/release-action@v1.14.0 + with: + artifacts: "builds/linux/Descent3-*-Source.tar.xz" + draft: true + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/2dlib/CMakeLists.txt b/2dlib/CMakeLists.txt index 5eff141e4..ab9827e2f 100644 --- a/2dlib/CMakeLists.txt +++ b/2dlib/CMakeLists.txt @@ -1,3 +1,6 @@ +set(HEADERS + gr.h + lib2d.h) set(CPPS font.cpp hardsurf.cpp @@ -9,7 +12,7 @@ set(CPPS viewport.cpp ) -add_library(2dlib STATIC ${CPPS}) +add_library(2dlib STATIC ${HEADERS} ${CPPS}) target_link_libraries(2dlib PRIVATE cfile mem diff --git a/2dlib/font.cpp b/2dlib/font.cpp index aedfd724f..b4086d2e0 100644 --- a/2dlib/font.cpp +++ b/2dlib/font.cpp @@ -554,7 +554,7 @@ void grFont::translate_to_surfaces(int slot) { void grFont::translate_mono_char(grSurface *sf, int x, int y, int index, gr_font_file_record *ft, int width) { int row, col; // byte width of char int rowsize; - uint8_t bit_mask = 0, byte; + uint8_t bit_mask = 0, byte = 0; uint8_t *fp; fp = ft->char_data[index]; diff --git a/AudioEncode/CMakeLists.txt b/AudioEncode/CMakeLists.txt index 70d161cf5..9e5079a36 100644 --- a/AudioEncode/CMakeLists.txt +++ b/AudioEncode/CMakeLists.txt @@ -1,10 +1,14 @@ +set(HEADERS + adecode.h + aencode.h + audio_encode.h) set(CPPS adecode.cpp aencode.cpp encoder.cpp ) -add_library(AudioEncode STATIC ${CPPS}) +add_library(AudioEncode STATIC ${HEADERS} ${CPPS}) target_link_libraries(AudioEncode PRIVATE libacm ) diff --git a/AudioEncode/encoder.cpp b/AudioEncode/encoder.cpp index 2e8c2eba8..3b310cfa3 100644 --- a/AudioEncode/encoder.cpp +++ b/AudioEncode/encoder.cpp @@ -42,9 +42,9 @@ bool aenc_Compress(char *input_filename, char *output_filename, const int *input FILE *in, *out; int32_t result; - int levels, samples_per_subband; - unsigned sample_rate, channels; - float factor, volume_scale; + int levels = 0, samples_per_subband = 0; + unsigned sample_rate = 0, channels = 0; + float factor = 0, volume_scale = 0; int levels_set = 0, samples_per_subband_set = 0, sample_rate_set = 0, channels_set = 0, factor_set = 0, volume_scale_set = 0; @@ -105,7 +105,8 @@ bool aenc_Compress(char *input_filename, char *output_filename, const int *input } if (!levels_set && !samples_per_subband_set) { - levels = 7, samples_per_subband = 16; + levels = 7; + samples_per_subband = 16; } else if (!samples_per_subband_set) { samples_per_subband = 2048 / (1 << levels); diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 000000000..7311f698d --- /dev/null +++ b/BUILD.md @@ -0,0 +1,170 @@ + +# Building Descent 3 Open Source + +## Dependencies +The build process uses [**CMake**](https://cmake.org/) and, by default, [**Ninja**](https://ninja-build.org/). You must install these; the project cannot locate them for you. The source code depends on [**SDL2**](https://github.com/libsdl-org/SDL/tree/SDL2) and [**zlib**](https://github.com/madler/zlib). You can supply these dependencies yourself via your system's library management tools, or the build system can locate the dependencies for you using [vcpkg](https://github.com/microsoft/vcpkg), a cross-platform dependency-management system developed by Microsoft. The official builds source their dependencies from vcpkg. + +## Installing and using vcpkg +* When building for Windows, vcpkg is already installed and configured when using any of the Visual Studio command prompts (either actual Command Prompt, or PowerShell). +* For Android, Linux or Mac (or non-standard-Windows) configurations, you will need to install vcpkg locally by cloning https://github.com/microsoft/vcpkg and setting your `VCPKG_ROOT` env var to the repository location. With this environment variable set, the build will automatically locate its dependencies. + +## Building - Windows +1. **Install the prerequisite build tools.** + + Make sure that you have Git and Visual Studio 2022 with the “Desktop development with C++” workload and the “C++ MFC for latest v143 build tools (x86 & x64)” component. If you don’t already have those installed or you aren’t sure, then open an elevated Command Prompt and run: + + ```batch + winget install Git.Git Microsoft.VisualStudio.2022.Community + + "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\setup.exe" modify^ + --passive^ + --channelId VisualStudio.17.Release^ + --productId Microsoft.VisualStudio.Product.Community^ + --add Microsoft.VisualStudio.Workload.NativeDesktop;includeRecommended^ + --add Microsoft.VisualStudio.Component.VC.ATLMFC + ``` + + **NOTE:** + Builds _must_ be performed in one of the Visual Studio-provided **x64 Native Tools** command prompts ("x64 Native Tools Command Prompt" or "x64 Native Tools PowerShell"), _not_ a standard Command Prompt or PowerShell. The VS prompts will already have vcpkg installed and configured for use, so no dependency management is needed. + +2. **Clone the Descent3 source code.** + + Open a "x64 Native Tools Command Prompt" or "x64 Native Tools PowerShell" and run: + ```batch + git clone https://github.com/DescentDevelopers/Descent3 + ``` + +4. **Build Descent3.** + + ```batch + cd Descent3 + cmake --preset win + cmake --build --preset win --config [Debug|Release] + ``` + See [Build Options](#build-options) below for more information on `Debug` vs `Release`. + +Once CMake finishes, the built files will be put in `builds\win\Descent3\Debug` or `builds\win\Descent3\Release`. + +## Building - macOS +1. **Install the prerequisite build tools.** + + * Make sure that [Xcode](https://developer.apple.com/xcode) is installed. + * Make sure that [Homebrew](https://brew.sh) is installed. + +2. **Acquire the library dependencies.** + + * If you would like to use vcpkg: + ```sh + git clone https://github.com/microsoft/vcpkg + export VCPKG_ROOT="$PWD/vcpkg" + ``` + **NOTE:** + You will need `$VCPKG_ROOT` defined in the environment for all build runs. It is a good idea to set this in your `.bashrc` or equivalent. + * If you would like to manage the code dependencies yourself: + ```sh + brew install sdl2 zlib googletest + ``` + +3. **Clone the Descent3 source code.** + + ```sh + git clone https://github.com/DescentDevelopers/Descent3 + ``` + +4. **Build Descent3.** + + ```sh + cd Descent3 + brew bundle install + cmake --preset mac + cmake --build --preset mac --config [Debug|Release] + ``` + See [Build Options](#build-options) below for more information on `Debug` vs `Release`. + +Once CMake finishes, the built files will be put in `builds/mac/Descent3/Debug` or `builds/mac/Descent3/Release`. + +## Building - Linux +1. **Install the prerequisite build tools.** + + * APT users (Debian, Ubuntu) + ```sh + sudo apt update + sudo apt install -y --no-install-recommends git ninja-build cmake g++ + ``` + * DNF users (Red Hat, Fedora) + ```sh + sudo dnf update --refresh + sudo dnf install -y git ninja-build cmake gcc-c++ + ``` + +2. **Acquire the library dependencies.** + + * If you would like to use vcpkg: + 1. Clone vcpkg: + ```sh + git clone https://github.com/microsoft/vcpkg + export VCPKG_ROOT="$PWD/vcpkg" + ``` + **NOTE:** + You will need `$VCPKG_ROOT` defined in the environment for all build runs. It is a good idea to set this in your `.bashrc` or equivalent. + 2. Install vcpkg-needed build tools and dependencies: + * APT users + ```sh + sudo apt install -y --no-install-recommends curl pkg-config autoconf automake libtool libltdl-dev make python3-jinja2 libx11-dev libxft-dev libxext-dev libwayland-dev libxkbcommon-dev libegl1-mesa-dev libibus-1.0-dev libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev + ``` + * DNF users + ```sh + sudo dnf install -y autoconf automake libtool perl-open perl-FindBin python-jinja2 libX11-devel libXft-devel libXext-devel wayland-devel libxkbcommon-devel mesa-libEGL-devel ibus-devel alsa-lib-devel pulseaudio-libs-devel + ``` + * If you would like to manage the code dependencies yourself: + * APT users + ```sh + sudo apt install -y --no-install-recommends libsdl2-dev zlib1g-dev libgtest-dev + ``` + * DNF users + ```sh + sudo dnf install -y SDL2-devel zlib-devel gtest + ``` + +3. **Clone the Descent3 source code.** + + ```sh + git clone https://github.com/DescentDevelopers/Descent3 + ``` + +4. **Build Descent3.** + + ```sh + cd Descent3 + cmake --preset linux + cmake --build --preset linux --config [Debug|Release] + ``` + See [Build Options](#build-options) below for more information on `Debug` vs `Release`. + +Once CMake finishes, the built files will be put in `builds/linux/Descent3/Debug` or `builds/linux/Descent3/Release`. + +## Build Options + +The Descent3 build can be customized by [setting CMake variables on the command line](https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-D) during its "Configuration" phase (the command without the `--build` option). To set a variable, you prepend the variable name with `-D` and then append the value, all as one single parameter. For example: +```sh +cmake --preset linux -DENABLE_LOGGER=ON +``` + +**NOTE:** CMake variables, or more technically _CMake cache entries_, will persist in their values until they are explicitly cleared. So, if you set a variable and then run another CMake command _without_ that variable specified, the variable will still be set. Variables must be explicitly unset, or the `builds/` directory cleaned, in order to be cleared. + +| Option | Description | Default | +| ------ | ----------- | ------- | +| `CMAKE_BUILD_TYPE`
(or just [`--config`](https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-build-config), without the `-D` syntax) |

`Debug` builds are generally larger, slower and contain extra correctness checks that will validate game data and interrupt gameplay when problems are detected.

`Release` builds are optimized for size and speed and do not include debugging information, which makes it harder to find problems.

| `Debug` | +| `BUILD_EDITOR` | _(Windows-only)_ Build internal editor. | `OFF` | +| `BUILD_TESTING` | Enable testing. Requires GTest. | `OFF` | +| `ENABLE_LOGGER` | Enable logging to the terminal. | `OFF` | +| `ENABLE_MEM_RTL` | Enable Real-time library memory management functions (disable to verbose memory allocations). | `ON` | +| `FORCE_COLORED_OUTPUT` | Always produce ANSI-colored compiler warnings/errors (GCC/Clang only; esp. useful with Ninja). | `OFF` | +| `FORCE_PORTABLE_INSTALL` | Install all files into local directory defined by `CMAKE_INSTALL_PREFIX`. | `ON` | +| `USE_VCPKG` | Explicitly control whether or not to use vcpkg for dependency resolution. `ON` requires the environment variable `VCPKG_ROOT` to be set. | Determined by the existence of `VCPKG_ROOT` in the environment: If it exists, vcpkg is used. | diff --git a/Brewfile b/Brewfile index ffd96d258..2f716b79f 100644 --- a/Brewfile +++ b/Brewfile @@ -9,3 +9,5 @@ brew "ninja" # zlib brew "zlib" + +brew "glm" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..09f617053 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,90 @@ +# Descent 3 Open Source - Changelog + +## 1.5.0 - August 2024 + +This is the first release of the community port of Descent 3, release as open source software under the GPLv3 license on April 16th 2024. + +This release is the work of 28 individual contributors over 4 months. It fills in the gaps left in the never-released 1.5 patch of the game, and makes it more accessible and convinient to run on modern devices. + +Our focus for this release has been compatibility with modern CPUs and developer experience improvement, while keeping features mostly identical to the code initially released. The next releases will be given more latitude to improve in-game player experience. + +Descent 3 now runs on 64-bit Linux, Windows and MacOS using SDL2, on AMD64 as well as ARM64 CPUs. 32-bit support has been dropped. + + +### Added + - New HogMaker utility script to build platform-specific HOG files containing level scripts (#122, #143, #153, #275, #277, #298) + - Set up gtest as a unit testing framework (#171, #251) + - Show git hash in main menu (#224, #440, #451) + + +### Changed + - Use SDL2 on all platforms (#241, #457). Upon code release, the Windows was using an old version of DirectX for input and window management, and Linux and MacOS were using SDL1.2 from the Loki port of the game. All operating systems now use a common SDL2 back-end. + - Use a configuration file instead of the registry to store game settings on Windows, to be consistent with the other OSes. + - Support 64-bit builds on all platforms (#59, #158, #178, #179, #192, #233, #272, #354, #356, #357, #385, #397). 32bit compatibility for existing savefiles and demos is not functional. + - Eliminate assembly code specific to x86 (#72). + - Add icons to Windows and MacOS bundles (#498) + - Replace OS-specific filesystem functions by C++17 std::filesystem in the CFile and DDIO modules (#383, #443, #475, #484, #486, #499). + - Use standard temporary directory for cache files instead of game data directory (#500) + - Implement new byteswap functions (#85, #165, #172) + - Build the internal level editor using MFC UI framework. The executable is not included in this release because it is still very unstable and not usable, and can only run on Windows (32-bit) (#397, #476) + - Render the game to an OpenGL Frame Buffer Object at the game's resolution (#437) + - Format code-base using clang-format (#13, #16, #19, #24, #51, #438) + - Use upstream libacm 1.3 for ACM audio decoding (#135, #191, #221) + - Implement a new MVE video decoder based on the open source implementation used in D2X (#289). MVE movies for intro and cutscenes can now be played on all platforms. OGV movies shipped with the Linux game cannot be played yet. + - Use the "push" model of filling sound buffer for MVE playback (#491) + - Write a new implementation of the md5 algorithm used to compute checksums. (#316) + - Use VCPKG to build third-party dependencies not included in the code tree, such as SDL2 and zlib (#137, #430, #469, #512). + - Set up automated build and testing using Github Actions for Linux (clang/gcc), Windows (MSVC) and MacOS (apple-clang, x64 & arm64) (#14, #28, #29, #45, #50, #60, #123, #133, #139, #155, #166, #177, #182) + - Modernize build system: require CMake 3.20, use present-day CMake practices (#20, #63, #77, #86, #99, #104, #127, #131, #144, #220, #225, #227, #235, #256, #318, #340, #400, #407, #422, #460, #463, #482, #504) + - Ensure compatibility with popular compilers, convert misc. pieces of code to modern C++ (#17, #20, #23, #40, #54, #58, #70, #108, #304, #328, #344, #358, #388, #405, #416) + - Mark relevant variables and functions as static (#185) + - Update the module system: isolate code for independant sub-modules in separate directories and CMake targets (#76, #89, #91, #195, #367, #374, #448, #470, #502) + - Document build procedure and usage on all platforms (#116, #118, #119, #124, #147, #154, #170, #174, #175, #184, #190, #204, #210, #211, #222, #259, #261, #270, #285, #297, #384, #413, #435) + - Unifiy Windows & Unix command line arguments: --foo, -foo and +foo is accepted on any OS (#199) + - Refactor CleanupStr in misc/pstring.cpp (#207) + - Change non-specific types (e.g. unsigned int) to their stdint specified counterparts (e.g. `uint32_t`) (#268, #464) + - Support case-insensitive loading of content files (#294) + - Build TCP/IP and PXO multiplayer modules (#296, #302, #420, #424, #432) + - Refactor renderer: move non-OpenGL specific code to a base file, abstract triangle rendering code (#315, #323, #336) + - Save screenshots in PNG format instead of the legacy TGA format (#325, #348) + - Increment max cells value to increase render distance for outdoor terrain (#338) + - Use chrono C++11 steady_clock for time measurement (#394) + - Enable real-time library memory functions by default (#436, #445, #456) + - Change `__LINUX__` defines to `POSIX` for general OS checks (#492) + + +### Fixed + - Cleanup warnings issued by modern compilers (#57, #74, #82, #87, #89, #109, #117, #218, #349, #387, #428, #434, #478, #507) + - Replace sprintf by snprintf(#78, #252, #266) + - Add object unlink sanity check (#140) + - Use a static background image in the main menu if the video file is not present (#152) + - Add virtual default constructors on abstract classes (#219) + - Fix cursor not being grabbed on macOS (#223) + - Fix detection of mercenary installation, where hogfiles are not the same for CD and digital installation (#260) + - Fix some out-of-bounds array access (#263) + - Fix for Level 5 script; Make CustomText2 centered on Y axis (#307) + - Fix a crash when calling `quit` in the server console in dedicated server mode (#370) + - Fix a game crash when launching with `-useexedir` argument (#372) + - `-nomousegrab` command-line argument now works correctly (#401) + - Only close SDL audio if it's open (#409) + - Do not segfault when critical game files are missing (#414) + - Avoid server crash during client connection (#431) + - Fix `-aspect` aspect ratio argument for ship selection screen (#454) + - Remove usage of non-glibc `GLOB_PERIOD` (#462) + - Fix endian issues with iff importer (#481) + - Fix a crash with `-nointro` command-line argument + - Support `-nosound` option for movie playbacks + - Use UTF-8 in more places on Windows using a manifest file (#494) + + +### Removed + - Remove unused supporting modules for obsolete hardware or unused features: Aureal 3D sound cards (#345), GameGauge performance benchmark (#238, #337), CD-ROM asset loading (#452, #455), Intellivibe interface for VRF Tactile Feedback System (#453), AngelScript (#15), legacy Macintosh (#188), IPX/SPX network protocol support (#237), Rock'n Ride (#292) + - Unused library dynamic loading headers (#283) + - References to libGLU (#246) + - References to X11 and glX (#247, #244) + - Unused mono debug code (#410) + - Unused software renderer and d3m files (#305, #314, #321) + - DDAccess.h header and access ring definitions (#342) + - DMFC_DLL definition (#441) + - Misc. removal of unfinished or unused code (#21, #55, #189, #197, #234, #245, #299, #303, #334, #396, #408) + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b4241cb2d..74a530ac5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,21 +5,41 @@ if(NOT CMAKE_BUILD_TYPE AND NOT DEFINED ENV{CMAKE_BUILD_TYPE}) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "default build type") endif() -project(Descent3 - LANGUAGES C CXX - VERSION 1.5.0 -) - -option(FORCE_COLORED_OUTPUT "Always produce ANSI-colored compiler warnings/errors (GCC/Clang only; esp. useful with ninja)." OFF) +option(FORCE_COLORED_OUTPUT "Always produce ANSI-colored compiler warnings/errors (GCC/Clang only; esp. useful with Ninja)." OFF) option(FORCE_PORTABLE_INSTALL "Install all files into local directory defined by CMAKE_INSTALL_PREFIX" ON) option(ENABLE_LOGGER "Enable logging to the terminal" OFF) option(ENABLE_MEM_RTL "Enable Real-time library memory management functions (disable to verbose memory allocations)" ON) option(BUILD_TESTING "Enable testing. Requires GTest." OFF) +set(USE_VCPKG "DEFAULT" CACHE STRING "Use vcpkg for dependency management. DEFAULT defers to existence of $VCPKG_ROOT environment variable.") +set_property(CACHE USE_VCPKG PROPERTY STRINGS "DEFAULT" "ON" "OFF") if(CMAKE_SYSTEM_NAME STREQUAL "Windows") option(BUILD_EDITOR "Build internal editor" OFF) endif() +if(USE_VCPKG) + if(DEFINED ENV{VCPKG_ROOT}) + if (CMAKE_TOOLCHAIN_FILE) + cmake_path(ABSOLUTE_PATH CMAKE_TOOLCHAIN_FILE NORMALIZE OUTPUT_VARIABLE VCPKG_CHAINLOAD_TOOLCHAIN_FILE) + endif() + + set(VCPKG_TOOLCHAIN_FILE "scripts/buildsystems/vcpkg.cmake") + cmake_path(ABSOLUTE_PATH VCPKG_TOOLCHAIN_FILE BASE_DIRECTORY $ENV{VCPKG_ROOT} NORMALIZE OUTPUT_VARIABLE CMAKE_TOOLCHAIN_FILE) + + if(CMAKE_TOOLCHAIN_FILE STREQUAL VCPKG_CHAINLOAD_TOOLCHAIN_FILE) + # prevent endless recursion + unset(VCPKG_CHAINLOAD_TOOLCHAIN_FILE) + endif() + elseif(NOT USE_VCPKG STREQUAL "DEFAULT") + message(WARNING "USE_VCPKG=${USE_VCPKG} but ENV{VCPKG_ROOT} not set; will use system-provided libraries. Did you forget to set VCPKG_ROOT in your environment?") + endif() +endif() + +project(Descent3 + LANGUAGES C CXX + VERSION 1.5.0 +) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -103,7 +123,7 @@ add_custom_command( ) install( - FILES LICENSE README.md THIRD_PARTY.md + FILES CHANGELOG.md USAGE.md README.md BUILD.md LICENSE THIRD_PARTY.md DESTINATION ${CMAKE_INSTALL_DOCDIR} ) @@ -233,3 +253,17 @@ add_subdirectory(tools) add_subdirectory(netcon) add_subdirectory(netgames) add_subdirectory(scripts) + +# Packaging stuff +set(CPACK_SOURCE_GENERATOR "TXZ") +set(CPACK_SOURCE_IGNORE_FILES + ".git/" + ".github/" + ".idea" + build[s]/ + cmake-build-* + ".*~$" +) +set(CPACK_VERBATIM_VARIABLES YES) +include(CPack) + diff --git a/CMakePresets.json b/CMakePresets.json index 0b5f90e51..23e5c4a11 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -21,8 +21,7 @@ "architecture": { "strategy": "external", "value": "x64" - }, - "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + } }, { "name": "mac", diff --git a/Descent3/CMakeLists.txt b/Descent3/CMakeLists.txt index 146e865f7..7a71ab635 100644 --- a/Descent3/CMakeLists.txt +++ b/Descent3/CMakeLists.txt @@ -1,7 +1,28 @@ set(HEADERS - aiambient.h AIGoal.h AIMain.h + BOA.h + Briefing.h + BriefingParse.h + ConfigItem.h + CtlCfgElem.h + D3ForceFeedback.h + DeathInfo.h + DllWrappers.h + Inventory.h + LoadLevel.h + Mission.h + NewPyroGauges.h + ObjScript.h + PilotPicsAPI.h + SmallViews.h + TelCom.h + TelComAutoMap.h + TelComCargo.h + TelComEffects.h + TelComEfxStructs.h + TelComGoals.h + aiambient.h aipath.h aistruct.h aistruct_external.h @@ -11,31 +32,25 @@ set(HEADERS attach.h audiotaunts.h bnode.h - BOA.h - Briefing.h - BriefingParse.h bsp.h buddymenu.h cinematics.h cockpit.h config.h - ConfigItem.h controls.h credits.h - CtlCfgElem.h ctlconfig.h ctlconfigtxt.h - D3ForceFeedback.h + d3movie.h + d3music.h d3serial.h damage.h damage_external.h - DeathInfo.h deathinfo_external.h debuggraph.h descent.h difficulty.h difficulty_external.h - DllWrappers.h door.h doorway.h fireball.h @@ -56,23 +71,19 @@ set(HEADERS hotspotmap.h hud.h init.h - Inventory.h levelgoal.h levelgoal_external.h lighting.h lightmap_info.h list.h - LoadLevel.h localization.h marker.h matcen.h matcen_external.h menu.h - Mission.h mission_download.h mmItem.h multi.h - multisafe.h multi_client.h multi_dll_mgr.h multi_external.h @@ -80,7 +91,7 @@ set(HEADERS multi_server.h multi_ui.h multi_world_state.h - NewPyroGauges.h + multisafe.h newui.h newui_core.h object.h @@ -88,12 +99,10 @@ set(HEADERS object_lighting.h objinfo.h objinit.h - ObjScript.h osiris_dll.h osiris_predefs.h osiris_share.h pilot.h - PilotPicsAPI.h pilot_class.h player.h player_external.h @@ -113,7 +122,6 @@ set(HEADERS screens.h ship.h slew.h - SmallViews.h soar.h soar_helpers.h sounds.h @@ -122,12 +130,6 @@ set(HEADERS splinter.h stringtable.h subtitles.h - TelCom.h - TelComAutoMap.h - TelComCargo.h - TelComEffects.h - TelComEfxStructs.h - TelComGoals.h terrain.h trigger.h vclip.h @@ -313,8 +315,12 @@ target_link_libraries(Descent3 PRIVATE music networking physics renderer rtperformance sndlib ui unzip vecmat md5 ${PLATFORM_LIBS}) target_include_directories(Descent3 PRIVATE ${PROJECT_BINARY_DIR}/lib) +target_link_options(Descent3 PRIVATE $<$:/DEBUG:FULL>) add_dependencies(Descent3 get_git_hash Direct_TCP_IP_Hog HogFull NetgamesDir Parallax_Online_Hog) install(TARGETS Descent3 RUNTIME BUNDLE DESTINATION .) +if(MSVC) + install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() if(BUILD_TESTING) add_subdirectory(tests) diff --git a/Descent3/Game2DLL.cpp b/Descent3/Game2DLL.cpp index 69a00c030..eb04412be 100644 --- a/Descent3/Game2DLL.cpp +++ b/Descent3/Game2DLL.cpp @@ -572,6 +572,8 @@ bool InitGameModule(const char *name, module *mod) { // Make the dll filename #if defined(WIN32) snprintf(dll_name, sizeof(dll_name), "%s.dll", name); +#elif defined(MACOSX) + snprintf(dll_name, sizeof(dll_name), "%s.dylib", name); #else snprintf(dll_name, sizeof(dll_name), "%s.so", name); #endif diff --git a/Descent3/Mission.cpp b/Descent3/Mission.cpp index b36c9f8f8..8706865b1 100644 --- a/Descent3/Mission.cpp +++ b/Descent3/Mission.cpp @@ -1635,20 +1635,15 @@ bool DoMissionBriefing(int level) { return ret; } extern bool FirstGame; -bool Skip_next_movie = false; + // --------------------------------------------------------------------------- // play movie void DoMissionMovie(const char *movie) { - char temppath[_MAX_PATH]; if (PROGRAM(windowed)) { mprintf(0, "Skipping movie...can't do in windowed mode!\n"); return; } - // Don't play this movie the first time through. This is a horrible hack. - if (Skip_next_movie) { - Skip_next_movie = false; - return; - } + #ifdef D3_FAST return; #endif @@ -1657,8 +1652,8 @@ void DoMissionMovie(const char *movie) { ddio_MakePath(mpath, LocalD3Dir, "movies", movie, NULL); PlayMovie(mpath); } - // PlayMovie(movie); } + /////////////////////////////////////////////////////////////////////////////// // Script Management for Missions and Levels /////////////////////////////////////////////////////////////////////////////// diff --git a/Descent3/gamesave.cpp b/Descent3/gamesave.cpp index 310ec0a50..94a5b3f07 100644 --- a/Descent3/gamesave.cpp +++ b/Descent3/gamesave.cpp @@ -622,7 +622,7 @@ bool LoadGameDialog() { fp = fopen(pathname, "rb"); if (fp) { - int bm_handle; + int bm_handle = -1; int *pbm_handle; fclose(fp); @@ -1121,11 +1121,11 @@ void SGSObjects(CFILE *fp) { gs_WriteInt(fp, op->attach_parent_handle); if ((op->attach_ultimate_handle) && (OBJECT_HANDLE_NONE != op->attach_ultimate_handle)) { mprintf(0, "Object %d has an ultimate parent of %d (%d)\n", i, OBJNUM(ObjGet(op->attach_ultimate_handle)), - op->attach_parent_handle); + op->attach_parent_handle); } if ((op->attach_ultimate_handle) && (OBJECT_HANDLE_NONE != op->attach_parent_handle)) { mprintf(0, "Object %d has a parent of %d (%d)\n", i, OBJNUM(ObjGet(op->attach_parent_handle)), - op->attach_parent_handle); + op->attach_parent_handle); } gs_WriteInt(fp, pm->n_attach); diff --git a/Descent3/init.cpp b/Descent3/init.cpp index 5eed345cb..6bb665eb5 100644 --- a/Descent3/init.cpp +++ b/Descent3/init.cpp @@ -1059,7 +1059,7 @@ void PreInitD3Systems() { debugging = true; #endif - error_Init(debugging, false, PRODUCT_NAME); + error_Init(debugging, PRODUCT_NAME); if (FindArg("-lowmem")) Mem_low_memory_mode = true; @@ -1117,9 +1117,6 @@ void PreInitD3Systems() { #endif } -/* - Save game variables to the registry -*/ void SaveGameSettings() { char tempbuffer[TEMPBUFFERSIZE]; int tempint; diff --git a/Descent3/init.h b/Descent3/init.h index f7cc89af4..535d0457f 100644 --- a/Descent3/init.h +++ b/Descent3/init.h @@ -98,4 +98,9 @@ void RestartD3(); void InitMessage(const char *c, float progress = -1); +/** + * Save game variables to the registry + */ +void SaveGameSettings(); + #endif diff --git a/Descent3/menu.cpp b/Descent3/menu.cpp index 3e9119ba9..c0e45a07a 100644 --- a/Descent3/menu.cpp +++ b/Descent3/menu.cpp @@ -658,12 +658,12 @@ #include "menu.h" #include "mmItem.h" #include "game.h" -#include "gamesequence.h" #include "Mission.h" #include "multi_ui.h" #include "ctlconfig.h" #include "config.h" #include "gamesave.h" +#include "gamesequence.h" #include "demofile.h" #include "pilot.h" #include "LoadLevel.h" @@ -671,6 +671,8 @@ #include "mem.h" #include "args.h" #include "cinematics.h" +#include "multi_dll_mgr.h" +#include "newui_core.h" #ifdef _WIN32 #define USE_DIRECTPLAY @@ -681,9 +683,6 @@ #else bool Directplay_lobby_launched_game = false; #endif -#include "multi_dll_mgr.h" -#include "d3music.h" -#include "newui_core.h" #define IDV_QUIT 0xff // Menu Item Defines @@ -702,8 +701,7 @@ bool MenuLoadLevel(void); #endif // for command line joining of games bool Auto_connected = false; -// externed from init.cpp -extern void SaveGameSettings(); + // runs command line options. bool ProcessCommandLine(); // new game selection @@ -715,7 +713,6 @@ extern bool Demo_looping; bool FirstGame = false; int MainMenu() { - extern void ShowStaticScreen(char *bitmap_filename, bool timed = false, float delay_time = 0.0f); mmInterface main_menu; bool exit_game = false; bool exit_menu = false; @@ -1127,15 +1124,16 @@ static inline int generate_mission_listbox(newuiListBox *lb, int n_maxfiles, cha } return c; } -extern bool Skip_next_movie; + #define OEM_TRAINING_FILE "training.mn3" #define OEM_MISSION_FILE "d3oem.mn3" + bool MenuNewGame() { newuiTiledWindow menu; newuiSheet *select_sheet; newuiListBox *msn_lb; - char **filelist = NULL; - int n_missions, i, res; //,k + char **filelist = nullptr; + int n_missions, i, res; bool found = false; bool do_menu = true, load_mission = false, retval = true; #ifdef DEMO @@ -1150,18 +1148,10 @@ bool MenuNewGame() { return false; } #else -#ifdef RELEASE if ((!FindArg("-mission")) && (!FirstGame) && (-1 == Current_pilot.find_mission_data(TRAINING_MISSION_NAME))) { FirstGame = true; - char moviepath[_MAX_PATH]; - ddio_MakePath(moviepath, LocalD3Dir, "movies", "level1.mve", nullptr); - if (cfexist(moviepath)) { - PlayMovie(moviepath); - } - Skip_next_movie = true; - if (LoadMission("training.mn3")) { CurrentPilotUpdateMissionStatus(true); // go into game mode. @@ -1190,7 +1180,7 @@ bool MenuNewGame() { return false; } } -#endif + // create menu. menu.Create(TXT_MENUNEWGAME, 0, 0, 448, 384); @@ -1333,7 +1323,7 @@ bool MenuNewGame() { goto redo_newgame_menu; } else { Current_mission.cur_level = start_level; - // pull out the ship permssions and use them + // pull out the ship permissions and use them Players[0].ship_permissions = GetPilotShipPermissions(&Current_pilot, Current_mission.name); } } diff --git a/Descent3/mmItem.h b/Descent3/mmItem.h index 9909fb832..55d5e0f22 100644 --- a/Descent3/mmItem.h +++ b/Descent3/mmItem.h @@ -68,9 +68,12 @@ */ #ifndef MMITEM_H #define MMITEM_H + +#include "cinematics.h" +#include "gamefont.h" #include "newui.h" #include "psclass.h" -#include "gamefont.h" + #if ((!defined(OEM)) && (!defined(DEMO))) #define MOVIE_MENU #endif @@ -176,7 +179,7 @@ class mmItem : public UIGadget { virtual void OnSelect(); }; // Main Menu Interface Object -struct tCinematic; + class mmInterface : public UIWindow { int m_nmenu_items; // number of menu items available. mmItem m_menuitems[N_MMENU_ITEMS]; // main menu items diff --git a/Descent3/multi_dll_mgr.cpp b/Descent3/multi_dll_mgr.cpp index 6e874a694..d7eec9c76 100644 --- a/Descent3/multi_dll_mgr.cpp +++ b/Descent3/multi_dll_mgr.cpp @@ -605,6 +605,8 @@ int LoadMultiDLL(const char *name) { // Make the dll filename #if defined(WIN32) snprintf(dll_name, sizeof(dll_name), "%s.dll", name); +#elif defined(MACOSX) + snprintf(dll_name, sizeof(dll_name), "%s.dylib", name); #else snprintf(dll_name, sizeof(dll_name), "%s.so", name); #endif diff --git a/Descent3/sdlmain.cpp b/Descent3/sdlmain.cpp index 40f6fe752..d3eedc573 100644 --- a/Descent3/sdlmain.cpp +++ b/Descent3/sdlmain.cpp @@ -41,6 +41,7 @@ #include "appdatabase.h" #include "args.h" #include "init.h" +#include "debug.h" #include "osiris_dll.h" @@ -134,7 +135,9 @@ void install_signal_handlers() { fprintf(stderr, "SIG: Unable to install SIGTRAP\n"); } #else -void install_signal_handlers() {} +void install_signal_handlers() { + SetUnhandledExceptionFilter(RecordExceptionInfo); +} #endif // --------------------------------------------------------------------------- diff --git a/README.md b/README.md index 22f84e889..5fb127a1e 100644 --- a/README.md +++ b/README.md @@ -2,171 +2,11 @@ This is the Descent 3 open source engine, licensed under [GPL-3.0](https://github.com/DescentDevelopers/Descent3?tab=GPL-3.0-1-ov-file). It includes the '1.5' patch written by Kevin Bentley and Jeff Slutter several years ago and brought to a stable condition by the Descent community. -In order to use this, you must provide your own game files. See the **Usage** section for details. +In order to use this, you must provide your own game files. See the [USAGE.md](USAGE.md) file for details about installation. -## Version 1.5 Notes -There is no "release" yet. The current milestone is "1.5 Stable", which is meant to more or less be Descent 3 as it might have been if the 1.5 patch had made it to retail years ago. Artifacts can be downloaded from the [Actions](https://github.com/DescentDevelopers/Descent3/actions) tab. -The milestone needs testing on all platforms. Please report issues when found. +To build the game, follow build instructions in the [BUILD.md](BUILD.md) file. -## Usage -1. Make sure that you have a copy of Descent 3. You can purchase a copy of Descent 3 from [GOG](https://www.gog.com/game/descent_3_expansion) or [Steam](https://store.steampowered.com/app/273590/Descent_3/). -2. Install Descent 3. - - - **Note for Steam users:** If you own Descent 3 on Steam, then it’s recommended that you install the Windows version of the game even if you’re running macOS or Linux, otherwise movies will not work due to [current lack of Ogv support](https://github.com/DescentDevelopers/Descent3/issues/240). You can use either [Steam Play](https://help.steampowered.com/en/faqs/view/08F7-5D56-9654-39AF) or [SteamCMD](https://developer.valvesoftware.com/wiki/SteamCMD#Cross-Platform_Installation) to install the Windows version of the game on macOS or Linux. - - - **Note for non-Windows users:** If you have the Windows version of the game on CDs but you don’t want to use Windows to install them, then you can follow these instructions: - -
- How to install the Windows Dual-Jewel version of Descent 3 in Wine - -
    -
  1. Make sure that you have Wine installed.
  2. -
  3. (Recommended) Run winecfg and make sure that “Emulate a virtual desktop” is enabled.
  4. -
  5. -

    (Optional) Determine if you’re going to be affected by a bug with Descent 3’s installer, and potentially apply a workaround:

    -
      -
    1. Download Environment Size Checker.
    2. -
    3. Run wine environment-size-checker.exe.
    4. -
    5. If that program tells you that your environment is more than 32,724 bytes large, then you’ll need to unset or shorten environment variables before running Descent 3’s installer. If you don’t, then the installer will page fault.
    6. -
    -
  6. -
  7. -

    Install Descent 3:

    -
      -
    1. Insert disc 1.
    2. -
    3. Make sure that disc 1 is mounted.
    4. -
    5. Determine which drive letter Wine is using for your CD drive. (Hint: try running wine explorer).
    6. -
    7. Run wine '<drive-letter>:\Setup.exe'.
    8. -
    9. Follow the installation wizard’s instructions until it asks you to choose a “Setup Type”.
    10. -
    11. Select the “Full” Setup Type, then click “Next”. -
    12. Continue following the installation wizard’s instructions until it asks you to insert disc 2.
    13. -
    14. -

      Switch to disc 2:

      - -
        -
      • Run wine eject <drive-letter>:.
      • -
      • Make sure that the disc was unmounted and ejected.
      • -
      • Insert disc 2.
      • -
      • Mount disc 2.
      • -
      -
    15. -
    16. Continue following the installation wizard’s instructions until it asks you to insert disc 1 again.
    17. -
    18. Switch back to disc 1. Follow a similar procedure to the one that you used to switch to disc 2.
    19. -
    20. Finish the going through the installation wizard.
    21. -
    22. When the installation wizard finishes, it will open an explorer window. Close out of that window.
    23. -
    24. Unmount the disc.
    25. -
    26. Eject the disc.
    27. -
    -
  8. -

    Install Descent 3: Mercenary:

    -
      -
    1. Insert disc 3.
    2. -
    3. Make sure that disc 3 is mounted.
    4. -
    5. Run wine start /d <drive-letter>: setup.exe -autorun.
    6. -
    7. Follow the instructions in the installation wizard.
    8. -
    -
  9. -
- -
- -3. If your version of Descent 3 is older than v1.4, then [update it to v1.4](http://descent3.com/downloads.php). -4. Create a new folder named `D3-open-source`. -5. Copy the following files from your installation of Descent 3 to `D3-open-source`: - - All `.hog` files - - The `missions` folder - - _(Optional)_ All `.pld` files - - _(Optional)_ The `demo` folder - - _(Optional)_ The `movies` folder -6. Create the `custom/` folder in `D3-open-source` -7. Obtain new Descent 3 engine files: - - If you want to use pre-built binaries, then download one of the artifacts from our latest CI run. You can find a list of CI runs [here](https://github.com/DescentDevelopers/Descent3/actions/workflows/build.yml?query=branch%3Amain). - - If you want to build the engine files yourself, the follow [these instructions](#building). Once you build the engine files, they’ll be put in `builds//Descent3//`. For example, if you’re using Linux and you create a “Release” build, then the files will be located at `builds/linux/Descent3/Release`. -8. Copy all of the new engine files into `D3-open-source` and overwrite any conflicts. -9. Run the game: - - On Windows, run `D3-open-source\Descent3.exe`. - - On other platforms, run `D3-open-source/Descent3`. -10. Special notes: - - D3 Open Source compiles level scripts in their own hogfiles. Make sure you copy and overwrite `d3-{platform}.hog`. - -## Building -#### Building - Windows -1. Make sure that you have Git and Visual Studio 2022 with the “Desktop development with C++” workload and the “C++ MFC for latest v143 build tools (x86 & x64)” component. If you don’t already have those installed or you aren’t sure, then open an elevated Command Prompt and run: - - - - ```batch - winget install Git.Git Microsoft.VisualStudio.2022.Community - - "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\setup.exe" modify^ - --passive^ - --channelId VisualStudio.17.Release^ - --productId Microsoft.VisualStudio.Product.Community^ - --add Microsoft.VisualStudio.Workload.NativeDesktop;includeRecommended^ - --add Microsoft.VisualStudio.Component.VC.ATLMFC - ``` - -2. Open a “x64 Native Tools Command Prompt” and run: - - ```batch - git clone https://github.com/DescentDevelopers/Descent3 - cd Descent3 - cmake --preset win -D ENABLE_LOGGER=[ON|OFF] -D BUILD_EDITOR=[ON|OFF] - cmake --build --preset win --config [Debug|Release] - ``` - -Once CMake finishes, the built files will be put in `builds\win\Descent3\Debug` or `builds\win\Descent3\Release`. - -#### Building - macOS -1. Make sure that [Xcode](https://developer.apple.com/xcode) is installed. - -2. Make sure that [Homebrew](https://brew.sh) is installed. - -3. Run these commands: - - ```sh - git clone https://github.com/DescentDevelopers/Descent3 - cd Descent3 - brew bundle install - cmake --preset mac -D ENABLE_LOGGER=[ON|OFF] - cmake --build --preset mac --config [Debug|Release] - ``` - -Once CMake finishes, the built files will be put in `builds/mac/Descent3/Debug` or `builds/mac/Descent3/Release`. - -#### Building - Linux (Ubuntu) -Run these commands: - -```sh -sudo apt update -sudo apt install -y --no-install-recommends git ninja-build cmake g++ libsdl2-dev zlib1g-dev -git clone https://github.com/DescentDevelopers/Descent3 -cd Descent3 -cmake --preset linux -D ENABLE_LOGGER=[ON|OFF] -cmake --build --preset linux --config [Debug|Release] -``` - -Once CMake finishes, the built files will be put in `builds/linux/Descent3/Debug` or `builds/linux/Descent3/Release`. - -#### Building - Linux (Fedora) -Run these commands: - -```sh -sudo dnf update --refresh -sudo dnf install -y git ninja-build cmake gcc-c++ SDL2-devel zlib-devel -git clone https://github.com/DescentDevelopers/Descent3 -cd Descent3 -cmake --preset linux -D ENABLE_LOGGER=[ON|OFF] -cmake --build --preset linux --config [Debug|Release] -``` - -Once CMake finishes, the built files will be put in `builds/linux/Descent3/Debug` or `builds/linux/Descent3/Release`. +Build or runtime issues should be reported on our [GitHub tracker](https://github.com/DescentDevelopers/Descent3/issues). ## Contributing -Anyone can contribute! We have an active Discord presence at [Descent Developer Network](https://discord.gg/GNy5CUQ). If you are interested in maintaining the project on a regular basis, please contact Kevin Bentley. +Anyone can contribute! We have an active Discord presence at [Descent Developer Network](https://discord.gg/GNy5CUQ). Patches should be submitted on GitHub. \ No newline at end of file diff --git a/USAGE.md b/USAGE.md new file mode 100644 index 000000000..d40b4a618 --- /dev/null +++ b/USAGE.md @@ -0,0 +1,37 @@ +# Descent 3 Open source usage instructions + +**Important note**: This open source distribution of Descent 3 DOES NOT CONTAIN GAME ASSETS. Assets must be acquired separately from an official copy of the game, and copied as describe in the next section. + +This is the first release of the Descent 3 open source engine, that should be considered a beta version. If you find a bug that has not been reported before, please open a new ticket it on our [online issue tracker](https://github.com/DescentDevelopers/Descent3/issues). + +1. Make sure that you have a copy of Descent 3. You can purchase a copy of Descent 3 from [GOG](https://www.gog.com/game/descent_3_expansion) or [Steam](https://store.steampowered.com/app/273590/Descent_3/). +2. Install Descent 3. + **Note for Steam users:** If you own Descent 3 on Steam, then it’s recommended that you install the Windows version of the game even if you’re running macOS or Linux, otherwise movies will not work due to [current lack of Ogv support](https://github.com/DescentDevelopers/Descent3/issues/240). You can use either [Steam Play](https://help.steampowered.com/en/faqs/view/08F7-5D56-9654-39AF) or [SteamCMD](https://developer.valvesoftware.com/wiki/SteamCMD#Cross-Platform_Installation) to install the Windows version of the game on macOS or Linux. +3. If your version of Descent 3 is older than v1.4, then [update it to v1.4](http://descent3.com/downloads.php). +4. Find the installation location of Descent 3. Using the Steam client, you can find it from the library page using the `Manage > Browse local files` context menu. +5. Create a new folder named `D3-open-source`. +6. Copy the following files from your installation of Descent 3 to `D3-open-source`: + - All `.hog` files + - The `missions` folder + - _(Optional)_ All `.pld` files + - _(Optional)_ The `movies` folder +7. Create the `custom/` folder in `D3-open-source` +8. Obtain new Descent 3 engine files: + - If you want to use pre-built binaries, then download the latest [release](https://github.com/DescentDevelopers/Descent3/releases). For a more cutting-edge experience with the latest features, use the artifacts from the latest automated build. You can find the list of automated builds [here](https://github.com/DescentDevelopers/Descent3/actions/workflows/build.yml?query=branch%3Amain+event%3Apush). + - If you want to build the engine files yourself, the follow the instructions in [BUILD.md](BUILD.md). Once you build the engine files, they’ll be put in `builds//Descent3//`. For example, if you’re using Linux and you create a “Release” build, then the files will be located at `builds/linux/Descent3/Release`. +9. Copy all of the new engine files into `D3-open-source` and overwrite any conflicts. +10. Special notes: + - D3 Open Source compiles level scripts in their own hogfiles. Make sure you copy and overwrite `d3-{platform}.hog`. +11. Run the game: + - On Windows, run `D3-open-source\Descent3.exe` from a command-line or double-click on the `Descent3` executable. + - On Linux, `cd` to `D3-open-source` and run `./Descent3`. Wayland users may need to set environement variable `SDL_VIDEODRIVER=wayland` before launching the game. + - On MacOS, the `.app` bundle is currently not signed, so your operating system will not let you run it by double-clicking it. To remediate that, open your terminal and `cd` to `D3-open-source`. Run `chmod +x ./Descent3.app/Content/MacOS/Descent3`, then run the game using `./Descent3.app/Content/MacOS/Descent3` + +## Troubleshooting + +``` +Descent 3 Message(Error: Couldn't find the string table.) +``` + +This error means that game data could not be found. Make sure you copied all game files to the `D3-open-source` folder, and that you're running the game from this same folder. + diff --git a/bitmap/CMakeLists.txt b/bitmap/CMakeLists.txt index 26b48b124..1e2a7d4e2 100644 --- a/bitmap/CMakeLists.txt +++ b/bitmap/CMakeLists.txt @@ -1,8 +1,8 @@ -set(HEADERS iff.h) +set(HEADERS + NewBitmap.h + iff.h) set(CPPS NewBitmap.cpp - NewBitmap.h - bitmain.cpp bumpmap.cpp iff.cpp diff --git a/bitmap/bitmain.cpp b/bitmap/bitmain.cpp index 6a6edfa9c..34b7a7e15 100644 --- a/bitmap/bitmain.cpp +++ b/bitmap/bitmain.cpp @@ -329,7 +329,7 @@ typedef int bm_hashTableIndex; /* index into hash table */ #define compEQ(a, b) (stricmp((a)->name, (b)->name) == 0) struct bm_Node { struct bm_Node *next; /* next bm_Node */ - bm_T data; /* data stored in bm_Node */ + bm_T data; /* data stored in bm_Node */ }; static bm_Node *bm_findNode(bm_T data); static void bm_deleteNode(bm_T data); @@ -510,7 +510,7 @@ int bm_AllocateMemoryForIndex(int n, int w, int h, int add_mem) { // If add_mem is nonzero, adds that to the amount alloced // Returns bitmap handle if successful, -1 if otherwise int bm_AllocBitmap(int w, int h, int add_mem) { - int n, i; + int n = 0, i; if (!Bitmaps_initted) { Int3(); mprintf(0, "Bitmaps not initted!!!\n"); @@ -539,7 +539,7 @@ int bm_AllocBitmap(int w, int h, int add_mem) { } // Just like bm_AllocBitmap but doesn't actually allocate memory. Useful for paging! int bm_AllocNoMemBitmap(int w, int h) { - int n, i; + int n = 0, i; if (!Bitmaps_initted) { Int3(); mprintf(0, "Bitmaps not initted!!!\n"); @@ -654,7 +654,7 @@ void bm_ChangeEndName(const char *src, char *dest) { uint32_t i, limit; int last = -1; int curnum = -1; - char namedest[256+16]; + char namedest[256 + 16]; char path[256], ext[256], filename[256]; ddio_SplitPath(src, path, filename, ext); @@ -1079,7 +1079,7 @@ int bm_MakeBitmapResident(int handle) { } // Saves a bitmap to a file. Saves the bitmap as an OUTRAGE_COMPRESSED_OGF. // Returns -1 if something is wrong. -int bm_SaveFileBitmap(const std::filesystem::path& filename, int handle) { +int bm_SaveFileBitmap(const std::filesystem::path &filename, int handle) { int ret; CFILE *fp; if (!GameBitmaps[handle].used) { diff --git a/bitmap/tga.cpp b/bitmap/tga.cpp index 18c610cc4..fe1c6268f 100644 --- a/bitmap/tga.cpp +++ b/bitmap/tga.cpp @@ -327,7 +327,7 @@ int bm_tga_alloc_file(CFILE *infile, char *name, int format) { uint8_t upside_down = 0; uint16_t width, height; uint32_t pixel; - int i, t, n, data8bit = 0, savepos; + int i, t, n, data8bit = 0, savepos = 0; int mipped = 0; int num_mips = 1; int read_ok = 1; @@ -539,7 +539,7 @@ int bm_page_in_file(int n) { uint8_t image_id_len, color_map_type, image_type, pixsize, descriptor; uint8_t upside_down = 0; uint16_t width, height; - int i, data8bit = 0, savepos; + int i, data8bit = 0, savepos = 0; int mipped = 0, file_mipped = 0; int num_mips = 1; char name[BITMAP_NAME_LEN]; diff --git a/cfile/CMakeLists.txt b/cfile/CMakeLists.txt index 0dd2dc363..31535729f 100644 --- a/cfile/CMakeLists.txt +++ b/cfile/CMakeLists.txt @@ -1,10 +1,14 @@ +set(HEADERS + cfile.h + hogfile.h + inffile.h) set(CPPS cfile.cpp hogfile.cpp inffile.cpp ) -add_library(cfile STATIC ${CPPS}) +add_library(cfile STATIC ${HEADERS} ${CPPS}) target_link_libraries(cfile PRIVATE ddio mem diff --git a/ddebug/CMakeLists.txt b/ddebug/CMakeLists.txt index dc241f8cc..99616b84a 100644 --- a/ddebug/CMakeLists.txt +++ b/ddebug/CMakeLists.txt @@ -1,3 +1,7 @@ +set(HEADERS + debug.h + debugbreak.h + mono.h) set(CPPS debug.cpp $<$: @@ -10,7 +14,7 @@ set(CPPS > ) -add_library(ddebug STATIC ${CPPS}) +add_library(ddebug STATIC ${HEADERS} ${CPPS}) add_dependencies(ddebug get_git_hash) target_include_directories(ddebug PUBLIC $ + +long WINAPI RecordExceptionInfo(PEXCEPTION_POINTERS data); #endif #endif diff --git a/ddebug/lnxdebug.cpp b/ddebug/lnxdebug.cpp index 54ee3d15c..8508233c3 100644 --- a/ddebug/lnxdebug.cpp +++ b/ddebug/lnxdebug.cpp @@ -50,7 +50,7 @@ bool Debug_break = false; static char *Debug_DumpInfo(); // if we are running under a debugger, then pass true -bool Debug_Init(bool debugger, bool mono_debug) { +bool Debug_Init(bool debugger) { #ifndef RELEASE Debug_break = debugger; diff --git a/ddebug/windebug.cpp b/ddebug/windebug.cpp index e7e534394..a3bccfbaa 100644 --- a/ddebug/windebug.cpp +++ b/ddebug/windebug.cpp @@ -189,25 +189,21 @@ */ #include -#include -#include -#include +#include +#include +#include -#include "d3_version.h" #include "debug.h" #include "mem.h" -#include "mono.h" #include "pserror.h" /////////////////////////////////////////////////////////////////////////////// bool Debug_break = false; -char *Debug_DumpInfo(); - /////////////////////////////////////////////////////////////////////////////// -bool Debug_Init(bool debugger, bool mono_debug) { +bool Debug_Init(bool debugger) { // initialization of debugging consoles. #ifndef RELEASE @@ -229,13 +225,7 @@ bool Debug_Init(bool debugger, bool mono_debug) { // Messagebox shows topstring, then stack dump, then bottomstring // Return types are as the same the Windows return values int Debug_ErrorBox(int type, const char *title, const char *topstring, const char *bottomstring) { - int answer; - char *dumptext = Debug_DumpInfo(); - // HWND wnd = GetActiveWindow(); - - // ShowWindow(wnd, SW_SHOWMINNOACTIVE); - - DWORD flags; + DWORD flags = 0; if (type == OSMBOX_OK) flags = MB_OK; else if (type == OSMBOX_YESNO) @@ -249,40 +239,21 @@ int Debug_ErrorBox(int type, const char *title, const char *topstring, const cha else debug_break(); - char *tmpbuf = (char *)mem_malloc( - strlen(dumptext) + strlen(topstring) + strlen(bottomstring) + - 10); // malloc(strlen(dumptext) + strlen(topstring) + strlen(bottomstring) + 10); - - strcpy(tmpbuf, topstring); - if (dumptext[0]) { - strcat(tmpbuf, "\r\n\r\n"); - strcat(tmpbuf, dumptext); - } - if (bottomstring[0]) { - strcat(tmpbuf, "\r\n\r\n"); - strcat(tmpbuf, bottomstring); - } - - wsprintf(tmpbuf, "%s\r\n\r\n%s\r\n\r\n%s", topstring, dumptext, bottomstring); + char *tmpbuf = (char *)mem_malloc(strlen(topstring) + strlen(bottomstring) + 5); + wsprintf(tmpbuf, "%s\r\n\r\n%s", topstring, bottomstring); ShowCursor(TRUE); - answer = MessageBox(NULL, tmpbuf, title, flags | MB_TASKMODAL | MB_SETFOREGROUND); // what's MB_ICONHAND? + int answer = MessageBox(nullptr, tmpbuf, title, flags | MB_TASKMODAL | MB_SETFOREGROUND); ShowCursor(FALSE); - // free(tmpbuf); mem_free(tmpbuf); - // ShowWindow(wnd, SW_SHOWMAXIMIZED); - return answer; } // Return types are the same the Windows return values int Debug_MessageBox(int type, const char *title, const char *str) { - DWORD flags; - int answer; - HWND wnd = GetActiveWindow(); - + DWORD flags = 0; if (type == OSMBOX_OK) flags = MB_OK; else if (type == OSMBOX_YESNO) @@ -295,630 +266,16 @@ int Debug_MessageBox(int type, const char *title, const char *str) { DebugBreak(); ShowCursor(TRUE); - // ShowWindow(wnd, SW_SHOWMINNOACTIVE); - answer = MessageBox(nullptr, str, title, flags | MB_TASKMODAL | MB_SETFOREGROUND); + int answer = MessageBox(nullptr, str, title, flags | MB_TASKMODAL | MB_SETFOREGROUND); ShowCursor(FALSE); - // ShowWindow(wnd, SW_SHOWMAXIMIZED); return answer; } -/////////////////////////////////////////////////////////////////////////////// -// This CODE SHOULD ONLY BE USED IN A DEBUGGABLE VERSION. - -#ifndef _WIN64 -#define SHOW_CALL_STACK // Uncomment SHOW_CALL_STACK to show the call stack in terminal cases -// #define DUMPRAM -#endif // _WIN64 - -#ifdef SHOW_CALL_STACK - -class DumpBuffer { -public: - enum { BUFFER_SIZE = 32000 }; - DumpBuffer(); - void Clear(); - void Printf(const char *format, ...); - void SetWindowText(HWND hWnd) const; - char buffer[BUFFER_SIZE]; - -private: - char *current; -}; - -class PE_Debug { -public: - PE_Debug(); - ~PE_Debug(); - void ClearReport(); - int DumpDebugInfo(DumpBuffer &dumpBuffer, const BYTE *caller, HINSTANCE hInstance); - void Display(); - -private: - // Report data - enum { MAX_MODULENAME_LEN = 512, VA_MAX_FILENAME_LEN = 256 }; - char latestModule[MAX_MODULENAME_LEN]; - char latestFile[VA_MAX_FILENAME_LEN]; - // File mapping data - HANDLE hFile; - HANDLE hFileMapping; - PIMAGE_DOS_HEADER fileBase; - // Pointers to debug information - PIMAGE_NT_HEADERS NT_Header; - PIMAGE_COFF_SYMBOLS_HEADER COFFDebugInfo; - PIMAGE_SYMBOL COFFSymbolTable; - int COFFSymbolCount; - const char *stringTable; - - void ClearFileCache(); - void ClearDebugPtrs(); - void MapFileInMemory(const char *module); - void FindDebugInfo(); - void DumpSymbolInfo(DumpBuffer &dumpBuffer, DWORD relativeAddress); - void DumpLineNumber(DumpBuffer &dumpBuffer, DWORD relativeAddress); - PIMAGE_COFF_SYMBOLS_HEADER GetDebugHeader(); - PIMAGE_SECTION_HEADER SectionHeaderFromName(const char *name); - const char *GetSymbolName(PIMAGE_SYMBOL sym); -}; - -DumpBuffer ::DumpBuffer() { Clear(); } - -void DumpBuffer ::Clear() { current = buffer; } - -void DumpBuffer ::Printf(const char *format, ...) { - // protect against obvious buffer overflow - if (current - buffer < BUFFER_SIZE) { - va_list argPtr; - va_start(argPtr, format); - int count = wvsprintf(current, format, argPtr); - va_end(argPtr); - current += count; - } -} - -void DumpBuffer ::SetWindowText(HWND hWnd) const { SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)buffer); } - -/////////////////////////////////////////////////////////////////////////////// - -// Add an offset to a pointer and cast to a given type; may be -// implemented as a template function but Visual C++ has some problems. -#define BasedPtr(type, ptr, ofs) (type)((DWORD)(ptr) + (DWORD)(ofs)) - -PE_Debug ::PE_Debug() { - // Init file mapping cache - hFileMapping = 0; - hFile = INVALID_HANDLE_VALUE; - fileBase = 0; - ClearDebugPtrs(); - ClearReport(); -} - -PE_Debug ::~PE_Debug() { ClearFileCache(); } - -void PE_Debug ::ClearReport() { - latestModule[0] = 0; - latestFile[0] = 0; -} - -void PE_Debug ::ClearDebugPtrs() { - NT_Header = NULL; - COFFDebugInfo = NULL; - COFFSymbolTable = NULL; - COFFSymbolCount = 0; - stringTable = NULL; -} - -void PE_Debug ::ClearFileCache() { - if (fileBase) { - UnmapViewOfFile(fileBase); - fileBase = 0; - } - if (hFileMapping != 0) { - CloseHandle(hFileMapping); - hFileMapping = 0; - } - if (hFile != INVALID_HANDLE_VALUE) { - CloseHandle(hFile); - hFile = INVALID_HANDLE_VALUE; - } -} - -void PE_Debug ::DumpLineNumber(DumpBuffer &dumpBuffer, DWORD relativeAddress) { - PIMAGE_LINENUMBER line = BasedPtr(PIMAGE_LINENUMBER, COFFDebugInfo, COFFDebugInfo->LvaToFirstLinenumber); - DWORD lineCount = COFFDebugInfo->NumberOfLinenumbers; - const DWORD none = (DWORD)-1; - DWORD maxAddr = 0; - DWORD lineNum = none; - for (DWORD i = 0; i < lineCount; i++) { - if (line->Linenumber != 0) // A regular line number - { - // look for line with bigger address <= relativeAddress - if (line->Type.VirtualAddress <= relativeAddress && line->Type.VirtualAddress > maxAddr) { - maxAddr = line->Type.VirtualAddress; - lineNum = line->Linenumber; - } - } - line++; - } - if (lineNum != none) - dumpBuffer.Printf(" line %d\r\n", lineNum); - // else - // dumpBuffer.Printf( " line \r\n" ) ; -} - -const char *PE_Debug ::GetSymbolName(PIMAGE_SYMBOL sym) { - const int NAME_MAX_LEN = 64; - static char buf[NAME_MAX_LEN]; - if (sym->N.Name.Short != 0) { - strncpy(buf, (const char *)sym->N.ShortName, 8); - buf[8] = 0; - } else { - strncpy(buf, stringTable + sym->N.Name.Long, NAME_MAX_LEN); - buf[NAME_MAX_LEN - 1] = 0; - } - return (buf); -} - -void unmangle(char *dst, const char *src) { - // strcpy( dst, src ); - // return; - - src++; - while ((*src) && (*src != ' ') && (*src != '@')) { - *dst++ = *src++; - } - *dst++ = 0; -} - -#ifdef DUMPRAM - -struct MemSymbol { - int section; - int offset; - int size; - char name[132]; -}; - -int Num_symbols = 0; -int Max_symbols = 0; -MemSymbol *Symbols; - -void InitSymbols() { - Num_symbols = 0; - Max_symbols = 5000; - Symbols = (MemSymbol *)mem_malloc(Max_symbols * sizeof(MemSymbol)); - if (!Symbols) { - Max_symbols = 0; - } -} - -void Add_Symbol(int section, int offset, const char *name, char *module) { - if (Num_symbols >= Max_symbols) { - return; - } - - MemSymbol *sym = &Symbols[Num_symbols++]; - - sym->section = section; - sym->offset = offset; - sym->size = -1; - - strcpy(sym->name, name); - strcat(sym->name, "("); - strcat(sym->name, module); - strcat(sym->name, ")"); -} - -int Sym_compare(const void *arg1, const void *arg2) { - MemSymbol *sym1 = (MemSymbol *)arg1; - MemSymbol *sym2 = (MemSymbol *)arg2; - - if (sym1->section < sym2->section) { - return -1; - } else if (sym1->section > sym2->section) { - return 1; - } else { - if (sym1->offset > sym2->offset) { - return 1; - } else { - return -1; - } - } -} - -int Sym_compare1(const void *arg1, const void *arg2) { - MemSymbol *sym1 = (MemSymbol *)arg1; - MemSymbol *sym2 = (MemSymbol *)arg2; - - if (sym1->size < sym2->size) { - return 1; - } else if (sym1->size > sym2->size) { - return -1; - } else { - return 0; - } -} - -void DumpSymbols() { - int i; - - qsort(Symbols, Num_symbols, sizeof(MemSymbol), Sym_compare); - - for (i = 0; i < Num_symbols; i++) { - MemSymbol *sym1 = &Symbols[i]; - MemSymbol *sym2 = &Symbols[i + 1]; - if ((i < Num_symbols - 1) && (sym1->section == sym2->section)) { - sym1->size = sym2->offset - sym1->offset; - } else { - sym1->size = -1; - } - } - - qsort(Symbols, Num_symbols, sizeof(MemSymbol), Sym_compare1); - - FILE *fp = fopen("memory.out", "wt"); - - fprintf(fp, "%-60s %8s %8s\n", "Name", "Size", "Total"); - - int total_size = 0; - for (i = 0; i < Num_symbols; i++) { - MemSymbol *sym = &Symbols[i]; - if (sym->size > 0) - total_size += sym->size; - fprintf(fp, "%-60s %8d %8d\n", sym->name, sym->size, total_size); - } - - fclose(fp); - - mem_free(Symbols); - Symbols = NULL; - _asm int 3 -} -#endif - -void PE_Debug::DumpSymbolInfo(DumpBuffer &dumpBuffer, DWORD relativeAddress) { - // Variables to keep track of function symbols - PIMAGE_SYMBOL currentSym = COFFSymbolTable; - PIMAGE_SYMBOL fnSymbol = NULL; - DWORD maxFnAddress = 0; - -#ifdef DUMPRAM - InitSymbols(); -#endif - - // Variables to keep track of file symbols - PIMAGE_SYMBOL fileSymbol = NULL; - PIMAGE_SYMBOL latestFileSymbol = NULL; - for (int i = 0; i < COFFSymbolCount; i++) { - - // Look for .text section where relativeAddress belongs to. - // Keep track of the filename the .text section belongs to. - if (currentSym->StorageClass == IMAGE_SYM_CLASS_FILE) { - latestFileSymbol = currentSym; - } - - // Borland uses "CODE" instead of the standard ".text" entry - // Microsoft uses sections that only _begin_ with .text - const char *symName = GetSymbolName(currentSym); - - if (strnicmp(symName, ".text", 5) == 0 || stricmp(symName, "CODE") == 0) { - if (currentSym->Value <= relativeAddress) { - PIMAGE_AUX_SYMBOL auxSym = (PIMAGE_AUX_SYMBOL)(currentSym + 1); - if (currentSym->Value + auxSym->Section.Length >= relativeAddress) { - fileSymbol = latestFileSymbol; - } - } - } - - // Look for the function with biggest address <= relativeAddress - BOOL isFunction = ISFCN(currentSym->Type); // Type == 0x20, See WINNT.H - if (isFunction && - (currentSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL || currentSym->StorageClass == IMAGE_SYM_CLASS_STATIC)) { - - if (currentSym->Value <= relativeAddress && currentSym->Value > maxFnAddress) { - maxFnAddress = currentSym->Value; - fnSymbol = currentSym; - } - } - -#ifdef DUMPRAM - if (!isFunction && (currentSym->SectionNumber > -1)) { - if ((symName[0] == '_' && symName[1] != '$') || (symName[0] == '?')) { - - char pretty_module[1024]; - - if (fileSymbol) { - const char *auxSym = (const char *)(latestFileSymbol + 1); - char tmpFile[VA_MAX_FILENAME_LEN]; - strcpy(tmpFile, auxSym); - strcpy(pretty_module, tmpFile); - char *p = pretty_module + strlen(pretty_module) - 1; - // Move p to point to first letter of EXE filename - while ((*p != '\\') && (*p != '/') && (*p != ':')) - p--; - p++; - if (strlen(p) < 1) { - strcpy(pretty_module, ""); - } else { - memmove(pretty_module, p, strlen(p) + 1); - } - } else { - strcpy(pretty_module, ""); - } - - Add_Symbol(currentSym->SectionNumber, currentSym->Value, symName, pretty_module); - } - } -#endif - - // Advance counters, skip aux symbols - i += currentSym->NumberOfAuxSymbols; - currentSym += currentSym->NumberOfAuxSymbols; - currentSym++; - } - -#ifdef DUMPRAM - DumpSymbols(); -#endif - - // dump symbolic info if found - if (fileSymbol) { - const char *auxSym = (const char *)(fileSymbol + 1); - - if (stricmp(latestFile, auxSym)) { - strcpy(latestFile, auxSym); - // JAS dumpBuffer.Printf( " file: %s\r\n", auxSym ) ; - } - } else { - latestFile[0] = 0; - // JAS dumpBuffer.Printf( " file: unknown\r\n" ) ; - } - - if (fnSymbol) { - char tmp_name[1024]; - unmangle(tmp_name, GetSymbolName(fnSymbol)); - dumpBuffer.Printf(" %s()", tmp_name); - } else { - dumpBuffer.Printf(" "); - } -} - -PIMAGE_SECTION_HEADER PE_Debug ::SectionHeaderFromName(const char *name) { - PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(NT_Header); - for (unsigned i = 0; i < NT_Header->FileHeader.NumberOfSections; i++) { - if (strnicmp((const char *)section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0) - return (section); - else - section++; - } - return 0; -} - -PIMAGE_COFF_SYMBOLS_HEADER PE_Debug ::GetDebugHeader() { - // Some files have a wrong entry in the COFF header, so - // first check if the debug info exists at all - if (NT_Header->FileHeader.PointerToSymbolTable == 0) - return (0); - DWORD debugDirRVA = NT_Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; - if (debugDirRVA == 0) - return (0); - - // The following values must be calculated differently for MS/Borland files - PIMAGE_DEBUG_DIRECTORY debugDir; - DWORD size; - - // Borland files have the debug directory at the beginning of a .debug section - PIMAGE_SECTION_HEADER debugHeader = SectionHeaderFromName(".debug"); - if (debugHeader && debugHeader->VirtualAddress == debugDirRVA) { - debugDir = (PIMAGE_DEBUG_DIRECTORY)(debugHeader->PointerToRawData + (DWORD)fileBase); - size = NT_Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size * sizeof(IMAGE_DEBUG_DIRECTORY); - } else - // Microsoft debug directory is in the .rdata section - { - debugHeader = SectionHeaderFromName(".rdata"); - if (debugHeader == 0) - return (0); - size = NT_Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; - DWORD offsetInto_rdata = debugDirRVA - debugHeader->VirtualAddress; - debugDir = BasedPtr(PIMAGE_DEBUG_DIRECTORY, fileBase, debugHeader->PointerToRawData + offsetInto_rdata); - } - - // look for COFF debug info - DWORD debugFormats = size / sizeof(IMAGE_DEBUG_DIRECTORY); - for (DWORD i = 0; i < debugFormats; i++) { - if (debugDir->Type == IMAGE_DEBUG_TYPE_COFF) - return ((PIMAGE_COFF_SYMBOLS_HEADER)((DWORD)fileBase + debugDir->PointerToRawData)); - else - debugDir++; - } - return (NULL); -} - -void PE_Debug ::FindDebugInfo() { - ClearDebugPtrs(); - // Put everything into a try/catch in case the file has wrong fields - try { - // Verify that fileBase is a valid pointer to a DOS header - if (fileBase && fileBase->e_magic == IMAGE_DOS_SIGNATURE) { - // Get a pointer to the PE header - NT_Header = BasedPtr(PIMAGE_NT_HEADERS, fileBase, fileBase->e_lfanew); - - // Verify that NT_Header is a valid pointer to a NT header - if (NT_Header && NT_Header->Signature == IMAGE_NT_SIGNATURE) { - // Get a pointer to the debug header if any - COFFDebugInfo = GetDebugHeader(); - - // Get a pointer to the symbol table and retrieve the number of symbols - if (NT_Header->FileHeader.PointerToSymbolTable) - COFFSymbolTable = BasedPtr(PIMAGE_SYMBOL, fileBase, NT_Header->FileHeader.PointerToSymbolTable); - COFFSymbolCount = NT_Header->FileHeader.NumberOfSymbols; - - // The string table starts right after the symbol table - stringTable = (const char *)(COFFSymbolTable + COFFSymbolCount); - } - } - } catch (...) { - // Header wrong, do nothing - } -} - -void PE_Debug ::MapFileInMemory(const char *module) { - ClearFileCache(); - hFile = CreateFile(module, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (hFile != INVALID_HANDLE_VALUE) { - hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (hFileMapping != 0) - fileBase = (PIMAGE_DOS_HEADER)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); - } - // NB: open files/mapping are closed later in ClearFileCache -} - -int PE_Debug::DumpDebugInfo(DumpBuffer &dumpBuffer, const BYTE *caller, HINSTANCE hInstance) { - // Avoid to open, map and looking for debug header/symbol table - // by caching the latest and comparing the actual module with - // the latest one. - static char module[MAX_MODULENAME_LEN]; - GetModuleFileName(hInstance, module, MAX_MODULENAME_LEN); - - // New module - if (stricmp(latestModule, module)) { - strcpy(latestModule, module); - // JAS dumpBuffer.Printf( "Module: %s\r\n", module ); - MapFileInMemory(module); - FindDebugInfo(); - } - - char pretty_module[1024]; - - strcpy(pretty_module, module); - char *p = pretty_module + strlen(pretty_module) - 1; - // Move p to point to first letter of EXE filename - while ((*p != '\\') && (*p != '/') && (*p != ':')) - p--; - p++; - if (strlen(p) < 1) { - strcpy(pretty_module, ""); - } else { - memmove(pretty_module, p, strlen(p) + 1); - } - - if (fileBase) { - // Put everything into a try/catch in case the file has wrong fields - try { - DWORD relativeAddress = caller - (BYTE *)hInstance; - // Dump symbolic information and line number if available - if (COFFSymbolCount != 0 && COFFSymbolTable != NULL) { - DumpSymbolInfo(dumpBuffer, relativeAddress); - if (COFFDebugInfo) - DumpLineNumber(dumpBuffer, relativeAddress); - return 1; - } else { - // dumpBuffer.Printf( "Call stack is unavailable, because there is\r\nno COFF debugging info in this - // module.\r\n" ) ; JAS dumpBuffer.Printf( " no debug information\r\n" ) ; - dumpBuffer.Printf(" %s %08x()\r\n", pretty_module, caller); - return 0; - } - } catch (...) { - // Header wrong, do nothing - return 0; - } - } else { - dumpBuffer.Printf(" %s %08x()\r\n", pretty_module, caller); - // JAS dumpBuffer.Printf( " module not accessible\r\n" ) ; - // JAS dumpBuffer.Printf( " address: %8X\r\n", caller ) ; - return 0; - } -} - -void DumpCallsStack(DumpBuffer &dumpBuffer) { - const char *separator = "------------------------------------------------------------------\r\n"; - static PE_Debug PE_debug; - - dumpBuffer.Printf("\r\nCall stack:\r\n"); - dumpBuffer.Printf(separator); - - // The structure of the stack frames is the following: - // EBP -> parent stack frame EBP - // return address for this call ( = caller ) - // The chain can be navigated iteratively, after the - // initial value of EBP is loaded from the register - DWORD parentEBP, retval; - MEMORY_BASIC_INFORMATION mbi; - HINSTANCE hInstance; - - int depth = 0; - - __asm MOV parentEBP, EBP - - do { - depth++; - if (depth > 16) - break; - - if ((parentEBP & 3) || IsBadReadPtr((DWORD *)parentEBP, sizeof(DWORD))) { - break; - } - parentEBP = *(DWORD *)parentEBP; - - BYTE **NextCaller = ((BYTE **)parentEBP + 1); - - if (IsBadReadPtr(NextCaller, sizeof(BYTE *))) { - break; - } - - BYTE *caller = *NextCaller; // Error sometimes!!! - - // Skip the first EBP as it points to AssertionFailed, which is - // uninteresting for the user - - if (depth > 1) { - - // Get the instance handle of the module where caller belongs to - retval = VirtualQuery(caller, &mbi, sizeof(mbi)); - - // The instance handle is equal to the allocation base in Win32 - hInstance = (HINSTANCE)mbi.AllocationBase; - - if ((retval == sizeof(mbi)) && hInstance) { - if (!PE_debug.DumpDebugInfo(dumpBuffer, caller, hInstance)) { - // break; - } - } else { - break; // End of the call chain - } - } - } - while (TRUE) - ; - - dumpBuffer.Printf(separator); - PE_debug.ClearReport(); // Prepare for future calls -} - -// This ought to be local to VerboseAssert, but it -// causes problems in Visual C++ (in the CRTL init phase) -static DumpBuffer dumpBuffer; - -#endif // SHOW_CALL_STACK - /////////////////////////////////////////////////////////////////////////////// void dump_text_to_clipboard(char *text); -char *Debug_DumpInfo() { -#ifdef SHOW_CALL_STACK - dumpBuffer.Clear(); - DumpCallsStack(dumpBuffer); - dump_text_to_clipboard(dumpBuffer.buffer); - - dumpBuffer.Printf("\r\n[ This info has been copied to the clipboard for pasting to a bug report. ]\r\n"); - - return dumpBuffer.buffer; -#else - return (""); -#endif -} - /////////////////////////////////////////////////////////////////////////////// void DumpTextToClipboard(char *text) { @@ -936,7 +293,7 @@ void DumpTextToClipboard(char *text) { } // Length of string with CRs added - int len = strlen(text) + extra + 1; + size_t len = strlen(text) + extra + 1; HGLOBAL h_text = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len); if (!h_text) @@ -965,295 +322,43 @@ void DumpTextToClipboard(char *text) { void dump_text_to_clipboard(char *text) { DumpTextToClipboard(text); } -// Translate the exception code into something human readable. - -static const char *GetExceptionDescription(DWORD ExceptionCode) { - struct ExceptionNames { - DWORD ExceptionCode; - char *ExceptionName; - }; - - ExceptionNames ExceptionMap[] = { - {0x40010005, "a Control-C"}, - {0x40010008, "a Control-Break"}, - {0x80000002, "a Datatype Misalignment"}, - {0x80000003, "a Breakpoint"}, - {0xc0000005, "an Access Violation"}, - {0xc0000006, "an In Page Error"}, - {0xc0000017, "a No Memory"}, - {0xc000001d, "an Illegal Instruction"}, - {0xc0000025, "a Noncontinuable Exception"}, - {0xc0000026, "an Invalid Disposition"}, - {0xc000008c, "a Array Bounds Exceeded"}, - {0xc000008d, "a Float Denormal Operand"}, - {0xc000008e, "a Float Divide by Zero"}, - {0xc000008f, "a Float Inexact Result"}, - {0xc0000090, "a Float Invalid Operation"}, - {0xc0000091, "a Float Overflow"}, - {0xc0000092, "a Float Stack Check"}, - {0xc0000093, "a Float Underflow"}, - {0xc0000094, "an Integer Divide by Zero"}, - {0xc0000095, "an Integer Overflow"}, - {0xc0000096, "a Privileged Instruction"}, - {0xc00000fD, "a Stack Overflow"}, - {0xc0000142, "a DLL Initialization Failed"}, - {0xe06d7363, "a Microsoft C++ Exception"}, - }; - - for (int i = 0; i < sizeof(ExceptionMap) / sizeof(ExceptionMap[0]); i++) - if (ExceptionCode == ExceptionMap[i].ExceptionCode) - return ExceptionMap[i].ExceptionName; - - return "Unknown exception type"; -} - -static void PrintFileTime(char *sztime, FILETIME ftime) { - SYSTEMTIME systime, fixtime; - *sztime = NULL; - - if (FileTimeToSystemTime(&ftime, &fixtime)) { - if (SystemTimeToTzSpecificLocalTime(NULL, &fixtime, &systime)) { - wsprintf(sztime, "%d/%d/%d %02d:%02d:%02d", systime.wMonth, systime.wDay, systime.wYear, systime.wHour, - systime.wMinute, systime.wSecond); - } else { - wsprintf(sztime, "Unknown Time"); - } - } -} - -// Print information about a code module (DLL or EXE) such as its size, -// location, time stamp, etc. - -static void ShowModuleInfo(HANDLE LogFile, HINSTANCE ModuleHandle) { - char FmtString[2000]; - DWORD bytesout; - char ModName[_MAX_PATH]; - __try { - if (GetModuleFileName(ModuleHandle, ModName, sizeof(ModName)) > 0) { - // If GetModuleFileName returns greater than zero then this must - // be a valid code module address. Therefore we can try to walk - // our way through its structures to find the link time stamp. - IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER *)ModuleHandle; - if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic) - return; - IMAGE_NT_HEADERS *NTHeader = (IMAGE_NT_HEADERS *)((char *)DosHeader + DosHeader->e_lfanew); - if (IMAGE_NT_SIGNATURE != NTHeader->Signature) - return; - // Open the code module file so that we can get its file date - // and size. - HANDLE ModuleFile = - CreateFile(ModName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - char TimeBuffer[100] = ""; - DWORD FileSize = 0; - if (ModuleFile != INVALID_HANDLE_VALUE) { - FileSize = GetFileSize(ModuleFile, 0); - FILETIME LastWriteTime; - if (GetFileTime(ModuleFile, 0, 0, &LastWriteTime)) { - PrintFileTime(TimeBuffer + lstrlen(TimeBuffer), LastWriteTime); - } - CloseHandle(ModuleFile); - } - - wsprintf(FmtString, "%s,\taddr: 0x%08x\tsize:%d\t[%s]\r\n", ModName, ModuleHandle, FileSize, - TimeBuffer); // NTHeader->FileHeader.TimeDateStamp, - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - } - } - // Handle any exceptions by continuing from this point. - __except (EXCEPTION_EXECUTE_HANDLER) { - } -} - -// Scan memory looking for code modules (DLLs or EXEs). VirtualQuery is used -// to find all the blocks of address space that were reserved or committed, -// and ShowModuleInfo will display module information if they are code -// modules. - -static void RecordModuleList(HANDLE LogFile) { - char FmtString[2000]; - DWORD bytesout; - wsprintf(FmtString, "\r\n" - "Modules:\r\n"); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - SYSTEM_INFO SystemInfo; - GetSystemInfo(&SystemInfo); - const size_t PageSize = SystemInfo.dwPageSize; - // Set NumPages to the number of pages in the 4GByte address space, - // while being careful to avoid overflowing ints. - const size_t NumPages = 4 * size_t((1024 * 1024 * 1024) / PageSize); - size_t pageNum = 0; - void *LastAllocationBase = 0; - while (pageNum < NumPages) { - MEMORY_BASIC_INFORMATION MemInfo; - if (VirtualQuery((void *)(pageNum * PageSize), &MemInfo, sizeof(MemInfo))) { - if (MemInfo.RegionSize > 0) { - // Adjust the page number to skip over this block of memory. - pageNum += MemInfo.RegionSize / PageSize; - if (MemInfo.State == MEM_COMMIT && MemInfo.AllocationBase > LastAllocationBase) { - // Look for new blocks of committed memory, and try - // recording their module names - this will fail - // gracefully if they aren't code modules. - LastAllocationBase = MemInfo.AllocationBase; - ShowModuleInfo(LogFile, (HINSTANCE)LastAllocationBase); - } - } else - pageNum += (64 * 1024) / PageSize; - } else - pageNum += (64 * 1024) / PageSize; - } -} - -// Record information about the user's system, such as processor type, amount -// of memory, etc. - -static void RecordSystemInformation(HANDLE LogFile) { - char FmtString[2000]; - DWORD bytesout; - FILETIME CurrentTime; - GetSystemTimeAsFileTime(&CurrentTime); - char TimeBuffer[100]; - - PrintFileTime(TimeBuffer, CurrentTime); - - wsprintf(FmtString, "Error occurred at %s.\r\n", TimeBuffer); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - char ModuleName[_MAX_PATH]; - if (GetModuleFileName(0, ModuleName, sizeof(ModuleName)) <= 0) - lstrcpy(ModuleName, "Unknown"); - - wsprintf(FmtString, "Module: %s.\r\n", ModuleName); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - - MEMORYSTATUS ms; - ms.dwLength = sizeof(ms); - GlobalMemoryStatus(&ms); - // Print out the amount of physical memory, rounded up. - wsprintf(FmtString, "System Memory Status:\r\n"); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - wsprintf(FmtString, "Percent of memory in use: %d\r\n", ms.dwMemoryLoad); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - wsprintf(FmtString, "Bytes of physical memory : %d\r\n", ms.dwTotalPhys); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - wsprintf(FmtString, "Free physical memory bytes : %d\r\n", ms.dwAvailPhys); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); - wsprintf(FmtString, "Available virtual memory : %d\r\n\r\n", ms.dwAvailPageFile); - WriteFile(LogFile, FmtString, lstrlen(FmtString), &bytesout, 0); -} -/* -extern bool Debug_break; -extern char *Debug_DumpInfo(); -*/ -#define FORMAT_REG \ - "Registers:\r\nEAX=%08x CS=%04x EIP=%08x EFLGS=%08x\r\nEBX=%08x SS=%04x ESP=%08x EBP=%08x\r\nECX=%08x DS=%04x " \ - "ESI=%08x FS=%04x\r\nEDX=%08x ES=%04x EDI=%08x GS=%04x\r\n" -#define FORMAT_SEP "\r\n--------------------------------------------------------------------------------\r\n" -#define FORMATCRLF "\r\n" - -const int NumCodeBytes = 16; // Number of code bytes to record. -const int MaxStackDump = 2048; // Maximum number of DWORDS in stack dumps. -const int StackColumns = 8; // Number of columns in stack dump. +/////////////////////////////////////////////////////////////////////////////// -int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const char *Message) { - static int BeenHere; +#pragma comment(lib, "DbgHelp.lib") +long WINAPI RecordExceptionInfo(PEXCEPTION_POINTERS data) { + static bool BeenHere = false; if (BeenHere) // Going recursive! That must mean this routine crashed! return EXCEPTION_CONTINUE_SEARCH; BeenHere = true; -#ifndef _WIN64 - PEXCEPTION_RECORD Exception = data->ExceptionRecord; - PCONTEXT Context = data->ContextRecord; - const char *desc = GetExceptionDescription(Exception->ExceptionCode); + SetMessageBoxTitle("Unexpected error"); - // An Int3() - if (0x80000003 == Exception->ExceptionCode) { - BeenHere = false; - return EXCEPTION_CONTINUE_SEARCH; + std::error_code ec; + const std::filesystem::path dumFilePath = std::filesystem::temp_directory_path(ec) / "d3-crash.dmp"; + if (ec) { + OutrageMessageBox("Could not find temporary directory to write crash dump file into: %s", ec.message().c_str()); + exit(1); } - char topmsg[500]; - char tmpmsg[1000]; - char bottommsg[1000] = ""; - char callstack[1000] = ""; - - wsprintf(topmsg, "Execution in %s was stopped by %s", Message, desc); - - wsprintf(bottommsg, FORMAT_REG, Context->Eax, Context->SegCs, Context->Eip, Context->EFlags, Context->Ebx, - Context->SegSs, Context->Esp, Context->Ebp, Context->Ecx, Context->SegDs, Context->Esi, Context->SegFs, - Context->Edx, Context->SegEs, Context->Edi, Context->SegGs); - - HANDLE LogFile = - CreateFile("error.log", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0); - if (LogFile != INVALID_HANDLE_VALUE) { - - char *p = Debug_DumpInfo(); - lstrcpy(callstack, p); - - DWORD NumBytes; - SetFilePointer(LogFile, 0, 0, FILE_END); - - WriteFile(LogFile, topmsg, lstrlen(topmsg), &NumBytes, 0); - WriteFile(LogFile, FORMATCRLF, lstrlen(FORMATCRLF), &NumBytes, 0); - - char Username[100]; - DWORD unamelen = 99; - char Machinename[200]; - DWORD cnamelen = 199; - GetUserName(Username, &unamelen); - GetComputerName(Machinename, &cnamelen); - wsprintf(callstack, "Username: %s\r\nMachineName: %s\r\n", Username, Machinename); - WriteFile(LogFile, callstack, lstrlen(callstack), &NumBytes, 0); - -#if (defined(RELEASE) && (!defined(DEMO))) - wsprintf(callstack, "Descent 3 Release build %s\r\n", D3_GIT_HASH); - WriteFile(LogFile, callstack, lstrlen(callstack), &NumBytes, 0); -#endif - RecordSystemInformation(LogFile); - RecordModuleList(LogFile); - - WriteFile(LogFile, bottommsg, lstrlen(bottommsg), &NumBytes, 0); - WriteFile(LogFile, FORMAT_SEP, lstrlen(FORMAT_SEP), &NumBytes, 0); + HANDLE hDumpFile = CreateFile(dumFilePath.u8string().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0); + if (hDumpFile == INVALID_HANDLE_VALUE) { + OutrageMessageBox("Could not create crash dump file, error code: %x", GetLastError()); + exit(1); + } - DWORD *pStack = (DWORD *)Context->Esp; - DWORD *pStackTop; - __asm { - mov eax, fs:[4] - mov pStackTop, eax - } - if (pStackTop > pStack + MaxStackDump) pStackTop = pStack + MaxStackDump; - int Count = 0; + MINIDUMP_EXCEPTION_INFORMATION exceptInfo; + exceptInfo.ThreadId = GetCurrentThreadId(); + exceptInfo.ExceptionPointers = data; + exceptInfo.ClientPointers = TRUE; - char buffer[1000] = ""; - const int safetyzone = 50; - char *nearend = buffer + sizeof(buffer) - safetyzone; - char *output = buffer; - while (pStack + 1 <= pStackTop) { - if ((Count % StackColumns) == 0) - output += wsprintf(output, "%08x: ", pStack); - char *Suffix = " "; - if ((++Count % StackColumns) == 0 || pStack + 2 > pStackTop) - Suffix = "\r\n"; - output += wsprintf(output, "%08x%s", *pStack, Suffix); - pStack++; - // Check for when the buffer is almost full, and flush it to disk. - if (output > nearend) { - wsprintf(tmpmsg, "%s", buffer); - WriteFile(LogFile, tmpmsg, lstrlen(tmpmsg), &NumBytes, 0); - buffer[0] = 0; - output = buffer; - } - } - CloseHandle(LogFile); + if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &exceptInfo, nullptr, nullptr)) { + OutrageMessageBox("Crash dump file written to: %s\nYou can attach it to a bug report.", dumFilePath.u8string().c_str()); + } else { + OutrageMessageBox("Could not write crash dump file, error code: %x", GetLastError()); + exit(1); } - if ((!Debug_break) && (!no_debug_dialog)) - Debug_ErrorBox(OSMBOX_OK, "Error", topmsg, bottommsg); -#endif // _WIN64 - - if (no_debug_dialog) - exit(0); BeenHere = false; - if (Debug_break) - return EXCEPTION_CONTINUE_SEARCH; - else - return EXCEPTION_EXECUTE_HANDLER; + + return Debug_break ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER; } diff --git a/ddio/CMakeLists.txt b/ddio/CMakeLists.txt index 77db61cea..06e44bfd8 100644 --- a/ddio/CMakeLists.txt +++ b/ddio/CMakeLists.txt @@ -1,3 +1,9 @@ +set(HEADERS + chrono_timer.h + ddio.h + ddio_common.h + ddio_lnx.h + ddio_win.h) set(CPPS chrono_timer.cpp ddio.cpp @@ -17,7 +23,7 @@ set(CPPS winfile.cpp > ) -add_library(ddio STATIC ${CPPS}) +add_library(ddio STATIC ${HEADERS} ${CPPS}) target_link_libraries(ddio PRIVATE SDL2::SDL2 ddebug diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 2c88c0357..83a321ea4 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -576,6 +576,13 @@ target_link_libraries(Descent3Editor PRIVATE fix grtext manage mem misc model module stream_audio music networking physics renderer rtperformance sndlib ui unzip vecmat md5 ${PLATFORM_LIBS}) +target_link_options(Descent3Editor PRIVATE $<$:/DEBUG:FULL>) add_dependencies(Descent3Editor get_git_hash) -install(TARGETS Descent3Editor RUNTIME) + +# FIXME: enable installation again when the editor is stable/usable +# install(TARGETS Descent3Editor RUNTIME) +# if(MSVC) +# install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR}) +# endif() + diff --git a/fix/CMakeLists.txt b/fix/CMakeLists.txt index 765148ded..1be0cf631 100644 --- a/fix/CMakeLists.txt +++ b/fix/CMakeLists.txt @@ -1,4 +1,5 @@ -set(HEADERS) +set(HEADERS + fix.h) set(CPPS fix.cpp) diff --git a/grtext/CMakeLists.txt b/grtext/CMakeLists.txt index 1d29a9f0c..9bd360dc4 100644 --- a/grtext/CMakeLists.txt +++ b/grtext/CMakeLists.txt @@ -1,10 +1,13 @@ +set(HEADERS + grtext.h + grtextlib.h) set(CPPS grfont.cpp grtext.cpp textaux.cpp ) -add_library(grtext STATIC ${CPPS}) +add_library(grtext STATIC ${HEADERS} ${CPPS}) target_link_libraries(grtext PRIVATE ddio mem diff --git a/grtext/grfont.cpp b/grtext/grfont.cpp index e425991f3..b23d551c3 100644 --- a/grtext/grfont.cpp +++ b/grtext/grfont.cpp @@ -913,7 +913,7 @@ void grfont_TranslateToBitmaps(int handle) { // Font translation routines void grfont_XlateMonoChar(int bmp_handle, int x, int y, int index, tFontFileInfo *ft, int width) { int row, col; // byte width of char - uint8_t bit_mask = 0, byte; + uint8_t bit_mask = 0, byte = 0; uint8_t *fp; fp = ft->char_data[index]; diff --git a/lib/vecmat.h b/lib/vecmat.h index 144602d4f..279830d63 100644 --- a/lib/vecmat.h +++ b/lib/vecmat.h @@ -148,19 +148,12 @@ * $NoKeywords: $ */ -#ifndef _VECMAT_H -#define _VECMAT_H +#ifndef VECMAT_H +#define VECMAT_H -#include "pstypes.h" -#include "math.h" -#include "fix.h" - -// what does this do? Why didn't Jason put a comment here? -// Jason replies: This pragma disables the "possible loss of data" warning that -// is generated when converting doubles to floats -// A thousand pardons for the confusion +#include -#pragma warning(disable : 4244) +#include "fix.h" // All structs, defines and inline functions are located in vecmat_external.h // vecmat_external.h is where anything that can be used by DLLs should be. @@ -253,7 +246,7 @@ void vm_Orthogonalize(matrix *m); // Parameters: m - filled in with the orienation matrix // fvec,uvec,rvec - pointers to vectors that determine the matrix. // One or two of these must be specified, with the other(s) set to NULL. -void vm_VectorToMatrix(matrix *m, vector *fvec, vector *uvec = NULL, vector *rvec = NULL); +void vm_VectorToMatrix(matrix *m, vector *fvec, vector *uvec = nullptr, vector *rvec = nullptr); // Computes a matrix from a vector and and angle of rotation around that vector // Parameters: m - filled in with the computed matrix diff --git a/libmve/CMakeLists.txt b/libmve/CMakeLists.txt index ed356f84c..6d5b10e12 100644 --- a/libmve/CMakeLists.txt +++ b/libmve/CMakeLists.txt @@ -1,3 +1,9 @@ +set(HEADERS + decoders.h + movie_sound.h + mve_audio.h + mvelib.h + sound_interface.h) set(CPPS decoder8.cpp decoder16.cpp @@ -7,7 +13,7 @@ set(CPPS mveplay.cpp ) -add_library(libmve STATIC ${CPPS}) +add_library(libmve STATIC ${HEADERS} ${CPPS}) target_link_libraries(libmve PRIVATE ddio SDL2::SDL2 diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index ef3199582..9063cc6fe 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -1,3 +1,8 @@ +set(HEADERS + linux_fix.h + lnxapp.h + lnxcontroller.h + registry.h) set(CPPS lnxcon.cpp lnxcon_raw.cpp @@ -8,7 +13,7 @@ set(CPPS registry.cpp ) -add_library(linux STATIC ${CPPS}) +add_library(linux STATIC ${HEADERS} ${CPPS}) target_link_libraries(linux PRIVATE cfile ) diff --git a/linux/lnxapp.cpp b/linux/lnxapp.cpp index 34c53cd8c..1f9d8663b 100644 --- a/linux/lnxapp.cpp +++ b/linux/lnxapp.cpp @@ -72,7 +72,6 @@ #include #if defined(POSIX) #include -#include #include #else #include "winsock.h" diff --git a/manage/pagelock.cpp b/manage/pagelock.cpp index a83554729..5422666a1 100644 --- a/manage/pagelock.cpp +++ b/manage/pagelock.cpp @@ -362,7 +362,7 @@ int mng_CheckIfPageLocked(mngs_Pagelock *pl) { CFILE *infile; mngs_Pagelock testlock; - int r, done = 0; + int r = -1, done = 0; if (!Network_up) return 1; @@ -408,7 +408,7 @@ int mng_CheckIfPageOwned(mngs_Pagelock *pl, char *owner) { CFILE *infile; mngs_Pagelock testlock; - int r, done = 0; + int r = -1, done = 0; infile = (CFILE *)cfopen(TableLockFilename, "rb"); if (infile == NULL) { diff --git a/md5/CMakeLists.txt b/md5/CMakeLists.txt index 25ef760aa..7c151f9f8 100644 --- a/md5/CMakeLists.txt +++ b/md5/CMakeLists.txt @@ -2,9 +2,7 @@ set(HEADERS md5.h) set(CPPS md5.cpp) -set(PLATFORMCPPS) - -add_library(md5 STATIC ${HEADERS} ${CPPS} ${PLATFORMCPPS}) +add_library(md5 STATIC ${HEADERS} ${CPPS}) if(BUILD_TESTING) add_subdirectory(tests) diff --git a/mem/CMakeLists.txt b/mem/CMakeLists.txt index fbf1f6fe8..d895e0fe1 100644 --- a/mem/CMakeLists.txt +++ b/mem/CMakeLists.txt @@ -1,8 +1,7 @@ -set(CPPS - mem.cpp -) +set(HEADERS mem.h) +set(CPPS mem.cpp) -add_library(mem STATIC ${CPPS}) +add_library(mem STATIC ${HEADERS} ${CPPS}) target_compile_definitions(mem PUBLIC $<$:MEM_USE_RTL> ) diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt index b94f5ddd9..e797b7ca5 100644 --- a/misc/CMakeLists.txt +++ b/misc/CMakeLists.txt @@ -1,3 +1,10 @@ +set(HEADERS + log.h + logfile.h + pserror.h + psglob.h + psrand.h + pstring.h) set(CPPS error.cpp logfile.cpp @@ -7,7 +14,7 @@ set(CPPS pstring.cpp ) -add_library(misc STATIC ${CPPS}) +add_library(misc STATIC ${HEADERS} ${CPPS}) target_link_libraries(misc PRIVATE ddebug SDL2::SDL2 diff --git a/misc/error.cpp b/misc/error.cpp index 821d0c488..bf58414ad 100644 --- a/misc/error.cpp +++ b/misc/error.cpp @@ -77,8 +77,6 @@ #define MAX_MSG_LEN 2000 -void Default_dbgbrk_callback(); - // Debug break chain handlers void (*DebugBreak_callback_stop)() = NULL; void (*DebugBreak_callback_resume)() = NULL; @@ -97,8 +95,8 @@ void error_Spew(); ////////////////////////////////////////////////////////////////////////////// // initializes error handler. -bool error_Init(bool debugger, bool mono_debug, const char *app_title) { - Debug_Init(debugger, mono_debug); +bool error_Init(bool debugger, const char *app_title) { + Debug_Init(debugger); Error_initialized = true; Exit_message[0] = 0; @@ -114,8 +112,6 @@ bool error_Init(bool debugger, bool mono_debug, const char *app_title) { return true; } -int no_debug_dialog = 0; - // exits the application and prints out a standard error message void Error(const char *fmt, ...) { std::va_list arglist; @@ -132,20 +128,17 @@ void Error(const char *fmt, ...) { mprintf(0, "%s\n", Exit_message); #ifdef _DEBUG - int answer; + int answer = IDOK; if (DebugBreak_callback_stop) (*DebugBreak_callback_stop)(); if (Debug_break) answer = Debug_ErrorBox(OSMBOX_ABORTRETRYIGNORE, Exit_title_str, Exit_message, "Press RETRY to debug."); - else if (!no_debug_dialog) + else answer = Debug_ErrorBox(OSMBOX_OKCANCEL, Exit_title_str, Exit_message, "Press OK to exit, CANCEL to ignore this error and continue."); - if (no_debug_dialog) - answer = IDOK; - switch (answer) { case IDRETRY: debug_break(); // Step Out of this function to see where Error() was called @@ -225,7 +218,7 @@ void AssertionFailed(const char *expstr, const char *file, int line) { // error message output function void error_Spew() { - if (Exit_message[0] && !no_debug_dialog) + if (Exit_message[0]) Debug_MessageBox(OSMBOX_OK, Exit_title_str, Exit_message); } @@ -282,4 +275,4 @@ int OutrageMessageBox(int type, const char *str, ...) { "The dialog that follows this one overflowed its text buffer. The program may crash."); return Debug_MessageBox(os_flags, Messagebox_title, buf); -} \ No newline at end of file +} diff --git a/misc/pserror.h b/misc/pserror.h index 5ec401db4..ea7ee2950 100644 --- a/misc/pserror.h +++ b/misc/pserror.h @@ -152,10 +152,8 @@ #include "debug.h" #include "mono.h" -extern int no_debug_dialog; - // initializes error handler. -bool error_Init(bool debugger, bool mono_debug, const char *app_title); +bool error_Init(bool debugger, const char *app_title); // exits the application and prints out a standard error message void Error(const char *fmt, ...); // prints out an assertion error diff --git a/model/CMakeLists.txt b/model/CMakeLists.txt index c89e063e9..5f0e4126b 100644 --- a/model/CMakeLists.txt +++ b/model/CMakeLists.txt @@ -1,9 +1,11 @@ +set(HEADERS + polymodel.h) set(CPPS newstyle.cpp polymodel.cpp ) -add_library(model STATIC ${CPPS}) +add_library(model STATIC ${HEADERS} ${CPPS}) target_link_libraries(model PRIVATE cfile mem diff --git a/model/polymodel.cpp b/model/polymodel.cpp index e6bf7a464..0a1e0d19a 100644 --- a/model/polymodel.cpp +++ b/model/polymodel.cpp @@ -1154,7 +1154,7 @@ void SetPolymodelProperties(bsp_info *subobj, char *props) { subobj->flags |= SOF_TURRET; subobj->fov = fov_angle / 720.0f; // 720 = 360 * 2 and we want to make fov the amount we can move in either // direction it has a minimum value of (0.0) to [0.5] - subobj->rps = 1.0f / turret_spr; // convert spr to rps (rotations per second) + subobj->rps = 1.0f / turret_spr; // convert spr to rps (rotations per second) subobj->think_interval = reaction_time; return; @@ -1779,7 +1779,7 @@ int ReadNewModelFile(int polynum, CFILE *infile) { case ID_ROT_ANIM: case ID_ANIM: { - int nframes; + int nframes = 0; // mprintf(0,"ROT ANIM chunk!!!\n"); if (!timed) { @@ -1861,7 +1861,7 @@ int ReadNewModelFile(int polynum, CFILE *infile) { } case ID_POS_ANIM: { - int nframes; + int nframes = 0; // mprintf(0,"POS ANIM chunk!!!\n"); if (!timed) { @@ -3052,7 +3052,7 @@ void FreeAllModels() { // Inits our models array and loads our ship pof int InitModels() { - for (auto & Poly_model : Poly_models) { + for (auto &Poly_model : Poly_models) { memset(&Poly_model, 0, sizeof(poly_model)); Poly_model.used = 0; } diff --git a/music/CMakeLists.txt b/music/CMakeLists.txt index 7b34d9bce..1e7cc216f 100644 --- a/music/CMakeLists.txt +++ b/music/CMakeLists.txt @@ -1,4 +1,6 @@ -set(HEADERS) +set(HEADERS + music.h + musiclib.h) set(CPPS omflex.cpp sequencer.cpp diff --git a/netcon/inetfile/inetgetfile.cpp b/netcon/inetfile/inetgetfile.cpp index 3c5401bbe..d3014fc22 100644 --- a/netcon/inetfile/inetgetfile.cpp +++ b/netcon/inetfile/inetgetfile.cpp @@ -248,7 +248,7 @@ BOOL InetGetFile::IsFileReceived() { } BOOL InetGetFile::IsFileError() { - int state; + int state = FTP_STATE_INTERNAL_ERROR; if (m_HardError) return true; if (m_bUseHTTP) { @@ -278,7 +278,7 @@ BOOL InetGetFile::IsFileError() { } int InetGetFile::GetErrorCode() { - int state; + int state = FTP_STATE_INTERNAL_ERROR; if (m_HardError) return m_HardError; if (m_bUseHTTP) { diff --git a/netcon/lanclient/CMakeLists.txt b/netcon/lanclient/CMakeLists.txt index 2c867deb4..deae8140c 100644 --- a/netcon/lanclient/CMakeLists.txt +++ b/netcon/lanclient/CMakeLists.txt @@ -1,6 +1,9 @@ +set(HEADERS + lanclient.h + lanstrings.h) set(CPPS lanclient.cpp) -add_library(Direct_TCP_IP MODULE ${CPPS}) +add_library(Direct_TCP_IP MODULE ${HEADERS} ${CPPS}) set_target_properties(Direct_TCP_IP PROPERTIES PREFIX "") set_target_properties(Direct_TCP_IP PROPERTIES CXX_VISIBILITY_PRESET "hidden") set_target_properties(Direct_TCP_IP PROPERTIES OUTPUT_NAME "Direct TCP~IP") @@ -11,6 +14,9 @@ target_link_libraries(Direct_TCP_IP PRIVATE ui $<$:ws2_32> ) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set_target_properties(Direct_TCP_IP PROPERTIES SUFFIX ".dylib") +endif() add_custom_target(Direct_TCP_IP_Hog COMMAND $ diff --git a/netcon/mtclient/CMakeLists.txt b/netcon/mtclient/CMakeLists.txt index 72940c94b..0bbfb5cde 100644 --- a/netcon/mtclient/CMakeLists.txt +++ b/netcon/mtclient/CMakeLists.txt @@ -1,3 +1,10 @@ +set(HEADERS + chat_api.h + mt_net.h + mtclient.h + mtgametrack.h + mtpilottrack.h + mtstrings.h) set(CPPS chat_api.cpp mt_net.cpp @@ -6,7 +13,7 @@ set(CPPS mtpilottracker.cpp ) -add_library(Parallax_Online MODULE ${CPPS}) +add_library(Parallax_Online MODULE ${HEADERS} ${CPPS}) set_target_properties(Parallax_Online PROPERTIES PREFIX "") set_target_properties(Parallax_Online PROPERTIES CXX_VISIBILITY_PRESET "hidden") set_target_properties(Parallax_Online PROPERTIES OUTPUT_NAME "Parallax Online") @@ -17,6 +24,9 @@ target_link_libraries(Parallax_Online PRIVATE ui $<$:ws2_32> ) +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set_target_properties(Parallax_Online PROPERTIES SUFFIX ".dylib") +endif() add_custom_target(Parallax_Online_Hog COMMAND $ diff --git a/netgames/coop/CMakeLists.txt b/netgames/coop/CMakeLists.txt index 41a391139..c69e29962 100644 --- a/netgames/coop/CMakeLists.txt +++ b/netgames/coop/CMakeLists.txt @@ -1,4 +1,6 @@ -set(HEADERS coop.h) +set(HEADERS + coop.h + coopstr.h) set(CPPS coop.cpp) set(NETGAME_MODULE coop) diff --git a/physics/CMakeLists.txt b/physics/CMakeLists.txt index 1efb7e423..db256db40 100644 --- a/physics/CMakeLists.txt +++ b/physics/CMakeLists.txt @@ -1,3 +1,7 @@ +set(HEADERS + collide.h + findintersection.h + physics.h) set(CPPS collide.cpp findintersection.cpp @@ -5,7 +9,7 @@ set(CPPS physics.cpp ) -add_library(physics STATIC ${CPPS}) +add_library(physics STATIC ${HEADERS} ${CPPS}) target_link_libraries(physics PRIVATE ddio mem diff --git a/rtperformance/CMakeLists.txt b/rtperformance/CMakeLists.txt index 057648148..e05c8bf2d 100644 --- a/rtperformance/CMakeLists.txt +++ b/rtperformance/CMakeLists.txt @@ -1,7 +1,9 @@ +set(HEADERS + rtperformance.h) set(CPPS rtperformance.cpp) -add_library(rtperformance STATIC ${CPPS}) +add_library(rtperformance STATIC ${HEADERS} ${CPPS}) target_link_libraries(rtperformance PRIVATE ddio ) diff --git a/scripts/AIGame.cpp b/scripts/AIGame.cpp index ad92eab77..faddc259a 100644 --- a/scripts/AIGame.cpp +++ b/scripts/AIGame.cpp @@ -1516,7 +1516,7 @@ struct guidebot_data { float mode_time; uint16_t mp_slot; // Owner's slot number - int my_player; // Owner's object reference + int my_player; // Owner's object reference bool f_parented; // Buddy will not collide with parent until it isn't parented bool f_pickup; // Marked for pickup by the owner @@ -8072,8 +8072,8 @@ void BarnSwallow::DoFrame(int me) { case BSM_NEST: { if (Game_GetTime() > memory->next_mode_time) { int target; - int room; - int me_room; + int room = 0; + int me_room = 0; AI_Value(me, VF_GET, AIV_I_TARGET_HANDLE, &target); diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 414c50caf..ccff1c633 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -1,5 +1,11 @@ set(CMAKE_FOLDER "scripts") +set(HEADERS + AIGame3_External.h + linux_lib.h + osiris_common.h + osiris_import.h + osiris_vector.h) set(CPPS $<$: linux_lib.cpp @@ -69,7 +75,7 @@ set(SCRIPTS #) foreach(SCRIPT ${SCRIPTS}) - add_library(${SCRIPT} MODULE ${CPPS} "${SCRIPT}.cpp") + add_library(${SCRIPT} MODULE ${CPPS} ${HEADERS} "${SCRIPT}.cpp") target_link_libraries(${SCRIPT} fix misc diff --git a/sndlib/CMakeLists.txt b/sndlib/CMakeLists.txt index 18c735066..cf0fd2edb 100644 --- a/sndlib/CMakeLists.txt +++ b/sndlib/CMakeLists.txt @@ -1,3 +1,15 @@ +set(HEADERS + auddev.h + ddsndgeometry.h + ds3dlib.h + ds3dlib_internal.h + hlsoundlib.h + mixer.h + sdlsound.h + sndrender.h + soundload.h + ssl_lib.h + vmanpset.h) set(CPPS hlsoundlib.cpp sndrender.cpp @@ -9,7 +21,7 @@ set(CPPS sdlsound.cpp ) -add_library(sndlib STATIC ${CPPS}) +add_library(sndlib STATIC ${HEADERS} ${CPPS}) target_link_libraries(sndlib PRIVATE cfile ddio diff --git a/stream_audio/CMakeLists.txt b/stream_audio/CMakeLists.txt index 34a70b745..2852282e7 100644 --- a/stream_audio/CMakeLists.txt +++ b/stream_audio/CMakeLists.txt @@ -1,4 +1,5 @@ -set(HEADERS) +set(HEADERS + streamaudio.h) set(CPPS osfarchive.cpp streamaudio.cpp diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 7b3cd299b..f09c2e496 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,3 +1,9 @@ +set(HEADERS + UIlib.h + ui.h + uidraw.h + uires.h + uisys.h) set(CPPS UIButton.cpp UICombo.cpp @@ -16,7 +22,7 @@ set(CPPS UIWindow.cpp ) -add_library(ui STATIC ${CPPS}) +add_library(ui STATIC ${HEADERS} ${CPPS}) target_link_libraries(ui PRIVATE ddio grtext diff --git a/unzip/CMakeLists.txt b/unzip/CMakeLists.txt index 58fd49376..a3c7984ae 100644 --- a/unzip/CMakeLists.txt +++ b/unzip/CMakeLists.txt @@ -1,3 +1,4 @@ +set(HEADERS unzip.h) set(CPPS unzip.cpp) add_library(unzip STATIC ${HEADERS} ${CPPS}) diff --git a/vcpkg.json b/vcpkg.json index 56db60f8a..c76a14c1e 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,11 +1,18 @@ { - "builtin-baseline": "f7423ee180c4b7f40d43402c2feb3859161ef625", + "builtin-baseline": "198d68dbcc6c907cb3d0b9b1d93c3df6ecf93c62", "dependencies": [ "gtest", "zlib", { "name": "sdl2", - "version>=": "2.30.3" + "version>=": "2.30.3", + "features": ["x11","wayland", "alsa"], + "platform": "linux" + }, + { + "name": "sdl2", + "version>=": "2.30.3", + "platform": "!linux" } ], "overrides": [