├── .editorconfig ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── RELEASES.md ├── d2dx-defaults.cfg ├── screenshots ├── d2dx1.png ├── d2dx2.png ├── d2dx3.png ├── d2dx_dxnowide1.png ├── d2dx_dxnowide2.png ├── d2dx_dxnowide3.png ├── d2dx_fxaa1.png ├── d2dx_nofxaa1.png ├── d2dx_scaling_0.png ├── d2dx_scaling_1.png ├── d2dx_scaling_2.png ├── svens1.png ├── svens2.png └── svens3.png ├── src ├── d2dx.sln ├── d2dx │ ├── Batch.h │ ├── Buffer.h │ ├── BuiltinMods.cpp │ ├── BuiltinMods.h │ ├── CompatModeCheck.cpp │ ├── CompatModeCheck.h │ ├── Constants.hlsli │ ├── D2DXConfigurator.cpp │ ├── D2DXConfigurator.h │ ├── D2DXContext.cpp │ ├── D2DXContext.h │ ├── D2DXContextFactory.cpp │ ├── D2DXContextFactory.h │ ├── D2Types.h │ ├── Detours.cpp │ ├── Detours.h │ ├── Display.hlsli │ ├── DisplayBilinearScalePS.hlsl │ ├── DisplayCatmullRomScalePS.hlsl │ ├── DisplayIntegerScalePS.hlsl │ ├── DisplayNearestScalePS.hlsl │ ├── DisplayNonintegerScalePS.hlsl │ ├── DisplayVS.hlsl │ ├── ErrorHandling.h │ ├── FXAA.hlsli │ ├── Game.hlsli │ ├── GameBilinearPS.hlsl │ ├── GameHelper.cpp │ ├── GameHelper.h │ ├── GamePS.hlsl │ ├── GameVS.hlsl │ ├── GammaPS.hlsl │ ├── ID2DXContext.h │ ├── ID2InterceptionHandler.h │ ├── IGlide3x.h │ ├── IRenderContext.h │ ├── ITextureCache.h │ ├── IWin32InterceptionHandler.h │ ├── Metrics.cpp │ ├── Metrics.h │ ├── Options.cpp │ ├── Options.h │ ├── Profiler.cpp │ ├── Profiler.h │ ├── RenderContext.cpp │ ├── RenderContext.h │ ├── RenderContextResources.cpp │ ├── RenderContextResources.h │ ├── ResolveAA.hlsl │ ├── TextureCache.cpp │ ├── TextureCache.h │ ├── TextureCachePolicyBitPmru.cpp │ ├── TextureCachePolicyBitPmru.h │ ├── TextureHasher.cpp │ ├── TextureHasher.h │ ├── Types.h │ ├── Utils.cpp │ ├── Utils.h │ ├── Vertex.h │ ├── VideoGammaPS.hlsl │ ├── VideoPS.hlsl │ ├── d2dx.rc │ ├── d2dx.vcxproj │ ├── d2dx.vcxproj.filters │ ├── d2dx.vcxproj.user │ ├── dllmain.cpp │ ├── dx256_bmp.h │ ├── glide3x.cpp │ ├── pch.cpp │ ├── pch.h │ └── resource.h └── d2dxtests │ ├── TestBatch.cpp │ ├── TestMetrics.cpp │ ├── TestSimd.cpp │ ├── TestTextureCache.cpp │ ├── d2dxtests.vcxproj │ ├── d2dxtests.vcxproj.filters │ ├── d2dxtests.vcxproj.user │ └── pch.cpp ├── thirdparty ├── detours │ ├── detours.h │ ├── detours.lib │ ├── detours.pdb │ ├── detver.h │ ├── syelog.h │ └── syelog.lib ├── fnv │ ├── fnv.h │ ├── hash_32a.c │ └── license.txt ├── glide3 │ ├── 3DFX.H │ ├── FXDLL.H │ ├── FXGLOB.H │ ├── FXOS.H │ ├── SST1VID.H │ ├── glide.h │ ├── glidesys.h │ ├── glideutl.h │ └── sst1init.h ├── pocketlzma │ ├── pocketlzma-LICENSE.txt │ └── pocketlzma.hpp ├── sgd2freeres │ ├── SGD2FreeRes - CHANGELOG.md │ ├── SGD2FreeRes - COPYING │ ├── SGD2FreeRes - LICENSE.md │ ├── SGD2FreeRes - README.md │ ├── SGD2FreeRes.dll │ ├── SGD2FreeRes.dll.lzma │ ├── SGD2FreeRes.mpq │ └── SGD2FreeRes.mpq.lzma ├── stb_image │ └── stb_image_write.h ├── toml │ ├── toml.c │ └── toml.h └── xxhash │ ├── CHANGELOG │ ├── LICENSE │ ├── xxhash.c │ └── xxhash.h └── toml-LICENSE.txt /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.*] 2 | indent_style = tab 3 | insert_final_newline = true 4 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '44 20 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'cpp' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /src/.vs/d2dx/v16/.suo 2 | /src/.vs/ 3 | **.aps 4 | **.res 5 | **/Debug/ 6 | **/Release/ 7 | **/Release (ResMod)/ 8 | **/Release (Profile)/ 9 | *_cso.h 10 | publish/ 11 | **_dxbc.txt 12 | /.vs/ 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # D2DX 2 | 3 | D2DX is a Glide-wrapper and mod that makes the classic Diablo II/LoD run well on modern PCs, while honoring the original look and feel of the game. Play in a window or in fullscreen, glitch-free, with or without enhancements like widescreen, true high framerate and anti-aliasing. 4 | 5 | ## Features 6 | 7 | - Turns the game into a well behaved DirectX 11 title on Windows 10 (also 7, 8 and 8.1). 8 | - High quality scaling to fit modern screen sizes, including [widescreen aspect ratios](https://raw.githubusercontent.com/bolrog/d2dx/main/screenshots/d2dx2.png). 9 | - High FPS mod using motion smoothing, bypassing the internal 25 fps limit. Play at 60 fps and higher! ([video](https://imgur.com/a/J1F8Ctb)) 10 | - [Anti-aliasing](https://github.com/bolrog/d2dx/wiki/Screenshots#anti-aliasing) of specific jagged edges in the game (sprites, walls, some floors). 11 | - Seamless windowed/fullscreen switching with (ALT-Enter). 12 | - Improved fullscreen: instant ALT-TAB and low latency. 13 | - Improved windowed mode. 14 | - Proper gamma/contrast. 15 | - Fixes a few window-related glitches in Diablo II itself. 16 | 17 | ### Video Showcasing Motion Smoothing 18 | 19 | [FPS increase in menus, FPS increase for projectiles, monsters, +more](https://imgur.com/a/J1F8Ctb) 20 | 21 | ## Requirements 22 | 23 | - Windows 7 SP1 and above (10 recommended for latency improvements). 24 | - A CPU with SSE4 support. 25 | - Integrated graphics or discrete GPU with DirectX 10.1 support. 26 | 27 | ## Version Compatibility 28 | 29 | Basic rendering is supported for all Diablo II versions and should work for all mods. 30 | 31 | High resolution is provided by [SGD2FreeRes] and supports the following versions: `1.09d`, `1.10`, `1.12`, `1.13c`, `1.13d`, `1.14c`, `1.14d`. 32 | 33 | The anti-aliasing filter is supported on all LoD versions except: `1.09c`, `1.13a` and `1.13b`. 34 | 35 | High FPS and motion smoothing is provided by [D2fps] and supports nearly all released Diablo II versions. This may have compatibility issues with other mods providing the same features. 36 | 37 | ### MedianXL 38 | 39 | MedianXL is not compatible with the resolution mod. Launch with `-dxnoresmod` or set `noresmod=false` in `d2dx.cfg`. 40 | 41 | ### Project Diablo 2 42 | 43 | Auto casting can sometimes get stuck when the game fps is unlocked via d2fps. Can be worked around by setting the fps to a number higher than can be rendered via `d2fps.ini` (e.g. 10000). Vsync can still be used to limit the frame rate via `d2dx.cfg`. 44 | 45 | ### Others 46 | 47 | For compatibility with other mods, see the [wiki](https://github.com/bolrog/d2dx/wiki/Compatibility-with-other-mods). 48 | 49 | ## Documentation 50 | 51 | This readme contains basic information to get you started. See the [D2DX wiki](https://github.com/bolrog/d2dx/wiki/) for more documentation. 52 | 53 | ## Installation 54 | 55 | Copy the included "glide3x.dll" and "d2fps.dll" into your Diablo II folder. 56 | 57 | Note that in some cases you may have to also download and install the Visual C++ runtime library from Microsoft: 58 | 59 | ## Usage 60 | 61 | To start the game with D2DX the game will have to be launched in glide mode. This can be done by: 62 | 63 | - Launching the game with `-3dfx`. e.g. `game.exe -3dfx`. 64 | - Selecting '3dfx Glide' from `D2VidTst.exe` 65 | - Setting `HKEY_CURRENT_USER\SOFTWARE\Blizzard Entertainment\Diablo II\VideoConfig` to `3` in the registry 66 | 67 | Windowed/fullscreen mode can be switched at any time by pressing ALT-Enter. The normal -w command-line option works too. 68 | 69 | Many of the default settings of D2DX can be changed. For a full list of command-line options and how to use a configuration file, see the [wiki](https://github.com/bolrog/d2dx/wiki/). 70 | 71 | ## Troubleshooting 72 | 73 | ### I get a message box saying "Diablo II is unable to proceed. Unsupported graphics mode." 74 | 75 | You are running the download version of Diablo II from blizzard.com. This can be modified to work with D2DX (Wiki page about this to come). 76 | 77 | ### It's ugly/slow/buggy 78 | 79 | Let me know by filing an issue! I'd like to keep improving D2DX (within the scope of the project). 80 | 81 | ## Credits 82 | 83 | Continued Development/Maintainence: Jarcho 84 | Original development: bolrog 85 | Patch contributions: Xenthalon 86 | 87 | The research of many people in the Diablo II community over twenty years made this project possible. 88 | 89 | Thanks to Mir Drualga for making the fantastic SGD2FreeRes mod! 90 | Thanks also to everyone who contributes bug reports. 91 | 92 | D2DX uses the following third party libraries: 93 | 94 | - FNV1a hash reference implementation, which is in the public domain. 95 | - Detours by Microsoft. 96 | - SGD2FreeRes by Mir Drualga, licensed under Affero GPL v3. 97 | - FXAA implementation by Timothy Lottes. (This software contains source code provided by NVIDIA Corporation.) 98 | - stb_image by Sean Barrett 99 | - pocketlzma by Robin Berg Pettersen 100 | - 9-tap Catmull-Rom texture filtering by TheRealMJP. 101 | - xxHash by Yann Collet 102 | 103 | [SGD2FreeRes]: https://github.com/mir-diablo-ii-tools/SlashGaming-Diablo-II-Free-Resolution 104 | [D2fps]: https://github.com/Jarcho/d2-rs/tree/main/d2fps 105 | -------------------------------------------------------------------------------- /d2dx-defaults.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # This is an example config file for D2DX. 3 | # 4 | # If you don't like the default settings, you can edit this file, rename it to "d2dx.cfg" 5 | # and place it in the game folder. 6 | # 7 | 8 | [window] 9 | scale=1.0 # range 1.0-3.0, a scale factor for the window 10 | position=[-1,-1] # if [-1,-1] the window will be centered, otherwise placed at the explicit position given here 11 | frameless=false # if true, the window frame (caption bar etc) will be removed 12 | 13 | [game] 14 | size=[-1,-1] # if [-1,-1] d2dx will decide a suitable game size, otherwise will use the size given here 15 | filtering=0 # if 0, will use high quality filtering (sharp, more pixelated) 16 | # 1, will use bilinear filtering (blurry) 17 | # 2, will use catmull-rom filtering (higher quality than bilinear) 18 | # 3, will use nearest neighbour filtering (sharp, pixelated) 19 | # 4, will rasterize the game at the target resolution 20 | bilinear-sharpness=2.0 # Sharpness of the bilinear filter when rendering textures. Can be set to any value higher than 1. 21 | # 1.0, same as a regular bilinear filter 22 | # 2.0, same as a 2x bilinear-sharp filter 23 | 24 | # 25 | # Opt-outs from default D2DX behavior 26 | # 27 | [optouts] 28 | noclipcursor=false # if true, will not lock the mouse cursor to the game window 29 | nofpsmod=false # if true, will not load d2fps 30 | noresmod=false # if true, will not apply the built-in D2HD resolution mod (precludes widescreen support) 31 | nowide=false # if true, will not choose a widescreen resolution (if noresmod is true, this does nothing) 32 | nologo=false # if true, will not display the D2DX logo on the title screen 33 | novsync=true # if true, will not use vertical sync 34 | noframetearing=true # if true, will not allow frame tearing; must be `false` for variable refresh to work 35 | noaa=false # if true, will not apply anti-aliasing to jagged edges 36 | nocompatmodefix=false # if true, will not block the use of "Windows XP compatibility mode" 37 | notitlechange=false # if true, will not change the window title text 38 | nokeepaspectratio=false # if true, will not keep the aspect ratio when drawing to the screen 39 | -------------------------------------------------------------------------------- /screenshots/d2dx1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx1.png -------------------------------------------------------------------------------- /screenshots/d2dx2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx2.png -------------------------------------------------------------------------------- /screenshots/d2dx3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx3.png -------------------------------------------------------------------------------- /screenshots/d2dx_dxnowide1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_dxnowide1.png -------------------------------------------------------------------------------- /screenshots/d2dx_dxnowide2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_dxnowide2.png -------------------------------------------------------------------------------- /screenshots/d2dx_dxnowide3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_dxnowide3.png -------------------------------------------------------------------------------- /screenshots/d2dx_fxaa1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_fxaa1.png -------------------------------------------------------------------------------- /screenshots/d2dx_nofxaa1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_nofxaa1.png -------------------------------------------------------------------------------- /screenshots/d2dx_scaling_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_scaling_0.png -------------------------------------------------------------------------------- /screenshots/d2dx_scaling_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_scaling_1.png -------------------------------------------------------------------------------- /screenshots/d2dx_scaling_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/d2dx_scaling_2.png -------------------------------------------------------------------------------- /screenshots/svens1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/svens1.png -------------------------------------------------------------------------------- /screenshots/svens2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/svens2.png -------------------------------------------------------------------------------- /screenshots/svens3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/screenshots/svens3.png -------------------------------------------------------------------------------- /src/d2dx.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33516.290 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d2dx", "d2dx\d2dx.vcxproj", "{93A28F27-8D56-470C-B699-15B0CF2C926A}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d2dxtests", "d2dxtests\d2dxtests.vcxproj", "{64214704-FE00-4DB6-BEFA-1E622F7262A1}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x86 = Debug|x86 13 | Release (Profile)|x86 = Release (Profile)|x86 14 | Release (ResMod)|x86 = Release (ResMod)|x86 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Debug|x86.ActiveCfg = Debug|Win32 19 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Debug|x86.Build.0 = Debug|Win32 20 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Release (Profile)|x86.ActiveCfg = Release (Profile)|Win32 21 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Release (Profile)|x86.Build.0 = Release (Profile)|Win32 22 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Release (ResMod)|x86.ActiveCfg = Release (ResMod)|Win32 23 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Release (ResMod)|x86.Build.0 = Release (ResMod)|Win32 24 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Release|x86.ActiveCfg = Release|Win32 25 | {93A28F27-8D56-470C-B699-15B0CF2C926A}.Release|x86.Build.0 = Release|Win32 26 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Debug|x86.ActiveCfg = Debug|Win32 27 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Debug|x86.Build.0 = Debug|Win32 28 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Release (Profile)|x86.ActiveCfg = Release (Profile)|Win32 29 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Release (Profile)|x86.Build.0 = Release (Profile)|Win32 30 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Release (ResMod)|x86.ActiveCfg = Release (ResMod)|Win32 31 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Release (ResMod)|x86.Build.0 = Release (ResMod)|Win32 32 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Release|x86.ActiveCfg = Release|Win32 33 | {64214704-FE00-4DB6-BEFA-1E622F7262A1}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {680244CF-729A-4310-A2CA-D9ABD4923671} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /src/d2dx/Buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "ErrorHandling.h" 22 | 23 | namespace d2dx 24 | { 25 | template 26 | struct Buffer final 27 | { 28 | Buffer() noexcept : 29 | items(nullptr), 30 | capacity(0) 31 | { 32 | } 33 | 34 | Buffer(uint32_t capacity_, bool zeroFill = false) noexcept : 35 | items((T* __restrict)_aligned_malloc(sizeof(T)* capacity_, 256)), 36 | capacity(capacity_) 37 | { 38 | assert(items); 39 | 40 | if (!items) 41 | { 42 | D2DX_FATAL_ERROR("Out of memory."); 43 | } 44 | 45 | if (!zeroFill) 46 | { 47 | return; 48 | } 49 | 50 | ::memset(items, 0, sizeof(T) * capacity); 51 | } 52 | 53 | Buffer(uint32_t capacity_, bool fill, T fillValue) noexcept : 54 | Buffer(capacity_, false) 55 | { 56 | if (!fill) 57 | { 58 | return; 59 | } 60 | 61 | for (uint32_t i = 0; i < capacity; ++i) 62 | { 63 | items[i] = fillValue; 64 | } 65 | } 66 | 67 | Buffer(const Buffer&) = delete; 68 | 69 | Buffer& operator=(const Buffer&) = delete; 70 | 71 | Buffer(Buffer&& rhs) noexcept : Buffer() 72 | { 73 | std::swap(items, rhs.items); 74 | std::swap(capacity, rhs.capacity); 75 | } 76 | 77 | Buffer& operator=(Buffer&& rhs) noexcept 78 | { 79 | std::swap(items, rhs.items); 80 | std::swap(capacity, rhs.capacity); 81 | return *this; 82 | } 83 | 84 | ~Buffer() noexcept 85 | { 86 | _aligned_free(items); 87 | } 88 | 89 | T* __restrict items; 90 | uint32_t capacity; 91 | }; 92 | } 93 | -------------------------------------------------------------------------------- /src/d2dx/BuiltinMods.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "BuiltinMods.h" 21 | #include "Utils.h" 22 | #include "resource.h" 23 | 24 | using namespace d2dx; 25 | 26 | #ifdef D2DX_RES_MOD 27 | bool WriteResourceToFile( 28 | _In_ HMODULE hModule, 29 | _In_ int32_t resourceId, 30 | _In_z_ const char* ext, 31 | _In_z_ const char* filename) 32 | { 33 | void* payloadPtr = nullptr; 34 | DWORD payloadSize = 0; 35 | HRSRC resourceInfo = nullptr; 36 | HGLOBAL resourceData = nullptr; 37 | HANDLE file = nullptr; 38 | DWORD bytesWritten = 0; 39 | bool succeeded = true; 40 | 41 | resourceInfo = FindResourceA(hModule, MAKEINTRESOURCEA(resourceId), ext); 42 | if (!resourceInfo) 43 | { 44 | succeeded = false; 45 | goto end; 46 | } 47 | 48 | resourceData = LoadResource(hModule, resourceInfo); 49 | if (!resourceData) 50 | { 51 | succeeded = false; 52 | goto end; 53 | } 54 | 55 | payloadSize = SizeofResource(hModule, resourceInfo); 56 | payloadPtr = LockResource(resourceData); 57 | if (!payloadPtr || !payloadSize) 58 | { 59 | succeeded = false; 60 | goto end; 61 | } 62 | 63 | succeeded = DecompressLZMAToFile((const uint8_t*)payloadPtr, payloadSize, filename); 64 | 65 | end: 66 | if (resourceData) 67 | { 68 | UnlockResource(resourceData); 69 | } 70 | if (file) 71 | { 72 | CloseHandle(file); 73 | } 74 | 75 | return succeeded; 76 | } 77 | 78 | bool WriteConfig( 79 | _In_ Size gameSize) 80 | { 81 | HANDLE file = nullptr; 82 | DWORD bytesWritten = 0; 83 | bool succeeded = true; 84 | 85 | file = CreateFileA("d2dx_sgd2freeres.json", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 86 | if (!file) 87 | { 88 | succeeded = false; 89 | goto end; 90 | } 91 | 92 | char configStr[1024]; 93 | 94 | sprintf_s(configStr, 95 | "{\r\n" 96 | " \"D2DX\" : \"PLEASE DO NOT EDIT THIS CONFIGURATION FILE. IT IS GENERATED ON EVERY STARTUP.\",\r\n" 97 | " \"SlashGaming Diablo II Free Resolution\": {\r\n" 98 | " \"!!!Metadata (Do not modify)!!!\": {\r\n" 99 | " \"Major Version A\": 3,\r\n" 100 | " \"Major Version B\" : 0,\r\n" 101 | " \"Minor Version A\" : 1,\r\n" 102 | " \"Minor Version B\" : 0\r\n" 103 | " },\r\n" 104 | " \"Ingame Resolutions\": [\r\n" 105 | " \"640x480\",\r\n" 106 | " \"800x600\",\r\n" 107 | " \"%ix%i\"\r\n" 108 | " ],\r\n" 109 | " \"Ingame Resolution Mode\" : 2,\r\n" 110 | " \"Main Menu Resolution\" : \"800x600\",\r\n" 111 | " \"Custom MPQ File\": \"d2dx_sgd2freeres.mpq\",\r\n" 112 | " \"Enable Screen Border Frame?\" : true,\r\n" 113 | " \"Use Original Screen Border Frame?\" : false,\r\n" 114 | " \"Use 800 Interface Bar?\" : true\r\n" 115 | " },\r\n" 116 | " \"!!!Globals!!!\": {\r\n" 117 | " \"Config Tab Width\": 4\r\n" 118 | " }\r\n" 119 | "}\r\n", 120 | gameSize.width, gameSize.height); 121 | 122 | if (!WriteFile(file, configStr, strlen(configStr), &bytesWritten, nullptr)) 123 | { 124 | succeeded = false; 125 | goto end; 126 | } 127 | 128 | end: 129 | if (file) 130 | { 131 | CloseHandle(file); 132 | } 133 | 134 | return succeeded; 135 | } 136 | #endif 137 | 138 | _Use_decl_annotations_ 139 | void BuiltinMods::Init( 140 | HMODULE hModule, 141 | Size gameSize, 142 | Options& options) 143 | { 144 | if (!hModule) 145 | { 146 | return; 147 | } 148 | 149 | if (!options.GetFlag(OptionsFlag::NoResMod)) 150 | { 151 | #ifdef D2DX_RES_MOD 152 | D2DX_LOG("Writing SGD2FreeRes files."); 153 | 154 | if (!WriteResourceToFile(hModule, IDR_SGD2FR_MPQ, "mpq", "d2dx_sgd2freeres.mpq")) 155 | { 156 | options.SetFlag(OptionsFlag::NoResMod, true); 157 | D2DX_LOG("Failed to write d2dx_sgd2freeres.mpq"); 158 | goto LOAD_FPS; 159 | } 160 | 161 | if (!WriteResourceToFile(hModule, IDR_SGD2FR_DLL, "dll", "d2dx_sgd2freeres.dll")) 162 | { 163 | options.SetFlag(OptionsFlag::NoResMod, true); 164 | D2DX_LOG("Failed to write d2dx_sgd2freeres.mpq"); 165 | goto LOAD_FPS; 166 | } 167 | 168 | if (!WriteConfig(gameSize)) 169 | { 170 | options.SetFlag(OptionsFlag::NoResMod, true); 171 | D2DX_LOG("Failed to write SGD2FreeRes configuration."); 172 | goto LOAD_FPS; 173 | } 174 | 175 | D2DX_LOG("Initializing SGD2FreeRes."); 176 | if (!LoadLibraryW(L"d2dx_sgd2freeres.dll")) { 177 | options.SetFlag(OptionsFlag::NoResMod, true); 178 | D2DX_LOG("Failed to load d2dx_sgd2freeres.dll."); 179 | goto LOAD_FPS; 180 | } 181 | #else 182 | D2DX_LOG("Initializing SGD2FreeRes."); 183 | if (!LoadLibraryW(L"SGD2FreeRes.dll")) { 184 | options.SetFlag(OptionsFlag::NoResMod, true); 185 | D2DX_LOG("Failed to load SGD2FreeRes.dll"); 186 | goto LOAD_FPS; 187 | } 188 | #endif 189 | } 190 | 191 | LOAD_FPS: 192 | if (!options.GetFlag(OptionsFlag::NoFpsMod)) 193 | { 194 | D2DX_LOG("Initializing D2FPS."); 195 | HMODULE fps = LoadLibraryW(L"d2fps.dll"); 196 | if (!fps) { 197 | options.SetFlag(OptionsFlag::NoFpsMod, true); 198 | D2DX_LOG("Failed to load d2fps.dll"); 199 | return; 200 | } 201 | 202 | auto init = (void(__stdcall*)())GetProcAddress(fps, "_Init@0"); 203 | if (!init) { 204 | options.SetFlag(OptionsFlag::NoFpsMod, true); 205 | D2DX_LOG("Failed to load d2fps.dll"); 206 | return; 207 | } 208 | init(); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/d2dx/BuiltinMods.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Options.h" 22 | 23 | namespace d2dx 24 | { 25 | class BuiltinMods final 26 | { 27 | public: 28 | void Init( 29 | _In_opt_ HMODULE hModule, 30 | _In_ Size gameSize, 31 | _In_ Options& options); 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/d2dx/CompatModeCheck.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "CompatModeCheck.h" 21 | #include "Utils.h" 22 | 23 | using namespace d2dx; 24 | 25 | static const wchar_t* CompatModeStrings[] = 26 | { 27 | L"WIN8RTM", 28 | L"WIN7RTM", 29 | L"VISTASP2", 30 | L"VISTASP1", 31 | L"VISTARTM", 32 | L"WINXPSP3", 33 | L"WINXPSP2", 34 | L"WIN98", 35 | L"WIN95", 36 | }; 37 | 38 | CompatModeState CheckCompatModeReg( 39 | _In_ HKEY hRootKey, 40 | _In_ const wchar_t* path, 41 | _In_ bool remove) 42 | { 43 | HKEY hKey; 44 | LSTATUS result = RegOpenKeyExW( 45 | hRootKey, 46 | L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 47 | 0, 48 | KEY_QUERY_VALUE | KEY_WOW64_64KEY | (remove ? KEY_SET_VALUE : 0), 49 | &hKey); 50 | if (result != ERROR_SUCCESS) 51 | { 52 | return CompatModeState::Unknown; 53 | } 54 | 55 | std::wstring buf; 56 | DWORD len = MAX_PATH * 2; 57 | do 58 | { 59 | buf.resize(len / 2); 60 | result = RegGetValueW( 61 | hKey, 62 | nullptr, 63 | path, 64 | RRF_RT_REG_SZ, 65 | nullptr, 66 | buf.data(), 67 | &len); 68 | } while (result == ERROR_MORE_DATA); 69 | if (result != ERROR_SUCCESS) 70 | { 71 | RegCloseKey(hKey); 72 | return CompatModeState::Unknown; 73 | } 74 | buf.resize(len / 2); 75 | 76 | CompatModeState ret = CompatModeState::Disabled; 77 | switch (result) 78 | { 79 | case ERROR_SUCCESS: 80 | for (const wchar_t* s : CompatModeStrings) 81 | { 82 | std::size_t pos = buf.find(s); 83 | if (pos != std::wstring::npos) 84 | { 85 | ret = CompatModeState::Enabled; 86 | if (remove) 87 | { 88 | std::size_t len = wcslen(s); 89 | if (pos != 0 && buf[pos - 1] == L' ') 90 | { 91 | --pos; 92 | ++len; 93 | } 94 | else if (pos + len < buf.length() && buf[pos + len] == L' ') 95 | { 96 | ++len; 97 | } 98 | else 99 | { 100 | continue; 101 | } 102 | 103 | if (len + 2 == buf.length() && pos == 1 && buf[0] == L'~') 104 | { 105 | result = RegDeleteValueW(hKey, path); 106 | } 107 | else 108 | { 109 | buf.erase(pos, len); 110 | result = RegSetValueExW( 111 | hKey, 112 | path, 113 | 0, 114 | REG_SZ, 115 | reinterpret_cast(buf.data()), 116 | buf.length() * 2); 117 | } 118 | if (result == ERROR_SUCCESS) 119 | { 120 | ret = CompatModeState::Updated; 121 | } 122 | } 123 | break; 124 | } 125 | } 126 | break; 127 | 128 | case ERROR_FILE_NOT_FOUND: 129 | break; 130 | 131 | default: 132 | ret = CompatModeState::Unknown; 133 | break; 134 | } 135 | 136 | RegCloseKey(hKey); 137 | return ret; 138 | } 139 | 140 | _Use_decl_annotations_ 141 | CompatModeState d2dx::CheckCompatMode(bool remove) 142 | { 143 | auto version = d2dx::GetWindowsVersion(); 144 | auto realVersion = d2dx::GetActualWindowsVersion(); 145 | 146 | if (realVersion.major == version.major && realVersion.minor == version.minor) 147 | { 148 | return CompatModeState::Disabled; 149 | } 150 | if (version.major > 6 || (version.major == 6 && version.minor >= 3)) 151 | { 152 | // Compat mode is set to at least win10. 153 | return CompatModeState::Disabled; 154 | } 155 | 156 | HMODULE module = GetModuleHandleW(nullptr); 157 | std::vector path; 158 | DWORD result = MAX_PATH / 2; 159 | do 160 | { 161 | result *= 2; 162 | path.resize(result); 163 | result = GetModuleFileNameW(module, path.data(), path.size()); 164 | if (result == 0) 165 | { 166 | return CompatModeState::Unknown; 167 | } 168 | } while (result == path.size()); 169 | path.resize(static_cast(result + 1)); 170 | 171 | CompatModeState ustate = CheckCompatModeReg(HKEY_CURRENT_USER, path.data(), remove); 172 | if (ustate == CompatModeState::Enabled || ustate == CompatModeState::Updated) 173 | { 174 | return ustate; 175 | } 176 | 177 | CompatModeState mstate = CheckCompatModeReg(HKEY_LOCAL_MACHINE, path.data(), false); 178 | if (mstate == CompatModeState::Enabled) 179 | { 180 | return mstate; 181 | } 182 | 183 | return realVersion.major == 0 && mstate == CompatModeState::Unknown && ustate == CompatModeState::Unknown 184 | ? CompatModeState::Unknown 185 | : CompatModeState::Enabled; 186 | } 187 | -------------------------------------------------------------------------------- /src/d2dx/CompatModeCheck.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | namespace d2dx 22 | { 23 | enum class CompatModeState { 24 | Enabled, 25 | Updated, 26 | Disabled, 27 | Unknown 28 | }; 29 | 30 | CompatModeState CheckCompatMode(_In_ bool remove); 31 | } 32 | -------------------------------------------------------------------------------- /src/d2dx/Constants.hlsli: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | 20 | cbuffer Constants : register(b0) 21 | { 22 | float2 c_screenSize : packoffset(c0); 23 | float2 c_invScreenSize : packoffset(c0.z); 24 | uint2 c_flagsx : packoffset(c1); 25 | float c_sharpness : packoffset(c1.z); 26 | uint c_padding : packoffset(c1.w); 27 | }; 28 | 29 | SamplerState PointSampler : register(s0); 30 | SamplerState BilinearSampler : register(s1); 31 | 32 | #define FLAGS_CHROMAKEY_ENABLED_MASK 1 33 | -------------------------------------------------------------------------------- /src/d2dx/D2DXConfigurator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "D2DXContextFactory.h" 21 | #include "D2DXConfigurator.h" 22 | 23 | using namespace d2dx; 24 | using namespace std; 25 | using namespace Microsoft::WRL; 26 | 27 | class D2DXConfigurator : public ID2DXConfigurator 28 | { 29 | public: 30 | D2DXConfigurator() noexcept 31 | { 32 | } 33 | 34 | virtual ~D2DXConfigurator() noexcept 35 | { 36 | } 37 | 38 | STDMETHOD(QueryInterface)( 39 | /* [in] */ REFIID riid, 40 | /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) 41 | { 42 | if (IsEqualIID(riid, __uuidof(IUnknown)) || 43 | IsEqualIID(riid, __uuidof(ID2DXConfigurator))) 44 | { 45 | *ppvObject = this; 46 | return S_OK; 47 | } 48 | else 49 | { 50 | *ppvObject = nullptr; 51 | return E_NOINTERFACE; 52 | } 53 | } 54 | 55 | STDMETHOD_(ULONG, AddRef)(void) 56 | { 57 | /* We just pretend to be refcounted. */ 58 | return 1U; 59 | } 60 | 61 | STDMETHOD_(ULONG, Release)(void) 62 | { 63 | /* We just pretend to be refcounted. */ 64 | return 1U; 65 | } 66 | 67 | STDMETHOD(SetCustomResolution)( 68 | int32_t width, 69 | int32_t height) noexcept 70 | { 71 | auto d2dxContext = D2DXContextFactory::GetInstance(false); 72 | 73 | if (!d2dxContext) 74 | { 75 | return E_POINTER; 76 | } 77 | 78 | d2dxContext->SetCustomResolution({ width, height }); 79 | 80 | return S_OK; 81 | } 82 | 83 | STDMETHOD(GetSuggestedCustomResolution)( 84 | _Out_ int32_t* width, 85 | _Out_ int32_t* height) noexcept 86 | { 87 | if (!width || !height) 88 | { 89 | return E_INVALIDARG; 90 | } 91 | 92 | auto d2dxContext = D2DXContextFactory::GetInstance(false); 93 | 94 | if (!d2dxContext) 95 | { 96 | return E_POINTER; 97 | } 98 | 99 | Size size = d2dxContext->GetSuggestedCustomResolution(); 100 | *width = size.width; 101 | *height = size.height; 102 | 103 | return S_OK; 104 | } 105 | }; 106 | 107 | namespace d2dx 108 | { 109 | ID2DXConfigurator* GetConfiguratorInternal() 110 | { 111 | static D2DXConfigurator configurator; 112 | return &configurator; 113 | } 114 | } 115 | 116 | extern "C" 117 | { 118 | D2DX_EXPORTED ID2DXConfigurator* __stdcall D2DXGetConfigurator() 119 | { 120 | auto d2dxInstance = D2DXContextFactory::GetInstance(false); 121 | 122 | if (!d2dxInstance) 123 | { 124 | return nullptr; 125 | } 126 | 127 | d2dxInstance->DisableBuiltinResMod(); 128 | 129 | return GetConfiguratorInternal(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/d2dx/D2DXConfigurator.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | #include 21 | #include 22 | 23 | #ifdef D2DX_EXPORT 24 | #define D2DX_EXPORTED __declspec(dllexport) 25 | #else 26 | #define D2DX_EXPORTED 27 | #endif 28 | 29 | /* 30 | ID2DXConfigurator is a pseudo-COM interface that can be used to integrate with D2DX. 31 | It is suitable e.g. for "high-res" mods that want to use arbitrary resolutions. 32 | 33 | It can be accessed via the helper d2dx::TryGetConfigurator, or manually by 34 | using LoadLibrary/GetProcAddress to get a pointer to _D2DXGetConfigurator@4. 35 | 36 | Note that the object is not really refcounted and there's no need to call AddRef/Release. 37 | 38 | Note also that the built-in resolution mod in D2DX will be disabled if D2DXGetConfigurator 39 | is called prior to the first Glide call made. 40 | 41 | Example use: 42 | 43 | ID2DXConfigurator* d2dxConfigurator = d2dx::TryGetConfigurator(); 44 | if (d2dxConfigurator) 45 | { 46 | d2dxConfigurator->SetCustomResolution(1000, 500); 47 | } 48 | grSstWinOpen(hWnd, ...) 49 | 50 | */ 51 | MIDL_INTERFACE("B11C5FA4-983F-4E34-9E43-BD82F9CCDB65") 52 | ID2DXConfigurator : public IUnknown 53 | { 54 | public: 55 | /* 56 | Tell D2DX that the following call(s) to grSstWinOpen intends this custom resolution, 57 | and to ignore the 'screen_resolution' argument. To return to normal behavior, call 58 | this method with a width and height of zero. 59 | 60 | Returns S_OK on success and an HRESULT error code otherwise. 61 | */ 62 | virtual HRESULT STDMETHODCALLTYPE SetCustomResolution( 63 | int width, 64 | int height) = 0; 65 | 66 | /* 67 | Get a suggested custom resolution from D2DX (typically close to 640x480 or 800x600, 68 | but in the aspect ratio of the monitor). 69 | 70 | This method allows matching D2DX's default behavior. 71 | 72 | Returns S_OK on success and an HRESULT error code otherwise. 73 | */ 74 | virtual HRESULT STDMETHODCALLTYPE GetSuggestedCustomResolution( 75 | /* [out] */ int* width, 76 | /* [out] */ int* height) = 0; 77 | }; 78 | 79 | extern "C" 80 | { 81 | D2DX_EXPORTED ID2DXConfigurator* __stdcall D2DXGetConfigurator(); 82 | } 83 | 84 | #if __cplusplus > 199711L 85 | namespace d2dx 86 | { 87 | namespace detail 88 | { 89 | class D2DXGetConfiguratorFuncLoader final 90 | { 91 | public: 92 | D2DXGetConfiguratorFuncLoader() : _d2dxGetConfiguratorFunc{ nullptr } 93 | { 94 | HINSTANCE hD2DX = LoadLibraryA("glide3x.dll"); 95 | if (hD2DX) 96 | { 97 | _d2dxGetConfiguratorFunc = (D2DXGetConfiguratorFunc)GetProcAddress( 98 | hD2DX, "_D2DXGetConfigurator@4"); 99 | } 100 | } 101 | ID2DXConfigurator* operator()() 102 | { 103 | return _d2dxGetConfiguratorFunc ? _d2dxGetConfiguratorFunc() : nullptr; 104 | } 105 | private: 106 | typedef ID2DXConfigurator* (__stdcall *D2DXGetConfiguratorFunc)(); 107 | D2DXGetConfiguratorFunc _d2dxGetConfiguratorFunc; 108 | }; 109 | } 110 | static ID2DXConfigurator* TryGetConfigurator() 111 | { 112 | static detail::D2DXGetConfiguratorFuncLoader d2dxGetConfiguratorFuncLoader; 113 | return d2dxGetConfiguratorFuncLoader(); 114 | } 115 | } 116 | #endif 117 | -------------------------------------------------------------------------------- /src/d2dx/D2DXContextFactory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "D2DXContextFactory.h" 21 | #include "GameHelper.h" 22 | #include "D2DXContext.h" 23 | 24 | using namespace d2dx; 25 | 26 | static bool destroyed = false; 27 | static std::shared_ptr instance; 28 | 29 | ID2DXContext* D2DXContextFactory::GetInstance( 30 | bool createIfNeeded) 31 | { 32 | /* The game is single threaded and there's no worry about synchronization. */ 33 | 34 | if (!instance && !destroyed && createIfNeeded) 35 | { 36 | instance = std::make_shared(); 37 | } 38 | 39 | return instance.get(); 40 | } 41 | 42 | void D2DXContextFactory::DestroyInstance() 43 | { 44 | instance = nullptr; 45 | destroyed = true; 46 | } 47 | -------------------------------------------------------------------------------- /src/d2dx/D2DXContextFactory.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "ID2DXContext.h" 22 | 23 | namespace d2dx 24 | { 25 | class D2DXContextFactory 26 | { 27 | public: 28 | static ID2DXContext* GetInstance(bool createIfNeeded = true); 29 | static void DestroyInstance(); 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/d2dx/D2Types.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | namespace d2dx 22 | { 23 | namespace D2 24 | { 25 | struct Vertex 26 | { 27 | float x, y; 28 | uint32_t color; 29 | uint32_t padding; 30 | float s, t; 31 | uint32_t padding2; 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/d2dx/Detours.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | namespace d2dx 22 | { 23 | class GameHelper; 24 | struct ID2DXContext; 25 | 26 | void AttachDetours( 27 | _In_ GameHelper& gameHelper, 28 | _In_ ID2DXContext& d2dxContext); 29 | 30 | void DetachDetours( 31 | _In_ GameHelper& gameHelper, 32 | _In_ ID2DXContext& d2dxContext); 33 | } 34 | -------------------------------------------------------------------------------- /src/d2dx/Display.hlsli: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | 20 | struct DisplayVSInput 21 | { 22 | float2 pos : POSITION; 23 | int2 st : TEXCOORD0; 24 | float4 color : COLOR; 25 | uint2 misc : TEXCOORD1; 26 | }; 27 | 28 | struct DisplayVSOutput 29 | { 30 | noperspective float2 tc : TEXCOORD0; 31 | nointerpolation float4 textureSize_invTextureSize : TEXCOORD1; 32 | }; 33 | 34 | typedef DisplayVSOutput DisplayPSInput; 35 | -------------------------------------------------------------------------------- /src/d2dx/DisplayBilinearScalePS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D sceneTexture : register(t0); 23 | 24 | float4 main( 25 | in DisplayPSInput ps_in) : SV_TARGET 26 | { 27 | return sceneTexture.Sample(BilinearSampler, ps_in.tc); 28 | } 29 | -------------------------------------------------------------------------------- /src/d2dx/DisplayCatmullRomScalePS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D sceneTexture : register(t0); 23 | 24 | // This filtering code under MIT license, taken from: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1 25 | 26 | // Samples a texture with Catmull-Rom filtering, using 9 texture fetches instead of 16. 27 | // See http://vec3.ca/bicubic-filtering-in-fewer-taps/ for more details 28 | float4 SampleTextureCatmullRom(in Texture2D tex, in SamplerState linearSampler, in float2 uv, in float4 texSize_invTexSize) 29 | { 30 | // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding 31 | // down the sample location to get the exact center of our "starting" texel. The starting texel will be at 32 | // location [1, 1] in the grid, where [0, 0] is the top left corner. 33 | float2 samplePos = uv * texSize_invTexSize.xy; 34 | float2 texPos1 = floor(samplePos - 0.5f) + 0.5f; 35 | 36 | // Compute the fractional offset from our starting texel to our original sample location, which we'll 37 | // feed into the Catmull-Rom spline function to get our filter weights. 38 | float2 f = samplePos - texPos1; 39 | 40 | // Compute the Catmull-Rom weights using the fractional offset that we calculated earlier. 41 | // These equations are pre-expanded based on our knowledge of where the texels will be located, 42 | // which lets us avoid having to evaluate a piece-wise function. 43 | float2 w0 = f * (-0.5f + f * (1.0f - 0.5f * f)); 44 | float2 w1 = 1.0f + f * f * (-2.5f + 1.5f * f); 45 | float2 w2 = f * (0.5f + f * (2.0f - 1.5f * f)); 46 | float2 w3 = f * f * (-0.5f + 0.5f * f); 47 | 48 | // Work out weighting factors and sampling offsets that will let us use bilinear filtering to 49 | // simultaneously evaluate the middle 2 samples from the 4x4 grid. 50 | float2 w12 = w1 + w2; 51 | float2 offset12 = w2 / (w1 + w2); 52 | 53 | // Compute the final UV coordinates we'll use for sampling the texture 54 | float2 texPos0 = texPos1 - 1; 55 | float2 texPos3 = texPos1 + 2; 56 | float2 texPos12 = texPos1 + offset12; 57 | 58 | texPos0 *= texSize_invTexSize.zw; 59 | texPos3 *= texSize_invTexSize.zw; 60 | texPos12 *= texSize_invTexSize.zw; 61 | 62 | float3 result = 63 | (tex.SampleLevel(linearSampler, float2(texPos0.x, texPos0.y), 0.0f).rgb * w0.x + 64 | tex.SampleLevel(linearSampler, float2(texPos12.x, texPos0.y), 0.0f).rgb * w12.x + 65 | tex.SampleLevel(linearSampler, float2(texPos3.x, texPos0.y), 0.0f).rgb * w3.x) * w0.y; 66 | 67 | result += 68 | (tex.SampleLevel(linearSampler, float2(texPos0.x, texPos12.y), 0.0f).rgb * w0.x + 69 | tex.SampleLevel(linearSampler, float2(texPos12.x, texPos12.y), 0.0f).rgb * w12.x + 70 | tex.SampleLevel(linearSampler, float2(texPos3.x, texPos12.y), 0.0f).rgb * w3.x) * w12.y; 71 | 72 | result += 73 | (tex.SampleLevel(linearSampler, float2(texPos0.x, texPos3.y), 0.0f).rgb * w0.x + 74 | tex.SampleLevel(linearSampler, float2(texPos12.x, texPos3.y), 0.0f).rgb * w12.x + 75 | tex.SampleLevel(linearSampler, float2(texPos3.x, texPos3.y), 0.0f).rgb * w3.x) * w3.y; 76 | 77 | return float4(result, 1); 78 | } 79 | 80 | float4 main( 81 | in DisplayPSInput ps_in) : SV_TARGET 82 | { 83 | return SampleTextureCatmullRom(sceneTexture, BilinearSampler, ps_in.tc, ps_in.textureSize_invTextureSize); 84 | } 85 | -------------------------------------------------------------------------------- /src/d2dx/DisplayIntegerScalePS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D sceneTexture : register(t0); 23 | 24 | float4 main( 25 | in DisplayPSInput ps_in) : SV_TARGET 26 | { 27 | return sceneTexture.SampleLevel(PointSampler, ps_in.tc, 0); 28 | } 29 | -------------------------------------------------------------------------------- /src/d2dx/DisplayNearestScalePS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D sceneTexture : register(t0); 23 | 24 | float4 main( 25 | in DisplayPSInput ps_in) : SV_TARGET 26 | { 27 | return sceneTexture.Sample(PointSampler, ps_in.tc); 28 | } 29 | -------------------------------------------------------------------------------- /src/d2dx/DisplayNonintegerScalePS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D sceneTexture : register(t0); 23 | 24 | /* Anti-aliased nearest-neighbor sampling, taken from https://www.shadertoy.com/view/WtjyWy by user Amarcoli. */ 25 | float2 nearestSampleUV_AA(float2 uv, float sharpness, float4 textureSize_invTextureSize) { 26 | float2 tileUv = uv * textureSize_invTextureSize.xy; 27 | float2 dxdy = float2(ddx(tileUv.x), ddy(tileUv.y)); 28 | 29 | float2 texelDelta = frac(tileUv) - 0.5; 30 | float2 distFromEdge = 0.5 - abs(texelDelta); 31 | float2 aa_factor = saturate(distFromEdge * sharpness / dxdy); 32 | 33 | return uv - texelDelta * aa_factor * textureSize_invTextureSize.zw; 34 | } 35 | 36 | float4 main( 37 | in DisplayPSInput ps_in) : SV_TARGET 38 | { 39 | return sceneTexture.Sample(BilinearSampler, nearestSampleUV_AA(ps_in.tc, 2.0, ps_in.textureSize_invTextureSize)); 40 | } 41 | -------------------------------------------------------------------------------- /src/d2dx/DisplayVS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | void main( 23 | in DisplayVSInput vs_in, 24 | uint vs_in_vertexId : SV_VertexID, 25 | out DisplayVSOutput vs_out, 26 | out noperspective float4 vs_out_pos : SV_POSITION) 27 | { 28 | float2 fpos = float2(vs_in.pos) * c_invScreenSize - 0.5; 29 | vs_out_pos = fpos.xyxx * float4(2, -2, 0, 0) + float4(0,0,0,1); 30 | 31 | float2 stf = vs_in.st; 32 | vs_out.textureSize_invTextureSize = float4(stf, 1/stf); 33 | 34 | const float srcWidth = vs_in.misc.y & 16383; 35 | const float srcHeight = vs_in.misc.x & 4095; 36 | 37 | switch (vs_in_vertexId) 38 | { 39 | default: 40 | case 0: 41 | vs_out.tc = float2(0, 0); 42 | break; 43 | case 1: 44 | vs_out.tc = float2(srcWidth * 2 * vs_out.textureSize_invTextureSize.z, 0); 45 | break; 46 | case 2: 47 | vs_out.tc = float2(0, srcHeight * 2 * vs_out.textureSize_invTextureSize.w); 48 | break; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/d2dx/ErrorHandling.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | namespace d2dx 22 | { 23 | namespace detail 24 | { 25 | __declspec(noinline) void ThrowFromHRESULT(HRESULT hr, _In_z_ const char* func, int32_t line); 26 | __declspec(noinline) char* GetMessageForHRESULT(HRESULT hr, _In_z_ const char* func, int32_t line) noexcept; 27 | [[noreturn]] __declspec(noinline) void FatalException() noexcept; 28 | [[noreturn]] __declspec(noinline) void FatalError(_In_z_ const char* msg) noexcept; 29 | } 30 | 31 | struct ComException final : public std::runtime_error 32 | { 33 | ComException(HRESULT hr_, const char* func_, int32_t line_) : 34 | std::runtime_error(detail::GetMessageForHRESULT(hr_, func_, line_)), 35 | hr{ hr_ }, 36 | func{ func_ }, 37 | line{ line_ } 38 | { 39 | } 40 | 41 | HRESULT hr; 42 | const char* func; 43 | int32_t line; 44 | }; 45 | 46 | #define D2DX_THROW_HR(hr) detail::ThrowFromHRESULT(hr, __FUNCTION__, __LINE__) 47 | #define D2DX_CHECK_HR(expr) { HRESULT hr = (expr); if (FAILED(hr)) { detail::ThrowFromHRESULT((hr), __FUNCTION__, __LINE__); } } 48 | #define D2DX_FATAL_EXCEPTION detail::FatalException() 49 | #define D2DX_FATAL_ERROR(msg) detail::FatalError(msg) 50 | } 51 | -------------------------------------------------------------------------------- /src/d2dx/Game.hlsli: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | 20 | struct GameVSInput 21 | { 22 | float2 pos : POSITION; 23 | int2 texCoord : TEXCOORD0; 24 | float4 color : COLOR0; 25 | uint2 misc : TEXCOORD1; 26 | }; 27 | 28 | struct GameVSOutput 29 | { 30 | noperspective float4 pos : SV_POSITION; 31 | noperspective float2 tc : TEXCOORD0; 32 | noperspective float4 color : COLOR0; 33 | nointerpolation uint4 atlasIndex_paletteIndex_surfaceId_flags : TEXCOORD1; 34 | }; 35 | 36 | typedef GameVSOutput GamePSInput; 37 | 38 | struct GamePSOutput 39 | { 40 | float4 color : SV_TARGET0; 41 | float surfaceId : SV_TARGET1; 42 | }; 43 | -------------------------------------------------------------------------------- /src/d2dx/GameBilinearPS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Game.hlsli" 21 | 22 | Texture2DArray tex : register(t0); 23 | Texture1DArray palette : register(t1); 24 | 25 | void main( 26 | in GamePSInput ps_in, 27 | out GamePSOutput ps_out) 28 | { 29 | const uint atlasIndex = ps_in.atlasIndex_paletteIndex_surfaceId_flags.x; 30 | const bool chromaKeyEnabled = ps_in.atlasIndex_paletteIndex_surfaceId_flags.w & 1; 31 | const uint surfaceId = ps_in.atlasIndex_paletteIndex_surfaceId_flags.z; 32 | const uint paletteIndex = ps_in.atlasIndex_paletteIndex_surfaceId_flags.y; 33 | 34 | if (chromaKeyEnabled && tex.Load(int4(ps_in.tc, atlasIndex, 0)) == 0) 35 | discard; 36 | 37 | const float2 tc = ps_in.tc - 0.5; 38 | const int2 ulTc = int2(tc); 39 | const int2 lrTc = ulTc + 1; 40 | const uint i1 = tex.Load(int4(ulTc, atlasIndex, 0)); 41 | const uint i2 = tex.Load(int4(lrTc.x, ulTc.y, atlasIndex, 0)); 42 | const uint i3 = tex.Load(int4(ulTc.x, lrTc.y, atlasIndex, 0)); 43 | const uint i4 = tex.Load(int4(lrTc, atlasIndex, 0)); 44 | const float4 c1 = palette.Load(int3(i1, paletteIndex, 0)); 45 | const float4 c2 = palette.Load(int3(i2, paletteIndex, 0)); 46 | const float4 c3 = palette.Load(int3(i3, paletteIndex, 0)); 47 | const float4 c4 = palette.Load(int3(i4, paletteIndex, 0)); 48 | 49 | const float2 blend = saturate((tc - float2(ulTc)) * c_sharpness - ((c_sharpness - 1.0) * 0.5)); 50 | 51 | const float4 c12 = chromaKeyEnabled && (i1 == 0 || i2 == 0) 52 | ? (i1 == 0 ? c2 : c1) 53 | : lerp(c1, c2, blend.xxxx); 54 | 55 | const float4 c34 = chromaKeyEnabled && (i3 == 0 || i4 == 0) 56 | ? (i3 == 0 ? c4 : c3) 57 | : lerp(c3, c4, blend.xxxx); 58 | 59 | const bool c12Discard = i1 == 0 && i2 == 0; 60 | const bool c34Discard = i3 == 0 && i4 == 0; 61 | const float4 c = chromaKeyEnabled && (c12Discard || c34Discard) 62 | ? (c12Discard ? c34 : c12) 63 | : lerp(c12, c34, blend.yyyy); 64 | 65 | ps_out.color = ps_in.color * c; 66 | ps_out.surfaceId = surfaceId * 1.0 / 16383.0; 67 | } -------------------------------------------------------------------------------- /src/d2dx/GameHelper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "GameHelper.h" 21 | #include "Buffer.h" 22 | #include "Utils.h" 23 | 24 | using namespace d2dx; 25 | 26 | 27 | GameVersion GetGameVersion() 28 | { 29 | GameVersion version = GameVersion::Unsupported; 30 | 31 | auto versionSize = GetFileVersionInfoSizeA("game.exe", nullptr); 32 | Buffer verData(versionSize); 33 | 34 | if (!GetFileVersionInfoA("game.exe", NULL, verData.capacity, verData.items)) 35 | { 36 | D2DX_LOG("Failed to get file version for game.exe."); 37 | return GameVersion::Unsupported; 38 | } 39 | 40 | uint32_t size = 0; 41 | const uint8_t* lpBuffer = nullptr; 42 | bool success = VerQueryValueA(verData.items, "\\", (VOID FAR * FAR*) & lpBuffer, &size); 43 | 44 | if (!(success && size > 0)) 45 | { 46 | D2DX_LOG("Failed to query version info for game.exe."); 47 | return GameVersion::Unsupported; 48 | } 49 | 50 | VS_FIXEDFILEINFO* vsFixedFileInfo = (VS_FIXEDFILEINFO*)lpBuffer; 51 | if (vsFixedFileInfo->dwSignature != 0xfeef04bd) 52 | { 53 | D2DX_LOG("Unexpected signature in version info for game.exe."); 54 | return GameVersion::Unsupported; 55 | } 56 | 57 | const int32_t a = vsFixedFileInfo->dwFileVersionMS >> 16; 58 | const int32_t b = vsFixedFileInfo->dwFileVersionMS & 0xffff; 59 | const int32_t c = vsFixedFileInfo->dwFileVersionLS >> 16; 60 | const int32_t d = vsFixedFileInfo->dwFileVersionLS & 0xffff; 61 | 62 | if (a == 1 && b == 0 && c == 7 && d == 0) 63 | { 64 | version = GameVersion::Lod107; 65 | } 66 | else if (a == 1 && b == 0 && c == 8 && d == 28) 67 | { 68 | version = GameVersion::Lod108; 69 | } 70 | else if (a == 1 && b == 0 && c == 9 && d == 19) 71 | { 72 | version = GameVersion::Lod109; 73 | } 74 | else if (a == 1 && b == 0 && c == 9 && d == 20) 75 | { 76 | version = GameVersion::Lod109b; 77 | } 78 | else if (a == 1 && b == 0 && c == 9 && d == 22) 79 | { 80 | version = GameVersion::Lod109d; 81 | } 82 | else if (a == 1 && b == 0 && c == 10 && d == 39) 83 | { 84 | version = GameVersion::Lod110f; 85 | } 86 | else if (a == 1 && b == 0 && c == 11 && d == 45) 87 | { 88 | version = GameVersion::Lod111; 89 | } 90 | else if (a == 1 && b == 0 && c == 11 && d == 46) 91 | { 92 | version = GameVersion::Lod111b; 93 | } 94 | else if (a == 1 && b == 0 && c == 12 && d == 49) 95 | { 96 | version = GameVersion::Lod112; 97 | } 98 | else if (a == 1 && b == 0 && c == 13 && d == 60) 99 | { 100 | version = GameVersion::Lod113c; 101 | } 102 | else if (a == 1 && b == 0 && c == 13 && d == 64) 103 | { 104 | version = GameVersion::Lod113d; 105 | } 106 | else if (a == 1 && b == 14 && c == 0 && d == 64) 107 | { 108 | D2DX_FATAL_ERROR("This version (1.14a) of Diablo II will not work with D2DX. Please upgrade to version 1.14d."); 109 | } 110 | else if (a == 1 && b == 14 && c == 1 && d == 68) 111 | { 112 | D2DX_FATAL_ERROR("This version (1.14b) of Diablo II will not work with D2DX. Please upgrade to version 1.14d."); 113 | } 114 | else if (a == 1 && b == 14 && c == 2 && d == 70) 115 | { 116 | version = GameVersion::Lod114c; 117 | } 118 | else if (a == 1 && b == 14 && c == 3 && d == 71) 119 | { 120 | version = GameVersion::Lod114d; 121 | } 122 | 123 | D2DX_LOG("Game version: %d.%d.%d.%d (%s)\n", a, b, c, d, version == GameVersion::Unsupported ? "unsupported" : "supported"); 124 | 125 | return version; 126 | } 127 | 128 | 129 | GameHelper::GameHelper() : 130 | gameVersion(GetGameVersion()), 131 | process(GetCurrentProcess()), 132 | gameExe(GetModuleHandleA("game.exe")), 133 | d2ClientDll(LoadLibraryA("D2Client.dll")), 134 | d2CommonDll(LoadLibraryA("D2Common.dll")), 135 | d2GfxDll(LoadLibraryA("D2Gfx.dll")), 136 | d2WinDll(LoadLibraryA("D2Win.dll")), 137 | isProjectDiablo2(GetModuleHandleA("PD2_EXT.dll") != nullptr) 138 | { 139 | if (isProjectDiablo2) 140 | { 141 | D2DX_LOG("Detected Project Diablo 2."); 142 | } 143 | } 144 | 145 | _Use_decl_annotations_ 146 | const char* GameHelper::GetVersionString() const 147 | { 148 | switch (gameVersion) 149 | { 150 | case GameVersion::Lod107: 151 | return "Lod107"; 152 | case GameVersion::Lod108: 153 | return "Lod108"; 154 | case GameVersion::Lod109: 155 | return "Lod109"; 156 | case GameVersion::Lod109b: 157 | return "Lod109b"; 158 | case GameVersion::Lod109d: 159 | return "Lod109d"; 160 | case GameVersion::Lod110f: 161 | return "Lod110"; 162 | case GameVersion::Lod111: 163 | return "Lod111"; 164 | case GameVersion::Lod111b: 165 | return "Lod111g"; 166 | case GameVersion::Lod112: 167 | return "Lod112"; 168 | case GameVersion::Lod113c: 169 | return "Lod113c"; 170 | case GameVersion::Lod113d: 171 | return "Lod113d"; 172 | case GameVersion::Lod114c: 173 | return "Lod114c"; 174 | case GameVersion::Lod114d: 175 | return "Lod114d"; 176 | default: 177 | return "Unhandled"; 178 | } 179 | } 180 | 181 | Size GameHelper::GetConfiguredGameSize() const 182 | { 183 | HKEY hKey; 184 | LPCTSTR diablo2Key = TEXT("SOFTWARE\\Blizzard Entertainment\\Diablo II"); 185 | LONG openRes = RegOpenKeyEx(HKEY_CURRENT_USER, diablo2Key, 0, KEY_READ, &hKey); 186 | if (openRes != ERROR_SUCCESS) 187 | { 188 | return { 800, 600 }; 189 | } 190 | 191 | DWORD type = REG_DWORD; 192 | DWORD size = 4; 193 | DWORD value = 0; 194 | auto queryRes = RegQueryValueExA(hKey, "Resolution", NULL, &type, (LPBYTE)&value, &size); 195 | assert(queryRes == ERROR_SUCCESS || queryRes == ERROR_MORE_DATA); 196 | 197 | RegCloseKey(hKey); 198 | 199 | if (value == 0) 200 | { 201 | return { 640, 480 }; 202 | } 203 | else 204 | { 205 | return { 800, 600 }; 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /src/d2dx/GameHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Types.h" 22 | 23 | namespace d2dx 24 | { 25 | class GameHelper final 26 | { 27 | public: 28 | GameHelper(); 29 | 30 | _Ret_z_ const char* GetVersionString() const; 31 | 32 | Size GetConfiguredGameSize() const; 33 | 34 | HANDLE process; 35 | HANDLE gameExe; 36 | HANDLE d2ClientDll; 37 | HANDLE d2CommonDll; 38 | HANDLE d2GfxDll; 39 | HANDLE d2WinDll; 40 | GameVersion gameVersion; 41 | bool isProjectDiablo2; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /src/d2dx/GamePS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Game.hlsli" 21 | 22 | Texture2DArray tex : register(t0); 23 | Texture1DArray palette : register(t1); 24 | 25 | void main( 26 | in GamePSInput ps_in, 27 | out GamePSOutput ps_out) 28 | { 29 | const uint atlasIndex = ps_in.atlasIndex_paletteIndex_surfaceId_flags.x; 30 | const bool chromaKeyEnabled = ps_in.atlasIndex_paletteIndex_surfaceId_flags.w & 1; 31 | const uint surfaceId = ps_in.atlasIndex_paletteIndex_surfaceId_flags.z; 32 | const uint paletteIndex = ps_in.atlasIndex_paletteIndex_surfaceId_flags.y; 33 | 34 | const uint indexedColor = tex.Load(int4(ps_in.tc, atlasIndex, 0)); 35 | 36 | if (chromaKeyEnabled && indexedColor == 0) 37 | discard; 38 | 39 | const float4 textureColor = palette.Load(int3(indexedColor, paletteIndex, 0)); 40 | 41 | ps_out.color = ps_in.color * textureColor; 42 | ps_out.surfaceId = surfaceId * 1.0 / 16383.0; 43 | } 44 | -------------------------------------------------------------------------------- /src/d2dx/GameVS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Game.hlsli" 21 | 22 | void main( 23 | in GameVSInput vs_in, 24 | out GameVSOutput vs_out) 25 | { 26 | float2 unitPos = float2(vs_in.pos) * c_invScreenSize - 0.5; 27 | vs_out.pos = unitPos.xyxx * float4(2, -2, 0, 0) + float4(0, 0, 0, 1); 28 | vs_out.tc = vs_in.texCoord; 29 | vs_out.color = vs_in.color; 30 | vs_out.atlasIndex_paletteIndex_surfaceId_flags.x = vs_in.misc.x & 4095; 31 | vs_out.atlasIndex_paletteIndex_surfaceId_flags.y = (vs_in.misc.x >> 12) | ((vs_in.misc.y & 0x8000) ? 0x10 : 0); 32 | vs_out.atlasIndex_paletteIndex_surfaceId_flags.z = vs_in.misc.y & 16383; 33 | vs_out.atlasIndex_paletteIndex_surfaceId_flags.w = (vs_in.misc.y & 0x4000) ? 1 : 0; 34 | } 35 | -------------------------------------------------------------------------------- /src/d2dx/GammaPS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D sceneTexture : register(t0); 23 | Texture1D gammaTexture : register(t1); 24 | 25 | float4 main( 26 | in DisplayPSInput ps_in) : SV_TARGET 27 | { 28 | float4 c = sceneTexture.SampleLevel(PointSampler, ps_in.tc, 0); 29 | c.r = gammaTexture.SampleLevel(BilinearSampler, c.r, 0).r; 30 | c.g = gammaTexture.SampleLevel(BilinearSampler, c.g, 0).g; 31 | c.b = gammaTexture.SampleLevel(BilinearSampler, c.b, 0).b; 32 | c.a = dot(c.rgb, float3(0.299, 0.587, 0.114)); 33 | return c; 34 | } 35 | -------------------------------------------------------------------------------- /src/d2dx/ID2DXContext.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "IGlide3x.h" 22 | #include "IWin32InterceptionHandler.h" 23 | #include "ID2InterceptionHandler.h" 24 | #include "Options.h" 25 | 26 | namespace d2dx 27 | { 28 | struct ID2DXContext abstract : 29 | public IGlide3x, 30 | public IWin32InterceptionHandler, 31 | public ID2InterceptionHandler 32 | { 33 | virtual ~ID2DXContext() noexcept {} 34 | 35 | virtual void SetCustomResolution( 36 | _In_ Size size) = 0; 37 | 38 | virtual Size GetSuggestedCustomResolution() = 0; 39 | 40 | virtual void DisableBuiltinResMod() = 0; 41 | 42 | virtual const Options& GetOptions() const = 0; 43 | virtual Options& GetOptions() = 0; 44 | 45 | virtual uint32_t GetActiveThreadId() const noexcept = 0; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/d2dx/ID2InterceptionHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Types.h" 22 | #include "D2Types.h" 23 | 24 | namespace d2dx 25 | { 26 | struct ID2InterceptionHandler abstract 27 | { 28 | virtual ~ID2InterceptionHandler() noexcept {} 29 | 30 | virtual void InterceptDrawText( 31 | _Inout_z_ wchar_t* str) = 0; 32 | 33 | virtual uint16_t SetSurface( 34 | _In_ uint16_t surface) = 0; 35 | virtual uint16_t SetNewSurface() = 0; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /src/d2dx/IGlide3x.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Types.h" 22 | 23 | namespace d2dx 24 | { 25 | struct IGlide3x abstract 26 | { 27 | virtual ~IGlide3x() noexcept {} 28 | 29 | virtual const char* OnGetString( 30 | _In_ uint32_t pname) = 0; 31 | 32 | virtual uint32_t OnGet( 33 | _In_ uint32_t pname, 34 | _In_ uint32_t plength, 35 | _Out_writes_(plength) int32_t* params) = 0; 36 | 37 | virtual void OnSstWinOpen( 38 | _In_ uint32_t hWnd, 39 | _In_ int32_t width, 40 | _In_ int32_t height) = 0; 41 | 42 | virtual void OnVertexLayout( 43 | _In_ uint32_t param, 44 | _In_ int32_t offset) = 0; 45 | 46 | virtual void OnTexDownload( 47 | _In_ uint32_t tmu, 48 | _In_reads_(width* height) const uint8_t* sourceAddress, 49 | _In_ uint32_t startAddress, 50 | _In_ int32_t width, 51 | _In_ int32_t height) = 0; 52 | 53 | virtual void OnTexSource( 54 | _In_ uint32_t tmu, 55 | _In_ uint32_t startAddress, 56 | _In_ int32_t width, 57 | _In_ int32_t height, 58 | _In_ uint32_t largeLog2, 59 | _In_ uint32_t ratioLog2) = 0; 60 | 61 | virtual void OnConstantColorValue( 62 | _In_ uint32_t color) = 0; 63 | 64 | virtual void OnAlphaBlendFunction( 65 | _In_ GrAlphaBlendFnc_t rgb_sf, 66 | _In_ GrAlphaBlendFnc_t rgb_df, 67 | _In_ GrAlphaBlendFnc_t alpha_sf, 68 | _In_ GrAlphaBlendFnc_t alpha_df) = 0; 69 | 70 | virtual void OnColorCombine( 71 | _In_ GrCombineFunction_t function, 72 | _In_ GrCombineFactor_t factor, 73 | _In_ GrCombineLocal_t local, 74 | _In_ GrCombineOther_t other, 75 | _In_ bool invert) = 0; 76 | 77 | virtual void OnAlphaCombine( 78 | _In_ GrCombineFunction_t function, 79 | _In_ GrCombineFactor_t factor, 80 | _In_ GrCombineLocal_t local, 81 | _In_ GrCombineOther_t other, 82 | _In_ bool invert) = 0; 83 | 84 | virtual void OnDrawPoint( 85 | _In_ const void* pt, 86 | _In_ uint32_t gameContext) = 0; 87 | 88 | virtual void OnDrawLine( 89 | _In_ const void* v1, 90 | _In_ const void* v2, 91 | _In_ uint32_t gameContext) = 0; 92 | 93 | virtual void OnDrawVertexArray( 94 | _In_ uint32_t mode, 95 | _In_ uint32_t count, 96 | _In_reads_(count) uint8_t** pointers, 97 | _In_ uint32_t gameContext) = 0; 98 | 99 | virtual void OnDrawVertexArrayContiguous( 100 | _In_ uint32_t mode, 101 | _In_ uint32_t count, 102 | _In_reads_(count* stride) uint8_t* vertex, 103 | _In_ uint32_t stride, 104 | _In_ uint32_t gameContext) = 0; 105 | 106 | virtual void OnTexDownloadTable( 107 | _In_ GrTexTable_t type, 108 | _In_reads_bytes_(256 * 4) void* data) = 0; 109 | 110 | virtual void OnLoadGammaTable( 111 | _In_ uint32_t nentries, 112 | _In_reads_(nentries) uint32_t* red, 113 | _In_reads_(nentries) uint32_t* green, 114 | _In_reads_(nentries) uint32_t* blue) = 0; 115 | 116 | virtual void OnChromakeyMode( 117 | _In_ GrChromakeyMode_t mode) = 0; 118 | 119 | virtual void OnLfbUnlock( 120 | _In_reads_bytes_(640 * 480 * 4) const uint8_t* lfbPtr, 121 | _In_ bool is16Bit) = 0; 122 | 123 | virtual void OnGammaCorrectionRGB( 124 | _In_ float red, 125 | _In_ float green, 126 | _In_ float blue) = 0; 127 | 128 | virtual void OnBufferSwap() = 0; 129 | 130 | virtual void OnTexFilterMode( 131 | _In_ GrChipID_t tmu, 132 | _In_ GrTextureFilterMode_t filterMode) = 0; 133 | }; 134 | } 135 | -------------------------------------------------------------------------------- /src/d2dx/IRenderContext.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "ITextureCache.h" 22 | #include "Types.h" 23 | #include "Options.h" 24 | 25 | namespace d2dx 26 | { 27 | class Vertex; 28 | class Batch; 29 | 30 | struct IRenderContext abstract 31 | { 32 | virtual ~IRenderContext() noexcept {} 33 | 34 | virtual HWND GetHWnd() const = 0; 35 | 36 | virtual void LoadGammaTable( 37 | _In_reads_(valueCount) const uint32_t* values, 38 | _In_ uint32_t valueCount) = 0; 39 | 40 | virtual uint32_t BulkWriteVertices( 41 | _In_reads_(vertexCount) const Vertex* vertices, 42 | _In_ uint32_t vertexCount) = 0; 43 | 44 | virtual TextureCacheLocation UpdateTexture( 45 | _In_ const Batch& batch, 46 | _In_reads_(tmuDataSize) const uint8_t* tmuData, 47 | _In_ uint32_t tmuDataSize) = 0; 48 | 49 | virtual void Draw( 50 | _In_ const Batch& batch, 51 | _In_ uint32_t startVertexLocation) = 0; 52 | 53 | virtual void Present() = 0; 54 | 55 | virtual void WriteToScreen( 56 | _In_reads_(width * height * 2) const uint8_t* pixels, 57 | _In_ int32_t width, 58 | _In_ int32_t height, 59 | _In_ bool is16Bit, 60 | _In_ bool forCinematic) = 0; 61 | 62 | virtual void SetPalette( 63 | _In_ int32_t paletteIndex, 64 | _In_reads_(256) const uint32_t* palette) = 0; 65 | 66 | virtual const Options& GetOptions() const = 0; 67 | 68 | virtual ITextureCache* GetTextureCache( 69 | _In_ const Batch& batch) const = 0; 70 | 71 | virtual void SetSizes( 72 | _In_ Size gameSize, 73 | _In_ Size windowSize, 74 | _In_ ScreenMode screenMode) = 0; 75 | 76 | virtual void GetCurrentMetrics( 77 | _Out_opt_ Size* gameSize, 78 | _Out_opt_ Rect* renderRect) const = 0; 79 | 80 | virtual void ToggleFullscreen() = 0; 81 | 82 | virtual float GetFrameTime() const = 0; 83 | 84 | virtual int32_t GetFrameTimeFp() const = 0; 85 | 86 | virtual ScreenMode GetScreenMode() const = 0; 87 | }; 88 | } 89 | -------------------------------------------------------------------------------- /src/d2dx/ITextureCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Types.h" 22 | 23 | namespace d2dx 24 | { 25 | class Batch; 26 | 27 | struct TextureCacheLocation final 28 | { 29 | int16_t _textureAtlas; 30 | int16_t _textureIndex; 31 | }; 32 | 33 | static_assert(sizeof(TextureCacheLocation) == 4, "sizeof(TextureCacheLocation) == 4"); 34 | 35 | struct ITextureCache abstract 36 | { 37 | virtual ~ITextureCache() noexcept {} 38 | 39 | virtual void OnNewFrame() = 0; 40 | 41 | virtual TextureCacheLocation FindTexture( 42 | _In_ uint64_t contentKey, 43 | _In_ int32_t lastIndex) = 0; 44 | 45 | virtual TextureCacheLocation InsertTexture( 46 | _In_ uint64_t contentKey, 47 | _In_ const Batch& batch, 48 | _In_reads_(tmuDataSize) const uint8_t* tmuData, 49 | _In_ uint32_t tmuDataSize) = 0; 50 | 51 | virtual ID3D11ShaderResourceView* GetSrv( 52 | _In_ uint32_t atlasIndex) const = 0; 53 | 54 | virtual uint32_t GetMemoryFootprint() const = 0; 55 | 56 | virtual uint32_t GetUsedCount() const = 0; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /src/d2dx/IWin32InterceptionHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Types.h" 22 | 23 | namespace d2dx 24 | { 25 | struct IWin32InterceptionHandler abstract 26 | { 27 | virtual ~IWin32InterceptionHandler() noexcept {} 28 | 29 | virtual Offset OnSetCursorPos( 30 | _In_ Offset pos) = 0; 31 | 32 | virtual Offset OnMouseMoveMessage( 33 | _In_ Offset pos) = 0; 34 | 35 | virtual bool IsD2ClientModule( 36 | _In_ HMODULE module) = 0; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /src/d2dx/Metrics.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Metrics.h" 3 | 4 | using namespace d2dx; 5 | using namespace DirectX; 6 | 7 | struct MetricsTableEntry final 8 | { 9 | Size desktopSize; 10 | Size gameSize; 11 | Size gameSizeWide; 12 | }; 13 | 14 | static const struct MetricsTableEntry metricsTable[] = 15 | { 16 | { 17 | .desktopSize { 1280, 720 }, 18 | .gameSize { 960, 720 }, 19 | .gameSizeWide { 1280, 720 }, 20 | }, 21 | { 22 | .desktopSize { 1360, 768 }, 23 | .gameSize { 1024, 768 }, 24 | .gameSizeWide { 1360, 768 }, 25 | }, 26 | { 27 | .desktopSize { 1366, 768 }, 28 | .gameSize { 1024, 768 }, 29 | .gameSizeWide { 1366, 768 }, 30 | }, 31 | { 32 | .desktopSize { 1280, 800 }, 33 | .gameSize { 1066, 800 }, 34 | .gameSizeWide { 1280, 800 }, 35 | }, 36 | { 37 | .desktopSize { 1536, 864 }, 38 | .gameSize { 1152, 864 }, 39 | .gameSizeWide { 1536, 864 }, 40 | }, 41 | { 42 | .desktopSize { 1440, 900 }, 43 | .gameSize { 1200, 900 }, 44 | .gameSizeWide { 1440, 900 }, 45 | }, 46 | { 47 | .desktopSize { 1600, 900 }, 48 | .gameSize { 1200, 900 }, 49 | .gameSizeWide { 1600, 900 }, 50 | }, 51 | { 52 | .desktopSize { 1280, 1024 }, 53 | .gameSize { 640, 480 }, 54 | .gameSizeWide { 640, 512 }, 55 | }, 56 | { 57 | .desktopSize { 1400, 1050 }, 58 | .gameSize { 700, 525 }, 59 | .gameSizeWide { 700, 525 }, 60 | }, 61 | { 62 | .desktopSize { 1680, 1050 }, 63 | .gameSize { 700, 525 }, 64 | .gameSizeWide { 840, 525 }, 65 | }, 66 | { 67 | .desktopSize { 1920, 1080 }, 68 | .gameSize { 720, 540 }, 69 | .gameSizeWide { 960, 540 }, 70 | }, 71 | { 72 | .desktopSize { 2560, 1080 }, 73 | .gameSize { 720, 540 }, 74 | .gameSizeWide { 960, 540 }, /* note: doesn't cover entire monitor */ 75 | }, 76 | { 77 | .desktopSize { 2048, 1152 }, 78 | .gameSize { 768, 576 }, 79 | .gameSizeWide { 1024, 576 }, 80 | }, 81 | { 82 | .desktopSize { 1600, 1200 }, 83 | .gameSize { 800, 600 }, 84 | .gameSizeWide { 800, 600 }, 85 | }, 86 | { 87 | .desktopSize { 1920, 1200 }, 88 | .gameSize { 800, 600 }, 89 | .gameSizeWide { 960, 600 }, 90 | }, 91 | { 92 | .desktopSize { 2560, 1440 }, 93 | .gameSize { 960, 720 }, 94 | .gameSizeWide { 1280, 720 }, 95 | }, 96 | { 97 | .desktopSize { 3440, 1440 }, 98 | .gameSize { 960, 720 }, 99 | .gameSizeWide { 1280, 720 }, /* note: doesn't cover entire monitor */ 100 | }, 101 | { 102 | .desktopSize { 2048, 1536 }, 103 | .gameSize { 1024, 768 }, 104 | .gameSizeWide { 1024, 768 }, 105 | }, 106 | { 107 | .desktopSize { 2560, 1600 }, 108 | .gameSize { 710, 532 }, 109 | .gameSizeWide { 852, 532 }, 110 | }, 111 | { 112 | .desktopSize { 2560, 2048 }, 113 | .gameSize { 852, 640 }, 114 | .gameSizeWide { 852, 682 }, 115 | }, 116 | { 117 | .desktopSize { 3200, 2048 }, 118 | .gameSize { 852, 640 }, 119 | .gameSizeWide { 1066, 682 }, 120 | }, 121 | { 122 | .desktopSize { 3840, 2160 }, 123 | .gameSize { 960, 720 }, 124 | .gameSizeWide { 1280, 720 }, 125 | }, 126 | { 127 | .desktopSize { 4096, 2160 }, 128 | .gameSize { 960, 720 }, 129 | .gameSizeWide { 1364, 720 }, 130 | }, 131 | { 132 | .desktopSize { 4320, 2160 }, 133 | .gameSize { 960, 720 }, 134 | .gameSizeWide { 1440, 720 }, 135 | }, 136 | { 137 | .desktopSize { 3200, 2400 }, 138 | .gameSize { 800, 600 }, 139 | .gameSizeWide { 800, 600 }, 140 | }, 141 | { 142 | .desktopSize { 3840, 2400 }, 143 | .gameSize { 800, 600 }, 144 | .gameSizeWide { 960, 600 }, 145 | }, 146 | }; 147 | 148 | _Use_decl_annotations_ 149 | Size d2dx::Metrics::GetSuggestedGameSize( 150 | Size desktopSize, 151 | bool wide) noexcept 152 | { 153 | for (int32_t i = 0; i < ARRAYSIZE(metricsTable); ++i) 154 | { 155 | if (metricsTable[i].desktopSize.width == desktopSize.width && 156 | metricsTable[i].desktopSize.height == desktopSize.height) 157 | { 158 | return wide ? metricsTable[i].gameSizeWide : metricsTable[i].gameSize; 159 | } 160 | } 161 | 162 | Size size = { 0, 0 }; 163 | for (int32_t scaleFactor = 1; scaleFactor <= 8; ++scaleFactor) 164 | { 165 | size.width = desktopSize.width / scaleFactor; 166 | size.height = desktopSize.height / scaleFactor; 167 | if ((desktopSize.height / (scaleFactor + 1)) <= 600) 168 | { 169 | break; 170 | } 171 | } 172 | 173 | if (size.height > 720) 174 | { 175 | const float aspect = (float)desktopSize.width / desktopSize.height; 176 | size.width = (int32_t)(aspect * 720); 177 | size.height = 720; 178 | } 179 | 180 | return size; 181 | } 182 | 183 | _Use_decl_annotations_ 184 | Rect d2dx::Metrics::GetRenderRect( 185 | Size gameSize, 186 | Size desktopSize, 187 | bool keepAspect) noexcept 188 | { 189 | if (!keepAspect) { 190 | return Rect{ 0, 0, desktopSize.width, desktopSize.height }; 191 | } 192 | 193 | int32_t scaleFactor = 1; 194 | 195 | while ( 196 | gameSize.width * (scaleFactor + 1) <= desktopSize.width && 197 | gameSize.height * (scaleFactor + 1) <= desktopSize.height) 198 | { 199 | ++scaleFactor; 200 | } 201 | 202 | Rect rect 203 | { 204 | (desktopSize.width - gameSize.width * scaleFactor) / 2, 205 | (desktopSize.height - gameSize.height * scaleFactor) / 2, 206 | gameSize.width * scaleFactor, 207 | gameSize.height * scaleFactor 208 | }; 209 | 210 | /* Allow for a small amount of black margin on all sides. When more than that, 211 | rescale the image with a non-integer factor. */ 212 | if (rect.offset.x < 0 || rect.offset.y < 0 || (rect.offset.x >= 16 && rect.offset.y >= 16)) 213 | { 214 | float scaleFactorF = (float)desktopSize.width / gameSize.width; 215 | int32_t scaledHeight = (int32_t)(gameSize.height * scaleFactorF); 216 | rect.offset.x = 0; 217 | rect.offset.y = (desktopSize.height - scaledHeight) / 2; 218 | rect.size.width = desktopSize.width; 219 | rect.size.height = min(scaledHeight, desktopSize.height); 220 | 221 | if (rect.offset.x < 0 || rect.offset.y < 0) 222 | { 223 | float scaleFactorF = (float)desktopSize.height / gameSize.height; 224 | int32_t scaledWidth = (int32_t)(gameSize.width * scaleFactorF); 225 | rect.offset.x = (desktopSize.width - scaledWidth) / 2; 226 | rect.offset.y = 0; 227 | rect.size.width = min(scaledWidth, desktopSize.width); 228 | rect.size.height = desktopSize.height; 229 | } 230 | } 231 | 232 | assert( 233 | rect.offset.x >= 0 && 234 | rect.offset.y >= 0 && 235 | rect.size.width > 0 && 236 | rect.size.height > 0 && 237 | (rect.offset.x + rect.size.width) <= desktopSize.width && 238 | (rect.offset.y + rect.size.height) <= desktopSize.height); 239 | 240 | return rect; 241 | } 242 | 243 | Buffer d2dx::Metrics::GetStandardDesktopSizes() noexcept 244 | { 245 | Buffer standardDesktopSizes(ARRAYSIZE(metricsTable)); 246 | 247 | for (int32_t i = 0; i < ARRAYSIZE(metricsTable); ++i) 248 | { 249 | standardDesktopSizes.items[i] = metricsTable[i].desktopSize; 250 | } 251 | 252 | return standardDesktopSizes; 253 | } 254 | -------------------------------------------------------------------------------- /src/d2dx/Metrics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Buffer.h" 4 | #include "Types.h" 5 | 6 | namespace d2dx 7 | { 8 | namespace Metrics 9 | { 10 | Size GetSuggestedGameSize( 11 | _In_ Size desktopSize, 12 | _In_ bool wide) noexcept; 13 | 14 | Rect GetRenderRect( 15 | _In_ Size gameSize, 16 | _In_ Size desktopSize, 17 | _In_ bool keepAspect) noexcept; 18 | 19 | Buffer GetStandardDesktopSizes() noexcept; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/d2dx/Options.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Types.h" 22 | 23 | namespace d2dx 24 | { 25 | enum class OptionsFlag 26 | { 27 | NoClipCursor, 28 | NoResMod, 29 | NoFpsMod, 30 | NoWide, 31 | NoLogo, 32 | NoAntiAliasing, 33 | NoCompatModeFix, 34 | NoTitleChange, 35 | NoVSync, 36 | NoKeepAspectRatio, 37 | NoFrameTearing, 38 | 39 | DbgDumpTextures, 40 | 41 | Frameless, 42 | 43 | Count 44 | }; 45 | 46 | enum class UpscaleMethod 47 | { 48 | HighQuality = 0, 49 | Bilinear = 1, 50 | CatmullRom = 2, 51 | Nearest = 3, 52 | Rasterize = 4, 53 | Count = 5 54 | }; 55 | 56 | class Options final 57 | { 58 | public: 59 | Options(); 60 | ~Options() noexcept; 61 | 62 | void ApplyCfg( 63 | _In_z_ const char* cfg); 64 | 65 | void ApplyCommandLine( 66 | _In_z_ const char* cmdLine); 67 | 68 | bool GetFlag( 69 | _In_ OptionsFlag flag) const; 70 | 71 | void SetFlag( 72 | _In_ OptionsFlag flag, 73 | _In_ bool value); 74 | 75 | float GetWindowScale() const; 76 | 77 | void SetWindowScale( 78 | _In_ float zoomLevel); 79 | 80 | Offset GetWindowPosition() const; 81 | 82 | void SetWindowPosition( 83 | _In_ Offset windowPosition); 84 | 85 | Size GetUserSpecifiedGameSize() const; 86 | 87 | void SetUserSpecifiedGameSize( 88 | _In_ Size size); 89 | 90 | UpscaleMethod GetUpscaleMethod() const; 91 | 92 | void SetUpscaleMethod( 93 | _In_ UpscaleMethod upscaleMethod) noexcept; 94 | 95 | float GetBilinearSharpness() const; 96 | 97 | void SetBilinearSharpness( 98 | _In_ float sharpness) noexcept; 99 | 100 | private: 101 | uint32_t _flags = (1 << (uint32_t)OptionsFlag::NoVSync) | (1 << (uint32_t)OptionsFlag::NoFrameTearing); 102 | float _windowScale = 1; 103 | Offset _windowPosition{ -1, -1 }; 104 | Size _userSpecifiedGameSize{ -1, -1 }; 105 | UpscaleMethod _upscaleMethod{ UpscaleMethod::HighQuality }; 106 | float _bilinearSharpness = 2.0; 107 | }; 108 | } -------------------------------------------------------------------------------- /src/d2dx/Profiler.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "Profiler.h" 4 | #include "Utils.h" 5 | #include "D2DXContextFactory.h" 6 | 7 | using namespace d2dx; 8 | using namespace std; 9 | 10 | #ifdef D2DX_PROFILE 11 | static thread_local unsigned int halt_sleep_profile = 0; 12 | static thread_local Timer* currentTimer = nullptr; 13 | 14 | class Profiler { 15 | public: 16 | void AddTime( 17 | _In_ int64_t time, 18 | _In_ ProfCategory category, 19 | _In_ bool fullEvent) noexcept 20 | { 21 | if (category == ProfCategory::Sleep) 22 | { 23 | if (halt_sleep_profile == 0) 24 | { 25 | auto ctxt = D2DXContextFactory::GetInstance(false); 26 | if (ctxt && ctxt->GetActiveThreadId() == GetCurrentThreadId()) 27 | { 28 | _times[static_cast(category)] += time; 29 | _times[static_cast(ProfCategory::Count)] += time; 30 | if (fullEvent) 31 | { 32 | ++_events[static_cast(category)]; 33 | ++_events[static_cast(ProfCategory::Count)]; 34 | } 35 | } 36 | else 37 | { 38 | _atomicTime.fetch_add(time, std::memory_order_relaxed); 39 | if (fullEvent) 40 | { 41 | _atomicEvents.fetch_add(1, std::memory_order_relaxed); 42 | } 43 | } 44 | } 45 | } 46 | else 47 | { 48 | _times[static_cast(category)] += time; 49 | _times[static_cast(ProfCategory::Count)] += time; 50 | if (fullEvent) 51 | { 52 | ++_events[static_cast(category)]; 53 | ++_events[static_cast(ProfCategory::Count)]; 54 | } 55 | } 56 | } 57 | 58 | void WriteProfile() noexcept 59 | { 60 | double frameTime = TimeToMs(TimeStamp() - lastProfileTime); 61 | 62 | double hashSize = static_cast(tex_miss_size); 63 | auto hashUnit = "B"; 64 | if (hashSize >= 1024 * 1024) { 65 | hashSize /= 1024 * 1024; 66 | hashUnit = "MiB"; 67 | } 68 | else if (hashSize >= 1024) { 69 | hashSize /= 1024; 70 | hashUnit = "kiB"; 71 | } 72 | int64_t atomicTime = _atomicTime.load(memory_order_relaxed); 73 | uint32_t atomicEvents = _atomicEvents.load(memory_order_relaxed); 74 | 75 | if (frameTime > 20) { 76 | D2DX_LOG_PROFILE( 77 | "Frame profile:\n" 78 | "Time: %.4fms\n" 79 | "Profiled time: %.4fms (%u events)\n" 80 | "TextureDownload: %.4fms (%u events)\n" 81 | "TextureSource: %.4fms (%u events)\n" 82 | "TextureHash Miss Rate: %u/%u (%.2f%s)\n" 83 | "MotionPrediction: %.4fms (%u events)\n" 84 | "Draw: %.4fms (%u events) (%u dropped)\n" 85 | "DrawBatches: %.4fms\n" 86 | "Sleep: %.4fms (%u events)\n" 87 | "Sleep (other): %.4fms (%u events)\n" 88 | "Present: %.4fms\n", 89 | frameTime, 90 | TimeToMs(_times[static_cast(ProfCategory::Count)]), 91 | _events[static_cast(ProfCategory::Count)], 92 | TimeToMs(_times[static_cast(ProfCategory::TextureDownload)]), 93 | _events[static_cast(ProfCategory::TextureDownload)], 94 | TimeToMs(_times[static_cast(ProfCategory::TextureSource)]), 95 | _events[static_cast(ProfCategory::TextureSource)], 96 | tex_misses, tex_lookups, hashSize, hashUnit, 97 | TimeToMs(_times[static_cast(ProfCategory::MotionPrediction)]), 98 | _events[static_cast(ProfCategory::MotionPrediction)], 99 | TimeToMs(_times[static_cast(ProfCategory::Draw)]), 100 | _events[static_cast(ProfCategory::Draw)], 101 | dropped_draws, 102 | TimeToMs(_times[static_cast(ProfCategory::DrawBatches)]), 103 | TimeToMs(_times[static_cast(ProfCategory::Sleep)]), 104 | _events[static_cast(ProfCategory::Sleep)], 105 | TimeToMs(atomicTime), 106 | atomicEvents, 107 | TimeToMs(_times[static_cast(ProfCategory::Present)]) 108 | ); 109 | } 110 | memset(&_times, 0, sizeof(_times)); 111 | memset(&_events, 0, sizeof(_events)); 112 | _atomicTime.fetch_sub(atomicTime, memory_order_relaxed); 113 | _atomicEvents.fetch_sub(atomicEvents, memory_order_relaxed); 114 | tex_lookups = 0; 115 | tex_misses = 0; 116 | tex_miss_size = 0; 117 | dropped_draws = 0; 118 | lastProfileTime = TimeStamp(); 119 | } 120 | 121 | int64_t _times[static_cast(ProfCategory::Count) + 1] = {}; 122 | uint32_t _events[static_cast(ProfCategory::Count) + 1] = {}; 123 | atomic _atomicTime = { 0 }; 124 | atomic _atomicEvents = { 0 }; 125 | 126 | int64_t lastProfileTime = 0; 127 | size_t tex_lookups = 0; 128 | size_t tex_misses = 0; 129 | size_t tex_miss_size = 0; 130 | 131 | size_t dropped_draws = 0; 132 | }; 133 | 134 | static Profiler profiler; 135 | #endif 136 | 137 | _Use_decl_annotations_ 138 | d2dx::Timer::Timer( 139 | ProfCategory category) noexcept 140 | #ifdef D2DX_PROFILE 141 | : category(category) 142 | , start(TimeStamp()) 143 | , parent(currentTimer) 144 | #endif 145 | { 146 | #ifdef D2DX_PROFILE 147 | currentTimer = this; 148 | if (parent) 149 | { 150 | profiler.AddTime(start - parent->start, parent->category, false); 151 | } 152 | #endif 153 | } 154 | 155 | d2dx::Timer::~Timer() noexcept 156 | { 157 | #ifdef D2DX_PROFILE 158 | profiler.AddTime(TimeStamp() - start, category, true); 159 | if (parent) 160 | { 161 | parent->start = TimeStamp(); 162 | } 163 | currentTimer = parent; 164 | #endif 165 | } 166 | 167 | d2dx::HaltSleepProfile::HaltSleepProfile() noexcept 168 | { 169 | #ifdef D2DX_PROFILE 170 | ++halt_sleep_profile; 171 | #endif 172 | } 173 | 174 | d2dx::HaltSleepProfile::~HaltSleepProfile() noexcept 175 | { 176 | #ifdef D2DX_PROFILE 177 | --halt_sleep_profile; 178 | #endif 179 | } 180 | 181 | void d2dx::WriteProfile() noexcept 182 | { 183 | #ifdef D2DX_PROFILE 184 | profiler.WriteProfile(); 185 | #endif 186 | } 187 | 188 | void d2dx::AddTexHashLookup() noexcept 189 | { 190 | #ifdef D2DX_PROFILE 191 | profiler.tex_lookups += 1; 192 | #endif 193 | } 194 | 195 | _Use_decl_annotations_ 196 | void d2dx::AddTexHashMiss( 197 | size_t size) noexcept 198 | { 199 | #ifdef D2DX_PROFILE 200 | profiler.tex_misses += 1; 201 | profiler.tex_miss_size += size; 202 | #endif 203 | } 204 | 205 | void d2dx::AddDroppedDraw() noexcept 206 | { 207 | #ifdef D2DX_PROFILE 208 | profiler.dropped_draws += 1; 209 | #endif 210 | } 211 | -------------------------------------------------------------------------------- /src/d2dx/Profiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace d2dx { 4 | enum class ProfCategory { 5 | TextureSource, 6 | MotionPrediction, 7 | Draw, 8 | DrawBatches, 9 | TextureDownload, 10 | Sleep, 11 | Present, 12 | Count 13 | }; 14 | 15 | class Timer final { 16 | public: 17 | Timer( 18 | _In_ ProfCategory category) noexcept; 19 | ~Timer() noexcept; 20 | 21 | private: 22 | #ifdef D2DX_PROFILE 23 | Timer* parent = nullptr; 24 | ProfCategory category; 25 | int64_t start; 26 | #endif 27 | }; 28 | 29 | class HaltSleepProfile final { 30 | public: 31 | HaltSleepProfile() noexcept; 32 | ~HaltSleepProfile() noexcept; 33 | }; 34 | 35 | void WriteProfile() noexcept; 36 | 37 | void AddTexHashLookup() noexcept; 38 | void AddTexHashMiss( 39 | _In_ size_t size) noexcept; 40 | 41 | void AddDroppedDraw() noexcept; 42 | } 43 | -------------------------------------------------------------------------------- /src/d2dx/ResolveAA.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | //#define SHOW_SURFACE_IDS 23 | //#define SHOW_MASK 24 | //#define SHOW_AMPLIFIED_DIFFERENCE 25 | 26 | Texture2D sceneTexture : register(t0); 27 | Texture2D idTexture : register(t1); 28 | 29 | #define FXAA_PC 1 30 | #define FXAA_HLSL_4 1 31 | #define FXAA_QUALITY__PRESET 23 32 | #include "FXAA.hlsli" 33 | 34 | float4 main( 35 | in DisplayPSInput ps_in) : SV_TARGET 36 | { 37 | float4 c = sceneTexture.SampleLevel(PointSampler, ps_in.tc, 0); 38 | 39 | /* 40 | A B C 41 | D E F 42 | G H I 43 | */ 44 | 45 | float2 tcShifted = ps_in.tc - 0.5 * ps_in.textureSize_invTextureSize.zw; 46 | 47 | float idC = idTexture.SampleLevel(PointSampler, ps_in.tc, 0, int2(1,-1)); 48 | float4 idDEBA = idTexture.Gather(BilinearSampler, tcShifted); 49 | float4 idHIFE = idTexture.Gather(BilinearSampler, tcShifted, int2(1, 1)); 50 | float idG = idTexture.SampleLevel(PointSampler, ps_in.tc, 0, int2(-1, 1)); 51 | 52 | bool isEdge = 53 | idDEBA.y < (1.0-1.0/16383.0) && (idG != idC || any(idDEBA - idC) || any(idHIFE - idC)); 54 | 55 | if (isEdge) 56 | { 57 | #ifdef SHOW_MASK 58 | return float4(1, 0, 0, 1); 59 | #else 60 | FxaaTex ftx; 61 | ftx.smpl = BilinearSampler; 62 | ftx.tex = sceneTexture; 63 | 64 | #ifdef SHOW_AMPLIFIED_DIFFERENCE 65 | float4 oldc = c; 66 | #endif 67 | c = FxaaPixelShader(c, ps_in.tc, ftx, ps_in.textureSize_invTextureSize.zw, 0.5, 0.166, 0.166 * 0.5); 68 | #ifdef SHOW_AMPLIFIED_DIFFERENCE 69 | c.rgb = 0.5 + 4*(c.rgb - oldc.rgb); 70 | #endif 71 | #endif 72 | } 73 | #if defined(SHOW_MASK) || defined(SHOW_AMPLIFIED_DIFFERENCE) 74 | else 75 | { 76 | return float4(0.5, 0.5, 0.5, 1); 77 | } 78 | #endif 79 | 80 | #ifdef SHOW_SURFACE_IDS 81 | uint iid = (uint)(idTexture.SampleLevel(PointSampler, ps_in.tc, 0).x * 16383.0); 82 | float3 idc; 83 | idc.r = (iid & 31) / 31.0; 84 | idc.g = ((iid >> 5) & 31) / 31.0; 85 | idc.b = ((iid >> 10) & 15) / 15.0; 86 | c.rgb = lerp(c.rgb, isEdge ? 1 - idc : idc, 0.5); 87 | #endif 88 | 89 | return c; 90 | } 91 | -------------------------------------------------------------------------------- /src/d2dx/TextureCache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "D2DXContext.h" 21 | #include "Utils.h" 22 | #include "TextureCache.h" 23 | #include "TextureCachePolicyBitPmru.h" 24 | 25 | using namespace d2dx; 26 | using namespace std; 27 | 28 | _Use_decl_annotations_ 29 | TextureCache::TextureCache( 30 | int32_t width, 31 | int32_t height, 32 | uint32_t capacity, 33 | uint32_t texturesPerAtlas, 34 | ID3D11Device* device) 35 | { 36 | assert(_atlasCount <= 4); 37 | 38 | _width = width; 39 | _height = height; 40 | _capacity = capacity; 41 | _texturesPerAtlas = texturesPerAtlas; 42 | _atlasCount = (int32_t)max(1, capacity / texturesPerAtlas); 43 | _policy = TextureCachePolicyBitPmru(capacity); 44 | 45 | #ifndef D2DX_UNITTEST 46 | 47 | CD3D11_TEXTURE2D_DESC desc 48 | { 49 | DXGI_FORMAT_R8_UINT, 50 | (UINT)width, 51 | (UINT)height, 52 | _texturesPerAtlas, 53 | 1U, 54 | D3D11_BIND_SHADER_RESOURCE, 55 | D3D11_USAGE_DEFAULT 56 | }; 57 | 58 | uint32_t capacityPerPartition = _capacity; 59 | 60 | for (int32_t partition = 0; partition < 4; ++partition) 61 | { 62 | D2DX_CHECK_HR(device->CreateTexture2D(&desc, nullptr, &_textures[partition])); 63 | D2DX_CHECK_HR(device->CreateShaderResourceView(_textures[partition].Get(), NULL, _srvs[partition].GetAddressOf())); 64 | } 65 | 66 | device->GetImmediateContext(&_deviceContext); 67 | assert(_deviceContext); 68 | #endif 69 | } 70 | 71 | uint32_t TextureCache::GetMemoryFootprint() const 72 | { 73 | return _width * _height * _texturesPerAtlas * _atlasCount; 74 | } 75 | 76 | _Use_decl_annotations_ 77 | TextureCacheLocation TextureCache::FindTexture( 78 | uint64_t contentKey, 79 | int32_t lastIndex) 80 | { 81 | const int32_t index = _policy.Find(contentKey, lastIndex); 82 | 83 | if (index < 0) 84 | { 85 | return { -1, -1 }; 86 | } 87 | 88 | return { (int16_t)(index / _texturesPerAtlas), (int16_t)(index & (_texturesPerAtlas - 1)) }; 89 | } 90 | 91 | _Use_decl_annotations_ 92 | TextureCacheLocation TextureCache::InsertTexture( 93 | uint64_t contentKey, 94 | const Batch& batch, 95 | const uint8_t* tmuData, 96 | uint32_t tmuDataSize) 97 | { 98 | assert(batch.IsValid() && batch.GetTextureWidth() > 0 && batch.GetTextureHeight() > 0); 99 | 100 | bool evicted = false; 101 | int32_t replacementIndex = _policy.Insert(contentKey, evicted); 102 | 103 | if (evicted) 104 | { 105 | D2DX_DEBUG_LOG("Evicted %ix%i texture %i from cache.", batch.GetTextureWidth(), batch.GetTextureHeight(), replacementIndex); 106 | } 107 | 108 | #ifndef D2DX_UNITTEST 109 | CD3D11_BOX box; 110 | box.left = 0; 111 | box.top = 0; 112 | box.right = batch.GetTextureWidth(); 113 | box.bottom = batch.GetTextureHeight(); 114 | box.front = 0; 115 | box.back = 1; 116 | 117 | const uint8_t* pData = tmuData + batch.GetTextureStartAddress(); 118 | 119 | _deviceContext->UpdateSubresource(_textures[replacementIndex / _texturesPerAtlas].Get(), replacementIndex & (_texturesPerAtlas - 1), &box, pData, batch.GetTextureWidth(), 0); 120 | #endif 121 | 122 | return { (int16_t)(replacementIndex / _texturesPerAtlas), (int16_t)(replacementIndex & (_texturesPerAtlas - 1)) }; 123 | } 124 | 125 | _Use_decl_annotations_ 126 | ID3D11ShaderResourceView* TextureCache::GetSrv( 127 | uint32_t textureAtlas) const 128 | { 129 | assert(textureAtlas >= 0 && textureAtlas < (uint32_t)_atlasCount); 130 | return _srvs[textureAtlas].Get(); 131 | } 132 | 133 | void TextureCache::OnNewFrame() 134 | { 135 | _policy.OnNewFrame(); 136 | } 137 | 138 | _Use_decl_annotations_ 139 | void TextureCache::CopyPixels( 140 | int32_t srcWidth, 141 | int32_t srcHeight, 142 | const uint8_t* __restrict srcPixels, 143 | uint32_t srcPitch, 144 | uint8_t* __restrict dstPixels, 145 | uint32_t dstPitch) 146 | { 147 | const int32_t srcSkip = srcPitch - srcWidth; 148 | const int32_t dstSkip = dstPitch - srcWidth; 149 | 150 | assert(srcSkip >= 0); 151 | assert(dstSkip >= 0); 152 | 153 | for (int32_t y = 0; y < srcHeight; ++y) 154 | { 155 | for (int32_t x = 0; x < srcWidth; ++x) 156 | { 157 | *dstPixels++ = *srcPixels++; 158 | } 159 | srcPixels += srcSkip; 160 | dstPixels += dstSkip; 161 | } 162 | } 163 | 164 | uint32_t TextureCache::GetUsedCount() const 165 | { 166 | return _policy.GetUsedCount(); 167 | } 168 | -------------------------------------------------------------------------------- /src/d2dx/TextureCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "ITextureCache.h" 22 | #include "TextureCachePolicyBitPmru.h" 23 | 24 | namespace d2dx 25 | { 26 | class TextureCache final : public ITextureCache 27 | { 28 | public: 29 | TextureCache( 30 | _In_ int32_t width, 31 | _In_ int32_t height, 32 | _In_ uint32_t capacity, 33 | _In_ uint32_t texturesPerAtlas, 34 | _In_ ID3D11Device* device); 35 | 36 | virtual ~TextureCache() noexcept {} 37 | 38 | virtual void OnNewFrame() override; 39 | 40 | virtual TextureCacheLocation FindTexture( 41 | _In_ uint64_t contentKey, 42 | _In_ int32_t lastIndex) override; 43 | 44 | virtual TextureCacheLocation InsertTexture( 45 | _In_ uint64_t contentKey, 46 | _In_ const Batch& batch, 47 | _In_reads_(tmuDataSize) const uint8_t* tmuData, 48 | _In_ uint32_t tmuDataSize) override; 49 | 50 | virtual ID3D11ShaderResourceView* GetSrv( 51 | _In_ uint32_t atlasIndex) const override; 52 | 53 | virtual uint32_t GetMemoryFootprint() const override; 54 | 55 | virtual uint32_t GetUsedCount() const override; 56 | 57 | private: 58 | void CopyPixels( 59 | _In_ int32_t srcWidth, 60 | _In_ int32_t srcHeight, 61 | _In_reads_(srcPitch* srcHeight) const uint8_t* __restrict srcPixels, 62 | _In_ uint32_t srcPitch, 63 | _Out_writes_all_(dstPitch* srcHeight) uint8_t* __restrict dstPixels, 64 | _In_ uint32_t dstPitch); 65 | 66 | int32_t _width = 0; 67 | int32_t _height = 0; 68 | uint32_t _capacity = 0; 69 | uint32_t _texturesPerAtlas = 0; 70 | int32_t _atlasCount = 0; 71 | ComPtr _deviceContext; 72 | ComPtr _textures[4]; 73 | ComPtr _srvs[4]; 74 | TextureCachePolicyBitPmru _policy; 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /src/d2dx/TextureCachePolicyBitPmru.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "Utils.h" 21 | #include "TextureCachePolicyBitPmru.h" 22 | 23 | using namespace d2dx; 24 | 25 | _Use_decl_annotations_ 26 | TextureCachePolicyBitPmru::TextureCachePolicyBitPmru( 27 | uint32_t capacity) : 28 | _capacity{ capacity }, 29 | _contentKeys{ capacity, true }, 30 | _usedInFrameBits{ capacity >> 5, true }, 31 | _mruBits{ capacity >> 5, true } 32 | { 33 | assert(!(capacity & 63)); 34 | } 35 | 36 | _Use_decl_annotations_ 37 | int32_t TextureCachePolicyBitPmru::Find( 38 | uint64_t contentKey, 39 | int32_t lastIndex) 40 | { 41 | assert(contentKey != 0); 42 | 43 | if (_capacity == 0) 44 | { 45 | return -1; 46 | } 47 | 48 | if (lastIndex >= 0 && lastIndex < (int32_t)_capacity && 49 | contentKey == _contentKeys.items[lastIndex]) 50 | { 51 | _usedInFrameBits.items[lastIndex >> 5] |= 1 << (lastIndex & 31); 52 | _mruBits.items[lastIndex >> 5] |= 1 << (lastIndex & 31); 53 | return lastIndex; 54 | } 55 | 56 | int32_t findIndex = IndexOfUInt64(_contentKeys.items, _capacity, contentKey); 57 | 58 | if (findIndex >= 0) 59 | { 60 | _usedInFrameBits.items[findIndex >> 5] |= 1 << (findIndex & 31); 61 | _mruBits.items[findIndex >> 5] |= 1 << (findIndex & 31); 62 | return findIndex; 63 | } 64 | 65 | return -1; 66 | } 67 | 68 | _Use_decl_annotations_ 69 | int32_t TextureCachePolicyBitPmru::Insert( 70 | uint64_t contentKey, 71 | bool& evicted) 72 | { 73 | if (_capacity == 0) 74 | { 75 | evicted = false; 76 | return -1; 77 | } 78 | 79 | int32_t replacementIndex = -1; 80 | 81 | for (uint32_t i = 0; i < _mruBits.capacity; ++i) 82 | { 83 | DWORD ri; 84 | if (BitScanForward(&ri, (DWORD)~_mruBits.items[i])) 85 | { 86 | replacementIndex = (int32_t)(i * 32 + ri); 87 | break; 88 | } 89 | } 90 | 91 | if (replacementIndex < 0) 92 | { 93 | memcpy(_mruBits.items, _usedInFrameBits.items, sizeof(uint32_t) * _mruBits.capacity); 94 | 95 | for (uint32_t i = 0; i < _mruBits.capacity; ++i) 96 | { 97 | DWORD ri; 98 | if (BitScanForward(&ri, (DWORD)~_mruBits.items[i])) 99 | { 100 | replacementIndex = (int32_t)(i * 32 + ri); 101 | break; 102 | } 103 | } 104 | } 105 | 106 | if (replacementIndex < 0) 107 | { 108 | D2DX_LOG("All texture atlas entries used in a single frame, starting over!"); 109 | memset(_mruBits.items, 0, sizeof(uint32_t) * _mruBits.capacity); 110 | memset(_usedInFrameBits.items, 0, sizeof(uint32_t) * _usedInFrameBits.capacity); 111 | 112 | for (uint32_t i = 0; i < _mruBits.capacity; ++i) 113 | { 114 | DWORD ri; 115 | if (BitScanForward(&ri, (DWORD)~_mruBits.items[i])) 116 | { 117 | replacementIndex = (int32_t)(i * 32 + ri); 118 | break; 119 | } 120 | } 121 | } 122 | 123 | _mruBits.items[replacementIndex >> 5] |= 1 << (replacementIndex & 31); 124 | _usedInFrameBits.items[replacementIndex >> 5] |= 1 << (replacementIndex & 31); 125 | 126 | evicted = _contentKeys.items[replacementIndex] != 0; 127 | 128 | if (!evicted) 129 | { 130 | ++_usedCount; 131 | } 132 | 133 | _contentKeys.items[replacementIndex] = contentKey; 134 | 135 | return replacementIndex; 136 | } 137 | 138 | void TextureCachePolicyBitPmru::OnNewFrame() 139 | { 140 | memset(_usedInFrameBits.items, 0, sizeof(uint32_t) * _usedInFrameBits.capacity); 141 | } 142 | 143 | uint32_t TextureCachePolicyBitPmru::GetUsedCount() const 144 | { 145 | return _usedCount; 146 | } 147 | -------------------------------------------------------------------------------- /src/d2dx/TextureCachePolicyBitPmru.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Buffer.h" 22 | 23 | namespace d2dx 24 | { 25 | class TextureCachePolicyBitPmru final 26 | { 27 | public: 28 | TextureCachePolicyBitPmru() = default; 29 | TextureCachePolicyBitPmru& operator=(TextureCachePolicyBitPmru&& rhs) = default; 30 | 31 | TextureCachePolicyBitPmru( 32 | _In_ uint32_t capacity); 33 | ~TextureCachePolicyBitPmru() noexcept {} 34 | 35 | int32_t Find( 36 | _In_ uint64_t contentKey, 37 | _In_ int32_t lastIndex); 38 | 39 | int32_t Insert( 40 | _In_ uint64_t contentKey, 41 | _Out_ bool& evicted); 42 | 43 | void OnNewFrame(); 44 | 45 | uint32_t GetUsedCount() const; 46 | 47 | private: 48 | uint32_t _capacity = 0; 49 | Buffer _contentKeys; 50 | Buffer _usedInFrameBits; 51 | Buffer _mruBits; 52 | uint32_t _usedCount = 0; 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /src/d2dx/TextureHasher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "TextureHasher.h" 21 | #include "Types.h" 22 | #include "Utils.h" 23 | #include "Profiler.h" 24 | 25 | using namespace d2dx; 26 | 27 | TextureHasher::TextureHasher() : 28 | _cache{ D2DX_TMU_MEMORY_SIZE / 256, true } 29 | { 30 | } 31 | 32 | _Use_decl_annotations_ 33 | void TextureHasher::Invalidate( 34 | uint32_t startAddress) 35 | { 36 | _cache.items[startAddress >> 8] = 0; 37 | } 38 | 39 | _Use_decl_annotations_ 40 | XXH64_hash_t TextureHasher::GetHash( 41 | uint32_t startAddress, 42 | const uint8_t* pixels, 43 | uint32_t pixelsSize, 44 | uint32_t largeLog2, 45 | uint32_t ratioLog2) 46 | { 47 | assert((startAddress & 255) == 0); 48 | 49 | XXH64_hash_t hash = _cache.items[startAddress >> 8]; 50 | AddTexHashLookup(); 51 | 52 | if (!hash) 53 | { 54 | AddTexHashMiss(pixelsSize); 55 | hash = XXH3_64bits((void *)pixels, pixelsSize); 56 | hash ^= static_cast(largeLog2 * 0x01000193u); 57 | hash ^= static_cast(ratioLog2 * 0x01000193u) << 32; 58 | _cache.items[startAddress >> 8] = hash; 59 | } 60 | 61 | return hash; 62 | } 63 | -------------------------------------------------------------------------------- /src/d2dx/TextureHasher.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "Buffer.h" 22 | 23 | namespace d2dx 24 | { 25 | class TextureHasher final 26 | { 27 | public: 28 | TextureHasher(); 29 | ~TextureHasher() noexcept {} 30 | 31 | void Invalidate( 32 | _In_ uint32_t startAddress); 33 | 34 | XXH64_hash_t GetHash( 35 | _In_ uint32_t startAddress, 36 | _In_reads_(pixelsSize) const uint8_t* pixels, 37 | _In_ uint32_t pixelsSize, 38 | _In_ uint32_t largeLog2, 39 | _In_ uint32_t ratioLog2); 40 | 41 | private: 42 | Buffer _cache; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/d2dx/Types.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #define D2DX_TMU_ADDRESS_ALIGNMENT 256 22 | #define D2DX_TMU_MEMORY_SIZE (16 * 1024 * 1024) 23 | #define D2DX_SIDE_TMU_MEMORY_SIZE (1 * 1024 * 1024) 24 | #define D2DX_MAX_BATCHES_PER_FRAME 16384 25 | #define D2DX_MAX_VERTICES_PER_FRAME (1024 * 1024) 26 | 27 | #define D2DX_MAX_GAME_PALETTES 14 28 | #define D2DX_WHITE_PALETTE_INDEX 14 29 | #define D2DX_LOGO_PALETTE_INDEX 15 30 | #define D2DX_MAX_PALETTES 16 31 | 32 | #define D2DX_SURFACE_UI 0 33 | #define D2DX_SURFACE_CURSOR 1 34 | #define D2DX_SURFACE_FIRST 2 35 | 36 | namespace d2dx 37 | { 38 | static_assert(((D2DX_TMU_MEMORY_SIZE - 1) >> 8) == 0xFFFF, "TMU memory start addresses aren't 16 bit."); 39 | 40 | enum class ScreenMode 41 | { 42 | Windowed = 0, 43 | FullscreenDefault = 1, 44 | }; 45 | 46 | enum class MajorGameState 47 | { 48 | Unknown = 0, 49 | FmvIntro = 1, 50 | TitleScreen = 2, 51 | Other = 3, 52 | }; 53 | 54 | enum class PrimitiveType 55 | { 56 | Points = 0, 57 | Lines = 1, 58 | Triangles = 2, 59 | Count = 3 60 | }; 61 | 62 | enum class AlphaBlend 63 | { 64 | Opaque = 0, 65 | SrcAlphaInvSrcAlpha = 1, 66 | Additive = 2, 67 | Multiplicative = 3, 68 | Count = 4 69 | }; 70 | 71 | enum class RgbCombine 72 | { 73 | ColorMultipliedByTexture = 0, 74 | ConstantColor = 1, 75 | Count = 2 76 | }; 77 | 78 | enum class AlphaCombine 79 | { 80 | One = 0, 81 | FromColor = 1, 82 | Count = 2 83 | }; 84 | 85 | enum class GameVersion 86 | { 87 | Unsupported = 0, 88 | Lod107, 89 | Lod108, 90 | Lod109, 91 | Lod109b, 92 | Lod109d, 93 | Lod110f, 94 | Lod111, 95 | Lod111b, 96 | Lod112, 97 | Lod113c, 98 | Lod113d, 99 | Lod114c, 100 | Lod114d, 101 | }; 102 | 103 | template 104 | struct OffsetT final 105 | { 106 | T x = T{ 0 }; 107 | T y = T{ 0 }; 108 | 109 | constexpr OffsetT(T x_, T y_) noexcept : 110 | x{ x_ }, 111 | y{ y_ } 112 | { 113 | } 114 | 115 | template 116 | constexpr explicit OffsetT(const OffsetT& other) noexcept: 117 | x(static_cast(other.x)), 118 | y(static_cast(other.y)) 119 | { 120 | } 121 | 122 | constexpr OffsetT& operator+=(const OffsetT& rhs) noexcept 123 | { 124 | x += rhs.x; 125 | y += rhs.y; 126 | return *this; 127 | } 128 | 129 | constexpr OffsetT& operator-=(const OffsetT& rhs) noexcept 130 | { 131 | x -= rhs.x; 132 | y -= rhs.y; 133 | return *this; 134 | } 135 | 136 | constexpr OffsetT& operator*=(const OffsetT& rhs) noexcept 137 | { 138 | x *= rhs.x; 139 | y *= rhs.y; 140 | return *this; 141 | } 142 | 143 | constexpr OffsetT& operator+=(T rhs) noexcept 144 | { 145 | x += rhs; 146 | y += rhs; 147 | return *this; 148 | } 149 | 150 | constexpr OffsetT& operator-=(T rhs) noexcept 151 | { 152 | x -= rhs; 153 | y -= rhs; 154 | return *this; 155 | } 156 | 157 | constexpr OffsetT& operator*=(T rhs) noexcept 158 | { 159 | x *= rhs; 160 | y *= rhs; 161 | return *this; 162 | } 163 | 164 | constexpr OffsetT operator+(const OffsetT& rhs) const noexcept 165 | { 166 | return { x + rhs.x, y + rhs.y }; 167 | } 168 | 169 | constexpr OffsetT operator-(const OffsetT& rhs) const noexcept 170 | { 171 | return { x - rhs.x, y - rhs.y }; 172 | } 173 | 174 | constexpr OffsetT operator*(const OffsetT& rhs) const noexcept 175 | { 176 | return { x * rhs.x, y * rhs.y }; 177 | } 178 | 179 | constexpr OffsetT operator/(const OffsetT& rhs) const noexcept 180 | { 181 | return { x / rhs.x, y / rhs.y }; 182 | } 183 | 184 | constexpr OffsetT operator+(T rhs) const noexcept 185 | { 186 | return { x + rhs, y + rhs }; 187 | } 188 | 189 | constexpr OffsetT operator-(T rhs) const noexcept 190 | { 191 | return { x - rhs, y - rhs }; 192 | } 193 | 194 | constexpr OffsetT operator*(T rhs) const noexcept 195 | { 196 | return { x * rhs, y * rhs }; 197 | } 198 | 199 | constexpr bool operator==(const OffsetT& rhs) const noexcept = default; 200 | constexpr bool operator!=(const OffsetT& rhs) const noexcept = default; 201 | 202 | constexpr T Length() const noexcept 203 | { 204 | return std::hypot(x, y); 205 | } 206 | 207 | constexpr void Normalize() noexcept 208 | { 209 | NormalizeTo(T { 1.0 }); 210 | } 211 | 212 | constexpr void NormalizeTo(T target) noexcept 213 | { 214 | T len = Length(); 215 | T inv = target / len; 216 | *this *= len == T{ 0 } ? T{ 1 } : inv; 217 | } 218 | }; 219 | 220 | using OffsetF = OffsetT; 221 | using Offset = OffsetT; 222 | 223 | struct Size final 224 | { 225 | int32_t width = 0; 226 | int32_t height = 0; 227 | 228 | Size operator*(int32_t value) noexcept 229 | { 230 | return { width * value, height * value }; 231 | } 232 | 233 | Size operator*(uint32_t value) noexcept 234 | { 235 | return { width * (int32_t)value, height * (int32_t)value }; 236 | } 237 | 238 | Size operator*(float value) noexcept 239 | { 240 | return { static_cast(static_cast(width) * value), 241 | static_cast(static_cast(height) * value) }; 242 | } 243 | 244 | bool operator==(const Size& rhs) const noexcept 245 | { 246 | return width == rhs.width && height == rhs.height; 247 | } 248 | }; 249 | 250 | struct Rect final 251 | { 252 | Offset offset; 253 | Size size; 254 | 255 | Rect() noexcept : 256 | offset{ 0,0 }, 257 | size{ 0,0 } 258 | { 259 | } 260 | 261 | Rect(int32_t x, int32_t y, int32_t w, int32_t h) noexcept : 262 | offset{ x,y }, 263 | size{ w,h } 264 | { 265 | } 266 | 267 | bool IsValid() const noexcept 268 | { 269 | return size.width > 0 && size.height > 0; 270 | } 271 | 272 | bool operator==(const Rect& rhs) const noexcept 273 | { 274 | return offset == rhs.offset && size == rhs.size; 275 | } 276 | }; 277 | } 278 | -------------------------------------------------------------------------------- /src/d2dx/Utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | #include "ErrorHandling.h" 22 | #include "Buffer.h" 23 | 24 | #define D2DX_LOG(fmt, ...) \ 25 | { \ 26 | static char ssss[1024]; \ 27 | sprintf_s(ssss, fmt "\n", __VA_ARGS__); \ 28 | d2dx::detail::Log(ssss); \ 29 | } 30 | 31 | #ifdef NDEBUG 32 | #define D2DX_DEBUG_LOG(fmt, ...) 33 | #else 34 | #define D2DX_DEBUG_LOG(fmt, ...) D2DX_LOG(fmt, __VA_ARGS__) 35 | #endif 36 | 37 | #ifdef D2DX_PROFILE 38 | #define D2DX_LOG_PROFILE(fmt, ...) D2DX_LOG(fmt, __VA_ARGS__) 39 | #else 40 | #define D2DX_LOG_PROFILE(fmt, ...) 41 | #endif 42 | 43 | namespace d2dx 44 | { 45 | namespace detail 46 | { 47 | __declspec(noinline) void Log(_In_z_ const char* s); 48 | } 49 | 50 | int64_t TimeStamp() noexcept; 51 | double TimeToMs(int64_t time) noexcept; 52 | 53 | struct WindowsVersion 54 | { 55 | uint32_t major; 56 | uint32_t minor; 57 | uint32_t build; 58 | }; 59 | 60 | WindowsVersion GetWindowsVersion(); 61 | 62 | WindowsVersion GetActualWindowsVersion(); 63 | 64 | Buffer ReadTextFile( 65 | _In_z_ const char* filename); 66 | 67 | void DumpTexture( 68 | _In_ uint64_t hash, 69 | _In_ int32_t w, 70 | _In_ int32_t h, 71 | _In_reads_(pixelsSize) const uint8_t* pixels, 72 | _In_ uint32_t pixelsSize, 73 | _In_reads_(256) const uint32_t* palette); 74 | 75 | bool DecompressLZMAToFile( 76 | _In_reads_(dataSize) const uint8_t* data, 77 | _In_ uint32_t dataSize, 78 | _In_z_ const char* filename); 79 | 80 | int32_t IndexOfUInt64( 81 | _In_reads_(itemsCount) const uint64_t* __restrict items, 82 | _In_ uint32_t itemsCount, 83 | _In_ uint64_t item); 84 | } 85 | -------------------------------------------------------------------------------- /src/d2dx/Vertex.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #pragma once 20 | 21 | namespace d2dx 22 | { 23 | class Vertex final 24 | { 25 | public: 26 | Vertex() noexcept : 27 | _x{ 0 }, 28 | _y{ 0 }, 29 | _s{ 0 }, 30 | _t{ 0 }, 31 | _color{ 0 }, 32 | _isChromaKeyEnabled_surfaceId{ 0 }, 33 | _paletteIndex_atlasIndex{ 0 } 34 | { 35 | } 36 | 37 | Vertex( 38 | float x, 39 | float y, 40 | int32_t s, 41 | int32_t t, 42 | uint32_t color, 43 | bool isChromaKeyEnabled, 44 | int32_t atlasIndex, 45 | int32_t paletteIndex, 46 | int32_t surfaceId) noexcept : 47 | _x(x), 48 | _y(y), 49 | _s(s), 50 | _t(t), 51 | _color(color), 52 | _isChromaKeyEnabled_surfaceId((isChromaKeyEnabled ? 0x4000 : 0) | (surfaceId & 16383)), 53 | _paletteIndex_atlasIndex((paletteIndex << 12) | (atlasIndex & 4095)) 54 | { 55 | assert(s >= INT16_MIN && s <= INT16_MAX); 56 | assert(t >= INT16_MIN && t <= INT16_MAX); 57 | assert(paletteIndex >= 0 && paletteIndex < D2DX_MAX_PALETTES); 58 | assert(atlasIndex >= 0 && atlasIndex <= 4095); 59 | assert(surfaceId >= 0 && surfaceId <= 16383); 60 | } 61 | 62 | inline void AddOffset( 63 | _In_ int32_t x, 64 | _In_ int32_t y) noexcept 65 | { 66 | _x += x; 67 | _y += y; 68 | } 69 | 70 | inline float GetX() const noexcept 71 | { 72 | return _x; 73 | } 74 | 75 | inline float GetY() const noexcept 76 | { 77 | return _y; 78 | } 79 | 80 | inline void SetPosition(float x, float y) noexcept 81 | { 82 | _x = x; 83 | _y = y; 84 | } 85 | 86 | inline void SetSurfaceId(int32_t surfaceId) noexcept 87 | { 88 | assert(surfaceId >= 0 && surfaceId <= 16383); 89 | _isChromaKeyEnabled_surfaceId &= ~16383; 90 | _isChromaKeyEnabled_surfaceId |= surfaceId & 16383; 91 | } 92 | 93 | inline int32_t GetSurfaceId() const noexcept 94 | { 95 | return _isChromaKeyEnabled_surfaceId & 16383; 96 | } 97 | 98 | inline int32_t GetS() const noexcept 99 | { 100 | return _s; 101 | } 102 | 103 | inline int32_t GetT() const noexcept 104 | { 105 | return _t; 106 | } 107 | 108 | inline void SetTexcoord(int32_t s, int32_t t) noexcept 109 | { 110 | assert(s >= 0 && s <= 511); 111 | assert(t >= 0 && t <= 511); 112 | _s = s; 113 | _t = t; 114 | } 115 | 116 | inline void SetAtlasIndex(int32_t atlasIndex) noexcept 117 | { 118 | assert(atlasIndex >= 0 && atlasIndex <= 4095); 119 | _paletteIndex_atlasIndex = (_paletteIndex_atlasIndex & ~4095) | (atlasIndex & 4095); 120 | } 121 | 122 | inline uint32_t GetColor() const noexcept 123 | { 124 | return _color; 125 | } 126 | 127 | inline void SetColor(uint32_t color) noexcept 128 | { 129 | _color = color; 130 | } 131 | 132 | inline bool IsChromaKeyEnabled() const noexcept 133 | { 134 | return (_isChromaKeyEnabled_surfaceId & 0x4000) != 0; 135 | } 136 | 137 | private: 138 | float _x; 139 | float _y; 140 | int16_t _s; 141 | int16_t _t; 142 | uint32_t _color; 143 | uint16_t _paletteIndex_atlasIndex; 144 | uint16_t _isChromaKeyEnabled_surfaceId; 145 | }; 146 | 147 | static_assert(sizeof(Vertex) == 20, "sizeof(Vertex)"); 148 | } 149 | -------------------------------------------------------------------------------- /src/d2dx/VideoGammaPS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D tex : register(t0); 23 | 24 | float4 main( 25 | in DisplayPSInput ps_in) : SV_TARGET 26 | { 27 | #pragma warning(push) 28 | #pragma warning(disable:3571) 29 | return pow(tex.Sample(BilinearSampler, ps_in.tc), 1/1.5) * float4(1, 1, 1, 0) + float4(0, 0, 0, 1); 30 | #pragma warning(pop) 31 | } 32 | -------------------------------------------------------------------------------- /src/d2dx/VideoPS.hlsl: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "Constants.hlsli" 20 | #include "Display.hlsli" 21 | 22 | Texture2D tex : register(t0); 23 | 24 | float4 main( 25 | in DisplayPSInput ps_in) : SV_TARGET 26 | { 27 | return tex.Sample(BilinearSampler, ps_in.tc) * float4(1, 1, 1, 0) + float4(0, 0, 0, 1); 28 | } 29 | -------------------------------------------------------------------------------- /src/d2dx/d2dx.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "winres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // Neutral (Default) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) 19 | LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT 20 | #pragma code_page(1252) 21 | 22 | ///////////////////////////////////////////////////////////////////////////// 23 | // 24 | // Version 25 | // 26 | 27 | VS_VERSION_INFO VERSIONINFO 28 | FILEVERSION 0,103,4,0 29 | PRODUCTVERSION 0,103,4,0 30 | FILEFLAGSMASK 0x3fL 31 | #ifdef _DEBUG 32 | FILEFLAGS 0x1L 33 | #else 34 | FILEFLAGS 0x0L 35 | #endif 36 | FILEOS 0x40004L 37 | FILETYPE 0x2L 38 | FILESUBTYPE 0x0L 39 | BEGIN 40 | BLOCK "StringFileInfo" 41 | BEGIN 42 | BLOCK "040004b0" 43 | BEGIN 44 | VALUE "CompanyName", "Jarcho" 45 | VALUE "FileDescription", "Glide wrapper for D2" 46 | VALUE "FileVersion", "0.103.4.0" 47 | VALUE "InternalName", "d2dx.dll" 48 | VALUE "LegalCopyright", "Copyright (C) 2024" 49 | VALUE "OriginalFilename", "d2dx.dll" 50 | VALUE "ProductName", "D2DX" 51 | VALUE "ProductVersion", "0.103.4.0" 52 | END 53 | END 54 | BLOCK "VarFileInfo" 55 | BEGIN 56 | VALUE "Translation", 0x400, 1200 57 | END 58 | END 59 | 60 | 61 | ///////////////////////////////////////////////////////////////////////////// 62 | // 63 | // MPQ 64 | // 65 | 66 | #if defined(APSTUDIO_INVOKED) || defined(D2DX_RES_MOD) 67 | #if defined(APSTUDIO_INVOKED) 68 | IDR_SGD2FR_MPQ$(D2DX_RES_MOD) MPQ "..\\..\\thirdparty\\sgd2freeres\\sgd2freeres.mpq.lzma" 69 | 70 | #else 71 | IDR_SGD2FR_MPQ MPQ "..\\..\\thirdparty\\sgd2freeres\\sgd2freeres.mpq.lzma" 72 | 73 | #endif 74 | #endif 75 | 76 | ///////////////////////////////////////////////////////////////////////////// 77 | // 78 | // DLL 79 | // 80 | 81 | #if defined(APSTUDIO_INVOKED) || defined(D2DX_RES_MOD) 82 | #if defined(APSTUDIO_INVOKED) 83 | IDR_SGD2FR_DLL$(D2DX_RES_MOD) DLL "..\\..\\thirdparty\\sgd2freeres\\sgd2freeres.dll.lzma" 84 | 85 | #else 86 | IDR_SGD2FR_DLL DLL "..\\..\\thirdparty\\sgd2freeres\\sgd2freeres.dll.lzma" 87 | 88 | #endif 89 | #endif 90 | #endif // Neutral (Default) resources 91 | ///////////////////////////////////////////////////////////////////////////// 92 | 93 | 94 | ///////////////////////////////////////////////////////////////////////////// 95 | // Swedish (Sweden) resources 96 | 97 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) 98 | LANGUAGE LANG_SWEDISH, SUBLANG_SWEDISH 99 | #pragma code_page(1252) 100 | 101 | #ifdef APSTUDIO_INVOKED 102 | ///////////////////////////////////////////////////////////////////////////// 103 | // 104 | // TEXTINCLUDE 105 | // 106 | 107 | 1 TEXTINCLUDE 108 | BEGIN 109 | "resource.h\0" 110 | END 111 | 112 | 2 TEXTINCLUDE 113 | BEGIN 114 | "#include ""winres.h""\r\n" 115 | "\0" 116 | END 117 | 118 | 3 TEXTINCLUDE 119 | BEGIN 120 | "\r\n" 121 | "\0" 122 | END 123 | 124 | #endif // APSTUDIO_INVOKED 125 | 126 | #endif // Swedish (Sweden) resources 127 | ///////////////////////////////////////////////////////////////////////////// 128 | 129 | 130 | 131 | #ifndef APSTUDIO_INVOKED 132 | ///////////////////////////////////////////////////////////////////////////// 133 | // 134 | // Generated from the TEXTINCLUDE 3 resource. 135 | // 136 | 137 | 138 | ///////////////////////////////////////////////////////////////////////////// 139 | #endif // not APSTUDIO_INVOKED 140 | -------------------------------------------------------------------------------- /src/d2dx/d2dx.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | C:\Program Files\Diablo II\game.exe 5 | WindowsLocalDebugger 6 | -3dfx -dxnologo -dxnowide -w -dxnoresmod 7 | C:\Program Files\Diablo II 8 | NativeOnly 9 | 10 | 11 | C:\Program Files\Diablo II\game.exe 12 | WindowsLocalDebugger 13 | -3dfx -dxnologo -dxnowide -w -dxnoresmod 14 | C:\Program Files\Diablo II 15 | NativeOnly 16 | 17 | 18 | C:\Program Files\Diablo II\game.exe 19 | WindowsLocalDebugger 20 | -3dfx -dxnologo -dxnowide -w -dxnoresmod 21 | C:\Program Files\Diablo II 22 | NativeOnly 23 | 24 | 25 | C:\Program Files\Diablo II\game.exe 26 | WindowsLocalDebugger 27 | -3dfx -dxnologo -dxnowide -w -dxnoresmod 28 | C:\Program Files\Diablo II 29 | NativeOnly 30 | 31 | -------------------------------------------------------------------------------- /src/d2dx/dllmain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include "Detours.h" 21 | 22 | #pragma comment(lib, "comctl32.lib") 23 | #pragma comment(lib, "dxgi.lib") 24 | #pragma comment(lib, "d3d11.lib") 25 | #pragma comment(lib, "d3dcompiler.lib") 26 | 27 | using namespace d2dx; 28 | using namespace std; 29 | 30 | BOOL APIENTRY DllMain( 31 | _In_ HMODULE hModule, 32 | _In_ DWORD ul_reason_for_call, 33 | _In_ LPVOID lpReserved 34 | ) 35 | { 36 | switch (ul_reason_for_call) 37 | { 38 | case DLL_PROCESS_ATTACH: 39 | SetProcessDPIAware(); 40 | break; 41 | 42 | case DLL_THREAD_ATTACH: 43 | case DLL_THREAD_DETACH: 44 | case DLL_PROCESS_DETACH: 45 | break; 46 | } 47 | return TRUE; 48 | } 49 | -------------------------------------------------------------------------------- /src/d2dx/pch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | -------------------------------------------------------------------------------- /src/d2dx/pch.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #ifndef PCH_H 20 | #define PCH_H 21 | 22 | #define WIN32_LEAN_AND_MEAN 23 | #define __MSC__ 24 | 25 | #define XXH_VECTOR XXH_SSE2 26 | #define XXH_NO_STREAM 1 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #include "../../thirdparty/fnv/fnv.h" 50 | #include "../../thirdparty/detours/detours.h" 51 | #include "../../thirdparty/xxhash/xxhash.h" 52 | #include 53 | 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | template 64 | using ComPtr = Microsoft::WRL::ComPtr; 65 | 66 | using EventHandle = Microsoft::WRL::Wrappers::HandleT; 67 | 68 | #endif //PCH_H 69 | -------------------------------------------------------------------------------- /src/d2dx/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by d2dx.rc 4 | // 5 | #define IDR_SGD2FR_MPQ 101 6 | #define IDR_SGD2FR_DLL 102 7 | 8 | // Next default values for new objects 9 | // 10 | #ifdef APSTUDIO_INVOKED 11 | #ifndef APSTUDIO_READONLY_SYMBOLS 12 | #define _APS_NEXT_RESOURCE_VALUE 102 13 | #define _APS_NEXT_COMMAND_VALUE 40001 14 | #define _APS_NEXT_CONTROL_VALUE 1001 15 | #define _APS_NEXT_SYMED_VALUE 101 16 | #endif 17 | #endif 18 | -------------------------------------------------------------------------------- /src/d2dxtests/TestMetrics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include 21 | #include "CppUnitTest.h" 22 | #include "../d2dx/Metrics.h" 23 | 24 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 25 | using namespace d2dx; 26 | using namespace DirectX; 27 | 28 | namespace Microsoft 29 | { 30 | namespace VisualStudio 31 | { 32 | namespace CppUnitTestFramework 33 | { 34 | template<> static std::wstring ToString(const Offset& t) { return ToString(t.x) + L", " + ToString(t.y); } 35 | template<> static std::wstring ToString(const Size& t) { return ToString(t.width) + L"x" + ToString(t.height); } 36 | } 37 | } 38 | } 39 | 40 | namespace d2dxtests 41 | { 42 | TEST_CLASS(TestStandardMetrics) 43 | { 44 | public: 45 | TEST_METHOD(TestGetStandardDesktopSizes) 46 | { 47 | auto standardDesktopSizes = d2dx::Metrics::GetStandardDesktopSizes(); 48 | Assert::IsTrue(standardDesktopSizes.capacity > 8); 49 | } 50 | 51 | TEST_METHOD(TestGetGameSize) 52 | { 53 | auto suggestedGameSize = d2dx::Metrics::GetSuggestedGameSize({ 1920, 1080 }, false); 54 | Assert::AreEqual(Size(720, 540), suggestedGameSize); 55 | 56 | // Odd desktop size that isn't large enough to divide down. 57 | suggestedGameSize = d2dx::Metrics::GetSuggestedGameSize({ 1000, 500 }, true); 58 | Assert::AreEqual(Size(1000, 500), suggestedGameSize); 59 | 60 | // Odd desktop size where a 2x integer scale would result in a too small game size. 61 | suggestedGameSize = d2dx::Metrics::GetSuggestedGameSize({ 2001, 1003 }, true); 62 | Assert::AreEqual(Size(1436, 720), suggestedGameSize); 63 | } 64 | 65 | void AssertThatGameSizeIsIntegerScale(Size desktopSize, bool wide, bool lenient) 66 | { 67 | auto suggestedGameSize = d2dx::Metrics::GetSuggestedGameSize(desktopSize, wide); 68 | auto renderRect = d2dx::Metrics::GetRenderRect(suggestedGameSize, desktopSize, wide); 69 | Assert::IsTrue(renderRect.offset.x >= 0); 70 | Assert::IsTrue(renderRect.offset.y >= 0); 71 | Assert::IsTrue(renderRect.size.width > 0); 72 | Assert::IsTrue(renderRect.size.height > 0); 73 | Assert::IsTrue((renderRect.offset.x + renderRect.size.width) <= desktopSize.width); 74 | Assert::IsTrue((renderRect.offset.y + renderRect.size.height) <= desktopSize.height); 75 | 76 | if (renderRect.offset.x > 0 && renderRect.offset.y > 0) 77 | { 78 | Assert::IsTrue(renderRect.offset.x < 16 || renderRect.offset.y < 16); 79 | } 80 | 81 | int32_t reconstructedDesktopWidth = renderRect.size.width + renderRect.offset.x * 2; 82 | int32_t reconstructedDesktopHeight = renderRect.size.height + renderRect.offset.y * 2; 83 | 84 | if (lenient) 85 | { 86 | /* The "remainder" on the right may not be exactly equal to desktop width. */ 87 | Assert::IsTrue(desktopSize.width == reconstructedDesktopWidth || desktopSize.width == reconstructedDesktopWidth + 1); 88 | 89 | /* The "remainder" on the bottom may not be exactly equal to desktop height. */ 90 | Assert::IsTrue(desktopSize.height == reconstructedDesktopHeight || desktopSize.height == reconstructedDesktopHeight + 1); 91 | } 92 | else 93 | { 94 | Assert::AreEqual(desktopSize.width, reconstructedDesktopWidth); 95 | Assert::AreEqual(desktopSize.height, reconstructedDesktopHeight); 96 | } 97 | } 98 | 99 | TEST_METHOD(TestRenderRectsAreGoodForStandardDesktopSizes) 100 | { 101 | auto standardDesktopSizes = d2dx::Metrics::GetStandardDesktopSizes(); 102 | for (uint32_t i = 0; i < standardDesktopSizes.capacity; ++i) 103 | { 104 | AssertThatGameSizeIsIntegerScale(standardDesktopSizes.items[i], false, false); 105 | AssertThatGameSizeIsIntegerScale(standardDesktopSizes.items[i], true, false); 106 | } 107 | } 108 | 109 | TEST_METHOD(TestRenderRectsAreGoodForNonStandardDesktopSizes) 110 | { 111 | for (int32_t width = 50; width < 1600; ++width) 112 | { 113 | AssertThatGameSizeIsIntegerScale({ width, 503 }, false, true); 114 | AssertThatGameSizeIsIntegerScale({ width, 503 }, true, true); 115 | } 116 | for (int32_t height = 50; height < 1600; ++height) 117 | { 118 | AssertThatGameSizeIsIntegerScale({ 614, height }, false, true); 119 | AssertThatGameSizeIsIntegerScale({ 614, height }, true, true); 120 | } 121 | } 122 | }; 123 | } 124 | -------------------------------------------------------------------------------- /src/d2dxtests/TestSimd.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include 21 | #include "CppUnitTest.h" 22 | #include "../d2dx/Utils.h" 23 | 24 | using namespace Microsoft::WRL; 25 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 26 | using namespace d2dx; 27 | 28 | namespace d2dxtests 29 | { 30 | TEST_CLASS(TestSimd) 31 | { 32 | public: 33 | TEST_METHOD(FindUInt64) 34 | { 35 | alignas(64) std::array items; 36 | 37 | for (uint64_t i = 0; i < 1024; ++i) 38 | { 39 | items[i] = 1023ull - i; 40 | } 41 | 42 | Assert::AreEqual(0, IndexOfUInt64(items.data(), items.size(), 1023)); 43 | Assert::AreEqual(1023, IndexOfUInt64(items.data(), items.size(), 0)); 44 | Assert::AreEqual(1009, IndexOfUInt64(items.data(), items.size(), 14)); 45 | Assert::AreEqual(114, IndexOfUInt64(items.data(), items.size(), 909)); 46 | } 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /src/d2dxtests/TestTextureCache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | #include "pch.h" 20 | #include 21 | #include "CppUnitTest.h" 22 | 23 | #include "../d2dx/Batch.h" 24 | #include "../d2dx/Types.h" 25 | #include "../d2dx/TextureCache.h" 26 | 27 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 28 | using namespace d2dx; 29 | 30 | namespace d2dxtests 31 | { 32 | TEST_CLASS(TestTextureCache) 33 | { 34 | public: 35 | TEST_METHOD(CreateAtlas) 36 | { 37 | for (int32_t h = 3; h <= 8; ++h) 38 | { 39 | for (int32_t w = 3; w <= 8; ++w) 40 | { 41 | auto textureCache = std::make_unique( 42 | 1 << w, 1 << h, 1024, 512, (ID3D11Device*)nullptr); 43 | } 44 | } 45 | } 46 | 47 | TEST_METHOD(FindNonExistentTexture) 48 | { 49 | auto textureCache = std::make_unique(256, 128, 2048, 512, (ID3D11Device*)nullptr); 50 | auto tcl = textureCache->FindTexture(0x12345678, -1); 51 | Assert::AreEqual((int16_t)-1, tcl._textureAtlas); 52 | Assert::AreEqual((int16_t)-1, tcl._textureIndex); 53 | } 54 | 55 | TEST_METHOD(InsertAndFindTextures) 56 | { 57 | auto tmuData = std::make_unique>(); 58 | 59 | Batch batch; 60 | batch.SetTextureStartAddress(0); 61 | batch.SetTextureSize(256, 128); 62 | 63 | auto textureCache = std::make_unique(256, 128, 64, 512, (ID3D11Device*)nullptr); 64 | 65 | for (uint64_t i = 0; i < 64; ++i) 66 | { 67 | uint64_t hash = (0xFFull << 24) | (i << 16) | (i << 8) | i; 68 | textureCache->InsertTexture(hash, batch, (const uint8_t*)tmuData->data(), (uint32_t)tmuData->size()); 69 | } 70 | 71 | for (uint64_t i = 0; i < 64; ++i) 72 | { 73 | uint64_t hash = (0xFFull << 24) | (i << 16) | (i << 8) | i; 74 | auto tcl = textureCache->FindTexture(hash, -1); 75 | Assert::AreEqual((int16_t)0, tcl._textureAtlas); 76 | Assert::AreEqual((int16_t)i, tcl._textureIndex); 77 | } 78 | } 79 | 80 | TEST_METHOD(FirstInsertedTextureIsReplaced) 81 | { 82 | auto tmuData = std::make_unique>(); 83 | 84 | Batch batch; 85 | batch.SetTextureStartAddress(0); 86 | batch.SetTextureSize(256, 128); 87 | 88 | auto textureCache = std::make_unique(256, 128, 64, 512, (ID3D11Device*)nullptr); 89 | 90 | for (uint64_t i = 0; i < 65; ++i) 91 | { 92 | uint64_t hash = (0xFFull << 24) | (i << 16) | (i << 8) | i; 93 | auto tcl = textureCache->InsertTexture(hash, batch, (const uint8_t*)tmuData->data(), (uint32_t)tmuData->size()); 94 | 95 | if (i == 64) 96 | { 97 | Assert::AreEqual((int16_t)0, tcl._textureAtlas); 98 | Assert::AreEqual((int16_t)0, tcl._textureIndex); 99 | } 100 | else 101 | { 102 | Assert::AreEqual((int16_t)0, tcl._textureAtlas); 103 | Assert::AreEqual((int16_t)i, tcl._textureIndex); 104 | } 105 | } 106 | 107 | for (uint64_t i = 0; i < 64; ++i) 108 | { 109 | uint64_t hash = (0xFFull << 24) | (i << 16) | (i << 8) | i; 110 | auto tcl = textureCache->FindTexture(hash, -1); 111 | 112 | int16_t expectedTextureAtlas = 0; 113 | int16_t expectedTextureIndex = i; 114 | 115 | if (i == 0) 116 | { 117 | expectedTextureAtlas = -1; 118 | expectedTextureIndex = -1; 119 | } 120 | else if (i == 64) 121 | { 122 | expectedTextureIndex = 0; 123 | } 124 | 125 | Assert::AreEqual(expectedTextureAtlas, tcl._textureAtlas); 126 | Assert::AreEqual(expectedTextureIndex, tcl._textureIndex); 127 | } 128 | } 129 | 130 | TEST_METHOD(SecondInsertedTextureIsReplacedIfFirstOneWasUsedInFrame) 131 | { 132 | auto tmuData = std::make_unique>(); 133 | 134 | Batch batch; 135 | batch.SetTextureStartAddress(0); 136 | batch.SetTextureSize(256, 128); 137 | 138 | auto textureCache = std::make_unique(256, 128, 64, 512, (ID3D11Device*)nullptr); 139 | 140 | for (uint64_t i = 0; i < 65; ++i) 141 | { 142 | uint64_t hash = (0xFFull << 24) | (i << 16) | (i << 8) | i; 143 | 144 | if (i == 64) 145 | { 146 | // Simulate new frame and use of texture in slot 0 147 | textureCache->OnNewFrame(); 148 | auto tcl = textureCache->FindTexture(0xFF000000, -1); 149 | Assert::AreEqual((int16_t)0, tcl._textureAtlas); 150 | Assert::AreEqual((int16_t)0, tcl._textureIndex); 151 | } 152 | 153 | auto tcl = textureCache->InsertTexture(hash, batch, (const uint8_t*)tmuData->data(), (uint32_t)tmuData->size()); 154 | 155 | if (i == 64) 156 | { 157 | Assert::AreEqual((int16_t)0, tcl._textureAtlas); 158 | Assert::AreEqual((int16_t)1, tcl._textureIndex); 159 | } 160 | else 161 | { 162 | Assert::AreEqual((int16_t)0, tcl._textureAtlas); 163 | Assert::AreEqual((int16_t)i, tcl._textureIndex); 164 | } 165 | } 166 | 167 | for (uint64_t i = 0; i < 64; ++i) 168 | { 169 | uint64_t hash = (0xFFull << 24) | (i << 16) | (i << 8) | i; 170 | auto tcl = textureCache->FindTexture(hash, -1); 171 | 172 | int16_t expectedTextureAtlas = 0; 173 | int16_t expectedTextureIndex = i; 174 | 175 | if (i == 1) 176 | { 177 | expectedTextureAtlas = -1; 178 | expectedTextureIndex = -1; 179 | } 180 | else if (i == 64) 181 | { 182 | expectedTextureIndex = 1; 183 | } 184 | 185 | Assert::AreEqual(expectedTextureAtlas, tcl._textureAtlas); 186 | Assert::AreEqual(expectedTextureIndex, tcl._textureIndex); 187 | } 188 | } 189 | }; 190 | } 191 | -------------------------------------------------------------------------------- /src/d2dxtests/d2dxtests.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {0657af1f-16df-48e5-8bb7-323129c7f9a9} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | d2dx 14 | 15 | 16 | d2dx 17 | 18 | 19 | d2dx 20 | 21 | 22 | d2dx 23 | 24 | 25 | 26 | d2dx 27 | 28 | 29 | 30 | d2dx 31 | 32 | 33 | 34 | 35 | d2dx 36 | 37 | 38 | d2dx 39 | 40 | 41 | d2dx 42 | 43 | 44 | d2dx 45 | 46 | 47 | d2dx 48 | 49 | 50 | d2dx 51 | 52 | 53 | d2dx 54 | 55 | 56 | d2dx 57 | 58 | 59 | d2dx 60 | 61 | 62 | d2dx 63 | 64 | 65 | d2dx 66 | 67 | 68 | d2dx 69 | 70 | 71 | d2dx 72 | 73 | 74 | d2dx 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/d2dxtests/d2dxtests.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/d2dxtests/pch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of D2DX. 3 | 4 | Copyright (C) 2021 Bolrog 5 | 6 | D2DX is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | D2DX is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with D2DX. If not, see . 18 | */ 19 | 20 | #include "pch.h" 21 | -------------------------------------------------------------------------------- /thirdparty/detours/detours.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/detours/detours.lib -------------------------------------------------------------------------------- /thirdparty/detours/detours.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/detours/detours.pdb -------------------------------------------------------------------------------- /thirdparty/detours/detver.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Common version parameters. 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #define _USING_V110_SDK71_ 1 11 | #include "winver.h" 12 | #if 0 13 | #include 14 | #include 15 | #else 16 | #ifndef DETOURS_STRINGIFY 17 | #define DETOURS_STRINGIFY_(x) #x 18 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 19 | #endif 20 | 21 | #define VER_FILEFLAGSMASK 0x3fL 22 | #define VER_FILEFLAGS 0x0L 23 | #define VER_FILEOS 0x00040004L 24 | #define VER_FILETYPE 0x00000002L 25 | #define VER_FILESUBTYPE 0x00000000L 26 | #endif 27 | #define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS) 28 | -------------------------------------------------------------------------------- /thirdparty/detours/syelog.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Detours Test Program (syelog.h of syelog.lib) 4 | // 5 | // Microsoft Research Detours Package 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | #pragma once 10 | #ifndef _SYELOGD_H_ 11 | #define _SYELOGD_H_ 12 | #include 13 | 14 | #pragma pack(push, 1) 15 | #pragma warning(push) 16 | #pragma warning(disable: 4200) 17 | 18 | ////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // 21 | #define SYELOG_PIPE_NAMEA "\\\\.\\pipe\\syelog" 22 | #define SYELOG_PIPE_NAMEW L"\\\\.\\pipe\\syelog" 23 | #ifdef UNICODE 24 | #define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEW 25 | #else 26 | #define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEA 27 | #endif 28 | 29 | ////////////////////////////////////////////////////////////////////////////// 30 | // 31 | #define SYELOG_MAXIMUM_MESSAGE 4086 // 4096 - sizeof(header stuff) 32 | 33 | typedef struct _SYELOG_MESSAGE 34 | { 35 | USHORT nBytes; 36 | BYTE nFacility; 37 | BYTE nSeverity; 38 | DWORD nProcessId; 39 | FILETIME ftOccurance; 40 | BOOL fTerminate; 41 | CHAR szMessage[SYELOG_MAXIMUM_MESSAGE]; 42 | } SYELOG_MESSAGE, *PSYELOG_MESSAGE; 43 | 44 | 45 | // Facility Codes. 46 | // 47 | #define SYELOG_FACILITY_KERNEL 0x10 // OS Kernel 48 | #define SYELOG_FACILITY_SECURITY 0x20 // OS Security 49 | #define SYELOG_FACILITY_LOGGING 0x30 // OS Logging-internal 50 | #define SYELOG_FACILITY_SERVICE 0x40 // User-mode system daemon 51 | #define SYELOG_FACILITY_APPLICATION 0x50 // User-mode application 52 | #define SYELOG_FACILITY_USER 0x60 // User self-generated. 53 | #define SYELOG_FACILITY_LOCAL0 0x70 // Locally defined. 54 | #define SYELOG_FACILITY_LOCAL1 0x71 // Locally defined. 55 | #define SYELOG_FACILITY_LOCAL2 0x72 // Locally defined. 56 | #define SYELOG_FACILITY_LOCAL3 0x73 // Locally defined. 57 | #define SYELOG_FACILITY_LOCAL4 0x74 // Locally defined. 58 | #define SYELOG_FACILITY_LOCAL5 0x75 // Locally defined. 59 | #define SYELOG_FACILITY_LOCAL6 0x76 // Locally defined. 60 | #define SYELOG_FACILITY_LOCAL7 0x77 // Locally defined. 61 | #define SYELOG_FACILITY_LOCAL8 0x78 // Locally defined. 62 | #define SYELOG_FACILITY_LOCAL9 0x79 // Locally defined. 63 | 64 | // Severity Codes. 65 | // 66 | #define SYELOG_SEVERITY_FATAL 0x00 // System is dead. 67 | #define SYELOG_SEVERITY_ALERT 0x10 // Take action immediately. 68 | #define SYELOG_SEVERITY_CRITICAL 0x20 // Critical condition. 69 | #define SYELOG_SEVERITY_ERROR 0x30 // Error 70 | #define SYELOG_SEVERITY_WARNING 0x40 // Warning 71 | #define SYELOG_SEVERITY_NOTICE 0x50 // Significant condition. 72 | #define SYELOG_SEVERITY_INFORMATION 0x60 // Informational 73 | #define SYELOG_SEVERITY_AUDIT_FAIL 0x66 // Audit Failed 74 | #define SYELOG_SEVERITY_AUDIT_PASS 0x67 // Audit Succeeeded 75 | #define SYELOG_SEVERITY_DEBUG 0x70 // Debugging 76 | 77 | // Logging Functions. 78 | // 79 | VOID SyelogOpen(PCSTR pszIdentifier, BYTE nFacility); 80 | VOID Syelog(BYTE nSeverity, PCSTR pszMsgf, ...); 81 | VOID SyelogV(BYTE nSeverity, PCSTR pszMsgf, va_list args); 82 | VOID SyelogClose(BOOL fTerminate); 83 | 84 | #pragma warning(pop) 85 | #pragma pack(pop) 86 | 87 | #endif // _SYELOGD_H_ 88 | // 89 | ///////////////////////////////////////////////////////////////// End of File. 90 | -------------------------------------------------------------------------------- /thirdparty/detours/syelog.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/detours/syelog.lib -------------------------------------------------------------------------------- /thirdparty/fnv/fnv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fnv - Fowler/Noll/Vo- hash code 3 | * 4 | * @(#) $Revision: 5.4 $ 5 | * @(#) $Id: fnv.h,v 5.4 2009/07/30 22:49:13 chongo Exp $ 6 | * @(#) $Source: /usr/local/src/cmd/fnv/RCS/fnv.h,v $ 7 | * 8 | *** 9 | * 10 | * Fowler/Noll/Vo- hash 11 | * 12 | * The basis of this hash algorithm was taken from an idea sent 13 | * as reviewer comments to the IEEE POSIX P1003.2 committee by: 14 | * 15 | * Phong Vo (http://www.research.att.com/info/kpv/) 16 | * Glenn Fowler (http://www.research.att.com/~gsf/) 17 | * 18 | * In a subsequent ballot round: 19 | * 20 | * Landon Curt Noll (http://www.isthe.com/chongo/) 21 | * 22 | * improved on their algorithm. Some people tried this hash 23 | * and found that it worked rather well. In an EMail message 24 | * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. 25 | * 26 | * FNV hashes are designed to be fast while maintaining a low 27 | * collision rate. The FNV speed allows one to quickly hash lots 28 | * of data while maintaining a reasonable collision rate. See: 29 | * 30 | * http://www.isthe.com/chongo/tech/comp/fnv/index.html 31 | * 32 | * for more details as well as other forms of the FNV hash. 33 | * 34 | *** 35 | * 36 | * NOTE: The FNV-0 historic hash is not recommended. One should use 37 | * the FNV-1 hash instead. 38 | * 39 | * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the 40 | * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str(). 41 | * 42 | * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the 43 | * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str(). 44 | * 45 | * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the 46 | * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str(). 47 | * 48 | * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the 49 | * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str(). 50 | * 51 | * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the 52 | * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str(). 53 | * 54 | * To use the recommended 64 bit FNV-1a hash, pass FNV1A_64_INIT as the 55 | * Fnv64_t hashval argument to fnv_64a_buf() or fnv_64a_str(). 56 | * 57 | *** 58 | * 59 | * Please do not copyright this code. This code is in the public domain. 60 | * 61 | * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 62 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 63 | * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR 64 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 65 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 66 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 67 | * PERFORMANCE OF THIS SOFTWARE. 68 | * 69 | * By: 70 | * chongo /\oo/\ 71 | * http://www.isthe.com/chongo/ 72 | * 73 | * Share and Enjoy! :-) 74 | */ 75 | 76 | #if !defined(__FNV_H__) 77 | #define __FNV_H__ 78 | 79 | #include 80 | #include 81 | 82 | #define FNV_VERSION "5.0.2" /* @(#) FNV Version */ 83 | 84 | 85 | /* 86 | * 32 bit FNV-0 hash type 87 | */ 88 | typedef uint32_t Fnv32_t; 89 | 90 | /* 91 | * 32 bit FNV-1 and FNV-1a non-zero initial basis 92 | * 93 | * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets: 94 | * 95 | * chongo /\../\ 96 | * 97 | * NOTE: The \'s above are not back-slashing escape characters. 98 | * They are literal ASCII backslash 0x5c characters. 99 | * 100 | * NOTE: The FNV-1a initial basis is the same value as FNV-1 by definition. 101 | */ 102 | #define FNV1_32_INIT ((Fnv32_t)0x01000193) 103 | #define FNV1_32A_INIT FNV1_32_INIT 104 | 105 | /* 106 | * external functions 107 | */ 108 | 109 | /* hash_32a.c */ 110 | extern Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hashval); 111 | extern Fnv32_t fnv_32a_str(char *buf, Fnv32_t hashval); 112 | 113 | #endif /* __FNV_H__ */ 114 | -------------------------------------------------------------------------------- /thirdparty/fnv/hash_32a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hash_32 - 32 bit Fowler/Noll/Vo FNV-1a hash code 3 | * 4 | * @(#) $Revision: 5.1 $ 5 | * @(#) $Id: hash_32a.c,v 5.1 2009/06/30 09:13:32 chongo Exp $ 6 | * @(#) $Source: /usr/local/src/cmd/fnv/RCS/hash_32a.c,v $ 7 | * 8 | *** 9 | * 10 | * Fowler/Noll/Vo hash 11 | * 12 | * The basis of this hash algorithm was taken from an idea sent 13 | * as reviewer comments to the IEEE POSIX P1003.2 committee by: 14 | * 15 | * Phong Vo (http://www.research.att.com/info/kpv/) 16 | * Glenn Fowler (http://www.research.att.com/~gsf/) 17 | * 18 | * In a subsequent ballot round: 19 | * 20 | * Landon Curt Noll (http://www.isthe.com/chongo/) 21 | * 22 | * improved on their algorithm. Some people tried this hash 23 | * and found that it worked rather well. In an EMail message 24 | * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. 25 | * 26 | * FNV hashes are designed to be fast while maintaining a low 27 | * collision rate. The FNV speed allows one to quickly hash lots 28 | * of data while maintaining a reasonable collision rate. See: 29 | * 30 | * http://www.isthe.com/chongo/tech/comp/fnv/index.html 31 | * 32 | * for more details as well as other forms of the FNV hash. 33 | *** 34 | * 35 | * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the 36 | * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str(). 37 | * 38 | *** 39 | * 40 | * Please do not copyright this code. This code is in the public domain. 41 | * 42 | * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 43 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 44 | * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR 45 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 46 | * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 47 | * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 48 | * PERFORMANCE OF THIS SOFTWARE. 49 | * 50 | * By: 51 | * chongo /\oo/\ 52 | * http://www.isthe.com/chongo/ 53 | * 54 | * Share and Enjoy! :-) 55 | */ 56 | #include "fnv.h" 57 | 58 | 59 | /* 60 | * 32 bit magic FNV-1a prime 61 | */ 62 | #define FNV_32_PRIME ((Fnv32_t)0x01000193) 63 | 64 | 65 | /* 66 | * fnv_32a_buf - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a buffer 67 | * 68 | * input: 69 | * buf - start of buffer to hash 70 | * len - length of buffer in octets 71 | * hval - previous hash value or 0 if first call 72 | * 73 | * returns: 74 | * 32 bit hash as a static hash type 75 | * 76 | * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the 77 | * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str(). 78 | */ 79 | Fnv32_t 80 | fnv_32a_buf(void *buf, size_t len, Fnv32_t hval) 81 | { 82 | unsigned char *bp = (unsigned char *)buf; /* start of buffer */ 83 | unsigned char *be = bp + len; /* beyond end of buffer */ 84 | 85 | /* 86 | * FNV-1a hash each octet in the buffer 87 | */ 88 | while (bp < be) { 89 | 90 | /* xor the bottom with the current octet */ 91 | hval ^= (Fnv32_t)*bp++; 92 | 93 | /* multiply by the 32 bit FNV magic prime mod 2^32 */ 94 | #if defined(NO_FNV_GCC_OPTIMIZATION) 95 | hval *= FNV_32_PRIME; 96 | #else 97 | hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24); 98 | #endif 99 | } 100 | 101 | /* return our new hash value */ 102 | return hval; 103 | } 104 | 105 | 106 | /* 107 | * fnv_32a_str - perform a 32 bit Fowler/Noll/Vo FNV-1a hash on a string 108 | * 109 | * input: 110 | * str - string to hash 111 | * hval - previous hash value or 0 if first call 112 | * 113 | * returns: 114 | * 32 bit hash as a static hash type 115 | * 116 | * NOTE: To use the recommended 32 bit FNV-1a hash, use FNV1_32A_INIT as the 117 | * hval arg on the first call to either fnv_32a_buf() or fnv_32a_str(). 118 | */ 119 | Fnv32_t 120 | fnv_32a_str(char *str, Fnv32_t hval) 121 | { 122 | unsigned char *s = (unsigned char *)str; /* unsigned string */ 123 | 124 | /* 125 | * FNV-1a hash each octet in the buffer 126 | */ 127 | while (*s) { 128 | 129 | /* xor the bottom with the current octet */ 130 | hval ^= (Fnv32_t)*s++; 131 | 132 | /* multiply by the 32 bit FNV magic prime mod 2^32 */ 133 | #if defined(NO_FNV_GCC_OPTIMIZATION) 134 | hval *= FNV_32_PRIME; 135 | #else 136 | hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24); 137 | #endif 138 | } 139 | 140 | /* return our new hash value */ 141 | return hval; 142 | } 143 | -------------------------------------------------------------------------------- /thirdparty/fnv/license.txt: -------------------------------------------------------------------------------- 1 | This is the reference implementation of the FNV hash algorithm. 2 | It is placed in the public domain by the authors. 3 | 4 | See: http://www.isthe.com/chongo/tech/comp/fnv/index.html#public_domain 5 | 6 | -------------------------------------------------------------------------------- /thirdparty/glide3/3DFX.H: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 1995, 3Dfx Interactive, Inc. 3 | ** All Rights Reserved. 4 | ** 5 | ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; 6 | ** the contents of this file may not be disclosed to third parties, copied or 7 | ** duplicated in any form, in whole or in part, without the prior written 8 | ** permission of 3Dfx Interactive, Inc. 9 | ** 10 | ** RESTRICTED RIGHTS LEGEND: 11 | ** Use, duplication or disclosure by the Government is subject to restrictions 12 | ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data 13 | ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or 14 | ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 15 | ** rights reserved under the Copyright Laws of the United States. 16 | ** 17 | ** $Revision: 9 $ 18 | ** $Date: 12/23/97 9:57a $ 19 | */ 20 | #ifndef __3DFX_H__ 21 | #define __3DFX_H__ 22 | 23 | /* 24 | ** basic data types 25 | */ 26 | typedef unsigned char FxU8; 27 | typedef signed char FxI8; 28 | typedef unsigned short FxU16; 29 | typedef signed short FxI16; 30 | typedef signed long FxI32; 31 | typedef unsigned long FxU32; 32 | typedef int FxBool; 33 | typedef float FxFloat; 34 | typedef double FxDouble; 35 | 36 | /* 37 | ** color types 38 | */ 39 | typedef unsigned long FxColor_t; 40 | typedef struct { float r, g, b, a; } FxColor4; 41 | 42 | /* 43 | ** fundamental types 44 | */ 45 | #define FXTRUE 1 46 | #define FXFALSE 0 47 | 48 | /* 49 | ** helper macros 50 | */ 51 | #define FXUNUSED( a ) ((void)(a)) 52 | #define FXBIT( i ) ( 1L << (i) ) 53 | 54 | /* 55 | ** export macros 56 | */ 57 | 58 | #if defined(__MSC__) 59 | # if defined (MSVC16) 60 | # define FX_ENTRY 61 | # define FX_CALL 62 | # else 63 | # define FX_ENTRY __declspec(dllexport) 64 | # define FX_CALL __stdcall 65 | # endif 66 | #elif defined(__WATCOMC__) 67 | # define FX_ENTRY extern 68 | # define FX_CALL __stdcall 69 | #elif defined (__IBMC__) || defined (__IBMCPP__) 70 | /* IBM Visual Age C/C++: */ 71 | # define FX_ENTRY extern 72 | # define FX_CALL __stdcall 73 | #elif defined(__DJGPP__) 74 | # define FX_ENTRY extern 75 | # define FX_CALL 76 | #elif defined(__unix__) 77 | # define FX_ENTRY extern 78 | # define FX_CALL 79 | #elif defined(__MWERKS__) 80 | # if macintosh 81 | # define FX_ENTRY extern 82 | # define FX_CALL 83 | # else /* !macintosh */ 84 | # error "Unknown MetroWerks target platform" 85 | # endif /* !macintosh */ 86 | #else 87 | # warning define FX_ENTRY & FX_CALL for your compiler 88 | # define FX_ENTRY extern 89 | # define FX_CALL 90 | #endif 91 | 92 | /* 93 | ** x86 compiler specific stuff 94 | */ 95 | #if defined(__BORLANDC_) 96 | # define REALMODE 97 | 98 | # define REGW( a, b ) ((a).x.b) 99 | # define REGB( a, b ) ((a).h.b) 100 | # define INT86( a, b, c ) int86(a,b,c) 101 | # define INT86X( a, b, c, d ) int86x(a,b,c,d) 102 | 103 | # define RM_SEG( a ) FP_SEG( a ) 104 | # define RM_OFF( a ) FP_OFF( a ) 105 | #elif defined(__WATCOMC__) 106 | # undef FP_SEG 107 | # undef FP_OFF 108 | 109 | # define REGW( a, b ) ((a).w.b) 110 | # define REGB( a, b ) ((a).h.b) 111 | # define INT86( a, b, c ) int386(a,b,c) 112 | # define INT86X( a, b, c, d ) int386x(a,b,c,d) 113 | 114 | # define RM_SEG( a ) ( ( ( ( FxU32 ) (a) ) & 0x000F0000 ) >> 4 ) 115 | # define RM_OFF( a ) ( ( FxU16 ) (a) ) 116 | #endif 117 | 118 | #endif /* !__3DFX_H__ */ 119 | -------------------------------------------------------------------------------- /thirdparty/glide3/FXDLL.H: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 1995, 1996, 3Dfx Interactive, Inc. 3 | ** All Rights Reserved. 4 | ** 5 | ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; 6 | ** the contents of this file may not be disclosed to third parties, copied or 7 | ** duplicated in any form, in whole or in part, without the prior written 8 | ** permission of 3Dfx Interactive, Inc. 9 | ** 10 | ** RESTRICTED RIGHTS LEGEND: 11 | ** Use, duplication or disclosure by the Government is subject to restrictions 12 | ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data 13 | ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or 14 | ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 15 | ** rights reserved under the Copyright Laws of the United States. 16 | ** 17 | ** $Revision: 9 $ 18 | ** $Date: 7/24/98 1:37p $ 19 | */ 20 | /* preprocessor defines for libraries to support DLL creation */ 21 | 22 | /* in header file, use FX_ENTRY return-type FX_CALL function-name ( ... ) */ 23 | /* in source file, use FX_EXPORT return-type FX_CSTYLE function-name (... ) */ 24 | 25 | /* in source file, set FX_DLL_DEFINITION, include this file, then include 26 | header file for library. */ 27 | 28 | /* we need to use two macros per declaration/definition because MSVC 29 | requires __stdcall and __declspec( dllexport ) be in different parts 30 | of the prototype! */ 31 | 32 | /* I use two sets in case we need to control declarations and definitions 33 | differently. If it turns out we don't, it should be easy to do a search 34 | and replace to eliminate one set */ 35 | 36 | /* NOTE: this header file may be included more than once, and FX_DLL_DEFINITION 37 | may have changed, so we do not protect this with an #fndef __FXDLL_H__ 38 | statement like we normally would. */ 39 | 40 | 41 | #ifdef FX_ENTRY 42 | #undef FX_ENTRY 43 | #endif 44 | 45 | #ifdef FX_CALL 46 | #undef FX_CALL 47 | #endif 48 | 49 | #ifdef FX_EXPORT 50 | #undef FX_EXPORT 51 | #endif 52 | 53 | #ifdef FX_CSTYLE 54 | #undef FX_CSTYLE 55 | #endif 56 | 57 | #if defined(FX_DLL_DEFINITION) 58 | #if defined(FX_DLL_ENABLE) 59 | #if defined(__MSC__) 60 | #ifndef KERNEL 61 | #define FX_ENTRY __declspec( dllexport ) 62 | #define FX_EXPORT __declspec( dllexport ) 63 | #else 64 | #define FX_ENTRY 65 | #define FX_EXPORT 66 | #endif /* #ifndef KERNEL */ 67 | #define FX_CALL __stdcall 68 | #define FX_CSTYLE __stdcall 69 | 70 | #elif defined(__WATCOMC__) 71 | #define FX_ENTRY 72 | #define FX_CALL __stdcall __export 73 | 74 | #define FX_EXPORT 75 | #define FX_CSTYLE __stdcall __export 76 | 77 | #else /* compiler */ 78 | #error define FX_ENTRY,FX_CALL & FX_EXPORT,FX_CSTYLE for your compiler 79 | #endif /* compiler */ 80 | 81 | #else /* FX_DLL_ENABLE */ 82 | #define FX_ENTRY 83 | #define FX_CALL __stdcall 84 | 85 | #define FX_EXPORT 86 | #define FX_CSTYLE __stdcall 87 | #endif /* FX_DLL_ENABLE */ 88 | 89 | #else /* FX_DLL_DEFINITION */ 90 | #define FX_ENTRY extern 91 | #define FX_CALL __stdcall 92 | #endif /* FX_DLL_DEFINITION */ 93 | 94 | /* 95 | * We don't want any of this DLL junk for DJGPP or UNIX 96 | * so undo what is done above. 97 | */ 98 | #if defined(__DJGPP__) || defined(__unix__) 99 | #ifdef FX_CALL 100 | #undef FX_CALL 101 | #endif 102 | 103 | #ifdef FX_CSTYLE 104 | #undef FX_CSTYLE 105 | #endif 106 | 107 | #ifdef FX_EXPORT 108 | #undef FX_EXPORT 109 | #endif 110 | 111 | #ifdef FX_ENTRY 112 | #undef FX_ENTRY 113 | #endif 114 | 115 | #define FX_CALL 116 | #define FX_CSTYLE 117 | #define FX_EXPORT 118 | #define FX_ENTRY 119 | #endif 120 | 121 | #if defined (MSVC16) 122 | #undef FX_CALL 123 | #define FX_CALL 124 | #endif 125 | 126 | -------------------------------------------------------------------------------- /thirdparty/glide3/FXGLOB.H: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 1995, 3Dfx Interactive, Inc. 3 | ** All Rights Reserved. 4 | ** 5 | ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; 6 | ** the contents of this file may not be disclosed to third parties, copied or 7 | ** duplicated in any form, in whole or in part, without the prior written 8 | ** permission of 3Dfx Interactive, Inc. 9 | ** 10 | ** RESTRICTED RIGHTS LEGEND: 11 | ** Use, duplication or disclosure by the Government is subject to restrictions 12 | ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data 13 | ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or 14 | ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 15 | ** rights reserved under the Copyright Laws of the United States. 16 | ** 17 | ** $ Revision: $ 18 | ** $ Date: $ 19 | ** 20 | */ 21 | 22 | 23 | #ifndef _FXGLOB_H_ 24 | #define _FXGLOB_H_ 25 | 26 | 27 | void fxGlobify( int *argc, char ***argv ); 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /thirdparty/glide3/FXOS.H: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 1995, 3Dfx Interactive, Inc. 3 | ** All Rights Reserved. 4 | ** 5 | ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; 6 | ** the contents of this file may not be disclosed to third parties, copied or 7 | ** duplicated in any form, in whole or in part, without the prior written 8 | ** permission of 3Dfx Interactive, Inc. 9 | ** 10 | ** RESTRICTED RIGHTS LEGEND: 11 | ** Use, duplication or disclosure by the Government is subject to restrictions 12 | ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data 13 | ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or 14 | ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 15 | ** rights reserved under the Copyright Laws of the United States. 16 | ** 17 | ** $ Revision: $ 18 | ** $ Date: $ 19 | ** 20 | */ 21 | 22 | 23 | #ifndef _FXOS_H_ 24 | #define _FXOS_H_ 25 | 26 | #include 27 | 28 | # ifdef __cplusplus 29 | extern "C" { 30 | # endif 31 | 32 | # ifdef WIN32 33 | void sleep(int secs); 34 | #define gethostname fxGethostname 35 | 36 | int gethostname(char *name, int namelen); 37 | 38 | # endif 39 | 40 | float fxTime(void); 41 | float timer(int flag); 42 | 43 | FILE *fxFopenPath(const char *filename, const char *mode, 44 | const char *path, const char **pprefix); 45 | 46 | # ifdef __cplusplus 47 | } 48 | # endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /thirdparty/glide3/SST1VID.H: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 1995, 3Dfx Interactive, Inc. 3 | ** All Rights Reserved. 4 | ** 5 | ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; 6 | ** the contents of this file may not be disclosed to third parties, copied or 7 | ** duplicated in any form, in whole or in part, without the prior written 8 | ** permission of 3Dfx Interactive, Inc. 9 | ** 10 | ** RESTRICTED RIGHTS LEGEND: 11 | ** Use, duplication or disclosure by the Government is subject to restrictions 12 | ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data 13 | ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or 14 | ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 15 | ** rights reserved under the Copyright Laws of the United States. 16 | ** 17 | ** $Header: /devel/cvg/incsrc/SST1VID.H 6 7/24/98 1:41p Hohn $ 18 | ** $Log: /devel/cvg/incsrc/SST1VID.H $ 19 | ** 20 | ** 6 7/24/98 1:41p Hohn 21 | ** 22 | ** 5 3/10/98 2:33p Psmith 23 | ** separating cvg tree from h3/h4 trees 24 | * 25 | * 4 9/09/97 7:35p Sellers 26 | * Added 400x300 resolution 27 | * 28 | * 3 8/24/97 9:31a Sellers 29 | * moved new video timing to sst1vid.h 30 | * redefined 1600x1280 to be 1600x1200 31 | * 32 | * 2 6/05/97 11:14p Pgj 33 | * 34 | * 5 7/24/96 3:43p Sellers 35 | * added 512x384 @ 60 Hz for arcade monitors 36 | * added 512x256 @ 60 Hz for arcade monitors 37 | * 38 | * 4 7/18/96 10:58a Sellers 39 | * fixed FT and TF clock delay values for lower frequencies with 40 | * .5/.5 combos 41 | * 42 | * 3 6/18/96 6:54p Sellers 43 | * added sst1InitShutdownSli() to fix Glide Splash screen problems with 44 | * SLI 45 | * 46 | * 2 6/13/96 7:45p Sellers 47 | * added "voodoo.ini" support 48 | * added DirectX support 49 | * misc cleanup 50 | * 51 | * 2 6/11/96 1:43p Sellers 52 | * added support for 60, 75, 85, and 120 Hz refresh rates for "most" 53 | * resolutions 54 | * 55 | * 1 5/08/96 5:43p Paik 56 | * Video definitions 57 | */ 58 | #ifndef __SST1VID_H__ 59 | #define __SST1VID_H__ 60 | 61 | #ifdef __cplusplus 62 | extern "C" { 63 | #endif 64 | 65 | /* Video defines */ 66 | 67 | typedef FxI32 GrScreenRefresh_t; 68 | #define GR_REFRESH_60Hz 0x0 69 | #define GR_REFRESH_70Hz 0x1 70 | #define GR_REFRESH_72Hz 0x2 71 | #define GR_REFRESH_75Hz 0x3 72 | #define GR_REFRESH_80Hz 0x4 73 | #define GR_REFRESH_90Hz 0x5 74 | #define GR_REFRESH_100Hz 0x6 75 | #define GR_REFRESH_85Hz 0x7 76 | #define GR_REFRESH_120Hz 0x8 77 | #define GR_REFRESH_NONE 0xff 78 | 79 | typedef FxI32 GrScreenResolution_t; 80 | #define GR_RESOLUTION_320x200 0x0 81 | #define GR_RESOLUTION_320x240 0x1 82 | #define GR_RESOLUTION_400x256 0x2 83 | #define GR_RESOLUTION_512x384 0x3 84 | #define GR_RESOLUTION_640x200 0x4 85 | #define GR_RESOLUTION_640x350 0x5 86 | #define GR_RESOLUTION_640x400 0x6 87 | #define GR_RESOLUTION_640x480 0x7 88 | #define GR_RESOLUTION_800x600 0x8 89 | #define GR_RESOLUTION_960x720 0x9 90 | #define GR_RESOLUTION_856x480 0xa 91 | #define GR_RESOLUTION_512x256 0xb 92 | #define GR_RESOLUTION_1024x768 0xC 93 | #define GR_RESOLUTION_1280x1024 0xD 94 | #define GR_RESOLUTION_1600x1200 0xE 95 | #define GR_RESOLUTION_400x300 0xF 96 | #define GR_RESOLUTION_NONE 0xff 97 | 98 | #ifdef GR_RESOLUTION_MAX 99 | #undef GR_RESOLUTION_MAX 100 | #endif 101 | #ifdef GR_RESOLUTION_MIN 102 | #undef GR_RESOLUTION_MIN 103 | #endif 104 | #define GR_RESOLUTION_MIN GR_RESOLUTION_320x200 105 | #define GR_RESOLUTION_MAX GR_RESOLUTION_1600x1200 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif /* __SST1VID_H__ */ 112 | -------------------------------------------------------------------------------- /thirdparty/glide3/glidesys.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 1995, 3Dfx Interactive, Inc. 3 | ** All Rights Reserved. 4 | ** 5 | ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; 6 | ** the contents of this file may not be disclosed to third parties, copied or 7 | ** duplicated in any form, in whole or in part, without the prior written 8 | ** permission of 3Dfx Interactive, Inc. 9 | ** 10 | ** RESTRICTED RIGHTS LEGEND: 11 | ** Use, duplication or disclosure by the Government is subject to restrictions 12 | n** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data 13 | ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or 14 | ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 15 | ** rights reserved under the Copyright Laws of the United States. 16 | ** 17 | ** $Header: /devel/cvg/glide3/src/glidesys.h 3 7/24/98 1:41p Hohn $ 18 | ** $Log: /devel/cvg/glide3/src/glidesys.h $ 19 | ** 20 | ** 3 7/24/98 1:41p Hohn 21 | ** 22 | ** 2 6/15/98 10:50a Peter 23 | ** made csim compile time option 24 | * 25 | * 1 1/16/98 4:29p Atai 26 | * create glide 3 src 27 | * 28 | * 10 12/09/97 12:20p Peter 29 | * mac glide port 30 | * 31 | * 9 11/04/97 4:00p Dow 32 | * Banshee Mods 33 | * 34 | * 8 8/18/97 3:52p Peter 35 | * pre-hw arrival fixes/cleanup 36 | * 37 | * 7 6/02/97 4:09p Peter 38 | * Compile w/ gcc for Dural 39 | * 40 | * 6 5/27/97 1:16p Peter 41 | * Basic cvg, w/o cmd fifo stuff. 42 | * 43 | * 5 5/21/97 6:05a Peter 44 | */ 45 | #ifndef __GLIDESYS_H__ 46 | #define __GLIDESYS_H__ 47 | 48 | /* 49 | n** ----------------------------------------------------------------------- 50 | ** COMPILER/ENVIRONMENT CONFIGURATION 51 | ** ----------------------------------------------------------------------- 52 | */ 53 | 54 | /* Endianness is stored in bits [30:31] */ 55 | #define GLIDE_ENDIAN_SHIFT 30 56 | #define GLIDE_ENDIAN_LITTLE (0x1 << GLIDE_ENDIAN_SHIFT) 57 | #define GLIDE_ENDIAN_BIG (0x2 << GLIDE_ENDIAN_SHIFT) 58 | 59 | /* OS is stored in bits [0:6] */ 60 | #define GLIDE_OS_SHIFT 0 61 | #define GLIDE_OS_UNIX 0x1 62 | #define GLIDE_OS_DOS32 0x2 63 | #define GLIDE_OS_WIN32 0x4 64 | #define GLIDE_OS_MACOS 0x8 65 | #define GLIDE_OS_OS2 0x10 66 | #define GLIDE_OS_OTHER 0x40 /* For Proprietary Arcade HW */ 67 | 68 | /* Sim vs. Hardware is stored in bits [7:8] */ 69 | #define GLIDE_SST_SHIFT 7 70 | #define GLIDE_SST_SIM (0x1 << GLIDE_SST_SHIFT) 71 | #define GLIDE_SST_HW (0x2 << GLIDE_SST_SHIFT) 72 | 73 | /* Hardware Type is stored in bits [9:13] */ 74 | #define GLIDE_HW_SHIFT 9 75 | #define GLIDE_HW_SST1 (0x1 << GLIDE_HW_SHIFT) 76 | #define GLIDE_HW_SST96 (0x2 << GLIDE_HW_SHIFT) 77 | #define GLIDE_HW_H3 (0x4 << GLIDE_HW_SHIFT) 78 | #define GLIDE_HW_SST2 (0x8 << GLIDE_HW_SHIFT) 79 | #define GLIDE_HW_CVG (0x10 << GLIDE_HW_SHIFT) 80 | 81 | /* 82 | ** Make sure we handle all instances of WIN32 83 | */ 84 | #ifndef __WIN32__ 85 | # if defined (_WIN32) || defined (WIN32) || defined(__NT__) 86 | # define __WIN32__ 87 | # endif 88 | #endif 89 | 90 | /* We need two checks on the OS: one for endian, the other for OS */ 91 | /* Check for endianness */ 92 | #if defined(__IRIX__) || defined(__sparc__) || defined(MACOS) 93 | # define GLIDE_ENDIAN GLIDE_ENDIAN_BIG 94 | #else 95 | # define GLIDE_ENDIAN GLIDE_ENDIAN_LITTLE 96 | #endif 97 | 98 | /* Check for OS */ 99 | #if defined(__IRIX__) || defined(__sparc__) || defined(__linux__) 100 | # define GLIDE_OS GLIDE_OS_UNIX 101 | #elif defined(__DOS__) 102 | # define GLIDE_OS GLIDE_OS_DOS32 103 | #elif defined(__WIN32__) 104 | # define GLIDE_OS GLIDE_OS_WIN32 105 | #elif defined(macintosh) 106 | # define GLIDE_OS GLIDE_OS_MACOS 107 | #else 108 | #error "Unknown OS" 109 | #endif 110 | 111 | /* Check for Simulator vs. Hardware */ 112 | #if HAL_CSIM || HWC_CSIM 113 | # define GLIDE_SST GLIDE_SST_SIM 114 | #else 115 | # define GLIDE_SST GLIDE_SST_HW 116 | #endif 117 | 118 | /* Check for type of hardware */ 119 | #ifdef SST96 120 | # define GLIDE_HW GLIDE_HW_SST96 121 | #elif defined(H3) 122 | # define GLIDE_HW GLIDE_HW_H3 123 | #elif defined(SST2) 124 | # define GLIDE_HW GLIDE_HW_SST2 125 | #elif defined(CVG) 126 | # define GLIDE_HW GLIDE_HW_CVG 127 | #else /* Default to SST1 */ 128 | # define GLIDE_HW GLIDE_HW_SST1 129 | #endif 130 | 131 | 132 | #define GLIDE_PLATFORM (GLIDE_ENDIAN | GLIDE_OS | GLIDE_SST | GLIDE_HW) 133 | 134 | /* 135 | ** Control the number of TMUs 136 | */ 137 | #ifndef GLIDE_NUM_TMU 138 | # define GLIDE_NUM_TMU 2 139 | #endif 140 | 141 | 142 | #if ((GLIDE_NUM_TMU < 0) && (GLIDE_NUM_TMU > 3)) 143 | # error "GLIDE_NUM_TMU set to an invalid value" 144 | #endif 145 | 146 | #endif /* __GLIDESYS_H__ */ 147 | -------------------------------------------------------------------------------- /thirdparty/glide3/glideutl.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 1995, 3Dfx Interactive, Inc. 3 | ** All Rights Reserved. 4 | ** 5 | ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of 3Dfx Interactive, Inc.; 6 | ** the contents of this file may not be disclosed to third parties, copied or 7 | ** duplicated in any form, in whole or in part, without the prior written 8 | ** permission of 3Dfx Interactive, Inc. 9 | ** 10 | ** RESTRICTED RIGHTS LEGEND: 11 | ** Use, duplication or disclosure by the Government is subject to restrictions 12 | ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data 13 | ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or 14 | ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - 15 | ** rights reserved under the Copyright Laws of the United States. 16 | ** 17 | ** $Header: /devel/cvg/glide3/src/glideutl.h 4 7/24/98 1:41p Hohn $ 18 | ** $Log: /devel/cvg/glide3/src/glideutl.h $ 19 | ** 20 | ** 4 7/24/98 1:41p Hohn 21 | ** 22 | ** 3 1/30/98 4:27p Atai 23 | ** gufog* prototype 24 | ** 25 | ** 1 1/29/98 4:00p Atai 26 | * 27 | * 1 1/16/98 4:29p Atai 28 | * create glide 3 src 29 | * 30 | * 11 1/07/98 11:18a Atai 31 | * remove GrMipMapInfo and GrGC.mm_table in glide3 32 | * 33 | * 10 1/06/98 6:47p Atai 34 | * undo grSplash and remove gu routines 35 | * 36 | * 9 1/05/98 6:04p Atai 37 | * move 3df gu related data structure from glide.h to glideutl.h 38 | * 39 | * 8 12/18/97 2:13p Peter 40 | * fogTable cataclysm 41 | * 42 | * 7 12/15/97 5:52p Atai 43 | * disable obsolete glide2 api for glide3 44 | * 45 | * 6 8/14/97 5:32p Pgj 46 | * remove dead code per GMT 47 | * 48 | * 5 6/12/97 5:19p Pgj 49 | * Fix bug 578 50 | * 51 | * 4 3/05/97 9:36p Jdt 52 | * Removed guFbWriteRegion added guEncodeRLE16 53 | * 54 | * 3 1/16/97 3:45p Dow 55 | * Embedded fn protos in ifndef FX_GLIDE_NO_FUNC_PROTO 56 | */ 57 | 58 | /* Glide Utility routines */ 59 | 60 | #ifndef __GLIDEUTL_H__ 61 | #define __GLIDEUTL_H__ 62 | 63 | #ifdef __cplusplus 64 | extern "C" { 65 | #endif 66 | 67 | /* 68 | ** 3DF texture file structs 69 | */ 70 | 71 | typedef struct 72 | { 73 | FxU32 width, height; 74 | int small_lod, large_lod; 75 | GrAspectRatio_t aspect_ratio; 76 | GrTextureFormat_t format; 77 | } Gu3dfHeader; 78 | 79 | typedef struct 80 | { 81 | FxU8 yRGB[16]; 82 | FxI16 iRGB[4][3]; 83 | FxI16 qRGB[4][3]; 84 | FxU32 packed_data[12]; 85 | } GuNccTable; 86 | 87 | typedef struct { 88 | FxU32 data[256]; 89 | } GuTexPalette; 90 | 91 | typedef union { 92 | GuNccTable nccTable; 93 | GuTexPalette palette; 94 | } GuTexTable; 95 | 96 | typedef struct 97 | { 98 | Gu3dfHeader header; 99 | GuTexTable table; 100 | void *data; 101 | FxU32 mem_required; /* memory required for mip map in bytes. */ 102 | } Gu3dfInfo; 103 | 104 | #ifndef FX_GLIDE_NO_FUNC_PROTO 105 | /* 106 | ** Gamma functions 107 | */ 108 | 109 | FX_ENTRY void FX_CALL 110 | guGammaCorrectionRGB( FxFloat red, FxFloat green, FxFloat blue ); 111 | 112 | /* 113 | ** fog stuff 114 | */ 115 | FX_ENTRY float FX_CALL 116 | guFogTableIndexToW( int i ); 117 | 118 | FX_ENTRY void FX_CALL 119 | guFogGenerateExp( GrFog_t *fogtable, float density ); 120 | 121 | FX_ENTRY void FX_CALL 122 | guFogGenerateExp2( GrFog_t *fogtable, float density ); 123 | 124 | FX_ENTRY void FX_CALL 125 | guFogGenerateLinear(GrFog_t *fogtable, 126 | float nearZ, float farZ ); 127 | 128 | /* 129 | ** hi-level texture manipulation tools. 130 | */ 131 | FX_ENTRY FxBool FX_CALL 132 | gu3dfGetInfo( const char *filename, Gu3dfInfo *info ); 133 | 134 | FX_ENTRY FxBool FX_CALL 135 | gu3dfLoad( const char *filename, Gu3dfInfo *data ); 136 | 137 | #endif /* FX_GLIDE_NO_FUNC_PROTO */ 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif /* __GLIDEUTL_H__ */ 144 | -------------------------------------------------------------------------------- /thirdparty/pocketlzma/pocketlzma-LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, Robin Berg Pettersen 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /thirdparty/sgd2freeres/SGD2FreeRes - README.md: -------------------------------------------------------------------------------- 1 | # SlashGaming Diablo II Free Resolution (SGD2FreeRes) 2 | This is a project aimed at modding Diablo II to support any resolution. 3 | 4 | ## Features 5 | - Enables selecting user-specified resolutions from the Video Options menu. 6 | - Automatically adjusts the positions of inventory and UI elements, using 800x600 as a base for positions. 7 | - Allows limited customization of the UI. 8 | 9 | ## Compatibility 10 | - Supports 1.09D, 1.10, 1.12A, 1.13C, 1.13D, 1.14C, and 1.14D. 11 | - Supports multiple video modes. 12 | - Supports standard GDI mode. Resolutions are unrestricted. 13 | - Supports standard DirectDraw and Direct3D modes, restricted to "standard" resolutions. 14 | - Supports CnC-DDraw wrapper. Resolutions are unrestricted. 15 | - Supports [Sven's Glide wrapper](http://www.svenswrapper.de/english/), [nGlide](https://www.zeus-software.com/), and [D2DX](https://github.com/bolrog/d2dx) Glide wrapper. Resolutions are unrestricted. 16 | - Compatibility with select modsystems. 17 | - [PlugY](http://plugy.free.fr/en/index.html) 18 | - [D2SE](https://snej.org/forum/index2.php?topic=18954.msg459574#msg459574) 19 | 20 | ## Usage 21 | The DLL does nothing on its own and must be loaded into the game via external tools. Once loaded, the game will need to be run in order to generate the config file for the first time. Singleplayer resolutions, along with other configuration options can be configured to the preferences of the user. 22 | 23 | ## Multiplayer Use 24 | Multiplayer use is restricted to certain gateways. This cannot be changed easily and prevents unintentional abuse where it is not allowed (i.e. Battle.net). If used in unpermitted environments, the resolution is hardcoded to run with only 640x480 or 800x600. It is also still possible to be detected by anti-cheat systems and be banned for unauthorized modification of the game client, even if the functionality is ineffective. Where it is permitted, the resolutions are preset for the server. 25 | 26 | Any server owner that wishes to authorize the usage of SGD2FreeRes on their server should contact Mir Drualga on the SlashDiablo Discord. 27 | 28 | Servers that permit SGD2FreeRes: 29 | - [Diablo 09](https://www.diablo09.com/): 640x480, 800x600, 856x480, 1068x600 30 | - [SlashDiablo](https://slashdiablo.net/): 640x480, 800x600, 856x480, 1068x600 31 | - [Resurgence](https://resurgence.slashgaming.net/): 640x480, 800x600, 856x480, 1068x600 32 | - [Project Diablo 2](https://www.projectdiablo2.com/): 640x480, 800x600, 856x480, 1068x600 33 | - [D2LOD.NET](http://d2lod.net/): 640x480, 800x600, 856x480, 1024x768, 1068x600 34 | - And more... 35 | 36 | ## Contribution 37 | SGD2FreeRes is coded in C++20. It currently is intended to compile with Visual Studio 2019. 38 | 39 | When you submit a pull request, you certify that the code in the pull request is AGPLv3+ compatible. You also certify that you have authorization to submit the pull request with the code changes. You certify that the merging of the pull request with those changes is authorized under the license terms of the AGPLv3+. Finally, you certify that the contribution is licensed under the AGPLv3+. 40 | 41 | ## Thanks 42 | - [/r/SlashDiablo](https://www.reddit.com/r/slashdiablo/): The community that got me started. The whole reason the project took off. 43 | - [PhrozenKeep](https://d2mods.info/): Community with plenty of information on Diablo II, modding, and resources. 44 | - [bolrog](https://github.com/bolrog): For providing an extended API to enable interfacing with the D2DX Glide wrapper. 45 | - [Jarcho](https://github.com/Jarcho): For adding support for 1.10 and 1.12A. 46 | - Szumigajowy: For supplying the starting point for the tile culling boundary patch. 47 | - Necrolis: All-round code editing genius. Provides good advice. 48 | 49 | ## Legal 50 | The project is licensed under the terms of the Affero General Public License, version 3 or higher, with exceptions. Components may be licensed under other terms, so check LICENSE for more details. If you wish to apply for a proprietary license exception, please contact Mir Drualga on the SlashDiablo Discord channel. 51 | 52 | Diablo II and Diablo II: Lord of Destruction are registered trademarks of Blizzard Entertainment. This project is not affiliated with Blizzard Entertainment in any way. 53 | -------------------------------------------------------------------------------- /thirdparty/sgd2freeres/SGD2FreeRes.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/sgd2freeres/SGD2FreeRes.dll -------------------------------------------------------------------------------- /thirdparty/sgd2freeres/SGD2FreeRes.dll.lzma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/sgd2freeres/SGD2FreeRes.dll.lzma -------------------------------------------------------------------------------- /thirdparty/sgd2freeres/SGD2FreeRes.mpq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/sgd2freeres/SGD2FreeRes.mpq -------------------------------------------------------------------------------- /thirdparty/sgd2freeres/SGD2FreeRes.mpq.lzma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/sgd2freeres/SGD2FreeRes.mpq.lzma -------------------------------------------------------------------------------- /thirdparty/toml/toml.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jarcho/d2dx/1dc55a4af96f0a3921d8fe2d764ca2f56cf434d2/thirdparty/toml/toml.c -------------------------------------------------------------------------------- /thirdparty/xxhash/CHANGELOG: -------------------------------------------------------------------------------- 1 | v0.8.1 2 | - perf : much improved performance for XXH3 streaming variants, notably on gcc and msvc 3 | - perf : improved XXH64 speed and latency on small inputs 4 | - perf : small XXH32 speed and latency improvement on small inputs of random size 5 | - perf : minor stack usage improvement for XXH32 and XXH64 6 | - api : new experimental variants XXH3_*_withSecretandSeed() 7 | - api : update XXH3_generateSecret(), can no generate secret of any size (>= XXH3_SECRET_SIZE_MIN) 8 | - cli : xxhsum can now generate and check XXH3 checksums, using command `-H3` 9 | - build: can build xxhash without XXH3, with new build macro XXH_NO_XXH3 10 | - build: fix xxh_x86dispatch build with MSVC, by @apankrat 11 | - build: XXH_INLINE_ALL can always be used safely, even after XXH_NAMESPACE or a previous XXH_INLINE_ALL 12 | - build: improved PPC64LE vector support, by @mpe 13 | - install: fix pkgconfig, by @ellert 14 | - install: compatibility with Haiku, by @Begasus 15 | - doc : code comments made compatible with doxygen, by @easyaspi314 16 | - misc : XXH_ACCEPT_NULL_INPUT_POINTER is no longer necessary, all functions can accept NULL input pointers, as long as size == 0 17 | - misc : complete refactor of CI tests on Github Actions, offering much larger coverage, by @t-mat 18 | - misc : xxhsum code base split into multiple specialized units, within directory cli/, by @easyaspi314 19 | 20 | v0.8.0 21 | - api : stabilize XXH3 22 | - cli : xxhsum can parse BSD-style --check lines, by @WayneD 23 | - cli : `xxhsum -` accepts console input, requested by @jaki 24 | - cli : xxhsum accepts -- separator, by @jaki 25 | - cli : fix : print correct default algo for symlinked helpers, by @martinetd 26 | - install: improved pkgconfig script, allowing custom install locations, requested by @ellert 27 | 28 | v0.7.4 29 | - perf: automatic vector detection and selection at runtime (`xxh_x86dispatch.h`), initiated by @easyaspi314 30 | - perf: added AVX512 support, by @gzm55 31 | - api : new: secret generator `XXH_generateSecret()`, suggested by @koraa 32 | - api : fix: XXH3_state_t is movable, identified by @koraa 33 | - api : fix: state is correctly aligned in AVX mode (unlike `malloc()`), by @easyaspi314 34 | - api : fix: streaming generated wrong values in some combination of random ingestion lengths, reported by @WayneD 35 | - cli : fix unicode print on Windows, by @easyaspi314 36 | - cli : can `-c` check file generated by sfv 37 | - build: `make DISPATCH=1` generates `xxhsum` and `libxxhash` with runtime vector detection (x86/x64 only) 38 | - install: cygwin installation support 39 | - doc : Cryptol specification of XXH32 and XXH64, by @weaversa 40 | 41 | v0.7.3 42 | - perf: improved speed for large inputs (~+20%) 43 | - perf: improved latency for small inputs (~10%) 44 | - perf: s390x Vectorial code, by @easyaspi314 45 | - cli: improved support for Unicode filenames on Windows, thanks to @easyaspi314 and @t-mat 46 | - api: `xxhash.h` can now be included in any order, with and without `XXH_STATIC_LINKING_ONLY` and `XXH_INLINE_ALL` 47 | - build: xxHash's implementation transferred into `xxhash.h`. No more need to have `xxhash.c` in the `/include` directory for `XXH_INLINE_ALL` to work 48 | - install: created pkg-config file, by @bket 49 | - install: VCpkg installation instructions, by @LilyWangL 50 | - doc: Highly improved code documentation, by @easyaspi314 51 | - misc: New test tool in `/tests/collisions`: brute force collision tester for 64-bit hashes 52 | 53 | v0.7.2 54 | - Fixed collision ratio of `XXH128` for some specific input lengths, reported by @svpv 55 | - Improved `VSX` and `NEON` variants, by @easyaspi314 56 | - Improved performance of scalar code path (`XXH_VECTOR=0`), by @easyaspi314 57 | - `xxhsum`: can generate 128-bit hashes with the `-H2` option (note: for experimental purposes only! `XXH128` is not yet frozen) 58 | - `xxhsum`: option `-q` removes status notifications 59 | 60 | v0.7.1 61 | - Secret first: the algorithm computation can be altered by providing a "secret", which is any blob of bytes, of size >= `XXH3_SECRET_SIZE_MIN`. 62 | - `seed` is still available, and acts as a secret generator 63 | - updated `ARM NEON` variant by @easyaspi314 64 | - Streaming implementation is available 65 | - Improve compatibility and performance with Visual Studio, with help from @aras-p 66 | - Better integration when using `XXH_INLINE_ALL`: do not pollute host namespace, use its own macros, such as `XXH_ASSERT()`, `XXH_ALIGN`, etc. 67 | - 128-bit variant provides helper functions for comparison of hashes. 68 | - Better `clang` generation of `rotl` instruction, thanks to @easyaspi314 69 | - `XXH_REROLL` build macro to reduce binary size, by @easyaspi314 70 | - Improved `cmake` script, by @Mezozoysky 71 | - Full benchmark program provided in `/tests/bench` 72 | -------------------------------------------------------------------------------- /thirdparty/xxhash/LICENSE: -------------------------------------------------------------------------------- 1 | xxHash Library 2 | Copyright (c) 2012-2020 Yann Collet 3 | All rights reserved. 4 | 5 | BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, this 14 | list of conditions and the following disclaimer in the documentation and/or 15 | other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /thirdparty/xxhash/xxhash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * xxHash - Extremely Fast Hash algorithm 3 | * Copyright (C) 2012-2020 Yann Collet 4 | * 5 | * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following disclaimer 15 | * in the documentation and/or other materials provided with the 16 | * distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * You can contact the author at: 31 | * - xxHash homepage: https://www.xxhash.com 32 | * - xxHash source repository: https://github.com/Cyan4973/xxHash 33 | */ 34 | 35 | 36 | /* 37 | * xxhash.c instantiates functions defined in xxhash.h 38 | */ 39 | 40 | #define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ 41 | #define XXH_IMPLEMENTATION /* access definitions */ 42 | 43 | #include "xxhash.h" 44 | -------------------------------------------------------------------------------- /toml-LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 CK Tan 4 | https://github.com/cktan/tomlc99 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | --------------------------------------------------------------------------------