From 923cc4ebb0dba88a43647616a161083ed0d9bfce Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Mon, 16 Jun 2025 19:22:38 -0700 Subject: [PATCH] add missing xbox includes --- .../System/GetVersionInfoXB.x86.inc.s | 101 ++++++++++++++++++ .../System/WriteCallToCodeMultiXB.x86.inc.s | 101 ++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 system/client-functions/System/GetVersionInfoXB.x86.inc.s create mode 100644 system/client-functions/System/WriteCallToCodeMultiXB.x86.inc.s diff --git a/system/client-functions/System/GetVersionInfoXB.x86.inc.s b/system/client-functions/System/GetVersionInfoXB.x86.inc.s new file mode 100644 index 00000000..51ea773a --- /dev/null +++ b/system/client-functions/System/GetVersionInfoXB.x86.inc.s @@ -0,0 +1,101 @@ +# Implements the function: +# const PSOXBVersionInfo* @ eax [/none] get_version(); +# The return opcode is not included in this fragment. +# +# The returned structure is: +# struct PSOXBVersionInfo { +# /* 00 */ uint32_t specific_version; +# /* 04 */ void* check_addr; +# /* 08 */ void (**MmSetAddressProtect)(void* addr @ [esp+4], uint32_t size @ [esp + 8], uint32_t flags @ [esp+0xC]); +# /* 0C */ uint32_t @ eax (**MmQueryAddressProtect)(void* addr @ [esp+4]); +# /* 10 */ void* @ eax (*malloc7)(uint32_t size @ ecx, AllocatorInstance* instance @ edx); +# /* 14 */ AllocatorInstance** malloc7_instance; // For use with malloc7 +# }; +# +# NOTE: Cxbx-Reloaded defines the protection flags as: +# XBOX_PAGE_NOACCESS = 0x00000001 +# XBOX_PAGE_READONLY = 0x00000002 +# XBOX_PAGE_READWRITE = 0x00000004 +# XBOX_PAGE_WRITECOPY = 0x00000008 +# XBOX_PAGE_EXECUTE = 0x00000010 +# XBOX_PAGE_EXECUTE_READ = 0x00000020 +# XBOX_PAGE_EXECUTE_READWRITE = 0x00000040 +# XBOX_PAGE_EXECUTE_WRITECOPY = 0x00000080 +# XBOX_PAGE_GUARD = 0x00000100 +# XBOX_PAGE_NOCACHE = 0x00000200 +# XBOX_PAGE_WRITECOMBINE = 0x00000400 + +start: + push ecx + push edx + call get_data + + .data 0x344F4A42 # 4OJB + .data 0x0043D460 + .data 0x00400578 + .data 0x0040057C + .data 0x002C63F0 + .data 0x006305E0 + + .data 0x344F4A44 # 4OJD + .data 0x0043D7D0 + .data 0x00400918 + .data 0x0040091C + .data 0x002C6F40 + .data 0x00630C40 + + .data 0x344F4A55 # 4OJU + .data 0x00440FE0 + .data 0x00403E3C + .data 0x00403E40 + .data 0x002C84E0 + .data 0x0063878C + + .data 0x344F4544 # 4OED + .data 0x0044174C + .data 0x00404518 + .data 0x0040451C + .data 0x002C8030 + .data 0x00635C74 + + .data 0x344F4555 # 4OEU + .data 0x00440FEC + .data 0x00403E3C + .data 0x00403E40 + .data 0x002C8210 + .data 0x0063550C + + .data 0x344F5044 # 4OPD + .data 0x00441768 + .data 0x00404538 + .data 0x0040453C + .data 0x002C8060 + .data 0x00635C74 + + .data 0x344F5055 # 4OPU + .data 0x00441AF8 + .data 0x0040491C + .data 0x00404920 + .data 0x002C8330 + .data 0x0063600C + + .data 0x00000000 + .data 0x00000000 + +get_data: + pop edx + xor eax, eax + sub edx, 0x18 + +check_next_version: + add edx, 0x18 + mov ecx, [edx + 0x04] + test ecx, ecx + jz done + cmp dword [ecx], 0x61657244 + jne check_next_version + mov eax, edx + +done: + pop edx + pop ecx diff --git a/system/client-functions/System/WriteCallToCodeMultiXB.x86.inc.s b/system/client-functions/System/WriteCallToCodeMultiXB.x86.inc.s new file mode 100644 index 00000000..732765ad --- /dev/null +++ b/system/client-functions/System/WriteCallToCodeMultiXB.x86.inc.s @@ -0,0 +1,101 @@ +# This function has the same signature as WriteCallToCodeMulti-59NL. + +write_call_to_code: + .include GetVersionInfoXB + push ebx + push ebp + push esi + push edi + mov edi, eax + + # [esp + 0x14] = code ptr + # [esp + 0x18] = code size + # [esp + 0x1C] = callsite count + # [esp + 0x20] = callsite address + # [esp + 0x24] = callsite size + # ... (further callsite address/size pairs) + # esi = allocated code addr + # edi = version_info + + # Allocate memory for the copied code + mov ecx, [esp + 0x18] + mov edx, [edi + 0x14] + mov edx, [edx] + call [edi + 0x10] # malloc7(code_size, version_info->malloc7_instance) + test eax, eax + je done + mov esi, eax + + # Copy the code to the newly-allocated memory + # eax = dest pointer (from malloc7 call above) + mov edx, [esp + 0x14] # edx = source pointer + mov ecx, [esp + 0x18] # ecx = source size +memcpy_again: + dec ecx + mov bl, [edx + ecx] # Copy one byte from source to dest + mov [esi + ecx], bl + test ecx, ecx + jne memcpy_again + + # Make the memory executable + push 0x40 + push dword [esp + 0x1C] + push esi + mov ecx, [edi + 0x08] + call [ecx] # MmSetAddressProtect(dest_addr, code_size, XBOX_PAGE_EXECUTE_READWRITE) + + # Write the call opcodes + mov ebx, [esp + 0x1C] # ebx = callsite count + mov ebp, 0x20 # Stack offset of first callsite pair + +next_callsite: + # Make the memory writable + push esi + mov ecx, [edi + 0x0C] + call [ecx] # MmQueryAddressProtect(callsite_addr) + push eax + + push 0x04 + push dword [esp + ebp + 0x0C] + push dword [esp + ebp + 0x0C] + mov ecx, [edi + 0x08] + call [ecx] # MmSetAddressProtect(callsite_addr, callsite_size, XBOX_PAGE_READWRITE) + + mov edx, [esp + ebp + 4] # edx = jump callsite + lea ecx, [esi - 5] + sub ecx, edx # ecx = (dest code addr) - (jump callsite) - 5 + mov byte [edx], 0xE8 + mov [edx + 1], ecx # Write E8 (call) followed by delta + + # Write as many nops after the call opcode as necessary + mov ecx, 5 + mov eax, [esp + ebp + 8] +write_nop_again: + cmp ecx, eax + jge this_callsite_done + mov byte [edx + ecx], 0x90 + inc ecx + jmp write_nop_again + +this_callsite_done: + # Restore the previous protection + # Previous protection is still on the stack from MmQueryAddressProtect call + push dword [esp + ebp + 8] + push dword [esp + ebp + 8] + mov ecx, [edi + 0x08] + call [ecx] # MmSetAddressProtect(callsite_addr, callsite_size, prev_protection) + + add ebp, 8 + dec ebx + jnz next_callsite + + mov ecx, ebp + +done: + mov edi, [esp] + mov esi, [esp + 0x04] + mov ebp, [esp + 0x08] + mov ebx, [esp + 0x0C] + mov eax, [esp + 0x10] + add esp, ecx + jmp eax