Compare commits

...

9 Commits

Author SHA1 Message Date
Ian Brun
7e6be03c5d
Merge pull request #166 from meekee7/mousewheel-crash
Resolve mousewheel crash
2021-05-07 20:34:49 +02:00
Ian Brun
fbf95a4063
Merge pull request #167 from meekee7/cmake-and-documentation
Updates to CMake script and documentation
2021-05-07 20:33:56 +02:00
Michael
d72763b9c7 CMakeCommon.cmake: generate map files 2021-04-25 02:24:12 +02:00
Michael
bcf924c113 Root/CMakeLists.txt: do not force set cmake variable 2021-04-25 01:38:15 +02:00
Michael
b471e469d4 MemoryDebugging.md: updates and clarifications to the memory debugging instructions 2021-04-24 22:41:45 +02:00
Michael
74a9f6847e Root/README.md: update to new executable name
- Add reference to memory debugging instructions
2021-04-24 22:36:00 +02:00
Michael
aa4cc9ff2e Root/CMakeLists.txt: add option to use AddressSanitizer 2021-04-24 18:38:31 +02:00
Michael
18ce52d8ef mainwnd.cpp: add nullptr check 2021-04-23 21:33:52 +02:00
meekee7
4ff32feb8c
Merge pull request #37 from OpenTrespasser/dev
Merge upstream/dev into staging
2021-04-04 00:19:19 +02:00
5 changed files with 31 additions and 12 deletions

View File

