Compare commits

..

5 Commits
pr316 ... pr320

Author SHA1 Message Date
icex2
8b82b32894 feat: Integrate frame time performance graph into iidxhook 1-8
Integrate the previously created frame time graph component
into iidxhook 1 to 8. iidxhook9 uses d3d9ex which still requires
a separate hook implementation for imgui.

Guard the feature with a switch as it might have some performance
impact and it’s something that is only required to be turned on
when needed.
2025-02-07 15:19:02 +01:00
icex2
8efeb68c75 feat: Add frame time performance graph imgui overlay
A overlay window showing the a frame time graph with
the current frame time, ~10 seconds of history as well
as reference lines for the current avg. and a configurable
target frame time.

This is considered a debug tool to support in any efforts
that are related to understanding current frame times
of the games. More specifically this can be used to asses
impact of any bemanitools hooking to the game’s main
(render) loop.
2025-02-07 15:14:25 +01:00
icex2
d482acd533 feat: Add bt d3d9 hook specific imgui overlay
For now, we focus on internal overlays for bemanitools
that hook into an existing d3d9 context. The current
abstraction is fairly thin and should be fine as a start.

Implementations are called “components” and hook
up with a single frame_update function to execute
and logic and drawing updates with imgui
2025-02-07 15:12:21 +01:00
icex2
8d49bd8f40 fix: Add missing hook_table_revert function
The function signature was already defined in the header
but the implementation in the module missing
2025-02-07 15:10:31 +01:00
icex2
d977a0bf35 feat: Integrate imgui library, squash to initial integration
Version 1.91.7 of the imgui library with the cimgui wrapper.

imgui allows us to easily create minimal and powerful UI for
use-cases like in-game overlays or separate tooling.

The additional wrappers cimgui_impl_dx9 and cimgui_impl_win32
were added to provide a full C linkage integration for the rest
of the code base.

Tweaks to the makefile were kept to a minimum but enable
compilation of C++ since imgui is C++ based.

Remark: At this point bemanitools itself is still to be kept a pure
C codebase. Due to the lack of proper module/library management
with the current build system in bemanitools 5, proper separation
of concerns and clean integration with external libraries isn’t
possible with reasonable effort.


Summary:

Test Plan:
2025-02-07 15:10:31 +01:00
21 changed files with 143 additions and 0 deletions

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) # Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO)
eamuse.card_type=C02 eamuse.card_type=C02

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) # Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO)
eamuse.card_type=D01 eamuse.card_type=D01

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) # Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO)
eamuse.card_type=E11 eamuse.card_type=E11

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) # Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO)
eamuse.card_type=ECO eamuse.card_type=ECO

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO) # Magnetic card type, format XXX, 3 digit string (supports: C02, D01, E11, ECO)
eamuse.card_type=C02 eamuse.card_type=C02

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. # URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80 eamuse.server=localhost:80

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. # URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80 eamuse.server=localhost:80

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. # URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80 eamuse.server=localhost:80

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80. # URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
eamuse.server=localhost:80 eamuse.server=localhost:80

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# PCBID # PCBID
eamuse.pcbid=0101020304050607086F eamuse.pcbid=0101020304050607086F

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# PCBID # PCBID
eamuse.pcbid=0101020304050607086F eamuse.pcbid=0101020304050607086F

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -1,3 +1,6 @@
# Enable frame performance graph overlay
debug.enable_frame_perf_graph=false
# Run the game in a framed window (requires windowed option) # Run the game in a framed window (requires windowed option)
gfx.framed=false gfx.framed=false

View File

@@ -15,12 +15,21 @@ static const size_t apiset_prefix_len = sizeof(apiset_prefix) - 1;
static void hook_table_apply_to_all( static void hook_table_apply_to_all(
const char *depname, const struct hook_symbol *syms, size_t nsyms); const char *depname, const struct hook_symbol *syms, size_t nsyms);
static void hook_table_revert_to_all(
const char *depname, const struct hook_symbol *syms, size_t nsyms);
static void hook_table_apply_to_iid( static void hook_table_apply_to_iid(
HMODULE target, HMODULE target,
const pe_iid_t *iid, const pe_iid_t *iid,
const struct hook_symbol *syms, const struct hook_symbol *syms,
size_t nsyms); size_t nsyms);
static void hook_table_revert_to_iid(
HMODULE target,
const pe_iid_t *iid,
const struct hook_symbol *syms,
size_t nsyms);
static bool hook_table_match_module( static bool hook_table_match_module(
HMODULE target, const char *iid_name, const char *depname); HMODULE target, const char *iid_name, const char *depname);
@@ -44,6 +53,23 @@ static void hook_table_apply_to_all(
} }
} }
static void hook_table_revert_to_all(
const char *depname, const struct hook_symbol *syms, size_t nsyms)
{
const peb_dll_t *dll;
HMODULE pe;
for (dll = peb_dll_get_first(); dll != NULL; dll = peb_dll_get_next(dll)) {
pe = peb_dll_get_base(dll);
if (pe == NULL) {
continue; /* ?? Happens sometimes. */
}
hook_table_revert(pe, depname, syms, nsyms);
}
}
void hook_table_apply( void hook_table_apply(
HMODULE target, HMODULE target,
const char *depname, const char *depname,
@@ -73,6 +99,35 @@ void hook_table_apply(
} }
} }
void hook_table_revert(
HMODULE target,
const char *depname,
const struct hook_symbol *syms,
size_t nsyms)
{
const pe_iid_t *iid;
const char *iid_name;
assert(depname != NULL);
assert(syms != NULL || nsyms == 0);
if (target == NULL) {
/* Call out, which will then call us back repeatedly. Awkward, but
viewed from the outside it's good for usability. */
hook_table_revert_to_all(depname, syms, nsyms);
} else {
for (iid = pe_iid_get_first(target); iid != NULL;
iid = pe_iid_get_next(target, iid)) {
iid_name = pe_iid_get_name(target, iid);
if (hook_table_match_module(target, iid_name, depname)) {
hook_table_revert_to_iid(target, iid, syms, nsyms);
}
}
}
}
static void hook_table_apply_to_iid( static void hook_table_apply_to_iid(
HMODULE target, HMODULE target,
const pe_iid_t *iid, const pe_iid_t *iid,
@@ -101,6 +156,34 @@ static void hook_table_apply_to_iid(
} }
} }
static void hook_table_revert_to_iid(
HMODULE target,
const pe_iid_t *iid,
const struct hook_symbol *syms,
size_t nsyms)
{
struct pe_iat_entry iate;
size_t i;
size_t j;
const struct hook_symbol *sym;
i = 0;
while (pe_iid_get_iat_entry(target, iid, i++, &iate) == S_OK) {
for (j = 0; j < nsyms; j++) {
sym = &syms[j];
if (hook_table_match_proc(&iate, sym)) {
// Only revert-able if the original pointer was stored
// previously
if (sym->link != NULL && *sym->link != NULL) {
pe_patch(iate.ppointer, sym->link, sizeof(*sym->link));
}
}
}
}
}
static bool hook_table_match_module( static bool hook_table_match_module(
HMODULE target, const char *iid_name, const char *depname) HMODULE target, const char *iid_name, const char *depname)
{ {