commonlibsse_ng\re\t/
TLSData.rs

1use core::ptr::NonNull;
2
3use crate::re::BSExtraData::BSExtraData;
4use crate::re::ExtraDataList::ExtraDataList;
5use crate::re::ExtraDataType::ExtraDataType;
6
7const CACHED_EXTRA_DATA_SIZE: usize = (ExtraDataType::ResourcesPreload.bits() + 1) as usize;
8
9#[derive(Debug)]
10#[repr(C)]
11pub struct TLSData {
12    pub unk000: [u8; 0x10], // 0x000
13    ///  - on GetExtraData(), this gets checked against the GlobalStateCounter,
14    ///    which is incremented every time extra data is changed or removed:if they're not equal,
15    ///    then the following cached extra data is zeroed-out and reached
16    pub stateCounter: u32, // 0x010
17    pub pad014: u32,        // 0x014
18    pub cachedExtraDataList: *mut ExtraDataList, // 0x018
19
20    /// - ExtraData types up to ResourcesPreload (0xB5) are cached
21    pub cachedExtraData: [*mut BSExtraData; CACHED_EXTRA_DATA_SIZE], // 0x020
22    pub unk5D0: [u8; 0x30],  // 0x5D0
23    pub consoleMode: bool,   // 0x600
24    pub unk601: [u8; 0x167], // 0x601
25    pub taskFlag: u32,       // 0x768 -- unknown enum
26
27                             // ... many others ...
28}
29const _: () = {
30    assert!(core::mem::offset_of!(TLSData, consoleMode) == 0x600);
31    assert!(core::mem::offset_of!(TLSData, taskFlag) == 0x768);
32};
33
34impl TLSData {
35    #[inline]
36    pub fn get_static_tls_data() -> Option<NonNull<Self>> {
37        let index = get_tls_index()? as usize;
38        unsafe {
39            let tls_data_array = read_gs_qword::<*mut Self>(0x58);
40            let tls_data = *(tls_data_array.add(index));
41            NonNull::new(tls_data)
42        }
43    }
44}
45
46#[commonlibsse_ng_derive_internal::relocate(
47    cast_as = "*const u32",
48    deref_once,
49    id(se = 515064, ae = 401203),
50    default = "None"
51)]
52#[inline]
53fn get_tls_index() -> Option<u32> {
54    |tls_index: DerefType| Some(tls_index)
55}
56
57#[inline]
58unsafe fn read_gs_qword<T>(offset: u64) -> *mut T {
59    let value: *mut T;
60    unsafe {
61        core::arch::asm!(
62            "mov {}, gs:[{}]",
63            out(reg) value,
64            in(reg) offset,
65            options(nostack, preserves_flags),
66        );
67    }
68    value
69}