@ -25,13 +25,18 @@ else()
set(CMAKE_MFC_FLAG 2)
endif()
set(ENABLE_SANITIZERS FALSE CACHE BOOL INTERNAL)
if (ENABLE_SANITIZERS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
endif()
set(USE_TRESPASSER_DIRECTORY TRUE CACHE BOOL INTERNAL)
get_filename_component(TRESPASS_INSTALL_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\DreamWorks Interactive\\Trespasser;Installed Directory]" ABSOLUTE)
if ( (NOT TRESPASS_INSTALL_DIR STREQUAL "/registry") AND USE_TRESPASSER_DIRECTORY ) #Found and read the registry entry, and it is valid
set(FOUND_TRESPASS_DIR TRUE)
set(CMAKE_INSTALL_PREFIX ${TRESPASS_INSTALL_DIR} CACHE STRING INTERNAL FORCE)
set(CMAKE_INSTALL_PREFIX ${TRESPASS_INSTALL_DIR} CACHE STRING INTERNAL)
else()
set(FOUND_TRESPASS_DIR FALSE)
endif()

View File

@ -4,28 +4,32 @@ As is the case with many C/C++ programs, OpenTrespasser has frequent problems wi
Here is an example: the game used to crash after reloading the level after death. The crashes were in seemingly random places: opening a file, reading the registry, resizing a vector of UI elements, and more. Some of these spots were within Win32 API calls. Mitigating those exceptions in place just shifted the problem to somewhere else.
What all those places had in common was a memory deallocation operation. Clearly, this was a case of heap corruption. Execution with FPHV (see below) revealed the cause: memory writes outside of array boundaries in the pathfinding for the dinosaur AI.
What all those places had in common was a memory deallocation operation. Clearly, this was a case of heap corruption. Execution with FPHV (see below) revealed the cause: illegal memory writes outside of array boundaries in the pathfinding for the dinosaur AI.
OpenTrespasser should be checked regularly for MAVs that are not caught be the default runtime checks. Tools and libraries exist to raise errors immediately when they occur. However, these techniques come with a significant performance penalty for both speed and memory.
#### Full Page Heap Verification (FPHV)
This technique catches illegal memory reads and writes as soon as they occur.
This technique catches illegal memory reads and writes as soon as they occur. It works by reserving an entire 'memory page' for each dynamically allocated memory block. Furthermore, it surrounds each allocation with inaccessible memory pages. Thus an illegal memory access is more likely to also hit an invalid address and raise an exception.
1. Open a command line with admin rights and navigate to `C:\Program Files (x86)\Windows Kits\10\Debuggers\x64`.
How to use FPHV:
1. Open a command line *with admin rights* and navigate to `C:\Program Files (x86)\Windows Kits\10\Debuggers\x64`.
1. Run the command `gflags /p /enable OpenTrespasser.exe /full`. You do *not* have to specify the full path to `OpenTrespasser.exe`. Instead, this setting will affect *any* copy of the program.
1. Verify that the setting was applied with `gflags /p`.
1. Start the game. If you are starting it from outside Visual Studio, remember to attach the debugger manually.
1. Test the game normally and wait for an exception to be raised by a MAV.
1. After you are done with debugging, disable FPHV with `gflags /p /disable OpenTrespasser.exe`.
If `gflags` is missing in the Windows SDK, [download the installer for the latest Windows SDK from Microsoft](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/) and install the subpackage "Debugging Tools for Wndows".
If `gflags` is missing in the Windows SDK, [download the installer for the latest Windows SDK from Microsoft](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/) and install the subpackage "Debugging Tools for Windows".
[For a more detailed explanation of `gflags` and FPHV, please refer to the documentation by Microsoft.](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/example-12---using-page-heap-verification-to-find-a-bug)
#### VS AddressSanitizer
Visual Studio 2019 offers an *experimental* AddressSanitizer option, based on the Clang/LLVM address sanitizer library. It needs to be installed as a VS package and requires VS 2019 15.7 or higher to work in all configurations.
Visual Studio 2019 offers an AddressSanitizer option, based on the Clang/LLVM address sanitizer library. It needs to be installed as an extra VS package.
[For more details, please refer to the documentation by Microsoft.](https://devblogs.microsoft.com/cppblog/addresssanitizer-asan-for-windows-with-msvc/)
To activate AddressSanitizer via CMake, add `/fsanitize=address` to the compiler flags.
Set the CMake variable `ENABLE_SANITIZERS` to `TRUE` to activate AddressSanitizer.
When you launch Trespasser outside of Visual Studio, you may need to copy the AddressSanitizer DLLs to your execution directory. The DLLs (`clang_rt.asan*.dll`) can be found in the `bin` directory of the MSVC tools directory.
If the runtime libraries are statically linked (which is the default for OTP), then using AddressSanitizer in combination with MFC will result in linker errors because both libraries want to implement the operators `new` and `delete`. This affects certain MFC-based tools like *GUIApp*, but not the main game.
If instead the runtime libraries are dynamically linked and you want to launch `OpenTrespasser.exe` or other applications outside of Visual Studio, you may need to copy the AddressSanitizer DLLs to your execution directory. The DLLs (`clang_rt.asan*.dll`) can be found in the `bin` directory of the MSVC tools directory.

View File

@ -31,10 +31,10 @@ Note that debug symbols (PDBs) are generated in all three configurations, so usi
## Execution and debugging
The game executable `trespass.exe` needs to be run in the Trespasser game directory, usually found in the `C:\Program Files (x86)\...` path.
The game executable `OpenTrespasser.exe` needs to be run in the Trespasser game directory, usually found in the `C:\Program Files (x86)\...` path.
If a Trespasser installation is detected by CMake, then the Trespasser directory is automatically set to be the working directory for debug execution in VS. This means that you can start the game directly from VS.
Also the built `trespass.exe` is automatically copied to the Trespasser directory after each build.
Also the built `OpenTrespasser.exe` is automatically copied to the Trespasser directory after each build.
Depending on your system configuration, a program running in the Trespasser directory might require elevated rights to write files in that directory. It is recommended that you start VS with admin rights (see below). You should also configure the program to start with admin rights directly, via the compatibility settings.
@ -79,8 +79,10 @@ By launching VS with admin rights, it can launch Trespasser with elevated rights
- The old Direct3D code in the Windows SDK headers is only activated if your project is based on Direct3D 7.0 or lower. In modern Windows SDKs, the MFC headers include the stuff of newer Direct3D versions by default.
- If you get the error `The command "setlocal` during the build, that means something went wrong in the postbuild step which is supposed to copy the newly built `trespass.exe` to the Trespasser directory.
- If you get the error `The command "setlocal` during the build, that means something went wrong in the postbuild step which is supposed to copy the newly built `OpenTrespasser.exe` to the Trespasser directory.
- Ensure that VS is started with Admin rights (see above)
- If the problem persists, disable the postbuild step.
- To disable it in VS, open the project settings for `trespass`, go to `Build Events` and remove the postbuild command. Note that it will be added again when the solution is regenerated by CMake.
- To disable the postbuild step in CMake, regenerate the solution, but set the CMake variable `USE_TRESPASSER_DIRECTORY` to `FALSE`. That can be easily done with the CMake GUI.
- To disable the postbuild step in CMake, regenerate the solution, but set the CMake variable `USE_TRESPASSER_DIRECTORY` to `FALSE`. That can be easily done with the CMake GUI.
- See `Documents/MemoryDebugging.md` for instructions on advanced debugging tools for memory corruption.

View File

@ -239,6 +239,8 @@ void CMainWnd::OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
void CMainWnd::OnMouseWheel(HWND hwnd, int x, int y, int zDelta, UINT fwKeys)
{
if (!m_pUIMgr)
return;
if (CUIWnd* puiwnd = m_pUIMgr->GetActiveUIWnd(); puiwnd && !puiwnd->m_bExitWnd)
puiwnd->OnMouseWheel(x, y, zDelta, fwKeys);
}

View File

@ -25,6 +25,12 @@ set(CMAKE_CXX_FLAGS_FINAL ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} PARENT_SCOPE)
set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} PARENT_SCOPE)
set(CMAKE_EXE_LINKER_FLAGS_TMP "${CMAKE_EXE_LINKER_FLAGS} /MAP:${PROJECT_NAME}.map")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS_TMP}" PARENT_SCOPE)
set(CMAKE_SHARED_LINKER_FLAGS_TMP "${CMAKE_SHARED_LINKER_FLAGS} /MAP:${PROJECT_NAME}.map")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_TMP}" PARENT_SCOPE)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE_TMP ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO})
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE_TMP ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO})