diag(fifa17): port the passive kit-selector trace onto main
Cherry-pick of 4b1d5aa from wip/kit-selector-re, which forked before the TLS
work and cannot be rebased: that branch predates fifa17_tls.rs/patch_mem.rs and
carries a large unrelated lineage (probe/lsx/recv_hook). Only the kit_trace
commit's own contents are taken.
Traces the client-side FUT pre-match kit path in CardsDLL: the GetMatchKits_DP
gate (KITS_AVAILABLE), setAvailableKits (home/away list count), the kit-item
clone driver (item type/subid/teamid at FUN_1801c3480), and the local teamkits
DB clone. Read-only passive detours reusing season_trace's installers, which
this widens to pub(crate).
The one open unknown it answers: the selector requires item+0x60 == 4, a pile
value the server has never been observed to produce (/club emits 1,
/purchased 6).
Verified in the cross-built artifact that the roster TLS gate patch is intact
alongside the new trace (fifa17_tls markers present, KIT_* markers present).
This commit is contained in:
@@ -29,14 +29,14 @@ use crate::write_log;
|
||||
|
||||
static REPORTS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
unsafe fn rd_i32(addr: usize) -> Option<i32> {
|
||||
pub(crate) unsafe fn rd_i32(addr: usize) -> Option<i32> {
|
||||
readable_range(addr, 4).then(|| core::ptr::read_volatile(addr as *const i32))
|
||||
}
|
||||
unsafe fn rd_u8(addr: usize) -> Option<u8> {
|
||||
pub(crate) unsafe fn rd_u8(addr: usize) -> Option<u8> {
|
||||
readable_range(addr, 1).then(|| core::ptr::read_volatile(addr as *const u8))
|
||||
}
|
||||
/// Read a NUL-terminated string safely (bounded, only reads mapped bytes).
|
||||
unsafe fn rd_cstr(addr: usize, max: usize) -> String {
|
||||
pub(crate) unsafe fn rd_cstr(addr: usize, max: usize) -> String {
|
||||
if addr == 0 || !readable_range(addr, 1) {
|
||||
return String::from("<unreadable>");
|
||||
}
|
||||
@@ -56,7 +56,7 @@ unsafe fn rd_cstr(addr: usize, max: usize) -> String {
|
||||
/// Generic passive detour: overwrite the first `copy_len` bytes of `target` (which
|
||||
/// MUST be whole, position-independent instructions) with an absolute jump to
|
||||
/// `wrapper`; the wrapper calls the trampoline (copied prologue + jump back).
|
||||
unsafe fn install_detour(
|
||||
pub(crate) unsafe fn install_detour(
|
||||
base: usize,
|
||||
rva: usize,
|
||||
name: &str,
|
||||
@@ -267,7 +267,7 @@ unsafe fn alloc_near(base: usize, size: usize) -> Option<usize> {
|
||||
/// both within the copied bytes). The trampoline is allocated near `base` and the
|
||||
/// disp32 is relocated so it resolves to the same absolute address. Read-only.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
unsafe fn install_detour_reloc(
|
||||
pub(crate) unsafe fn install_detour_reloc(
|
||||
base: usize,
|
||||
rva: usize,
|
||||
name: &str,
|
||||
|
||||
Reference in New Issue
Block a user