合并本地领先源码:旧UI、GM疲劳燃烧、白金徽章孔、宠物修复、支援兵普攻开关
This commit is contained in:
1 parent
f2debaf9bf
commit
70b3c5a6dc
57 files changed
+4256
-30
No files matched your search
@@ -0,0 +1,95 @@
|
||||
// Included inside 90CN.cpp's namespace after its existing patch helpers.
|
||||
// Only the evidenced UI update iterator call-site is patched, never the CRT.
|
||||
uintptr_t g_uiIteratorNativeAdvance = 0;
|
||||
uintptr_t g_uiIteratorAdvanceResume = 0;
|
||||
uintptr_t g_uiIteratorNextBucket = 0;
|
||||
volatile LONG g_uiIteratorInvalidations = 0;
|
||||
int __stdcall CanAdvanceUiUpdateIterator(unsigned int bucket,
|
||||
const uintptr_t* owner, const uintptr_t* iterator)
|
||||
{
|
||||
dnf90::UiIteratorSnapshot s = {};
|
||||
__try {
|
||||
s.owner = reinterpret_cast<uintptr_t>(owner);
|
||||
if (owner && iterator) {
|
||||
s.proxy = owner[0]; s.iteratorProxy = iterator[0];
|
||||
s.begin = owner[1]; s.end = owner[2]; s.current = iterator[2];
|
||||
if (s.proxy && s.iteratorProxy == s.proxy)
|
||||
s.proxyOwner = *reinterpret_cast<const uintptr_t*>(s.proxy);
|
||||
}
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) { s.proxyOwner = 0; }
|
||||
if (dnf90::CanAdvanceUiIterator(s)) return 1;
|
||||
LONG n = InterlockedIncrement(&g_uiIteratorInvalidations);
|
||||
if (n <= 16) LogLine("ui-update iterator invalidated bucket=%u owner=%08X "
|
||||
"proxy=%08X iter_proxy=%08X begin=%08X end=%08X current=%08X "
|
||||
"action=defer_remaining_bucket_until_next_frame hit=%ld",
|
||||
bucket, s.owner, s.proxy, s.iteratorProxy, s.begin, s.end, s.current, n);
|
||||
return 0;
|
||||
}
|
||||
__declspec(naked) void ProxyUiUpdateIteratorAdvance()
|
||||
{
|
||||
__asm {
|
||||
// Entry is a JMP replacing CALL; result pointer and dummy are on stack.
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push ecx
|
||||
push dword ptr [ebp - 14h]
|
||||
push dword ptr [ebp - 1Ch]
|
||||
call CanAdvanceUiUpdateIterator
|
||||
test eax, eax
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
jz invalidated
|
||||
call dword ptr [g_uiIteratorNativeAdvance]
|
||||
jmp dword ptr [g_uiIteratorAdvanceResume]
|
||||
invalidated:
|
||||
// Native ++ would have consumed two arguments (ret 8). Do not compare
|
||||
// an invalid iterator again; the next bucket constructs a fresh one.
|
||||
add esp, 8
|
||||
jmp dword ptr [g_uiIteratorNextBucket]
|
||||
}
|
||||
}
|
||||
bool InstallUiIteratorAdvanceCompatibility()
|
||||
{
|
||||
const uintptr_t site = g_dnfBase + 0x02BF2732;
|
||||
static const unsigned char kLoopContract[] = {
|
||||
0x8B,0x0F,0x8B,0x11,0x8B,0x42,0x10,0xFF,0xD0,0x6A,0x00,
|
||||
0x8D,0x4D,0xB4,0x51,0x8D,0x4D,0xD4,0xE8,0x19,0x02,0x7F,0xFD,
|
||||
0xE9,0x77,0xFF,0xFF,0xFF,0x8B,0x45,0xE4,0x83,0x45,0xEC,0x14,
|
||||
0x40,0x89,0x45,0xE4,0x3D,0x87,0x04,0x00,0x00,0x0F,0x8C,0x55,0xFF,0xFF,0xFF
|
||||
};
|
||||
static const unsigned char kBeginContract[] = {
|
||||
0x55,0x8B,0xEC,0x8B,0x45,0x08,0x8B,0x51,0x04,0x8B,0x09,
|
||||
0xC7,0x40,0x04,0,0,0,0,0x89,0x50,0x08,0x89,0x08,0x5D,0xC2,0x04,0
|
||||
};
|
||||
static const unsigned char kAdvanceContract[] = {
|
||||
0x55,0x8B,0xEC,0x8B,0x45,0x08,0x8B,0x11,0x56,0xC7,0x00,0,0,0,0
|
||||
};
|
||||
if (!BytesMatch(reinterpret_cast<unsigned char*>(g_dnfBase+0x02BF2720),
|
||||
kLoopContract,sizeof(kLoopContract)) ||
|
||||
!BytesMatch(reinterpret_cast<unsigned char*>(g_dnfBase+0x00A44ED0),
|
||||
kBeginContract,sizeof(kBeginContract)) ||
|
||||
!BytesMatch(reinterpret_cast<unsigned char*>(g_dnfBase+0x003E2950),
|
||||
kAdvanceContract,sizeof(kAdvanceContract))) {
|
||||
LogLine("ui-update iterator compatibility disabled: native signature mismatch");
|
||||
return false;
|
||||
}
|
||||
g_uiIteratorNativeAdvance = g_dnfBase + 0x003E2950;
|
||||
g_uiIteratorAdvanceResume = g_dnfBase + 0x02BF2737;
|
||||
g_uiIteratorNextBucket = g_dnfBase + 0x02BF273C;
|
||||
DWORD oldProtection = 0;
|
||||
if (!VirtualProtect(reinterpret_cast<void*>(site),5,PAGE_EXECUTE_READWRITE,&oldProtection)) {
|
||||
LogLine("ui-update iterator compatibility protection failed error=%lu",GetLastError());
|
||||
return false;
|
||||
}
|
||||
unsigned char jump[5] = {0xE9};
|
||||
*reinterpret_cast<int32_t*>(jump+1) = static_cast<int32_t>(
|
||||
reinterpret_cast<intptr_t>(&ProxyUiUpdateIteratorAdvance)-static_cast<intptr_t>(site+5));
|
||||
memcpy(reinterpret_cast<void*>(site),jump,sizeof(jump));
|
||||
DWORD ignored = 0;
|
||||
VirtualProtect(reinterpret_cast<void*>(site),5,oldProtection,&ignored);
|
||||
FlushInstructionCache(GetCurrentProcess(),reinterpret_cast<void*>(site),5);
|
||||
LogLine("ui-update mutation-safe iterator installed site=%08X next_bucket=%08X",site,g_uiIteratorNextBucket);
|
||||
return true;
|
||||
}
|
||||
Reference in new issue
Block a user