Ronnie Moir - DirectX 9 Realtime Texture Inspector

Home

Overview

An ongoing project for a DirectX 9 realtime texture inspector using an injected hook dll and a WPF frontend.

Current Status





Process

(09/06/2026)

I first started out by creating the basic injectable dll. The main goal was to ensure that the hooks were setup correctly. I am using minhook to handle creating the trampoline functions between the real DirectX function calls and my overidden ones. I created a hook for the EndScene function and setup a basic Imgui to render.



(9/06/2026)

Next I created a hook for the CreateTexture DX function. Here I can track the creation of new textures and store pointers to them. From these pointers, I setup the imgui to draw all the loaded textures. I also at this step tested a hook for the SetTexture function. We can intercept this function to replace the incoming texture pointer with our own one. By simply loading my own custom texture and substituting it for one of the in-game textures I can manipulate which textures are drawn at runtime. With these ideas proven out, I next wanted to move away from using Imgui and instead create a WPF application to preview textures and allow the user to select replacement textures.



(10/06/2026)

One of the next big challenges at this stage was handling communication between the hook library and the C# WPF application. For this I used Named Pipes. The WPF app acts as the host, with the hook acting as the client. The server sends commands to the client and the client sends back a response.

At this stage I created two commands:

  • GetTextureList - Requests a full list of collected textures, returns metadata information like: hash, width, height and format.
  • GetTextureData - Requests the texture data for a specific texture referenced by its hash. This is used to update the texture preview on the user interface

  • Another challenge was collecting the texture data for all the created textures. In DirectX 9 textures by default are loaded directly into VRAM leaving few opportunities to intercept the data on the CPU. To bypass this I had to add some more hooks, specifically an UpdateTexture hook allows me read texture data when it is copied from CPU into GPU. Depending on the game this allows me to collect a significantly more textures, however this still does not collect all textures loaded into VRAM.

    Next steps will be to expose picking a replacement texture file to the user interface and creating a command to send that information over to the hook library. In the hook we can then create a texture and substitute it for the selected reference texture.



    (12/06/2026)

    Before fully tackling the texture replacement flow, I took the opportunity to tidy up the UI, expose useful information, and gave a way for the user to write friendly names for textures making it easier to search for them later. These aren't currently saved between runs yet, but I am planning to add a button to create/load a project folder which is where we can store information like this between sessions.



    (12/06/2026)

    For texture replacement, I added two new commands:

  • SetTextureReplacement - Sets a replacement for a texture using a file path
  • ClearTextureReplacement - Reverts a replacement of a texture

  • Upon receiving the SetTextureReplacement command, the hook library will read the texture hash and associate the replacement file path with it. In the DX SetTexture hook function we then check if the texture has a replacement associated. If it is not loaded at this stage we load it into memory and intercept the original SetTexture call with our replacement texture.

    With this I have managed to prove out the core idea of the project. However I still have some challenges I want to tackle next:
  • Introduce a project folder to persist data between runs
  • Explore new ways to hook into texture creation to have more versatile data collection
  • Allow the hook library to automatically setup its data from the project folder, loading texture replacements automatically
  • Explore creating an image classification model to automatically give friendly names to textures
  • Explore realtime editing for lights and shaders.
  • Some general UI improvements


  • (14/06/2026)

    Mostly spent time on improvements to the UI and some behind the scenes work to start supporting a project framework. I also now track load state and reference counts of images for better support of texture replacements later on. Some basic work in the hook and UI has been put in place for persisting replacements through runs which has working in early testing.



    (19/06/2026)

    I spent the last couple of days continuing the work on refactoring the UI and supporting the project framework. With this work I also fixed up some of the areas not conforming to the MVVM paradigm. Overall the project framework is now working, with the texture info saved to a file alongside any imported textures for replacements.

    The startup page for the application is now a project selection page. The other pages are locked until a project is created or loaded. The connection state to the hook is also now tracked visually on the bottom of the window.

    The textures page now has cached thumbnail previews for the textures along with some overall visual improvements.

    With the project framework we can also now save previously recorded textures and edit them even if they aren't actively loaded by the hook library. For these unloaded textures we show the thumbnail preview and give a warning to the user.

    Back to top