├── .gitignore ├── wiki ├── public │ ├── tools │ │ ├── renderdoc │ │ │ └── settings.png │ │ └── ld-for-embedding-resources │ │ │ └── msys2-setup.png │ └── beginners-guide │ │ ├── getting-started │ │ ├── new-project.png │ │ ├── profile-toolchain.png │ │ └── successful-build.png │ │ └── development-setup │ │ └── add-toolchain.png ├── index.md ├── tools │ ├── clang.md │ ├── renderdoc.md │ └── ld-for-embedding-resources.md ├── topics │ ├── gdk.md │ └── uwp.md ├── rendering │ ├── overview.md │ └── getting-started-with-directx.md ├── beginners-guide │ ├── development-setup.md │ ├── introduction.md │ ├── getting-started.md │ └── your-first-hook.md └── reverse-engineering │ ├── introduction.md │ └── using-ida.md ├── package.json ├── README.md ├── LICENSE ├── .vitepress └── config.mts └── .github └── workflows └── deploy.yml /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.vitepress/cache 3 | /.idea -------------------------------------------------------------------------------- /wiki/public/tools/renderdoc/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedrock-native-modding/wiki/HEAD/wiki/public/tools/renderdoc/settings.png -------------------------------------------------------------------------------- /wiki/public/beginners-guide/getting-started/new-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedrock-native-modding/wiki/HEAD/wiki/public/beginners-guide/getting-started/new-project.png -------------------------------------------------------------------------------- /wiki/public/tools/ld-for-embedding-resources/msys2-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedrock-native-modding/wiki/HEAD/wiki/public/tools/ld-for-embedding-resources/msys2-setup.png -------------------------------------------------------------------------------- /wiki/public/beginners-guide/development-setup/add-toolchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedrock-native-modding/wiki/HEAD/wiki/public/beginners-guide/development-setup/add-toolchain.png -------------------------------------------------------------------------------- /wiki/public/beginners-guide/getting-started/profile-toolchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedrock-native-modding/wiki/HEAD/wiki/public/beginners-guide/getting-started/profile-toolchain.png -------------------------------------------------------------------------------- /wiki/public/beginners-guide/getting-started/successful-build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bedrock-native-modding/wiki/HEAD/wiki/public/beginners-guide/getting-started/successful-build.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "test": "echo \"Error: no test specified\" && exit 1", 4 | "docs:dev": "vitepress dev", 5 | "docs:build": "vitepress build", 6 | "docs:preview": "vitepress preview" 7 | }, 8 | "devDependencies": { 9 | "vitepress": "^2.0.0-alpha.12" 10 | } 11 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bedrock Native Modding Wiki 2 | This is the source code for the Bedrock Native Modding Wiki. 3 | 4 | # Building Locally 5 | To build the wiki locally, do: 6 | 7 | - `npm install` 8 | - `npm run docs:dev` 9 | 10 | Open the localhost link in your browser to view the wiki. The site will hot reload as you edit the code. -------------------------------------------------------------------------------- /wiki/index.md: -------------------------------------------------------------------------------- 1 | ::: warning 2 | This wiki is **under construction**! Information here is subject to rapid change. 3 | ::: 4 | 5 | # Bedrock Native Modding Wiki 6 | Welcome to the Bedrock Modding Native Wiki! 7 | 8 | This wiki is a knowledge hub for making native mods for Minecraft: Bedrock Edition. 9 | 10 | The goal of this wiki is to: 11 | - Teach developers how to make native mods 12 | - Teach developers how to reverse engineer the game 13 | - Document the internal structures of the game 14 | 15 | To get started, check out the [Beginner's Guide](/beginners-guide/introduction)! -------------------------------------------------------------------------------- /wiki/tools/clang.md: -------------------------------------------------------------------------------- 1 | # Clang 2 | [Clang](https://clang.llvm.org/) is an alternative compiler to MSVC based on LLVM. For advanced users, Clang is recommended over MSVC for its superior code analysis and code generation, at the cost of increased compilation time. What makes Clang most appealing is `clang-cl`, which provides an MSVC-like front end to the compiler, effectively acting as a drop-in replacement for MSVC. 3 | 4 | When configured through `clang-cl`, Clang generates code that is mostly ABI-compatible with MSVC, which makes it viable for Bedrock mods. 5 | 6 | ## IDE Setup 7 | [JetBrains' guide for CLion](https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#clang-cl). 8 | 9 | [Microsoft's guide for Visual Studio](https://learn.microsoft.com/en-us/cpp/build/clang-support-msbuild?view=msvc-170). 10 | 11 | ## ABI Differences 12 | Clang generates different type names than MSVC. This causes EnTT to generate different hashes for component types, which means EnTT won't be ABI-compatible with Minecraft on Clang out-of-the-box. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 The Bedrock Native Modding Maintainers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /wiki/topics/gdk.md: -------------------------------------------------------------------------------- 1 | # GDK 2 | In 1.21.120, Mojang started building Minecraft with GDK, a [game development kit from Microsoft](https://learn.microsoft.com/en-us/gaming/gdk/) that replaces [UWP](/topics/uwp). 3 | 4 | Because Minecraft is no longer a UWP app, that means a few things: 5 | 6 | - The game is no longer sandboxed, meaning all Windows APIs can now work in your DLLs as expected. 7 | - WinRT APIs bound to the ApplicationView will no longer work. 8 | 9 | ## Extracting the Executable File 10 | For unknown reasons, GDK apps have their main executable files encrypted at-rest. You also can't copy the file. 11 | This makes it more difficult to extract the executable for static analysis, but fortunately the protection is pretty easy to get around. 12 | 13 | To extract the decrypted executable, use this PowerShell command to drop the executable onto your desktop: 14 | 15 | ```ps 16 | Invoke-CommandInDesktopPackage -PackageFamilyName "Microsoft.MinecraftUWP_8wekyb3d8bbwe" -AppId "Game" -Command "cmd.exe" -Args "/C copy `"$((Get-AppxPackage "Microsoft.MinecraftUWP").InstallLocation)\Minecraft.Windows.exe`" `"$ENV:USERPROFILE\Desktop\Minecraft.Windows.exe`"" 17 | ``` 18 | -------------------------------------------------------------------------------- /wiki/rendering/overview.md: -------------------------------------------------------------------------------- 1 | # Rendering Overview 2 | From version 1.16.200 onwards, Minecraft: Bedrock Edition uses a cross-platform, proprietary rendering system named RenderDragon, created in collaboration with Nvidia. Under the hood, it is an abstraction over Mojang's closed-source fork of [`bgfx`](https://github.com/bkaradzic/bgfx). When compiling for different platforms, Mojang enables the correct `bgfx` backends for each. This overview will focus on Windows and the DirectX backends. 3 | 4 | ## Backends 5 | On the Windows build of the game, Mojang includes 3 different rendering backends. Each backend supports different rendering modes within the game, and the highest backend supported by the system's GPU is enabled. 6 | 7 | | Rendering modes | Simple | Fancy | Vibrant Visuals | Ray Tracing | 8 | |------------------|--------|-------|-----------------|-------------| 9 | | DirectX 11 | ✔️ | ✔️ | ✖️ | ✖️ | 10 | | DirectX 12 | ✔️ | ✔️ | ✔️ | ✖️ | 11 | | DirectX 12 (RTX) | ✔️ | ✔️ | ✔️ | ✔️ | 12 | 13 | ## Other Rendering Abstractions 14 | On top of the base RenderDragon rendering system, Minecraft: Bedrock Edition also implements other rendering abstractions. These can include specialized entity renderers, UI rendering contexts, and tesselators. Depending on your use case, these can be more beneficial than submitting raw DirectX calls to the game. We will attempt to document as many of these as possible in the wiki. -------------------------------------------------------------------------------- /wiki/beginners-guide/development-setup.md: -------------------------------------------------------------------------------- 1 | # Development Setup 2 | 3 | This section will walk you through installing all the required tools to develop your first native Bedrock mod. 4 | 5 | ## IDE Setup 6 | 7 | We recommend you use [CLion](https://www.jetbrains.com/clion/), a free (for non-commercial use) C++ IDE. 8 | 9 | ### Creating a Visual Studio Toolchain 10 | 11 | CLion's default toolchain, MinGW, is not ABI-compatible with Minecraft. 12 | 13 | You'll need to install [Visual Studio](https://visualstudio.microsoft.com/vs/) to provide the required build tools. Install the `Desktop development with C++` package. 14 | 15 | ::: info 16 | You can also use Visual Studio as an IDE, but the beginner guide will assume you are using CLion. We are just installing Visual Studio to provide the build tools to CLion. 17 | ::: 18 | 19 | In CLion, go to **Settings** > **Build, Execution, Deployment** > **Toolchains**. 20 | Click the plus icon, and select **Visual Studio**. 21 | 22 | ![Add Toolchain](/beginners-guide/development-setup/add-toolchain.png) 23 | 24 | Click the up arrow near the plus icon to move the new toolchain up until it's at the top, and click **Apply**. 25 | 26 | Now you have a Visual Studio toolchain, which can build code that is compatible with the game's ABI. 27 | 28 | ## DLL Injector 29 | 30 | As mentioned in the [Introduction](/beginners-guide/introduction), to get your code running inside the game's process, you will build the code into a `.dll` file and inject it into the game. To do that, you'll need to install a DLL Injector. 31 | 32 | For beginners, we recommend using [Fate Injector](https://github.com/fligger/FateInjector/releases). 33 | 34 | ::: info 35 | DLL Injectors often falsely trigger anti-viruses (which is understandable, as DLL injection is sometimes used by malware). 36 | ::: -------------------------------------------------------------------------------- /wiki/topics/uwp.md: -------------------------------------------------------------------------------- 1 | # UWP 2 | Before 1.21.120, Minecraft was built with [UWP](https://learn.microsoft.com/en-us/windows/uwp/), which was Microsoft's attempt at unifying projects built for desktop Windows, Xbox, and Windows Phone under one platform. UWP is considered to be a deprecated platform (since October 2021), and was not ideal for developing games. These are possible reasons as to why Mojang decided to move the game to [GDK](/topics/gdk). 3 | 4 | ## Key differences 5 | Compared to regular Win32 apps, UWP apps: 6 | - run in a sandbox, and cannot access files outside of their application data directories by default 7 | - use WinRT exclusively instead of the regular Win32 APIs 8 | 9 | ### DLL injection 10 | When injecting your mod into UWP builds of the game, it's important that the DLL file has the `ALL_APPLICATION_PACKAGES` permission so the game can access its contents. This is why we recommend [Fate Injector](https://github.com/fligger/FateInjector/releases), as it is specifically designed for the UWP builds and applies this permission before injecting. 11 | 12 | ### WinRT vs Win32 13 | When developing for UWP, you are required to use WinRT to interface with the operating system. As a result, the WinRT APIs should be preferred over their Win32 counterparts when creating your mod, as most do not work inside of a UWP app. For example, setting the window title is much different within UWP: 14 | 15 | ```cpp 16 | // Win32, assuming UNICODE is defined 17 | #include 18 | 19 | HWND handle = FindWindow(nullptr, L"Minecraft"); 20 | SetWindowText(handle, L"My window title"); 21 | 22 | // WinRT 23 | #include 24 | using namespace winrt; 25 | using namespace Windows::UI::ViewManagement; 26 | 27 | ApplicationView::GetForCurrentView().Title(L"My window title"); 28 | ``` 29 | 30 | ::: tip 31 | Most WinRT functions must be ran on the main thread: 32 | 33 | ```cpp 34 | #include 35 | #include 36 | 37 | using namespace winrt; 38 | using namespace Windows::ApplicationModel::Core; 39 | using namespace Windows::UI::Core; 40 | 41 | CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync( 42 | CoreDispatcherPriority::Normal, []{ ... } 43 | ); 44 | ``` 45 | ::: -------------------------------------------------------------------------------- /wiki/tools/renderdoc.md: -------------------------------------------------------------------------------- 1 | # RenderDoc 2 | Whether you want to debug your own custom GUI rendering, or you just want to see how Minecraft's rendering pipeline works, 3 | RenderDoc is extremely useful for analyzing frames. Some additional setup is required to get it working for Minecraft. 4 | 5 | You can install it [here](https://renderdoc.org/). 6 | 7 | ## GDK 8 | 9 | Since GDK apps are just regular Win32 programs, you should be able to launch Minecraft directly with RenderDoc, 10 | and everything should work fine. 11 | 12 | ## UWP 13 | 14 | Prior to 1.21.120, Minecraft was a UWP app, which RenderDoc isn't designed for. 15 | You'll need some extra steps to get it working for the UWP build. 16 | 17 | ### CheckNetIsolation 18 | 19 | RenderDoc talks to the process it's attached to with a loopback network connection, which normally isn't allowed on UWP apps. 20 | 21 | To make it work, run this PowerShell command in the background as an administrator: 22 | 23 | ```ps 24 | CheckNetIsolation.exe LoopbackExempt -is -n="Microsoft.MinecraftUWP_8wekyb3d8bbwe" 25 | ``` 26 | 27 | ### Capture Directory 28 | Under **Tools** > **Settings** > **General**, set both capture directories to locations under the game's `RoamingState` folder: 29 | 30 | `C:\Users\User\AppData\Local\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\RoamingState` 31 | 32 | ![img.png](/tools/renderdoc/settings.png) 33 | 34 | ### DLL Permissions 35 | 36 | By default, UWP won't be able to load `renderdoc.dll` (see [UWP > DLL injection](/topics/uwp#dll-injection)). 37 | The easiest way to fix this is by injecting it once with a UWP DLL injector, like [Fate Injector](https://github.com/fligger/FateInjector). 38 | You can find the DLL in the installation directory of RenderDoc, eg. `C:\Program Files\RenderDoc\renderdoc.dll`. 39 | 40 | ### Configuring the Game 41 | 42 | RenderDoc needs to load before the graphics API is initialized. 43 | RenderDoc can't start UWP apps on its own, but there is a workaround for Minecraft. 44 | 45 | Hidden in `options.txt`, there is a setting called `load_renderdocdll`. 46 | Set it to 1 to reload the renderer after Minecraft is done loading. 47 | 48 | ### Actually Capturing 49 | 50 | `renderdoc.dll` can't actually detect key presses in UWP apps, so you need to do it from the RenderDoc window. -------------------------------------------------------------------------------- /.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress' 2 | 3 | // https://vitepress.dev/reference/site-config 4 | export default defineConfig({ 5 | srcDir: "wiki", 6 | title: "Bedrock Native Modding Wiki", 7 | description: "A knowledge hub for making native mods for Minecraft: Bedrock Edition", 8 | themeConfig: { 9 | // https://vitepress.dev/reference/default-theme-config 10 | nav: [ 11 | { text: 'Home', link: '/' } 12 | ], 13 | sidebar: [ 14 | { 15 | text: 'Beginner\'s Guide', 16 | collapsed: true, 17 | items: [ 18 | { text: 'Introduction', link: '/beginners-guide/introduction' }, 19 | { text: 'Development Setup', link: '/beginners-guide/development-setup' }, 20 | { text: 'Getting Started', link: '/beginners-guide/getting-started' }, 21 | { text: 'Your First Hook', link: '/beginners-guide/your-first-hook' } 22 | ] 23 | }, 24 | { 25 | text: 'Tools', 26 | collapsed: true, 27 | items: [ 28 | { text: 'Clang', link: '/tools/clang' }, 29 | { text: 'Using ld to embed resources', link: '/tools/ld-for-embedding-resources' }, 30 | { text: 'RenderDoc', link: '/tools/renderdoc' }, 31 | ] 32 | }, 33 | { 34 | text: 'Topics', 35 | collapsed: true, 36 | items: [ 37 | { text: 'GDK', link: '/topics/gdk' }, 38 | { text: 'UWP', link: '/topics/uwp' } 39 | ] 40 | }, 41 | { 42 | text: 'Rendering', 43 | collapsed: true, 44 | items: [ 45 | { text: 'Overview', link: '/rendering/overview' }, 46 | { text: 'Getting Started with DirectX', link: '/rendering/getting-started-with-directx' } 47 | ] 48 | }, 49 | { 50 | text: 'Reverse Engineering', 51 | collapsed: true, 52 | items: [ 53 | {text: 'Introduction', link:'/reverse-engineering/introduction'}, 54 | {text: 'Using IDA', link: '/reverse-engineering/using-ida'} 55 | ] 56 | 57 | } 58 | ], 59 | socialLinks: [ 60 | { icon: 'github', link: 'https://github.com/bedrock-native-modding/wiki' } 61 | ], 62 | search: { 63 | provider: 'local' 64 | }, 65 | externalLinkIcon: true, 66 | lastUpdated: true, 67 | }, 68 | base: '/wiki/' 69 | }) 70 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a VitePress site to GitHub Pages 2 | # 3 | name: Deploy VitePress site to Pages 4 | 5 | on: 6 | # Runs on pushes targeting the `main` branch. Change this to `master` if you're 7 | # using the `master` branch as the default branch. 8 | push: 9 | branches: [master, release] 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 15 | permissions: 16 | contents: read 17 | pages: write 18 | id-token: write 19 | 20 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 21 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 22 | concurrency: 23 | group: pages 24 | cancel-in-progress: false 25 | 26 | jobs: 27 | # Build job 28 | build: 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | with: 34 | fetch-depth: 0 # Not needed if lastUpdated is not enabled 35 | # - uses: pnpm/action-setup@v3 # Uncomment this block if you're using pnpm 36 | # with: 37 | # version: 9 # Not needed if you've set "packageManager" in package.json 38 | # - uses: oven-sh/setup-bun@v1 # Uncomment this if you're using Bun 39 | - name: Setup Node 40 | uses: actions/setup-node@v4 41 | with: 42 | node-version: 22 43 | cache: npm # or pnpm / yarn 44 | - name: Setup Pages 45 | uses: actions/configure-pages@v4 46 | - name: Install dependencies 47 | run: npm ci # or pnpm install / yarn install / bun install 48 | - name: Build with VitePress 49 | run: npm run docs:build # or pnpm docs:build / yarn docs:build / bun run docs:build 50 | - name: Upload artifact 51 | uses: actions/upload-pages-artifact@v3 52 | with: 53 | path: .vitepress/dist 54 | 55 | # Deployment job 56 | deploy: 57 | if: github.ref == 'refs/heads/release' 58 | environment: 59 | name: github-pages 60 | url: ${{ steps.deployment.outputs.page_url }} 61 | needs: build 62 | runs-on: ubuntu-latest 63 | name: Deploy 64 | steps: 65 | - name: Deploy to GitHub Pages 66 | id: deployment 67 | uses: actions/deploy-pages@v4 68 | -------------------------------------------------------------------------------- /wiki/beginners-guide/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Welcome to native Bedrock modding! 4 | 5 | This beginner's guide will walk you through creating your first native Bedrock mod. First, you should understand a few basic concepts about native moddding. 6 | 7 | Most articles in this wiki will assume that you understand programming, and at least have a basic understanding of C++, the language Bedrock Edition is written in. 8 | If you don't know C++, you should [learn the basics of the language first](https://learncpp.com). 9 | 10 | ## What's a Native Mod? 11 | 12 | Unlike addons, native mods directly interface with Minecraft's memory and code. This (theoretically) gives you full control over *everything* happening inside the game. 13 | 14 | ## Where Do Native Mods Run? 15 | 16 | Native Bedrock mods mostly run on Windows 10/11, on x64 processors. It's possible to mod Bedrock Edition on Android and Linux, but this is not yet documented on this wiki. 17 | 18 | This guide will only work on 64-bit Windows. 19 | 20 | ## What's a DLL? 21 | 22 | Native mods typically run their code inside the game's process (often called *internal modding*). This is done by compiling the code into a Dynamic Link Library (DLL) and injecting it into the game with a DLL injector. 23 | 24 | ## What's a Hook? 25 | 26 | Hooks are what you use to modify the game's inner workings. Most functions in the game can be hooked. When you hook a function, you redirect calls to that function to your own code, effectively replacing the function's code with your own. 27 | 28 | Hooking is usually provided by a hooking library. The recommended choices are [MinHook](https://github.com/TsudaKageyu/minhook) and [SafetyHook](https://github.com/cursey/safetyhook). 29 | MinHook is simpler and more beginner friendly, while SafetyHook has more features and a more advanced API. 30 | 31 | In this guide, we will be using MinHook. 32 | 33 | ## What's a Signature? 34 | 35 | The location of every function in Minecraft changes when the game updates; however, the machine code comprising these 36 | functions remains largely unchanged. To find functions in a way that's more likely to survive updates, we use *signatures*. 37 | 38 | Fundamentally, signatures are just patterns that match specific sequences of bytes that we want to locate. Their syntax 39 | looks like this: `48 8D 05 ? ? ? ? 49 89 04 24 49 8D 8C 24` 40 | 41 | > [!NOTE] 42 | > Signatures are also sometimes called patterns, byte patterns, or an array of bytes. 43 | 44 | 45 | ## Where Do I Start? 46 | 47 | Now that you've learned some basic concepts about native modding, you're ready to start the guide! In the next page, you'll set up an appropriate development environment. 48 | -------------------------------------------------------------------------------- /wiki/reverse-engineering/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | Reverse engineering, in the context of software engineering, is the process of deconstructing a program to understand 3 | its architecture, functionality, and original design. 4 | 5 | Reverse engineering is a very broad topic that is predominantly made up of logical thinking, 6 | however, there are many techniques and shortcuts that can be used when reversing Minecraft, with two core methods 7 | that summarize the topic: 8 | - Static Analysis 9 | - Dynamic Analysis 10 | 11 | Both of these methods will be covered and used within this section to define data structures and classes 12 | or find functions and analyze their behavior. 13 | 14 | It is subjective which method you prefer to use, and neither is better than the other, though they both have their use 15 | cases. This topic will aim to describe both static and dynamic analysis as thoroughly as possible, including 16 | scenarios where one method is more suitable. 17 | 18 | > [!NOTE] 19 | > Reverse engineering is sometimes shortened to *reversing*, or just *R.E.* 20 | 21 | ## Static Analysis 22 | Static analysis is the process of reverse engineering a program's code **without** executing it. 23 | 24 | We can statically analyze Minecraft: Bedrock Edition by using a *disassembler* to convert its compiled machine code back 25 | into human-readable assembly, and inspecting the code. 26 | 27 | > [!NOTE] 28 | > As MCBE is compiled from C++ directly into machine code that runs natively on the system, it is impossible to 29 | > decompile its code back to source code. 30 | 31 | There are many disassemblers that provide an environment for static analysis. We recommend 32 | [IDA Pro](https://hex-rays.com/ida-pro) for its robust feature set, wide use in the Bedrock native modding 33 | community, and use within this wiki. 34 | 35 | > [!NOTE] 36 | > It is not guaranteed that the [IDA Freeware](https://hex-rays.com/ida-free) distribution will provide every feature used in this wiki. 37 | > We strongly suggest that you use IDA Pro. 38 | 39 | Keep in mind, static analysis is **not** just analyzing a disassembly. There are many other resources and tools that can be 40 | used to reverse engineer Minecraft: Bedrock Edition statically, some of which will be covered. 41 | 42 | ## Dynamic Analysis 43 | Dynamic analysis is the process of examining a program's behavior **while it is executing**. 44 | 45 | There are many tools that can be used to perform dynamic analysis, for example: 46 | - [ReClass.NET](https://github.com/ReClassNET/ReClass.NET): A tool mainly used to map data structures in memory 47 | - [Cheat Engine](https://www.cheatengine.org/): A program featuring a robust set of dynamic analysis tools, 48 | namely, a memory scanner and debugger 49 | 50 | Again, it is subjective what tools you use. Every tool has its own use case; feel free to use one tool or a variety of 51 | programs you see fit. 52 | 53 | 54 | -------------------------------------------------------------------------------- /wiki/beginners-guide/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ::: info 4 | You can find the reference code for this section [here](https://github.com/bedrock-native-modding/beginners-guide-example/tree/sections/getting-started). 5 | ::: 6 | 7 | Now that you've set up your [development environment](/beginners-guide/development-setup.md), you're ready to make your first mod! 8 | 9 | Start by creating a **New Project** in CLion, and selecting **C++ Library**. Set the **Language standard** to at least C++20, and the **Library type** to shared. This will make your code compile to a `.dll` file that can be injected into the game. 10 | 11 | ![New project](/beginners-guide/getting-started/new-project.png) 12 | 13 | In the top right, you will see a dropdown labeled **Debug**. Select it, click **Edit CMake profiles...**, and make sure the **Debug** profile is using the Visual Studio toolchain you created. 14 | 15 | ![Debug toolchain](/beginners-guide/getting-started/profile-toolchain.png) 16 | 17 | ## Configuring CMake 18 | 19 | Open `CMakeLists.txt`. It should look something like this: 20 | 21 | ```cmake 22 | cmake_minimum_required(VERSION 3.31) 23 | project(project_name_here) 24 | 25 | set(CMAKE_CXX_STANDARD 20) 26 | 27 | add_library(project_name_here SHARED library.cpp) 28 | ``` 29 | 30 | Above `add_library`, add the following: 31 | 32 | ```cmake 33 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") 34 | ``` 35 | 36 | This configures your DLL to use the release runtime library, which ensures ABI compatibility (TBA!!!!!!!!!!!!!!! ADD A LINK TO THE ABI COMPATIBILITY ARTICLE RN!!!!!!!!!!!!!!!!) with the game when building in debug mode. Without this, you wouldn't be able to use standard library types like `std::string` with the game! 37 | 38 | ## Writing DllMain 39 | 40 | Right click `library.cpp` and `library.h` and click **Delete**. Right click the root folder in the project view, click **New** > **C/C++ Source File**. Name the file `dllmain.cpp`. 41 | 42 | Add the following code to `dllmain.cpp`: 43 | 44 | ```cpp 45 | #define NOMINMAX 46 | #include 47 | #include 48 | 49 | static DWORD WINAPI startup(LPVOID dll) { 50 | // The call to `std::abort` will just crash the game to show us that the DLL was injected. 51 | std::abort(); 52 | } 53 | 54 | // `DllMain` is the function that will be called by Windows when your mod is injected into the game's process. 55 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 56 | switch (fdwReason) { 57 | case DLL_PROCESS_ATTACH: 58 | // DLL_PROCESS_ATTACH means the DLL is being initialized. 59 | 60 | // We create a new thread to call `startup`. 61 | // This is necessary since we can't use most Windows APIs inside DllMain. 62 | CreateThread(nullptr, 0, &startup, hinstDLL, 0, nullptr); 63 | break; 64 | 65 | case DLL_PROCESS_DETACH: 66 | // DLL_PROCESS_DETACH means that the DLL is being ejected, 67 | // or that the game is shutting down. 68 | 69 | default: 70 | break; 71 | } 72 | 73 | return TRUE; 74 | } 75 | ``` 76 | 77 | ::: info 78 | More information about DllMain can be found [here](https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain). 79 | ::: 80 | 81 | Now, update your `CMakeLists.txt` to compile `dllmain.cpp` instead of `library.cpp`: 82 | 83 | ```cmake 84 | add_library(my_first_native_mod SHARED dllmain.cpp) 85 | ``` 86 | 87 | Finally, click the hammer icon in the top right of the IDE, and build the project! If all went well, you should see this: 88 | 89 | ![Sucessful build](/beginners-guide/getting-started/successful-build.png) 90 | 91 | Now, inject the DLL into Minecraft. If your game crashed, that means it worked! -------------------------------------------------------------------------------- /wiki/reverse-engineering/using-ida.md: -------------------------------------------------------------------------------- 1 | # Using IDA 2 | 3 | > [!TIP] 4 | > For a more in depth write-up of the basic usage of IDA, we recommend you read the official Hex-Rays article on this 5 | > topic, this can be found [here](https://docs.hex-rays.com/getting-started/basic-usage). 6 | 7 | [Hex-Rays IDA](https://hex-rays.com/ida-pro) is a powerful disassembler and reverse engineering environment, used by many in the Bedrock Native 8 | Modding community for static analysis. This article will cover how to set up your IDA environment for 9 | MCBE. 10 | 11 | > [!NOTE] 12 | > This wiki assumes you are on [IDA Pro 9.2](https://docs.hex-rays.com/release-notes/9_2), the latest as of writing. 13 | > It is not guaranteed that certain features or plugins used in this wiki support other versions of IDA. 14 | > [IDA Free](https://hex-rays.com/ida-free) is a viable alternative that supports disassembly and decompilation of 15 | > x86/x64 binaries. 16 | 17 | ## Running IDA 18 | When you run IDA, an **IDA Quickstart** window will open. 19 | 20 | In this dialog, there are four areas of interest: 21 | - **New** - This will ask you to select a file for loading. 22 | - **Go** - This will bring you to the main IDA view, in a dormant state. 23 | - **Previous** - This will load the previously loaded file. 24 | - **Recent files box** - This will display your recently opened files for quick access. 25 | 26 | Here, you can just press **Go**. 27 | 28 | ## Loading Minecraft into IDA 29 | 30 | [FloppyDolphin57](https://github.com/FloppyDolphin57) kindly provides pre-analyzed Minecraft binaries for most Minecraft Bedrock versions in the form of 31 | packed IDA databases (i64 or idb files). These databases can be downloaded 32 | [here](https://www.mediafire.com/folder/ammda8wfvbw9x/The_Flopper_Databases). 33 | 34 | Most versions include a Windows Client, Windows Server, and Linux Server database. Server versions prior to 1.21.2 35 | shipped with debug symbols, and are useful for cross-referencing code against even the latest client versions. 36 | 37 | Once you have downloaded and extracted the client version of your choice, you can simply **drag and drop the i64 file 38 | into your IDA window** to load it. 39 | 40 | If you are using a newer version of IDA than the database was created with, IDA will prompt you to upgrade to the latest 41 | supported format. This is a mandatory step and may take a while, but it only has to be done once. Once the upgrade is 42 | complete, it's recommended to immediately save the database to avoid having to do so again, should the database be 43 | improperly saved. 44 | 45 | Alternatively, you can manually analyze Minecraft by dragging and dropping the `Minecraft.Windows.exe` file from your 46 | Minecraft install into IDA. If you are analyzing a GDK version, the executable must be 47 | [extracted](/topics/gdk#extracting-the-executable-file) first. This process **will** take multiple hours. 48 | 49 | > [!NOTE] 50 | > IDA may seem to freeze when loading a database or during general use. Don't worry, as IDA is likely working in the background. 51 | 52 | At this point, Minecraft should be loaded into IDA. You can now start reversing. 53 | 54 | > [!TIP] 55 | > The database file will be available within the quickstart menu after opening it, along with other recently opened files. 56 | > You can now double-click its entry to load the database. 57 | 58 | 59 | ## Plugins 60 | IDA supports [plugins](https://docs.hex-rays.com/user-guide/plugins) to extend its capability. In the context of reverse engineering, this can be used to 61 | automate many tasks which are otherwise tedious and/or monotonous. 62 | 63 | A plugin can either come as an IDAPython script or a native binary, and may be installed by copying their respective 64 | file (`.py` or `.dll`) into the `plugins` subdirectory in IDA's installation directory. 65 | 66 | > [!WARNING] 67 | > IDA plugins can contain malware. Only install plugins from sources you trust. 68 | 69 | For efficiently creating [signatures](/beginners-guide/introduction#what-s-a-signature), it's recommended to use a 70 | plugin such as [A200K's SigMaker plugin](https://github.com/A200K/IDA-Pro-SigMaker) (Usage provided in the repository's 71 | README). 72 | -------------------------------------------------------------------------------- /wiki/beginners-guide/your-first-hook.md: -------------------------------------------------------------------------------- 1 | # Your First Hook 2 | 3 | ::: info 4 | You can find the reference code for this section [here](https://github.com/bedrock-native-modding/beginners-guide-example/tree/sections/your-first-hook). 5 | ::: 6 | 7 | Now that you have your mod working, you probably want it to do something instead of crashing the game. 8 | 9 | In this section, we will hook `Dimension::getTimeOfDay` to make time appear to pass faster. 10 | We'll need to scan a signature to find this function, and then hook the function. 11 | To do this, we'll need to add some dependency libraries. 12 | 13 | To scan signatures, we will use `libhat`, a memory hacking library that includes a fast signature scanner. 14 | 15 | For hooking, we will use `MinHook`. 16 | 17 | ## CPM 18 | [CPM](https://github.com/cpm-cmake/CPM.cmake) is a CMake library that makes it easier to add other libraries. 19 | 20 | To use it, download `CPM.cmake` from the [latest release](https://github.com/cpm-cmake/CPM.cmake/releases) and save it at `cmake/CPM.cmake` in your project's directory. 21 | 22 | Now, in your `CMakeLists.txt`, below the `CMAKE_MSVC_RUNTIME_LIBRARY` line, add the following: 23 | 24 | ```cmake 25 | include(cmake/CPM.cmake) 26 | ``` 27 | 28 | You now have CPM added to your project. 29 | 30 | ## Adding the Libraries 31 | 32 | Below the CPM line, add the following: 33 | 34 | ```cmake 35 | CPMAddPackage("gh:BasedInc/libhat@0.9.0") 36 | CPMAddPackage("gh:TsudaKageyu/minhook@1.3.4") 37 | ``` 38 | 39 | This will make CPM automatically download the libraries. To use them in your mod, you must link against them. Add the following at the bottom of your `CMakeLists.txt`: 40 | 41 | ```cmake 42 | target_link_libraries( PRIVATE 43 | libhat::libhat 44 | minhook) 45 | ``` 46 | 47 | ## Adding Your First Hook 48 | 49 | Now, we will use `libhat` to scan for `Dimension::getTimeOfDay`. As of 1.21.120, the signature for `getTimeOfDay` is `44 8B C2 B8 F1 19 76 05 F7 EA`. 50 | 51 | ```cpp 52 | #include 53 | #include 54 | 55 | static DWORD WINAPI startup(LPVOID dll) { 56 | constexpr auto signature = hat::compile_signature<"44 8B C2 B8 F1 19 76 05 F7 EA">(); 57 | 58 | hat::scan_result scanResult = hat::find_pattern(signature, ".text"); 59 | std::byte* getTimeOfDay = scanResult.get(); 60 | } 61 | ``` 62 | 63 | Next, write the detour function which `MinHook` will redirect `getTimeOfDay` to. 64 | 65 | ```cpp 66 | // MinHook will redirect Dimension::getTimeOfDay to this function, replacing its behavior with our own code. 67 | static float hk_getTimeOfDay(void* _this, int32_t time, float alpha) { 68 | static float value = 0.f; 69 | value += 0.00001f; 70 | value = std::fmodf(value, 1.f); 71 | 72 | return value; 73 | } 74 | ``` 75 | 76 | Finally, we'll initialize `MinHook` after scanning for `getTimeOfDay`, create a hook that redirects it to `hk_getTimeOfDay`, and enable that hook. 77 | Then we will exit `startup`. Because of the way DLL injection works, this will cause our client to remain injected until the game is closed. 78 | 79 | ```cpp 80 | #include 81 | 82 | static DWORD WINAPI startup(LPVOID dll) { 83 | constexpr auto signature = hat::compile_signature<"44 8B C2 B8 F1 19 76 05 F7 EA">(); 84 | 85 | hat::scan_result scanResult = hat::find_pattern(signature, ".text"); 86 | std::byte* getTimeOfDay = scanResult.get(); 87 | 88 | // Initialize MinHook. 89 | MH_Initialize(); 90 | 91 | // Hook getTimeOfDay. 92 | LPVOID original; 93 | MH_CreateHook(getTimeOfDay, &hk_getTimeOfDay, &original); 94 | MH_EnableHook(getTimeOfDay); 95 | 96 | // Exiting this thread without calling FreeLibraryAndExitThread on `dll` will cause the DLL to remain injected forever. 97 | return 0; 98 | } 99 | ``` 100 | 101 | Now build your mod again, and inject the DLL. If you see the sun and moon spinning around you, it worked! 102 | 103 | You can try changing the constant in `hk_getTimeOfDay` to make the time go faster or slower. 104 | 105 | ::: tip 106 | You can't build your mod while the DLL is injected. Close the game before building your mod again. 107 | ::: -------------------------------------------------------------------------------- /wiki/tools/ld-for-embedding-resources.md: -------------------------------------------------------------------------------- 1 | # Using `ld` to embed resources 2 | It is possible to embed your mod's resources directly into your resulting DLL file. In most cases, this is preferable over shipping these resources separately or downloading them from a server on the internet. 3 | 4 | To achieve this, we will use a tool called `ld`. 5 | 6 | ## Background 7 | `ld` is a command line tool used to link compiled objects to executables. It is part of the GNU project, and is only available on Unix-based systems as a result. However, a port for Windows exists through MinGW. We will be using [MSYS2](https://www.msys2.org/) to install MinGW. 8 | 9 | ## Installation 10 | Download the MSYS2 installer from their [official website](https://www.msys2.org/#installation). A step-by-step tutorial on how to install it exists on their website, but make sure you install MSYS2 to the default path, as this guide assumes it's installed there. 11 | 12 | ![MSYS2 Setup](/tools/ld-for-embedding-resources/msys2-setup.png) 13 | 14 | Once installed, go to your **Start menu > MSYS folder > MSYS2 MSYS**. Run this command to install MinGW via `pacman`: 15 | 16 | ```bash 17 | $ pacman -S mingw-w64-x86_64-binutils 18 | ``` 19 | 20 | The binaries for MinGW will be installed in `C:\msys64\mingw64\bin`. **You will need to add this folder to your system PATH to use it in your project.** 21 | 22 | Again, open the **Start menu**, search for **environment variables**, and select the first result. In the Control Panel menu that appears, select **"System variables..."**. Your PATH environment variable will be in the group labeled **"System variables"**. Double click this variable, and add the MinGW path to it. 23 | 24 | Ensure `ld` can be ran by running it in a terminal. The following output should appear: 25 | 26 | ```powershell 27 | PS C:\Users\User> ld.exe 28 | C:\msys64\mingw64\bin\ld.exe: no input files 29 | ``` 30 | 31 | ::: tip 32 | If you had your IDE open during installation, you must restart it so it can receive the new PATH variable. 33 | ::: 34 | 35 | You are now ready to use `ld` to embed resources. 36 | 37 | ## Integrating with CMake 38 | Using `ld` to embed resources into your mod involves invoking the tool at build time. This can be achieved with a custom CMake function, which you can add somewhere in your `CMakeLists.txt`: 39 | 40 | ```cmake 41 | function(ADD_RESOURCES out_var) 42 | set(result) 43 | foreach (in_f ${ARGN}) 44 | file(RELATIVE_PATH src_f ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${in_f}) 45 | set(out_f "${PROJECT_BINARY_DIR}/${in_f}.o") 46 | add_custom_command(OUTPUT ${out_f} 47 | COMMAND ld.exe -r -b binary -o ${out_f} ${src_f} 48 | DEPENDS ${in_f} 49 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 50 | COMMENT "Building object ${out_f}" 51 | VERBATIM 52 | ) 53 | list(APPEND result ${out_f}) 54 | endforeach() 55 | set(${out_var} "${result}" PARENT_SCOPE) 56 | endfunction() 57 | ``` 58 | 59 | The `add_resources` function is now available to use in your project, and it takes a variable as the resulting object files, followed by a list of relative paths to files you'd like to embed. For example, assuming you have a `resources` folder in your project: 60 | 61 | ```cmake 62 | add_resources(EMBEDDED_RESOURCES 63 | resources/image.png 64 | resources/Roboto.ttf 65 | ) 66 | ``` 67 | 68 | When you have a lot of files to embed, this process of adding files manually can become tedious. Luckily, this can be remedied with the `file` function: 69 | 70 | ```cmake 71 | # Recursively search for files in the 'resources' directory 72 | # and add them as resources: 73 | file(GLOB_RECURSE RESOURCES RELATIVE ${CMAKE_CURRENT_LIST_DIR} CONFIGURE_DEPENDS "resources/*") 74 | add_resources(EMBEDDED_RESOURCES ${RESOURCES}) 75 | ``` 76 | 77 | The `add_resources` function will build your resources as object files, and place them inside of the output variable you provide in the first argument. These object files must be added as sources to your project: 78 | 79 | ```cmake 80 | # Use 'target_sources' to add these object files to your project: 81 | target_sources(project_name_here PRIVATE ${EMBEDDED_RESOURCES}) 82 | 83 | # Alternatively, they can be placed within 'add_library' 84 | # alongside your project source files: 85 | add_library(project_name_here SHARED ... ${EMBEDDED_RESOURCES}) 86 | ``` 87 | 88 | Reconfigure CMake to make these embedded resources available for use within your project. 89 | 90 | ## Embedded resources in code 91 | Resources built by `ld` will create external definitions for their start and end positions in your binary. The names of these definitions are generated as follows: 92 | 93 | | Example | 94 | |:---------------------------------------------------------------------:| 95 | | resources/image.png | 96 | | ↓ | 97 | | `_binary_resources_image_png_start / _binary_resources_image_png_end` | 98 | 99 | Here, the definition begins with `_binary_`, followed by the path to your resource relative to your project root, with all non-alphanumeric characters replaced with underscores. At the end, `_start` and `_end` are added to mark the start and end positions respectfully. These definitions respect any capitalization of your resource file paths, making them case-sensitive. 100 | 101 | We can use this info to write some abstractions to reference and use the data from your resources: 102 | 103 | ```cpp 104 | #include 105 | #include 106 | #include 107 | 108 | #define LOAD_RESOURCE(x) extern "C" char _binary_resources_##x##_start, _binary_resources_##x##_end; 109 | #define GET_RESOURCE(x) Resource{&_binary_resources_##x##_start, &_binary_resources_##x##_end} 110 | 111 | struct Resource { 112 | Resource(const char* begin, const char* end) : _begin(begin), _end(end) {} 113 | [[nodiscard]] const char* data() const { return _begin; } 114 | [[nodiscard]] const char* begin() const { return _begin; } 115 | [[nodiscard]] const char* end() const { return _end; } 116 | [[nodiscard]] size_t size() const { return size_t(_end - _begin); } 117 | [[nodiscard]] std::string_view str() const { return std::string_view{this->data(), this->size()}; } 118 | [[nodiscard]] std::span bytes() const { 119 | return { 120 | reinterpret_cast(this->begin()), 121 | reinterpret_cast(this->end()) 122 | }; 123 | } 124 | private: 125 | const char* _begin; 126 | const char* _end; 127 | }; 128 | ``` 129 | 130 | ::: tip 131 | The `LOAD_RESOURCE` and `GET_RESOURCE` macros assume your resources are in a folder named `resources` in your project. You may have to edit these macros to fit your project structure. 132 | ::: 133 | 134 | Example usage in your project is as follows: 135 | 136 | ```cpp 137 | // Define the external definitions for your resources. 138 | LOAD_RESOURCE(image_png) 139 | LOAD_RESOURCE(Roboto_ttf) 140 | 141 | void loadResources() { 142 | // We can now create instances of Resource from these definitions. 143 | const Resource image = GET_RESOURCE(image_png) 144 | const Resource roboto = GET_RESOURCE(Roboto_png) 145 | 146 | // Pseudocode to load each resource: 147 | Images::load(image.data(), image.size()); 148 | Fonts::load(roboto.data(), roboto.size()); 149 | } 150 | ``` 151 | 152 | You are now familiar with embedding resources into your mod! -------------------------------------------------------------------------------- /wiki/rendering/getting-started-with-directx.md: -------------------------------------------------------------------------------- 1 | # Getting Started with DirectX 2 | In this guide, you will create hooks for various DirectX functions and create a suitable environment for rendering. 3 | 4 | ## Background 5 | Unlike most games, Minecraft attempts to use the latest version of DirectX supported by your system, instead of sticking 6 | to one version. This **must** be taken into account when hooking DirectX functions to provide the widest level of 7 | support for your mod. Specifics on each backend and their in-game render capabilities are covered 8 | [here](/rendering/overview#backends). 9 | 10 | ## Requirements 11 | To facilitate hooking DirectX functions, we will be using an updated fork of [kiero](https://github.com/BasedInc/kiero). 12 | kiero handles the boilerplate that is required to get the runtime implementations of DirectX's interfaces, and provides 13 | a type-safe API for looking up functions and creating hooks. 14 | 15 | If you have a CMake project using CPM ([setup](/beginners-guide/your-first-hook#cpm)), adding kiero is as follows: 16 | 17 | ```cmake 18 | CPMAddPackage( 19 | URI "gh:BasedInc/kiero#269860311ac04b0ee89e68f68bca55abd02a3390" # Dec 2, 2025 20 | OPTIONS 21 | "KIERO_INCLUDE_D3D11 ON" 22 | "KIERO_INCLUDE_D3D12 ON" 23 | ) 24 | ``` 25 | 26 | ::: info 27 | While the [BasedInc](https://github.com/BasedInc) fork of kiero supports many new quality-of-life features that this 28 | article leverages, it is still under active-development. The commit hash in the previous snippet reflects the version 29 | this article is based on, and usage in future versions may be subject to change. 30 | ::: 31 | 32 | In addition to kiero, you will need a hooking library. kiero offers an opt-in hooking API that can be integrated with 33 | either `MinHook` or `SafetyHook`, but it must be configured with additional options for your specific setup. 34 | Currently, 3 targets are provided: 35 | 36 | | Hook Library | CMake Target | `kiero::getMethod` | `kiero::bind` | 37 | |--------------|---------------------------|--------------------|---------------| 38 | | N/A | `kiero::kiero` | ✔️ | ✖️ | 39 | | MinHook | `kiero::kiero-minhook` | ✔️ | ✔️ | 40 | | SafetyHook | `kiero::kiero-safetyhook` | ✔️ | ✔️ | 41 | 42 | For example, using kiero if `MinHook` is already included in an existing project: 43 | 44 | ```cmake 45 | CPMAddPackage( 46 | URI # <...> 47 | OPTIONS 48 | # <...> 49 | "KIERO_BUILD_MINHOOK ON" // [!code ++] 50 | "KIERO_MINHOOK_EXTERNAL ON" # If you already have MinHook included // [!code ++] 51 | ) 52 | ``` 53 | 54 | ```cmake 55 | # Using Kiero with kiero::bind supported by MinHook 56 | target_link_libraries( PRIVATE 57 | kiero::kiero-minhook) 58 | ``` 59 | 60 | 61 | ## `IDXGISwapChain::Present` 62 | As of Direct3D 10, [`IDXGISwapChain::Present`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-present) is called by a program to display the resulting frame to the user, 63 | after all draw calls are submitted. Since Minecraft on Windows only supports Direct3D 11 and Direct3D 12 as 64 | rendering backends, this is the only function needed to submit draw calls before a frame is displayed. 65 | 66 | ### Creating the hook 67 | This is the full function prototype for `IDXGISwapChain::Present`: 68 | 69 | ```cpp 70 | HRESULT IDXGISwapChain::Present(UINT SyncInterval, UINT Flags); 71 | ``` 72 | 73 | We **must** match the ABI of this member-function prototype when creating a callback for this function hook. This 74 | requirement is enforced at compile time by `kiero::bind`: 75 | 76 | ```cpp 77 | #include 78 | 79 | using presentFunc = HRESULT(*)(IDXGISwapChain*, UINT, UINT); 80 | static presentFunc oPresent{}; 81 | ``` 82 | 83 | Next, create your function callback, making sure to match the function prototype above: 84 | 85 | ```cpp 86 | static HRESULT hk_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags) { 87 | // You can interface with DirectX here. 88 | 89 | // When you're done, call the original function to return 90 | // control to the game and display the resulting frame. 91 | return oPresent(_this, SyncInterval, Flags); 92 | } 93 | ``` 94 | 95 | Finally, we can initialize kiero and create the hook: 96 | 97 | ```cpp 98 | #include 99 | 100 | void createHooks() { 101 | if (kiero::init(kiero::RenderType::Auto) != kiero::Status::Success) { 102 | // Kiero failed to initialize, handle failure case. 103 | return; 104 | } 105 | 106 | // Kiero provides IDXGISwapChain for both D3D11 and D3D12. 107 | // We can use it to hook Present, regardless of the renderer: 108 | auto status = kiero::bind<&IDXGISwapChain::Present>(&oPresent, &hk_Present); 109 | assert(status == kiero::Status::Success); 110 | 111 | // If you are using kiero without kiero::bind support, the function's 112 | // addressed can be fetched and passed to your own hook function. 113 | auto pPresent = kiero::getMethod<&IDXGISwapChain::Present>(); 114 | my_hook_function(pPresent, &oPresent, &hk_Present); 115 | } 116 | ``` 117 | 118 | ::: info 119 | Specifics on how to draw content using DirectX is out of scope for this wiki. You can refer to other sources and 120 | tutorials on how to use DirectX. For a renderer-independent approach, it's worth considering a third-party library to do 121 | the heavy lifting. A commonly used one is [Dear ImGui](https://github.com/ocornut/imgui), which provides an interface 122 | for drawing text and geometry across many rendering backends. 123 | ::: 124 | 125 | Although `kiero::init` has resolved a renderer, it may not actually match the active renderer in use by Minecraft. This 126 | can happen if a fallback to Direct3D 11 occurs, even when the system supports Direct3D 12. We can query for which type 127 | of D3D device is in use via `IDXGISwapChain::GetDevice` in our `Present` hook: 128 | 129 | ```cpp 130 | #include 131 | #include 132 | #include 133 | #include 134 | 135 | // Required for winrt::com_ptr, which is effectively a smart-pointer type 136 | // for COM (and subsequently DirectX) objects. winrt::com_ptr uses RAII 137 | // to manage the reference count of the underlying object, so we can avoid 138 | // manual calls to AddRef() and Release(). 139 | #include 140 | 141 | static winrt::com_ptr d3d11Device; 142 | static winrt::com_ptr d3d12Device; 143 | 144 | static HRESULT hk_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags) { 145 | if (SUCCEEDED(_this->GetDevice(IID_PPV_ARGS(d3d12device.put())))) { 146 | // If this call succeeds, DirectX 12 is being used. 147 | // Do your DirectX 12-specific initialization work here. 148 | } else if (SUCCEEDED(_this->GetDevice(IID_PPV_ARGS(d3d11device.put())))) { 149 | // If this call succeeds, DirectX 11 is being used. 150 | // Do your DirectX 11-specific initialization work here. 151 | } else { 152 | // No device could be retrieved. 153 | } 154 | 155 | return oPresent(_this, SyncInterval, Flags); 156 | } 157 | ``` 158 | 159 | ::: info 160 | You can read more about `winrt::com_ptr` on [Microsoft Learn](https://learn.microsoft.com/en-us/uwp/cpp-ref-for-winrt/com-ptr). 161 | ::: 162 | 163 | ## `IDXGISwapChain::ResizeBuffers` 164 | If you've held any references to the game's back buffer(s) in your `Present` callback, your game will crash when attempting 165 | to resize the window. This is because the game is calling [`IDXGISwapChain::ResizeBuffers`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-resizebuffers), which requires 166 | all references to the swap chain's back buffers to be released before it is called (see [Remarks](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-resizebuffers#remarks)). 167 | 168 | ```cpp 169 | HRESULT IDXGISwapChain::ResizeBuffers( 170 | UINT BufferCount, 171 | UINT Width, 172 | UINT Height, 173 | DXGI_FORMAT NewFormat, 174 | UINT SwapChainFlags 175 | ); 176 | ``` 177 | 178 | This issue can be resolved with another function hook: 179 | ```cpp 180 | using resizeBuffersFunc = HRESULT(*)(IDXGISwapChain*, 181 | UINT, UINT, UINT, DXGI_FORMAT, UINT); 182 | static resizeBuffersFunc oResizeBuffers{}; 183 | 184 | // Possible outstanding reference 185 | static winrt::com_ptr backBufferRTV; 186 | 187 | static HRESULT hk_ResizeBuffers( 188 | IDXGISwapChain* _this, UINT BufferCount, UINT Width, 189 | UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags 190 | ) { 191 | // Release reference(s) 192 | backBufferRTV = nullptr; 193 | 194 | // Finish resizing 195 | return oResizeBuffers(_this, BufferCount, Width, 196 | Height, NewFormat, SwapChainFlags); 197 | } 198 | 199 | void createHooks() { 200 | // ... 201 | kiero::bind<&IDXGISwapChain::ResizeBuffers>( 202 | &oResizeBuffers, &hk_ResizeBuffers); 203 | } 204 | ``` 205 | 206 | ::: info 207 | As of Minecraft 1.21.120 (the initial GDK release), the [`IDXGISwapChain3::ResizeBuffers1`](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_4/nf-dxgi1_4-idxgiswapchain3-resizebuffers1) 208 | extension is called instead of `ResizeBuffers`. The prototype and bind target must be updated accordingly. 209 | ::: 210 | --------------------------------------------------------------------------------