Add session markers for chat and raw combat logs

Write CHAT_SESSION and COMBATLOG_SESSION markers on first write to each
log type. Raw combat log handle address captured dynamically from
SuperWoW's InitializeLogBuffer call.
This commit is contained in:
MarcelineVQ
2026-03-04 14:01:29 -08:00
parent 5768c50868
commit ddd4c9681d
+43 -21
View File
@@ -99,8 +99,15 @@ var g_session_realm_len: usize = 0;
/// True once paths have been configured for this login session.
var g_paths_configured: bool = false;
/// Session marker written flag.
var g_session_marker_written: bool = false;
/// Per-log-type session marker flags.
var g_combat_marker_written: bool = false;
var g_chat_marker_written: bool = false;
var g_raw_marker_written: bool = false;
/// Raw combat log handle address — captured from initLogDetour when SuperWoW
/// calls InitializeLogBuffer for WoWRawCombatLog. We don't know this address
/// statically; SuperWoW passes it as handle_out.
var g_raw_combat_handle_addr: u32 = 0;
/// Saved original path pointers for restoration.
var g_original_combat_path_ptr: u32 = 0;
@@ -375,6 +382,7 @@ fn initLogDetour(file_path: u32, flags: u32, handle_out: u32) callconv(sc) u32 {
}
if (g_raw_combat_path_len > 0 and std.mem.endsWith(u8, path_span, "WoWRawCombatLog.txt")) {
g_raw_combat_handle_addr = handle_out; // capture SuperWoW's handle address
con.fmt("[combatlog] redirect: {s} -> {s}\n", .{ path_span, g_raw_combat_path[0..g_raw_combat_path_len] });
return init_log_hook.callOriginal(.{ @intFromPtr(&g_raw_combat_path), flags, handle_out });
}
@@ -388,7 +396,7 @@ fn initLogDetour(file_path: u32, flags: u32, handle_out: u32) callconv(sc) u32 {
}
// =============================================================================
// WriteFormattedLogMessage hook — inject session marker on first combat write
// WriteFormattedLogMessage hook — inject session markers on first write per log
// =============================================================================
var write_log_hook: hook.Detour(fn (u32, u32, u32) callconv(sc) void) = .{};
@@ -396,24 +404,37 @@ var write_log_hook: hook.Detour(fn (u32, u32, u32) callconv(sc) void) = .{};
fn writeLogDetour(handle: u32, fmt: u32, va_list: u32) callconv(sc) void {
asm volatile ("" ::: .{ .esi = true, .edi = true, .ebx = true });
if (!g_session_marker_written) {
const combat_handle = hook.readMem(u32, o.COMBAT_LOG_HANDLE);
if (handle == combat_handle and combat_handle != 0) {
writeSessionMarkerNow(handle);
if (g_session_char_len > 0) {
if (!g_combat_marker_written) {
const combat_handle = hook.readMem(u32, o.COMBAT_LOG_HANDLE);
if (handle == combat_handle and combat_handle != 0) {
writeSessionMarker(handle, "COMBATLOG_SESSION: %s");
g_combat_marker_written = true;
}
}
if (!g_chat_marker_written) {
const chat_handle = hook.readMem(u32, o.CHAT_LOG_HANDLE);
if (handle == chat_handle and chat_handle != 0) {
writeSessionMarker(handle, "CHAT_SESSION: %s");
g_chat_marker_written = true;
}
}
if (!g_raw_marker_written and g_raw_combat_handle_addr != 0) {
const raw_handle = hook.readMem(u32, g_raw_combat_handle_addr);
if (handle == raw_handle and raw_handle != 0) {
writeSessionMarker(handle, "COMBATLOG_SESSION: %s");
g_raw_marker_written = true;
}
}
}
write_log_hook.callOriginal(.{ handle, fmt, va_list });
}
/// Write session marker using stored character + realm names (no inline asm needed).
fn writeSessionMarkerNow(handle: u32) void {
if (g_session_char_len == 0) {
con.print("[combatlog] session marker: names not resolved yet\n");
return;
}
// Build "CharName RealmName" string on the stack
/// Write a session marker line using stored character + realm names.
fn writeSessionMarker(handle: u32, fmt_str: [*:0]const u8) void {
var marker_buf: [128]u8 = undefined;
const marker_str = std.fmt.bufPrint(&marker_buf, "{s} {s}", .{
g_session_char[0..g_session_char_len],
@@ -421,16 +442,14 @@ fn writeSessionMarkerNow(handle: u32) void {
}) catch return;
marker_buf[marker_str.len] = 0;
// va_list for %s: pointer to a char*
const marker_ptr: u32 = @intFromPtr(&marker_buf);
write_log_hook.callOriginal(.{
handle,
@intFromPtr(@as([*:0]const u8, "COMBATLOG_SESSION: %s")),
@intFromPtr(fmt_str),
@intFromPtr(&marker_ptr),
});
g_session_marker_written = true;
con.fmt("[combatlog] session marker: {s}\n", .{marker_str});
con.fmt("[combatlog] marker: {s}\n", .{marker_str});
}
// =============================================================================
@@ -440,11 +459,14 @@ fn writeSessionMarkerNow(handle: u32) void {
/// Resets all session state so the next login gets fresh paths.
/// Called from logoutDetour/shutdownDetour in main.zig.
pub fn onShutdown() void {
if (g_paths_configured or g_session_marker_written) {
if (g_paths_configured) {
con.print("[combatlog] session reset\n");
}
g_paths_configured = false;
g_session_marker_written = false;
g_combat_marker_written = false;
g_chat_marker_written = false;
g_raw_marker_written = false;
g_raw_combat_handle_addr = 0;
g_combat_path_len = 0;
g_raw_combat_path_len = 0;
g_chat_path_len = 0;