ReShade
A generic post-processing injector for games and video software.
reshade.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2021 Patrick Mours
3  * SPDX-License-Identifier: BSD-3-Clause OR MIT
4  */
5 
6 #pragma once
7 
8 #include "reshade_events.hpp"
9 #include "reshade_overlay.hpp"
10 #include <charconv>
11 #include <Windows.h>
12 
13 #define RESHADE_API_VERSION 5
14 
15  // Use the kernel32 variant of module enumeration functions so it can be safely called from 'DllMain'
16 extern "C" BOOL WINAPI K32EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
17 
18 namespace reshade
19 {
20  namespace internal
21  {
25  inline HMODULE &get_reshade_module_handle()
26  {
27  static HMODULE handle = nullptr;
28  if (handle == nullptr)
29  {
30  HMODULE modules[1024]; DWORD num = 0;
31  if (K32EnumProcessModules(GetCurrentProcess(), modules, sizeof(modules), &num))
32  {
33  if (num > sizeof(modules))
34  num = sizeof(modules);
35 
36  for (DWORD i = 0; i < num / sizeof(HMODULE); ++i)
37  {
38  if (GetProcAddress(modules[i], "ReShadeRegisterAddon") &&
39  GetProcAddress(modules[i], "ReShadeUnregisterAddon"))
40  {
41  handle = modules[i];
42  break;
43  }
44  }
45  }
46  }
47  return handle;
48  }
49 
53  inline HMODULE &get_current_module_handle()
54  {
55  static HMODULE handle = nullptr;
56  return handle;
57  }
58  }
59 
65  inline void log_message(int level, const char *message)
66  {
67  static const auto func = reinterpret_cast<void(*)(HMODULE, int, const char *)>(
68  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeLogMessage"));
69  func(internal::get_current_module_handle(), level, message);
70  }
71 
81  inline bool config_get_value(api::effect_runtime *runtime, const char *section, const char *key, char *value, size_t *length)
82  {
83  static const auto func = reinterpret_cast<bool(*)(HMODULE, api::effect_runtime *, const char *, const char *, char *, size_t *)>(
84  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeGetConfigValue"));
85  return func(internal::get_current_module_handle(), runtime, section, key, value, length);
86  }
87  template <typename T>
88  inline bool config_get_value(api::effect_runtime *runtime, const char *section, const char *key, T &value)
89  {
90  char value_string[32] = ""; size_t value_length = sizeof(value_string) - 1;
91  if (!config_get_value(runtime, section, key, value_string, &value_length))
92  return false;
93  return std::from_chars(value_string, value_string + value_length, value).ec == std::errc {};
94  }
95  template <>
96  inline bool config_get_value<bool>(api::effect_runtime *runtime, const char *section, const char *key, bool &value)
97  {
98  int value_int = 0;
99  if (!config_get_value<int>(runtime, section, key, value_int))
100  return false;
101  value = value_int != 0;
102  return true;
103  }
104 
112  inline void config_set_value(api::effect_runtime *runtime, const char *section, const char *key, const char *value)
113  {
114  static const auto func = reinterpret_cast<void(*)(HMODULE, api::effect_runtime *, const char *, const char *, const char *)>(
115  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeSetConfigValue"));
116  func(internal::get_current_module_handle(), runtime, section, key, value);
117  }
118  template <typename T>
119  inline void config_set_value(api::effect_runtime *runtime, const char *section, const char *key, const T &value)
120  {
121  char value_string[32] = "";
122  std::to_chars(value_string, value_string + sizeof(value_string) - 1, value);
123  config_set_value(runtime, section, key, static_cast<const char *>(value_string));
124  }
125  template <>
126  inline void config_set_value<bool>(api::effect_runtime *runtime, const char *section, const char *key, const bool &value)
127  {
128  config_set_value<int>(runtime, section, key, value ? 1 : 0);
129  }
130 
136  inline bool register_addon(HMODULE module)
137  {
139 
140  const HMODULE reshade_module = internal::get_reshade_module_handle();
141  if (reshade_module == nullptr)
142  return false;
143 
144  // Check that the ReShade module supports the used API
145  const auto func = reinterpret_cast<bool(*)(HMODULE, uint32_t)>(
146  GetProcAddress(reshade_module, "ReShadeRegisterAddon"));
147  if (!func(module, RESHADE_API_VERSION))
148  return false;
149 
150 #if defined(IMGUI_VERSION_NUM)
151  // Check that the ReShade module was built with Dear ImGui support and supports the used version
152  const auto imgui_func = reinterpret_cast<const imgui_function_table *(*)(uint32_t)>(
153  GetProcAddress(reshade_module, "ReShadeGetImGuiFunctionTable"));
154  if (imgui_func == nullptr || !(imgui_function_table_instance() = imgui_func(IMGUI_VERSION_NUM)))
155  return false;
156 #endif
157 
158  return true;
159  }
164  inline void unregister_addon(HMODULE module)
165  {
166  const HMODULE reshade_module = internal::get_reshade_module_handle();
167  if (reshade_module == nullptr)
168  return;
169 
170  const auto func = reinterpret_cast<bool(*)(HMODULE)>(
171  GetProcAddress(reshade_module, "ReShadeUnregisterAddon"));
172  func(module);
173  }
174 
180  template <reshade::addon_event ev>
181  inline void register_event(typename reshade::addon_event_traits<ev>::decl callback)
182  {
183  static const auto func = reinterpret_cast<void(*)(reshade::addon_event, void *)>(
184  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeRegisterEvent"));
185  func(ev, static_cast<void *>(callback));
186  }
191  template <reshade::addon_event ev>
192  inline void unregister_event(typename reshade::addon_event_traits<ev>::decl callback)
193  {
194  static const auto func = reinterpret_cast<void(*)(reshade::addon_event, void *)>(
195  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUnregisterEvent"));
196  func(ev, static_cast<void *>(callback));
197  }
198 
205  inline void register_overlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime))
206  {
207  static const auto func = reinterpret_cast<void(*)(const char *, void(*)(reshade::api::effect_runtime *))>(
208  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeRegisterOverlay"));
209  if (func != nullptr)
210  func(title, callback);
211  }
217  inline void unregister_overlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime))
218  {
219  static const auto func = reinterpret_cast<void(*)(const char *, void(*)(reshade::api::effect_runtime *))>(
220  GetProcAddress(internal::get_reshade_module_handle(), "ReShadeUnregisterOverlay"));
221  if (func != nullptr)
222  func(title, callback);
223  }
224 }
HMODULE & get_reshade_module_handle()
Gets the handle to the ReShade module.
Definition: reshade.hpp:25
HMODULE & get_current_module_handle()
Gets the handle to the current add-on module.
Definition: reshade.hpp:53
Definition: reshade.hpp:19
addon_event
Definition: reshade_events.hpp:13
bool config_get_value(api::effect_runtime *runtime, const char *section, const char *key, char *value, size_t *length)
Gets a value from one of ReShade's config files.
Definition: reshade.hpp:81
void config_set_value(api::effect_runtime *runtime, const char *section, const char *key, const char *value)
Sets and saves a value in one of ReShade's config files.
Definition: reshade.hpp:112
void config_set_value< bool >(api::effect_runtime *runtime, const char *section, const char *key, const bool &value)
Definition: reshade.hpp:126
void unregister_overlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime))
Unregisters an overlay that was previously registered via register_overlay.
Definition: reshade.hpp:217
bool register_addon(HMODULE module)
Registers this module as an add-on with ReShade. Call this in 'DllMain' during process attach,...
Definition: reshade.hpp:136
void unregister_event(typename reshade::addon_event_traits< ev >::decl callback)
Unregisters a callback for the specified event (via template) that was previously registered via regi...
Definition: reshade.hpp:192
void log_message(int level, const char *message)
Writes a message to ReShade's log.
Definition: reshade.hpp:65
void register_event(typename reshade::addon_event_traits< ev >::decl callback)
Registers a callback for the specified event (via template) with ReShade.
Definition: reshade.hpp:181
void unregister_addon(HMODULE module)
Unregisters this module. Call this in 'DllMain' during process detach, after any of the other API fun...
Definition: reshade.hpp:164
bool config_get_value< bool >(api::effect_runtime *runtime, const char *section, const char *key, bool &value)
Definition: reshade.hpp:96
void register_overlay(const char *title, void(*callback)(reshade::api::effect_runtime *runtime))
Registers an overlay with ReShade.
Definition: reshade.hpp:205
BOOL WINAPI K32EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded)
#define RESHADE_API_VERSION
Definition: reshade.hpp:13
A ReShade effect runtime, used to control effects.
Definition: reshade_api.hpp:39